LCOV - code coverage report
Current view: top level - src/executioners - SteffensenSolve.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 117 121 96.7 %
Date: 2026-05-29 20:35:17 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         574 : SteffensenSolve::SteffensenSolve(Executioner & ex) : FixedPointSolve(ex) {}
      28             : 
      29             : void
      30         861 : SteffensenSolve::allocateStorage(const bool primary)
      31             : {
      32         861 :   findTransformedSystem(primary);
      33             : 
      34             :   TagID fxn_m1_tagid;
      35             :   TagID xn_m1_tagid;
      36             :   const std::vector<PostprocessorName> * transformed_pps;
      37             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
      38         861 :   if (primary)
      39             :   {
      40         574 :     xn_m1_tagid = _problem.addVectorTag("xn_m1", Moose::VECTOR_TAG_SOLUTION);
      41         574 :     fxn_m1_tagid = _problem.addVectorTag("fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      42         574 :     transformed_pps = &_transformed_pps;
      43         574 :     transformed_pps_values = &_transformed_pps_values;
      44         574 :     _xn_m1_tagid = xn_m1_tagid;
      45         574 :     _fxn_m1_tagid = fxn_m1_tagid;
      46             :   }
      47             :   else
      48             :   {
      49         287 :     xn_m1_tagid = _problem.addVectorTag("secondary_xn_m1", Moose::VECTOR_TAG_SOLUTION);
      50         287 :     fxn_m1_tagid = _problem.addVectorTag("secondary_fxn_m1", Moose::VECTOR_TAG_SOLUTION);
      51         287 :     transformed_pps = &_secondary_transformed_pps;
      52         287 :     transformed_pps_values = &_secondary_transformed_pps_values;
      53         287 :     _secondary_xn_m1_tagid = xn_m1_tagid;
      54         287 :     _secondary_fxn_m1_tagid = fxn_m1_tagid;
      55             :   }
      56             : 
      57             :   // Store a copy of the previous solution here
      58             :   // If we don't have a transformed system, we are not accelerating variables
      59         861 :   if (_transformed_sys)
      60             :   {
      61         208 :     _transformed_sys->addVector(xn_m1_tagid, false, PARALLEL);
      62         208 :     _transformed_sys->addVector(fxn_m1_tagid, false, PARALLEL);
      63             :   }
      64             : 
      65             :   // Allocate storage for the previous postprocessor values
      66         861 :   (*transformed_pps_values).resize((*transformed_pps).size());
      67        1028 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
      68         167 :     (*transformed_pps_values)[i].resize(2);
      69         861 : }
      70             : 
      71             : void
      72         574 : SteffensenSolve::initialSetup()
      73             : {
      74         574 :   FixedPointSolve::initialSetup();
      75             : 
      76         574 :   auto & convergence = _problem.getConvergence(_problem.getMultiAppFixedPointConvergenceName());
      77         574 :   if (!dynamic_cast<DefaultMultiAppFixedPointConvergence *>(&convergence))
      78           0 :     mooseError(
      79             :         "Only DefaultMultiAppFixedPointConvergence objects may be used for "
      80             :         "'multiapp_fixed_point_convergence' when using the Steffensen fixed point algorithm.");
      81         574 : }
      82             : 
      83             : void
      84        7312 : SteffensenSolve::saveVariableValues(const bool primary)
      85             : {
      86             :   unsigned int iteration;
      87             :   TagID fxn_m1_tagid;
      88             :   TagID xn_m1_tagid;
      89        7312 :   if (primary)
      90             :   {
      91        5758 :     iteration = _fixed_point_it;
      92        5758 :     fxn_m1_tagid = _fxn_m1_tagid;
      93        5758 :     xn_m1_tagid = _xn_m1_tagid;
      94             :   }
      95             :   else
      96             :   {
      97        1554 :     iteration = _main_fixed_point_it;
      98        1554 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
      99        1554 :     xn_m1_tagid = _secondary_xn_m1_tagid;
     100             :   }
     101             : 
     102             :   // Check to make sure allocateStorage has been called
     103             :   mooseAssert(fxn_m1_tagid != Moose::INVALID_TAG_ID,
     104             :               "allocateStorage has not been called with primary = " + Moose::stringify(primary));
     105             :   mooseAssert(xn_m1_tagid != Moose::INVALID_TAG_ID,
     106             :               "allocateStorage has not been called with primary = " + Moose::stringify(primary));
     107             : 
     108             :   // Save previous variable values
     109        7312 :   NumericVector<Number> & solution = _transformed_sys->solution();
     110        7312 :   NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
     111        7312 :   NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
     112             : 
     113             :   // What 'solution' is with regards to the Steffensen solve depends on the step
     114        7312 :   if (iteration % 2 == 1)
     115        2420 :     xn_m1 = solution;
     116             :   else
     117        4892 :     fxn_m1 = solution;
     118        7312 : }
     119             : 
     120             : void
     121       31203 : SteffensenSolve::savePostprocessorValues(const bool primary)
     122             : {
     123             :   unsigned int iteration;
     124             :   const std::vector<PostprocessorName> * transformed_pps;
     125             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     126       31203 :   if (primary)
     127             :   {
     128       22628 :     iteration = _fixed_point_it;
     129       22628 :     transformed_pps = &_transformed_pps;
     130       22628 :     transformed_pps_values = &_transformed_pps_values;
     131             :   }
     132             :   else
     133             :   {
     134        8575 :     iteration = _main_fixed_point_it;
     135        8575 :     transformed_pps = &_secondary_transformed_pps;
     136        8575 :     transformed_pps_values = &_secondary_transformed_pps_values;
     137             :   }
     138             : 
     139             :   // Save previous postprocessor values
     140       36309 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     141             :   {
     142        5106 :     if (iteration % 2 == 0)
     143        2605 :       (*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
     144             :     else
     145        2501 :       (*transformed_pps_values)[i][0] = getPostprocessorValueByName((*transformed_pps)[i]);
     146             :   }
     147       31203 : }
     148             : 
     149             : bool
     150       11704 : SteffensenSolve::useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary)
     151             : {
     152             :   // Need at least two values to compute the Steffensen update, and the update is only performed
     153             :   // every other iteration as two evaluations of the coupled problem are necessary
     154       11704 :   if (primary)
     155        6857 :     return _fixed_point_it > 1 && (_fixed_point_it % 2 == 0);
     156             :   else
     157        4847 :     return _main_fixed_point_it > 1 && (_main_fixed_point_it % 2 == 0);
     158             : }
     159             : 
     160             : void
     161        1825 : SteffensenSolve::transformPostprocessors(const bool primary)
     162             : {
     163             :   Real relaxation_factor;
     164             :   const std::vector<PostprocessorName> * transformed_pps;
     165             :   std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
     166        1825 :   if (primary)
     167             :   {
     168        1059 :     relaxation_factor = _relax_factor;
     169        1059 :     transformed_pps = &_transformed_pps;
     170        1059 :     transformed_pps_values = &_transformed_pps_values;
     171             :   }
     172             :   else
     173             :   {
     174         766 :     relaxation_factor = _secondary_relaxation_factor;
     175         766 :     transformed_pps = &_secondary_transformed_pps;
     176         766 :     transformed_pps_values = &_secondary_transformed_pps_values;
     177             :   }
     178             : 
     179             :   // Relax postprocessors for the main application
     180        3650 :   for (size_t i = 0; i < (*transformed_pps).size(); i++)
     181             :   {
     182             :     // Get new postprocessor value
     183        1825 :     const Real current_value = getPostprocessorValueByName((*transformed_pps)[i]);
     184        1825 :     const Real fxn_m1 = (*transformed_pps_values)[i][0];
     185        1825 :     const Real xn_m1 = (*transformed_pps_values)[i][1];
     186             : 
     187             :     // Compute and set relaxed value
     188        1825 :     Real new_value = current_value;
     189        1825 :     if (!MooseUtils::absoluteFuzzyEqual(current_value + xn_m1 - 2 * fxn_m1, 0))
     190        1825 :       new_value =
     191        1825 :           xn_m1 - (fxn_m1 - xn_m1) * (fxn_m1 - xn_m1) / (current_value + xn_m1 - 2 * fxn_m1);
     192             : 
     193             :     // Relax update
     194        1825 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1;
     195             : 
     196        1825 :     _problem.setPostprocessorValueByName((*transformed_pps)[i], new_value);
     197             :   }
     198        1825 : }
     199             : 
     200             : void
     201        1867 : SteffensenSolve::transformVariables(const std::set<dof_id_type> & transformed_dofs,
     202             :                                     const bool primary)
     203             : {
     204             :   Real relaxation_factor;
     205             :   TagID fxn_m1_tagid;
     206             :   TagID xn_m1_tagid;
     207        1867 :   if (primary)
     208             :   {
     209        1223 :     relaxation_factor = _relax_factor;
     210        1223 :     fxn_m1_tagid = _fxn_m1_tagid;
     211        1223 :     xn_m1_tagid = _xn_m1_tagid;
     212             :   }
     213             :   else
     214             :   {
     215         644 :     relaxation_factor = _secondary_relaxation_factor;
     216         644 :     fxn_m1_tagid = _secondary_fxn_m1_tagid;
     217         644 :     xn_m1_tagid = _secondary_xn_m1_tagid;
     218             :   }
     219             : 
     220        1867 :   NumericVector<Number> & solution = _transformed_sys->solution();
     221        1867 :   NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
     222        1867 :   NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
     223             : 
     224      166064 :   for (const auto & dof : transformed_dofs)
     225             :   {
     226             :     // Avoid 0 denominator issue
     227      164197 :     Real new_value = solution(dof);
     228      164197 :     if (!MooseUtils::absoluteFuzzyEqual(solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof), 0))
     229      134343 :       new_value = xn_m1(dof) - (fxn_m1(dof) - xn_m1(dof)) * (fxn_m1(dof) - xn_m1(dof)) /
     230      134343 :                                    (solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof));
     231             : 
     232             :     // Relax update
     233      164197 :     new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1(dof);
     234             : 
     235      164197 :     solution.set(dof, new_value);
     236             :   }
     237        1867 :   solution.close();
     238        1867 :   _transformed_sys->update();
     239        1867 : }
     240             : 
     241             : void
     242       11034 : SteffensenSolve::printFixedPointConvergenceHistory(
     243             :     const Real initial_norm,
     244             :     const std::vector<Real> & timestep_begin_norms,
     245             :     const std::vector<Real> & timestep_end_norms) const
     246             : {
     247       11034 :   _console << "\n 0 Steffensen initialization |R| = "
     248       11034 :            << Console::outputNorm(std::numeric_limits<Real>::max(), initial_norm) << '\n';
     249             : 
     250       11034 :   Real max_norm_old = initial_norm;
     251       50415 :   for (unsigned int i = 0; i <= _fixed_point_it; ++i)
     252             :   {
     253       39381 :     Real max_norm = std::max(timestep_begin_norms[i], timestep_end_norms[i]);
     254       39381 :     std::stringstream steffensen_prefix;
     255       39381 :     if (i == 0)
     256       11034 :       steffensen_prefix << " Steffensen initialization |R| = ";
     257       28347 :     else if (i % 2 == 0)
     258       11718 :       steffensen_prefix << " Steffensen half-step      |R| = ";
     259             :     else
     260       16629 :       steffensen_prefix << " Steffensen step           |R| = ";
     261             : 
     262       39381 :     _console << std::setw(2) << i + 1 << steffensen_prefix.str()
     263       39381 :              << Console::outputNorm(max_norm_old, max_norm) << '\n';
     264             : 
     265       39381 :     max_norm_old = max_norm;
     266       39381 :   }
     267       11034 : }

Generated by: LCOV version 1.14