# How to stop simulation after a given model variable achieves certain value?

I would like to stop my simulation after a given model variable (say, plastic strain averaged over entire domain) achieves a given threshold value. Do you know how to do it?

I'm supplying the MWE. How can I force AceFEM to stop simulation after EyPlAver achieves some threshold value, say 0.02 ?

<< AceFEM;

SMTInputData[];
"ExamplesFiniteStrain", {"E *" -> 206.9, "\[Nu] *" -> .29,
"\[Sigma]y *" -> 0.45, "K *" -> 0.12924, "\[Sigma]yInf *" -> 0.715,
"\[Delta] *" -> 16.93}];
WX = 1; WY = 1;
\[CapitalDelta]WY = 0.1;
SMTAddMesh[Polygon[{{WX, 0}, {WX, WY}, {0, WY}, {0, 0}}], "A",
"Q1", {10, 10}];

1 -> 0}, {Line[{{0, 0}, {WX, 0}}], 2 -> 0}, {
Line[{{0, WY}, {WX, WY}}], 2 -> \[CapitalDelta]WY }];
SMTAnalysis[];

Clear[\[Lambda]]; \[Lambda][t_] := t;

tMax = 1.; t0 = tMax/500.; \[CapitalDelta]tMin =
tMax/10000.; \[CapitalDelta]tMax = tMax/10.;
tolNR = 10.^-8; maxNR = 15; targetNR = 8;
SMTNextStep["t" -> t0, "\[Lambda][t]" -> \[Lambda]];
TElements = SMTFindElements["A"];
While[
While[step =
SMTConvergence[tolNR,
targetNR, \[CapitalDelta]tMin, \[CapitalDelta]tMax, tMax}],
SMTNewtonIteration[];];
If[step[[4]] === "MinBound",
SMTStatusReport[
"\[CapitalDelta]T<\!$$\*SubscriptBox[\(\[CapitalDelta]T$$, \
$$min$$]\)"]; SMTStepBack[];];
If[Not[step[[1]]],
EyPl = {};
For[i = 1, i <= Length[TElements], i++,
AppendTo[EyPl, SMTElementPostData[TElements[[i]]][[1]][[All, 23]]]
];
EyPlAver = Mean[Flatten[EyPl]];
Print[EyPlAver];
];
step[[3]]
, If[step[[1]], SMTStepBack[];];
SMTNextStep["\[CapitalDelta]t" -> step[[2]],
"\[Lambda][t]" -> \[Lambda]]
];

• I didn't actually try to analyze your code, so this is just a general suggestion. You can use Return to break out of a "function". So, adding some conditional with a Return when the condition is satisfied might work. You might also be interested in Break, Throw, and Abort (and probably a few others) as ways to exit a function or loop. Commented Apr 27, 2022 at 17:25

What you are looking for is an option to SMTConvergence[... , "AlternativeTarget"-> Function[...]]:

You can modify your SMTConvergence as:

SMTConvergence[tolNR, maxNR,
{"Adaptive Time", targetNR, \[CapitalDelta]tMin, \[CapitalDelta]tMax, tMax},
"AlternativeTarget" -> Function[{},
EyPl = Table[SMTElementPostData[i][[1, All, 23]], {i, TElements}];
EyPlAver = Mean[Flatten[EyPl]];
Print[EyPlAver];
EyPlAver >=  0.02] ]


The procedure will start decreasing step size after EyPlAver > 0.02  is reached, trying to get as close to 0.02 as possible, so if you want to break at exactly 0.02 you will need very low minimum time step \CapitalDelta]tMin, otherwise it will stop once it reaches minimum step to get it as close to 0.02 as possible.

I would suggest to avoid Append since it is slow when applied many times on large lists. For even better performance and if you want a real average value, I suggest you write a task that integrates or sums this plastic deformation over element volume, then you can call SMTTask["AverageEPl"] and divide it by volume of domain or number of total entries.

If you don't care about stopping at exactly 0.02, then simple Break /Abort/ Return will be best, since you can avoid extra iterations from searching for exact value of 0.02:

 step[[3]], If[step[[1]], SMTStepBack[];,If[EyPlAver >=  0.02, Break[]]];
`