LCOV - code coverage report
Current view: top level - src/executioners - SteffensenSolve.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 110 119 92.4 %
Date: 2025-07-17 01:28:37 Functions: 8 10 80.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         576 : SteffensenSolve::SteffensenSolve(Executioner & ex) : FixedPointSolve(ex) { allocateStorage(true); }
      28             : 
      29             : void
      30         864 : 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         864 :   if (primary)
      37             :   {
      38         576 :     xn_m1_tagid = _problem.addVectorTag("xn_m1", Moose::VECTOR_TAG_SOLUTION);
      39         576 :     fxn_m1_tagid = _problem.addVectorTag("fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      40         576 :     transformed_pps = &_transformed_pps;
      41         576 :     transformed_pps_values = &_transformed_pps_values;
      42         576 :     _xn_m1_tagid = xn_m1_tagid;
      43         576 :     _fxn_m1_tagid = fxn_m1_tagid;
      44             :   }
      45             :   else
      46             :   {
      47         288 :     xn_m1_tagid = _problem.addVectorTag("secondary_xn_m1", Moose::VECTOR_TAG_SOLUTION);
      48         288 :     fxn_m1_tagid = _problem.addVectorTag("secondary_fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      49         288 :     transformed_pps = &_secondary_transformed_pps;
      50         288 :     transformed_pps_values = &_secondary_transformed_pps_values;
      51         288 :     _secondary_xn_m1_tagid = xn_m1_tagid;
      52         288 :     _secondary_fxn_m1_tagid = fxn_m1_tagid;
      53             :   }
      54             : 
      55             :   // Store a copy of the previous solution here
      56         864 :   _solver_sys.addVector(xn_m1_tagid, false, PARALLEL);
      57         864 :   _solver_sys.addVector(fxn_m1_tagid, false, PARALLEL);
      58             : 
      59             :   // Allocate storage for the previous postprocessor values
      60         864 :   (*transformed_pps_values).resize((*transformed_pps).size());
      61        1032 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
      62         168 :     (*transformed_pps_values)[i].resize(2);
      63         864 : }
      64             : 
      65             : void
      66           0 : SteffensenSolve::initialSetup()
      67             : {
      68           0 :   FixedPointSolve::initialSetup();
      69             : 
      70           0 :   auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
      71           0 :   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           0 : }
      76             : 
      77             : void
      78       31001 : SteffensenSolve::saveVariableValues(const bool primary)
      79             : {
      80             :   unsigned int iteration;
      81             :   TagID fxn_m1_tagid;
      82             :   TagID xn_m1_tagid;
      83       31001 :   if (primary)
      84             :   {
      85       22514 :     iteration = _fixed_point_it;
      86       22514 :     fxn_m1_tagid = _fxn_m1_tagid;
      87       22514 :     xn_m1_tagid = _xn_m1_tagid;
      88             :   }
      89             :   else
      90             :   {
      91        8487 :     iteration = _main_fixed_point_it;
      92        8487 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
      93        8487 :     xn_m1_tagid = _secondary_xn_m1_tagid;
      94             :   }
      95             : 
      96             :   // Save previous variable values
      97       31001 :   NumericVector<Number> & solution = _solver_sys.solution();
      98       31001 :   NumericVector<Number> & fxn_m1 = _solver_sys.getVector(fxn_m1_tagid);
      99       31001 :   NumericVector<Number> & xn_m1 = _solver_sys.getVector(xn_m1_tagid);
     100             : 
     101             :   // What 'solution' is with regards to the Steffensen solve depends on the step
     102       31001 :   if (iteration % 2 == 1)
     103        9736 :     xn_m1 = solution;
     104             :   else
     105       21265 :     fxn_m1 = solution;
     106       31001 : }
     107             : 
     108             : void
     109       31001 : SteffensenSolve::savePostprocessorValues(const bool primary)
     110             : {
     111             :   unsigned int iteration;
     112             :   const std::vector<PostprocessorName> * transformed_pps;
     113             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     114       31001 :   if (primary)
     115             :   {
     116       22514 :     iteration = _fixed_point_it;
     117       22514 :     transformed_pps = &_transformed_pps;
     118       22514 :     transformed_pps_values = &_transformed_pps_values;
     119             :   }
     120             :   else
     121             :   {
     122        8487 :     iteration = _main_fixed_point_it;
     123        8487 :     transformed_pps = &_secondary_transformed_pps;
     124        8487 :     transformed_pps_values = &_secondary_transformed_pps_values;
     125             :   }
     126             : 
     127             :   // Save previous postprocessor values
     128       36101 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     129             :   {
     130        5100 :     if (iteration % 2 == 0)
     131        2600 :       (*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
     132             :     else
     133        2500 :       (*transformed_pps_values)[i][0] = getPostprocessorValueByName((*transformed_pps)[i]);
     134             :   }
     135       31001 : }
     136             : 
     137             : bool
     138       11647 : SteffensenSolve::useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary)
     139             : {
     140             :   // Need at least two values to compute the Steffensen update, and the update is only performed
     141             :   // every other iteration as two evaluations of the coupled problem are necessary
     142       11647 :   if (primary)
     143        6837 :     return _fixed_point_it > 1 && (_fixed_point_it % 2 == 0);
     144             :   else
     145        4810 :     return _main_fixed_point_it > 1 && (_main_fixed_point_it % 2 == 0);
     146             : }
     147             : 
     148             : void
     149        1820 : SteffensenSolve::transformPostprocessors(const bool primary)
     150             : {
     151             :   Real relaxation_factor;
     152             :   const std::vector<PostprocessorName> * transformed_pps;
     153             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     154        1820 :   if (primary)
     155             :   {
     156        1060 :     relaxation_factor = _relax_factor;
     157        1060 :     transformed_pps = &_transformed_pps;
     158        1060 :     transformed_pps_values = &_transformed_pps_values;
     159             :   }
     160             :   else
     161             :   {
     162         760 :     relaxation_factor = _secondary_relaxation_factor;
     163         760 :     transformed_pps = &_secondary_transformed_pps;
     164         760 :     transformed_pps_values = &_secondary_transformed_pps_values;
     165             :   }
     166             : 
     167             :   // Relax postprocessors for the main application
     168        3640 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     169             :   {
     170             :     // Get new postprocessor value
     171        1820 :     const Real current_value = getPostprocessorValueByName((*transformed_pps)[i]);
     172        1820 :     const Real fxn_m1 = (*transformed_pps_values)[i][0];
     173        1820 :     const Real xn_m1 = (*transformed_pps_values)[i][1];
     174             : 
     175             :     // Compute and set relaxed value
     176        1820 :     Real new_value = current_value;
     177        1820 :     if (!MooseUtils::absoluteFuzzyEqual(current_value + xn_m1 - 2 * fxn_m1, 0))
     178        1820 :       new_value =
     179        1820 :           xn_m1 - (fxn_m1 - xn_m1) * (fxn_m1 - xn_m1) / (current_value + xn_m1 - 2 * fxn_m1);
     180             : 
     181             :     // Relax update
     182        1820 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1;
     183             : 
     184        1820 :     _problem.setPostprocessorValueByName((*transformed_pps)[i], new_value);
     185             :   }
     186        1820 : }
     187             : 
     188             : void
     189        1849 : SteffensenSolve::transformVariables(const std::set<dof_id_type> & transformed_dofs,
     190             :                                     const bool primary)
     191             : {
     192             :   Real relaxation_factor;
     193             :   TagID fxn_m1_tagid;
     194             :   TagID xn_m1_tagid;
     195        1849 :   if (primary)
     196             :   {
     197        1211 :     relaxation_factor = _relax_factor;
     198        1211 :     fxn_m1_tagid = _fxn_m1_tagid;
     199        1211 :     xn_m1_tagid = _xn_m1_tagid;
     200             :   }
     201             :   else
     202             :   {
     203         638 :     relaxation_factor = _secondary_relaxation_factor;
     204         638 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
     205         638 :     xn_m1_tagid = _secondary_xn_m1_tagid;
     206             :   }
     207             : 
     208        1849 :   NumericVector<Number> & solution = _solver_sys.solution();
     209        1849 :   NumericVector<Number> & fxn_m1 = _solver_sys.getVector(fxn_m1_tagid);
     210        1849 :   NumericVector<Number> & xn_m1 = _solver_sys.getVector(xn_m1_tagid);
     211             : 
     212      163868 :   for (const auto & dof : transformed_dofs)
     213             :   {
     214             :     // Avoid 0 denominator issue
     215      162019 :     Real new_value = solution(dof);
     216      162019 :     if (!MooseUtils::absoluteFuzzyEqual(solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof), 0))
     217      132561 :       new_value = xn_m1(dof) - (fxn_m1(dof) - xn_m1(dof)) * (fxn_m1(dof) - xn_m1(dof)) /
     218      132561 :                                    (solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof));
     219             : 
     220             :     // Relax update
     221      162019 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1(dof);
     222             : 
     223      162019 :     solution.set(dof, new_value);
     224             :   }
     225        1849 :   solution.close();
     226        1849 :   _solver_sys.update();
     227        1849 : }
     228             : 
     229             : void
     230       10977 : SteffensenSolve::printFixedPointConvergenceHistory(
     231             :     const Real initial_norm,
     232             :     const std::vector<Real> & timestep_begin_norms,
     233             :     const std::vector<Real> & timestep_end_norms) const
     234             : {
     235       10977 :   _console << "\n 0 Steffensen initialization |R| = "
     236       10977 :            << Console::outputNorm(std::numeric_limits<Real>::max(), initial_norm) << '\n';
     237             : 
     238       10977 :   Real max_norm_old = initial_norm;
     239       50106 :   for (unsigned int i = 0; i <= _fixed_point_it; ++i)
     240             :   {
     241       39129 :     Real max_norm = std::max(timestep_begin_norms[i], timestep_end_norms[i]);
     242       39129 :     std::stringstream steffensen_prefix;
     243       39129 :     if (i == 0)
     244       10977 :       steffensen_prefix << " Steffensen initialization |R| = ";
     245       28152 :     else if (i % 2 == 0)
     246       11632 :       steffensen_prefix << " Steffensen half-step      |R| = ";
     247             :     else
     248       16520 :       steffensen_prefix << " Steffensen step           |R| = ";
     249             : 
     250       39129 :     _console << std::setw(2) << i + 1 << steffensen_prefix.str()
     251       39129 :              << Console::outputNorm(max_norm_old, max_norm) << '\n';
     252             : 
     253       39129 :     max_norm_old = max_norm;
     254       39129 :   }
     255       10977 : }

Generated by: LCOV version 1.14