LCOV - code coverage report
Current view: top level - src/outputs - PetscOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 101 103 98.1 %
Date: 2025-08-08 20:01:16 Functions: 8 8 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             : // MOOSE includes
      11             : #include "PetscOutput.h"
      12             : #include "FEProblem.h"
      13             : #include "NonlinearSystem.h"
      14             : #include "CommonOutputAction.h"
      15             : 
      16             : #include "libmesh/libmesh_common.h"
      17             : #include "libmesh/petsc_nonlinear_solver.h"
      18             : 
      19      167649 : PetscOutputInterface::PetscOutputInterface(PetscOutput * obj) : _petsc_output(obj)
      20             : {
      21             :   // register petsc output interface
      22      167649 :   obj->getMooseApp().registerInterfaceObject(*this);
      23      167649 : }
      24             : 
      25             : PetscErrorCode
      26      813200 : PetscOutputInterface::petscNonlinearOutput(SNES, PetscInt its, PetscReal norm, void * void_ptr)
      27             : {
      28             :   // Get the primary outputter object
      29      813200 :   PetscOutput * primary_ptr = static_cast<PetscOutput *>(void_ptr);
      30             : 
      31             :   // loop over all interface objects
      32     3052444 :   for (const auto poi_ptr : primary_ptr->getMooseApp().getInterfaceObjects<PetscOutputInterface>())
      33             :   {
      34     2239244 :     auto ptr = poi_ptr->_petsc_output;
      35             : 
      36             :     // check time
      37     2239244 :     if (!ptr->inNonlinearTimeWindow())
      38         978 :       continue;
      39             : 
      40             :     // Update the pseudo times
      41     2238266 :     ptr->_nonlinear_time += ptr->_nonlinear_dt;
      42     2238266 :     ptr->_linear_time = ptr->_nonlinear_time;
      43             : 
      44             :     // Set the current norm and iteration number
      45     2238266 :     ptr->_norm = norm;
      46     2238266 :     ptr->_nonlinear_iter = its;
      47             : 
      48             :     // Set the flag indicating that output is occurring on the non-linear residual
      49     2238266 :     ptr->_on_nonlinear_residual = true;
      50             : 
      51             :     // Perform the output
      52     2238266 :     ptr->outputStep(EXEC_NONLINEAR);
      53             : 
      54             :     /**
      55             :      * This is one of three locations where we explicitly flush the output buffers during a
      56             :      * simulation:
      57             :      * PetscOutput::petscNonlinearOutput()
      58             :      * PetscOutput::petscLinearOutput()
      59             :      * OutputWarehouse::outputStep()
      60             :      *
      61             :      * All other Console output _should_ be using newlines to avoid covering buffer errors
      62             :      * and to avoid excessive I/O. This call is necessary. In the PETSc callback the
      63             :      * context bypasses the OutputWarehouse.
      64             :      */
      65     2238266 :     ptr->_app.getOutputWarehouse().flushConsoleBuffer();
      66             : 
      67             :     // Reset the non-linear output flag and the simulation time
      68     2238266 :     ptr->_on_nonlinear_residual = false;
      69             :   }
      70             : 
      71             :   // Done
      72      813200 :   return (PetscErrorCode)0;
      73             : }
      74             : 
      75             : PetscErrorCode
      76     2602355 : PetscOutputInterface::petscLinearOutput(KSP, PetscInt its, PetscReal norm, void * void_ptr)
      77             : {
      78             :   // Get the primary outputter object
      79     2602355 :   PetscOutput * primary_ptr = static_cast<PetscOutput *>(void_ptr);
      80             : 
      81             :   // loop over all interface objects
      82     9774005 :   for (const auto poi_ptr : primary_ptr->getMooseApp().getInterfaceObjects<PetscOutputInterface>())
      83             :   {
      84     7171650 :     auto ptr = poi_ptr->_petsc_output;
      85             : 
      86             :     // check time
      87     7171650 :     if (!ptr->inLinearTimeWindow())
      88        2608 :       continue;
      89             : 
      90             :     // Update the pseudo time
      91     7169042 :     ptr->_linear_time += ptr->_linear_dt;
      92             : 
      93             :     // Set the current norm and iteration number
      94     7169042 :     ptr->_norm = norm;
      95     7169042 :     ptr->_linear_iter = its;
      96             : 
      97             :     // Set the flag indicating that output is occurring on the non-linear residual
      98     7169042 :     ptr->_on_linear_residual = true;
      99             : 
     100             :     // Perform the output
     101     7169042 :     ptr->outputStep(EXEC_LINEAR);
     102             : 
     103             :     /**
     104             :      * This is one of three locations where we explicitly flush the output buffers during a
     105             :      * simulation:
     106             :      * PetscOutput::petscNonlinearOutput()
     107             :      * PetscOutput::petscLinearOutput()
     108             :      * OutputWarehouse::outputStep()
     109             :      *
     110             :      * All other Console output _should_ be using newlines to avoid covering buffer errors
     111             :      * and to avoid excessive I/O. This call is necessary. In the PETSc callback the
     112             :      * context bypasses the OutputWarehouse.
     113             :      */
     114     7169042 :     ptr->_app.getOutputWarehouse().flushConsoleBuffer();
     115             : 
     116             :     // Reset the linear output flag and the simulation time
     117     7169042 :     ptr->_on_linear_residual = false;
     118             :   }
     119             : 
     120             :   // Done
     121     2602355 :   return (PetscErrorCode)0;
     122             : }
     123             : 
     124             : InputParameters
     125      652769 : PetscOutput::validParams()
     126             : {
     127      652769 :   InputParameters params = Output::validParams();
     128             : 
     129             :   // Toggled for outputting nonlinear and linear residuals, only if we have PETSc
     130     1958307 :   params.addParam<bool>("output_linear",
     131     1305538 :                         false,
     132             :                         "Specifies whether output occurs on each PETSc linear residual evaluation");
     133     1958307 :   params.addParam<bool>(
     134             :       "output_nonlinear",
     135     1305538 :       false,
     136             :       "Specifies whether output occurs on each PETSc nonlinear residual evaluation");
     137      652769 :   params.addParamNamesToGroup("output_linear output_nonlinear", "Execution scheduling");
     138             : 
     139             :   // Pseudo time step divisors
     140     1958307 :   params.addParam<Real>(
     141             :       "nonlinear_residual_dt_divisor",
     142     1305538 :       1000,
     143             :       "Number of divisions applied to time step when outputting non-linear residuals");
     144     1958307 :   params.addParam<Real>(
     145             :       "linear_residual_dt_divisor",
     146     1305538 :       1000,
     147             :       "Number of divisions applied to time step when outputting linear residuals");
     148             : 
     149             :   // Start times for residual output
     150      652769 :   params.addParam<Real>(
     151             :       "linear_residual_start_time",
     152             :       "Specifies a start time to begin output on each linear residual evaluation");
     153      652769 :   params.addParam<Real>(
     154             :       "nonlinear_residual_start_time",
     155             :       "Specifies a start time to begin output on each nonlinear residual evaluation");
     156             : 
     157             :   // End time for residual output
     158             :   /* Note, No default is given here so that in Peacock giant numbers do not show up by default, the
     159             :    * defaults are set in the initialization list */
     160      652769 :   params.addParam<Real>("linear_residual_end_time",
     161             :                         "Specifies an end time to begin output on each linear residual evaluation");
     162      652769 :   params.addParam<Real>(
     163             :       "nonlinear_residual_end_time",
     164             :       "Specifies an end time to begin output on each nonlinear residual evaluation");
     165             : 
     166      652769 :   params.addParamNamesToGroup("linear_residual_start_time "
     167             :                               "nonlinear_residual_start_time linear_residual_end_time "
     168             :                               "nonlinear_residual_end_time  nonlinear_residual_dt_divisor "
     169             :                               "linear_residual_dt_divisor",
     170             :                               "PETSc linear/nonlinear output");
     171      652769 :   return params;
     172           0 : }
     173             : 
     174      167657 : PetscOutput::PetscOutput(const InputParameters & parameters)
     175             :   : Output(parameters),
     176             :     PetscOutputInterface(this),
     177      167649 :     _nonlinear_iter(0),
     178      167649 :     _linear_iter(0),
     179      167649 :     _on_linear_residual(false),
     180      167649 :     _on_nonlinear_residual(false),
     181      167649 :     _nonlinear_dt_divisor(getParam<Real>("nonlinear_residual_dt_divisor")),
     182      167649 :     _linear_dt_divisor(getParam<Real>("linear_residual_dt_divisor")),
     183      167649 :     _nonlinear_start_time(-std::numeric_limits<Real>::max()),
     184      167649 :     _linear_start_time(-std::numeric_limits<Real>::max()),
     185      167649 :     _nonlinear_end_time(std::numeric_limits<Real>::max()),
     186      335306 :     _linear_end_time(std::numeric_limits<Real>::max())
     187             : {
     188             :   // Output toggle support
     189      167649 :   if (getParam<bool>("output_linear"))
     190          13 :     _execute_on.setAdditionalValue("linear");
     191      167649 :   if (getParam<bool>("output_nonlinear"))
     192           0 :     _execute_on.setAdditionalValue("nonlinear");
     193             : 
     194             :   // Nonlinear residual start-time supplied by user
     195      167649 :   if (isParamValid("nonlinear_residual_start_time"))
     196             :   {
     197          20 :     _nonlinear_start_time = getParam<Real>("nonlinear_residual_start_time");
     198          20 :     _execute_on.setAdditionalValue("nonlinear");
     199             :   }
     200             : 
     201             :   // Nonlinear residual end-time supplied by user
     202      167649 :   if (isParamValid("nonlinear_residual_end_time"))
     203          10 :     _nonlinear_end_time = getParam<Real>("nonlinear_residual_end_time");
     204             : 
     205             :   // Linear residual start-time supplied by user
     206      167649 :   if (isParamValid("linear_residual_start_time"))
     207             :   {
     208          20 :     _linear_start_time = getParam<Real>("linear_residual_start_time");
     209          20 :     _execute_on.setAdditionalValue("linear");
     210             :   }
     211             : 
     212             :   // Linear residual end-time supplied by user
     213      167649 :   if (isParamValid("linear_residual_end_time"))
     214          10 :     _linear_end_time = getParam<Real>("linear_residual_end_time");
     215      167649 : }
     216             : 
     217             : void
     218      993134 : PetscOutput::solveSetup()
     219             : {
     220             :   // Update the pseudo times
     221      993134 :   _nonlinear_time = _time_old; // non-linear time starts with the previous time step
     222      993134 :   if (_dt != 0)
     223             :     // set the pseudo non-linear timestep as fraction
     224             :     // of real timestep for transient executioners
     225      887214 :     _nonlinear_dt = _dt / _nonlinear_dt_divisor;
     226             :   else
     227             :     // set the pseudo non-linear timestep for steady
     228             :     // executioners (here _dt==0)
     229      105920 :     _nonlinear_dt = 1. / _nonlinear_dt_divisor;
     230             : 
     231      993134 :   _linear_dt = _nonlinear_dt / _linear_dt_divisor; // set the pseudo linear timestep
     232             : 
     233             :   // only the first PetscOutput object registers a DM monitor for linear and nonlinear
     234             :   // all other PetscOutput objects are dispatched from that one monitor (per app).
     235      993134 :   if (_app.getInterfaceObjects<PetscOutputInterface>()[0] != this)
     236      629038 :     return;
     237             : 
     238      364096 :   ActionWarehouse & awh = _app.actionWarehouse();
     239      364096 :   const auto actions = awh.getActions<CommonOutputAction>();
     240             :   mooseAssert(actions.size() <= 1, "Should not be more than one CommonOutputAction");
     241      364096 :   const Action * common = actions.empty() ? nullptr : *actions.begin();
     242             : 
     243             :   // Extract the non-linear and linear solvers from PETSc
     244      364096 :   NonlinearSystemBase & nl = _problem_ptr->currentNonlinearSystem();
     245      364096 :   SNES snes = nl.getSNES();
     246             :   KSP ksp;
     247      364096 :   LibmeshPetscCallA(_communicator.get(), SNESGetKSP(snes, &ksp));
     248             : 
     249             :   // Set the PETSc monitor functions (register the nonlinear callback so that linear outputs
     250             :   // get an updated nonlinear iteration number)
     251             :   // Not every Output should register its own DM monitor! Just register one each of nonlinear
     252             :   // and linear and dispatch all Outputs from there!
     253      364096 :   if (common && common->getParam<bool>("print_nonlinear_residuals"))
     254      359106 :     LibmeshPetscCallA(_communicator.get(),
     255             :                       SNESMonitorSet(snes, petscNonlinearOutput, this, LIBMESH_PETSC_NULLPTR));
     256      364096 :   if (common && common->getParam<bool>("print_linear_residuals"))
     257      357600 :     LibmeshPetscCallA(_communicator.get(),
     258             :                       KSPMonitorSet(ksp, petscLinearOutput, this, LIBMESH_PETSC_NULLPTR));
     259      364096 : }
     260             : 
     261             : Real
     262     1230779 : PetscOutput::time()
     263             : {
     264     1230779 :   if (_on_nonlinear_residual)
     265       23087 :     return _nonlinear_time;
     266     1207692 :   else if (_on_linear_residual)
     267         578 :     return _linear_time;
     268             :   else
     269     1207114 :     return Output::time();
     270             : }
     271             : 
     272             : Real
     273     1230200 : PetscOutput::getOutputTime()
     274             : {
     275     1230200 :   return time();
     276             : }

Generated by: LCOV version 1.14