16 using namespace blocksolvers;
41 int* I =
new int[fes.
GetNE()+1];
46 double* D =
new double[J.Size()];
47 fill_n(D, J.Size(), 1.0);
51 DFSSpaces::DFSSpaces(
int order,
int num_refine,
ParMesh *mesh,
53 : hdiv_fec_(order, mesh->Dimension()), l2_fec_(order, mesh->Dimension()),
54 l2_0_fec_(0, mesh->Dimension()), ess_bdr_attr_(ess_attr), level_(0)
58 mfem_error(
"DFSDataCollector: High order spaces on tetrahedra are not supported");
79 el_l2dof_.reserve(num_refine+1);
80 el_l2dof_.push_back(
ElemToDof(*coarse_l2_fes_));
86 data_.
Q_l2.resize(num_refine);
88 data_.
C.resize(num_refine+1);
110 int * I =
new int [tdof_agg.NumRows()+1]();
111 int * J =
new int[tdof_agg.NumNonZeroElems()];
117 for (
int i = 0; i < tdof_agg.NumRows(); ++i)
119 bool agg_bdr = is_bdr[i] || is_shared.RowSize(i) || tdof_agg.RowSize(i)>1;
120 if (agg_bdr) { I[i+1] = I[i];
continue; }
122 J[counter++] = tdof_agg.GetRowColumns(i)[0];
125 double * D =
new double[I[tdof_agg.NumRows()]];
126 std::fill_n(D, I[tdof_agg.NumRows()], 1.0);
128 SparseMatrix intdof_agg(I, J, D, tdof_agg.NumRows(), tdof_agg.NumCols());
132 void DFSSpaces::MakeDofRelationTables(
int level)
135 auto& elem_agg = (
const SparseMatrix&)*l2_0_fes_->GetUpdateOperator();
139 el_l2dof_.push_back(
ElemToDof(*l2_fes_));
140 data_.
agg_l2dof[level].Reset(
Mult(agg_el, el_l2dof_[level+1]));
143 hdiv_fes_->GetEssentialTrueDofs(all_bdr_attr_, bdr_tdofs);
145 *hdiv_fes_->Dof_TrueDof_Matrix(), agg_starts);
151 auto GetP = [
this](
OperatorPtr& P, unique_ptr<ParFiniteElementSpace>& cfes,
155 fes.GetTrueTransferOperator(*cfes, P);
160 (level_ < (int)data_.
P_l2.size()-1) ? cfes->Update() : cfes.reset();
163 GetP(data_.
P_hdiv[level_], coarse_hdiv_fes_, *hdiv_fes_,
true);
164 GetP(data_.
P_l2[level_], coarse_l2_fes_, *l2_fes_,
false);
165 MakeDofRelationTables(level_);
167 GetP(data_.
P_hcurl[level_], coarse_hcurl_fes_, *hcurl_fes_,
true);
169 Vector trash1(hcurl_fes_->GetVSize()), trash2(hdiv_fes_->GetVSize());
173 curl.EliminateTrialDofs(ess_bdr_attr_, trash1, trash2);
175 data_.
C[level_+1].Reset(curl.ParallelAssemble());
179 if (level_ == (
int)data_.
P_l2.size()) { DataFinalize(); }
182 void DFSSpaces::DataFinalize()
191 for (
int l = (
int)data_.
P_l2.size()-1; l >= 0; --l)
196 auto cW =
Mult(*PTW, P_l2);
206 :
Solver(B.NumRows()), BBT_solver_(B.GetComm())
221 :
Solver(M.NumRows()+B.NumRows()), local_system_(height), offset_(M.NumRows())
223 local_system_.
CopyMN(M, 0, 0);
224 local_system_.
CopyMN(B, offset_, 0);
225 local_system_.
CopyMNt(B, 0, offset_);
227 local_system_.
SetRow(offset_, 0.0);
228 local_system_.
SetCol(offset_, 0.0);
229 local_system_(offset_, offset_) = -1.0;
235 const double x0 = x[offset_];
236 const_cast<Vector&
>(x)[offset_] = 0.0;
239 local_solver_.
Mult(x, y);
241 const_cast<Vector&
>(x)[offset_] = x0;
250 :
Solver(M.NumRows() + B.NumRows()), agg_hdivdof_(agg_hdivdof),
251 agg_l2dof_(agg_l2dof), solvers_loc_(agg_l2dof.NumRows())
266 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
272 M_diag.
GetSubMatrix(hdivdofs_loc_, hdivdofs_loc_, M_loc);
274 solvers_loc_[agg].Reset(
new LocalSolver(M_loc, B_loc));
285 static_cast<Vector&
>(Pi_x) = x;
289 Vector coarse_l2_projection(Pi_x.BlockSize(1));
290 coarse_l2_projector_->
MultTranspose(Pi_x.GetBlock(1), coarse_l2_projection);
292 Pi_x.GetBlock(1) -= coarse_l2_projection;
294 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
299 offsets_loc_[1] = hdivdofs_loc_.
Size();
300 offsets_loc_[2] = offsets_loc_[1]+l2dofs_loc_.
Size();
302 BlockVector rhs_loc(offsets_loc_), sol_loc(offsets_loc_);
303 Pi_x.GetBlock(0).GetSubVector(hdivdofs_loc_, rhs_loc.GetBlock(0));
304 Pi_x.GetBlock(1).GetSubVector(l2dofs_loc_, rhs_loc.GetBlock(1));
306 solvers_loc_[agg]->Mult(rhs_loc, sol_loc);
308 blk_y.GetBlock(0).AddElementVector(hdivdofs_loc_, sol_loc.
GetBlock(0));
309 blk_y.GetBlock(1).AddElementVector(l2dofs_loc_, sol_loc.
GetBlock(1));
312 coarse_l2_projector_->
Mult(blk_y.GetBlock(1), coarse_l2_projection);
313 blk_y.GetBlock(1) -= coarse_l2_projection;
318 :
DarcySolver(M.NumRows(), B.NumRows()), op_(offsets_), prec_(offsets_),
344 for (
int dof : ess_zero_dofs_) { y[dof] = 0.0; }
349 :
DarcySolver(M.NumRows(), B.NumRows()), data_(data), param_(data.param),
350 BT_(B.
Transpose()), BBT_solver_(B, param_.BBT_solve_param),
351 ops_offsets_(data.P_l2.size()+1), ops_(ops_offsets_.size()),
352 blk_Ps_(ops_.Size()-1), smoothers_(ops_.Size())
356 ops_.Last()->SetBlock(0, 0, const_cast<HypreParMatrix*>(&M));
357 ops_.Last()->SetBlock(1, 0, const_cast<HypreParMatrix*>(&B));
358 ops_.Last()->SetBlock(0, 1, BT_.
Ptr());
360 for (
int l = data.
P_l2.size(); l >= 0; --l)
362 auto& M_f =
static_cast<HypreParMatrix&
>(ops_[l]->GetBlock(0, 0));
363 auto& B_f =
static_cast<HypreParMatrix&
>(ops_[l]->GetBlock(1, 0));
369 B_f.GetDiag(B_f_diag);
382 smoothers_[l] = coarse_solver;
394 agg_l2dof_l, P_l2_l, Q_l2_l);
399 S1->owns_blocks =
true;
400 smoothers_[l] =
new ProductSolver(ops_[l], S0, S1,
false,
true,
true);
410 ops_offsets_[l-1].SetSize(3, 0);
411 ops_offsets_[l-1][1] = M_c->
NumRows();
414 blk_Ps_[l-1] =
new BlockOperator(ops_offsets_[l], ops_offsets_[l-1]);
415 blk_Ps_[l-1]->SetBlock(0, 0, &P_hdiv_l);
416 blk_Ps_[l-1]->SetBlock(1, 1, &P_l2_l);
419 ops_[l-1]->SetBlock(0, 0, M_c);
420 ops_[l-1]->SetBlock(1, 0, B_c);
421 ops_[l-1]->SetBlock(0, 1, B_c->
Transpose());
422 ops_[l-1]->owns_blocks =
true;
429 own_smoothers =
true;
432 if (data_.
P_l2.size() == 0) {
return; }
439 own_ops, own_smoothers, own_Ps));
450 ops.Last()->EliminateZeroRows();
451 ops.Last()->DropSmallEntries(1e-14);
456 static_cast<HypreSmoother*
>(smoothers.Last())->SetOperatorSymmetry(
true);
458 for (
int l = Ps.Size()-1; l >= 0; --l)
464 static_cast<HypreSmoother*
>(smoothers[l])->SetOperatorSymmetry(
true);
467 prec_.
Reset(
new Multigrid(ops, smoothers, Ps, own_ops, own_smoothers, own_Ps));
477 for (
int i = 0; i < ops_.Size(); ++i)
480 delete smoothers_[i];
481 if (i == ops_.Size() - 1) {
break; }
486 void DivFreeSolver::SolveParticular(
const Vector& rhs,
Vector& sol)
const
488 std::vector<Vector> rhss(smoothers_.Size());
489 std::vector<Vector> sols(smoothers_.Size());
491 rhss.back().SetDataAndSize(const_cast<Vector&>(rhs), rhs.
Size());
492 sols.back().SetDataAndSize(sol, sol.
Size());
494 for (
int l = blk_Ps_.Size()-1; l >= 0; --l)
496 rhss[l].SetSize(blk_Ps_[l]->
NumCols());
497 sols[l].SetSize(blk_Ps_[l]->
NumCols());
502 blk_Ps_[l]->MultTranspose(rhss[l+1], rhss[l]);
505 for (
int l = 0; l < smoothers_.Size(); ++l)
507 smoothers_[l]->Mult(rhss[l], sols[l]);
510 for (
int l = 0; l < blk_Ps_.Size(); ++l)
513 blk_Ps_[l]->Mult(sols[l], P_sol);
518 void DivFreeSolver::SolveDivFree(
const Vector &rhs,
Vector& sol)
const
520 Vector rhs_divfree(data_.
C.back()->NumCols());
521 data_.
C.back()->MultTranspose(rhs, rhs_divfree);
523 Vector potential_divfree(rhs_divfree.Size());
524 potential_divfree = 0.0;
525 solver_->
Mult(rhs_divfree, potential_divfree);
527 data_.
C.back()->Mult(potential_divfree, sol);
530 void DivFreeSolver::SolvePotential(
const Vector& rhs,
Vector& sol)
const
534 BBT_solver_.
Mult(rhs_p, sol);
539 MFEM_VERIFY(x.
Size() ==
offsets_[2],
"MLDivFreeSolver: x size is invalid");
540 MFEM_VERIFY(y.
Size() ==
offsets_[2],
"MLDivFreeSolver: y size is invalid");
542 if (ops_.Size() == 1) { smoothers_[0]->Mult(x, y);
return; }
547 ops_.Last()->Mult(y, resid);
548 add(1.0, x, -1.0, resid, resid);
555 solver_->
Mult(resid, correction);
563 SolveParticular(resid, correction);
568 cout <<
"Particular solution found in " << ch.
RealTime() <<
"s.\n";
574 ops_.Last()->Mult(y, resid);
575 add(1.0, x, -1.0, resid, resid);
582 cout <<
"Divergence free solution found in " << ch.
RealTime() <<
"s.\n";
588 auto M =
dynamic_cast<HypreParMatrix&
>(ops_.Last()->GetBlock(0, 0));
595 cout <<
"Scalar potential found in " << ch.
RealTime() <<
"s.\n";
602 if (ops_.Size() == 1)
int Size() const
Return the logical size of the array.
int RowSize(const int i) const
Returns the number of elements in row i.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Conjugate gradient method.
MPI_Comm GetComm() const
MPI communicator.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
void EliminateCol(int col, DiagonalPolicy dpolicy=DIAG_ZERO)
Eliminates the column col from the matrix.
void SetCol(int c, const double *col)
A class to handle Vectors in a block fashion.
void SetRow(int r, const double *row)
DivFreeSolver(const HypreParMatrix &M, const HypreParMatrix &B, const DFSData &data)
void SetSize(int s)
Resize the vector to size s.
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
std::vector< OperatorPtr > Q_l2
Pointer to an Operator of a specified type.
Abstract solver class for Darcy's flow.
Array< int > coarsest_ess_hdivdofs
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Abstract parallel finite element space.
SaddleSchwarzSmoother(const HypreParMatrix &M, const HypreParMatrix &B, const SparseMatrix &agg_hdivdof, const SparseMatrix &agg_l2dof, const HypreParMatrix &P_l2, const HypreParMatrix &Q_l2)
std::vector< OperatorPtr > P_hcurl
double * GetData() const
Return a pointer to the beginning of the Vector data.
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
void add(const Vector &v1, const Vector &v2, Vector &v)
void AddDomainInterpolator(DiscreteInterpolator *di)
Adds a domain interpolator. Assumes ownership of di.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
IterSolveParameters coarse_solve_param
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
LocalSolver(const DenseMatrix &M, const DenseMatrix &B)
Operator & GetDiagonalBlock(int iblock)
Return a reference to block i,i.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
ID for class SparseMatrix.
int GetNE() const
Returns number of elements in the mesh.
The BoomerAMG solver in hypre.
Data for the divergence free solver.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
virtual int GetNumIterations() const
General product operator: x -> (A*B)(x) = A(B(x)).
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
void SetPrintLevel(int print_lvl)
A class to handle Block diagonal preconditioners in a matrix-free implementation. ...
Wrapper for the block-diagonal-preconditioned MINRES defined in ex5p.cpp.
Jacobi preconditioner in hypre.
SparseMatrix ElemToDof(const ParFiniteElementSpace &fes)
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void SetMaxIter(int max_it)
std::vector< OperatorPtr > P_hdiv
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
const Element * GetElement(int i) const
Parallel smoothers in hypre.
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Operator * Ptr() const
Access the underlying Operator pointer.
void Start()
Clear the elapsed time and start the stopwatch.
BDPMinresSolver(HypreParMatrix &M, HypreParMatrix &B, IterSolveParameters param)
void SetAbsTol(double atol)
void SetRelTol(double rtol)
Abstract base class for iterative solver.
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
OperatorHandle OperatorPtr
Add an alternative name for OperatorHandle – OperatorPtr.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void EliminateRowCol(int rc, const double sol, Vector &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Eliminate row rc and column rc and modify the rhs using sol.
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
std::vector< OperatorPtr > agg_hdivdof
std::vector< OperatorPtr > agg_l2dof
Parameters for the divergence free solver.
void Mult(const double *x, double *y) const
Matrix vector multiplication with the inverse of dense matrix.
std::vector< OperatorPtr > C
void GetDiag(Vector &d) const
Returns the Diagonal of A.
void CopyMNt(const DenseMatrix &A, int row_offset, int col_offset)
Copy matrix A^t to the location in *this at row_offset, col_offset.
void SetOptions(IterativeSolver &solver, const IterSolveParameters ¶m)
HypreParMatrix * TwoStepsRAP(const HypreParMatrix &Rt, const HypreParMatrix &A, const HypreParMatrix &P)
Block diagonal solver for symmetric A, each block is inverted by direct solver.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void GetRowColumnsRef(const SparseMatrix &A, int row, Array< int > &cols)
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
static void ListToMarker(const Array< int > &list, int marker_size, Array< int > &marker, int mark_val=-1)
Convert an array of indices (list) to a Boolean marker array where all indices in the list are marked...
void MakeRef(T *, int)
Make this Array a reference to a pointer.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Arbitrary order H(curl)-conforming Nedelec finite elements.
ID for class HypreParMatrix.
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, double alpha=1.0, double beta=0.0) const
Computes y = alpha * A * x + beta * y.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Parameters for iterative solver.
void DropSmallEntries(double tol)
Wrapper for hypre_ParCSRMatrixDropSmallEntries in different versions of hypre. Drop off-diagonal entr...
Arbitrary order H1-conforming (continuous) finite elements.
void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco)
Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this.
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element...
HypreParMatrix * LeftDiagMult(const SparseMatrix &D, HYPRE_BigInt *row_starts=NULL) const
Multiply the HypreParMatrix on the left by a block-diagonal parallel matrix D and return the result a...
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
SparseMatrix * AggToInteriorDof(const Array< int > &bdr_truedofs, const SparseMatrix &agg_elem, const SparseMatrix &elem_dof, const HypreParMatrix &dof_truedof, Array< HYPRE_Int > &agg_starts)
Solver for local problems in SaddleSchwarzSmoother.
Wrapper for hypre's ParCSR matrix class.
A class to handle Block systems in a matrix-free implementation.
BBTSolver(const HypreParMatrix &B, IterSolveParameters param)
Class for parallel meshes.
virtual Type GetType() const =0
Returns element's type.
std::vector< OperatorPtr > P_l2
static void AdjustVDofs(Array< int > &vdofs)
void Clear()
Clear the elapsed time on the stopwatch and restart it if it's running.
void SetBlock(int iRow, int iCol, Operator *op, double c=1.0)
Add a block op in the block-entry (iblock, jblock).
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
Vector & GetBlock(int i)
Get the i-th vector in the block.