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");
76 el_l2dof_.reserve(num_refine+1);
77 el_l2dof_.push_back(
ElemToDof(*coarse_l2_fes_));
83 data_.
Q_l2.resize(num_refine);
85 data_.
C.resize(num_refine+1);
107 int * I =
new int [tdof_agg.
NumRows()+1]();
114 for (
int i = 0; i < tdof_agg.
NumRows(); ++i)
116 bool agg_bdr = is_bdr[i] || is_shared.
RowSize(i) || tdof_agg.
RowSize(i)>1;
117 if (agg_bdr) { I[i+1] = I[i];
continue; }
123 std::fill_n(D, I[tdof_agg.
NumRows()], 1.0);
129void DFSSpaces::MakeDofRelationTables(
int level)
133 auto& elem_agg = (
const SparseMatrix&)*l2_0_fes_->GetUpdateOperator();
137 el_l2dof_.push_back(
ElemToDof(*l2_fes_));
138 data_.
agg_l2dof[level].Reset(
Mult(agg_el, el_l2dof_[level+1]));
141 hdiv_fes_->GetEssentialTrueDofs(all_bdr_attr_, bdr_tdofs);
143 *hdiv_fes_->Dof_TrueDof_Matrix(), agg_starts);
149 auto GetP = [
this](
OperatorPtr& P, unique_ptr<ParFiniteElementSpace>& cfes,
153 fes.GetTrueTransferOperator(*cfes, P);
158 (level_ < (int)data_.
P_l2.size()-1) ? cfes->Update() : cfes.reset();
161 GetP(data_.
P_hdiv[level_], coarse_hdiv_fes_, *hdiv_fes_,
true);
162 GetP(data_.
P_l2[level_], coarse_l2_fes_, *l2_fes_,
false);
163 MakeDofRelationTables(level_);
165 GetP(data_.
P_hcurl[level_], coarse_hcurl_fes_, *hcurl_fes_,
true);
173 hcurl_fes_->GetEssentialTrueDofs(ess_bdr_attr_, ess_hcurl_tdof);
178 if (level_ == (
int)data_.
P_l2.size()) { DataFinalize(); }
181void DFSSpaces::DataFinalize()
190 for (
int l = (
int)data_.
P_l2.size()-1; l >= 0; --l)
195 auto cW =
Mult(*PTW, P_l2);
205 :
Solver(B.NumRows()), BBT_solver_(B.GetComm())
220 :
Solver(M.NumRows()+B.NumRows()), local_system_(height), offset_(M.NumRows())
222 local_system_.
CopyMN(M, 0, 0);
223 local_system_.
CopyMN(B, offset_, 0);
224 local_system_.
CopyMNt(B, 0, offset_);
226 local_system_.
SetRow(offset_, 0.0);
227 local_system_.
SetCol(offset_, 0.0);
228 local_system_(offset_, offset_) = -1.0;
234 const real_t x0 = x[offset_];
235 const_cast<Vector&
>(x)[offset_] = 0.0;
238 local_solver_.
Mult(x, y);
240 const_cast<Vector&
>(x)[offset_] = x0;
249 :
Solver(M.NumRows() + B.NumRows()), agg_hdivdof_(agg_hdivdof),
250 agg_l2dof_(agg_l2dof), solvers_loc_(agg_l2dof.NumRows())
265 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
271 M_diag.
GetSubMatrix(hdivdofs_loc_, hdivdofs_loc_, M_loc);
273 solvers_loc_[agg].Reset(
new LocalSolver(M_loc, B_loc));
284 static_cast<Vector&
>(Pi_x) = x;
291 Pi_x.
GetBlock(1) -= coarse_l2_projection;
293 for (
int agg = 0; agg < (int)solvers_loc_.size(); agg++)
298 offsets_loc_[1] = hdivdofs_loc_.
Size();
299 offsets_loc_[2] = offsets_loc_[1]+l2dofs_loc_.
Size();
301 BlockVector rhs_loc(offsets_loc_), sol_loc(offsets_loc_);
305 solvers_loc_[agg]->Mult(rhs_loc, sol_loc);
311 coarse_l2_projector_->
Mult(blk_y.
GetBlock(1), coarse_l2_projection);
312 blk_y.
GetBlock(1) -= coarse_l2_projection;
317 :
DarcySolver(M.NumRows(), B.NumRows()), data_(data), param_(data.param),
318 BT_(B.
Transpose()), BBT_solver_(B, param_.BBT_solve_param),
319 ops_offsets_(data.P_l2.size()+1), ops_(ops_offsets_.size()),
320 blk_Ps_(ops_.Size()-1), smoothers_(ops_.Size())
326 ops_.Last()->SetBlock(0, 1, BT_.
Ptr());
328 for (
int l = data.
P_l2.size(); l >= 0; --l)
330 auto& M_f =
static_cast<const HypreParMatrix&
>(ops_[l]->GetBlock(0, 0));
331 auto& B_f =
static_cast<const HypreParMatrix&
>(ops_[l]->GetBlock(1, 0));
337 B_f.GetDiag(B_f_diag);
350 smoothers_[l] = coarse_solver;
362 agg_l2dof_l, P_l2_l, Q_l2_l);
367 S1->owns_blocks =
true;
368 smoothers_[l] =
new ProductSolver(ops_[l], S0, S1,
false,
true,
true);
378 ops_offsets_[l-1].SetSize(3, 0);
379 ops_offsets_[l-1][1] = M_c->
NumRows();
382 blk_Ps_[l-1] =
new BlockOperator(ops_offsets_[l], ops_offsets_[l-1]);
383 blk_Ps_[l-1]->SetBlock(0, 0, &P_hdiv_l);
384 blk_Ps_[l-1]->SetBlock(1, 1, &P_l2_l);
387 ops_[l-1]->SetBlock(0, 0, M_c);
388 ops_[l-1]->SetBlock(1, 0, B_c);
389 ops_[l-1]->SetBlock(0, 1, B_c->
Transpose());
390 ops_[l-1]->owns_blocks =
true;
397 own_smoothers =
true;
400 if (data_.
P_l2.size() == 0) {
return; }
407 own_ops, own_smoothers, own_Ps));
418 ops.
Last()->EliminateZeroRows();
419 ops.
Last()->DropSmallEntries(1e-14);
426 for (
int l = Ps.
Size()-1; l >= 0; --l)
432 static_cast<HypreSmoother*
>(smoothers[l])->SetOperatorSymmetry(
true);
435 prec_.
Reset(
new Multigrid(ops, smoothers, Ps, own_ops, own_smoothers, own_Ps));
445 for (
int i = 0; i < ops_.Size(); ++i)
448 delete smoothers_[i];
449 if (i == ops_.Size() - 1) {
break; }
454void DivFreeSolver::SolveParticular(
const Vector& rhs,
Vector& sol)
const
456 std::vector<Vector> rhss(smoothers_.Size());
457 std::vector<Vector> sols(smoothers_.Size());
462 for (
int l = blk_Ps_.Size()-1; l >= 0; --l)
464 rhss[l].SetSize(blk_Ps_[l]->
NumCols());
465 sols[l].SetSize(blk_Ps_[l]->
NumCols());
470 blk_Ps_[l]->MultTranspose(rhss[l+1], rhss[l]);
473 for (
int l = 0; l < smoothers_.Size(); ++l)
475 smoothers_[l]->Mult(rhss[l], sols[l]);
478 for (
int l = 0; l < blk_Ps_.Size(); ++l)
480 Vector P_sol(blk_Ps_[l]->
NumRows());
481 blk_Ps_[l]->Mult(sols[l], P_sol);
486void DivFreeSolver::SolveDivFree(
const Vector &rhs, Vector& sol)
const
488 Vector rhs_divfree(data_.
C.back()->NumCols());
489 data_.
C.back()->MultTranspose(rhs, rhs_divfree);
491 Vector potential_divfree(rhs_divfree.Size());
492 potential_divfree = 0.0;
493 solver_->
Mult(rhs_divfree, potential_divfree);
495 data_.
C.back()->Mult(potential_divfree, sol);
498void DivFreeSolver::SolvePotential(
const Vector& rhs, Vector& sol)
const
502 BBT_solver_.
Mult(rhs_p, sol);
507 MFEM_VERIFY(x.
Size() ==
offsets_[2],
"MLDivFreeSolver: x size is invalid");
508 MFEM_VERIFY(y.
Size() ==
offsets_[2],
"MLDivFreeSolver: y size is invalid");
510 if (ops_.Size() == 1) { smoothers_[0]->Mult(x, y);
return; }
515 ops_.Last()->Mult(y, resid);
516 add(1.0, x, -1.0, resid, resid);
523 solver_->
Mult(resid, correction);
531 SolveParticular(resid, correction);
536 cout <<
"Particular solution found in " << ch.
RealTime() <<
"s.\n";
542 ops_.Last()->Mult(y, resid);
543 add(1.0, x, -1.0, resid, resid);
550 cout <<
"Divergence free solution found in " << ch.
RealTime() <<
"s.\n";
556 auto& M =
dynamic_cast<const HypreParMatrix&
>(ops_.Last()->GetBlock(0, 0));
563 cout <<
"Scalar potential found in " << ch.
RealTime() <<
"s.\n";
570 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 Block systems 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.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication with the inverse of dense matrix.
virtual void SetOperator(const Operator &op)
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().
Arbitrary order H1-conforming (continuous) finite elements.
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.
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.
Arbitrary order H(curl)-conforming Nedelec finite 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
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.
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
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.
BBTSolver(const HypreParMatrix &B, IterSolveParameters param)
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
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.
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
DivFreeSolver(const HypreParMatrix &M, const HypreParMatrix &B, const DFSData &data)
virtual int GetNumIterations() const
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
Solver for local problems in SaddleSchwarzSmoother.
virtual void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
LocalSolver(const DenseMatrix &M, const DenseMatrix &B)
virtual void Mult(const Vector &x, Vector &y) const
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 HypreParMatrix &Q_l2)
Block diagonal solver for symmetric A, each block is inverted by direct solver.
HypreParMatrix * TwoStepsRAP(const HypreParMatrix &Rt, const HypreParMatrix &A, const HypreParMatrix &P)
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
std::vector< OperatorPtr > P_hcurl
Array< int > coarsest_ess_hdivdofs
std::vector< OperatorPtr > P_hdiv
std::vector< OperatorPtr > P_l2
std::vector< OperatorPtr > Q_l2
std::vector< OperatorPtr > agg_hdivdof
std::vector< OperatorPtr > C
Parameters for the divergence free solver.
IterSolveParameters coarse_solve_param