Line data Source code
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 "DiffusionPhysicsBase.h"
11 : #include "PetscSupport.h"
12 : #include "MooseEnumItem.h"
13 :
14 : InputParameters
15 692 : DiffusionPhysicsBase::validParams()
16 : {
17 692 : InputParameters params = PhysicsBase::validParams();
18 692 : params += PhysicsComponentInterface::validParams();
19 692 : params.addClassDescription("Base class for creating a diffusion equation");
20 :
21 : // Variable parameters
22 692 : params.addParam<VariableName>("variable_name", "u", "Variable name for the equation");
23 692 : params.addParam<FunctionName>("initial_condition", "Initial condition for the diffused variable");
24 :
25 : // Diffusivity
26 692 : params.addParam<MaterialPropertyName>("diffusivity_matprop",
27 : "Material property defining the diffusion coefficient");
28 692 : params.addParam<MooseFunctorName>("diffusivity_functor", "Functor specifying the diffusivity");
29 :
30 : // Source term
31 692 : params.addParam<MooseFunctorName>("source_functor", "Source term in the diffusion problem");
32 692 : params.addParam<Real>("source_coef", 1, "Coefficient multiplying the source");
33 :
34 : // Boundary conditions
35 692 : params.addParam<std::vector<BoundaryName>>(
36 : "neumann_boundaries", {}, "Boundaries on which to apply a diffusive flux");
37 692 : params.addParam<std::vector<BoundaryName>>(
38 : "dirichlet_boundaries", {}, "Boundaries on which to apply a fixed value");
39 692 : params.addParam<std::vector<MooseFunctorName>>(
40 : "boundary_fluxes", {}, "Functors to compute the diffusive flux on each Neumann boundary'");
41 692 : params.addParam<std::vector<MooseFunctorName>>(
42 : "boundary_values", {}, "Functors to compute the diffusive flux on each Dirichlet boundary'");
43 692 : params.addParamNamesToGroup("neumann_boundaries dirichlet_boundaries boundary_fluxes "
44 : "boundary_values",
45 : "Boundary conditions");
46 :
47 : // Postprocessing
48 692 : params.addParam<std::vector<BoundaryName>>(
49 : "compute_diffusive_fluxes_on", {}, "Surfaces to compute the diffusive flux on");
50 :
51 : // Preconditioning is implemented so let's use it by default
52 692 : MooseEnum pc_options("default defer", "default");
53 692 : params.addParam<MooseEnum>(
54 : "preconditioning", pc_options, "Which preconditioning to use for this Physics");
55 :
56 1384 : return params;
57 692 : }
58 :
59 286 : DiffusionPhysicsBase::DiffusionPhysicsBase(const InputParameters & parameters)
60 : : PhysicsBase(parameters),
61 : PhysicsComponentInterface(parameters),
62 286 : _var_name(getParam<VariableName>("variable_name")),
63 286 : _neumann_boundaries(getParam<std::vector<BoundaryName>>("neumann_boundaries")),
64 572 : _dirichlet_boundaries(getParam<std::vector<BoundaryName>>("dirichlet_boundaries"))
65 : {
66 : // Keep track of variables
67 286 : saveSolverVariableName(_var_name);
68 :
69 : // Parameter checking
70 286 : checkVectorParamsSameLength<BoundaryName, MooseFunctorName>("neumann_boundaries",
71 : "boundary_fluxes");
72 286 : checkVectorParamsSameLength<BoundaryName, MooseFunctorName>("dirichlet_boundaries",
73 : "boundary_values");
74 858 : checkVectorParamsNoOverlap<BoundaryName>({"neumann_boundaries", "dirichlet_boundaries"});
75 286 : if (isParamSetByUser("source_coef"))
76 136 : checkParamsBothSetOrNotSet("source_functor", "source_coef");
77 :
78 286 : addRequiredPhysicsTask("add_preconditioning");
79 286 : addRequiredPhysicsTask("add_postprocessor");
80 858 : }
81 :
82 : void
83 238 : DiffusionPhysicsBase::addPreconditioning()
84 : {
85 : // Use a multigrid method, known to work for elliptic problems such as diffusion
86 238 : if (_preconditioning == "default")
87 : {
88 : // We only pass petsc options as that's all that's needed to set up the preconditioner
89 : const auto option_pair1 =
90 238 : std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_type"), "hypre");
91 : const auto option_pair2 =
92 238 : std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_hypre_type"), "boomeramg");
93 714 : addPetscPairsToPetscOptions({option_pair1, option_pair2});
94 238 : }
95 476 : }
96 :
97 : void
98 238 : DiffusionPhysicsBase::addPostprocessors()
99 : {
100 238 : for (const auto & boundary_name :
101 489 : getParam<std::vector<BoundaryName>>("compute_diffusive_fluxes_on"))
102 : {
103 : // Create the boundary integration of the flux
104 26 : const bool use_ad = isParamValid("use_automatic_differentiation")
105 26 : ? getParam<bool>("use_automatic_differentiation")
106 13 : : false;
107 : const std::string pp_type =
108 13 : use_ad ? "ADSideDiffusiveFluxIntegral" : "SideDiffusiveFluxIntegral";
109 13 : auto params = _factory.getValidParams(pp_type);
110 26 : params.set<std::vector<VariableName>>("variable") = {_var_name};
111 13 : if (isParamValid("diffusivity_matprop"))
112 26 : params.set<MaterialPropertyName>("diffusivity") =
113 39 : getParam<MaterialPropertyName>("diffusivity_matprop");
114 0 : else if (isParamValid("diffusivity_functor"))
115 0 : params.set<MooseFunctorName>("functor_diffusivity") =
116 0 : getParam<MooseFunctorName>("diffusivity_functor");
117 : else
118 0 : params.set<MooseFunctorName>("functor_diffusivity") = "1";
119 26 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
120 : // Default to maximum computation
121 26 : params.set<ExecFlagEnum>("execute_on") = {
122 78 : EXEC_INITIAL, EXEC_TIMESTEP_END, EXEC_NONLINEAR, EXEC_LINEAR};
123 13 : getProblem().addPostprocessor(pp_type, prefix() + "diffusive_flux_" + boundary_name, params);
124 13 : }
125 277 : }
126 :
127 : void
128 242 : DiffusionPhysicsBase::addInitialConditions()
129 : {
130 242 : InputParameters params = getFactory().getValidParams("FunctionIC");
131 :
132 : // Get the list of blocks that have ics from components
133 242 : std::vector<SubdomainName> component_ic_blocks;
134 340 : for (const auto & [component_name, component_bc_map] : _components_initial_conditions)
135 : {
136 98 : if (!component_bc_map.count(_var_name))
137 0 : continue;
138 98 : const auto & comp_blocks = getActionComponent(component_name).blocks();
139 98 : component_ic_blocks.insert(component_ic_blocks.end(), comp_blocks.begin(), comp_blocks.end());
140 : }
141 :
142 : // Keep only blocks that have no component IC
143 242 : std::vector<SubdomainName> remaining_blocks;
144 625 : for (const auto & block : _blocks)
145 383 : if (std::find(component_ic_blocks.begin(), component_ic_blocks.end(), block) ==
146 766 : component_ic_blocks.end())
147 251 : remaining_blocks.push_back(block);
148 :
149 : // No need to add BCs on the Physics block restriction if Components are covering all of it
150 242 : if (remaining_blocks.empty())
151 34 : return;
152 208 : assignBlocks(params, remaining_blocks);
153 :
154 : // first obey any component-specific initial condition
155 : // then obey the user specification of initial conditions
156 : // NOTE: we may conflict with ICs in the input
157 : // there are no default initial conditions
158 : mooseAssert(parameters().isParamSetByUser("initial_condition") ||
159 : !parameters().hasDefault("initial_condition"),
160 : "Should not have a default");
161 208 : if (isParamValid("initial_condition") &&
162 4 : shouldCreateIC(
163 : _var_name, remaining_blocks, /*ic is a default*/ false, /*error if defined*/ true))
164 : {
165 0 : params.set<VariableName>("variable") = _var_name;
166 0 : params.set<FunctionName>("function") = getParam<FunctionName>("initial_condition");
167 :
168 0 : getProblem().addInitialCondition("FunctionIC", prefix() + _var_name + "_ic", params);
169 : }
170 306 : }
171 :
172 : void
173 242 : DiffusionPhysicsBase::addInitialConditionsFromComponents()
174 : {
175 242 : InputParameters params = getFactory().getValidParams("FunctorIC");
176 :
177 : // ICs from components are considered always set by the user, so we do not skip them when
178 : // restarting
179 340 : for (const auto & [component_name, component_bc_map] : _components_initial_conditions)
180 : {
181 98 : if (!component_bc_map.count(_var_name))
182 0 : continue;
183 98 : assignBlocks(params, getActionComponent(component_name).blocks());
184 98 : params.set<VariableName>("variable") = _var_name;
185 98 : params.set<MooseFunctorName>("functor") = libmesh_map_find(component_bc_map, _var_name);
186 :
187 196 : getProblem().addInitialCondition(
188 196 : "FunctorIC", prefix() + _var_name + "_ic_" + component_name, params);
189 : }
190 242 : }
|