https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Split.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
10// MOOSE includes
11#include "Split.h"
12#include "InputParameters.h"
13#include "PetscSupport.h"
14#include "FEProblem.h"
15#include "Conversion.h"
16#include "NonlinearSystem.h"
17
18#include <algorithm>
19
21
24{
26 params.addClassDescription("Field split based preconditioner for nonlinear solver.");
27 params.addParam<std::vector<NonlinearVariableName>>(
28 "vars", {}, "Variables Split operates on (omitting this implies \"all variables\"");
29 params.addParam<std::vector<SubdomainName>>(
30 "blocks", {}, "Mesh blocks Split operates on (omitting this implies \"all blocks\"");
31 params.addParam<std::vector<BoundaryName>>(
32 "sides", {}, "Sidesets Split operates on (omitting this implies \"all sidesets\")");
33 params.addParam<std::vector<BoundaryName>>(
34 "unsides",
35 {},
36 "Sidesets Split excludes (omitting this implies \"do not exclude any sidesets\")");
37 params.addParam<std::vector<std::string>>(
38 "splitting", {}, "The names of the splits (subsystems) in the decomposition of this split");
39 params.addParam<std::vector<BoundaryName>>(
40 "unside_by_var_boundary_name",
41 "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
42 params.addParam<std::vector<NonlinearVariableName>>(
43 "unside_by_var_var_name",
44 "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
45 params.addParamNamesToGroup("sides unsides unside_by_var_boundary_name unside_by_var_var_name",
46 "Sideset restriction");
47
48 MooseEnum SplittingTypeEnum("additive multiplicative symmetric_multiplicative schur", "additive");
49 params.addParam<MooseEnum>("splitting_type", SplittingTypeEnum, "Split decomposition type");
50
51 MooseEnum SchurTypeEnum("diag upper lower full", "full");
52 params.addParam<MooseEnum>("schur_type", SchurTypeEnum, "Type of Schur complement");
53
60 MooseEnum SchurPreEnum("S Sp A11", "S");
61 params.addParam<MooseEnum>(
62 "schur_pre", SchurPreEnum, "Type of Schur complement preconditioner matrix");
63
64 params.addParam<MultiMooseEnum>("petsc_options",
66 "PETSc flags for the FieldSplit solver");
67 params.addParam<MultiMooseEnum>("petsc_options_iname",
69 "PETSc option names for the FieldSplit solver");
70 params.addParam<std::vector<std::string>>("petsc_options_value",
71 "PETSc option values for the FieldSplit solver");
72
73 params.registerBase("Split");
74 params.registerSystemAttributeName("Split");
75 return params;
76}
77
78Split::Split(const InputParameters & parameters)
79 : MooseObject(parameters),
80 Restartable(this, "Splits"),
81 _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
82 _vars(getParam<std::vector<NonlinearVariableName>>("vars")),
83 _blocks(getParam<std::vector<SubdomainName>>("blocks")),
84 _sides(getParam<std::vector<BoundaryName>>("sides")),
85 _unsides(getParam<std::vector<BoundaryName>>("unsides")),
86 _splitting(getParam<std::vector<std::string>>("splitting")),
87 _splitting_type(getParam<MooseEnum>("splitting_type")),
88 _schur_type(getParam<MooseEnum>("schur_type")),
89 _schur_pre(getParam<MooseEnum>("schur_pre"))
90{
91}
92
93void
94Split::setup(NonlinearSystemBase & nl, const std::string & prefix)
95{
96 // The Split::setup() implementation does not actually depend on any
97 // specific version of PETSc, so there's no need to wrap the entire
98 // function.
99
100 // A reference to the PetscOptions
102 // prefix
103 const std::string prefix_with_dash = '-' + prefix;
104 std::string dmprefix = prefix_with_dash + "dm_moose_";
105
106 if (isParamValid("unside_by_var_boundary_name"))
107 {
108 const auto & unside_by_var_boundary_name =
109 getParam<std::vector<BoundaryName>>("unside_by_var_boundary_name");
110 const auto & unside_by_var_var_name =
111 getParam<std::vector<NonlinearVariableName>>("unside_by_var_var_name");
112
113 std::vector<std::string> vector_of_pairs;
114 for (const auto i : index_range(unside_by_var_boundary_name))
115 vector_of_pairs.push_back(unside_by_var_boundary_name[i] + ":" + unside_by_var_var_name[i]);
116 po.pairs.emplace_back(dmprefix + "unside_by_var", Moose::stringify(vector_of_pairs, ","));
117 }
118
119 // var options
120 if (!_vars.empty())
121 {
122 po.pairs.emplace_back(dmprefix + "vars", Moose::stringify(_vars, ","));
123
124 // check that variables are either field or scalars
125 for (const auto & var : _vars)
127 mooseError("Variable '", var, "' specified in split '", name(), "' does not exist");
128 }
129
130 // block options
131 if (!_blocks.empty())
132 po.pairs.emplace_back(dmprefix + "blocks", Moose::stringify(_blocks, ","));
133
134 // side options
135 if (!_sides.empty())
136 po.pairs.emplace_back(dmprefix + "sides", Moose::stringify(_sides, ","));
137
138 // unside options
139 if (!_unsides.empty())
140 po.pairs.emplace_back(dmprefix + "unsides", Moose::stringify(_unsides, ","));
141
142 if (!_splitting.empty())
143 {
144 // If this split has subsplits, it is presumed that the pc_type used to solve this split's
145 // subsystem is fieldsplit
146 // with the following parameters (unless overridden by the user-specified petsc_options below).
147 po.pairs.emplace_back(prefix_with_dash + "pc_type", "fieldsplit");
148
149 // set Splitting Type
150 const std::string petsc_splitting_type[] = {
151 "additive", "multiplicative", "symmetric_multiplicative", "schur"};
152 po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_type",
153 petsc_splitting_type[_splitting_type]);
154
156 {
157 // set Schur Type
158 const std::string petsc_schur_type[] = {"diag", "upper", "lower", "full"};
159 po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_schur_fact_type",
160 petsc_schur_type[_schur_type]);
161
162 // set Schur Preconditioner
163 const std::string petsc_schur_pre[] = {"self", "selfp", "a11"};
164 po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_schur_precondition",
165 petsc_schur_pre[_schur_pre]);
166 }
167
168 // The DM associated with this split defines the subsplits' geometry.
169 po.pairs.emplace_back(dmprefix + "nfieldsplits", Moose::stringify(_splitting.size()));
170 po.pairs.emplace_back(dmprefix + "fieldsplit_names", Moose::stringify(_splitting, ","));
171
172 // Finally, recursively configure the splits contained within this split.
173 std::map<NonlinearVariableName, std::vector<std::pair<std::string, std::shared_ptr<Split>>>>
174 vars_to_splits;
175 for (const auto & split_name : _splitting)
176 {
177 std::shared_ptr<Split> split = nl.getSplit(split_name);
178
179 // Make sure no two sibling splits explicitly claim the same variable in a way that would
180 // leave at most one of them actually preconditioning it. Two splits sharing a variable are
181 // only known to be safe if they are both restricted to disjoint regions; we can only prove
182 // that when both restrict via non-overlapping "blocks" (blocks partition the mesh, so any
183 // shared block name means the splits overlap). An unrestricted split applies to the whole
184 // mesh, so it conflicts with any sibling that claims the same variable, however that
185 // sibling restricts itself. Restrictions we cannot compare this way (sides/unsides, or
186 // subclass-specific mechanisms like ContactSplit's contact/uncontact surfaces) are assumed
187 // to legitimately partition the variable, as before.
188 for (const auto & var : split->getVars())
189 {
190 auto & prior_claims = vars_to_splits[var];
191 for (const auto & [prior_name, prior_split] : prior_claims)
192 {
193 const auto & blocks = split->getBlocks();
194 const auto & prior_blocks = prior_split->getBlocks();
195 const bool blocks_overlap =
196 !blocks.empty() && !prior_blocks.empty() &&
197 std::any_of(blocks.begin(),
198 blocks.end(),
199 [&prior_blocks](const auto & block)
200 {
201 return std::find(prior_blocks.begin(), prior_blocks.end(), block) !=
202 prior_blocks.end();
203 });
204 if (!split->restrictsRegion() || !prior_split->restrictsRegion() || blocks_overlap)
205 mooseError("Variable '",
206 var,
207 "' is specified in both split '",
208 prior_name,
209 "' and split '",
210 split_name,
211 "', which are both part of split '",
212 name(),
213 "'");
214 }
215 prior_claims.emplace_back(split_name, split);
216 }
217
218 std::string sprefix = prefix + "fieldsplit_" + split_name + "_";
219 split->setup(nl, sprefix);
220 }
221 }
222
223 // Now we set the user-specified petsc options for this split, possibly overriding the above
224 // settings.
226}
char ** blocks
registerMooseObject("MooseApp", Split)
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual bool hasScalarVariable(const std::string &var_name) const override
Returns a Boolean indicating whether any system contains a variable with the name provided.
virtual bool hasVariable(const std::string &var_name) const override
Whether or not this problem has the variable.
Moose::PetscSupport::PetscOptions & getPetscOptions()
Retrieve a writable reference the PETSc options (used by PetscSupport)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void registerSystemAttributeName(const std::string &value)
This method is used to define the MOOSE system name that is used by the TheWarehouse object for stori...
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
static InputParameters validParams()
Definition MooseObject.C:25
A struct for storing the various types of petsc options and values.
std::vector< std::pair< std::string, std::string > > pairs
PETSc key-value pairs.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type.
Nonlinear system to be solved.
std::shared_ptr< Split > getSplit(const std::string &name)
Retrieves a split by name.
A class for creating restricted objects.
Definition Restartable.h:29
Base class for split-based preconditioners.
Definition Split.h:26
Split(const InputParameters &parameters)
Definition Split.C:78
std::vector< BoundaryName > _sides
Definition Split.h:67
static InputParameters validParams()
Definition Split.C:23
MooseEnum _schur_pre
Definition Split.h:78
virtual void setup(NonlinearSystemBase &nl, const std::string &prefix="")
Definition Split.C:94
MooseEnum _splitting_type
Definition Split.h:76
std::vector< NonlinearVariableName > _vars
"Variables Split operates on
Definition Split.h:62
MooseEnum _schur_type
Definition Split.h:77
std::vector< SubdomainName > _blocks
Definition Split.h:66
@ SplittingTypeSchur
Definition Split.h:56
std::vector< BoundaryName > _unsides
Definition Split.h:68
FEProblemBase & _fe_problem
Definition Split.h:59
std::vector< std::string > _splitting
Split subsystem list.
Definition Split.h:72
MultiMooseEnum getCommonPetscFlags()
A helper function to produce a MultiMooseEnum with commonly used PETSc single options (flags)
void storePetscOptions(FEProblemBase &fe_problem, const std::string &prefix, const ParallelParamObject &param_object)
Stores the PETSc options supplied from the parameter object on the problem.
MultiMooseEnum getCommonPetscKeys()
A helper function to produce a MultiMooseEnum with commonly used PETSc iname options (keys in key-val...
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65