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 : // 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 : registerMooseObject("MooseApp", Split);
19 :
20 : InputParameters
21 15079 : Split::validParams()
22 : {
23 15079 : InputParameters params = MooseObject::validParams();
24 15079 : params.addClassDescription("Field split based preconditioner for nonlinear solver.");
25 15079 : params.addParam<std::vector<NonlinearVariableName>>(
26 : "vars", {}, "Variables Split operates on (omitting this implies \"all variables\"");
27 15079 : params.addParam<std::vector<SubdomainName>>(
28 : "blocks", {}, "Mesh blocks Split operates on (omitting this implies \"all blocks\"");
29 15079 : params.addParam<std::vector<BoundaryName>>(
30 : "sides", {}, "Sidesets Split operates on (omitting this implies \"all sidesets\")");
31 15079 : params.addParam<std::vector<BoundaryName>>(
32 : "unsides",
33 : {},
34 : "Sidesets Split excludes (omitting this implies \"do not exclude any sidesets\")");
35 15079 : params.addParam<std::vector<std::string>>(
36 : "splitting", {}, "The names of the splits (subsystems) in the decomposition of this split");
37 15079 : params.addParam<std::vector<BoundaryName>>(
38 : "unside_by_var_boundary_name",
39 : "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
40 15079 : params.addParam<std::vector<NonlinearVariableName>>(
41 : "unside_by_var_var_name",
42 : "A map from boundary name to unside by variable, e.g. only unside for a given variable.");
43 15079 : params.addParamNamesToGroup("sides unsides unside_by_var_boundary_name unside_by_var_var_name",
44 : "Sideset restriction");
45 :
46 15079 : MooseEnum SplittingTypeEnum("additive multiplicative symmetric_multiplicative schur", "additive");
47 15079 : params.addParam<MooseEnum>("splitting_type", SplittingTypeEnum, "Split decomposition type");
48 :
49 15079 : MooseEnum SchurTypeEnum("diag upper lower full", "full");
50 15079 : params.addParam<MooseEnum>("schur_type", SchurTypeEnum, "Type of Schur complement");
51 :
52 : /**
53 : * Which preconditioning matrix to use with S = D - CA^{-1}B
54 : * 'Self' means use S to build the preconditioner.
55 : * limited choices here: PCNONE and PCLSC in PETSc
56 : * 'D' means the lower-right block in splitting J = [A B; C D]
57 : */
58 15079 : MooseEnum SchurPreEnum("S Sp A11", "S");
59 15079 : params.addParam<MooseEnum>(
60 : "schur_pre", SchurPreEnum, "Type of Schur complement preconditioner matrix");
61 :
62 45237 : params.addParam<MultiMooseEnum>("petsc_options",
63 30158 : Moose::PetscSupport::getCommonPetscFlags(),
64 : "PETSc flags for the FieldSplit solver");
65 45237 : params.addParam<MultiMooseEnum>("petsc_options_iname",
66 30158 : Moose::PetscSupport::getCommonPetscKeys(),
67 : "PETSc option names for the FieldSplit solver");
68 15079 : params.addParam<std::vector<std::string>>("petsc_options_value",
69 : "PETSc option values for the FieldSplit solver");
70 :
71 15079 : params.registerBase("Split");
72 15079 : params.registerSystemAttributeName("Split");
73 30158 : return params;
74 15079 : }
75 :
76 407 : Split::Split(const InputParameters & parameters)
77 : : MooseObject(parameters),
78 : Restartable(this, "Splits"),
79 407 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
80 407 : _vars(getParam<std::vector<NonlinearVariableName>>("vars")),
81 407 : _blocks(getParam<std::vector<SubdomainName>>("blocks")),
82 407 : _sides(getParam<std::vector<BoundaryName>>("sides")),
83 407 : _unsides(getParam<std::vector<BoundaryName>>("unsides")),
84 407 : _splitting(getParam<std::vector<std::string>>("splitting")),
85 407 : _splitting_type(getParam<MooseEnum>("splitting_type")),
86 407 : _schur_type(getParam<MooseEnum>("schur_type")),
87 814 : _schur_pre(getParam<MooseEnum>("schur_pre"))
88 : {
89 407 : }
90 :
91 : void
92 407 : Split::setup(NonlinearSystemBase & nl, const std::string & prefix)
93 : {
94 : // The Split::setup() implementation does not actually depend on any
95 : // specific version of PETSc, so there's no need to wrap the entire
96 : // function.
97 :
98 : // A reference to the PetscOptions
99 407 : Moose::PetscSupport::PetscOptions & po = _fe_problem.getPetscOptions();
100 : // prefix
101 407 : std::string dmprefix = prefix + "dm_moose_";
102 :
103 407 : if (isParamValid("unside_by_var_boundary_name"))
104 : {
105 : const auto & unside_by_var_boundary_name =
106 13 : getParam<std::vector<BoundaryName>>("unside_by_var_boundary_name");
107 : const auto & unside_by_var_var_name =
108 13 : getParam<std::vector<NonlinearVariableName>>("unside_by_var_var_name");
109 :
110 13 : std::vector<std::string> vector_of_pairs;
111 39 : for (const auto i : index_range(unside_by_var_boundary_name))
112 26 : vector_of_pairs.push_back(unside_by_var_boundary_name[i] + ":" + unside_by_var_var_name[i]);
113 13 : po.pairs.emplace_back(dmprefix + "unside_by_var", Moose::stringify(vector_of_pairs, ","));
114 13 : }
115 :
116 : // var options
117 407 : if (!_vars.empty())
118 : {
119 281 : po.pairs.emplace_back(dmprefix + "vars", Moose::stringify(_vars, ","));
120 :
121 : // check that variables are either field or scalars
122 562 : for (const auto & var : _vars)
123 281 : if (!_fe_problem.hasVariable(var) && !_fe_problem.hasScalarVariable(var))
124 0 : mooseError("Variable '", var, "' specified in split '", name(), "' does not exist");
125 : }
126 :
127 : // block options
128 407 : if (!_blocks.empty())
129 0 : po.pairs.emplace_back(dmprefix + "blocks", Moose::stringify(_blocks, ","));
130 :
131 : // side options
132 407 : if (!_sides.empty())
133 47 : po.pairs.emplace_back(dmprefix + "sides", Moose::stringify(_sides, ","));
134 :
135 : // unside options
136 407 : if (!_unsides.empty())
137 34 : po.pairs.emplace_back(dmprefix + "unsides", Moose::stringify(_unsides, ","));
138 :
139 407 : if (!_splitting.empty())
140 : {
141 : // If this split has subsplits, it is presumed that the pc_type used to solve this split's
142 : // subsystem is fieldsplit
143 : // with the following parameters (unless overridden by the user-specified petsc_options below).
144 147 : po.pairs.emplace_back(prefix + "pc_type", "fieldsplit");
145 :
146 : // set Splitting Type
147 : const std::string petsc_splitting_type[] = {
148 882 : "additive", "multiplicative", "symmetric_multiplicative", "schur"};
149 147 : po.pairs.emplace_back(prefix + "pc_fieldsplit_type", petsc_splitting_type[_splitting_type]);
150 :
151 147 : if (_splitting_type == SplittingTypeSchur)
152 : {
153 : // set Schur Type
154 0 : const std::string petsc_schur_type[] = {"diag", "upper", "lower", "full"};
155 0 : po.pairs.emplace_back(prefix + "pc_fieldsplit_schur_fact_type",
156 0 : petsc_schur_type[_schur_type]);
157 :
158 : // set Schur Preconditioner
159 0 : const std::string petsc_schur_pre[] = {"self", "selfp", "a11"};
160 0 : po.pairs.emplace_back(prefix + "pc_fieldsplit_schur_precondition",
161 0 : petsc_schur_pre[_schur_pre]);
162 0 : }
163 :
164 : // The DM associated with this split defines the subsplits' geometry.
165 147 : po.pairs.emplace_back(dmprefix + "nfieldsplits", Moose::stringify(_splitting.size()));
166 147 : po.pairs.emplace_back(dmprefix + "fieldsplit_names", Moose::stringify(_splitting, ","));
167 :
168 : // Finally, recursively configure the splits contained within this split.
169 441 : for (const auto & split_name : _splitting)
170 : {
171 294 : std::shared_ptr<Split> split = nl.getSplit(split_name);
172 294 : std::string sprefix = prefix + "fieldsplit_" + split_name + "_";
173 294 : split->setup(nl, sprefix);
174 294 : }
175 735 : }
176 :
177 : // Now we set the user-specified petsc options for this split, possibly overriding the above
178 : // settings.
179 407 : Moose::PetscSupport::storePetscOptions(_fe_problem, prefix, *this);
180 407 : }
|