https://mooseframework.inl.gov
Loading...
Searching...
No Matches
DiffusionCG.C
Go to the documentation of this file.
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
15registerMooseAction("MooseApp", DiffusionCG, "add_kernel");
16registerMooseAction("MooseApp", DiffusionCG, "add_bc");
17registerMooseAction("MooseApp", DiffusionCG, "add_variables_physics");
18
21{
24 "Discretizes a diffusion equation with the continuous Galerkin finite element method");
25 params.addParam<bool>(
26 "use_automatic_differentiation",
27 true,
28 "Whether to use automatic differentiation for all the terms in the equation");
29 params.transferParam<MooseEnum>(MooseVariableBase::validParams(), "order", "variable_order");
30
31 return params;
32}
33
35 : PhysicsBase(parameters),
36 PhysicsComponentInterface(parameters),
37 DiffusionPhysicsBase(parameters),
38 _use_ad(getParam<bool>("use_automatic_differentiation"))
39{
40}
41
42void
44{
45 // Diffusion term
46 {
47 // Select the kernel type based on the user parameters
48 std::string kernel_type;
49 if (isParamValid("diffusivity_matprop"))
50 kernel_type = _use_ad ? "ADMatDiffusion" : "MatDiffusion";
51 else if (isParamValid("diffusivity_functor"))
52 {
53 const auto & d = getParam<MooseFunctorName>("diffusivity_functor");
54 if (getProblem().hasFunction(d) || MooseUtils::parsesToReal(d))
55 kernel_type = "FunctionDiffusion";
56 else
57 paramError("diffusivity_functor",
58 "No diffusion kernel implemented for the diffusivity type of ",
59 d);
60 }
61 else
62 kernel_type = _use_ad ? "ADDiffusion" : "Diffusion";
63 InputParameters params = getFactory().getValidParams(kernel_type);
64 params.set<NonlinearVariableName>("variable") = _var_name;
65 assignBlocks(params, _blocks);
66
67 // Transfer the diffusivity parameter from the Physics to the kernel
68 // From parameters
69 if (isParamValid("diffusivity_matprop"))
70 params.set<MaterialPropertyName>("diffusivity") =
71 getParam<MaterialPropertyName>("diffusivity_matprop");
72 else if (isParamValid("diffusivity_functor"))
73 params.set<FunctionName>("function") = getParam<MooseFunctorName>("diffusivity_functor");
74
75 getProblem().addKernel(kernel_type, prefix() + _var_name + "_diffusion", params);
76 }
77
78 // Source term
79 if (isParamValid("source_functor"))
80 {
81 // Select the kernel type based on the user parameters
82 std::string kernel_type;
83 const auto & source = getParam<MooseFunctorName>("source_functor");
84 if (MooseUtils::parsesToReal(source) || getProblem().hasFunction(source) ||
85 getProblem().hasPostprocessorValueByName(source))
86 kernel_type = _use_ad ? "ADBodyForce" : "BodyForce";
87 else if (getProblem().hasVariable(source))
88 kernel_type = _use_ad ? "ADCoupledForce" : "CoupledForce";
89 else
90 paramError("source_functor",
91 "No kernel defined for a source term in CG for the type of '",
92 source,
93 "'");
94
95 InputParameters params = getFactory().getValidParams(kernel_type);
96 params.set<NonlinearVariableName>("variable") = _var_name;
97 assignBlocks(params, _blocks);
98
99 // Transfer the source and coefficient parameter from the Physics to the kernel
100 const auto coef = getParam<Real>("source_coef");
101 if (MooseUtils::parsesToReal(source))
102 params.set<Real>("value") = MooseUtils::convert<Real>(source) * coef;
103 else if (getProblem().hasFunction(source))
104 {
105 params.set<Real>("value") = coef;
106 params.set<FunctionName>("function") = source;
107 }
108 else if (getProblem().hasPostprocessorValueByName(source))
109 {
110 params.set<Real>("value") = coef;
111 params.set<PostprocessorName>("postprocessor") = source;
112 }
113 else
114 {
115 params.set<Real>("coef") = coef;
116 params.set<std::vector<VariableName>>("v") = {source};
117 }
118
119 getProblem().addKernel(kernel_type, prefix() + _var_name + "_source", params);
120 }
121
122 // Time derivative term
124 {
125 const std::string kernel_type = _use_ad ? "ADTimeDerivative" : "TimeDerivative";
126 InputParameters params = getFactory().getValidParams(kernel_type);
127 params.set<NonlinearVariableName>("variable") = _var_name;
128 assignBlocks(params, _blocks);
129 getProblem().addKernel(kernel_type, prefix() + _var_name + "_time", params);
130 }
131}
132
133void
135{
136 if (isParamSetByUser("neumann_boundaries"))
137 {
138 const auto & boundary_fluxes = getParam<std::vector<MooseFunctorName>>("boundary_fluxes");
139 for (const auto i : index_range(_neumann_boundaries))
140 {
141 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 std::string bc_type = "";
146 if (MooseUtils::parsesToReal(bc_flux))
147 bc_type = _use_ad ? "ADNeumannBC" : "NeumannBC";
148 else if (getProblem().hasVariable(bc_flux))
149 bc_type = "CoupledVarNeumannBC"; // not AD, but still perfect Jacobian
150 else if (getProblem().hasFunction(bc_flux))
151 bc_type = _use_ad ? "ADFunctionNeumannBC" : "FunctionNeumannBC";
152 else if (getProblem().hasPostprocessorValueByName(bc_flux))
153 bc_type = "PostprocessorNeumannBC";
154 else // this is AD, but we can mix AD and non-AD
155 bc_type = "FunctorNeumannBC";
156
157 // Get the parameters for the object type chosen and set the common parameters
158 InputParameters params = getFactory().getValidParams(bc_type);
159 params.set<NonlinearVariableName>("variable") = _var_name;
160 params.set<std::vector<BoundaryName>>("boundary") = {_neumann_boundaries[i]};
161
162 // Set the flux parameter for the specific type of NeumannBC used
163 if (MooseUtils::parsesToReal(bc_flux))
164 params.set<Real>("value") = MooseUtils::convert<Real>(bc_flux);
165 else if (getProblem().hasVariable(bc_flux))
166 params.set<std::vector<VariableName>>("v") = {bc_flux};
167 else if (getProblem().hasFunction(bc_flux))
168 params.set<FunctionName>("function") = bc_flux;
169 else if (getProblem().hasPostprocessorValueByName(bc_flux))
170 params.set<PostprocessorName>("postprocessor") = bc_flux;
171 else
172 params.set<MooseFunctorName>("functor") = bc_flux;
173
175 bc_type, prefix() + _var_name + "_neumann_bc_" + _neumann_boundaries[i], params);
176 }
177 }
178 if (isParamSetByUser("dirichlet_boundaries"))
179 {
180 const auto & boundary_values = getParam<std::vector<MooseFunctorName>>("boundary_values");
181 for (const auto i : index_range(_dirichlet_boundaries))
182 {
183 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 std::string bc_type = "";
186 if (MooseUtils::parsesToReal(bc_value))
187 bc_type = _use_ad ? "ADDirichletBC" : "DirichletBC";
188 else if (getProblem().hasVariable(bc_value))
189 bc_type = _use_ad ? "ADMatchedValueBC" : "MatchedValueBC";
190 else if (getProblem().hasFunction(bc_value))
191 bc_type = _use_ad ? "ADFunctionDirichletBC" : "FunctionDirichletBC";
192 else if (getProblem().hasPostprocessorValueByName(bc_value))
193 bc_type = "PostprocessorDirichletBC";
194 else // this is AD, but we can mix AD and non-AD
195 bc_type = "FunctorDirichletBC";
196
197 InputParameters params = getFactory().getValidParams(bc_type);
198 params.set<NonlinearVariableName>("variable") = _var_name;
199 params.set<std::vector<BoundaryName>>("boundary") = {_dirichlet_boundaries[i]};
200
201 // Set the flux parameter for the specific type of DirichletBC used
202 if (MooseUtils::parsesToReal(bc_value))
203 params.set<Real>("value") = MooseUtils::convert<Real>(bc_value);
204 else if (getProblem().hasVariable(bc_value))
205 params.set<std::vector<VariableName>>("v") = {bc_value};
206 else if (getProblem().hasFunction(bc_value))
207 params.set<FunctionName>("function") = bc_value;
208 else if (getProblem().hasPostprocessorValueByName(bc_value))
209 params.set<PostprocessorName>("postprocessor") = bc_value;
210 else
211 params.set<MooseFunctorName>("functor") = bc_value;
212
214 bc_type, prefix() + _var_name + "_dirichlet_bc_" + _dirichlet_boundaries[i], params);
215 }
216 }
217}
218
219void
221{
222 // If the variable was added outside the Physics
224 {
225 reportPotentiallyMissedParameters({"variable_order", "system_names"}, "MooseVariable");
226 return;
227 }
228
229 const std::string variable_type = "MooseVariable";
230 InputParameters params = getFactory().getValidParams(variable_type);
231 params.set<MooseEnum>("order") = getParam<MooseEnum>("variable_order");
232 assignBlocks(params, _blocks);
233 params.set<SolverSystemName>("solver_sys") = getSolverSystem(_var_name);
234
235 getProblem().addVariable(variable_type, _var_name, params);
236}
237
238void
240{
241 const auto bc_type_fixed = "FunctorDirichletBC";
242 InputParameters params_fixed = getFactory().getValidParams(bc_type_fixed);
243 const auto bc_type_flux = "FunctorNeumannBC";
244 InputParameters params_flux = getFactory().getValidParams(bc_type_flux);
245
246 for (const auto & comp_pair : _components_boundary_conditions)
247 {
248 for (const auto & bc_pair : comp_pair.second)
249 {
250 params_fixed.set<NonlinearVariableName>("variable") = _var_name;
251 params_flux.set<NonlinearVariableName>("variable") = _var_name;
252
253 const auto bc_type = bc_pair.second.second;
254 const auto functor_name = bc_pair.second.first;
255 params_fixed.set<MooseFunctorName>("functor") = functor_name;
256 params_flux.set<MooseFunctorName>("functor") = functor_name;
257
258 const auto surface_name = bc_pair.first.second;
259 params_fixed.set<std::vector<BoundaryName>>("boundary") = {surface_name};
260 params_flux.set<std::vector<BoundaryName>>("boundary") = {surface_name};
261
263 getProblem().addBoundaryCondition(bc_type_fixed,
264 prefix() + _var_name + "_comp_" + comp_pair.first +
265 "_fixed_value_" + surface_name,
266 params_fixed);
268 getProblem().addBoundaryCondition(bc_type_flux,
269 prefix() + _var_name + "_comp_" + comp_pair.first +
270 "_flux_" + surface_name,
271 params_flux);
272 else
273 mooseError("Boundary condition type not implemented");
274 }
275 }
276}
registerDiffusionPhysicsBaseTasks("MooseApp", DiffusionCG)
registerMooseAction("MooseApp", DiffusionCG, "add_kernel")
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Creates all the objects needed to solve a diffusion equation with a continuous Galerkin finite elemen...
Definition DiffusionCG.h:19
virtual void addFEBCs() override
virtual void addBoundaryConditionsFromComponents() override
static InputParameters validParams()
Definition DiffusionCG.C:20
DiffusionCG(const InputParameters &parameters)
Definition DiffusionCG.C:34
virtual void addSolverVariables() override
The default implementation of these routines will do nothing as we do not expect all Physics to be de...
const bool _use_ad
Whether to use automatic differentiation or not.
Definition DiffusionCG.h:33
virtual void addFEKernels() override
Definition DiffusionCG.C:43
Base class to host all common parameters and attributes of Physics actions to solve the diffusion equ...
const std::vector< BoundaryName > & _neumann_boundaries
Boundaries on which a Neumann boundary condition is applied.
const VariableName & _var_name
Name of the diffused variable.
static InputParameters validParams()
const std::vector< BoundaryName > & _dirichlet_boundaries
Boundaries on which a Dirichlet boundary condition is applied.
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding a non-linear variable.
bool hasPostprocessorValueByName(const PostprocessorName &name) const
Whether or not a Postprocessor value exists by a given name.
virtual void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual bool hasFunction(const std::string &name, const THREAD_ID tid=0)
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void transferParam(const InputParameters &source_param, const std::string &name, const std::string &new_name="", const std::string &new_description="")
A routine to transfer a parameter from one class' validParams to another.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
static InputParameters validParams()
Base class to help creating an entire physics.
Definition PhysicsBase.h:31
virtual FEProblemBase & getProblem()
Get the problem for this physics Useful to add objects to the simulation.
Factory & getFactory()
Get the factory for this physics The factory lets you get the parameters for objects.
bool shouldCreateTimeDerivative(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_already_defined) const
Returns whether this Physics should create the variable.
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
Set the blocks parameter to the input parameters of an object this Physics will create.
void reportPotentiallyMissedParameters(const std::vector< std::string > &param_names, const std::string &object_type, const std::string &object_name="") const
When this is called, we are knowingly not using the value of these parameters.
std::string prefix() const
Use prefix() to disambiguate names.
const SolverSystemName & getSolverSystem(unsigned int variable_index) const
Get the solver system for this variable index.
bool shouldCreateVariable(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_aux)
Returns whether this Physics should create the variable.
std::vector< SubdomainName > _blocks
Keep track of the subdomains the Physics is defined on.
Interface class to help components interact with Physics.
std::map< std::string, std::map< std::pair< VariableName, BoundaryName >, std::pair< MooseFunctorName, ComponentBoundaryConditionInterface::BoundaryConditionType > > > _components_boundary_conditions
Map of components to variables and boundary conditions.
bool parsesToReal(const std::string &input, Real *parsed_real)
Definition MooseUtils.C:100