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 15017 : Split::validParams()
22 : {
23 15017 : InputParameters params = MooseObject::validParams();
24 15017 : params.addClassDescription("Field split based preconditioner for nonlinear solver.");
25 15017 : params.addParam<std::vector<NonlinearVariableName>>(
26 : "vars", {}, "Variables Split operates on (omitting this implies \"all variables\"");
27 15017 : params.addParam<std::vector<SubdomainName>>(
28 : "blocks", {}, "Mesh blocks Split operates on (omitting this implies \"all blocks\"");
29 15017 : params.addParam<std::vector<BoundaryName>>(
30 : "sides", {}, "Sidesets Split operates on (omitting this implies \"all sidesets\")");
31 15017 : params.addParam<std::vector<BoundaryName>>(
32 : "unsides",
33 : {},
34 : "Sidesets Split excludes (omitting this implies \"do not exclude any sidesets\")");
35 15017 : params.addParam<std::vector<std::string>>(
36 : "splitting", {}, "The names of the splits (subsystems) in the decomposition of this split");
37 15017 : 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 15017 : 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 15017 : params.addParamNamesToGroup("sides unsides unside_by_var_boundary_name unside_by_var_var_name",
44 : "Sideset restriction");
45 :
46 15017 : MooseEnum SplittingTypeEnum("additive multiplicative symmetric_multiplicative schur", "additive");
47 15017 : params.addParam<MooseEnum>("splitting_type", SplittingTypeEnum, "Split decomposition type");
48 :
49 15017 : MooseEnum SchurTypeEnum("diag upper lower full", "full");
50 15017 : 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 15017 : MooseEnum SchurPreEnum("S Sp A11", "S");
59 15017 : params.addParam<MooseEnum>(
60 : "schur_pre", SchurPreEnum, "Type of Schur complement preconditioner matrix");
61 :
62 45051 : params.addParam<MultiMooseEnum>("petsc_options",
63 30034 : Moose::PetscSupport::getCommonPetscFlags(),
64 : "PETSc flags for the FieldSplit solver");
65 45051 : params.addParam<MultiMooseEnum>("petsc_options_iname",
66 30034 : Moose::PetscSupport::getCommonPetscKeys(),
67 : "PETSc option names for the FieldSplit solver");
68 15017 : params.addParam<std::vector<std::string>>("petsc_options_value",
69 : "PETSc option values for the FieldSplit solver");
70 :
71 15017 : params.registerBase("Split");
72 15017 : params.registerSystemAttributeName("Split");
73 30034 : return params;
74 15017 : }
75 :
76 376 : Split::Split(const InputParameters & parameters)
77 : : MooseObject(parameters),
78 : Restartable(this, "Splits"),
79 376 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
80 376 : _vars(getParam<std::vector<NonlinearVariableName>>("vars")),
81 376 : _blocks(getParam<std::vector<SubdomainName>>("blocks")),
82 376 : _sides(getParam<std::vector<BoundaryName>>("sides")),
83 376 : _unsides(getParam<std::vector<BoundaryName>>("unsides")),
84 376 : _splitting(getParam<std::vector<std::string>>("splitting")),
85 376 : _splitting_type(getParam<MooseEnum>("splitting_type")),
86 376 : _schur_type(getParam<MooseEnum>("schur_type")),
87 752 : _schur_pre(getParam<MooseEnum>("schur_pre"))
88 : {
89 376 : }
90 :
91 : void
92 376 : 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 376 : Moose::PetscSupport::PetscOptions & po = _fe_problem.getPetscOptions();
100 : // prefix
101 376 : std::string dmprefix = prefix + "dm_moose_";
102 :
103 376 : if (isParamValid("unside_by_var_boundary_name"))
104 : {
105 : const auto & unside_by_var_boundary_name =
106 12 : getParam<std::vector<BoundaryName>>("unside_by_var_boundary_name");
107 : const auto & unside_by_var_var_name =
108 12 : getParam<std::vector<NonlinearVariableName>>("unside_by_var_var_name");
109 :
110 12 : std::vector<std::string> vector_of_pairs;
111 36 : for (const auto i : index_range(unside_by_var_boundary_name))
112 24 : vector_of_pairs.push_back(unside_by_var_boundary_name[i] + ":" + unside_by_var_var_name[i]);
113 12 : po.pairs.emplace_back(dmprefix + "unside_by_var", Moose::stringify(vector_of_pairs, ","));
114 12 : }
115 :
116 : // var options
117 376 : if (!_vars.empty())
118 : {
119 260 : po.pairs.emplace_back(dmprefix + "vars", Moose::stringify(_vars, ","));
120 :
121 : // check that variables are either field or scalars
122 520 : for (const auto & var : _vars)
123 260 : 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 376 : if (!_blocks.empty())
129 0 : po.pairs.emplace_back(dmprefix + "blocks", Moose::stringify(_blocks, ","));
130 :
131 : // side options
132 376 : if (!_sides.empty())
133 44 : po.pairs.emplace_back(dmprefix + "sides", Moose::stringify(_sides, ","));
134 :
135 : // unside options
136 376 : if (!_unsides.empty())
137 32 : po.pairs.emplace_back(dmprefix + "unsides", Moose::stringify(_unsides, ","));
138 :
139 376 : 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 136 : po.pairs.emplace_back(prefix + "pc_type", "fieldsplit");
145 :
146 : // set Splitting Type
147 : const std::string petsc_splitting_type[] = {
148 816 : "additive", "multiplicative", "symmetric_multiplicative", "schur"};
149 136 : po.pairs.emplace_back(prefix + "pc_fieldsplit_type", petsc_splitting_type[_splitting_type]);
150 :
151 136 : 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 136 : po.pairs.emplace_back(dmprefix + "nfieldsplits", Moose::stringify(_splitting.size()));
166 136 : po.pairs.emplace_back(dmprefix + "fieldsplit_names", Moose::stringify(_splitting, ","));
167 :
168 : // Finally, recursively configure the splits contained within this split.
169 408 : for (const auto & split_name : _splitting)
170 : {
171 272 : std::shared_ptr<Split> split = nl.getSplit(split_name);
172 272 : std::string sprefix = prefix + "fieldsplit_" + split_name + "_";
173 272 : split->setup(nl, sprefix);
174 272 : }
175 680 : }
176 :
177 : // Now we set the user-specified petsc options for this split, possibly overriding the above
178 : // settings.
179 376 : Moose::PetscSupport::storePetscOptions(_fe_problem, prefix, *this);
180 376 : }
|