https://mooseframework.inl.gov
FixedPointSolve.C
Go to the documentation of this file.
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"
17 #include "Console.h"
18 #include "EigenExecutionerBase.h"
19 #include "Convergence.h"
21 
24 {
26 
27  params.addParam<unsigned int>(
28  "fixed_point_min_its", 1, "Specifies the minimum number of fixed point iterations.");
29  params.addParam<unsigned int>(
30  "fixed_point_max_its", 1, "Specifies the maximum number of fixed point iterations.");
31  params.addParam<bool>("disable_fixed_point_residual_norm_check",
32  false,
33  "Disable the residual norm evaluation thus the three parameters "
34  "fixed_point_rel_tol, fixed_point_abs_tol and fixed_point_force_norms.");
35  params.addParam<bool>(
36  "fixed_point_force_norms",
37  false,
38  "Force the evaluation of both the TIMESTEP_BEGIN and TIMESTEP_END norms regardless of the "
39  "existence of active MultiApps with those execute_on flags, default: false.");
40  params.addParam<bool>(
41  "accept_on_max_fixed_point_iteration",
42  false,
43  "True to treat reaching the maximum number of fixed point iterations as converged.");
44  params.addRangeCheckedParam<Real>("fixed_point_rel_tol",
45  1e-8,
46  "fixed_point_rel_tol>0",
47  "The relative nonlinear residual drop to shoot for "
48  "during fixed point iterations. This check is "
49  "performed based on the main app's nonlinear "
50  "residual.");
51  params.addRangeCheckedParam<Real>("fixed_point_abs_tol",
52  1e-50,
53  "fixed_point_abs_tol>0",
54  "The absolute nonlinear residual to shoot for "
55  "during fixed point iterations. This check is "
56  "performed based on the main app's nonlinear "
57  "residual.");
58 
59  params.addParam<PostprocessorName>("custom_pp",
60  "Postprocessor for custom fixed point convergence check.");
61  params.addParam<bool>("direct_pp_value",
62  false,
63  "True to use direct postprocessor value "
64  "(scaled by value on first iteration). "
65  "False (default) to use difference in postprocessor "
66  "value between fixed point iterations.");
67  params.addRangeCheckedParam<Real>("custom_rel_tol",
68  1e-8,
69  "custom_rel_tol>0",
70  "The relative nonlinear residual drop to shoot for "
71  "during fixed point iterations. This check is "
72  "performed based on the postprocessor defined by "
73  "custom_pp residual.");
74  params.addRangeCheckedParam<Real>("custom_abs_tol",
75  1e-50,
76  "custom_abs_tol>0",
77  "The absolute nonlinear residual to shoot for "
78  "during fixed point iterations. This check is "
79  "performed based on postprocessor defined by "
80  "the custom_pp residual.");
81 
82  params.addParamNamesToGroup(
83  "fixed_point_min_its fixed_point_max_its disable_fixed_point_residual_norm_check "
84  "accept_on_max_fixed_point_iteration fixed_point_rel_tol fixed_point_abs_tol "
85  "fixed_point_force_norms custom_pp direct_pp_value custom_abs_tol custom_rel_tol",
86  "Fixed point iterations");
87 
88  return params;
89 }
90 
93 {
96 
97  params.addParam<ConvergenceName>(
98  "multiapp_fixed_point_convergence",
99  "Name of the Convergence object to use to assess convergence of the "
100  "MultiApp fixed point solve. If not provided, a default Convergence "
101  "will be constructed internally from the executioner parameters.");
102 
103  // Parameters for relaxing the fixed point process
104  params.addRangeCheckedParam<Real>("relaxation_factor",
105  1.0,
106  "relaxation_factor>0 & relaxation_factor<2",
107  "Fraction of newly computed value to keep."
108  "Set between 0 and 2.");
109  params.addParam<std::vector<std::string>>(
110  "transformed_variables",
111  std::vector<std::string>(),
112  "List of main app variables to transform during fixed point iterations");
113  params.addParam<std::vector<PostprocessorName>>(
114  "transformed_postprocessors",
115  std::vector<PostprocessorName>(),
116  "List of main app postprocessors to transform during fixed point iterations");
117  params.addDeprecatedParam<std::vector<std::string>>(
118  "relaxed_variables",
119  std::vector<std::string>(),
120  "List of main app variables to relax during fixed point iterations",
121  "Relaxed variables is deprecated, use transformed_variables instead.");
122 
123  params.addParam<bool>("auto_advance",
124  "Whether to automatically advance sub-applications regardless of whether "
125  "their solve converges, for transient executioners only.");
126 
127  params.addParamNamesToGroup(
128  "multiapp_fixed_point_convergence "
129  "relaxation_factor transformed_variables transformed_postprocessors auto_advance",
130  "Fixed point iterations");
131 
132  params.addParam<unsigned int>(
133  "max_xfem_update",
135  "Maximum number of times to update XFEM crack topology in a step due to evolving cracks");
136  params.addParam<bool>("update_xfem_at_timestep_begin",
137  false,
138  "Should XFEM update the mesh at the beginning of the timestep");
139 
140  params.addParamNamesToGroup("max_xfem_update update_xfem_at_timestep_begin",
141  "XFEM fixed point iterations");
142 
143  return params;
144 }
145 
147  : SolveObject(ex),
148  _has_fixed_point_its(getParam<unsigned int>("fixed_point_max_its") > 1 ||
149  isParamSetByUser("multiapp_fixed_point_convergence")),
150  _relax_factor(getParam<Real>("relaxation_factor")),
151  _transformed_vars(getParam<std::vector<std::string>>("transformed_variables")),
152  _transformed_pps(getParam<std::vector<PostprocessorName>>("transformed_postprocessors")),
153  // this value will be set by MultiApp
154  _secondary_relaxation_factor(1.0),
155  _fixed_point_it(0),
156  _fixed_point_status(MooseFixedPointConvergenceReason::UNSOLVED),
157  _max_xfem_update(getParam<unsigned int>("max_xfem_update")),
158  _update_xfem_at_timestep_begin(getParam<bool>("update_xfem_at_timestep_begin")),
159  _xfem_update_count(0),
160  _xfem_repeat_step(false),
161  _old_entering_time(_problem.time() - 1),
162  _fail_step(false),
163  _auto_advance_set_by_user(isParamValid("auto_advance")),
164  _auto_advance_user_value(_auto_advance_set_by_user ? getParam<bool>("auto_advance") : true)
165 {
166  // Handle deprecated parameters
167  if (!parameters().isParamSetByAddParam("relaxed_variables"))
168  _transformed_vars = getParam<std::vector<std::string>>("relaxed_variables");
169 
170  if (_transformed_vars.size() > 0 && _transformed_pps.size() > 0)
171  mooseWarning(
172  "Both variable and postprocessor transformation are active. If the two share dofs, the "
173  "transformation will not be correct.");
174 
175  if (!_app.isUltimateMaster())
176  {
180  }
181 
182  if (isParamValid("multiapp_fixed_point_convergence"))
184  getParam<ConvergenceName>("multiapp_fixed_point_convergence"));
185  else
187 }
188 
189 void
191 {
193 
195  {
198  }
199 }
200 
201 bool
203 {
204  TIME_SECTION("PicardSolve", 1);
205 
206  Real current_dt = _problem.dt();
207 
208  bool converged = true;
209 
210  // need to back up multi-apps even when not doing fixed point iteration for recovering from failed
211  // multiapp solve
216 
217  // Prepare to relax variables as a main app
218  std::set<dof_id_type> transformed_dofs;
219  if ((_relax_factor != 1.0 || !dynamic_cast<PicardSolve *>(this)) && _transformed_vars.size() > 0)
220  {
221  // Snag all of the local dof indices for all of these variables
224  Threads::parallel_reduce(elem_range, aldit);
225 
226  transformed_dofs = aldit.getDofIndices();
227  }
228 
229  // Prepare to relax variables as a subapp
230  std::set<dof_id_type> secondary_transformed_dofs;
231  if (_secondary_relaxation_factor != 1.0 || !dynamic_cast<PicardSolve *>(this))
232  {
233  if (_secondary_transformed_variables.size() > 0)
234  {
235  // Snag all of the local dof indices for all of these variables
238  Threads::parallel_reduce(elem_range, aldit);
239 
240  secondary_transformed_dofs = aldit.getDofIndices();
241  }
242 
243  // To detect a new time step
244  if (_old_entering_time == _problem.time() &&
246  {
247  // Keep track of the iteration number of the main app
249 
250  // Save variable values before the solve. Solving will provide new values
251  if (!_app.isUltimateMaster())
252  saveVariableValues(/*is parent app of this iteration=*/false);
253  }
254  else
256  }
257 
259  {
261  convergence.initialize();
262  }
263 
264  _fixed_point_it = 0;
265  while (true)
266  {
268  {
269  if (_fixed_point_it != 0)
270  {
271  // For every iteration other than the first, we need to restore the state of the MultiApps
274  }
275 
276  _console << COLOR_MAGENTA << "Beginning fixed point iteration " << _fixed_point_it
277  << COLOR_DEFAULT << std::endl
278  << std::endl;
279  }
280 
281  // Solve a single application for one time step
282  const bool solve_converged = solveStep(transformed_dofs);
283 
284  if (solve_converged)
285  {
287  {
289 
290  // Examine convergence metrics & properties and set the convergence reason
291  bool break_out = examineFixedPointConvergence(converged);
292 
293  if (break_out)
294  {
295  // Except DefaultMultiAppFixedPointConvergence, convergence objects will not
296  // update _fixed_point_status, so we give those cases generic values:
298  {
299  if (converged)
301  else
303  }
304 
305  break;
306  }
307  }
308  }
309  else
310  {
311  // If the last solve didn't converge then we need to exit this step completely (even in the
312  // case of coupling). So we can retry...
313  converged = false;
314  break;
315  }
316 
317  _problem.dt() =
318  current_dt; // _dt might be smaller than this at this point for multistep methods
319 
320  _fixed_point_it++;
321 
323  break;
324  }
325 
326  if (converged)
327  {
328  // Fixed point iteration loop ends right above
332  {
334  return false;
335  }
337  }
338 
339  // Save postprocessors after the solve and their potential timestep_end execution
340  // The postprocessors could be overwritten at timestep_begin, which is why they are saved
341  // after the solve. They could also be saved right after the transfers.
344 
345  if (converged)
346  {
347  // Update the subapp using the fixed point algorithm
348  if (_secondary_transformed_variables.size() > 0 &&
350  transformVariables(secondary_transformed_dofs, false);
351 
352  // Update the entering time, used to detect failed solves
354  }
355 
358 
359  return converged;
360 }
361 
362 void
364 {
365  saveVariableValues(primary);
366  savePostprocessorValues(primary);
367 }
368 
369 bool
370 FixedPointSolve::solveStep(const std::set<dof_id_type> & transformed_dofs)
371 {
372  bool auto_advance = autoAdvance();
373 
376 
377  if (_fixed_point_it == 0)
378  {
382  {
384  return false;
385  }
387  }
388 
389  if (!_problem.execMultiApps(EXEC_TIMESTEP_BEGIN, auto_advance))
390  {
392  return false;
393  }
394 
397 
399 
400  // Transform the fixed point postprocessors before solving, but after the timestep_begin transfers
401  // have been received
407 
409  {
411  convergence.preExecute();
412  }
413 
414  // Perform output for timestep begin
416 
417  // Update warehouse active objects
419 
420  // Save the current values of variables and postprocessors, before the solve
421  saveAllValues(true);
422 
424  _console << COLOR_MAGENTA << "\nMain app solve:" << COLOR_DEFAULT << std::endl;
425  if (!_inner_solve->solve())
426  {
428 
429  // Perform the output of the current, failed time step (this only occurs if desired)
431  return false;
432  }
433  else
435 
436  // Use the fixed point algorithm if the conditions (availability of values, etc) are met
438  transformVariables(transformed_dofs, true);
439 
441  {
442  _console << "\nXFEM modified mesh, repeating step" << std::endl;
443  _xfem_repeat_step = true;
445  }
446  else
447  {
448  if (_problem.haveXFEM())
449  {
450  _xfem_repeat_step = false;
451  _xfem_update_count = 0;
452  _console << "\nXFEM did not modify mesh, continuing" << std::endl;
453  }
454 
457 
459  if (!_problem.execMultiApps(EXEC_TIMESTEP_END, auto_advance))
460  {
462  return false;
463  }
464  }
465 
466  if (_fail_step)
467  {
468  _fail_step = false;
469  return false;
470  }
471 
473 
474  return true;
475 }
476 
477 bool
479 {
481 
483  const auto status = convergence.checkConvergence(_fixed_point_it);
484  switch (status)
485  {
487  converged = true;
488  return true;
490  converged = false;
491  return true;
493  converged = false;
494  return false;
495  default:
496  mooseError("Should not reach here");
497  }
498 }
499 
500 void
502 {
503  _console << "Fixed point convergence reason: ";
504  switch (_fixed_point_status)
505  {
507  _console << "CONVERGED_ABS";
508  break;
510  _console << "CONVERGED_RELATIVE";
511  break;
513  _console << "CONVERGED_PP";
514  break;
516  _console << "REACH_MAX_ITS";
517  break;
519  _console << "CONVERGED_OBJECT (see Convergence object)";
520  break;
522  _console << "DIVERGED_MAX_ITS";
523  break;
525  _console << "DIVERGED_NONLINEAR";
526  break;
528  _console << "DIVERGED_FAILED_MULTIAPP";
529  break;
531  _console << "DIVERGED_OBJECT (see Convergence object)";
532  break;
533  default:
534  // UNSOLVED and CONVERGED_NONLINEAR should not be hit when coupling
535  // iteration is not on here
536  mooseError("Internal error: wrong fixed point status!");
537  break;
538  }
539  _console << std::endl;
540 }
541 
542 bool
544 {
545  bool auto_advance = !(_has_fixed_point_its && _problem.isTransient());
546 
547  if (dynamic_cast<EigenExecutionerBase *>(&_executioner) && _has_fixed_point_its)
548  auto_advance = true;
549 
551  auto_advance = _auto_advance_user_value;
552 
553  return auto_advance;
554 }
static InputParameters fixedPointDefaultConvergenceParams()
FEProblemBase & _problem
Reference to FEProblem.
Definition: SolveObject.h:47
const ExecFlagType EXEC_FAILED
Definition: Moose.C:46
libMesh::ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:1235
std::vector< std::string > sub_transformed_vars
The names of variables to transform for fixed point solve algorithms (e.g. secant, etc.).
Definition: MooseApp.h:118
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition: MooseApp.h:843
virtual Real & time() const
FixedPointSolve(Executioner &ex)
std::vector< PostprocessorName > sub_transformed_pps
The names of postprocessors to transform for fixed point solve algorithms (e.g. secant, etc.).
Definition: MooseApp.h:120
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
virtual void saveVariableValues(const bool primary)=0
Saves the current values of the variables, and update the old(er) vectors.
void setNeedToAddDefaultMultiAppFixedPointConvergence()
Sets _need_to_add_default_multiapp_fixed_point_convergence to true.
bool examineFixedPointConvergence(bool &converged)
Examine the various convergence metrics.
virtual void initialize()
Method that gets called before each iteration loop.
Definition: Convergence.h:53
virtual void preSolve()
Override this for actions that should take place before execution, called by FixedPointSolve.
Definition: Executioner.h:83
virtual MooseConvergenceStatus checkConvergence(unsigned int iter)=0
Returns convergence status.
FixedPointConfig & fixedPointConfig()
This info is stored here because we need a "globalish" place to put it in order to allow communicatio...
Definition: MooseApp.h:409
virtual void updateActiveObjects()
Update the active objects in the warehouses.
virtual bool solve() override
Iteratively solves the FEProblem.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const ExecFlagType EXEC_MULTIAPP_FIXED_POINT_END
Definition: Moose.C:38
virtual void onTimestepEnd() override
bool haveXFEM()
Find out whether the current analysis is using XFEM.
const ExecFlagType EXEC_TIMESTEP_END
Definition: Moose.C:34
MooseFixedPointConvergenceReason
Enumeration for fixed point convergence reasons.
virtual void initialSetup()
Method that should be executed once, before any solve calls.
Definition: SolveObject.h:32
virtual void saveAllValues(const bool primary)
Save both the variable and postprocessor values.
bool _fail_step
force the current step to fail, triggering are repeat with a cut dt
virtual void transformPostprocessors(const bool primary)=0
Use the fixed point algorithm to transform the postprocessors.
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
InputParameters emptyInputParameters()
const std::set< dof_id_type > & getDofIndices() const
std::vector< PostprocessorName > _secondary_transformed_pps
Postprocessors to be relaxed outside of fixed point iteration (used as a subapp)
auto max(const L &left, const R &right)
const std::vector< PostprocessorName > _transformed_pps
The postprocessors (transferred or not) that are going to be relaxed.
FP converged according to Convergence object.
virtual void savePostprocessorValues(const bool primary)=0
Saves the current values of the postprocessors, and update the old(er) vectors.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Grab all the (possibly semi)local dof indices for the variables passed in, in the system passed in...
MPI_Status status
unsigned int _xfem_update_count
Counter for number of xfem updates that have been performed in the current step.
virtual void execute(const ExecFlagType &exec_type)
Convenience function for performing execution of MOOSE systems.
Executioner & _executioner
Executioner used to construct this.
Definition: SolveObject.h:45
const Real _relax_factor
Relaxation factor for fixed point Iteration.
MooseFixedPointConvergenceReason _fixed_point_status
Status of fixed point solve.
virtual Convergence & getConvergence(const std::string &name, const THREAD_ID tid=0) const
Gets a Convergence object.
void setMultiAppFixedPointConvergenceName(const ConvergenceName &convergence_name)
Sets the MultiApp fixed point convergence object name if there is one.
const ConvergenceName & getMultiAppFixedPointConvergenceName() const
Gets the MultiApp fixed point convergence object name.
const ExecFlagType EXEC_TIMESTEP_BEGIN
Definition: Moose.C:35
SolveObject * _inner_solve
SolveObject wrapped by this solve object.
Definition: SolveObject.h:59
virtual void transformVariables(const std::set< dof_id_type > &transformed_dofs, const bool primary)=0
Use the fixed point algorithm to transform the variables.
virtual bool updateMeshXFEM()
Update the mesh due to changing XFEM cuts.
Executioners are objects that do the actual work of solving your problem.
Definition: Executioner.h:30
virtual void checkIterationType(IterationType) const
Perform checks related to the iteration type.
Definition: Convergence.h:48
Real _secondary_relaxation_factor
Relaxation factor outside of fixed point iteration (used as a subapp)
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
FP converged by relative residual tolerance.
void backupMultiApps(ExecFlagType type)
Backup the MultiApps associated with the ExecFlagType.
unsigned int _fixed_point_it
static InputParameters validParams()
virtual bool useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary)=0
Use the fixed point algorithm transform instead of simply using the Picard update This routine can be...
Real sub_relaxation_factor
relaxation factor to be used for a MultiApp&#39;s subapps.
Definition: MooseApp.h:116
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void postSolve()
Override this for actions that should take place after execution, called by FixedPointSolve.
Definition: Executioner.h:88
const bool _auto_advance_set_by_user
Whether the user has set the auto_advance parameter for handling advancement of sub-applications in m...
const ExecFlagType EXEC_MULTIAPP_FIXED_POINT_BEGIN
Definition: Moose.C:40
void restoreMultiApps(ExecFlagType type, bool force=false)
Restore the MultiApps associated with the ExecFlagType.
std::vector< std::string > _secondary_transformed_variables
Variables to be relaxed outside of fixed point iteration (used as a subapp)
bool autoAdvance() const
Whether sub-applications are automatically advanced no matter what happens during their solves...
const ExecFlagType EXEC_MULTIAPP_FIXED_POINT_ITERATION_END
Definition: Moose.C:36
virtual MooseMesh & mesh() override
bool _xfem_repeat_step
Whether step should be repeated due to xfem modifying the mesh.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
const InputParameters & parameters() const
Get the parameters of the object.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
Real _old_entering_time
Time of previous fixed point solve as a subapp.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Main app nonlinear solve converged, FP unassessed.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
bool execMultiApps(ExecFlagType type, bool auto_advance=true)
Execute the MultiApps associated with the ExecFlagType.
const unsigned int _max_xfem_update
Maximum number of xfem updates per step.
virtual bool isTransient() const override
const ExecFlagType EXEC_MULTIAPP_FIXED_POINT_CONVERGENCE
Definition: Moose.C:42
void printFixedPointConvergenceReason()
Print information about the fixed point convergence.
FP converged by hitting max iterations and accepting.
virtual void initialSetup() override
Method that should be executed once, before any solve calls.
const bool _has_fixed_point_its
Whether or not we activate fixed point iteration.
virtual bool solve()=0
Solve routine provided by this object.
virtual Real & dt() const
virtual bool solveStep(const std::set< dof_id_type > &transformed_dofs)
Perform one fixed point iteration or a full solve.
virtual void preExecute()
Method that gets called in each iteration before the solve.
Definition: Convergence.h:58
const bool _auto_advance_user_value
The value of auto_advance set by the user for handling advancement of sub-applications in multi-app c...
void ErrorVector unsigned int
unsigned int _main_fixed_point_it
fixed point iteration counter for the main app
FP converged by absolute or relative PP tolerance.
virtual void outputStep(ExecFlagType type)
Output the current step.
const bool _update_xfem_at_timestep_begin
Controls whether xfem should update the mesh at the beginning of the time step.
void execTransfers(ExecFlagType type)
Execute the Transfers associated with the ExecFlagType.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
std::vector< std::string > _transformed_vars
The variables (transferred or not) that are going to be relaxed.