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 14562 : DiscreteVariableResidualNorm::validParams() 20 : { 21 14562 : InputParameters params = ElementPostprocessor::validParams(); 22 : 23 14562 : params.addRequiredParam<VariableName>("variable", 24 : "The name of the variable to compute the residual for"); 25 14562 : MooseEnum norm_type("l_1=0 l_2=1 l_inf=2"); 26 14562 : norm_type.addDocumentation("l_1", "l-1 norm"); 27 14562 : norm_type.addDocumentation("l_2", "l-2 norm"); 28 14562 : norm_type.addDocumentation("l_inf", "l-infinity norm"); 29 14562 : params.addRequiredParam<MooseEnum>("norm_type", norm_type, "Type of discrete norm to compute"); 30 43686 : params.addParam<bool>( 31 : "correct_mesh_bias", 32 29124 : 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 : 37 14562 : params.addClassDescription("Computes a discrete norm for a block-restricted variable residual."); 38 : 39 29124 : return params; 40 14562 : } 41 : 42 154 : DiscreteVariableResidualNorm::DiscreteVariableResidualNorm(const InputParameters & parameters) 43 : : ElementPostprocessor(parameters), 44 462 : _var(_fe_problem.getVariable(_tid, 45 154 : getParam<VariableName>("variable"), 46 : Moose::VarKindType::VAR_SOLVER, 47 : Moose::VarFieldType::VAR_FIELD_STANDARD)), 48 154 : _norm_type(getParam<MooseEnum>("norm_type").getEnum<NormType>()), 49 154 : _correct_mesh_bias(getParam<bool>("correct_mesh_bias")), 50 308 : _nl_residual_vector(_fe_problem.getNonlinearSystemBase(_sys.number()).RHS()) 51 : { 52 154 : } 53 : 54 : void 55 143 : DiscreteVariableResidualNorm::initialize() 56 : { 57 143 : _norm = 0; 58 143 : _local_dof_indices.clear(); 59 143 : _nonlocal_dof_indices_map.clear(); 60 143 : } 61 : 62 : void 63 1170 : DiscreteVariableResidualNorm::execute() 64 : { 65 5175 : for (const auto dof_index : _var.dofIndices()) 66 : { 67 : // Dof indices may not be owned by the same processor as the current element 68 4005 : if (_var.dofMap().local_index(dof_index)) 69 3867 : _local_dof_indices.insert(dof_index); 70 : else 71 : { 72 : // if a Dof is non-local add it to a map, to be communicated to the owner in finalize() 73 138 : const auto dof_owner = _var.dofMap().dof_owner(dof_index); 74 138 : _nonlocal_dof_indices_map[dof_owner].push_back(dof_index); 75 : } 76 : } 77 1170 : } 78 : 79 : void 80 11 : DiscreteVariableResidualNorm::threadJoin(const UserObject & y) 81 : { 82 11 : const auto & pps = static_cast<const DiscreteVariableResidualNorm &>(y); 83 11 : _local_dof_indices.insert(pps._local_dof_indices.begin(), pps._local_dof_indices.end()); 84 11 : } 85 : 86 : void 87 132 : DiscreteVariableResidualNorm::finalize() 88 : { 89 : // communicate the non-local Dofs to their processors 90 21 : auto receive_functor = [&](processor_id_type /*pid*/, const std::vector<dof_id_type> & indices) 91 21 : { _local_dof_indices.insert(indices.begin(), indices.end()); }; 92 132 : Parallel::push_parallel_vector_data(_communicator, _nonlocal_dof_indices_map, receive_functor); 93 : 94 : // compute the total number of Dofs for the variable on the subdomain 95 132 : auto n_dofs = _local_dof_indices.size(); 96 132 : gatherSum(n_dofs); 97 : 98 132 : Real bias = 1.0; 99 132 : switch (_norm_type) 100 : { 101 60 : case NormType::l_1: 102 60 : _norm = _nl_residual_vector.subset_l1_norm(_local_dof_indices); 103 60 : bias = n_dofs; 104 60 : break; 105 36 : case NormType::l_2: 106 36 : _norm = _nl_residual_vector.subset_l2_norm(_local_dof_indices); 107 36 : bias = sqrt(n_dofs); 108 36 : break; 109 36 : case NormType::l_inf: 110 36 : _norm = _nl_residual_vector.subset_linfty_norm(_local_dof_indices); 111 36 : break; 112 0 : default: 113 0 : mooseError("Invalid norm type"); 114 : } 115 : 116 132 : if (_correct_mesh_bias) 117 36 : _norm /= bias; 118 132 : } 119 : 120 : PostprocessorValue 121 132 : DiscreteVariableResidualNorm::getValue() const 122 : { 123 132 : return _norm; 124 : }