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