23 const int vdim = pfespace->
GetVDim();
40 dynamic_cast<HypreADS*
>(prec)->SetPrintLevel(print_level);
47 dynamic_cast<HypreAMS*
>(prec)->SetPrintLevel(print_level);
52 MFEM_ABORT(
"Unsupported FiniteElementCollection type");
60 const std::vector<
Array<int>> & ess_bdr_marker_)
61 : pfes(pfes_), ess_bdr_marker(ess_bdr_marker_), nblocks(pfes.Size())
63 MFEM_VERIFY(
nblocks > 0,
"Empty pfes.");
65 MFEM_VERIFY(
pmesh,
"pfes[0] has null ParMesh.");
67 "ess_bdr_marker size must match nblocks.");
73 "ess_bdr_marker[" << i <<
"] size must match max bdr_attribute in mesh.");
96 for (
int i = 0; i <
nblocks; i++)
98 orders[i] =
pfes[i]->FEColl()->GetConstructorOrder();
108 MFEM_VERIFY(
maxlevels >= 1,
"Invalid maxlevels computed.");
114 for (
int lev = 0; lev <
maxlevels-1; lev++)
125 const int vdim =
pfes[
b]->GetVDim();
128 for (
int lev = 1; lev <=
maxlevels - 1; lev++)
135 fec_ptr.reset(fec_ref->
Clone(
p));
136 fes_ptr = std::make_unique<ParFiniteElementSpace>(
pmesh, fec_ptr.get(),
158 for (
int j = 0; j < block_tdof_list.
Size(); j++)
160 block_tdof_list[j] += tdof_offsets[
b];
162 tdof_list.
Append(block_tdof_list);
170 MFEM_VERIFY(lev >= 0 &&
171 lev <
maxlevels - 1,
"Invalid level in BuildProlongation().");
189 T_level[lev][
b] = std::make_unique<PRefinementTransferOperator>(
194 MFEM_VERIFY(P,
"PRefinement transfer returned null.");
203 const std::vector<
Array<int>> & ess_bdr_marker_,
205 real_t smoother_relax_factor,
bool mumps_coarse_solver,
206 int coarse_cg_max_iter,
real_t coarse_cg_rel_tol)
207 :
Multigrid(), hierarchy(pfes_, ess_bdr_marker_), Op(Op_)
209#ifndef MFEM_USE_MUMPS
210 if (mumps_coarse_solver)
212 MFEM_WARNING(
"MFEM not built with MUMPS."
213 "Switching to default coarse solver (CG).");
215 mumps_coarse_solver =
false;
220 const int maxlevels = hierarchy.
maxlevels;
221 const int nblocks = hierarchy.
nblocks;
231 const int nP = std::max(0, maxlevels - 1);
236 for (
int lev = nP - 1; lev >= 0; lev--)
248 MFEM_VERIFY(OpFine,
"Expected BlockOperator at fine level.");
250 for (
int i = 0; i < nblocks; i++)
253 MFEM_VERIFY(Pi,
"Expected HypreParMatrix prolongation block.");
256 for (
int j = 0; j < nblocks; j++)
262 MFEM_VERIFY(A_fine,
"Expected HypreParMatrix block.");
271 MFEM_VERIFY(Pj,
"Expected HypreParMatrix prolongation block.");
286 for (
int lev = 0; lev <
operators.Size(); lev++)
289 MFEM_VERIFY(cOp,
"Expected BlockOperator in operators[].");
294 if (mumps_coarse_solver)
297 auto *mumps_solver =
new MUMPSSolver(MPI_COMM_WORLD);
298 mumps_solver->SetPrintLevel(0);
299 mumps_solver->SetOperator(*Acoarse);
311 for (
int b = 0;
b < nblocks;
b++)
315 MFEM_VERIFY(Ab,
"Expected HypreParMatrix block.");
318 solver->SetOperator(*Ab);
319 bd->SetDiagonalBlock(
b, solver);
322 coarse_prec.reset(bd);
324 auto *cg =
new CGSolver(MPI_COMM_WORLD);
325 cg->SetPrintLevel(-1);
326 cg->SetRelTol(coarse_cg_rel_tol);
327 cg->SetMaxIter(coarse_cg_max_iter);
328 cg->SetOperator(*cOp);
329 cg->SetPreconditioner(*coarse_prec);
338 smoother_relax_factor);
339 prec->owns_blocks = 1;
341 for (
int b = 0;
b < nblocks;
b++)
345 MFEM_VERIFY(Ab,
"Expected HypreParMatrix block.");
348 solver->SetOperator(*Ab);
349 prec->SetDiagonalBlock(
b, solver);
360 const std::vector<
Array<int>> & ess_bdr_marker,
362 real_t smoother_relax_factor,
bool mumps_coarse_solver,
363 int coarse_cg_max_iter,
real_t coarse_cg_rel_tol)
366#ifndef MFEM_USE_MUMPS
367 if (mumps_coarse_solver)
369 MFEM_WARNING(
"MFEM not built with MUMPS."
370 "Switching to default coarse solver (CG).");
372 mumps_coarse_solver =
false;
378 MFEM_VERIFY(Op_r,
"Expected BlockOperator from ComplexOperator real part.");
379 MFEM_VERIFY(Op_i,
"Expected BlockOperator from ComplexOperator imag part.");
381 const int nblocks = Op_r->NumRowBlocks();
382 MFEM_VERIFY(nblocks == Op_i->NumRowBlocks(),
"Real/imag block counts differ.");
383 hierarchy = std::make_unique<PRefinementHierarchy>(pfes_, ess_bdr_marker);
385 hierarchy->BuildSpaceHierarchy(mgmaxlevels);
387 const int maxlevels = hierarchy->maxlevels;
397 const int nP = std::max(0, maxlevels - 1);
401 for (
int lev = nP - 1; lev >= 0; lev--)
406 hierarchy->ess_tdof_list[lev],
407 hierarchy->ess_tdof_list[lev+1],
true);
415 OpLevel_r->owns_blocks = 1;
416 OpLevel_i->owns_blocks = 1;
419 MFEM_VERIFY(cOp,
"Expected ComplexOperator at fine level.");
423 MFEM_VERIFY(cOp_r,
"Expected BlockOperator fine real part.");
424 MFEM_VERIFY(cOp_i,
"Expected BlockOperator fine imag part.");
426 for (
int i = 0; i < nblocks; i++)
429 MFEM_VERIFY(Pi,
"Expected HypreParMatrix prolongation block.");
432 for (
int j = 0; j < nblocks; j++)
434 if (!cOp_r->IsZeroBlock(i, j))
438 MFEM_VERIFY(A_fine_r,
"Expected HypreParMatrix block (real).");
442 OpLevel_r->SetBlock(i, i,
RAP(A_fine_r, Pi));
447 MFEM_VERIFY(Pj,
"Expected HypreParMatrix prolongation block.");
453 OpLevel_r->SetBlock(i, j, PtAP);
457 if (!cOp_i->IsZeroBlock(i, j))
461 MFEM_VERIFY(A_fine_i,
"Expected HypreParMatrix block (imag).");
465 OpLevel_i->SetBlock(i, i,
RAP(A_fine_i, Pi));
470 MFEM_VERIFY(Pj,
"Expected HypreParMatrix prolongation block.");
476 OpLevel_i->SetBlock(i, j, PtAP);
484 auto *OpLevel_c =
new ComplexOperator(OpLevel_r, OpLevel_i,
true,
true);
490 for (
int lev = 0; lev <
operators.Size(); lev++)
493 MFEM_VERIFY(cOp,
"Expected ComplexOperator in operators[].");
496 MFEM_VERIFY(cOp_r,
"Expected BlockOperator real part in ComplexOperator.");
501 if (mumps_coarse_solver)
507 auto *mumps_solver =
new MUMPSSolver(MPI_COMM_WORLD);
508 mumps_solver->SetPrintLevel(0);
509 mumps_solver->SetOperator(*A);
519 prec_r->owns_blocks = 1;
521 for (
int b = 0;
b < nblocks;
b++)
525 MFEM_VERIFY(Ab,
"Expected HypreParMatrix block.");
528 solver->SetOperator(*Ab);
529 prec_r->SetDiagonalBlock(
b, solver);
534 auto *cg =
new CGSolver(MPI_COMM_WORLD);
535 cg->SetPrintLevel(-1);
536 cg->SetRelTol(coarse_cg_rel_tol);
537 cg->SetMaxIter(coarse_cg_max_iter);
538 cg->SetOperator(*cOp);
539 cg->SetPreconditioner(*coarse_prec);
548 smoother_relax_factor);
549 prec_r->owns_blocks = 1;
551 for (
int b = 0;
b < nblocks;
b++)
555 MFEM_VERIFY(Ab,
"Expected HypreParMatrix block.");
558 solver->SetOperator(*Ab);
559 prec_r->SetDiagonalBlock(
b, solver);
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
int Size() const
Return the logical size of the array.
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
A class to handle Block diagonal preconditioners in a matrix-free implementation.
A class to handle Block systems in a matrix-free implementation.
int IsZeroBlock(int i, int j) const
Check if block (i,j) is a zero block.
void SetBlock(int iRow, int iCol, Operator *op, real_t c=1.0)
Add a block op in the block-entry (iblock, jblock).
Operator & GetBlock(int i, int j)
Return a reference to block i,j.
Array< int > & ColOffsets()
Return the columns offsets for block starts.
Conjugate gradient method.
Specialization of the ComplexOperator built from a pair of HypreParMatrices.
HypreParMatrix * GetSystemMatrix() const
Mimic the action of a complex operator using two real operators.
virtual Operator & imag()
ComplexHypreParMatrix * AsComplexHypreParMatrix() const
Return a newly allocated ComplexHypreParMatrix representation.
virtual Operator & real()
Real or imaginary part accessor methods.
ComplexPRefinementMultigrid(const Array< ParFiniteElementSpace * > &pfes_, const std::vector< Array< int > > &ess_bdr_marker, const ComplexOperator &Op_, int mgmaxlevels=-1, real_t smoother_relax_factor=2.0/3, bool mumps_coarse_solver=false, int coarse_cg_max_iter=10, real_t coarse_cg_rel_tol=1e-3)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
virtual FiniteElementCollection * Clone(int p) const
Instantiate a new collection of the same type with a different order.
const FiniteElementCollection * FEColl() const
int GetVDim() const
Returns the vector dimension of the finite element space.
Arbitrary order H1-conforming (continuous) finite elements.
The Auxiliary-space Divergence Solver in hypre.
The Auxiliary-space Maxwell Solver in hypre.
The BoomerAMG solver in hypre.
Wrapper for hypre's ParCSR matrix class.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
Arbitrary order "L2-conforming" discontinuous finite elements.
MUMPS: A Parallel Sparse Direct Solver.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
int Dimension() const
Dimension of the reference space used within the elements.
Array< Operator * > operators
Array< bool > ownedSmoothers
Array< bool > ownedOperators
Array< Solver * > smoothers
Array< bool > ownedProlongations
Array< Operator * > prolongations
Arbitrary order H(curl)-conforming Nedelec finite elements.
std::vector< Array< int > > ess_tdof_list
std::vector< std::vector< std::unique_ptr< PRefinementTransferOperator > > > T_level
const Array< ParFiniteElementSpace * > & pfes
std::vector< std::vector< std::unique_ptr< ParFiniteElementSpace > > > fes_owned
int GetFESpaceMinimumOrder(const ParFiniteElementSpace *pfespace) const
std::vector< std::vector< std::unique_ptr< FiniteElementCollection > > > fec_owned
std::vector< Array< int > > ess_bdr_marker
void BuildSpaceHierarchy(int mgmaxlevels=-1)
Computes orders/maxlevels and constructs fec/fes hierarchy and T_level storage.
BlockOperator * BuildProlongation(int lev)
Builds block-diagonal prolongation for level lev (coarse=lev, fine=lev+1). Its diagonal blocks are Hy...
const ParFiniteElementSpace * GetParFESpace(int lev, int b) const
PRefinementHierarchy(const Array< ParFiniteElementSpace * > &pfes_, const std::vector< Array< int > > &ess_bdr_marker_)
PRefinementMultigrid(const Array< ParFiniteElementSpace * > &pfes_, const std::vector< Array< int > > &ess_bdr_marker_, const BlockOperator &Op_, int mgmaxlevels=-1, real_t smoother_relax_factor=2.0/3, bool mumps_coarse_solver=false, int coarse_cg_max_iter=10, real_t coarse_cg_rel_tol=1e-3)
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
int GetTrueVSize() const override
Return the number of local vector true dofs.
ParMesh * GetParMesh() const
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Rectangular Operator for imposing essential boundary conditions on the input space using only the act...
Solver * MakeFESpaceDefaultSolver(const ParFiniteElementSpace *pfespace, int print_level)
Creates a default solver for a given parallel FE space. The default solvers are the following:
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
real_t p(const Vector &x, real_t t)