LCOV - code coverage report
Current view: top level - src/outputs - TopResidualDebugOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 81 81 100.0 %
Date: 2026-05-29 20:35:17 Functions: 4 4 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 "TopResidualDebugOutput.h"
      12             : #include "FEProblem.h"
      13             : #include "MooseApp.h"
      14             : #include "Material.h"
      15             : #include "Console.h"
      16             : #include "Action.h"
      17             : #include "MooseMesh.h"
      18             : #include "NonlinearSystemBase.h"
      19             : 
      20             : #include "libmesh/transient_system.h"
      21             : #include "libmesh/fe_type.h"
      22             : 
      23             : registerMooseObject("MooseApp", TopResidualDebugOutput);
      24             : 
      25             : InputParameters
      26        3129 : TopResidualDebugOutput::validParams()
      27             : {
      28        3129 :   InputParameters params = PetscOutput::validParams();
      29        6258 :   params.addClassDescription("Debug output object for displaying the top contributing residuals.");
      30             : 
      31             :   // Create parameters for allowing debug outputter to be defined within the [Outputs] block
      32        6258 :   params.addParam<unsigned int>(
      33        6258 :       "num_residuals", 0, "The number of top residuals to print out (0 = no output)");
      34             : 
      35             :   // By default operate on both nonlinear and linear residuals
      36       15645 :   params.set<ExecFlagEnum>("execute_on", true) = {EXEC_LINEAR, EXEC_NONLINEAR, EXEC_TIMESTEP_END};
      37        9387 :   params.addParam<NonlinearSystemName>(
      38             :       "nl_sys", "nl0", "The nonlinear system that we should output information for.");
      39        3129 :   return params;
      40        3129 : }
      41             : 
      42          34 : TopResidualDebugOutput::TopResidualDebugOutput(const InputParameters & parameters)
      43             :   : PetscOutput(parameters),
      44          34 :     _num_residuals(getParam<unsigned int>("num_residuals")),
      45          34 :     _nl(_problem_ptr->getNonlinearSystemBase(
      46          34 :         _problem_ptr->nlSysNum(getParam<NonlinearSystemName>("nl_sys")))),
      47          68 :     _sys(_nl.system())
      48             : {
      49          34 : }
      50             : 
      51             : void
      52         225 : TopResidualDebugOutput::output()
      53             : {
      54             :   // Display the top residuals
      55         225 :   if (_num_residuals > 0)
      56         225 :     printTopResiduals(_nl.RHS(), _num_residuals);
      57         225 : }
      58             : 
      59             : void
      60         225 : TopResidualDebugOutput::printTopResiduals(const NumericVector<Number> & residual, unsigned int n)
      61             : {
      62         225 :   MooseMesh & mesh = _problem_ptr->mesh();
      63             : 
      64         225 :   std::vector<TopResidualDebugOutputTopResidualData> vec;
      65         225 :   vec.resize(residual.local_size());
      66             : 
      67         225 :   unsigned int j = 0;
      68             : 
      69             :   // Loop over all nodal variables
      70       11392 :   for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
      71             :   {
      72       11167 :     dof_id_type nd = node->id();
      73             : 
      74       22694 :     for (unsigned int var = 0; var < node->n_vars(_sys.number()); ++var)
      75             :       // check that variable exists on node
      76       11527 :       if (node->n_dofs(_sys.number(), var) > 0)
      77             :       {
      78        8747 :         const auto & subdomain_ids = mesh.getNodeBlockIds(*node);
      79        8747 :         dof_id_type dof_idx = node->dof_number(_sys.number(), var, 0);
      80       17494 :         vec[j] = TopResidualDebugOutputTopResidualData(
      81       17494 :             var, subdomain_ids, nd, *node, residual(dof_idx), false, true);
      82        8747 :         j++;
      83             :       }
      84         225 :   }
      85             : 
      86             :   // Loop over all elemental variables
      87        9117 :   for (const auto & elem : as_range(mesh.activeLocalElementsBegin(), mesh.activeLocalElementsEnd()))
      88             :   {
      89        8892 :     dof_id_type elem_id = elem->id();
      90        8892 :     const SubdomainID subdomain_id = elem->subdomain_id();
      91             : 
      92       17944 :     for (unsigned int var = 0; var < elem->n_vars(_sys.number()); ++var)
      93             :       // check that variable exists on element
      94        9052 :       if (elem->n_dofs(_sys.number(), var) > 0)
      95             :       {
      96          80 :         dof_id_type dof_idx = elem->dof_number(_sys.number(), var, 0);
      97         240 :         vec[j] = TopResidualDebugOutputTopResidualData(
      98         160 :             var, {subdomain_id}, elem_id, elem->vertex_average(), residual(dof_idx), false, false);
      99          80 :         j++;
     100             :       }
     101         225 :   }
     102             : 
     103             :   // Loop over all scalar variables
     104         225 :   std::vector<unsigned int> var_nums;
     105         225 :   _sys.get_all_variable_numbers(var_nums);
     106         225 :   const DofMap & dof_map = _sys.get_dof_map();
     107         490 :   for (const auto & var_num : var_nums)
     108         265 :     if (_sys.variable_type(var_num).family == SCALAR)
     109             :     {
     110          40 :       std::vector<dof_id_type> dof_indices;
     111          40 :       dof_map.SCALAR_dof_indices(dof_indices, var_num);
     112             : 
     113          80 :       for (const auto & dof : dof_indices)
     114          40 :         if (dof >= dof_map.first_dof() && dof < dof_map.end_dof())
     115             :         {
     116          40 :           vec[j] =
     117          80 :               TopResidualDebugOutputTopResidualData(var_num, {}, 0, Point(), residual(dof), true);
     118          40 :           j++;
     119             :         }
     120          40 :     }
     121             : 
     122             :   // Sort vec by residuals
     123         225 :   std::sort(vec.begin(), vec.end(), sortTopResidualData);
     124             : 
     125             :   // Display the residuals
     126         225 :   Moose::err << "[DBG][" << processor_id() << "] Max " << n << " residuals";
     127         225 :   if (j < n)
     128             :   {
     129          42 :     n = j;
     130          42 :     Moose::err << " (Only " << n << " available)";
     131             :   }
     132         225 :   Moose::err << std::endl;
     133             : 
     134        1026 :   for (unsigned int i = 0; i < n; ++i)
     135             :   {
     136         801 :     Moose::err << "[DBG][" << processor_id() << "] " << std::setprecision(15) << vec[i]._residual
     137         801 :                << " '" << _sys.variable_name(vec[i]._var).c_str() << "' ";
     138         801 :     if (vec[i]._is_scalar)
     139          40 :       Moose::err << "(SCALAR)\n";
     140             :     else
     141             :     {
     142             :       // Create subdomain list string for node
     143         761 :       const unsigned int n_subdomains = vec[i]._subdomain_ids.size();
     144         761 :       std::vector<SubdomainName> subdomain_names(n_subdomains);
     145         761 :       unsigned int i_block = 0;
     146        1522 :       for (const auto & subdomain_id : vec[i]._subdomain_ids)
     147             :       {
     148         761 :         subdomain_names[i_block] = mesh.getSubdomainName(subdomain_id);
     149         761 :         i_block++;
     150             :       }
     151        3044 :       const std::string subdomains_string = Moose::stringify(subdomain_names, ", ", "'", true);
     152             : 
     153         761 :       const std::string elem_or_node_string = vec[i]._is_nodal ? "node" : "element";
     154             : 
     155         761 :       Moose::err << "in subdomain(s) " << subdomains_string << " at " << elem_or_node_string << " "
     156         761 :                  << vec[i]._id << ": " << vec[i]._point << '\n';
     157         761 :     }
     158             :   }
     159             : 
     160         225 :   Moose::err << std::flush;
     161         225 : }

Generated by: LCOV version 1.14