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 305754 : FixedPointSolve::fixedPointDefaultConvergenceParams()
26 : {
27 305754 : InputParameters params = emptyInputParameters();
28 :
29 917262 : params.addParam<unsigned int>(
30 611508 : "fixed_point_min_its", 1, "Specifies the minimum number of fixed point iterations.");
31 917262 : params.addParam<unsigned int>(
32 611508 : "fixed_point_max_its", 1, "Specifies the maximum number of fixed point iterations.");
33 917262 : params.addParam<bool>("disable_fixed_point_residual_norm_check",
34 611508 : 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 917262 : params.addParam<bool>(
38 : "fixed_point_force_norms",
39 611508 : 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 917262 : params.addParam<bool>(
43 : "accept_on_max_fixed_point_iteration",
44 611508 : false,
45 : "True to treat reaching the maximum number of fixed point iterations as converged.");
46 1528770 : params.addRangeCheckedParam<Real>("fixed_point_rel_tol",
47 611508 : 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 1528770 : params.addRangeCheckedParam<Real>("fixed_point_abs_tol",
54 611508 : 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 1223016 : params.addParam<PostprocessorName>("custom_pp",
62 : "Postprocessor for custom fixed point convergence check.");
63 917262 : params.addParam<bool>("direct_pp_value",
64 611508 : 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 1528770 : params.addRangeCheckedParam<Real>("custom_rel_tol",
70 611508 : 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 1528770 : params.addRangeCheckedParam<Real>("custom_abs_tol",
77 611508 : 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 917262 : 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 305754 : return params;
91 0 : }
92 :
93 : InputParameters
94 174234 : FixedPointSolve::validParams()
95 : {
96 174234 : InputParameters params = emptyInputParameters();
97 174234 : params += FixedPointSolve::fixedPointDefaultConvergenceParams();
98 :
99 696936 : 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 871170 : params.addRangeCheckedParam<Real>("relaxation_factor",
107 348468 : 1.0,
108 : "relaxation_factor>0 & relaxation_factor<2",
109 : "Fraction of newly computed value to keep."
110 : "Set between 0 and 2.");
111 522702 : params.addParam<std::vector<std::string>>(
112 : "transformed_variables",
113 348468 : std::vector<std::string>(),
114 : "List of main app variables to transform during fixed point iterations");
115 522702 : params.addParam<std::vector<PostprocessorName>>(
116 : "transformed_postprocessors",
117 348468 : std::vector<PostprocessorName>(),
118 : "List of main app postprocessors to transform during fixed point iterations");
119 871170 : params.addDeprecatedParam<std::vector<std::string>>(
120 : "relaxed_variables",
121 348468 : 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 696936 : 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 696936 : params.addParamNamesToGroup(
130 : "multiapp_fixed_point_convergence "
131 : "relaxation_factor transformed_variables transformed_postprocessors auto_advance",
132 : "Fixed point iterations");
133 :
134 522702 : params.addParam<unsigned int>(
135 : "max_xfem_update",
136 348468 : std::numeric_limits<unsigned int>::max(),
137 : "Maximum number of times to update XFEM crack topology in a step due to evolving cracks");
138 522702 : params.addParam<bool>("update_xfem_at_timestep_begin",
139 348468 : false,
140 : "Should XFEM update the mesh at the beginning of the timestep");
141 :
142 522702 : params.addParamNamesToGroup("max_xfem_update update_xfem_at_timestep_begin",
143 : "XFEM fixed point iterations");
144 :
145 174234 : return params;
146 0 : }
147 :
148 61073 : FixedPointSolve::FixedPointSolve(Executioner & ex)
149 : : SolveObject(ex),
150 122146 : _has_fixed_point_its(getParam<unsigned int>("fixed_point_max_its") > 1 ||
151 301075 : getParam<unsigned int>("fixed_point_min_its") > 1 ||
152 240002 : isParamSetByUser("multiapp_fixed_point_convergence")),
153 122146 : _relax_factor(getParam<Real>("relaxation_factor")),
154 122146 : _transformed_vars(getParam<std::vector<std::string>>("transformed_variables")),
155 122146 : _transformed_pps(getParam<std::vector<PostprocessorName>>("transformed_postprocessors")),
156 61073 : _transformed_sys(nullptr),
157 : // this value will be set by MultiApp
158 61073 : _secondary_relaxation_factor(1.0),
159 61073 : _fixed_point_it(0),
160 61073 : _fixed_point_status(MooseFixedPointConvergenceReason::UNSOLVED),
161 122146 : _max_xfem_update(getParam<unsigned int>("max_xfem_update")),
162 122146 : _update_xfem_at_timestep_begin(getParam<bool>("update_xfem_at_timestep_begin")),
163 61073 : _xfem_update_count(0),
164 61073 : _xfem_repeat_step(false),
165 61073 : _old_entering_time(_problem.time() - 1),
166 61073 : _fail_step(false),
167 122146 : _auto_advance_set_by_user(isParamValid("auto_advance")),
168 183228 : _auto_advance_user_value(_auto_advance_set_by_user ? getParam<bool>("auto_advance") : true)
169 : {
170 : // Handle deprecated parameters
171 183219 : if (!parameters().isParamSetByAddParam("relaxed_variables"))
172 0 : _transformed_vars = getParam<std::vector<std::string>>("relaxed_variables");
173 :
174 61073 : 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 61073 : 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 120635 : if (!_has_fixed_point_its &&
185 299321 : (getParam<Real>("relaxation_factor") != 1 ||
186 299321 : getParam<std::vector<std::string>>("transformed_variables").size() ||
187 239759 : 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 61073 : if (!_app.isUltimateMaster())
202 : {
203 12088 : _secondary_relaxation_factor = _app.fixedPointConfig().sub_relaxation_factor;
204 12088 : _secondary_transformed_variables = _app.fixedPointConfig().sub_transformed_vars;
205 12088 : _secondary_transformed_pps = _app.fixedPointConfig().sub_transformed_pps;
206 : // TODO: use paramError by retrieving parent app's MultiApp
207 12156 : 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 183219 : if (isParamValid("multiapp_fixed_point_convergence"))
216 243 : _problem.setMultiAppFixedPointConvergenceName(
217 : getParam<ConvergenceName>("multiapp_fixed_point_convergence"));
218 : else
219 60992 : _problem.setNeedToAddDefaultMultiAppFixedPointConvergence();
220 61073 : }
221 :
222 : void
223 57646 : FixedPointSolve::initialSetup()
224 : {
225 57646 : SolveObject::initialSetup();
226 :
227 57646 : allocateStorage(true);
228 :
229 : // Add to the systems to copy if requested in the Problem
230 115428 : for (const auto i : make_range(_problem.numSolverSystems()))
231 57782 : if (_problem.needsPreviousMultiAppFixedPointIterationSolution(i))
232 36 : _systems_to_copy_previous_solutions_for.insert(&_problem.getSolverSystem(i));
233 57646 : if (_problem.needsPreviousMultiAppFixedPointIterationAuxiliary())
234 12 : _systems_to_copy_previous_solutions_for.insert(&_aux);
235 :
236 57646 : if (_has_fixed_point_its)
237 : {
238 1499 : auto & conv = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
239 1499 : conv.checkIterationType(ConvergenceIterationTypes::MULTIAPP_FIXED_POINT);
240 : }
241 57643 : }
242 :
243 : bool
244 262527 : FixedPointSolve::solve()
245 : {
246 787581 : TIME_SECTION("PicardSolve", 1);
247 :
248 262527 : Real current_dt = _problem.dt();
249 :
250 262527 : 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 262527 : _problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
255 262527 : _problem.backupMultiApps(EXEC_TIMESTEP_BEGIN);
256 262527 : _problem.backupMultiApps(EXEC_TIMESTEP_END);
257 262527 : _problem.backupMultiApps(EXEC_MULTIAPP_FIXED_POINT_END);
258 :
259 : // Prepare to relax variables as a main app
260 262527 : std::set<dof_id_type> transformed_dofs;
261 262527 : 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 262527 : std::set<dof_id_type> secondary_transformed_dofs;
273 262527 : 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 262527 : if (_has_fixed_point_its)
301 : {
302 11167 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
303 11167 : convergence.initialize();
304 : }
305 :
306 262527 : _fixed_point_it = 0;
307 : while (true)
308 : {
309 308328 : if (_has_fixed_point_its)
310 : {
311 56968 : if (_fixed_point_it != 0)
312 : {
313 : // For every iteration other than the first, we need to restore the state of the MultiApps
314 45801 : _problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN);
315 45801 : _problem.restoreMultiApps(EXEC_TIMESTEP_END);
316 : }
317 :
318 56965 : _console << COLOR_MAGENTA << "Beginning fixed point iteration " << _fixed_point_it
319 56965 : << COLOR_DEFAULT << std::endl
320 56965 : << std::endl;
321 : }
322 :
323 : // Solve a single application for one time step
324 308325 : const bool solve_converged = solveStep(transformed_dofs);
325 :
326 308069 : if (solve_converged)
327 : {
328 306039 : if (_has_fixed_point_its)
329 : {
330 56956 : _problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_ITERATION_END);
331 :
332 : // Examine convergence metrics & properties and set the convergence reason
333 56956 : bool break_out = examineFixedPointConvergence(converged);
334 :
335 56956 : if (break_out)
336 : {
337 : // Except DefaultMultiAppFixedPointConvergence, convergence objects will not
338 : // update _fixed_point_status, so we give those cases generic values:
339 11155 : if (_fixed_point_status == MooseFixedPointConvergenceReason::CONVERGED_NONLINEAR)
340 : {
341 44 : if (converged)
342 44 : _fixed_point_status = MooseFixedPointConvergenceReason::CONVERGED_OBJECT;
343 : else
344 0 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_OBJECT;
345 : }
346 :
347 11155 : 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 2030 : converged = false;
356 2030 : break;
357 : }
358 :
359 294884 : _problem.dt() =
360 : current_dt; // _dt might be smaller than this at this point for multistep methods
361 :
362 294884 : _fixed_point_it++;
363 :
364 294884 : if (!_has_fixed_point_its)
365 249083 : break;
366 45801 : }
367 :
368 262268 : if (converged)
369 : {
370 : // Fixed point iteration loop ends right above
371 259974 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_END);
372 259974 : _problem.execTransfers(EXEC_MULTIAPP_FIXED_POINT_END);
373 259974 : 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 259974 : _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 262268 : if (_old_entering_time == _problem.time())
385 44467 : savePostprocessorValues(false);
386 :
387 262268 : if (converged)
388 : {
389 : // Update the subapp using the fixed point algorithm
390 259974 : if (_secondary_transformed_variables.size() > 0 &&
391 259974 : 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 259974 : _old_entering_time = _problem.time();
396 : }
397 :
398 262268 : if (_has_fixed_point_its)
399 11164 : printFixedPointConvergenceReason();
400 :
401 262268 : return converged;
402 262268 : }
403 :
404 : void
405 308252 : FixedPointSolve::saveAllValues(const bool primary)
406 : {
407 308252 : if (_transformed_sys)
408 14305 : saveVariableValues(primary);
409 308252 : savePostprocessorValues(primary);
410 308252 : }
411 :
412 : bool
413 308325 : FixedPointSolve::solveStep(const std::set<dof_id_type> & transformed_dofs)
414 : {
415 308325 : bool auto_advance = autoAdvance();
416 :
417 : // Start new TIMESTEP_BEGIN section for solution invalidity
418 308325 : _app.solutionInvalidity().resetIterationOccurences();
419 308325 : _app.solutionInvalidity().resetTimeStepOccurences();
420 :
421 308325 : _executioner.preSolve();
422 308325 : _problem.execTransfers(EXEC_TIMESTEP_BEGIN);
423 :
424 308325 : if (_fixed_point_it == 0)
425 : {
426 262527 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
427 262527 : _problem.execTransfers(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
428 262527 : 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 262527 : _problem.outputStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
434 : }
435 :
436 308325 : 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 308258 : if (_problem.haveXFEM() && _update_xfem_at_timestep_begin)
443 0 : _problem.updateMeshXFEM();
444 :
445 308258 : _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 308255 : if (_transformed_pps.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(true))
450 12591 : transformPostprocessors(true);
451 314814 : if (_secondary_transformed_pps.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(false) &&
452 6559 : _problem.time() == _old_entering_time)
453 6559 : transformPostprocessors(false);
454 :
455 308255 : if (_has_fixed_point_its)
456 : {
457 56956 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
458 56956 : 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 308255 : _app.solutionInvalidity().syncIteration();
465 308255 : _app.solutionInvalidity().accumulateIterationIntoTimeStepOccurences();
466 :
467 : // Perform output for timestep begin
468 308255 : _problem.outputStep(EXEC_TIMESTEP_BEGIN);
469 :
470 : // Update warehouse active objects
471 308252 : _problem.updateActiveObjects();
472 :
473 : // Save the current values of variables and postprocessors, before the solve
474 308252 : saveAllValues(true);
475 :
476 : // Save the previous fixed point iteration solution and aux variables if requested
477 322756 : for (auto * sys : _systems_to_copy_previous_solutions_for)
478 14504 : sys->copyPreviousFixedPointSolutions();
479 :
480 308252 : if (_has_fixed_point_its)
481 56956 : _console << COLOR_MAGENTA << "\nMain app solve:" << COLOR_DEFAULT << std::endl;
482 308252 : if (!_inner_solve->solve())
483 : {
484 1857 : _fixed_point_status = MooseFixedPointConvergenceReason::DIVERGED_NONLINEAR;
485 :
486 : // Keep track of the solution warnings from the solve
487 1857 : _app.solutionInvalidity().accumulateTimeStepIntoTotalOccurences(_problem.timeStep());
488 :
489 : // Perform the output of the current, failed time step (this only occurs if desired)
490 1857 : _problem.outputStep(EXEC_FAILED);
491 1857 : return false;
492 : }
493 : else
494 306334 : _fixed_point_status = MooseFixedPointConvergenceReason::CONVERGED_NONLINEAR;
495 :
496 : // Use the fixed point algorithm if the conditions (availability of values, etc) are met
497 306334 : if (_transformed_vars.size() > 0 && useFixedPointAlgorithmUpdateInsteadOfPicard(true))
498 5556 : transformVariables(transformed_dofs, true);
499 :
500 306334 : 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 306334 : 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 306334 : _app.solutionInvalidity().resetIterationOccurences();
517 :
518 306334 : _problem.onTimestepEnd();
519 306334 : _problem.execute(EXEC_TIMESTEP_END);
520 :
521 306248 : _problem.execTransfers(EXEC_TIMESTEP_END);
522 306248 : 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 306203 : _app.solutionInvalidity().syncIteration();
527 306203 : _app.solutionInvalidity().accumulateIterationIntoTimeStepOccurences();
528 306203 : _app.solutionInvalidity().accumulateTimeStepIntoTotalOccurences(_problem.timeStep());
529 : }
530 :
531 306203 : if (_fixed_point_status == MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP)
532 69 : return false;
533 306134 : if (_fail_step)
534 : {
535 95 : _fail_step = false;
536 95 : return false;
537 : }
538 :
539 306039 : _executioner.postSolve();
540 :
541 306039 : return true;
542 : }
543 :
544 : bool
545 56956 : FixedPointSolve::examineFixedPointConvergence(bool & converged)
546 : {
547 56956 : _problem.execute(EXEC_MULTIAPP_FIXED_POINT_CONVERGENCE);
548 :
549 56956 : auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
550 56956 : const auto status = convergence.checkConvergence(_fixed_point_it);
551 56956 : switch (status)
552 : {
553 10891 : case Convergence::MooseConvergenceStatus::CONVERGED:
554 10891 : converged = true;
555 10891 : return true;
556 264 : case Convergence::MooseConvergenceStatus::DIVERGED:
557 264 : converged = false;
558 264 : return true;
559 45801 : case Convergence::MooseConvergenceStatus::ITERATING:
560 45801 : converged = false;
561 45801 : return false;
562 0 : default:
563 0 : mooseError("Should not reach here");
564 : }
565 : }
566 :
567 : void
568 11164 : FixedPointSolve::printFixedPointConvergenceReason()
569 : {
570 11164 : _console << "Fixed point convergence reason: ";
571 11164 : switch (_fixed_point_status)
572 : {
573 3394 : case MooseFixedPointConvergenceReason::CONVERGED_ABS:
574 3394 : _console << "CONVERGED_ABS";
575 3394 : break;
576 7339 : case MooseFixedPointConvergenceReason::CONVERGED_RELATIVE:
577 7339 : _console << "CONVERGED_RELATIVE";
578 7339 : break;
579 40 : case MooseFixedPointConvergenceReason::CONVERGED_PP:
580 40 : _console << "CONVERGED_PP";
581 40 : break;
582 74 : case MooseFixedPointConvergenceReason::REACH_MAX_ITS:
583 74 : _console << "REACH_MAX_ITS";
584 74 : break;
585 44 : case MooseFixedPointConvergenceReason::CONVERGED_OBJECT:
586 44 : _console << "CONVERGED_OBJECT (see Convergence object)";
587 44 : break;
588 264 : case MooseFixedPointConvergenceReason::DIVERGED_MAX_ITS:
589 264 : _console << "DIVERGED_MAX_ITS";
590 264 : break;
591 0 : case MooseFixedPointConvergenceReason::DIVERGED_NONLINEAR:
592 0 : _console << "DIVERGED_NONLINEAR";
593 0 : break;
594 9 : case MooseFixedPointConvergenceReason::DIVERGED_FAILED_MULTIAPP:
595 9 : _console << "DIVERGED_FAILED_MULTIAPP";
596 9 : break;
597 0 : case MooseFixedPointConvergenceReason::DIVERGED_OBJECT:
598 0 : _console << "DIVERGED_OBJECT (see Convergence object)";
599 0 : break;
600 0 : default:
601 : // UNSOLVED and CONVERGED_NONLINEAR should not be hit when coupling
602 : // iteration is not on here
603 0 : mooseError("Internal error: wrong fixed point status!");
604 : break;
605 : }
606 11164 : _console << std::endl;
607 11164 : }
608 :
609 : bool
610 1016273 : FixedPointSolve::autoAdvance() const
611 : {
612 1016273 : bool auto_advance = !(_has_fixed_point_its && _problem.isTransient());
613 :
614 1016273 : if (dynamic_cast<EigenExecutionerBase *>(&_executioner) && _has_fixed_point_its)
615 0 : auto_advance = true;
616 :
617 1016273 : if (_auto_advance_set_by_user)
618 162 : auto_advance = _auto_advance_user_value;
619 :
620 1016273 : return auto_advance;
621 : }
622 :
623 : bool
624 363136 : FixedPointSolve::performingRelaxation(const bool primary) const
625 : {
626 363136 : if (primary)
627 322461 : return !MooseUtils::absoluteFuzzyEqual(_relax_factor, 1.0);
628 : else
629 40675 : return !MooseUtils::absoluteFuzzyEqual(_secondary_relaxation_factor, 1.0);
630 : }
631 :
632 : void
633 1928 : FixedPointSolve::findTransformedSystem(const bool primary)
634 : {
635 : // Find the system for the transformed variables. They must all belong to the same system
636 1928 : const auto & transformed_vars = primary ? _transformed_vars : _secondary_transformed_variables;
637 1928 : if (!transformed_vars.empty())
638 : {
639 336 : if (_problem.hasAuxiliaryVariable(transformed_vars[0]))
640 0 : _transformed_sys = &_aux;
641 : else
642 336 : _transformed_sys = &_solver_sys;
643 : }
644 :
645 2264 : for (const auto & var_name : transformed_vars)
646 336 : if (!_transformed_sys->hasVariable(var_name))
647 : {
648 0 : if (primary)
649 0 : paramError("transformed_variables",
650 : "Transformed variables must all belong to the same system. Auxiliary and each "
651 : "solver system cannot be mixed");
652 : else
653 0 : mooseError("Secondary transformed variables must all belong to the same system. Auxiliary "
654 : "and each solver system cannot be mixed");
655 : }
656 :
657 1928 : if (primary && _transformed_sys == &_aux)
658 0 : mooseInfo("Transformation of auxiliary variables is only supported for auxiliary variables "
659 : "that are only transferred from the child application");
660 :
661 1928 : if (_transformed_sys)
662 452 : _systems_to_copy_previous_solutions_for.insert(_transformed_sys);
663 1928 : }
|