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

Generated by: LCOV version 1.14