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