Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "FixedPointSolve.h"
11 :
12 : #include "FEProblem.h"
13 : #include "Executioner.h"
14 : #include "MooseMesh.h"
15 : #include "NonlinearSystem.h"
16 : #include "AuxiliarySystem.h"
17 : #include "AllLocalDofIndicesThread.h"
18 : #include "Console.h"
19 : #include "EigenExecutionerBase.h"
20 : #include "Convergence.h"
21 : #include "ConvergenceIterationTypes.h"
22 : #include "MooseUtils.h"
23 :
24 : InputParameters
25 311114 : FixedPointSolve::fixedPointDefaultConvergenceParams()
26 : {
27 311114 : InputParameters params = emptyInputParameters();
28 :
29 933342 : params.addParam<unsigned int>(
30 622228 : "fixed_point_min_its", 1, "Specifies the minimum number of fixed point iterations.");
31 933342 : params.addParam<unsigned int>(
32 622228 : "fixed_point_max_its", 1, "Specifies the maximum number of fixed point iterations.");
33 933342 : params.addParam<bool>("disable_fixed_point_residual_norm_check",
34 622228 : false,
35 : "Disable the residual norm evaluation thus the three parameters "
36 : "fixed_point_rel_tol, fixed_point_abs_tol and fixed_point_force_norms.");
37 933342 : params.addParam<bool>(
38 : "fixed_point_force_norms",
39 622228 : false,
40 : "Force the evaluation of both the TIMESTEP_BEGIN and TIMESTEP_END norms regardless of the "
41 : "existence of active MultiApps with those execute_on flags, default: false.");
42 933342 : params.addParam<bool>(
43 : "accept_on_max_fixed_point_iteration",
44 622228 : false,
45 : "True to treat reaching the maximum number of fixed point iterations as converged.");
46 1555570 : params.addRangeCheckedParam<Real>("fixed_point_rel_tol",
47 622228 : 1e-8,
48 : "fixed_point_rel_tol>0",
49 : "The relative nonlinear residual drop to shoot for "
50 : "during fixed point iterations. This check is "
51 : "performed based on the main app's nonlinear "
52 : "residual.");
53 1555570 : params.addRangeCheckedParam<Real>("fixed_point_abs_tol",
54 622228 : 1e-50,
55 : "fixed_point_abs_tol>0",
56 : "The absolute nonlinear residual to shoot for "
57 : "during fixed point iterations. This check is "
58 : "performed based on the main app's nonlinear "
59 : "residual.");
60 :
61 1244456 : params.addParam<PostprocessorName>("custom_pp",
62 : "Postprocessor for custom fixed point convergence check.");
63 933342 : params.addParam<bool>("direct_pp_value",
64 622228 : false,
65 : "True to use direct postprocessor value "
66 : "(scaled by value on first iteration). "
67 : "False (default) to use difference in postprocessor "
68 : "value between fixed point iterations.");
69 1555570 : params.addRangeCheckedParam<Real>("custom_rel_tol",
70 622228 : 1e-8,
71 : "custom_rel_tol>0",
72 : "The relative nonlinear residual drop to shoot for "
73 : "during fixed point iterations. This check is "
74 : "performed based on the postprocessor defined by "
75 : "custom_pp residual.");
76 1555570 : params.addRangeCheckedParam<Real>("custom_abs_tol",
77 622228 : 1e-50,
78 : "custom_abs_tol>0",
79 : "The absolute nonlinear residual to shoot for "
80 : "during fixed point iterations. This check is "
81 : "performed based on postprocessor defined by "
82 : "the custom_pp residual.");
83 :
84 933342 : params.addParamNamesToGroup(
85 : "fixed_point_min_its fixed_point_max_its disable_fixed_point_residual_norm_check "
86 : "accept_on_max_fixed_point_iteration fixed_point_rel_tol fixed_point_abs_tol "
87 : "fixed_point_force_norms custom_pp direct_pp_value custom_abs_tol custom_rel_tol",
88 : "MultiApp fixed point iterations");
89 :
90 311114 : return params;
91 0 : }
92 :
93 : InputParameters
94 177098 : FixedPointSolve::validParams()
95 : {
96 177098 : InputParameters params = emptyInputParameters();
97 177098 : params += FixedPointSolve::fixedPointDefaultConvergenceParams();
98 :
99 708392 : params.addParam<ConvergenceName>(
100 : "multiapp_fixed_point_convergence",
101 : "Name of the Convergence object to use to assess convergence of the "
102 : "MultiApp fixed point solve. If not provided, a default Convergence "
103 : "will be constructed internally from the executioner parameters.");
104 :
105 : // Parameters for relaxing the fixed point process
106 885490 : params.addRangeCheckedParam<Real>("relaxation_factor",
107 354196 : 1.0,
108 : "relaxation_factor>0 & relaxation_factor<2",
109 : "Fraction of newly computed value to keep."
110 : "Set between 0 and 2.");
111 531294 : params.addParam<std::vector<std::string>>(
112 : "transformed_variables",
113 354196 : std::vector<std::string>(),
114 : "List of main app variables to transform during fixed point iterations");
115 531294 : params.addParam<std::vector<PostprocessorName>>(
116 : "transformed_postprocessors",
117 354196 : std::vector<PostprocessorName>(),
118 : "List of main app postprocessors to transform during fixed point iterations");
119 885490 : params.addDeprecatedParam<std::vector<std::string>>(
120 : "relaxed_variables",
121 354196 : std::vector<std::string>(),
122 : "List of main app variables to relax during fixed point iterations",
123 : "Relaxed variables is deprecated, use transformed_variables instead.");
124 :
125 708392 : params.addParam<bool>("auto_advance",
126 : "Whether to automatically advance sub-applications regardless of whether "
127 : "their solve converges, for transient executioners only.");
128 :
129 708392 : params.addParamNamesToGroup(
130 : "multiapp_fixed_point_convergence "
131 : "relaxation_factor transformed_variables transformed_postprocessors auto_advance",
132 : "Fixed point iterations");
133 :
134 531294 : params.addParam<unsigned int>(
135 : "max_xfem_update",
136 354196 : std::numeric_limits<unsigned int>::max(),
137 : "Maximum number of times to update XFEM crack topology in a step due to evolving cracks");
138 531294 : params.addParam<bool>("update_xfem_at_timestep_begin",
139 354196 : false,
140 : "Should XFEM update the mesh at the beginning of the timestep");
141 :
142 531294 : params.addParamNamesToGroup("max_xfem_update update_xfem_at_timestep_begin",
143 : "XFEM fixed point iterations");
144 :
145 177098 : return params;
146 0 : }
147 :
148 62267 : FixedPointSolve::FixedPointSolve(Executioner & ex)
149 : : SolveObject(ex),
150 124534 : _has_fixed_point_its(getParam<unsigned int>("fixed_point_max_its") > 1 ||
151 307009 : getParam<unsigned int>("fixed_point_min_its") > 1 ||
152 244742 : isParamSetByUser("multiapp_fixed_point_convergence")),
153 124534 : _relax_factor(getParam<Real>("relaxation_factor")),
154 124534 : _transformed_vars(getParam<std::vector<std::string>>("transformed_variables")),
155 124534 : _transformed_pps(getParam<std::vector<PostprocessorName>>("transformed_postprocessors")),
156 62267 : _transformed_sys(nullptr),
157 : // this value will be set by MultiApp
158 62267 : _secondary_relaxation_factor(1.0),
159 62267 : _fixed_point_it(0),
160 62267 : _fixed_point_status(MooseFixedPointConvergenceReason::UNSOLVED),
161 124534 : _max_xfem_update(getParam<unsigned int>("max_xfem_update")),
162 124534 : _update_xfem_at_timestep_begin(getParam<bool>("update_xfem_at_timestep_begin")),
163 62267 : _xfem_update_count(0),
164 62267 : _xfem_repeat_step(false),
165 62267 : _old_entering_time(_problem.time() - 1),
166 62267 : _fail_step(false),
167 124534 : _auto_advance_set_by_user(isParamValid("auto_advance")),
168 186810 : _auto_advance_user_value(_auto_advance_set_by_user ? getParam<bool>("auto_advance") : true)
169 : {
170 : // Handle deprecated parameters
171 186801 : if (!parameters().isParamSetByAddParam("relaxed_variables"))
172 0 : _transformed_vars = getParam<std::vector<std::string>>("relaxed_variables");
173 :
174 62267 : if (_transformed_vars.size() > 0 && _transformed_pps.size() > 0)
175 0 : mooseWarning(
176 : "Both variable and postprocessor transformation are active. If the two share dofs, the "
177 : "transformation will not be correct.");
178 62267 : if (_relax_factor != 1 && _transformed_vars.empty() && _transformed_pps.empty())
179 0 : paramError("relaxation_factor",
180 : "Relaxation factor must act on at least one 'transformed_variables' or one "
181 : "'transformed_postprocessors'");
182 :
183 : // Fixed point was not detected, and yet some parameters are passed
184 123014 : if (!_has_fixed_point_its &&
185 305255 : (getParam<Real>("relaxation_factor") != 1 ||
186 305255 : getParam<std::vector<std::string>>("transformed_variables").size() ||
187 244508 : getParam<std::vector<PostprocessorName>>("transformed_postprocessors").size()))
188 0 : paramError("fixed_point_min_its",
189 0 : std::string("Parameter(s) ") +
190 0 : ((getParam<Real>("relaxation_factor") != 1) ? "'relaxation_factor', " : "") +
191 0 : (getParam<std::vector<std::string>>("transformed_variables").size()
192 : ? "'transformed_variables', "
193 0 : : "") +
194 0 : (getParam<std::vector<std::string>>("transformed_postprocessors").size()
195 : ? "'transformed_postprocessors', "
196 0 : : "") +
197 : " were passed to the Executioner for multiapp fixed point iterations, but fixed "
198 : "point iterations are only activiated if 'fixed_point_min_its', "
199 : "'fixed_point_max_its' or 'multiapp_fixed_point_convergence' are passed");
200 :
201 62267 : if (!_app.isUltimateMaster())
202 : {
203 12241 : _secondary_relaxation_factor = _app.fixedPointConfig().sub_relaxation_factor;
204 12241 : _secondary_transformed_variables = _app.fixedPointConfig().sub_transformed_vars;
205 12241 : _secondary_transformed_pps = _app.fixedPointConfig().sub_transformed_pps;
206 : // TODO: use paramError by retrieving parent app's MultiApp
207 12309 : if (_secondary_relaxation_factor != 1 && _secondary_transformed_variables.empty() &&
208 68 : _secondary_transformed_pps.empty())
209 0 : mooseError(
210 : "Secondary relaxation factor, specified in the MultiApps block, must act on at least one "
211 : "'secondary_transformed_variables' or one 'secondary_transformed_postprocessors'. "
212 : "See parent application MultiApp parameters");
213 : }
214 :
215 186801 : if (isParamValid("multiapp_fixed_point_convergence"))
216 234 : _problem.setMultiAppFixedPointConvergenceName(
217 : getParam<ConvergenceName>("multiapp_fixed_point_convergence"));
218 : else
219 62189 : _problem.setNeedToAddDefaultMultiAppFixedPointConvergence();
220 62267 : }
221 :
222 : void
223 58623 : FixedPointSolve::initialSetup()
224 : {
225 58623 : SolveObject::initialSetup();
226 :
227 58623 : allocateStorage(true);
228 :
229 : // Add to the systems to copy if requested in the Problem
230 117445 : for (const auto i : make_range(_problem.numSolverSystems()))
231 58822 : if (_problem.needsPreviousMultiAppFixedPointIterationSolution(i))
232 36 : _systems_to_copy_previous_solutions_for.insert(&_problem.getSolverSystem(i));
233 58623 : if (_problem.needsPreviousMultiAppFixedPointIterationAuxiliary())
234 12 : _systems_to_copy_previous_solutions_for.insert(&_aux);
235 :
236 58623 : if (_has_fixed_point_its)
237 : {
238 1508 : auto & conv = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
239 1508 : conv.checkIterationType(ConvergenceIterationTypes::MULTIAPP_FIXED_POINT);
240 : }
241 58620 : }
242 :
243 : bool
244 266826 : FixedPointSolve::solve()
245 : {
246 800478 : TIME_SECTION("PicardSolve", 1);
247 :
248 266826 : Real current_dt = _problem.dt();
249 :
250 266826 : bool converged = true;
251 :
252 : // need to back up multi-apps even when not doing fixed point iteration for recovering from failed
253 : // multiapp solve
254 266826 : _problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
255 266826 : _problem.backupMultiApps(EXEC_TIMESTEP_BEGIN);
256 266826 : _problem.backupMultiApps(EXEC_TIMESTEP_END);
257 266826 : _problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_END);
258 :
259 : // Prepare to relax variables as a main app
260 266826 : std::set<dof_id_type> transformed_dofs;
261 266826 : if ((_relax_factor != 1.0 || !dynamic_cast<PicardSolve *>(this)) && _transformed_vars.size() > 0)
262 : {
263 : // Snag all of the local dof indices for all of these variables
264 1666 : AllLocalDofIndicesThread aldit(_problem, _transformed_vars);
265 1666 : libMesh::ConstElemRange & elem_range = *_problem.mesh().getActiveLocalElementRange();
266 1666 : Threads::parallel_reduce(elem_range, aldit);
267 :
268 1666 : transformed_dofs = aldit.getDofIndices();
269 1666 : }
270 :
271 : // Prepare to relax variables as a subapp
272 266826 : std::set<dof_id_type> secondary_transformed_dofs;
273 266826 : if (_secondary_relaxation_factor != 1.0 || !dynamic_cast<PicardSolve *>(this))
274 : {
275 37125 : if (_secondary_transformed_variables.size() > 0)
276 : {
277 : // Snag all of the local dof indices for all of these variables
278 5573 : AllLocalDofIndicesThread aldit(_problem, _secondary_transformed_variables);
279 5573 : libMesh::ConstElemRange & elem_range = *_problem.mesh().getActiveLocalElementRange();
280 5573 : Threads::parallel_reduce(elem_range, aldit);
281 :
282 5573 : secondary_transformed_dofs = aldit.getDofIndices();
283 5573 : }
284 :
285 : // To detect a new time step
286 61342 : if (_old_entering_time == _problem.time() &&
287 24217 : _fixed_point_status != MooseFixedPointConvergenceReason::UNSOLVED)
288 : {
289 : // Keep track of the iteration number of the main app
290 24169 : _main_fixed_point_it++;
291 :
292 : // Save variable values before the solve. Solving will provide new values
293 24169 : if (!_app.isUltimateMaster() && _transformed_sys)
294 3990 : saveVariableValues(/*is parent app of this iteration=*/false);
295 : }
296 : else
297 12956 : _main_fixed_point_it = 0;
298 : }
299 :
300 266826 : if (_has_fixed_point_its)
301 : {
302 11176 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
303 11176 : convergence.initialize();
304 : }
305 :
306 266826 : _fixed_point_it = 0;
307 : while (true)
308 : {
309 312612 : if (_has_fixed_point_its)
310 : {
311 56962 : if (_fixed_point_it != 0)
312 : {
313 : // For every iteration other than the first, we need to restore the state of the MultiApps
314 45786 : _problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN);
315 45786 : _problem.restoreMultiApps(EXEC_TIMESTEP_END);
316 : }
317 :
318 56959 : _console << COLOR_MAGENTA << "Beginning fixed point iteration " << _fixed_point_it
319 56959 : << COLOR_DEFAULT << std::endl
320 56959 : << std::endl;
321 : }
322 :
323 : // Solve a single application for one time step
324 312609 : const bool solve_converged = solveStep(transformed_dofs);
325 :
326 312353 : if (solve_converged)
327 : {
328 310271 : if (_has_fixed_point_its)
329 : {
330 56950 : _problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_ITERATION_END);
331 :
332 : // Examine convergence metrics & properties and set the convergence reason
333 56950 : bool break_out = examineFixedPointConvergence(converged);
334 :
335 56950 : if (break_out)
336 : {
337 : // Except DefaultMultiAppFixedPointConvergence, convergence objects will not
338 : // update _fixed_point_status, so we give those cases generic values:
339 11164 : if (_fixed_point_status == MooseFixedPointConvergenceReason::CONVERGED_NONLINEAR)
340 : {
341 42 : if (converged)
342 33 : _fixed_point_status = MooseFixedPointConvergenceReason::CONVERGED_OBJECT;
343 : else
344 9 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_OBJECT;
345 : }
346 :
347 11164 : break;
348 : }
349 : }
350 : }
351 : else
352 : {
353 : // If the last solve didn't converge then we need to exit this step completely (even in the
354 : // case of coupling). So we can retry...
355 2082 : converged = false;
356 2082 : break;
357 : }
358 :
359 299107 : _problem.dt() =
360 : current_dt; // _dt might be smaller than this at this point for multistep methods
361 :
362 299107 : _fixed_point_it++;
363 :
364 299107 : if (!_has_fixed_point_its)
365 253321 : break;
366 45786 : }
367 :
368 266567 : if (converged)
369 : {
370 : // Fixed point iteration loop ends right above
371 264212 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_END);
372 264212 : _problem.execTransfers(EXEC_MULTIAPP_FIXED_POINT_END);
373 264212 : if (!_problem.execMultiApps(EXEC_MULTIAPP_FIXED_POINT_END, autoAdvance()))
374 : {
375 0 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
376 0 : return false;
377 : }
378 264212 : _problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_END);
379 : }
380 :
381 : // Save postprocessors after the solve and their potential timestep_end execution
382 : // The postprocessors could be overwritten at timestep_begin, which is why they are saved
383 : // after the solve. They could also be saved right after the transfers.
384 266567 : if (_old_entering_time == _problem.time())
385 44504 : savePostprocessorValues(false);
386 :
387 266567 : if (converged)
388 : {
389 : // Update the subapp using the fixed point algorithm
390 264212 : if (_secondary_transformed_variables.size() > 0 &&
391 264212 : useFixedPointAlgorithmUpdateInsteadOfPicard(false) && _old_entering_time == _problem.time())
392 3080 : transformVariables(secondary_transformed_dofs, false);
393 :
394 : // Update the entering time, used to detect failed solves
395 264212 : _old_entering_time = _problem.time();
396 : }
397 :
398 266567 : if (_has_fixed_point_its)
399 11173 : printFixedPointConvergenceReason();
400 :
401 266567 : return converged;
402 266567 : }
403 :
404 : void
405 312536 : FixedPointSolve::saveAllValues(const bool primary)
406 : {
407 312536 : if (_transformed_sys)
408 14305 : saveVariableValues(primary);
409 312536 : savePostprocessorValues(primary);
410 312536 : }
411 :
412 : bool
413 312609 : FixedPointSolve::solveStep(const std::set<dof_id_type> & transformed_dofs)
414 : {
415 312609 : bool auto_advance = autoAdvance();
416 :
417 : // Start new TIMESTEP_BEGIN section for solution invalidity
418 312609 : _app.solutionInvalidity().resetIterationOccurences();
419 312609 : _app.solutionInvalidity().resetTimeStepOccurences();
420 :
421 312609 : _executioner.preSolve();
422 312609 : _problem.execTransfers(EXEC_TIMESTEP_BEGIN);
423 :
424 312609 : if (_fixed_point_it == 0)
425 : {
426 266826 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
427 266826 : _problem.execTransfers(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
428 266826 : if (!_problem.execMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN, autoAdvance()))
429 : {
430 0 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
431 0 : return false;
432 : }
433 266826 : _problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
434 : }
435 :
436 312609 : if (!_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, auto_advance))
437 : {
438 9 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
439 9 : return false;
440 : }
441 :
442 312542 : if (_problem.haveXFEM() && _update_xfem_at_timestep_begin)
443 0 : _problem.updateMeshXFEM();
444 :
445 312542 : _problem.execute(EXEC_TIMESTEP_BEGIN);
446 :
447 : // Transform the fixed point postprocessors before solving, but after the timestep_begin transfers
448 : // have been received
449 312539 : if (_transformed_pps.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(true))
450 12591 : transformPostprocessors(true);
451 319098 : if (_secondary_transformed_pps.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(false) &&
452 6559 : _problem.time() == _old_entering_time)
453 6559 : transformPostprocessors(false);
454 :
455 312539 : if (_has_fixed_point_its)
456 : {
457 56950 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
458 56950 : convergence.preExecute();
459 : }
460 :
461 : // Keep track of the solution warnings from the TIMESTEP_BEGIN phase before:
462 : // - the count reset at the beginning of each iteration of the solve
463 : // - the output on TIMESTEP_BEGIN
464 312539 : _app.solutionInvalidity().syncIteration();
465 312539 : _app.solutionInvalidity().accumulateIterationIntoTimeStepOccurences();
466 :
467 : // Perform output for timestep begin
468 312539 : _problem.outputStep(EXEC_TIMESTEP_BEGIN);
469 :
470 : // Update warehouse active objects
471 312536 : _problem.updateActiveObjects();
472 :
473 : // Save the current values of variables and postprocessors, before the solve
474 312536 : saveAllValues(true);
475 :
476 : // Save the previous fixed point iteration solution and aux variables if requested
477 327040 : for (auto * sys : _systems_to_copy_previous_solutions_for)
478 14504 : sys->copyPreviousFixedPointSolutions();
479 :
480 312536 : if (_has_fixed_point_its)
481 56950 : _console << COLOR_MAGENTA << "\nMain app solve:" << COLOR_DEFAULT << std::endl;
482 312536 : if (!_inner_solve->solve())
483 : {
484 1909 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_NONLINEAR;
485 :
486 : // Keep track of the solution warnings from the solve
487 1909 : _app.solutionInvalidity().accumulateTimeStepIntoTotalOccurences(_problem.timeStep());
488 :
489 : // Perform the output of the current, failed time step (this only occurs if desired)
490 1909 : _problem.outputStep(EXEC_FAILED);
491 1909 : return false;
492 : }
493 : else
494 310566 : _fixed_point_status = MooseFixedPointConvergenceReason::CONVERGED_NONLINEAR;
495 :
496 : // Use the fixed point algorithm if the conditions (availability of values, etc) are met
497 310566 : if (_transformed_vars.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(true))
498 5556 : transformVariables(transformed_dofs, true);
499 :
500 310566 : if (_problem.haveXFEM() && (_xfem_update_count < _max_xfem_update) && _problem.updateMeshXFEM())
501 : {
502 0 : _console << "\nRepeating step due to XFEM mesh modification" << std::endl;
503 0 : _xfem_repeat_step = true;
504 0 : ++_xfem_update_count;
505 : }
506 : else
507 : {
508 310566 : if (_problem.haveXFEM())
509 : {
510 0 : _xfem_repeat_step = false;
511 0 : _xfem_update_count = 0;
512 : }
513 :
514 : // Start new TIMESTEP_END section for solution invalidity
515 : // We have to restart the current iteration count to avoid double counting
516 310566 : _app.solutionInvalidity().resetIterationOccurences();
517 :
518 310566 : _problem.onTimestepEnd();
519 310566 : _problem.execute(EXEC_TIMESTEP_END);
520 :
521 310480 : _problem.execTransfers(EXEC_TIMESTEP_END);
522 310480 : if (!_problem.execMultiApps(EXEC_TIMESTEP_END, auto_advance))
523 69 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP;
524 :
525 : // Keep track of the solution warnings from the TIMESTEP_END phase
526 310435 : _app.solutionInvalidity().syncIteration();
527 310435 : _app.solutionInvalidity().accumulateIterationIntoTimeStepOccurences();
528 310435 : _app.solutionInvalidity().accumulateTimeStepIntoTotalOccurences(_problem.timeStep());
529 : }
530 :
531 310435 : if (_fixed_point_status == MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP)
532 69 : return false;
533 310366 : if (_fail_step)
534 : {
535 95 : _fail_step = false;
536 95 : return false;
537 : }
538 :
539 310271 : _executioner.postSolve();
540 :
541 310271 : return true;
542 : }
543 :
544 : bool
545 56950 : FixedPointSolve::examineFixedPointConvergence(bool & converged)
546 : {
547 56950 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_CONVERGENCE);
548 :
549 56950 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
550 : // checkConvergence expects the number of iterations performed, not the iteration index:
551 56950 : const auto n_iter = _fixed_point_it + 1;
552 56950 : const auto status = convergence.checkConvergence(n_iter);
553 56950 : switch (status)
554 : {
555 10891 : case Convergence::MooseConvergenceStatus::CONVERGED:
556 10891 : converged = true;
557 10891 : return true;
558 273 : case Convergence::MooseConvergenceStatus::DIVERGED:
559 273 : converged = false;
560 273 : return true;
561 45786 : case Convergence::MooseConvergenceStatus::ITERATING:
562 45786 : converged = false;
563 45786 : return false;
564 0 : default:
565 0 : mooseError("Should not reach here");
566 : }
567 : }
568 :
569 : void
570 11173 : FixedPointSolve::printFixedPointConvergenceReason()
571 : {
572 11173 : _console << "Fixed point convergence reason: ";
573 11173 : switch (_fixed_point_status)
574 : {
575 3405 : case MooseFixedPointConvergenceReason::CONVERGED_ABS:
576 3405 : _console << "CONVERGED_ABS";
577 3405 : break;
578 7339 : case MooseFixedPointConvergenceReason::CONVERGED_RELATIVE:
579 7339 : _console << "CONVERGED_RELATIVE";
580 7339 : break;
581 40 : case MooseFixedPointConvergenceReason::CONVERGED_PP:
582 40 : _console << "CONVERGED_PP";
583 40 : break;
584 74 : case MooseFixedPointConvergenceReason::REACH_MAX_ITS:
585 74 : _console << "REACH_MAX_ITS";
586 74 : break;
587 33 : case MooseFixedPointConvergenceReason::CONVERGED_OBJECT:
588 33 : _console << "CONVERGED_OBJECT (see Convergence object)";
589 33 : break;
590 264 : case MooseFixedPointConvergenceReason::DIVERGED_MAX_ITS:
591 264 : _console << "DIVERGED_MAX_ITS";
592 264 : break;
593 0 : case MooseFixedPointConvergenceReason::DIVERGED_NONLINEAR:
594 0 : _console << "DIVERGED_NONLINEAR";
595 0 : break;
596 9 : case MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP:
597 9 : _console << "DIVERGED_FAILED_MULTIAPP";
598 9 : break;
599 9 : case MooseFixedPointConvergenceReason::DIVERGED_OBJECT:
600 9 : _console << "DIVERGED_OBJECT (see Convergence object)";
601 9 : break;
602 0 : default:
603 : // UNSOLVED and CONVERGED_NONLINEAR should not be hit when coupling
604 : // iteration is not on here
605 0 : mooseError("Internal error: wrong fixed point status!");
606 : break;
607 : }
608 11173 : _console << std::endl;
609 11173 : }
610 :
611 : bool
612 1033574 : FixedPointSolve::autoAdvance() const
613 : {
614 1033574 : bool auto_advance = !(_has_fixed_point_its && _problem.isTransient());
615 :
616 1033574 : if (dynamic_cast<EigenExecutionerBase *>(&_executioner) && _has_fixed_point_its)
617 0 : auto_advance = true;
618 :
619 1033574 : if (_auto_advance_set_by_user)
620 162 : auto_advance = _auto_advance_user_value;
621 :
622 1033574 : return auto_advance;
623 : }
624 :
625 : bool
626 368587 : FixedPointSolve::performingRelaxation(const bool primary) const
627 : {
628 368587 : if (primary)
629 327722 : return !MooseUtils::absoluteFuzzyEqual(_relax_factor, 1.0);
630 : else
631 40865 : return !MooseUtils::absoluteFuzzyEqual(_secondary_relaxation_factor, 1.0);
632 : }
633 :
634 : void
635 1928 : FixedPointSolve::findTransformedSystem(const bool primary)
636 : {
637 : // Find the system for the transformed variables. They must all belong to the same system
638 1928 : const auto & transformed_vars = primary ? _transformed_vars : _secondary_transformed_variables;
639 1928 : if (!transformed_vars.empty())
640 : {
641 336 : if (_problem.hasAuxiliaryVariable(transformed_vars[0]))
642 0 : _transformed_sys = &_aux;
643 : else
644 336 : _transformed_sys = &_solver_sys;
645 : }
646 :
647 2264 : for (const auto & var_name : transformed_vars)
648 336 : if (!_transformed_sys->hasVariable(var_name))
649 : {
650 0 : if (primary)
651 0 : paramError("transformed_variables",
652 : "Transformed variables must all belong to the same system. Auxiliary and each "
653 : "solver system cannot be mixed");
654 : else
655 0 : mooseError("Secondary transformed variables must all belong to the same system. Auxiliary "
656 : "and each solver system cannot be mixed");
657 : }
658 :
659 1928 : if (primary && _transformed_sys == &_aux)
660 0 : mooseInfo("Transformation of auxiliary variables is only supported for auxiliary variables "
661 : "that are only transferred from the child application");
662 :
663 1928 : if (_transformed_sys)
664 452 : _systems_to_copy_previous_solutions_for.insert(_transformed_sys);
665 1928 : }
|