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 : }