LCOV - code coverage report
Current view: top level - src/postprocessors - DiscreteVariableResidualNorm.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 65 67 97.0 %
Date: 2026-05-29 20:35:17 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             : #include "DiscreteVariableResidualNorm.h"
      11             : #include "MooseVariableFieldBase.h"
      12             : #include "NonlinearSystemBase.h"
      13             : 
      14             : #include "libmesh/dof_map.h"
      15             : 
      16             : registerMooseObject("MooseApp", DiscreteVariableResidualNorm);
      17             : 
      18             : InputParameters
      19        3361 : DiscreteVariableResidualNorm::validParams()
      20             : {
      21        3361 :   InputParameters params = ElementPostprocessor::validParams();
      22             : 
      23       13444 :   params.addRequiredParam<VariableName>("variable",
      24             :                                         "The name of the variable to compute the residual for");
      25       13444 :   MooseEnum norm_type("l_1=0 l_2=1 l_inf=2");
      26       13444 :   norm_type.addDocumentation("l_1", "l-1 norm");
      27       13444 :   norm_type.addDocumentation("l_2", "l-2 norm");
      28       13444 :   norm_type.addDocumentation("l_inf", "l-infinity norm");
      29       13444 :   params.addRequiredParam<MooseEnum>("norm_type", norm_type, "Type of discrete norm to compute");
      30       10083 :   params.addParam<bool>(
      31             :       "correct_mesh_bias",
      32        6722 :       false,
      33             :       "If set to true, correct the mesh size bias associated with the selected norm. For l-1, "
      34             :       "divide by N, the number of block-restricted DoFs for the variable. For l-2, divide by "
      35             :       "sqrt(N). For l-infinity, no correction needs to be made.");
      36       10083 :   params.addParam<bool>("include_scaling_factor",
      37        6722 :                         false,
      38             :                         "If set to true, include the residual scaling factor in the norm; "
      39             :                         "otherwise, divide by the scaling factor");
      40             : 
      41        3361 :   params.addClassDescription("Computes a discrete norm for a block-restricted variable residual.");
      42             : 
      43        6722 :   return params;
      44        3361 : }
      45             : 
      46         156 : DiscreteVariableResidualNorm::DiscreteVariableResidualNorm(const InputParameters & parameters)
      47             :   : ElementPostprocessor(parameters),
      48         468 :     _var(_fe_problem.getVariable(_tid,
      49         156 :                                  getParam<VariableName>("variable"),
      50             :                                  Moose::VarKindType::VAR_SOLVER,
      51             :                                  Moose::VarFieldType::VAR_FIELD_STANDARD)),
      52         312 :     _norm_type(getParam<MooseEnum>("norm_type").getEnum<NormType>()),
      53         312 :     _correct_mesh_bias(getParam<bool>("correct_mesh_bias")),
      54         312 :     _include_scaling_factor(getParam<bool>("include_scaling_factor")),
      55         312 :     _nl_residual_vector(_fe_problem.getNonlinearSystemBase(_sys.number()).RHS())
      56             : {
      57         156 : }
      58             : 
      59             : void
      60         144 : DiscreteVariableResidualNorm::initialize()
      61             : {
      62         144 :   _norm = 0;
      63         144 :   _local_dof_indices.clear();
      64         144 :   _nonlocal_dof_indices_map.clear();
      65         144 : }
      66             : 
      67             : void
      68        1120 : DiscreteVariableResidualNorm::execute()
      69             : {
      70        5000 :   for (const auto dof_index : _var.dofIndices())
      71             :   {
      72             :     // Dof indices may not be owned by the same processor as the current element
      73        3880 :     if (_var.dofMap().local_index(dof_index))
      74        3732 :       _local_dof_indices.insert(dof_index);
      75             :     else
      76             :     {
      77             :       // if a Dof is non-local add it to a map, to be communicated to the owner in finalize()
      78         148 :       const auto dof_owner = _var.dofMap().dof_owner(dof_index);
      79         148 :       _nonlocal_dof_indices_map[dof_owner].push_back(dof_index);
      80             :     }
      81             :   }
      82        1120 : }
      83             : 
      84             : void
      85          12 : DiscreteVariableResidualNorm::threadJoin(const UserObject & y)
      86             : {
      87          12 :   const auto & pps = static_cast<const DiscreteVariableResidualNorm &>(y);
      88          12 :   _local_dof_indices.insert(pps._local_dof_indices.begin(), pps._local_dof_indices.end());
      89          12 : }
      90             : 
      91             : void
      92         132 : DiscreteVariableResidualNorm::finalize()
      93             : {
      94             :   // communicate the non-local Dofs to their processors
      95          23 :   auto receive_functor = [&](processor_id_type /*pid*/, const std::vector<dof_id_type> & indices)
      96          23 :   { _local_dof_indices.insert(indices.begin(), indices.end()); };
      97         132 :   Parallel::push_parallel_vector_data(_communicator, _nonlocal_dof_indices_map, receive_functor);
      98             : 
      99             :   // compute the total number of Dofs for the variable on the subdomain
     100         132 :   auto n_dofs = _local_dof_indices.size();
     101         132 :   gatherSum(n_dofs);
     102             : 
     103         132 :   Real bias = 1.0;
     104         132 :   switch (_norm_type)
     105             :   {
     106          55 :     case NormType::l_1:
     107          55 :       _norm = _nl_residual_vector.subset_l1_norm(_local_dof_indices);
     108          55 :       bias = n_dofs;
     109          55 :       break;
     110          33 :     case NormType::l_2:
     111          33 :       _norm = _nl_residual_vector.subset_l2_norm(_local_dof_indices);
     112          33 :       bias = sqrt(n_dofs);
     113          33 :       break;
     114          44 :     case NormType::l_inf:
     115          44 :       _norm = _nl_residual_vector.subset_linfty_norm(_local_dof_indices);
     116          44 :       break;
     117           0 :     default:
     118           0 :       mooseError("Invalid norm type");
     119             :   }
     120             : 
     121         132 :   if (_correct_mesh_bias)
     122          33 :     _norm /= bias;
     123             : 
     124         132 :   if (!_include_scaling_factor)
     125         121 :     _norm /= _var.scalingFactor();
     126         132 : }
     127             : 
     128             : PostprocessorValue
     129         132 : DiscreteVariableResidualNorm::getValue() const
     130             : {
     131         132 :   return _norm;
     132             : }

Generated by: LCOV version 1.14