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 "PointwiseRenormalizeVector.h" 11 : #include "MooseError.h" 12 : #include "NonlinearSystemBase.h" 13 : 14 : #include "libmesh/numeric_vector.h" 15 : #include "libmesh/int_range.h" 16 : 17 : registerMooseObject("MooseApp", PointwiseRenormalizeVector); 18 : 19 : InputParameters 20 14289 : PointwiseRenormalizeVector::validParams() 21 : { 22 14289 : InputParameters params = GeneralUserObject::validParams(); 23 14289 : params.addClassDescription( 24 : "Pointwise renormalize the solution of a set of variables comprising a vector"); 25 14289 : params.addCoupledVar("v", "Variables comprising the vector"); 26 14289 : params.addParam<Real>("norm", 1.0, "Desired norm for the coupled variable vector"); 27 14289 : params.registerBase("Corrector"); 28 : 29 14289 : return params; 30 0 : } 31 : 32 12 : PointwiseRenormalizeVector::PointwiseRenormalizeVector(const InputParameters & parameters) 33 : : GeneralUserObject(parameters), 34 24 : _mesh(_fe_problem.mesh()), 35 12 : _var_names(getParam<std::vector<VariableName>>("v")), 36 24 : _target_norm(getParam<Real>("norm")) 37 : { 38 12 : const MooseVariableFieldBase * first_var = nullptr; 39 36 : for (const auto & var_name : _var_names) 40 : { 41 24 : auto & var = _fe_problem.getVariable(0, var_name); 42 24 : if (!first_var) 43 12 : first_var = &var; 44 : else 45 : { 46 : // check order and family for consistency 47 12 : if (first_var->feType() != var.feType()) 48 0 : paramError("v", "All supplied variables must be of the same order and family."); 49 : // check block restriction for consistency 50 12 : if (!first_var->hasBlocks(var.blockIDs()) || !var.hasBlocks(first_var->blockIDs())) 51 0 : paramError("v", "All supplied variables must have the same block restriction."); 52 : } 53 : 54 24 : if (_sys.number() != var.sys().system().number()) 55 0 : paramError("v", "Variables must be all in the non-linear system."); 56 : 57 24 : if (var.isArray()) 58 : { 59 0 : const auto & array_var = _fe_problem.getArrayVariable(0, var_name); 60 0 : for (unsigned int p = 0; p < var.count(); ++p) 61 0 : _var_numbers.push_back(_sys.system().variable_number(array_var.componentName(p))); 62 : } 63 : else 64 24 : _var_numbers.push_back(_sys.system().variable_number(var_name)); 65 : } 66 12 : } 67 : 68 : void 69 110 : PointwiseRenormalizeVector::initialize() 70 : { 71 : // do one solution.close to get updated 72 110 : _sys.system().solution->close(); 73 110 : } 74 : 75 : void 76 110 : PointwiseRenormalizeVector::execute() 77 : { 78 110 : auto & dof_map = _sys.system().get_dof_map(); 79 110 : const auto local_dof_begin = dof_map.first_dof(); 80 110 : const auto local_dof_end = dof_map.end_dof(); 81 : 82 110 : std::vector<std::vector<dof_id_type>> dof_indices(_var_numbers.size()); 83 110 : std::vector<Real> cache(_var_numbers.size()); 84 : 85 8110 : for (const auto & elem : *_mesh.getActiveLocalElementRange()) 86 : { 87 : // prepare variable dofs 88 24000 : for (const auto i : index_range(_var_numbers)) 89 : { 90 16000 : dof_map.dof_indices(elem, dof_indices[i], _var_numbers[i]); 91 : 92 : // check that all vars have the same number of dofs 93 : mooseAssert(dof_indices[i].size() == dof_indices[0].size(), 94 : "All specified variables should have the same number of DOFs"); 95 : } 96 : 97 : // iterate over current, old, and older solutions 98 32000 : for (const auto s : make_range(3)) 99 24000 : if (_sys.hasSolutionState(s)) 100 : { 101 16000 : auto & solution = _sys.solutionState(s); 102 : 103 : // loop over all DOFs 104 80000 : for (const auto j : index_range(dof_indices[0])) 105 : { 106 : // check if the first variable's DOFs are local (if they are all other variables should 107 : // have local DOFS as well) 108 64000 : if (dof_indices[0][j] > local_dof_end || dof_indices[0][j] < local_dof_begin) 109 1360 : continue; 110 : 111 : // compute current norm 112 62640 : Real norm = 0.0; 113 187920 : for (const auto i : index_range(_var_numbers)) 114 125280 : norm += Utility::pow<2>(solution(dof_indices[i][j])); 115 : 116 62640 : if (norm == 0.0) 117 0 : continue; 118 62640 : norm = std::sqrt(norm); 119 : 120 : // renormalize 121 187920 : for (const auto i : index_range(_var_numbers)) 122 125280 : solution.set(dof_indices[i][j], solution(dof_indices[i][j]) / norm * _target_norm); 123 : } 124 : } 125 : } 126 110 : } 127 : 128 : void 129 110 : PointwiseRenormalizeVector::finalize() 130 : { 131 440 : for (const auto s : make_range(3)) 132 330 : if (_sys.hasSolutionState(s)) 133 220 : _sys.solutionState(s).close(); 134 : 135 110 : _sys.update(); 136 110 : }