Skip to content

Download MATLAB script

Smart Analysis¤

This live script is written as a guided walkthrough for a post-processing workflow. It focuses on retrieving, organizing, and visualizing model or response data after an OpenSees analysis. Read the text cells first, then run each code cell in order so that the variables, model state, and recorded results are available for the later sections.

Demonstrating how to use intelligent analysis algorithms.

See also opstool.

1
2
3
4
clc; clear;

opsMAT = OpenSeesMatlab();
ops = opsMAT.opensees;

Reinforced Concrete Frame Pushover Analysis¤

This section configures and runs the analysis. The solver, constraints, convergence test, and step size should be read together because they control numerical robustness.

1
2
3
4
FEModel(ops);

figure;
opsMAT.vis.plotModel();
Output
[OpenSeesMatlab] Model summary Nodes: 4 Beam elements: 3
figure_0.png

Smart Analysis¤

No fixed number of analyses¤

1
2
3
4
5
6
7
8
9
% Set some parameters
dU = 0.1;  % Displacement increment
maxU = 45.0;  % Max displacement
ok = 0;
currentDisp = 0;

FEModel(ops);
gravityAnalysis(ops);
pushoverLoad(ops);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
opsMAT.anlys.smartAnalyze.initialize();  % please make sure reset!
opsMAT.anlys.smartAnalyze.configure(...
    analysis="Static",...
    testType="EnergyIncr", ...
    testTol=1e-10, ...
    tryAddTestTimes=true, ...  % add test times to the analysis
    testIterTimes=10, ...
    testIterTimesMore=[50, 100], ...
    tryAlterAlgoTypes=true, ...  % try different algorithms
    algoTypes=[40, 10, 20, 30], ... % algorithm types to try
    tryRelaxStep=true, ...  %
    minStep=1e-6, ... % minimum step size for substepping
    debugMode=true, ... % False for progress bar, True for debug info
    printPer=50, ... % print every 100 steps
    recordNormHistory=true ...  % Don't use it if you want fastest speed
);
Output
[OpenSeesMatlab::SmartAnalyze] Configuration: analysis=Static, test=EnergyIncr, tol=1.000e-10, iter=10, printFlag=0 algorithm=KrylovNewton (type 40), candidates=[40, 10, 20, 30] retry: addIter=1 [50, 100], alterAlgo=1, alterTest=0 [NormDispIncr, NormUnbalance, RelativeEnergyIncr], looseTol=0 [1e-08], relaxStep=1 (relaxation=0.5, minStep=1.000e-06) record: normHistory=1, diagnostics=0, printPer=50
1
2
3
4
5
6
node=3; dof=1; seg=dU;
while ok == 0 && currentDisp < maxU
    %  Perform the analysis one step at a time
    opsMAT.anlys.smartAnalyze.staticAnalyze(node, dof, seg);
    currentDisp = ops.nodeDisp(3, 1);
end
Output
[OpenSeesMatlab::SmartAnalyze] progress 50 steps. Time: 0.112 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 100 steps. Time: 0.146 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 150 steps. Time: 0.175 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 200 steps. Time: 0.201 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 250 steps. Time: 0.233 s. ✅ [OpenSees] WARNING: CTestEnergyIncr::test() - failed to converge [OpenSees] after: 10 iterations [OpenSees] current EnergyIncr: 5.80578e-06 (max: 1e-10) Norm deltaX: 0.00017573, Norm deltaR: 0.672724 [OpenSees] AcceleratedNewton::solveCurrentStep() -The ConvergenceTest object failed in test() [OpenSees] StaticAnalysis::analyze() - the Algorithm failed at step: 0 with domain at load factor 2.89496 [OpenSees] OpenSees > analyze failed, returned: -3 error flag [OpenSeesMatlab::SmartAnalyze] Adding test times to 50. ✳️ [OpenSeesMatlab::SmartAnalyze] progress 300 steps. Time: 0.278 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 350 steps. Time: 0.317 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 400 steps. Time: 0.347 s. ✅ [OpenSees] WARNING: CTestEnergyIncr::test() - failed to converge [OpenSees] after: 10 iterations [OpenSees] current EnergyIncr: 2.70125e-05 (max: 1e-10) Norm deltaX: 0.000819596, Norm deltaR: 0.253889 [OpenSees] AcceleratedNewton::solveCurrentStep() -The ConvergenceTest object failed in test() [OpenSees] StaticAnalysis::analyze() - the Algorithm failed at step: 0 with domain at load factor 1.64367 [OpenSees] OpenSees > analyze failed, returned: -3 error flag [OpenSeesMatlab::SmartAnalyze] Adding test times to 50. ✳️ [OpenSeesMatlab::SmartAnalyze] progress 450 steps. Time: 0.383 s. ✅
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
history = opsMAT.anlys.smartAnalyze.getNormHistory();
lastNorms   = [history.lastNorm].';
stepIndices = [history.stepIndex].';
okFlags     = [history.ok].';

