LCOV - code coverage report
Current view: top level - src/outputs - TopResidualDebugOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 81 81 100.0 %
Date: 2025-07-17 01:28:37 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       14361 : TopResidualDebugOutput::validParams()
      27             : {
      28       14361 :   InputParameters params = PetscOutput::validParams();
      29       14361 :   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       43083 :   params.addParam<unsigned int>(
      33       28722 :       "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       57444 :   params.set<ExecFlagEnum>("execute_on", true) = {EXEC_LINEAR, EXEC_NONLINEAR, EXEC_TIMESTEP_END};
      37       14361 :   params.addParam<NonlinearSystemName>(
      38             :       "nl_sys", "nl0", "The nonlinear system that we should output information for.");
      39       14361 :   return params;
      40       14361 : }
      41             : 
      42          48 : TopResidualDebugOutput::TopResidualDebugOutput(const InputParameters & parameters)
      43             :   : PetscOutput(parameters),
      44          48 :     _num_residuals(getParam<unsigned int>("num_residuals")),
      45          48 :     _nl(_problem_ptr->getNonlinearSystemBase(
      46          48 :         _problem_ptr->nlSysNum(getParam<NonlinearSystemName>("nl_sys")))),
      47          96 :     _sys(_nl.system())
      48             : {
      49          48 : }
      50             : 
      51             : void
      52         103 : TopResidualDebugOutput::output()
      53             : {
      54             :   // Display the top residuals
      55         103 :   if (_num_residuals > 0)
      56         103 :     printTopResiduals(_nl.RHS(), _num_residuals);
      57         103 : }
      58             : 
      59             : void
      60         103 : TopResidualDebugOutput::printTopResiduals(const NumericVector<Number> & residual, unsigned int n)
      61             : {
      62         103 :   MooseMesh & mesh = _problem_ptr->mesh();
      63             : 
      64         103 :   std::vector<TopResidualDebugOutputTopResidualData> vec;
      65         103 :   vec.resize(residual.local_size());
      66             : 
      67         103 :   unsigned int j = 0;
      68             : 
      69             :   // Loop over all nodal variables
      70       12717 :   for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
      71             :   {
      72        6307 :     dof_id_type nd = node->id();
      73             : 
      74       12866 :     for (unsigned int var = 0; var < node->n_vars(_sys.number()); ++var)
      75             :       // check that variable exists on node
      76        6559 :       if (node->n_dofs(_sys.number(), var) > 0)
      77             :       {
      78        4613 :         const auto & subdomain_ids = mesh.getNodeBlockIds(*node);
      79        4613 :         dof_id_type dof_idx = node->dof_number(_sys.number(), var, 0);
      80        9226 :         vec[j] = TopResidualDebugOutputTopResidualData(
      81        9226 :             var, subdomain_ids, nd, *node, residual(dof_idx), false, true);
      82        4613 :         j++;
      83             :       }
      84         103 :   }
      85             : 
      86             :   // Loop over all elemental variables
      87       10239 :   for (const auto & elem : as_range(mesh.activeLocalElementsBegin(), mesh.activeLocalElementsEnd()))
      88             :   {
      89        5068 :     dof_id_type elem_id = elem->id();
      90        5068 :     const SubdomainID subdomain_id = elem->subdomain_id();
      91             : 
      92       10248 :     for (unsigned int var = 0; var < elem->n_vars(_sys.number()); ++var)
      93             :       // check that variable exists on element
      94        5180 :       if (elem->n_dofs(_sys.number(), var) > 0)
      95             :       {
      96          56 :         dof_id_type dof_idx = elem->dof_number(_sys.number(), var, 0);
      97         112 :         vec[j] = TopResidualDebugOutputTopResidualData(
      98         112 :             var, {subdomain_id}, elem_id, elem->vertex_average(), residual(dof_idx), false, false);
      99          56 :         j++;
     100             :       }
     101         103 :   }
     102             : 
     103             :   // Loop over all scalar variables
     104         103 :   std::vector<unsigned int> var_nums;
     105         103 :   _sys.get_all_variable_numbers(var_nums);
     106         103 :   const DofMap & dof_map = _sys.get_dof_map();
     107         234 :   for (const auto & var_num : var_nums)
     108         131 :     if (_sys.variable_type(var_num).family == SCALAR)
     109             :     {
     110          28 :       std::vector<dof_id_type> dof_indices;
     111          28 :       dof_map.SCALAR_dof_indices(dof_indices, var_num);
     112             : 
     113          56 :       for (const auto & dof : dof_indices)
     114          28 :         if (dof >= dof_map.first_dof() && dof < dof_map.end_dof())
     115             :         {
     116          28 :           vec[j] =
     117          56 :               TopResidualDebugOutputTopResidualData(var_num, {}, 0, Point(), residual(dof), true);
     118          28 :           j++;
     119             :         }
     120          28 :     }
     121             : 
     122             :   // Sort vec by residuals
     123         103 :   std::sort(vec.begin(), vec.end(), sortTopResidualData);
     124             : 
     125             :   // Display the residuals
     126         103 :   Moose::err << "[DBG][" << processor_id() << "] Max " << n << " residuals";
     127         103 :   if (j < n)
     128             :   {
     129          12 :     n = j;
     130          12 :     Moose::err << " (Only " << n << " available)";
     131             :   }
     132         103 :   Moose::err << std::endl;
     133             : 
     134         468 :   for (unsigned int i = 0; i < n; ++i)
     135             :   {
     136         365 :     Moose::err << "[DBG][" << processor_id() << "] " << std::setprecision(15) << vec[i]._residual
     137         365 :                << " '" << _sys.variable_name(vec[i]._var).c_str() << "' ";
     138         365 :     if (vec[i]._is_scalar)
     139          21 :       Moose::err << "(SCALAR)\n";
     140             :     else
     141             :     {
     142             :       // Create subdomain list string for node
     143         344 :       const unsigned int n_subdomains = vec[i]._subdomain_ids.size();
     144         344 :       std::vector<SubdomainName> subdomain_names(n_subdomains);
     145         344 :       unsigned int i_block = 0;
     146         688 :       for (const auto & subdomain_id : vec[i]._subdomain_ids)
     147             :       {
     148         344 :         subdomain_names[i_block] = mesh.getSubdomainName(subdomain_id);
     149         344 :         i_block++;
     150             :       }
     151         344 :       const std::string subdomains_string = Moose::stringify(subdomain_names, ", ", "'", true);
     152             : 
     153         344 :       const std::string elem_or_node_string = vec[i]._is_nodal ? "node" : "element";
     154             : 
     155         344 :       Moose::err << "in subdomain(s) " << subdomains_string << " at " << elem_or_node_string << " "
     156         344 :                  << vec[i]._id << ": " << vec[i]._point << '\n';
     157         344 :     }
     158             :   }
     159             : 
     160         103 :   Moose::err << std::flush;
     161         103 : }

Generated by: LCOV version 1.14