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 676 : DiffusionPhysicsBase::validParams()
16 : {
17 676 : InputParameters params = PhysicsBase::validParams();
18 676 : params += PhysicsComponentInterface::validParams();
19 676 : params.addClassDescription("Base class for creating a diffusion equation");
20 :
21 : // Variable parameters
22 676 : params.addParam<VariableName>("variable_name", "u", "Variable name for the equation");
23 676 : params.addParam<FunctionName>("initial_condition", "Initial condition for the diffused variable");
24 :
25 : // Diffusivity
26 676 : params.addParam<MaterialPropertyName>("diffusivity_matprop",
27 : "Material property defining the diffusion coefficient");
28 676 : params.addParam<MooseFunctorName>("diffusivity_functor", "Functor specifying the diffusivity");
29 :
30 : // Source term
31 676 : params.addParam<MooseFunctorName>("source_functor", "Source term in the diffusion problem");
32 676 : params.addParam<Real>("source_coef", 1, "Coefficient multiplying the source");
33 :
34 : // Boundary conditions
35 676 : params.addParam<std::vector<BoundaryName>>(
36 : "neumann_boundaries", {}, "Boundaries on which to apply a diffusive flux");
37 676 : params.addParam<std::vector<BoundaryName>>(
38 : "dirichlet_boundaries", {}, "Boundaries on which to apply a fixed value");
39 676 : params.addParam<std::vector<MooseFunctorName>>(
40 : "boundary_fluxes", {}, "Functors to compute the diffusive flux on each Neumann boundary'");
41 676 : params.addParam<std::vector<MooseFunctorName>>(
42 : "boundary_values", {}, "Functors to compute the diffusive flux on each Dirichlet boundary'");
43 676 : params.addParamNamesToGroup("neumann_boundaries dirichlet_boundaries boundary_fluxes "
44 : "boundary_values",
45 : "Boundary conditions");
46 :
47 : // Postprocessing
48 676 : 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 676 : MooseEnum pc_options("default none", "default");
53 676 : params.addParam<MooseEnum>(
54 : "preconditioning", pc_options, "Which preconditioning to use for this Physics");
55 :
56 1352 : return params;
57 676 : }
58 :
59 270 : DiffusionPhysicsBase::DiffusionPhysicsBase(const InputParameters & parameters)
60 : : PhysicsBase(parameters),
61 : PhysicsComponentInterface(parameters),
62 270 : _var_name(getParam<VariableName>("variable_name")),
63 270 : _neumann_boundaries(getParam<std::vector<BoundaryName>>("neumann_boundaries")),
64 540 : _dirichlet_boundaries(getParam<std::vector<BoundaryName>>("dirichlet_boundaries"))
65 : {
66 : // Keep track of variables
67 270 : saveSolverVariableName(_var_name);
68 :
69 : // Parameter checking
70 270 : checkVectorParamsSameLength<BoundaryName, MooseFunctorName>("neumann_boundaries",
71 : "boundary_fluxes");
72 270 : checkVectorParamsSameLength<BoundaryName, MooseFunctorName>("dirichlet_boundaries",
73 : "boundary_values");
74 810 : checkVectorParamsNoOverlap<BoundaryName>({"neumann_boundaries", "dirichlet_boundaries"});
75 270 : if (isParamSetByUser("source_coef"))
76 128 : checkParamsBothSetOrNotSet("source_functor", "source_coef");
77 :
78 270 : addRequiredPhysicsTask("add_preconditioning");
79 270 : addRequiredPhysicsTask("add_postprocessor");
80 810 : }
81 :
82 : void
83 222 : DiffusionPhysicsBase::addPreconditioning()
84 : {
85 : // Use a multigrid method, known to work for elliptic problems such as diffusion
86 222 : 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 222 : std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_type"), "hypre");
91 : const auto option_pair2 =
92 222 : std::make_pair<MooseEnumItem, std::string>(MooseEnumItem("-pc_hypre_type"), "boomeramg");
93 666 : addPetscPairsToPetscOptions({option_pair1, option_pair2});
94 222 : }
95 444 : }
96 :
97 : void
98 222 : DiffusionPhysicsBase::addPostprocessors()
99 : {
100 222 : for (const auto & boundary_name :
101 456 : getParam<std::vector<BoundaryName>>("compute_diffusive_fluxes_on"))
102 : {
103 : // Create the boundary integration of the flux
104 24 : const bool use_ad = isParamValid("use_automatic_differentiation")
105 24 : ? getParam<bool>("use_automatic_differentiation")
106 12 : : false;
107 : const std::string pp_type =
108 12 : use_ad ? "ADSideDiffusiveFluxIntegral" : "SideDiffusiveFluxIntegral";
109 12 : auto params = _factory.getValidParams(pp_type);
110 24 : params.set<std::vector<VariableName>>("variable") = {_var_name};
111 12 : if (isParamValid("diffusivity_matprop"))
112 24 : params.set<MaterialPropertyName>("diffusivity") =
113 36 : 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 24 : params.set<std::vector<BoundaryName>>("boundary") = {boundary_name};
120 : // Default to maximum computation
121 24 : params.set<ExecFlagEnum>("execute_on") = {
122 72 : EXEC_INITIAL, EXEC_TIMESTEP_END, EXEC_NONLINEAR, EXEC_LINEAR};
123 12 : getProblem().addPostprocessor(pp_type, prefix() + "diffusive_flux_" + boundary_name, params);
124 12 : }
125 258 : }
126 :
127 : void
128 226 : DiffusionPhysicsBase::addInitialConditions()
129 : {
130 226 : InputParameters params = getFactory().getValidParams("FunctionIC");
131 :
132 : // Get the list of blocks that have ics from components
133 226 : std::vector<SubdomainName> component_ic_blocks;
134 318 : for (const auto & [component_name, component_bc_map] : _components_initial_conditions)
135 : {
136 92 : if (!component_bc_map.count(_var_name))
137 0 : continue;
138 92 : const auto & comp_blocks = getActionComponent(component_name).blocks();
139 92 : 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 226 : std::vector<SubdomainName> remaining_blocks;
144 584 : for (const auto & block : _blocks)
145 358 : if (std::find(component_ic_blocks.begin(), component_ic_blocks.end(), block) ==
146 716 : component_ic_blocks.end())
147 234 : 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 226 : if (remaining_blocks.empty())
151 32 : return;
152 194 : 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 194 : 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 286 : }
171 :
172 : void
173 226 : DiffusionPhysicsBase::addInitialConditionsFromComponents()
174 : {
175 226 : 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 318 : for (const auto & [component_name, component_bc_map] : _components_initial_conditions)
180 : {
181 92 : if (!component_bc_map.count(_var_name))
182 0 : continue;
183 92 : assignBlocks(params, getActionComponent(component_name).blocks());
184 92 : params.set<VariableName>("variable") = _var_name;
185 92 : params.set<MooseFunctorName>("functor") = libmesh_map_find(component_bc_map, _var_name);
186 :
187 184 : getProblem().addInitialCondition(
188 184 : "FunctorIC", prefix() + _var_name + "_ic_" + component_name, params);
189 : }
190 226 : }
|