10 #ifdef MOOSE_MFEM_ENABLED 24 iterative_mode =
false;
38 _owner.BuildMultigrid(op);
44 MFEM_VERIFY(
_mg,
"MGProxy: GeometricMultigrid not yet built");
53 "Geometric (p-)multigrid preconditioner backed by mfem::GeometricMultigrid. " 54 "Requires a linear equation system, an MFEMFESpaceHierarchy, and per-level smoother " 58 "Name of the trial variable this preconditioner acts on.");
61 "Names of LinearSolverBase objects used as smoothers on the interior levels " 62 "(levels 1 to N-1). May have length 1 (used on all interior levels) or " 63 "N-1 (one per interior level, ordered coarse-to-fine).");
65 "coarse_solver",
"Name of the LinearSolverBase used on the coarsest level.");
66 params.
addParam<std::vector<std::string>>(
69 "Assembly level for each level in the hierarchy. Valid values: 'legacy', 'full', " 70 "'element', 'partial', 'none'. May have length 1 (used on all N levels) or N.");
81 auto eq_sys = problem.getProblemData().eqn_system;
83 if (eq_sys->IsEigen() || eq_sys->IsComplex())
84 mooseError(
"GeometricMultigridSolver '",
name(),
"': requires a real, non-eigen eq. system");
89 _hierarchy = problem.getProblemData().fespace_hierarchies.GetShared(*hierarchy_name);
91 paramError(
"variable",
"must be associated with an MFEMFESpaceHierarchy.");
95 mooseAssert(
N,
"Malformed MFEMFESpaceHierarchy w/ no levels");
96 const auto & asm_strs = getParam<std::vector<std::string>>(
"assembly_levels");
97 const int n_asm = asm_strs.size();
98 if (n_asm != 1 && n_asm !=
N)
100 "assembly_levels",
"must have length 1 or N = ",
N,
" (total levels), got ", n_asm,
".");
116 auto proxy = std::make_unique<MGProxy>(*this);
124 static MooseEnum assembly_levels(
"legacy full element partial none",
"legacy");
125 return (assembly_levels = s).getEnum<mfem::AssemblyLevel>();
138 auto eq_sys = problem.getProblemData().eqn_system;
140 if (eq_sys->IsNonlinear() || eq_sys->IsMultivariate())
141 mooseError(
"GeometricMultigridSolver '",
name(),
"': requires a univariate, linear eq. system");
144 const int finest_level =
_hierarchy->GetFinestLevelIndex();
148 if (n_smooth != 1 && n_smooth !=
N - 1)
149 paramError(
"smoothers",
"must have length 1 or N-1 = ",
N - 1,
", got ", n_smooth,
".");
161 mfem::Array<int> & ess_bdr = eq_sys->GetEssentialBoundaryMarkers(
_var_name);
163 auto & finest_fespace =
164 static_cast<mfem::ParFiniteElementSpace &
>(
_hierarchy->GetFESpaceAtLevel(finest_level));
165 const int finest_size = finest_fespace.GetTrueVSize();
166 if (op.Height() != finest_size || op.Width() != finest_size)
169 "': incoming fine operator has size ",
173 ", but the finest hierarchy space has true size ",
178 std::vector<std::shared_ptr<mfem::ParBilinearForm>> new_blfs;
179 std::vector<std::unique_ptr<mfem::OperatorHandle>> new_level_ops;
180 new_level_ops.reserve(
N - 1);
182 auto mg = std::make_unique<mfem::GeometricMultigrid>(*
_hierarchy, ess_bdr);
183 auto * mg_ptr = mg.get();
187 auto & level_fespace =
188 static_cast<mfem::ParFiniteElementSpace &
>(
_hierarchy->GetFESpaceAtLevel(level));
191 mfem::Array<int> level_tdofs;
192 level_fespace.GetEssentialTrueDofs(ess_bdr, level_tdofs);
195 mfem::Operator * level_op =
nullptr;
197 if (level == finest_level)
198 level_op =
const_cast<mfem::Operator *
>(&op);
204 auto level_op_handle = std::make_unique<mfem::OperatorHandle>();
205 blf->FormSystemMatrix(level_tdofs, *level_op_handle);
206 level_op = level_op_handle->Ptr();
207 new_level_ops.push_back(std::move(level_op_handle));
208 new_blfs.push_back(std::move(blf));
213 auto & level_smoother = get_smoother(level);
214 level_smoother.SetOperator(*level_op);
217 level_op, &level_smoother.GetSolver(),
false,
false);
void ConstructSolver() override
Creates a stable proxy solver; the real multigrid is built when the proxy gets an operator...
std::shared_ptr< mfem::ParFiniteElementSpaceHierarchy > _hierarchy
Finite element space hierarchy defining the multigrid levels.
MFEMGeometricMultigridSolver(const InputParameters ¶meters)
MFEMProblem & getMFEMProblem()
Return the owning MFEM problem.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
void BuildMultigrid(const mfem::Operator &op)
Rebuild the multigrid object and per-level operators for the supplied finest-level operator...
const std::string _var_name
Trial variable whose operator is preconditioned by this solver.
const InputParameters & parameters() const
Get the parameters of the object.
LinearSolverBase(const InputParameters ¶meters)
std::unique_ptr< mfem::Solver > _solver
Solver to be used for the problem.
MGProxy(MFEMGeometricMultigridSolver &owner)
Constructs a proxy that delegates multigrid rebuilding to the owning MOOSE solver.
void SetOperatorImpl(mfem::Operator &op) override
Rebuilds the multigrid hierarchy for the supplied finest-level operator.
Constructs and stores an mfem::ParGridFunction object.
static InputParameters validParams()
std::vector< mfem::AssemblyLevel > _assembly_levels
Assembly level requested for each multigrid level after optional single-value expansion.
const MFEMSolverName _coarse_solver_name
Name of the solver used on the coarsest multigrid level.
const std::string & name() const
Get the name of the class.
Base class for linear MFEM solvers and preconditioners.
void Mult(const mfem::Vector &x, mfem::Vector &y) const override
Applies the current concrete MFEM multigrid preconditioner.
static InputParameters validParams()
std::vector< std::shared_ptr< mfem::ParBilinearForm > > _level_blfs
Rediscretized bilinear forms kept alive for the active linear coarse-level operators.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
const std::vector< MFEMSolverName > _smoother_names
Names of solvers used as smoothers on interior multigrid levels.
std::unique_ptr< mfem::GeometricMultigrid > _mg
Concrete MFEM multigrid preconditioner rebuilt on each SetOperator() call.
const T * queryParam(const std::string &name) const
Query a parameter for the object.
mfem::AssemblyLevel ParseAssemblyLevel(const std::string &s) const
Map assembly-level string ("legacy", "full", "element", "partial", "none") to the corresponding mfem:...
void SetMG(mfem::GeometricMultigrid &mg)
Updates the concrete MFEM multigrid object used by Mult().
MGProxy * _mg_proxy
Non-owning pointer to the proxy solver stored in _solver.
IntRange< T > make_range(T beg, T end)
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...
P-multigrid / geometric multigrid preconditioner backed by mfem::GeometricMultigrid.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
std::vector< std::unique_ptr< mfem::OperatorHandle > > _level_ops
Constrained linear coarse-level operators; destroyed before the forms that own their data...
registerMooseObject("MooseApp", MFEMGeometricMultigridSolver)
void SetOperator(const mfem::Operator &op) override
Rebuilds the owner's multigrid hierarchy for the new outer-solver operator.