19static HypreParMatrix* TwoStepsRAP(
const HypreParMatrix *Rt,
20 const HypreParMatrix *A,
21 const HypreParMatrix *P)
25 return ParMult(RA.As<HypreParMatrix>(), P,
true);
35 int* I =
new int[fes.
GetNE()+1];
41 fill_n(D, J.
Size(), 1.0);
47 : hdiv_fec_(order, mesh->Dimension()), l2_fec_(order, mesh->Dimension()),
48 l2_0_fec_(0, mesh->Dimension()), ess_bdr_attr_(ess_attr), level_(0)
50 if (mesh->
GetNE() > 0)
54 MFEM_ABORT(
"DFSDataCollector: High order spaces on tetrahedra are not supported");
62 hcurl_fec_ = std::make_unique<ND_FECollection>(order+1, mesh->
Dimension());
66 hcurl_fec_ = std::make_unique<H1_FECollection>(order+1, mesh->
Dimension());
70 hdiv_fes_ = std::make_unique<ParFiniteElementSpace>(mesh, &hdiv_fec_);
71 l2_fes_ = std::make_unique<ParFiniteElementSpace>(mesh, &l2_fec_);
72 coarse_hdiv_fes_ = std::make_unique<ParFiniteElementSpace>(*hdiv_fes_);
73 coarse_l2_fes_ = std::make_unique<ParFiniteElementSpace>(*l2_fes_);
74 l2_0_fes_ = std::make_unique<ParFiniteElementSpace>(mesh, &l2_0_fec_);
76 el_l2dof_.reserve(num_refine+1);
77 el_l2dof_.push_back(
ElemToDof(*coarse_l2_fes_));
81 data_.
P_hdiv.resize(num_refine);
82 data_.
P_l2.resize(num_refine);
84 data_.
Q_l2.resize(num_refine);
86 data_.
C.resize(num_refine+1);
87 data_.
Ae.resize(num_refine+1);
89 hcurl_fes_ = std::make_unique<ParFiniteElementSpace>(mesh, hcurl_fec_.get());
90 coarse_hcurl_fes_ = std::make_unique<ParFiniteElementSpace>(*hcurl_fes_);
91 data_.
P_hcurl.resize(num_refine);
109 int *I =
new int[tdof_agg.
NumRows()+1]();
116 for (
int i = 0; i < tdof_agg.
NumRows(); ++i)
118 bool agg_bdr = is_bdr[i] || is_shared.
RowSize(i) || tdof_agg.
RowSize(i)>1;
119 if (agg_bdr) { I[i+1] = I[i];
continue; }
125 std::fill_n(D, I[tdof_agg.
NumRows()], 1.0);
131void 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 = [&](std::unique_ptr<OperatorPtr> &P,
152 std::unique_ptr<ParFiniteElementSpace> &cfes,
157 fes.GetTrueTransferOperator(*cfes, *T);
159 if (remove_zero) { P->As<
HypreParMatrix>()->DropSmallEntries(1e-16); }
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);
166 MakeDofRelationTables(level_);
168 GetP(data_.
P_hcurl[level_], coarse_hcurl_fes_, *hcurl_fes_,
true);
176 hcurl_fes_->GetEssentialTrueDofs(ess_bdr_attr_, ess_hcurl_tdof);
177 data_.
Ae[level_+1].reset(
183 if (level_ == (
int)data_.
P_l2.size()) { DataFinalize(); }
186void DFSSpaces::DataFinalize()
195 for (
int l = (
int)data_.
P_l2.size()-1; l >= 0; --l)
200 auto cW =
Mult(*PTW, P_l2);
210 :
Solver(B.NumRows()), BBT_solver_(B.GetComm())
225 :
Solver(M.NumRows()+B.NumRows()), local_system_(height), offset_(M.NumRows())
227 local_system_.
CopyMN(M, 0, 0);
228 local_system_.
CopyMN(B, offset_, 0);
229 local_system_.
CopyMNt(B, 0, offset_);
231 local_system_.
SetRow(offset_, 0.0);
232 local_system_.
SetCol(offset_, 0.0);
233 local_system_(offset_, offset_) = -1.0;
239 const real_t x0 = x[offset_];
240 const_cast<Vector&
>(x)[offset_] = 0.0;
243 local_solver_.
Mult(x, y);
245 const_cast<Vector&
>(x)[offset_] = x0;
254 :
Solver(M.NumRows() + B.NumRows()), agg_hdivdof_(agg_hdivdof),
255 agg_l2dof_(agg_l2dof), solvers_loc_(agg_l2dof.NumRows())
270 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
276 M_diag.
GetSubMatrix(hdivdofs_loc_, hdivdofs_loc_, M_loc);
278 solvers_loc_[agg].Reset(
new LocalSolver(M_loc, B_loc));
289 static_cast<Vector&
>(Pi_x) = x;
296 Pi_x.
GetBlock(1) -= coarse_l2_projection;
298 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
303 offsets_loc_[1] = hdivdofs_loc_.
Size();
304 offsets_loc_[2] = offsets_loc_[1]+l2dofs_loc_.
Size();
306 BlockVector rhs_loc(offsets_loc_), sol_loc(offsets_loc_);
310 solvers_loc_[agg]->Mult(rhs_loc, sol_loc);
316 coarse_l2_projector_->
Mult(blk_y.
GetBlock(1), coarse_l2_projection);
317 blk_y.
GetBlock(1) -= coarse_l2_projection;
323 :
DarcySolver(M.NumRows(), B.NumRows()), data_(data), param_(data.param),
325 BBT_solver_(B, param_.BBT_solve_param),
326 ops_offsets_(data.P_l2.size()+1),
327 ops_(ops_offsets_.size()),
328 blk_Ps_(ops_.size()-1),
329 smoothers_(ops_.size())
332 ops_.back() = std::make_unique<BlockOperator>(ops_offsets_.back());
335 ops_.back()->SetBlock(0, 1, BT_.
Ptr());
337 for (
int l = data.
P_l2.size(); l >= 0; --l)
339 auto &M_f =
static_cast<const HypreParMatrix&
>(ops_[l]->GetBlock(0, 0));
340 auto &B_f =
static_cast<const HypreParMatrix&
>(ops_[l]->GetBlock(1, 0));
346 B_f.GetDiag(B_f_diag);
359 smoothers_[l].reset(coarse_solver);
371 agg_l2dof_l, *P_l2_l, Q_l2_l);
378 std::make_unique<ProductSolver>(ops_[l].get(), S0, S1,
false,
true,
true);
382 smoothers_[l].reset(S0);
388 ops_offsets_[l-1].SetSize(3, 0);
389 ops_offsets_[l-1][1] = M_c->
NumRows();
393 std::make_unique<BlockOperator>(ops_offsets_[l], ops_offsets_[l-1]);
394 blk_Ps_[l-1]->SetBlock(0, 0, P_hdiv_l);
395 blk_Ps_[l-1]->SetBlock(1, 1, P_l2_l);
398 std::make_unique<BlockOperator>(ops_offsets_[l-1]);
399 ops_[l-1]->SetBlock(0, 0, M_c);
400 ops_[l-1]->SetBlock(1, 0, B_c);
401 ops_[l-1]->SetBlock(0, 1, B_c->
Transpose());
402 ops_[l-1]->owns_blocks = 1;
405 if (data_.
P_l2.size() == 0) {
return; }
410 own_ops =
false, own_smoothers =
false, own_blk_Ps =
false;
419 for (
size_t i = 0; i < ops_.size(); ++i) { ops[i] = ops_[i].get(); }
420 for (
size_t i = 0; i < blk_Ps_.size(); ++i) { blk_Ps[i] = blk_Ps_[i].get(); }
421 for (
size_t i = 0; i < smoothers_.size(); ++i) { smoothers[i] = smoothers_[i].get(); }
423 own_ops, own_smoothers, own_blk_Ps));
430 ops.
Last() = TwoStepsRAP(C_finest, &M, C_finest);
431 ops.
Last()->EliminateZeroRows();
432 ops.
Last()->DropSmallEntries(1e-14);
437 for (
int l = Ps.
Size()-1; l >= 0; --l)
440 ops[l] = TwoStepsRAP(Ps[l], ops[l+1], Ps[l]);
443 static_cast<HypreSmoother*
>(smoothers[l])->SetOperatorSymmetry(
true);
445 own_ops =
true, own_smoothers =
true;
447 own_ops, own_smoothers, own_blk_Ps));
454void DivFreeSolver::SolveParticular(
const Vector& rhs,
Vector& sol)
const
456 std::vector<Vector> rhss(smoothers_.size()), sols(smoothers_.size());
460 for (
int l = blk_Ps_.size()-1; l >= 0; --l)
462 rhss[l].SetSize(blk_Ps_[l]->
NumCols());
463 sols[l].SetSize(blk_Ps_[l]->
NumCols());
468 blk_Ps_[l]->MultTranspose(rhss[l+1], rhss[l]);
471 for (
size_t l = 0; l < smoothers_.size(); ++l)
473 smoothers_[l]->Mult(rhss[l], sols[l]);
476 for (
size_t l = 0; l < blk_Ps_.size(); ++l)
478 Vector P_sol(blk_Ps_[l]->
NumRows());
479 blk_Ps_[l]->Mult(sols[l], P_sol);
484void DivFreeSolver::SolveDivFree(
const Vector &rhs, Vector& sol)
const
486 Vector rhs_divfree(data_.
C.back()->NumCols());
487 data_.
C.back()->MultTranspose(rhs, rhs_divfree);
489 Vector potential_divfree(rhs_divfree.Size());
490 potential_divfree = 0.0;
491 solver_->
Mult(rhs_divfree, potential_divfree);
493 data_.
C.back()->Mult(potential_divfree, sol);
496void DivFreeSolver::SolvePotential(
const Vector& rhs, Vector& sol)
const
500 BBT_solver_.
Mult(rhs_p, sol);
505 MFEM_VERIFY(x.
Size() ==
offsets_[2],
"MLDivFreeSolver: x size is invalid");
506 MFEM_VERIFY(y.
Size() ==
offsets_[2],
"MLDivFreeSolver: y size is invalid");
508 if (ops_.size() == 1) { smoothers_[0]->Mult(x, y);
return; }
513 ops_.back()->Mult(y, resid);
514 add(1.0, x, -1.0, resid, resid);
521 solver_->
Mult(resid, correction);
529 SolveParticular(resid, correction);
534 cout <<
"Particular solution found in " << ch.
RealTime() <<
"s.\n";
540 ops_.back()->Mult(y, resid);
541 add(1.0, x, -1.0, resid, resid);
548 cout <<
"Divergence free solution found in " << ch.
RealTime() <<
"s.\n";
554 auto& M =
dynamic_cast<const HypreParMatrix&
>(ops_.back()->GetBlock(0, 0));
561 cout <<
"Scalar potential found in " << ch.
RealTime() <<
"s.\n";
568 if (ops_.size() == 1)
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
T * begin()
STL-like begin. Returns pointer to the first element of the array.
T & Last()
Return the last element in the array.
A class to handle Block diagonal preconditioners in a matrix-free implementation.
A class to handle Vectors in a block fashion.
Vector & GetBlock(int i)
Get the i-th vector in the block.
Conjugate gradient method.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication with the inverse of dense matrix.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Data type dense matrix using column-major storage.
void SetRow(int r, const real_t *row)
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
void SetCol(int c, const real_t *col)
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 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.
void AddDomainInterpolator(DiscreteInterpolator *di)
Adds a domain interpolator. Assumes ownership of di.
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
virtual Type GetType() const =0
Returns element's type.
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
static void AdjustVDofs(Array< int > &vdofs)
Remove the orientation information encoded into an array of dofs Some basis function types have a rel...
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...
int GetNE() const
Returns number of elements in the mesh.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
The BoomerAMG solver in hypre.
Wrapper for hypre's ParCSR matrix class.
void DropSmallEntries(real_t tol)
Wrapper for hypre_ParCSRMatrixDropSmallEntries in different versions of hypre. Drop off-diagonal entr...
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
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...
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, real_t alpha=1.0, real_t beta=0.0) const
Computes y = alpha * A * x + beta * y.
MPI_Comm GetComm() const
MPI communicator.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
HypreParMatrix * EliminateCols(const Array< int > &cols)
Parallel smoothers in hypre.
Abstract base class for iterative solver.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
Pointer to an Operator of a specified type.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Operator * Ptr() const
Access the underlying Operator pointer.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
@ MFEM_SPARSEMAT
ID for class SparseMatrix.
@ Hypre_ParCSR
ID for class HypreParMatrix.
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
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 ...
HypreParMatrix * ParallelAssemble() const
Returns the matrix "assembled" on the true dofs.
Abstract parallel finite element space.
Class for parallel meshes.
General product operator: x -> (A*B)(x) = A(B(x)).
void GetDiag(Vector &d) const
Returns the Diagonal of A.
void EliminateRowCol(int rc, const real_t sol, Vector &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Eliminate row rc and column rc and modify the rhs using sol.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
int NumNonZeroElems() const override
Returns the number of the nonzero elements in the matrix.
void EliminateCol(int col, DiagonalPolicy dpolicy=DIAG_ZERO)
Eliminates the column col from the matrix.
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
int RowSize(const int i) const
Returns the number of elements in row i.
double RealTime()
Return the number of real seconds elapsed since the stopwatch was started.
void Start()
Start the stopwatch. The elapsed time is not cleared.
void Clear()
Clear the elapsed time on the stopwatch and restart it if it's running.
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
BBTSolver(const HypreParMatrix &B, IterSolveParameters param)
Wrapper for the block-diagonal-preconditioned MINRES employed in ex5p.cpp.
DFSSpaces(int order, int num_refine, ParMesh *mesh, const Array< int > &ess_attr, const DFSParameters ¶m)
Abstract solver class for Darcy's flow.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
int GetNumIterations() const override
DivFreeSolver(const HypreParMatrix &M, const HypreParMatrix &B, const DFSData &data)
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
Solver for local problems in SaddleSchwarzSmoother.
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
LocalSolver(const DenseMatrix &M, const DenseMatrix &B)
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
SaddleSchwarzSmoother(const HypreParMatrix &M, const HypreParMatrix &B, const SparseMatrix &agg_hdivdof, const SparseMatrix &agg_l2dof, const HypreParMatrix &P_l2, const ProductOperator &Q_l2)
Block diagonal solver for symmetric A, each block is inverted by direct solver.
void SetOptions(IterativeSolver &solver, const IterSolveParameters ¶m)
void GetRowColumnsRef(const SparseMatrix &A, int row, Array< int > &cols)
SparseMatrix * AggToInteriorDof(const Array< int > &bdr_truedofs, const SparseMatrix &agg_elem, const SparseMatrix &elem_dof, const HypreParMatrix &dof_truedof, Array< HYPRE_BigInt > &agg_starts)
SparseMatrix ElemToDof(const ParFiniteElementSpace &fes)
OperatorHandle OperatorPtr
Add an alternative name for OperatorHandle – OperatorPtr.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void add(const Vector &v1, const Vector &v2, Vector &v)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
Data for the divergence free solver.
std::vector< OperatorPtr > agg_l2dof
Array< int > coarsest_ess_hdivdofs
std::vector< UniqueOperatorPtr > P_l2
std::vector< OperatorPtr > Q_l2
std::vector< UniqueHypreParMatrix > Ae
std::vector< UniqueOperatorPtr > P_hdiv
std::vector< UniqueOperatorPtr > P_hcurl
std::vector< OperatorPtr > agg_hdivdof
std::vector< OperatorPtr > C
Parameters for the divergence free solver.
IterSolveParameters coarse_solve_param