https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
14registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_kernel");
15registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_bc");
16registerMooseAction("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
34
35void
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];
52 kernel_type = "FunctionDiffusion";
53 else
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
131void
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
230void
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 continue;
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}
registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_kernel")
registerMultiSpeciesDiffusionPhysicsBaseTasks("ScalarTransportApp", MultiSpeciesDiffusionCG)
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
bool hasPostprocessorValueByName(const PostprocessorName &name) const
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
void transferParam(const InputParameters &source_param, const std::string &name, const std::string &new_name="", const std::string &new_description="")
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
const T & getParam(const std::string &name) const
bool isParamValid(const std::string &name) const
static InputParameters validParams()
Creates all the objects needed to solve diffusion equations for multiple species with a continuous Ga...
MultiSpeciesDiffusionCG(const InputParameters &parameters)
virtual void addFEBCs() override
virtual void addFEKernels() override
static InputParameters validParams()
virtual void addSolverVariables() override
Base class to host all common parameters and attributes of Physics actions to solve the diffusion equ...
const bool _use_ad
Whether to use automatic differentiation or not.
const std::vector< std::vector< BoundaryName > > & _dirichlet_boundaries
Boundaries on which a Dirichlet boundary condition is applied. Outer indexing is variables.
const std::vector< VariableName > & _species_names
Name of the diffused variables.
const std::vector< std::vector< BoundaryName > > & _neumann_boundaries
Boundaries on which a Neumann boundary condition is applied. Outer indexing is variables.
virtual FEProblemBase & getProblem()
Factory & getFactory()
bool shouldCreateTimeDerivative(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool error_if_already_defined) const
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
std::string prefix() const
bool variableExists(const VariableName &var_name, bool error_if_aux) const
const SolverSystemName & getSolverSystem(unsigned int variable_index) const
std::vector< SubdomainName > _blocks
bool parsesToReal(const std::string &input, Real *parsed_real)