https://mooseframework.inl.gov
MultiSpeciesDiffusionCG.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 
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");
18 
21 {
23  params.addClassDescription("Discretizes diffusion equations for several species with the "
24  "continuous Galerkin finite element method");
25  params.transferParam<MooseEnum>(MooseVariableBase::validParams(), "order", "variable_order");
26 
27  return params;
28 }
29 
32 {
33 }
34 
35 void
37 {
38  for (const auto s : index_range(_species_names))
39  {
40  const auto & var_name = _species_names[s];
41  // Diffusion term
42  if (isParamValid("diffusivity_matprops") || isParamValid("diffusivity_functors"))
43  {
44  // Select the kernel type based on the user parameters
45  std::string kernel_type;
46  if (isParamValid("diffusivity_matprops"))
47  kernel_type = _use_ad ? "ADMatDiffusion" : "MatDiffusion";
48  else if (isParamValid("diffusivity_functors"))
49  {
50  const auto & d = getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s];
51  if (getProblem().hasFunction(d))
52  kernel_type = "FunctionDiffusion";
53  else
54  paramError(
55  "diffusivity_functors", "No diffusion kernel implemented for the source type of", d);
56  }
57 
58  InputParameters params = getFactory().getValidParams(kernel_type);
59  params.set<NonlinearVariableName>("variable") = var_name;
60  assignBlocks(params, _blocks);
61 
62  // Transfer the diffusivity parameter from the Physics to the kernel
63  if (isParamValid("diffusivity_matprops"))
64  params.set<MaterialPropertyName>("diffusivity") =
65  getParam<std::vector<MaterialPropertyName>>("diffusivity_matprops")[s];
66  else if (isParamValid("diffusivity_functors"))
67  params.set<FunctionName>("function") =
68  getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s];
69 
70  getProblem().addKernel(kernel_type, prefix() + var_name + "_diffusion", params);
71  }
72 
73  // Source term
74  if (isParamValid("source_functors"))
75  {
76  // Select the kernel type based on the user parameters
77  std::string kernel_type;
78  const auto & sources = getParam<std::vector<MooseFunctorName>>("source_functors");
79  const auto & source = sources[s];
80  if (MooseUtils::parsesToReal(source) || getProblem().hasFunction(source) ||
82  kernel_type = _use_ad ? "ADBodyForce" : "BodyForce";
83  else if (getProblem().hasVariable(source))
84  kernel_type = _use_ad ? "ADCoupledForce" : "CoupledForce";
85  else
86  paramError("source_functors",
87  "No kernel defined for a source term in CG for the type of '",
88  source,
89  "'");
90 
91  InputParameters params = getFactory().getValidParams(kernel_type);
92  params.set<NonlinearVariableName>("variable") = var_name;
93  assignBlocks(params, _blocks);
94 
95  // Transfer the source and coefficient parameter from the Physics to the kernel
96  const auto coefs = getParam<std::vector<Real>>("source_coefs");
97  const auto coef = coefs[s];
98  if (MooseUtils::parsesToReal(source))
99  params.set<Real>("value") = MooseUtils::convert<Real>(source) * coef;
100  else if (getProblem().hasFunction(source))
101  {
102  params.set<Real>("value") = coef;
103  params.set<FunctionName>("function") = source;
104  }
105  else if (getProblem().hasPostprocessorValueByName(source))
106  {
107  params.set<Real>("value") = coef;
108  params.set<PostprocessorName>("postprocessor") = source;
109  }
110  else
111  {
112  params.set<Real>("coef") = coef;
113  params.set<std::vector<VariableName>>("v") = {source};
114  }
115 
116  getProblem().addKernel(kernel_type, prefix() + var_name + "_source", params);
117  }
118 
119  // Time derivative term
120  if (shouldCreateTimeDerivative(var_name, _blocks, false))
121  {
122  const std::string kernel_type = _use_ad ? "ADTimeDerivative" : "TimeDerivative";
123  InputParameters params = getFactory().getValidParams(kernel_type);
124  params.set<NonlinearVariableName>("variable") = var_name;
125  assignBlocks(params, _blocks);
126  getProblem().addKernel(kernel_type, prefix() + var_name + "_time", params);
127  }
128  }
129 }
130 
131 void
133 {
134  if (isParamSetByUser("neumann_boundaries"))
135  {
136  const auto & boundary_fluxes =
137  getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_fluxes");
138 
139  for (const auto s : index_range(_species_names))
140  {
141  const auto & var_name = _species_names[s];
142 
143  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  std::string bc_type = "";
150  if (MooseUtils::parsesToReal(bc_flux))
151  bc_type = _use_ad ? "ADNeumannBC" : "NeumannBC";
152  else if (getProblem().hasVariable(bc_flux))
153  bc_type = "CoupledVarNeumannBC"; // not AD, but still perfect Jacobian
154  else if (getProblem().hasFunction(bc_flux))
155  bc_type = _use_ad ? "ADFunctionNeumannBC" : "FunctionNeumannBC";
156  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  InputParameters params = getFactory().getValidParams(bc_type);
163  params.set<NonlinearVariableName>("variable") = var_name;
164  params.set<std::vector<BoundaryName>>("boundary") = {_neumann_boundaries[s][i]};
165 
166  // Set the flux parameter for the specific type of NeumannBC used
167  if (MooseUtils::parsesToReal(bc_flux))
168  params.set<Real>("value") = MooseUtils::convert<Real>(bc_flux);
169  else if (getProblem().hasVariable(bc_flux))
170  params.set<std::vector<VariableName>>("v") = {bc_flux};
171  else if (getProblem().hasFunction(bc_flux))
172  params.set<FunctionName>("function") = bc_flux;
173  else if (getProblem().hasPostprocessorValueByName(bc_flux))
174  params.set<PostprocessorName>("postprocessor") = bc_flux;
175  else
176  params.set<MooseFunctorName>("functor") = bc_flux;
177 
179  bc_type, prefix() + var_name + "_neumann_bc_" + _neumann_boundaries[s][i], params);
180  }
181  }
182  }
183  if (isParamSetByUser("dirichlet_boundaries"))
184  {
185  const auto & boundary_values =
186  getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_values");
187  for (const auto s : index_range(_species_names))
188  {
189  const auto & var_name = _species_names[s];
190  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  std::string bc_type = "";
196  if (MooseUtils::parsesToReal(bc_value))
197  bc_type = _use_ad ? "ADDirichletBC" : "DirichletBC";
198  else if (getProblem().hasVariable(bc_value))
199  bc_type = _use_ad ? "ADMatchedValueBC" : "MatchedValueBC";
200  else if (getProblem().hasFunction(bc_value))
201  bc_type = _use_ad ? "ADFunctionDirichletBC" : "FunctionDirichletBC";
202  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  InputParameters params = getFactory().getValidParams(bc_type);
208  params.set<NonlinearVariableName>("variable") = var_name;
209  params.set<std::vector<BoundaryName>>("boundary") = {_dirichlet_boundaries[s][i]};
210 
211  // Set the flux parameter for the specific type of DirichletBC used
212  if (MooseUtils::parsesToReal(bc_value))
213  params.set<Real>("value") = MooseUtils::convert<Real>(bc_value);
214  else if (getProblem().hasVariable(bc_value))
215  params.set<std::vector<VariableName>>("v") = {bc_value};
216  else if (getProblem().hasFunction(bc_value))
217  params.set<FunctionName>("function") = bc_value;
218  else if (getProblem().hasPostprocessorValueByName(bc_value))
219  params.set<PostprocessorName>("postprocessor") = bc_value;
220  else
221  params.set<MooseFunctorName>("functor") = bc_value;
222 
224  bc_type, prefix() + var_name + "_dirichlet_bc_" + _dirichlet_boundaries[s][i], params);
225  }
226  }
227  }
228 }
229 
230 void
232 {
233  for (const auto & var_name : _species_names)
234  {
235  // If the variable was added outside the Physics
236  if (variableExists(var_name, /*error_if_aux*/ true))
237  {
238  if (isParamValid("variable_order"))
239  paramError("variable_order",
240  "Cannot specify the variable order if variable " + var_name +
241  " is defined outside the Physics block");
242  else
243  return;
244  }
245 
246  const std::string variable_type = "MooseVariable";
247  InputParameters params = getFactory().getValidParams(variable_type);
248  params.set<MooseEnum>("order") = getParam<MooseEnum>("variable_order");
249  assignBlocks(params, _blocks);
250  params.set<SolverSystemName>("solver_sys") = getSolverSystem(var_name);
251 
252  getProblem().addVariable(variable_type, var_name, params);
253  }
254 }
static InputParameters validParams()
virtual void addFEBCs() override
std::string prefix() const
virtual bool hasVariable(const std::string &var_name) const override
bool parsesToReal(const std::string &input)
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
virtual void addFEKernels() override
static InputParameters validParams()
Factory & getFactory()
registerMultiSpeciesDiffusionPhysicsBaseTasks("ScalarTransportApp", MultiSpeciesDiffusionCG)
Base class to host all common parameters and attributes of Physics actions to solve the diffusion equ...
const std::vector< std::vector< BoundaryName > > & _neumann_boundaries
Boundaries on which a Neumann boundary condition is applied. Outer indexing is variables.
T & set(const std::string &name, bool quiet_mode=false)
InputParameters getValidParams(const std::string &name) const
bool shouldCreateTimeDerivative(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_already_defined) const
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
MultiSpeciesDiffusionCG(const InputParameters &parameters)
std::vector< SubdomainName > _blocks
registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_kernel")
virtual void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
bool isParamValid(const std::string &name) const
virtual FEProblemBase & getProblem()
const SolverSystemName & getSolverSystem(unsigned int variable_index) const
Creates all the objects needed to solve diffusion equations for multiple species with a continuous Ga...
bool hasPostprocessorValueByName(const PostprocessorName &name) const
const T & getParam(const std::string &name) const
void paramError(const std::string &param, Args... args) const
void transferParam(const InputParameters &source_param, const std::string &name, const std::string &new_name="", const std::string &new_description="")
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
const std::vector< VariableName > & _species_names
Name of the diffused variables.
bool variableExists(const VariableName &var_name, bool error_if_aux) const
virtual void addSolverVariables() override
bool isParamSetByUser(const std::string &nm) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< std::vector< BoundaryName > > & _dirichlet_boundaries
Boundaries on which a Dirichlet boundary condition is applied. Outer indexing is variables.
void addClassDescription(const std::string &doc_string)
const bool _use_ad
Whether to use automatic differentiation or not.
virtual bool hasFunction(const std::string &name, const THREAD_ID tid=0)
auto index_range(const T &sizable)