# How to collect results even if AceFEM analysis diverges?

Sometimes (implicit) finite element analysis with AceFEM diverges and solution procedure is aborted before reaching the final time/load step. I have followed the method shown in documentation for collecting results in the analysis loop. If analysis successfully finishes completely the list of results is returned and if it diverges nothing is returned. How can I get results for all successful steps before divergence occurred? The following small example illustrates the problem.

<< AceFEM

(* Function to collect results (residual force and displacement in X direction) *)
getResults[] := {Total[SMTResidual["X" == 1 &]][[1]],
SMTPostData["u", {1, 0, 0}]}

(* Setup of compression test of hyperelastic material with prescribed force. *)
setup[force_?NumberQ] := Module[{n = 5},
SMTInputData[];
SMTAddDomain["test", "OL:SED3H1DFHYH1NeoHooke", {"E *" -> 1}];
Hexahedron[{{0,0,0},{0,1,0},{0,1,1},{0,0,1},{1,0,0},{1,1,0},{1,1,1},{1,0,1}}],
"test", "H1", {n, n, n}
];
SMTAddEssentialBoundary[{ "X" == 0 &, 1 -> 0, 2 -> 0, 3 -> 0}];
Polygon[{{1, 0, 0}, {1, 1, 0}, {1, 1, 1}, {1, 0, 1}}],
1 -> Polygon[{force}]];
SMTAnalysis[];
]

(* Analysis loop with constant load step. *)
analysis[force_?NumberQ, nstep_Integer] := Module[{results = {}},
setup[force];

AppendTo[results, getResults[]];
Do[
SMTNextStep["Δλ" -> 1./nstep];
While[SMTConvergence[10^-8, 15], SMTNewtonIteration[]];
(* Collect results in converged step. *)
AppendTo[results, getResults[]],
{i, 1, nstep}
];
results
]


Analysis finishes successfully and a list is returned.

analysis[-0.1, 10]
(*{{0., 0.}, {-0.01, -0.00964376}, {-0.02, -0.0191696}, {-0.03,-0.0285796}, {-0.04, -0.0378759}, {-0.05, -0.0470607}, {-0.06, -0.0561361}, {-0.07, -0.0651046}, {-0.08, -0.0739684}, {-0.09, -0.0827299}, {-0.1, -0.0913916}}*)


Analysis diverges in 5. step and nothing is returned (actually symbol \$Aborted is returned).

analysis[-1, 10]


There is the third parameter for the function SMTConvergence[]. If you write "Analyze" as third parameter, the SMTConvergence[] will not abort:

SMTConvergence[10^-8, 15, "Analyze"]

analysis[-1, 10]


The output is now:

{{0., 0.}, {-0.1, -0.0913916}, {-0.2, -0.173146}, {-0.3, -0.249022}, {-0.4, -0.332748}, {-0.350802, -1.21446}, {-0.6, -1.01868}, {6407.89, -5.84366}, {217.063, -7.52827}, {825122., 29.3738}, {-23136.7, -6.36294}}


Edit: I have added the test that will break the iteration and return the converged results:

(*Analysis loop with constant load step.*)
analysis[force_?NumberQ, nstep_Integer] :=
Module[{}, results = {}; setup[force];
AppendTo[results, getResults[]];
err = False;
Do[SMTNextStep["\[CapitalDelta]\[Lambda]" -> 1./nstep];
While[(If[! BooleanQ[#],
Print["Error in iterative procedure step ", i, ": ", #];
err = True; False, #]) &@SMTConvergence[10^-8, 15, "Analyze"],
SMTNewtonIteration[]];
If[err, Return[],(*Collect results in converged step.*)
AppendTo[results, getResults[]];];
, {i, 1, nstep}];
results]

analysis[-1, 10]


The output is now:

Error in iterative procedure step 5: {Alternate}
{{0., 0.}, {-0.1, -0.0913916}, {-0.2, -0.173146}, {-0.3, -0.249022}, {-0.4, -0.332748}}

• Thank you, I didn't know before what this 3rd argument "Analyze" does. But I think the problem in your solution is that returned results are meaningless after the step when divergence occurred and there is no warning about it. Am I right? This may mislead an unsuspecting user. – Pinti May 30 '17 at 17:36
• I have modified my answer to return only the results of the converged solution. – BHudobivnik May 31 '17 at 8:12

One possible solution is to wrap the convergence checking procedure in CheckAbort and decide what to do when it aborts. In my example a warning message about divergence is issued and results are returned with Missing symbol appended, so it is clear something happened in the analysis loop. In my opinion the advantage of this solution is that also original AceFEM message/print is preserved and it works with adaptive time/load step, which is specified as the third argument of SMTConvergence.

analysis3::abrt = "Warning! Divergence has occurred in step 1. Analysis ended prematurely.";

analysis3[force_?NumberQ, nstep_Integer] := Module[{results = {}},
setup[force];
AppendTo[results, getResults[]];

Do[
SMTNextStep["Δλ" -> 1./nstep];
CheckAbort[
While[
SMTConvergence[10^-8, 15],
SMTNewtonIteration[]
];
AppendTo[results, getResults[]],
(* This happens in case of Abort. *)
Message[analysis3::abrt, SMTData["Step"]];
AppendTo[results, Missing["Nonexistent"]];
Return[results]
],
{i, 1, nstep}
];
results
]


Other functions (setup, getResults) are taken from OP's question. Example of behavior:

pts = analysis3[-1, 10]


(* {{0., 0.}, {-0.1, -0.0913916}, {-0.2, -0.173146},
{-0.3, -0.249022}, {-0.4, -0.332748}, Missing["Nonexistent"]} *)


Lists with Missing symbol can be still simply plotted without any manipulation.

ListPlot[pts, AxesLabel -> {"Force", "Displacement"}]


• You do not have to check for Abort, Just use "Analyse" and check what is returned by the SMTConvergence` command. If it is a string or list, than you got an error and you can stop the procedure yourself. I modified my answer. – BHudobivnik May 31 '17 at 8:03