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)
343 hA.
Mult(-1.0, rtilde, 1.0, temprhs);
381 MPI_Comm_rank(A.
GetComm(), &rank);
382 MPI_Comm_size(A.
GetComm(), &size);
384 int constraint_running_total = 0;
385 int local_constraints = B.
Height();
386 MPI_Scan(&local_constraints, &constraint_running_total, 1, MPI_INT,
388 int global_constraints = 0;
389 if (rank == size - 1) { global_constraints = constraint_running_total; }
390 MPI_Bcast(&global_constraints, 1, MPI_INT, size - 1, A.
GetComm());
394 HYPRE_BigInt row_starts[2] = { constraint_running_total - local_constraints,
395 constraint_running_total
399 row_starts, col_starts, &
B);
444 penalized_rhs += temp;
468 class IdentitySolver :
public Solver
471 IdentitySolver(
int size) :
Solver(size) { }
472 void Mult(
const Vector& x, Vector& y)
const { y = x; }
473 void SetOperator(
const Operator& op) { }
476 void SchurConstrainedSolver::Initialize()
485 tr_B =
new TransposeOperator(&
B);
499 primal_pc(&primal_pc_),
516 primal_pc(&primal_pc_),
565 if (
GetComm() != MPI_COMM_NULL)
580 const_cast<BlockDiagonalPreconditioner&>(*
block_pc));
599 h_primal_pc->SetPrintLevel(0);
602 h_primal_pc->SetSystemsOptions(dimension, reorder);
611 schur_mat =
ParMult(scaledB, scaledBT);
615 h_dual_pc->SetPrintLevel(0);
631 void ConstrainedSolver::Initialize()
671 for (
int i = 0; i < f.
Size(); ++i)
676 for (
int i = 0; i <
B.
Height(); ++i)
683 for (
int i = 0; i < f.
Size(); ++i)
687 for (
int i = 0; i <
B.
Height(); ++i)
694 Vector& x_and_lambda)
const
711 int node,
bool parallel,
int d=0)
720 const int vdof = pfespace->
DofToVDof(node, d);
725 MFEM_ABORT(
"Asked for parallel form of serial object!");
747 std::map<int, int> dof_bconstraint;
750 std::vector<std::map<int, int> > constraints;
751 int n_bconstraints = 0;
753 for (
int att : constrained_att)
756 std::set<int> constrained_tdofs;
757 for (
int i = 0; i < fespace.
GetNBE(); ++i)
770 if (tdof >= 0) { constrained_tdofs.insert(tdof); }
776 for (
auto k : constrained_tdofs)
778 auto it = dof_bconstraint.find(k);
779 if (it == dof_bconstraint.end())
782 dof_bconstraint[k] = n_bconstraints++;
783 constraints.emplace_back();
784 constraints.back()[att] = n_rows++;
789 constraints[it->second][att] = n_rows++;
797 std::map<int, int> reorder_rows;
800 constraint_rowstarts.
Append(0);
801 for (
auto& it : dof_bconstraint)
803 int bconstraint_index = it.second;
804 bool nconstraint =
false;
805 for (
auto& att_it : constraints[bconstraint_index])
807 auto rrit = reorder_rows.find(att_it.second);
808 if (rrit == reorder_rows.end())
811 reorder_rows[att_it.second] = new_row++;
814 if (nconstraint) { constraint_rowstarts.
Append(new_row); }
816 MFEM_VERIFY(new_row == n_rows,
"Remapping failed!");
817 for (
auto& constraint_map : constraints)
819 for (
auto& it : constraint_map)
821 it.second = reorder_rows[it.second];
831 std::map<int, int> node_visits;
832 for (
int i = 0; i < fespace.
GetNBE(); ++i)
835 if (constrained_att.FindSorted(att) != -1)
843 MFEM_VERIFY(dofs.
Size() == nodes.
Size(),
844 "Something wrong in finite element space!");
846 for (
int j = 0; j < dofs.
Size(); ++j)
857 auto nv_it = node_visits.find(truek);
858 if (nv_it == node_visits.end())
860 node_visits[truek] = 1;
864 node_visits[truek]++;
866 int visits = node_visits[truek];
867 int bconstraint = dof_bconstraint[truek];
868 int row = constraints[bconstraint][att];
869 for (
int d = 0; d <
dim; ++d)
875 mout->
Add(row, inner_truek, nor[d]);
880 const double pv = mout->
SearchRow(inner_truek);
881 const double scaling = ((double) (visits - 1)) /
885 mout->
Set(row, inner_truek,
886 scaling * pv + (1.0 / visits) * nor[d]);
905 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.
HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
Returns the matrix P^t * A * P.
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).
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.
SchurConstrainedHypreSolver(MPI_Comm comm, HypreParMatrix &hA_, HypreParMatrix &hB_, int dimension=0, bool reorder=false)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
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.
void Initialize(HypreParMatrix &A, HypreParMatrix &B)
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.
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.
void Solve(int m, int n, double *X) const
int GetVDim() const
Returns vector dimension.
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)
bool Factor(int m, double TOL=0.0)
Compute the LU factorization of the current matrix.
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).