figure; hold on;

% Plot as scatter dots to see every point clearly
semilogy(stepIndices, lastNorms,  'Color', 'blue');

% Tolerance line
yline(1e-10, 'r--', 'LineWidth', 1.5);

xlabel('Step index');
ylabel('Last norm (log scale)');
title('SmartAnalyze convergence history');
grid on;
set(gca, 'YScale', 'log');   % force log scale explicitly
figure_1.png

Analysis of the fixed number of steps¤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
FEModel(ops);
gravityAnalysis(ops);
pushoverLoad(ops);

opsMAT.anlys.smartAnalyze.initialize();  % please make sure reset!
opsMAT.anlys.smartAnalyze.configure(...
    analysis="Static",...
    testType="NormDispIncr", ...
    testTol=1e-8, ...
    tryAddTestTimes=true, ...  % add test times to the analysis
    testIterTimes=10, ...
    testIterTimesMore=[50, 100], ...
    tryAlterAlgoTypes=true, ...  % try different algorithms
    algoTypes=[40, 10, 20, 30], ... % algorithm types to try
    tryRelaxStep=true, ...  %
    minStep=1e-6, ... % minimum step size for substepping
    debugMode=true, ... % False for progress bar, True for debug info
    printPer=50 ... % print every 100 steps
);
Output
[OpenSeesMatlab::SmartAnalyze] Configuration: analysis=Static, test=NormDispIncr, tol=1.000e-08, iter=10, printFlag=0 algorithm=KrylovNewton (type 40), candidates=[40, 10, 20, 30] retry: addIter=1 [50, 100], alterAlgo=1, alterTest=0 [NormDispIncr, NormUnbalance, RelativeEnergyIncr], looseTol=0 [1e-08], relaxStep=1 (relaxation=0.5, minStep=1.000e-06) record: normHistory=1, diagnostics=0, printPer=50
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
H = 20.0;  % Reference lateral load
segs = opsMAT.anlys.smartAnalyze.staticStepSplit(maxU, dU);
data = zeros(numel(segs) + 1, 2);

for i = 1:numel(segs)
    opsMAT.anlys.smartAnalyze.staticAnalyze(node, dof, segs(i));

    data(i + 1, 1) = ops.nodeDisp(4, 1);
    data(i + 1, 2) = ops.getLoadFactor(2) * H;
