14 #include "../fem/fespace.hpp"
15 #include "../fem/pfespace.hpp"
26 lagrange_tdofs(lagrange_tdofs_),
27 primary_tdofs(primary_tdofs_),
28 secondary_tdofs(secondary_tdofs_)
30 MFEM_VERIFY(lagrange_tdofs.
Size() == secondary_tdofs.
Size(),
31 "Dof sizes don't match!");
92 eliminators(eliminators_)
98 MFEM_ASSERT(vin.
Size() ==
width,
"Wrong vector size!");
99 MFEM_ASSERT(vout.
Size() ==
height,
"Wrong vector size!");
103 for (
int k = 0; k < eliminators.Size(); ++k)
116 MFEM_ASSERT(vin.
Size() ==
height,
"Wrong vector size!");
117 MFEM_ASSERT(vout.
Size() ==
width,
"Wrong vector size!");
121 for (
int k = 0; k < eliminators.Size(); ++k)
128 vout.AddElementVector(elim->
PrimaryDofs(), subvec_out);
137 for (
int i = 0; i <
height; ++i)
142 for (
int k = 0; k < eliminators.Size(); ++k)
153 mat->
Add(i, j, mat_k(iz, jz));
165 MFEM_ASSERT(rtilde.
Size() == Aop.
Height(),
"Sizes don't match!");
168 for (
int k = 0; k < eliminators.Size(); ++k)
183 MFEM_ASSERT(disp.
Size() == Aop.
Height(),
"Sizes don't match!");
186 Aop.
Mult(disp, fullrhs);
189 for (
int k = 0; k < eliminators.Size(); ++k)
229 delete explicit_projector;
230 delete h_explicit_projector;
242 MFEM_VERIFY(secondary_dofs.
Size() == B.
Height(),
243 "Wrong number of dofs for elimination!");
245 for (
int i = 0; i < lagrange_dofs.Size(); ++i)
247 lagrange_dofs[i] = i;
269 for (
int k = 0; k < constraint_rowstarts.
Size() - 1; ++k)
271 int constraint_size = constraint_rowstarts[k + 1] -
272 constraint_rowstarts[k];
278 for (
int i = constraint_rowstarts[k]; i < constraint_rowstarts[k + 1]; ++i)
280 lagrange_dofs[i - constraint_rowstarts[k]] = i;
281 for (
int jptr = I[i]; jptr < I[i + 1]; ++jptr)
284 double val = data[jptr];
285 if (std::abs(val) > 1.e-12 && secondary_dofs.
Find(j) == -1)
287 secondary_dofs[i - constraint_rowstarts[k]] = j;
293 for (
int i = constraint_rowstarts[k]; i < constraint_rowstarts[k + 1]; ++i)
295 MFEM_ASSERT(secondary_dofs[i - constraint_rowstarts[k]] >= 0,
296 "Secondary dofs don't match rows!");
297 for (
int jptr = I[i]; jptr < I[i + 1]; ++jptr)
300 if (secondary_dofs.
Find(j) == -1)
347 hA.
Mult(-1.0, rtilde, 1.0, temprhs);
383 MPI_Comm_rank(A.
GetComm(), &rank);
384 MPI_Comm_size(A.
GetComm(), &size);
386 int constraint_running_total = 0;
387 int local_constraints = B.
Height();
388 MPI_Scan(&local_constraints, &constraint_running_total, 1, MPI_INT,
390 int global_constraints = 0;
391 if (rank == size - 1) { global_constraints = constraint_running_total; }
392 MPI_Bcast(&global_constraints, 1, MPI_INT, size - 1, A.
GetComm());
396 HYPRE_BigInt row_starts[2] = { constraint_running_total - local_constraints,
397 constraint_running_total
401 row_starts, col_starts, &
B);
478 penalized_rhs += temp;
502 class IdentitySolver :
public Solver
505 IdentitySolver(
int size) :
Solver(size) { }
506 void Mult(
const Vector& x, Vector& y)
const { y = x; }
507 void SetOperator(
const Operator& op) { }
510 void SchurConstrainedSolver::Initialize()
519 tr_B =
new TransposeOperator(&
B);
533 primal_pc(&primal_pc_),
550 primal_pc(&primal_pc_),
599 if (
GetComm() != MPI_COMM_NULL)
614 const_cast<BlockDiagonalPreconditioner&>(*
block_pc));
638 h_primal_pc->SetPrintLevel(0);
641 h_primal_pc->SetSystemsOptions(dimension, reorder);
655 schur_mat =
ParMult(scaledB, scaledBT);
659 h_dual_pc->SetPrintLevel(0);
675 void ConstrainedSolver::Initialize()
715 for (
int i = 0; i < f.
Size(); ++i)
720 for (
int i = 0; i <
B.
Height(); ++i)
727 for (
int i = 0; i < f.
Size(); ++i)
731 for (
int i = 0; i <
B.
Height(); ++i)
738 Vector& x_and_lambda)
const
755 int node,
bool parallel,
int d=0)
764 const int vdof = pfespace->
DofToVDof(node, d);
769 MFEM_ABORT(
"Asked for parallel form of serial object!");
791 std::map<int, int> dof_bconstraint;
794 std::vector<std::map<int, int> > constraints;
795 int n_bconstraints = 0;
797 for (
int att : constrained_att)
800 std::set<int> constrained_tdofs;
801 for (
int i = 0; i < fespace.
GetNBE(); ++i)
814 if (tdof >= 0) { constrained_tdofs.insert(tdof); }
820 for (
auto k : constrained_tdofs)
822 auto it = dof_bconstraint.find(k);
823 if (it == dof_bconstraint.end())
826 dof_bconstraint[k] = n_bconstraints++;
827 constraints.emplace_back();
828 constraints.back()[att] = n_rows++;
833 constraints[it->second][att] = n_rows++;
841 std::map<int, int> reorder_rows;
844 constraint_rowstarts.
Append(0);
845 for (
auto& it : dof_bconstraint)
847 int bconstraint_index = it.second;
848 bool nconstraint =
false;
849 for (
auto& att_it : constraints[bconstraint_index])
851 auto rrit = reorder_rows.find(att_it.second);
852 if (rrit == reorder_rows.end())
855 reorder_rows[att_it.second] = new_row++;
858 if (nconstraint) { constraint_rowstarts.
Append(new_row); }
860 MFEM_VERIFY(new_row == n_rows,
"Remapping failed!");
861 for (
auto& constraint_map : constraints)
863 for (
auto& it : constraint_map)
865 it.second = reorder_rows[it.second];
875 std::map<int, int> node_visits;
876 for (
int i = 0; i < fespace.
GetNBE(); ++i)
879 if (constrained_att.FindSorted(att) != -1)
887 MFEM_VERIFY(dofs.
Size() == nodes.
Size(),
888 "Something wrong in finite element space!");
890 for (
int j = 0; j < dofs.
Size(); ++j)
901 auto nv_it = node_visits.find(truek);
902 if (nv_it == node_visits.end())
904 node_visits[truek] = 1;
908 node_visits[truek]++;
910 int visits = node_visits[truek];
911 int bconstraint = dof_bconstraint[truek];
912 int row = constraints[bconstraint][att];
913 for (
int d = 0; d <
dim; ++d)
919 mout->
Add(row, inner_truek, nor[d]);
924 const double pv = mout->
SearchRow(inner_truek);
925 const double scaling = ((double) (visits - 1)) /
929 mout->
Set(row, inner_truek,
930 scaling * pv + (1.0 / visits) * nor[d]);
949 constraint_rowstarts,
true);
Abstract class for all finite elements.
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
int Size() const
Return the logical size of the array.
void Eliminate(const Vector &in, Vector &out) const
MPI_Comm GetComm() const
MPI communicator.
Class for an integration rule - an Array of IntegrationPoint.
void Mult(const Vector &x, Vector &y) const override
Solve for given .
HypreParMatrix * penalized_mat
int DofToVDof(int dof, int vd, int ndofs=-1) const
void Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T...
int GetNumIterations() const
MPI_Comm GetComm() const
Return the associated MPI communicator, or MPI_COMM_NULL if no communicator is set.
Array< int > & RowOffsets()
Return the row offsets for block starts.
SparseMatrix * ParBuildNormalConstraints(ParFiniteElementSpace &fespace, Array< int > &constrained_att, Array< int > &constraint_rowstarts)
Parallel wrapper for BuildNormalConstraints.
Solve constrained system by solving original mixed system; see ConstrainedSolver. ...
EliminationSolver(HypreParMatrix &A, SparseMatrix &B, Array< int > &primary_dofs, Array< int > &secondary_dofs)
Constructor, with explicit splitting into primary/secondary dofs.
void Mult(const Vector &x, Vector &y) const override
Operator application: y=A(x).
void Initialize(HypreParMatrix &A, HypreParMatrix &B, HypreParMatrix &D)
virtual void Finalize(int skip_zeros=1)
Finalize the matrix initialization, switching the storage format from LIL to CSR. ...
SparseMatrix * BuildNormalConstraints(FiniteElementSpace &fespace, Array< int > &constrained_att, Array< int > &constraint_rowstarts, bool parallel)
Build a matrix constraining normal components to zero.
void SetSize(int s)
Resize the vector to size s.
double & SearchRow(const int col)
Perform a fast search for an entry in the "current row". See SetColPtr().
virtual DofTransformation * GetBdrElementDofs(int bel, Array< int > &dofs) const
Returns indices of degrees of freedom for boundary element 'bel'.
bool Empty() const
Check if the SparseMatrix is empty.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
SchurConstrainedHypreSolver(MPI_Comm comm, HypreParMatrix &hA_, HypreParMatrix &hB_, Solver *prec=nullptr, int dimension=0, bool reorder=false)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int CanonicalNodeNumber(FiniteElementSpace &fespace, int node, bool parallel, int d=0)
int * GetJ()
Return the array J.
EliminationProjection(const Operator &A, Array< Eliminator * > &eliminators)
An abstract class to solve the constrained system subject to the constraint .
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
int GetBdrAttribute(int i) const
int * GetI()
Return the array I.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Abstract parallel finite element space.
double * HostReadWrite()
Shortcut for mfem::ReadWrite(GetMemory(), TotalSize(), false).
HypreParMatrix * h_explicit_operator
Eliminator(const SparseMatrix &B, const Array< int > &lagrange_dofs, const Array< int > &primary_tdofs, const Array< int > &secondary_tdofs)
bool GetConverged() const
int GetLocalTDofNumber(int ldof) const
void MultTranspose(const Vector &x, Vector &y) const override
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
double * GetData() const
Returns the matrix data array.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void CalcOrtho(const DenseMatrix &J, Vector &n)
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
virtual Solver * BuildPreconditioner() const =0
Build preconditioner for penalized system.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
void DeleteAll()
Delete the whole array.
Array< Eliminator * > eliminators
Operator & GetBlock(int i, int j)
Return a reference to block i,j.
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 ...
ConstrainedSolver(MPI_Comm comm, Operator &A_, Operator &B_)
double GetFinalNorm() const
double * GetData()
Return the element data, i.e. the array A.
virtual void Mult(const Vector &f, Vector &x) const override
Solve for given .
HYPRE_BigInt N() const
Returns the global number of columns.
HYPRE_BigInt M() const
Returns the global number of rows.
void EliminateZeroRows()
If a row contains only zeros, set its diagonal to 1.
virtual void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
void LagrangeSecondary(const Vector &in, Vector &out) const
Maps Lagrange multipliers to secondary dofs, applies .
HYPRE_BigInt * GetRowStarts() const
Return the parallel row partitioning array.
void Set(const int i, const int j, const double val)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
The BoomerAMG solver in hypre.
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
void BuildGTilde(const Vector &g, Vector >ilde) const
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
double f(const Vector &xvec)
int GetNBE() const
Returns number of boundary elements in the mesh.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Perform elimination of a single constraint.
virtual IterativeSolver * BuildKrylov() const =0
Select krylov solver for penalized system.
virtual ~SchurConstrainedSolver()
const Array< int > & PrimaryDofs() const
void SetMaxIter(int max_it)
void RecoverMultiplier(const Vector &primalrhs, const Vector &primalvars, Vector &lm) const
virtual void SetConstraintRHS(const Vector &r)
Set the right-hand side r for the constraint B x = r.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
ElementTransformation * GetBdrElementTransformation(int i) const
Returns ElementTransformation for the i-th boundary element.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
void ExplicitAssembly(DenseMatrix &mat) const
Return explicitly assembled in mat.
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
virtual void Solve(int m, int n, double *X) const
int GetVDim() const
Returns vector dimension.
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
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...
void EliminateTranspose(const Vector &in, Vector &out) const
Transpose of Eliminate(), applies .
void BuildExplicitOperator()
Internal utility routine; assembles eliminated matrix explicitly.
void Add(const int i, const int j, const double val)
virtual ~SchurConstrainedHypreSolver()
~PenaltyConstrainedSolver()
void SetAbsTol(double atol)
PrintLevel print_options
Output behavior for the iterative solver.
void SetRelTol(double rtol)
PenaltyConstrainedSolver(HypreParMatrix &A, SparseMatrix &B, double penalty_)
Abstract base class for iterative solver.
void Transpose()
(*this) = (*this)^t
void GetMultiplierSolution(Vector &lambda) const
Return the Lagrange multiplier solution in lambda.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int max_iter
Limit for the number of iterations the solver is allowed to do.
virtual void LagrangeSystemMult(const Vector &f_and_r, Vector &x_and_lambda) const
Solve for (x, lambda) given (f, r)
SchurConstrainedSolver(MPI_Comm comm, Operator &A_, Operator &B_, Solver &primal_pc_)
HypreParMatrix * ParAdd(const HypreParMatrix *A, const HypreParMatrix *B)
Returns the matrix A + B.
virtual Solver * BuildPreconditioner() const =0
Build preconditioner for eliminated system.
int height
Dimension of the output / number of rows in the matrix.
EliminationProjection * projector
double rel_tol
Relative tolerance.
void Mult(const Vector &x, Vector &y) const override
Solve for given .
HYPRE_BigInt GetGlobalNumRows() const
Return the global number of rows.
HYPRE_BigInt * ColPart()
Returns the column partitioning.
void InvScaleRows(const Vector &s)
Scale the local row i by 1./s(i)
HYPRE_BigInt * RowPart()
Returns the row partitioning.
virtual bool Factor(int m, double TOL=0.0)
Compute the LU factorization of the current matrix.
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
virtual void LagrangeSystemMult(const Vector &x, Vector &y) const override
Solve for (x, lambda) given (f, r)
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
virtual IterativeSolver * BuildKrylov() const =0
Select krylov solver for eliminated system.
void Mult(const double *x, double *y) const
Matrix vector multiplication.
const Array< int > & LagrangeDofs() const
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
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.
BlockDiagonalPreconditioner * block_pc
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
SparseMatrix * AssembleExact() const
Assemble this projector as a (processor-local) SparseMatrix.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Wrapper for hypre's ParCSR matrix class.
void LagrangeSecondaryTranspose(const Vector &in, Vector &out) const
Transpose of LagrangeSecondary()
int width
Dimension of the input / number of columns in the matrix.
void SetBlock(int iRow, int iCol, Operator *op, double c=1.0)
Add a block op in the block-entry (iblock, jblock).
const Array< int > & SecondaryDofs() const
double abs_tol
Absolute tolerance.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).