LCOV - code coverage report
Current view: top level - src/executioners - FixedPointSolve.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 291 331 87.9 %
Date: 2026-05-29 20:35:17 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14