LCOV - code coverage report
Current view: top level - src/executioners - SteffensenSolve.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 115 119 96.6 %
Date: 2025-08-08 20:01:16 Functions: 9 10 90.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 "SteffensenSolve.h"
      11             : 
      12             : #include "Executioner.h"
      13             : #include "FEProblemBase.h"
      14             : #include "NonlinearSystem.h"
      15             : #include "AllLocalDofIndicesThread.h"
      16             : #include "Console.h"
      17             : #include "DefaultMultiAppFixedPointConvergence.h"
      18             : 
      19             : InputParameters
      20           0 : SteffensenSolve::validParams()
      21             : {
      22           0 :   InputParameters params = FixedPointSolve::validParams();
      23             : 
      24           0 :   return params;
      25             : }
      26             : 
      27         624 : SteffensenSolve::SteffensenSolve(Executioner & ex) : FixedPointSolve(ex) { allocateStorage(true); }
      28             : 
      29             : void
      30         936 : SteffensenSolve::allocateStorage(const bool primary)
      31             : {
      32             :   TagID fxn_m1_tagid;
      33             :   TagID xn_m1_tagid;
      34             :   const std::vector<PostprocessorName> * transformed_pps;
      35             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
      36         936 :   if (primary)
      37             :   {
      38         624 :     xn_m1_tagid = _problem.addVectorTag("xn_m1", Moose::VECTOR_TAG_SOLUTION);
      39         624 :     fxn_m1_tagid = _problem.addVectorTag("fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      40         624 :     transformed_pps = &_transformed_pps;
      41         624 :     transformed_pps_values = &_transformed_pps_values;
      42         624 :     _xn_m1_tagid = xn_m1_tagid;
      43         624 :     _fxn_m1_tagid = fxn_m1_tagid;
      44             :   }
      45             :   else
      46             :   {
      47         312 :     xn_m1_tagid = _problem.addVectorTag("secondary_xn_m1", Moose::VECTOR_TAG_SOLUTION);
      48         312 :     fxn_m1_tagid = _problem.addVectorTag("secondary_fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      49         312 :     transformed_pps = &_secondary_transformed_pps;
      50         312 :     transformed_pps_values = &_secondary_transformed_pps_values;
      51         312 :     _secondary_xn_m1_tagid = xn_m1_tagid;
      52         312 :     _secondary_fxn_m1_tagid = fxn_m1_tagid;
      53             :   }
      54             : 
      55             :   // Store a copy of the previous solution here
      56         936 :   _solver_sys.addVector(xn_m1_tagid, false, PARALLEL);
      57         936 :   _solver_sys.addVector(fxn_m1_tagid, false, PARALLEL);
      58             : 
      59             :   // Allocate storage for the previous postprocessor values
      60         936 :   (*transformed_pps_values).resize((*transformed_pps).size());
      61        1118 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
      62         182 :     (*transformed_pps_values)[i].resize(2);
      63         936 : }
      64             : 
      65             : void
      66         624 : SteffensenSolve::initialSetup()
      67             : {
      68         624 :   FixedPointSolve::initialSetup();
      69             : 
      70         624 :   auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
      71         624 :   if (!dynamic_cast<DefaultMultiAppFixedPointConvergence *>(&convergence))
      72           0 :     mooseError(
      73             :         "Only DefaultMultiAppFixedPointConvergence objects may be used for "
      74             :         "'multiapp_fixed_point_convergence' when using the Steffensen fixed point algorithm.");
      75         624 : }
      76             : 
      77             : void
      78       34038 : SteffensenSolve::saveVariableValues(const bool primary)
      79             : {
      80             :   unsigned int iteration;
      81             :   TagID fxn_m1_tagid;
      82             :   TagID xn_m1_tagid;
      83       34038 :   if (primary)
      84             :   {
      85       24718 :     iteration = _fixed_point_it;
      86       24718 :     fxn_m1_tagid = _fxn_m1_tagid;
      87       24718 :     xn_m1_tagid = _xn_m1_tagid;
      88             :   }
      89             :   else
      90             :   {
      91        9320 :     iteration = _main_fixed_point_it;
      92        9320 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
      93        9320 :     xn_m1_tagid = _secondary_xn_m1_tagid;
      94             :   }
      95             : 
      96             :   // Check to make sure allocateStorage has been called
      97             :   mooseAssert(fxn_m1_tagid != Moose::INVALID_TAG_ID,
      98             :               "allocateStorage has not been called with primary = " + Moose::stringify(primary));
      99             :   mooseAssert(xn_m1_tagid != Moose::INVALID_TAG_ID,
     100             :               "allocateStorage has not been called with primary = " + Moose::stringify(primary));
     101             : 
     102             :   // Save previous variable values
     103       34038 :   NumericVector<Number> & solution = _solver_sys.solution();
     104       34038 :   NumericVector<Number> & fxn_m1 = _solver_sys.getVector(fxn_m1_tagid);
     105       34038 :   NumericVector<Number> & xn_m1 = _solver_sys.getVector(xn_m1_tagid);
     106             : 
     107             :   // What 'solution' is with regards to the Steffensen solve depends on the step
     108       34038 :   if (iteration % 2 == 1)
     109       10684 :     xn_m1 = solution;
     110             :   else
     111       23354 :     fxn_m1 = solution;
     112       34038 : }
     113             : 
     114             : void
     115       34080 : SteffensenSolve::savePostprocessorValues(const bool primary)
     116             : {
     117             :   unsigned int iteration;
     118             :   const std::vector<PostprocessorName> * transformed_pps;
     119             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     120       34080 :   if (primary)
     121             :   {
     122       24718 :     iteration = _fixed_point_it;
     123       24718 :     transformed_pps = &_transformed_pps;
     124       24718 :     transformed_pps_values = &_transformed_pps_values;
     125             :   }
     126             :   else
     127             :   {
     128        9362 :     iteration = _main_fixed_point_it;
     129        9362 :     transformed_pps = &_secondary_transformed_pps;
     130        9362 :     transformed_pps_values = &_secondary_transformed_pps_values;
     131             :   }
     132             : 
     133             :   // Save previous postprocessor values
     134       39663 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     135             :   {
     136        5583 :     if (iteration % 2 == 0)
     137        2848 :       (*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
     138             :     else
     139        2735 :       (*transformed_pps_values)[i][0] = getPostprocessorValueByName((*transformed_pps)[i]);
     140             :   }
     141       34080 : }
     142             : 
     143             : bool
     144       12788 : SteffensenSolve::useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary)
     145             : {
     146             :   // Need at least two values to compute the Steffensen update, and the update is only performed
     147             :   // every other iteration as two evaluations of the coupled problem are necessary
     148       12788 :   if (primary)
     149        7494 :     return _fixed_point_it > 1 && (_fixed_point_it % 2 == 0);
     150             :   else
     151        5294 :     return _main_fixed_point_it > 1 && (_main_fixed_point_it % 2 == 0);
     152             : }
     153             : 
     154             : void
     155        1996 : SteffensenSolve::transformPostprocessors(const bool primary)
     156             : {
     157             :   Real relaxation_factor;
     158             :   const std::vector<PostprocessorName> * transformed_pps;
     159             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     160        1996 :   if (primary)
     161             :   {
     162        1160 :     relaxation_factor = _relax_factor;
     163        1160 :     transformed_pps = &_transformed_pps;
     164        1160 :     transformed_pps_values = &_transformed_pps_values;
     165             :   }
     166             :   else
     167             :   {
     168         836 :     relaxation_factor = _secondary_relaxation_factor;
     169         836 :     transformed_pps = &_secondary_transformed_pps;
     170         836 :     transformed_pps_values = &_secondary_transformed_pps_values;
     171             :   }
     172             : 
     173             :   // Relax postprocessors for the main application
     174        3992 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     175             :   {
     176             :     // Get new postprocessor value
     177        1996 :     const Real current_value = getPostprocessorValueByName((*transformed_pps)[i]);
     178        1996 :     const Real fxn_m1 = (*transformed_pps_values)[i][0];
     179        1996 :     const Real xn_m1 = (*transformed_pps_values)[i][1];
     180             : 
     181             :     // Compute and set relaxed value
     182        1996 :     Real new_value = current_value;
     183        1996 :     if (!MooseUtils::absoluteFuzzyEqual(current_value + xn_m1 - 2 * fxn_m1, 0))
     184        1996 :       new_value =
     185        1996 :           xn_m1 - (fxn_m1 - xn_m1) * (fxn_m1 - xn_m1) / (current_value + xn_m1 - 2 * fxn_m1);
     186             : 
     187             :     // Relax update
     188        1996 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1;
     189             : 
     190        1996 :     _problem.setPostprocessorValueByName((*transformed_pps)[i], new_value);
     191             :   }
     192        1996 : }
     193             : 
     194             : void
     195        2037 : SteffensenSolve::transformVariables(const std::set<dof_id_type> & transformed_dofs,
     196             :                                     const bool primary)
     197             : {
     198             :   Real relaxation_factor;
     199             :   TagID fxn_m1_tagid;
     200             :   TagID xn_m1_tagid;
     201        2037 :   if (primary)
     202             :   {
     203        1335 :     relaxation_factor = _relax_factor;
     204        1335 :     fxn_m1_tagid = _fxn_m1_tagid;
     205        1335 :     xn_m1_tagid = _xn_m1_tagid;
     206             :   }
     207             :   else
     208             :   {
     209         702 :     relaxation_factor = _secondary_relaxation_factor;
     210         702 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
     211         702 :     xn_m1_tagid = _secondary_xn_m1_tagid;
     212             :   }
     213             : 
     214        2037 :   NumericVector<Number> & solution = _solver_sys.solution();
     215        2037 :   NumericVector<Number> & fxn_m1 = _solver_sys.getVector(fxn_m1_tagid);
     216        2037 :   NumericVector<Number> & xn_m1 = _solver_sys.getVector(xn_m1_tagid);
     217             : 
     218      186804 :   for (const auto & dof : transformed_dofs)
     219             :   {
     220             :     // Avoid 0 denominator issue
     221      184767 :     Real new_value = solution(dof);
     222      184767 :     if (!MooseUtils::absoluteFuzzyEqual(solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof), 0))
     223      151173 :       new_value = xn_m1(dof) - (fxn_m1(dof) - xn_m1(dof)) * (fxn_m1(dof) - xn_m1(dof)) /
     224      151173 :                                    (solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof));
     225             : 
     226             :     // Relax update
     227      184767 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1(dof);
     228             : 
     229      184767 :     solution.set(dof, new_value);
     230             :   }
     231        2037 :   solution.close();
     232        2037 :   _solver_sys.update();
     233        2037 : }
     234             : 
     235             : void
     236       12051 : SteffensenSolve::printFixedPointConvergenceHistory(
     237             :     const Real initial_norm,
     238             :     const std::vector<Real> & timestep_begin_norms,
     239             :     const std::vector<Real> & timestep_end_norms) const
     240             : {
     241       12051 :   _console << "\n 0 Steffensen initialization |R| = "
     242       12051 :            << Console::outputNorm(std::numeric_limits<Real>::max(), initial_norm) << '\n';
     243             : 
     244       12051 :   Real max_norm_old = initial_norm;
     245       55074 :   for (unsigned int i = 0; i <= _fixed_point_it; ++i)
     246             :   {
     247       43023 :     Real max_norm = std::max(timestep_begin_norms[i], timestep_end_norms[i]);
     248       43023 :     std::stringstream steffensen_prefix;
     249       43023 :     if (i == 0)
     250       12051 :       steffensen_prefix << " Steffensen initialization |R| = ";
     251       30972 :     else if (i % 2 == 0)
     252       12804 :       steffensen_prefix << " Steffensen half-step      |R| = ";
     253             :     else
     254       18168 :       steffensen_prefix << " Steffensen step           |R| = ";
     255             : 
     256       43023 :     _console << std::setw(2) << i + 1 << steffensen_prefix.str()
     257       43023 :              << Console::outputNorm(max_norm_old, max_norm) << '\n';
     258             : 
     259       43023 :     max_norm_old = max_norm;
     260       43023 :   }
     261       12051 : }

Generated by: LCOV version 1.14