LCOV - code coverage report
Current view: top level - src/outputs - PetscOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 909fe5 Lines: 101 103 98.1 %
Date: 2025-08-29 20:01:24 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      169654 : PetscOutputInterface::PetscOutputInterface(PetscOutput * obj) : _petsc_output(obj)
      20             : {
      21             :   // register petsc output interface
      22      169654 :   obj->getMooseApp().registerInterfaceObject(*this);
      23      169654 : }
      24             : 
      25             : PetscErrorCode
      26      816636 : PetscOutputInterface::petscNonlinearOutput(SNES, PetscInt its, PetscReal norm, void * void_ptr)
      27             : {
      28             :   // Get the primary outputter object
      29      816636 :   PetscOutput * primary_ptr = static_cast<PetscOutput *>(void_ptr);
      30             : 
      31             :   // loop over all interface objects
      32     3065357 :   for (const auto poi_ptr : primary_ptr->getMooseApp().getInterfaceObjects<PetscOutputInterface>())
      33             :   {
      34     2248721 :     auto ptr = poi_ptr->_petsc_output;
      35             : 
      36             :     // check time
      37     2248721 :     if (!ptr->inNonlinearTimeWindow())
      38         978 :       continue;
      39             : 
      40             :     // Update the pseudo times
      41     2247743 :     ptr->_nonlinear_time += ptr->_nonlinear_dt;
      42     2247743 :     ptr->_linear_time = ptr->_nonlinear_time;
      43             : 
      44             :     // Set the current norm and iteration number
      45     2247743 :     ptr->_norm = norm;
      46     2247743 :     ptr->_nonlinear_iter = its;
      47             : 
      48             :     // Set the flag indicating that output is occurring on the non-linear residual
      49     2247743 :     ptr->_on_nonlinear_residual = true;
      50             : 
      51             :     // Perform the output
      52     2247743 :     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     2247743 :     ptr->_app.getOutputWarehouse().flushConsoleBuffer();
      66             : 
      67             :     // Reset the non-linear output flag and the simulation time
      68     2247743 :     ptr->_on_nonlinear_residual = false;
      69             :   }
      70             : 
      71             :   // Done
      72      816636 :   return (PetscErrorCode)0;
      73             : }
      74             : 
      75             : PetscErrorCode
      76     2616628 : PetscOutputInterface::petscLinearOutput(KSP, PetscInt its, PetscReal norm, void * void_ptr)
      77             : {
      78             :   // Get the primary outputter object
      79     2616628 :   PetscOutput * primary_ptr = static_cast<PetscOutput *>(void_ptr);
      80             : 
      81             :   // loop over all interface objects
      82     9829911 :   for (const auto poi_ptr : primary_ptr->getMooseApp().getInterfaceObjects<PetscOutputInterface>())
      83             :   {
      84     7213283 :     auto ptr = poi_ptr->_petsc_output;
      85             : 
      86             :     // check time
      87     7213283 :     if (!ptr->inLinearTimeWindow())
      88        2608 :       continue;
      89             : 
      90             :     // Update the pseudo time
      91     7210675 :     ptr->_linear_time += ptr->_linear_dt;
      92             : 
      93             :     // Set the current norm and iteration number
      94     7210675 :     ptr->_norm = norm;
      95     7210675 :     ptr->_linear_iter = its;
      96             : 
      97             :     // Set the flag indicating that output is occurring on the non-linear residual
      98     7210675 :     ptr->_on_linear_residual = true;
      99             : 
     100             :     // Perform the output
     101     7210675 :     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     7210675 :     ptr->_app.getOutputWarehouse().flushConsoleBuffer();
     115             : 
     116             :     // Reset the linear output flag and the simulation time
     117     7210675 :     ptr->_on_linear_residual = false;
     118             :   }
     119             : 
     120             :   // Done
     121     2616628 :   return (PetscErrorCode)0;
     122             : }
     123             : 
     124             : InputParameters
     125      656965 : PetscOutput::validParams()
     126             : {
     127      656965 :   InputParameters params = Output::validParams();
     128             : 
     129             :   // Toggled for outputting nonlinear and linear residuals, only if we have PETSc
     130     1970895 :   params.addParam<bool>("output_linear",
     131     1313930 :                         false,
     132             :                         "Specifies whether output occurs on each PETSc linear residual evaluation");
     133     1970895 :   params.addParam<bool>(
     134             :       "output_nonlinear",
     135     1313930 :       false,
     136             :       "Specifies whether output occurs on each PETSc nonlinear residual evaluation");
     137     2627860 :   params.addParamNamesToGroup("output_linear output_nonlinear", "Execution scheduling");
     138             : 
     139             :   // Pseudo time step divisors
     140     1970895 :   params.addParam<Real>(
     141             :       "nonlinear_residual_dt_divisor",
     142     1313930 :       1000,
     143             :       "Number of divisions applied to time step when outputting non-linear residuals");
     144     1970895 :   params.addParam<Real>(
     145             :       "linear_residual_dt_divisor",
     146     1313930 :       1000,
     147             :       "Number of divisions applied to time step when outputting linear residuals");
     148             : 
     149             :   // Start times for residual output
     150     2627860 :   params.addParam<Real>(
     151             :       "linear_residual_start_time",
     152             :       "Specifies a start time to begin output on each linear residual evaluation");
     153     2627860 :   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     2627860 :   params.addParam<Real>("linear_residual_end_time",
     161             :                         "Specifies an end time to begin output on each linear residual evaluation");
     162     2627860 :   params.addParam<Real>(
     163             :       "nonlinear_residual_end_time",
     164             :       "Specifies an end time to begin output on each nonlinear residual evaluation");
     165             : 
     166     1970895 :   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      656965 :   return params;
     172           0 : }
     173             : 
     174      169662 : PetscOutput::PetscOutput(const InputParameters & parameters)
     175             :   : Output(parameters),
     176             :     PetscOutputInterface(this),
     177      169654 :     _nonlinear_iter(0),
     178      169654 :     _linear_iter(0),
     179      169654 :     _on_linear_residual(false),
     180      169654 :     _on_nonlinear_residual(false),
     181      169654 :     _nonlinear_dt_divisor(getParam<Real>("nonlinear_residual_dt_divisor")),
     182      339308 :     _linear_dt_divisor(getParam<Real>("linear_residual_dt_divisor")),
     183      169654 :     _nonlinear_start_time(-std::numeric_limits<Real>::max()),
     184      169654 :     _linear_start_time(-std::numeric_limits<Real>::max()),
     185      169654 :     _nonlinear_end_time(std::numeric_limits<Real>::max()),
     186      339316 :     _linear_end_time(std::numeric_limits<Real>::max())
     187             : {
     188             :   // Output toggle support
     189      508962 :   if (getParam<bool>("output_linear"))
     190          39 :     _execute_on.setAdditionalValue("linear");
     191      508962 :   if (getParam<bool>("output_nonlinear"))
     192           0 :     _execute_on.setAdditionalValue("nonlinear");
     193             : 
     194             :   // Nonlinear residual start-time supplied by user
     195      508962 :   if (isParamValid("nonlinear_residual_start_time"))
     196             :   {
     197          40 :     _nonlinear_start_time = getParam<Real>("nonlinear_residual_start_time");
     198          60 :     _execute_on.setAdditionalValue("nonlinear");
     199             :   }
     200             : 
     201             :   // Nonlinear residual end-time supplied by user
     202      508962 :   if (isParamValid("nonlinear_residual_end_time"))
     203          30 :     _nonlinear_end_time = getParam<Real>("nonlinear_residual_end_time");
     204             : 
     205             :   // Linear residual start-time supplied by user
     206      508962 :   if (isParamValid("linear_residual_start_time"))
     207             :   {
     208          40 :     _linear_start_time = getParam<Real>("linear_residual_start_time");
     209          60 :     _execute_on.setAdditionalValue("linear");
     210             :   }
     211             : 
     212             :   // Linear residual end-time supplied by user
     213      508962 :   if (isParamValid("linear_residual_end_time"))
     214          30 :     _linear_end_time = getParam<Real>("linear_residual_end_time");
     215      169654 : }
     216             : 
     217             : void
     218      997700 : PetscOutput::solveSetup()
     219             : {
     220             :   // Update the pseudo times
     221      997700 :   _nonlinear_time = _time_old; // non-linear time starts with the previous time step
     222      997700 :   if (_dt != 0)
     223             :     // set the pseudo non-linear timestep as fraction
     224             :     // of real timestep for transient executioners
     225      890471 :     _nonlinear_dt = _dt / _nonlinear_dt_divisor;
     226             :   else
     227             :     // set the pseudo non-linear timestep for steady
     228             :     // executioners (here _dt==0)
     229      107229 :     _nonlinear_dt = 1. / _nonlinear_dt_divisor;
     230             : 
     231      997700 :   _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      997700 :   if (_app.getInterfaceObjects<PetscOutputInterface>()[0] != this)
     236      631899 :     return;
     237             : 
     238      365801 :   ActionWarehouse & awh = _app.actionWarehouse();
     239      365801 :   const auto actions = awh.getActions<CommonOutputAction>();
     240             :   mooseAssert(actions.size() <= 1, "Should not be more than one CommonOutputAction");
     241      365801 :   const Action * common = actions.empty() ? nullptr : *actions.begin();
     242             : 
     243             :   // Extract the non-linear and linear solvers from PETSc
     244      365801 :   NonlinearSystemBase & nl = _problem_ptr->currentNonlinearSystem();
     245      365801 :   SNES snes = nl.getSNES();
     246             :   KSP ksp;
     247      365801 :   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     1097403 :   if (common && common->getParam<bool>("print_nonlinear_residuals"))
     254      360811 :     LibmeshPetscCallA(_communicator.get(),
     255             :                       SNESMonitorSet(snes, petscNonlinearOutput, this, LIBMESH_PETSC_NULLPTR));
     256     1097403 :   if (common && common->getParam<bool>("print_linear_residuals"))
     257      359305 :     LibmeshPetscCallA(_communicator.get(),
     258             :                       KSPMonitorSet(ksp, petscLinearOutput, this, LIBMESH_PETSC_NULLPTR));
     259      365801 : }
     260             : 
     261             : Real
     262     1239405 : PetscOutput::time()
     263             : {
     264     1239405 :   if (_on_nonlinear_residual)
     265       23327 :     return _nonlinear_time;
     266     1216078 :   else if (_on_linear_residual)
     267         578 :     return _linear_time;
     268             :   else
     269     1215500 :     return Output::time();
     270             : }
     271             : 
     272             : Real
     273     1238533 : PetscOutput::getOutputTime()
     274             : {
     275     1238533 :   return time();
     276             : }

Generated by: LCOV version 1.14