end
Output
[OpenSeesMatlab::SmartAnalyze] progress 11.111 % (50/450). Time: 0.067 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 22.222 % (100/450). Time: 0.110 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 33.333 % (150/450). Time: 0.140 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 44.444 % (200/450). Time: 0.170 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 55.556 % (250/450). Time: 0.207 s. ✅ [OpenSees] WARNING: CTestNormDispIncr::test() - failed to converge [OpenSees] after: 10 iterations current Norm: 0.000359096 (max: 1e-08, Norm deltaR: 0.195182) [OpenSees] AcceleratedNewton::solveCurrentStep() -The ConvergenceTest object failed in test() [OpenSees] StaticAnalysis::analyze() - the Algorithm failed at step: 0 with domain at load factor 2.89483 [OpenSees] OpenSees > analyze failed, returned: -3 error flag [OpenSeesMatlab::SmartAnalyze] Adding test times to 50. ✳️ [OpenSeesMatlab::SmartAnalyze] progress 66.667 % (300/450). Time: 0.263 s. ✅ [OpenSees] WARNING: CTestNormDispIncr::test() - failed to converge [OpenSees] after: 10 iterations current Norm: 3.45018e-08 (max: 1e-08, Norm deltaR: 0.00026513) [OpenSees] AcceleratedNewton::solveCurrentStep() -The ConvergenceTest object failed in test() [OpenSees] StaticAnalysis::analyze() - the Algorithm failed at step: 0 with domain at load factor 2.30484 [OpenSees] OpenSees > analyze failed, returned: -3 error flag [OpenSeesMatlab::SmartAnalyze] Adding test times to 50. ✳️ [OpenSeesMatlab::SmartAnalyze] progress 77.778 % (350/450). Time: 0.307 s. ✅ [OpenSeesMatlab::SmartAnalyze] progress 88.889 % (400/450). Time: 0.342 s. ✅ [OpenSees] WARNING: CTestNormDispIncr::test() - failed to converge [OpenSees] after: 10 iterations current Norm: 0.000819595 (max: 1e-08, Norm deltaR: 0.25389) [OpenSees] AcceleratedNewton::solveCurrentStep() -The ConvergenceTest object failed in test() [OpenSees] StaticAnalysis::analyze() - the Algorithm failed at step: 0 with domain at load factor 1.64367 [OpenSees] OpenSees > analyze failed, returned: -3 error flag [OpenSeesMatlab::SmartAnalyze] Adding test times to 50. ✳️ [OpenSeesMatlab::SmartAnalyze] progress 100.000 % (450/450). Time: 0.401 s. ✅ [OpenSeesMatlab::SmartAnalyze] Successfully finished! Progress: 100.000 % (450/450). Time: 0.402 s. 
1
2
3
4
5
figure;
plot(data(:, 1)/144.0, data(:, 2), 'LineWidth', 1.5, "Color", "blue");
xlabel('Horizontal Drift Ratio');
ylabel('Horizontal Load');
grid on;
figure_2.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function FEModel(ops)
    ops.wipe();
    ops.model("basic", "-ndm", 3, "-ndf", 6);
    width = 360.0;
    height = 144.0;
    ops.node(1, 0.0, 0.0, 0.0);
    ops.node(2, width, 0.0, 0.0);
    ops.node(3, 0.0, 0.0, height);
    ops.node(4, width, 0.0, height);
    ops.fix(1, 1, 1, 1, 1, 1, 1);
    ops.fix(2, 1, 1, 1, 1, 1, 1);

    ops.uniaxialMaterial("Concrete01", 1, -6.0, -0.004, -5.0, -0.014);
    ops.uniaxialMaterial("Concrete01", 2, -5.0, -0.002, 0.0, -0.006);

    fy = 60.0;
    E = 30000.0;
    ops.uniaxialMaterial("Steel01", 3, fy, E, 0.01);

    % Define cross-section for nonlinear columns
    % ------------------------------------------
    colWidth = 15;
    colDepth = 24;
    cover = 1.5;
    As = 0.60;  % area of no. 7 bars
    % some variables derived from the parameters
    y1 = colDepth / 2.0;
    z1 = colWidth / 2.0;

    ops.section("Fiber", 1, "-GJ", 1000000);
    ops.patch("rect", 1, 10, 10, cover - y1, cover - z1, y1 - cover, z1 - cover);
    % Create the concrete cover fibers (top, bottom, left, right);
    ops.patch("rect", 2, 11, 1, -y1, z1 - cover, y1, z1);
    ops.patch("rect", 2, 11, 1, -y1, -z1, y1, cover - z1);
    ops.patch("rect", 2, 1, 10, -y1, cover - z1, cover - y1, z1 - cover);
    ops.patch("rect", 2, 1, 10, y1 - cover, cover - z1, y1, z1 - cover);
    % Create the reinforcing fibers (left, middle, right);
    ops.layer("straight", 3, 5, As, y1 - cover, z1 - cover, y1 - cover, cover - z1);
    ops.layer("straight", 3, 2, As, 0.0, z1 - cover, 0.0, cover - z1);
    ops.layer("straight", 3, 5, As, cover - y1, z1 - cover, cover - y1, cover - z1);

    % Define column elements
    % ----------------------
    ops.geomTransf("PDelta", 1, -1, 0, 0);
    % Number of integration points along length of element
    np = 5;
    % Lobatto integratoin
    ops.beamIntegration("Lobatto", 1, 1, np);
    eleType = "forceBeamColumn";
    ops.element(eleType, 1, 1, 3, 1, 1);
    ops.element(eleType, 2, 2, 4, 1, 1);

    % Define beam elment
    % -----------------------------
    ops.geomTransf("Linear", 2, 0.0, 0.0, 1.0);
    ops.element("elasticBeamColumn", 3, 3, 4, 360.0, 4030.0, 2015.0, 10000, 8640.0, 8640.0, 2);
end
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function gravityAnalysis(ops)
    %  a parameter for the axial load
    P = 180.0;  % 10% of axial capacity of columns

    % Create a Plain load pattern with a Linear TimeSeries
    ops.timeSeries("Linear", 1);
    ops.pattern("Plain", 1, 1);

    % Create nodal loads at nodes 3 & 4
    %    nd  FX,  FY, MZ
    ops.load(3, 0.0, 0.0, -P, 0.0, 0.0, 0.0);
    ops.load(4, 0.0, 0.0, -P, 0.0, 0.0, 0.0);

    % Start of analysis generation
    % ------------------------------
    ops.system("BandGeneral");
    ops.constraints("Transformation");
    ops.numberer("RCM");
    ops.test("NormDispIncr", 1.0e-12, 10, 3);
    ops.algorithm("Newton");
    ops.integrator("LoadControl", 0.1);
    ops.analysis("Static");
    ops.analyze(10);
end
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function pushoverLoad(ops)
    ops.loadConst("-time", 0.0)
    % Define lateral loads
    % --------------------
    % Set some parameters
    H = 10.0;  % Reference lateral load
    % Set lateral load pattern with a Linear TimeSeries
    ops.pattern("Plain", 2, 1);
    ops.load(3, H, 0.0, 0.0, 0.0, 0.0, 0.0);
    ops.load(4, H, 0.0, 0.0, 0.0, 0.0, 0.0);
end