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 15235 : Split::validParams()
22 : {
23 15235 : InputParameters params = MooseObject::validParams();
24 30470 : params.addClassDescription("Field split based preconditioner for nonlinear solver.");
25 60940 : params.addParam<std::vector<NonlinearVariableName>>(
26 : "vars", {}, "Variables Split operates on (omitting this implies \"all variables\"");
27 60940 : params.addParam<std::vector<SubdomainName>>(
28 : "blocks", {}, "Mesh blocks Split operates on (omitting this implies \"all blocks\"");
29 60940 : params.addParam<std::vector<BoundaryName>>(
30 : "sides", {}, "Sidesets Split operates on (omitting this implies \"all sidesets\")");
31 60940 : params.addParam<std::vector<BoundaryName>>(
32 : "unsides",
33 : {},
34 : "Sidesets Split excludes (omitting this implies \"do not exclude any sidesets\")");
35 60940 : params.addParam<std::vector<std::string>>(
36 : "splitting", {}, "The names of the splits (subsystems) in the decomposition of this split");
37 60940 : 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 60940 : 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 60940 : params.addParamNamesToGroup("sides unsides unside_by_var_boundary_name unside_by_var_var_name",
44 : "Sideset restriction");
45 :
46 60940 : MooseEnum SplittingTypeEnum("additive multiplicative symmetric_multiplicative schur", "additive");
47 60940 : params.addParam<MooseEnum>("splitting_type", SplittingTypeEnum, "Split decomposition type");
48 :
49 60940 : MooseEnum SchurTypeEnum("diag upper lower full", "full");
50 60940 : 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 60940 : MooseEnum SchurPreEnum("S Sp A11", "S");
59 60940 : params.addParam<MooseEnum>(
60 : "schur_pre", SchurPreEnum, "Type of Schur complement preconditioner matrix");
61 :
62 45705 : params.addParam<MultiMooseEnum>("petsc_options",
63 30470 : Moose::PetscSupport::getCommonPetscFlags(),
64 : "PETSc flags for the FieldSplit solver");
65 45705 : params.addParam<MultiMooseEnum>("petsc_options_iname",
66 30470 : Moose::PetscSupport::getCommonPetscKeys(),
67 : "PETSc option names for the FieldSplit solver");
68 60940 : params.addParam<std::vector<std::string>>("petsc_options_value",
69 : "PETSc option values for the FieldSplit solver");
70 :
71 30470 : params.registerBase("Split");
72 15235 : params.registerSystemAttributeName("Split");
73 30470 : return params;
74 15235 : }
75 :
76 485 : Split::Split(const InputParameters & parameters)
77 : : MooseObject(parameters),
78 : Restartable(this, "Splits"),
79 1455 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
80 970 : _vars(getParam<std::vector<NonlinearVariableName>>("vars")),
81 970 : _blocks(getParam<std::vector<SubdomainName>>("blocks")),
82 970 : _sides(getParam<std::vector<BoundaryName>>("sides")),
83 970 : _unsides(getParam<std::vector<BoundaryName>>("unsides")),
84 970 : _splitting(getParam<std::vector<std::string>>("splitting")),
85 970 : _splitting_type(getParam<MooseEnum>("splitting_type")),
86 970 : _schur_type(getParam<MooseEnum>("schur_type")),
87 2425 : _schur_pre(getParam<MooseEnum>("schur_pre"))
88 : {
89 485 : }
90 :
91 : void
92 485 : 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 485 : Moose::PetscSupport::PetscOptions & po = _fe_problem.getPetscOptions();
100 : // prefix
101 485 : const std::string prefix_with_dash = '-' + prefix;
102 485 : std::string dmprefix = prefix_with_dash + "dm_moose_";
103 :
104 1455 : if (isParamValid("unside_by_var_boundary_name"))
105 : {
106 : const auto & unside_by_var_boundary_name =
107 26 : getParam<std::vector<BoundaryName>>("unside_by_var_boundary_name");
108 : const auto & unside_by_var_var_name =
109 26 : getParam<std::vector<NonlinearVariableName>>("unside_by_var_var_name");
110 :
111 13 : std::vector<std::string> vector_of_pairs;
112 39 : for (const auto i : index_range(unside_by_var_boundary_name))
113 26 : vector_of_pairs.push_back(unside_by_var_boundary_name[i] + ":" + unside_by_var_var_name[i]);
114 52 : po.pairs.emplace_back(dmprefix + "unside_by_var", Moose::stringify(vector_of_pairs, ","));
115 13 : }
116 :
117 : // var options
118 485 : if (!_vars.empty())
119 : {
120 1332 : po.pairs.emplace_back(dmprefix + "vars", Moose::stringify(_vars, ","));
121 :
122 : // check that variables are either field or scalars
123 666 : for (const auto & var : _vars)
124 333 : if (!_fe_problem.hasVariable(var) && !_fe_problem.hasScalarVariable(var))
125 0 : mooseError("Variable '", var, "' specified in split '", name(), "' does not exist");
126 : }
127 :
128 : // block options
129 485 : if (!_blocks.empty())
130 0 : po.pairs.emplace_back(dmprefix + "blocks", Moose::stringify(_blocks, ","));
131 :
132 : // side options
133 485 : if (!_sides.empty())
134 235 : po.pairs.emplace_back(dmprefix + "sides", Moose::stringify(_sides, ","));
135 :
136 : // unside options
137 485 : if (!_unsides.empty())
138 170 : po.pairs.emplace_back(dmprefix + "unsides", Moose::stringify(_unsides, ","));
139 :
140 485 : if (!_splitting.empty())
141 : {
142 : // If this split has subsplits, it is presumed that the pc_type used to solve this split's
143 : // subsystem is fieldsplit
144 : // with the following parameters (unless overridden by the user-specified petsc_options below).
145 173 : po.pairs.emplace_back(prefix_with_dash + "pc_type", "fieldsplit");
146 :
147 : // set Splitting Type
148 : const std::string petsc_splitting_type[] = {
149 1211 : "additive", "multiplicative", "symmetric_multiplicative", "schur"};
150 173 : po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_type",
151 173 : petsc_splitting_type[_splitting_type]);
152 :
153 173 : if (_splitting_type == SplittingTypeSchur)
154 : {
155 : // set Schur Type
156 0 : const std::string petsc_schur_type[] = {"diag", "upper", "lower", "full"};
157 0 : po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_schur_fact_type",
158 0 : petsc_schur_type[_schur_type]);
159 :
160 : // set Schur Preconditioner
161 0 : const std::string petsc_schur_pre[] = {"self", "selfp", "a11"};
162 0 : po.pairs.emplace_back(prefix_with_dash + "pc_fieldsplit_schur_precondition",
163 0 : petsc_schur_pre[_schur_pre]);
164 0 : }
165 :
166 : // The DM associated with this split defines the subsplits' geometry.
167 173 : po.pairs.emplace_back(dmprefix + "nfieldsplits", Moose::stringify(_splitting.size()));
168 692 : po.pairs.emplace_back(dmprefix + "fieldsplit_names", Moose::stringify(_splitting, ","));
169 :
170 : // Finally, recursively configure the splits contained within this split.
171 519 : for (const auto & split_name : _splitting)
172 : {
173 346 : std::shared_ptr<Split> split = nl.getSplit(split_name);
174 346 : std::string sprefix = prefix + "fieldsplit_" + split_name + "_";
175 346 : split->setup(nl, sprefix);
176 346 : }
177 865 : }
178 :
179 : // Now we set the user-specified petsc options for this split, possibly overriding the above
180 : // settings.
181 485 : Moose::PetscSupport::storePetscOptions(_fe_problem, prefix, *this);
182 485 : }
|