https://mooseframework.inl.gov
MultiSpeciesDiffusionPhysicsBase.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 "MatDiffusion.h"
12 #include "MoosePreconditioner.h"
13 #include "PetscSupport.h"
14 #include "MooseEnumItem.h"
15 #include "ActionComponent.h"
16 
19 {
21  params.addClassDescription(
22  "Base class for creating a diffusion equation for multiple diffused species");
23 
24  params.addRequiredParam<std::vector<VariableName>>("species", "Species being diffused");
25 
26  // Diffusivity
27  params.addParam<std::vector<MaterialPropertyName>>(
28  "diffusivity_matprops",
29  "Material properties defining the diffusion coefficient for each species");
30  params.addParam<std::vector<MooseFunctorName>>(
31  "diffusivity_functors", "Functors specifying the diffusivity for each species");
32 
33  // Source term
34  params.addParam<std::vector<MooseFunctorName>>(
35  "source_functors", "Source terms in the diffusion problem for each species");
36  params.addParam<std::vector<Real>>("source_coefs", {1}, "Coefficient multiplying the source");
37 
38  // Boundary conditions
39  params.addParam<std::vector<std::vector<BoundaryName>>>(
40  "neumann_boundaries", {}, "Boundaries on which to apply a diffusive flux for each species");
41  params.addParam<std::vector<std::vector<BoundaryName>>>(
42  "dirichlet_boundaries", {}, "Boundaries on which to apply a fixed value for each species");
43  params.addParam<std::vector<std::vector<MooseFunctorName>>>(
44  "boundary_fluxes",
45  {},
46  "Functors to compute the diffusive flux on each Neumann boundary for each species");
47  params.addParam<std::vector<std::vector<MooseFunctorName>>>(
48  "boundary_values",
49  {},
50  "Functors to compute the diffusive flux on each Dirichlet boundary for each species");
51  params.addParamNamesToGroup("neumann_boundaries dirichlet_boundaries boundary_fluxes "
52  "boundary_values",
53  "Boundary conditions");
54 
55  // Initial conditions
56  params.addParam<std::vector<FunctionName>>(
57  "initial_conditions_species", "Functions describing the initial conditions for the species");
58 
59  // Postprocessing
60  params.addParam<std::vector<BoundaryName>>(
61  "compute_diffusive_fluxes_on", {}, "Surfaces to compute the diffusive flux on");
62 
63  // Preconditioning is implemented so let's use it by default
64  MooseEnum pc_options("default defer", "default");
65  params.addParam<MooseEnum>(
66  "preconditioning", pc_options, "Which preconditioning to use for this Physics");
67 
68  params.addParam<bool>(
69  "use_automatic_differentiation",
70  true,
71  "Whether to use automatic differentiation for all the terms in the equation");
72 
73  return params;
74 }
75 
77  const InputParameters & parameters)
78  : PhysicsBase(parameters),
79  _species_names(getParam<std::vector<VariableName>>("species")),
80  _num_species(_species_names.size()),
81  _neumann_boundaries(getParam<std::vector<std::vector<BoundaryName>>>("neumann_boundaries")),
82  _dirichlet_boundaries(getParam<std::vector<std::vector<BoundaryName>>>("dirichlet_boundaries")),
83  _use_ad(getParam<bool>("use_automatic_differentiation"))
84 {
85  // Keep track of variables
86  for (const auto & var_name : _species_names)
87  saveSolverVariableName(var_name);
88 
89  // Parameter checking
90  checkTwoDVectorParamsSameLength<BoundaryName, MooseFunctorName>("neumann_boundaries",
91  "boundary_fluxes");
92  checkTwoDVectorParamsSameLength<BoundaryName, MooseFunctorName>("dirichlet_boundaries",
93  "boundary_values");
94  checkTwoDVectorParamsNoRespectiveOverlap<BoundaryName>(
95  {"neumann_boundaries", "dirichlet_boundaries"});
96  if (isParamSetByUser("source_coefs"))
97  checkParamsBothSetOrNotSet("source_functors", "source_coefs");
98  if (isParamValid("source_functors"))
99  checkVectorParamsSameLength<VariableName, MooseFunctorName>("species", "source_functors");
100  if (isParamValid("initial_conditions_species"))
101  checkVectorParamsSameLength<VariableName, FunctionName>("species",
102  "initial_conditions_species");
103 
104  addRequiredPhysicsTask("add_preconditioning");
105  addRequiredPhysicsTask("add_ic");
106 }
107 
108 void
110 {
111  // Use a multi-grid method, known to work for elliptic problems such as diffusion
112  if (_preconditioning == "default")
113  {
114  // We only pass petsc options as that's all that's needed to set up the preconditioner
115  const auto option_pair1 =
116  std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_type"), "hypre");
117  const auto option_pair2 =
118  std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_hypre_type"), "boomeramg");
119  addPetscPairsToPetscOptions({option_pair1, option_pair2});
120  }
121 }
122 
123 void
125 {
126  for (const auto i : index_range(_species_names))
127  {
128  const auto & var_name = _species_names[i];
129  for (const auto & boundary_name :
130  getParam<std::vector<BoundaryName>>("compute_diffusive_fluxes_on"))
131  {
132  // Create the boundary integration of the flux
133  const std::string pp_type =
134  _use_ad ? "ADSideDiffusiveFluxIntegral" : "SideDiffusiveFluxIntegral";
135  auto params = _factory.getValidParams(pp_type);
136  params.set<std::vector<VariableName>>("variable") = {var_name};
137  // FE variables require matprops for this postprocessor at the moment
138  if (isParamValid("diffusivity_matprops"))
139  params.set<MaterialPropertyName>("diffusivity") =
140  getParam<std::vector<MaterialPropertyName>>("diffusivity_matprops")[i];
141  // FV variables require functors
142  else if (isParamValid("diffusivity_functors"))
143  params.set<MooseFunctorName>("functor_diffusivity") =
144  getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[i];
145  else
146  mooseError("No diffusivity parameter specified");
147  params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
148  // Default to maximum computation
149  params.set<ExecFlagEnum>("execute_on") = {
152  pp_type, prefix() + "diffusive_flux_" + var_name + "_" + boundary_name, params);
153  }
154  }
155 }
156 
157 void
159 {
160  for (const auto & block : component.blocks())
161  _blocks.push_back(block);
162 }
163 
164 void
166 {
167  InputParameters params = getFactory().getValidParams("FunctionIC");
168  assignBlocks(params, _blocks);
169 
170  // always obey the user specification of initial conditions
171  // There are no default values, so no need to consider whether the app is restarting
172  for (const auto i : index_range(_species_names))
173  {
174  const auto & var_name = _species_names[i];
175  if (isParamValid("initial_conditions_species") &&
176  shouldCreateIC(var_name,
177  _blocks,
178  /*whether IC is a default*/ false,
179  /*error if already an IC*/ true))
180  {
181  params.set<VariableName>("variable") = var_name;
182  params.set<FunctionName>("function") =
183  getParam<std::vector<FunctionName>>("initial_conditions_species")[i];
184 
185  getProblem().addInitialCondition("FunctionIC", prefix() + var_name + "_ic", params);
186  }
187  }
188 }
std::string prefix() const
void assignBlocks(InputParameters &params, const std::vector< SubdomainName > &blocks) const
Factory & getFactory()
void addRequiredPhysicsTask(const std::string &task)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addPetscPairsToPetscOptions(const std::vector< std::pair< MooseEnumItem, std::string >> &petsc_pair_options)
static const std::string component
Definition: NS.h:153
T & set(const std::string &name, bool quiet_mode=false)
InputParameters getValidParams(const std::string &name) const
const MooseEnum & _preconditioning
const ExecFlagType EXEC_TIMESTEP_END
bool shouldCreateIC(const VariableName &var_name, const std::vector< SubdomainName > &blocks, const bool ic_is_default_ic, const bool error_if_already_defined) const
std::vector< SubdomainName > _blocks
void checkParamsBothSetOrNotSet(const std::string &param1, const std::string &param2) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
bool isParamValid(const std::string &name) const
Factory & _factory
virtual void addInitialCondition(const std::string &ic_name, const std::string &name, InputParameters &parameters)
virtual FEProblemBase & getProblem()
virtual void addInitialConditions() override
Add initial conditions for each diffused variable.
virtual void addPostprocessor(const std::string &pp_name, const std::string &name, InputParameters &parameters)
const T & getParam(const std::string &name) const
MultiSpeciesDiffusionPhysicsBase(const InputParameters &parameters)
const ExecFlagType EXEC_LINEAR
void addComponent(const ActionComponent &component) override
virtual void addPreconditioning() override
Add default preconditioning options.
const std::vector< VariableName > & _species_names
Name of the diffused variables.
static InputParameters validParams()
const ExecFlagType EXEC_NONLINEAR
bool isParamSetByUser(const std::string &nm) const
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
virtual void addPostprocessors() override
Add postprocessing of the fluxes.
const bool _use_ad
Whether to use automatic differentiation or not.
void saveSolverVariableName(const VariableName &var_name)
auto index_range(const T &sizable)
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
const ExecFlagType EXEC_INITIAL