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 "MultiSpeciesDiffusionCG.h" 11 : #include "MooseVariableBase.h" 12 : 13 : // Register the actions for the objects actually used 14 : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_kernel"); 15 : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_bc"); 16 : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_variable"); 17 : registerMultiSpeciesDiffusionPhysicsBaseTasks("ScalarTransportApp", MultiSpeciesDiffusionCG); 18 : 19 : InputParameters 20 54 : MultiSpeciesDiffusionCG::validParams() 21 : { 22 54 : InputParameters params = MultiSpeciesDiffusionPhysicsBase::validParams(); 23 54 : params.addClassDescription("Discretizes diffusion equations for several species with the " 24 : "continuous Galerkin finite element method"); 25 54 : params.transferParam<MooseEnum>(MooseVariableBase::validParams(), "order", "variable_order"); 26 : 27 54 : return params; 28 0 : } 29 : 30 54 : MultiSpeciesDiffusionCG::MultiSpeciesDiffusionCG(const InputParameters & parameters) 31 54 : : MultiSpeciesDiffusionPhysicsBase(parameters) 32 : { 33 54 : } 34 : 35 : void 36 54 : MultiSpeciesDiffusionCG::addFEKernels() 37 : { 38 216 : for (const auto s : index_range(_species_names)) 39 : { 40 162 : const auto & var_name = _species_names[s]; 41 : // Diffusion term 42 378 : if (isParamValid("diffusivity_matprops") || isParamValid("diffusivity_functors")) 43 : { 44 : // Select the kernel type based on the user parameters 45 : std::string kernel_type; 46 324 : if (isParamValid("diffusivity_matprops")) 47 135 : kernel_type = _use_ad ? "ADMatDiffusion" : "MatDiffusion"; 48 54 : else if (isParamValid("diffusivity_functors")) 49 : { 50 27 : const auto & d = getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s]; 51 27 : if (getProblem().hasFunction(d)) 52 : kernel_type = "FunctionDiffusion"; 53 : else 54 0 : paramError( 55 : "diffusivity_functors", "No diffusion kernel implemented for the source type of", d); 56 : } 57 : 58 162 : InputParameters params = getFactory().getValidParams(kernel_type); 59 324 : params.set<NonlinearVariableName>("variable") = var_name; 60 162 : assignBlocks(params, _blocks); 61 : 62 : // Transfer the diffusivity parameter from the Physics to the kernel 63 324 : if (isParamValid("diffusivity_matprops")) 64 270 : params.set<MaterialPropertyName>("diffusivity") = 65 270 : getParam<std::vector<MaterialPropertyName>>("diffusivity_matprops")[s]; 66 54 : else if (isParamValid("diffusivity_functors")) 67 54 : params.set<FunctionName>("function") = 68 81 : getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s]; 69 : 70 324 : getProblem().addKernel(kernel_type, prefix() + var_name + "_diffusion", params); 71 162 : } 72 : 73 : // Source term 74 324 : if (isParamValid("source_functors")) 75 : { 76 : // Select the kernel type based on the user parameters 77 : std::string kernel_type; 78 324 : const auto & sources = getParam<std::vector<MooseFunctorName>>("source_functors"); 79 : const auto & source = sources[s]; 80 162 : if (MooseUtils::parsesToReal(source) || getProblem().hasFunction(source) || 81 198 : getProblem().hasPostprocessorValueByName(source)) 82 153 : kernel_type = _use_ad ? "ADBodyForce" : "BodyForce"; 83 9 : else if (getProblem().hasVariable(source)) 84 9 : kernel_type = _use_ad ? "ADCoupledForce" : "CoupledForce"; 85 : else 86 0 : paramError("source_functors", 87 : "No kernel defined for a source term in CG for the type of '", 88 : source, 89 : "'"); 90 : 91 162 : InputParameters params = getFactory().getValidParams(kernel_type); 92 324 : params.set<NonlinearVariableName>("variable") = var_name; 93 162 : assignBlocks(params, _blocks); 94 : 95 : // Transfer the source and coefficient parameter from the Physics to the kernel 96 486 : const auto coefs = getParam<std::vector<Real>>("source_coefs"); 97 162 : const auto coef = coefs[s]; 98 162 : if (MooseUtils::parsesToReal(source)) 99 135 : params.set<Real>("value") = MooseUtils::convert<Real>(source) * coef; 100 27 : else if (getProblem().hasFunction(source)) 101 : { 102 9 : params.set<Real>("value") = coef; 103 18 : params.set<FunctionName>("function") = source; 104 : } 105 54 : else if (getProblem().hasPostprocessorValueByName(source)) 106 : { 107 9 : params.set<Real>("value") = coef; 108 18 : params.set<PostprocessorName>("postprocessor") = source; 109 : } 110 : else 111 : { 112 9 : params.set<Real>("coef") = coef; 113 27 : params.set<std::vector<VariableName>>("v") = {source}; 114 : } 115 : 116 324 : getProblem().addKernel(kernel_type, prefix() + var_name + "_source", params); 117 162 : } 118 : 119 : // Time derivative term 120 162 : if (shouldCreateTimeDerivative(var_name, _blocks, false)) 121 : { 122 189 : const std::string kernel_type = _use_ad ? "ADTimeDerivative" : "TimeDerivative"; 123 162 : InputParameters params = getFactory().getValidParams(kernel_type); 124 324 : params.set<NonlinearVariableName>("variable") = var_name; 125 162 : assignBlocks(params, _blocks); 126 324 : getProblem().addKernel(kernel_type, prefix() + var_name + "_time", params); 127 162 : } 128 : } 129 54 : } 130 : 131 : void 132 54 : MultiSpeciesDiffusionCG::addFEBCs() 133 : { 134 108 : if (isParamSetByUser("neumann_boundaries")) 135 : { 136 : const auto & boundary_fluxes = 137 27 : getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_fluxes"); 138 : 139 108 : for (const auto s : index_range(_species_names)) 140 : { 141 81 : const auto & var_name = _species_names[s]; 142 : 143 351 : for (const auto i : index_range(_neumann_boundaries[s])) 144 : { 145 : const auto & bc_flux = boundary_fluxes[s][i]; 146 : // Select the boundary type based on the user parameters and what we know to be most 147 : // efficient We could actually just use the very last option for everything but the 148 : // performance is better if one uses the specialized objects 149 270 : std::string bc_type = ""; 150 270 : if (MooseUtils::parsesToReal(bc_flux)) 151 81 : bc_type = _use_ad ? "ADNeumannBC" : "NeumannBC"; 152 189 : else if (getProblem().hasVariable(bc_flux)) 153 : bc_type = "CoupledVarNeumannBC"; // not AD, but still perfect Jacobian 154 135 : else if (getProblem().hasFunction(bc_flux)) 155 54 : bc_type = _use_ad ? "ADFunctionNeumannBC" : "FunctionNeumannBC"; 156 243 : else if (getProblem().hasPostprocessorValueByName(bc_flux)) 157 : bc_type = "PostprocessorNeumannBC"; 158 : else // this is AD, but we can mix AD and non-AD 159 : bc_type = "FunctorNeumannBC"; 160 : 161 : // Get the parameters for the object type chosen and set the common parameters 162 270 : InputParameters params = getFactory().getValidParams(bc_type); 163 540 : params.set<NonlinearVariableName>("variable") = var_name; 164 810 : params.set<std::vector<BoundaryName>>("boundary") = {_neumann_boundaries[s][i]}; 165 : 166 : // Set the flux parameter for the specific type of NeumannBC used 167 270 : if (MooseUtils::parsesToReal(bc_flux)) 168 81 : params.set<Real>("value") = MooseUtils::convert<Real>(bc_flux); 169 189 : else if (getProblem().hasVariable(bc_flux)) 170 162 : params.set<std::vector<VariableName>>("v") = {bc_flux}; 171 135 : else if (getProblem().hasFunction(bc_flux)) 172 108 : params.set<FunctionName>("function") = bc_flux; 173 243 : else if (getProblem().hasPostprocessorValueByName(bc_flux)) 174 162 : params.set<PostprocessorName>("postprocessor") = bc_flux; 175 : else 176 0 : params.set<MooseFunctorName>("functor") = bc_flux; 177 : 178 540 : getProblem().addBoundaryCondition( 179 540 : bc_type, prefix() + var_name + "_neumann_bc_" + _neumann_boundaries[s][i], params); 180 270 : } 181 : } 182 : } 183 108 : if (isParamSetByUser("dirichlet_boundaries")) 184 : { 185 : const auto & boundary_values = 186 27 : getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_values"); 187 108 : for (const auto s : index_range(_species_names)) 188 : { 189 81 : const auto & var_name = _species_names[s]; 190 297 : for (const auto i : index_range(_dirichlet_boundaries[s])) 191 : { 192 : const auto & bc_value = boundary_values[s][i]; 193 : // Select the boundary type based on the user parameters and what we know to be most 194 : // efficient 195 216 : std::string bc_type = ""; 196 216 : if (MooseUtils::parsesToReal(bc_value)) 197 81 : bc_type = _use_ad ? "ADDirichletBC" : "DirichletBC"; 198 135 : else if (getProblem().hasVariable(bc_value)) 199 27 : bc_type = _use_ad ? "ADMatchedValueBC" : "MatchedValueBC"; 200 108 : else if (getProblem().hasFunction(bc_value)) 201 27 : bc_type = _use_ad ? "ADFunctionDirichletBC" : "FunctionDirichletBC"; 202 243 : else if (getProblem().hasPostprocessorValueByName(bc_value)) 203 : bc_type = "PostprocessorDirichletBC"; 204 : else // this is AD, but we can mix AD and non-AD 205 : bc_type = "FunctorDirichletBC"; 206 : 207 216 : InputParameters params = getFactory().getValidParams(bc_type); 208 432 : params.set<NonlinearVariableName>("variable") = var_name; 209 648 : params.set<std::vector<BoundaryName>>("boundary") = {_dirichlet_boundaries[s][i]}; 210 : 211 : // Set the flux parameter for the specific type of DirichletBC used 212 216 : if (MooseUtils::parsesToReal(bc_value)) 213 81 : params.set<Real>("value") = MooseUtils::convert<Real>(bc_value); 214 135 : else if (getProblem().hasVariable(bc_value)) 215 81 : params.set<std::vector<VariableName>>("v") = {bc_value}; 216 108 : else if (getProblem().hasFunction(bc_value)) 217 54 : params.set<FunctionName>("function") = bc_value; 218 243 : else if (getProblem().hasPostprocessorValueByName(bc_value)) 219 162 : params.set<PostprocessorName>("postprocessor") = bc_value; 220 : else 221 0 : params.set<MooseFunctorName>("functor") = bc_value; 222 : 223 432 : getProblem().addBoundaryCondition( 224 432 : bc_type, prefix() + var_name + "_dirichlet_bc_" + _dirichlet_boundaries[s][i], params); 225 216 : } 226 : } 227 : } 228 54 : } 229 : 230 : void 231 54 : MultiSpeciesDiffusionCG::addSolverVariables() 232 : { 233 216 : for (const auto & var_name : _species_names) 234 : { 235 : // If the variable was added outside the Physics 236 162 : if (variableExists(var_name, /*error_if_aux*/ true)) 237 : { 238 0 : if (isParamValid("variable_order")) 239 0 : paramError("variable_order", 240 0 : "Cannot specify the variable order if variable " + var_name + 241 : " is defined outside the Physics block"); 242 : else 243 0 : continue; 244 : } 245 : 246 162 : const std::string variable_type = "MooseVariable"; 247 162 : InputParameters params = getFactory().getValidParams(variable_type); 248 486 : params.set<MooseEnum>("order") = getParam<MooseEnum>("variable_order"); 249 162 : assignBlocks(params, _blocks); 250 162 : params.set<SolverSystemName>("solver_sys") = getSolverSystem(var_name); 251 : 252 162 : getProblem().addVariable(variable_type, var_name, params); 253 162 : } 254 54 : }