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!");
91 eliminators(eliminators_)
97 MFEM_ASSERT(in.
Size() ==
width,
"Wrong vector size!");
98 MFEM_ASSERT(out.
Size() ==
height,
"Wrong vector size!");
102 for (
int k = 0; k < eliminators.Size(); ++k)
115 MFEM_ASSERT(in.
Size() ==
height,
"Wrong vector size!");
116 MFEM_ASSERT(out.
Size() ==
width,
"Wrong vector size!");
120 for (
int k = 0; k < eliminators.Size(); ++k)
127 out.AddElementVector(elim->
PrimaryDofs(), subvec_out);
136 for (
int i = 0; i <
height; ++i)
141 for (
int k = 0; k < eliminators.Size(); ++k)
152 out->
Add(i, j, mat(iz, jz));
164 MFEM_ASSERT(rtilde.
Size() == Aop.
Height(),
"Sizes don't match!");
167 for (
int k = 0; k < eliminators.Size(); ++k)
182 MFEM_ASSERT(disp.
Size() == Aop.
Height(),
"Sizes don't match!");
185 Aop.
Mult(disp, fullrhs);
188 for (
int k = 0; k < eliminators.Size(); ++k)
228 delete explicit_projector;
229 delete h_explicit_projector;
241 MFEM_VERIFY(secondary_dofs.
Size() == B.
Height(),
242 "Wrong number of dofs for elimination!");
244 for (
int i = 0; i < lagrange_dofs.Size(); ++i)
246 lagrange_dofs[i] = i;
268 for (
int k = 0; k < constraint_rowstarts.
Size() - 1; ++k)
270 int constraint_size = constraint_rowstarts[k + 1] -
271 constraint_rowstarts[k];
277 for (
int i = constraint_rowstarts[k]; i < constraint_rowstarts[k + 1]; ++i)
279 lagrange_dofs[i - constraint_rowstarts[k]] = i;
280 for (
int jptr = I[i]; jptr < I[i + 1]; ++jptr)
283 double val = data[jptr];
284 if (std::abs(val) > 1.e-12 && secondary_dofs.
Find(j) == -1)
286 secondary_dofs[i - constraint_rowstarts[k]] = j;
292 for (
int i = constraint_rowstarts[k]; i < constraint_rowstarts[k + 1]; ++i)
294 MFEM_ASSERT(secondary_dofs[i - constraint_rowstarts[k]] >= 0,
295 "Secondary dofs don't match rows!");
296 for (
int jptr = I[i]; jptr < I[i + 1]; ++jptr)
299 if (secondary_dofs.
Find(j) == -1)
342 hA.
Mult(-1.0, rtilde, 1.0, temprhs);
380 MPI_Comm_rank(A.
GetComm(), &rank);
381 MPI_Comm_size(A.
GetComm(), &size);
383 int constraint_running_total = 0;
384 int local_constraints = B.
Height();
385 MPI_Scan(&local_constraints, &constraint_running_total, 1, MPI_INT,
387 int global_constraints = 0;
388 if (rank == size - 1) { global_constraints = constraint_running_total; }
389 MPI_Bcast(&global_constraints, 1, MPI_INT, size - 1, A.
GetComm());
393 HYPRE_BigInt row_starts[2] = { constraint_running_total - local_constraints,
394 constraint_running_total
398 row_starts, col_starts, &
B);
443 penalized_rhs += temp;
467 class IdentitySolver :
public Solver
470 IdentitySolver(
int size) :
Solver(size) { }
471 void Mult(
const Vector& x, Vector& y)
const { y = x; }
472 void SetOperator(
const Operator& op) { }
475 void SchurConstrainedSolver::Initialize()
484 tr_B =
new TransposeOperator(&
B);
498 primal_pc(&primal_pc_),
515 primal_pc(&primal_pc_),
564 if (
GetComm() != MPI_COMM_NULL)
579 const_cast<BlockDiagonalPreconditioner&>(*
block_pc));
598 h_primal_pc->SetPrintLevel(0);
601 h_primal_pc->SetSystemsOptions(dimension, reorder);
610 schur_mat =
ParMult(scaledB, scaledBT);
614 h_dual_pc->SetPrintLevel(0);
630 void ConstrainedSolver::Initialize()
670 for (
int i = 0; i < f.
Size(); ++i)
675 for (
int i = 0; i <
B.
Height(); ++i)
682 for (
int i = 0; i < f.
Size(); ++i)
686 for (
int i = 0; i <
B.
Height(); ++i)
693 Vector& x_and_lambda)
const
710 int node,
bool parallel,
int d=0)
719 const int vdof = pfespace->
DofToVDof(node, d);
724 MFEM_ABORT(
"Asked for parallel form of serial object!");
746 std::map<int, int> dof_bconstraint;
749 std::vector<std::map<int, int> > constraints;
750 int n_bconstraints = 0;
752 for (
int att : constrained_att)
755 std::set<int> constrained_tdofs;
756 for (
int i = 0; i < fespace.
GetNBE(); ++i)
769 if (tdof >= 0) { constrained_tdofs.insert(tdof); }
775 for (
auto k : constrained_tdofs)
777 auto it = dof_bconstraint.find(k);
778 if (it == dof_bconstraint.end())
781 dof_bconstraint[k] = n_bconstraints++;
782 constraints.emplace_back();
783 constraints.back()[att] = n_rows++;
788 constraints[it->second][att] = n_rows++;
796 std::map<int, int> reorder_rows;
799 constraint_rowstarts.
Append(0);
800 for (
auto& it : dof_bconstraint)
802 int bconstraint_index = it.second;
803 bool nconstraint =
false;
804 for (
auto& att_it : constraints[bconstraint_index])
806 auto rrit = reorder_rows.find(att_it.second);
807 if (rrit == reorder_rows.end())
810 reorder_rows[att_it.second] = new_row++;
813 if (nconstraint) { constraint_rowstarts.
Append(new_row); }
815 MFEM_VERIFY(new_row == n_rows,
"Remapping failed!");
816 for (
auto& constraint_map : constraints)
818 for (
auto& it : constraint_map)
820 it.second = reorder_rows[it.second];
830 std::map<int, int> node_visits;
831 for (
int i = 0; i < fespace.
GetNBE(); ++i)
834 if (constrained_att.FindSorted(att) != -1)
842 MFEM_VERIFY(dofs.
Size() == nodes.
Size(),
843 "Something wrong in finite element space!");
845 for (
int j = 0; j < dofs.
Size(); ++j)
856 auto nv_it = node_visits.find(truek);
857 if (nv_it == node_visits.end())
859 node_visits[truek] = 1;
863 node_visits[truek]++;
865 int visits = node_visits[truek];
866 int bconstraint = dof_bconstraint[truek];
867 int row = constraints[bconstraint][att];
868 for (
int d = 0; d <
dim; ++d)
874 out->
Add(row, inner_truek, nor[d]);
879 const double pv = out->
SearchRow(inner_truek);
880 const double scaling = ((double) (visits - 1)) /
884 out->
Set(row, inner_truek,
885 scaling * pv + (1.0 / visits) * nor[d]);
904 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
void Add(const int i, const int j, const double a)
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().
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)
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.
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.
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
void SetPrintLevel(int print_lvl)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
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
virtual void GetBdrElementDofs(int bel, Array< int > &dofs) const
Returns indices of degrees of freedom for boundary element 'bel'.
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.
virtual ~SchurConstrainedHypreSolver()
~PenaltyConstrainedSolver()
void SetAbsTol(double atol)
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.
void Set(const int i, const int j, const double a)
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
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.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as 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
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).