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

Generated by: LCOV version 1.14