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.");
60 "fespace_hierarchy",
"Name of the MFEMFESpaceHierarchy that defines the level structure.");
63 "Names of LinearSolverBase objects used as smoothers on the interior levels " 64 "(levels 1 to N-1). May have length 1 (used on all interior levels) or " 65 "N-1 (one per interior level, ordered coarse-to-fine).");
67 "coarse_solver",
"Name of the LinearSolverBase used on the coarsest level.");
70 "Assembly level for each level in the hierarchy. Valid values: 'legacy', 'full', " 71 "'element', 'partial', 'none'. May have length 1 (used on all N levels) or N.");
82 const auto & hierarchy_name = getParam<std::string>(
"fespace_hierarchy");
87 const auto & asm_strs = getParam<std::vector<std::string>>(
"assembly_levels");
88 const int n_asm = asm_strs.size();
89 if (n_asm != 1 && n_asm !=
N)
91 "assembly_levels",
"must have length 1 or N = ",
N,
" (total levels), got ", n_asm,
".");
107 auto proxy = std::make_unique<MGProxy>(*this);
116 return mfem::AssemblyLevel::LEGACY;
118 return mfem::AssemblyLevel::FULL;
120 return mfem::AssemblyLevel::ELEMENT;
122 return mfem::AssemblyLevel::PARTIAL;
124 return mfem::AssemblyLevel::NONE;
126 "unknown assembly level '",
128 "'. Valid values: legacy, full, element, partial, none.");
129 return mfem::AssemblyLevel::LEGACY;
142 auto & pd = problem.getProblemData();
148 "': requires a standard (non-complex, non-time-dependent) EquationSystem.");
150 if (eq_sys->Nonlinear())
153 "': nonlinear equation systems are not currently supported.");
155 if (eq_sys->HasMixedBilinearForms(
_var_name))
157 "mixed bilinear form contributions are not supported for variable '",
159 "'. Block multigrid is required for saddle-point / mixed-field problems.");
163 paramError(
"fespace_hierarchy",
"hierarchy must contain at least one level.");
164 const int finest_level =
N - 1;
168 if (n_smooth != 1 && n_smooth !=
N - 1)
169 paramError(
"smoothers",
"must have length 1 or N-1 = ",
N - 1,
", got ", n_smooth,
".");
181 mfem::Array<int> ess_bdr = eq_sys->BuildEssentialBoundaryMarkers(
_var_name);
183 auto & finest_fespace =
184 static_cast<mfem::ParFiniteElementSpace &
>(
_hierarchy->GetFESpaceAtLevel(finest_level));
185 const int finest_size = finest_fespace.GetTrueVSize();
186 if (op.Height() != finest_size || op.Width() != finest_size)
189 "': incoming fine operator has size ",
193 ", but the finest hierarchy space has true size ",
198 std::vector<std::shared_ptr<mfem::ParBilinearForm>> new_blfs;
199 std::vector<std::unique_ptr<mfem::OperatorHandle>> new_level_ops;
200 new_level_ops.reserve(
N - 1);
202 auto mg = std::make_unique<mfem::GeometricMultigrid>(*
_hierarchy, ess_bdr);
203 auto * mg_ptr = mg.get();
207 auto & level_fespace =
208 static_cast<mfem::ParFiniteElementSpace &
>(
_hierarchy->GetFESpaceAtLevel(level));
211 mfem::Array<int> level_tdofs;
212 level_fespace.GetEssentialTrueDofs(ess_bdr, level_tdofs);
215 mfem::Operator * level_op =
nullptr;
218 if (level == finest_level)
220 level_op =
const_cast<mfem::Operator *
>(&op);
228 auto level_op_handle = std::make_unique<mfem::OperatorHandle>();
229 blf->FormSystemMatrix(level_tdofs, *level_op_handle);
230 level_op = level_op_handle->Ptr();
232 new_level_ops.push_back(std::move(level_op_handle));
233 new_blfs.push_back(std::move(blf));
238 auto & level_smoother = get_smoother(level);
239 level_smoother.SetOperator(*level_op);
241 mg_ptr->AddLevel(level_op, &level_smoother.GetSolver(), own_op,
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.
MFEMProblemData & getProblemData()
Method to get the current MFEMProblemData object storing the current data specifying the FE 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.
Owns the weak-form mathematics of a MOOSE MFEM problem.
MGProxy(MFEMGeometricMultigridSolver &owner)
Constructs a proxy that delegates multigrid rebuilding to the owning MOOSE solver.
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 SetOperator(mfem::Operator &op) override
Rebuilds the multigrid hierarchy for the supplied finest-level operator.
void Mult(const mfem::Vector &x, mfem::Vector &y) const override
Applies the current concrete MFEM multigrid preconditioner.
static InputParameters validParams()
Moose::MFEM::FESpaceHierarchies fespace_hierarchies
std::vector< std::shared_ptr< mfem::ParBilinearForm > > _level_blfs
Rediscretized bilinear forms kept alive for the active linear coarse-level operators.
std::shared_ptr< T > GetShared(const std::string &field_name) const
Returns a shared pointer to the field. This is guaranteed to return a non-null shared pointer...
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.
mfem::AssemblyLevel ParseAssemblyLevel(const std::string &s) const
Map assembly-level string ("legacy", "full", "element", "partial", "none") to the corresponding mfem:...
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...
void setMG(mfem::GeometricMultigrid &mg)
Updates the concrete MFEM multigrid object used by Mult().
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.