https://mooseframework.inl.gov
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
14 registerMooseAction("MooseApp", DiffusionCG, "add_kernel");
15 registerMooseAction("MooseApp", DiffusionCG, "add_bc");
16 registerMooseAction("MooseApp", DiffusionCG, "add_variable");
18 
21 {
23  params.addClassDescription(
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 
42 void
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");
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) ||
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 
133 void
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 
219 void
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 
238 void
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 
262  if (bc_type == ComponentBoundaryConditionInterface::BoundaryConditionType::FIXED_VALUE)
263  getProblem().addBoundaryCondition(bc_type_fixed,
264  prefix() + _var_name + "_comp_" + comp_pair.first +
265  "_fixed_value_" + surface_name,
266  params_fixed);
267  else if (bc_type == ComponentBoundaryConditionInterface::BoundaryConditionType::FLUX)
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 }
static InputParameters validParams()
std::string prefix() const
Use prefix() to disambiguate names.
Definition: PhysicsBase.h:135
virtual bool hasVariable(const std::string &var_name) const override
Whether or not this problem has the variable.
bool parsesToReal(const std::string &input)
Check if the input string can be parsed into a Real.
Definition: MooseUtils.C:89
const bool _use_ad
Whether to use automatic differentiation or not.
Definition: DiffusionCG.h:33
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.
Definition: PhysicsBase.C:484
bool shouldCreateVariable(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_aux)
Returns whether this Physics should create the variable.
Definition: PhysicsBase.C:602
static InputParameters validParams()
Factory & getFactory()
Get the factory for this physics The factory lets you get the parameters for objects.
Definition: PhysicsBase.h:108
virtual void addBoundaryConditionsFromComponents() override
Definition: DiffusionCG.C:239
const std::vector< BoundaryName > & _neumann_boundaries
Boundaries on which a Neumann boundary condition is applied.
Base class to help creating an entire physics.
Definition: PhysicsBase.h:30
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
static InputParameters validParams()
Definition: DiffusionCG.C:20
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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.
Definition: PhysicsBase.C:678
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
const VariableName & _var_name
Name of the diffused variable.
std::vector< SubdomainName > _blocks
Keep track of the subdomains the Physics is defined on.
Definition: PhysicsBase.h:261
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.
DiffusionCG(const InputParameters &parameters)
Definition: DiffusionCG.C:34
virtual void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
virtual FEProblemBase & getProblem()
Get the problem for this physics Useful to add objects to the simulation.
Definition: PhysicsBase.h:112
virtual void addFEBCs() override
Definition: DiffusionCG.C:134
const SolverSystemName & getSolverSystem(unsigned int variable_index) const
Get the solver system for this variable index.
Definition: PhysicsBase.C:440
Interface class to help components interact with Physics.
bool hasPostprocessorValueByName(const PostprocessorName &name) const
Whether or not a Postprocessor value exists by a given name.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
const std::vector< BoundaryName > & _dirichlet_boundaries
Boundaries on which a Dirichlet boundary condition is applied.
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 ...
Creates all the objects needed to solve a diffusion equation with a continuous Galerkin finite elemen...
Definition: DiffusionCG.h:18
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&#39; validParams to another.
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding a non-linear variable.
virtual void addSolverVariables() override
The default implementation of these routines will do nothing as we do not expect all Physics to be de...
Definition: DiffusionCG.C:220
bool isParamSetByUser(const std::string &nm) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerDiffusionPhysicsBaseTasks("MooseApp", DiffusionCG)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
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...
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 reportPotentiallyMissedParameters(const std::vector< std::string > &param_names, const std::string &object_type) const
When this is called, we are knowingly not using the value of these parameters.
Definition: PhysicsBase.C:779
virtual void addFEKernels() override
Definition: DiffusionCG.C:43
virtual bool hasFunction(const std::string &name, const THREAD_ID tid=0)
auto index_range(const T &sizable)
Base class to host all common parameters and attributes of Physics actions to solve the diffusion equ...
registerMooseAction("MooseApp", DiffusionCG, "add_kernel")