14 #include "../../general/forall.hpp" 26 hypre_ParCSRMatrix *A_hypre = D;
29 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A_hypre);
30 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A_hypre);
32 HYPRE_Int diag_ncols = hypre_CSRMatrixNumCols(diag);
33 HYPRE_Int offd_ncols = hypre_CSRMatrixNumCols(offd);
35 const int n_ess_dofs = ess_dofs.
Size();
39 hypre_ParCSRCommHandle *comm_handle;
40 HYPRE_Int *int_buf_data, *eliminate_col_diag, *eliminate_col_offd;
42 eliminate_col_diag = mfem_hypre_CTAlloc_host(HYPRE_Int, diag_ncols);
43 eliminate_col_offd = mfem_hypre_CTAlloc_host(HYPRE_Int, offd_ncols);
46 hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
49 hypre_MatvecCommPkgCreate(A_hypre);
50 comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
54 for (
int i = 0; i < diag_ncols; i++)
56 eliminate_col_diag[i] = 0;
60 for (
int i = 0; i < n_ess_dofs; i++)
62 eliminate_col_diag[ess_dofs[i]] = 1;
67 HYPRE_Int num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg);
68 HYPRE_Int int_buf_sz = hypre_ParCSRCommPkgSendMapStart(comm_pkg, num_sends);
69 int_buf_data = mfem_hypre_CTAlloc_host(HYPRE_Int, int_buf_sz);
70 HYPRE_Int *send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg);
71 for (
int i = 0; i < int_buf_sz; ++i)
73 const int k = send_map_elmts[i];
74 int_buf_data[i] = eliminate_col_diag[k];
76 comm_handle = hypre_ParCSRCommHandleCreate(
77 11, comm_pkg, int_buf_data, eliminate_col_offd);
84 const int nrows_diag = hypre_CSRMatrixNumRows(diag);
85 const auto I = diag->i;
86 const auto J = diag->j;
87 auto data = diag->data;
88 MFEM_HYPRE_FORALL(i, nrows_diag,
90 for (
int jj=I[i]; jj<I[i+1]; ++jj)
93 data[jj] *= 1 - cols[j];
100 hypre_ParCSRCommHandleDestroy(comm_handle);
101 mfem_hypre_TFree_host(int_buf_data);
102 mfem_hypre_TFree_host(eliminate_col_diag);
108 const int nrows_offd = hypre_CSRMatrixNumRows(offd);
109 const auto I = offd->i;
110 const auto J = offd->j;
111 auto data = offd->data;
112 MFEM_HYPRE_FORALL(i, nrows_offd,
114 for (
int jj=I[i]; jj<I[i+1]; ++jj)
117 data[jj] *= 1 - cols[j];
123 mfem_hypre_TFree_host(eliminate_col_offd);
129 const int op1 = order + 1;
131 for (
int iy = 0; iy < o; ++iy)
133 for (
int ix = 0; ix < o; ++ix)
135 const int ivol = ix + iy*o;
136 element2face[0 + 4*ivol] = -1 - (ix + iy*op1);
137 element2face[1 + 4*ivol] = ix+1 + iy*op1;
138 element2face[2 + 4*ivol] = -1 - (ix + iy*o + o*op1);
139 element2face[3 + 4*ivol] = ix + (iy+1)*o + o*op1;
147 const int op1 = order + 1;
149 const int n = o*o*op1;
151 for (
int iz = 0; iz < o; ++iz)
153 for (
int iy = 0; iy < o; ++iy)
155 for (
int ix = 0; ix < o; ++ix)
157 const int ivol = ix + iy*o + iz*o*o;
158 element2face[0 + 6*ivol] = -1 - (ix + iy*op1 + iz*o*op1);
159 element2face[1 + 6*ivol] = ix+1 + iy*op1 + iz*o*op1;
160 element2face[2 + 6*ivol] = -1 - (ix + iy*o + iz*o*op1 + n);
161 element2face[3 + 6*ivol] = ix + (iy+1)*o + iz*o*op1 + n;
162 element2face[4 + 6*ivol] = -1 - (ix + iy*o + iz*o*o + 2*n);
163 element2face[5 + 6*ivol] = ix + iy*o + (iz+1)*o*o + 2*n;
185 const int nnz = n_l2*2*
dim;
186 auto I = D_local.
WriteI();
187 MFEM_FORALL(i, n_l2+1, I[i] = 2*
dim*i; );
189 const int nel_ho = mesh.
GetNE();
190 const int nface_per_el =
dim*pow(order,
dim-1)*(order+1);
191 const int nvol_per_el = pow(order,
dim);
201 else { MFEM_ABORT(
"Unsupported dimension.") }
206 const auto gather_rt =
Reshape(R_rt->GatherMap().Read(), nface_per_el, nel_ho);
207 const auto e2f =
Reshape(element2face.
Read(), 2*
dim, nvol_per_el);
213 auto J = D_local.
WriteJ();
219 const int i_loc = i%nvol_per_el;
220 const int i_el = i/nvol_per_el;
222 for (
int k = 0; k < 2*
dim; ++k)
224 const int sjv_loc = e2f(k, i_loc);
225 const int jv_loc = (sjv_loc >= 0) ? sjv_loc : -1 - sjv_loc;
226 const int sgn1 = (sjv_loc >= 0) ? 1 : -1;
227 const int sj = gather_rt(jv_loc, i_el);
228 const int j = (sj >= 0) ? sj : -1 - sj;
229 const int sgn2 = (sj >= 0) ? 1 : -1;
232 V[k + 2*
dim*i] = sgn1*sgn2;
238 D_diag.MakeRectangularBlockDiag(fes_rt.
GetComm(),
250 D_diag.SetOperatorOwner(
false);
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
virtual const Operator * GetProlongationMatrix() const
The returned Operator is owned by the FiniteElementSpace.
int Dimension() const
Dimension of the reference space used within the elements.
void Delete()
Delete the owned pointers and reset the Memory object.
Pointer to an Operator of a specified type.
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Abstract parallel finite element space.
virtual const SparseMatrix * GetRestrictionMatrix() const
Get the R matrix which restricts a local dof vector to true dof vector.
Memory< double > & GetMemoryData()
Memory< int > & GetMemoryI()
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Memory< int > & GetMemoryJ()
void FormElementToFace3D(int order, Array< int > &element2face)
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
int GetMaxElementOrder() const
Return the maximum polynomial order.
void FormElementToFace2D(int order, Array< int > &element2face)
int * WriteI(bool on_dev=true)
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
HYPRE_BigInt GlobalTrueVSize() const
void MakeRectangularBlockDiag(MPI_Comm comm, HYPRE_BigInt glob_num_rows, HYPRE_BigInt glob_num_cols, HYPRE_BigInt *row_starts, HYPRE_BigInt *col_starts, SparseMatrix *diag)
Reset the OperatorHandle to hold a parallel rectangular block-diagonal matrix using the currently set...
bool IsIdentityProlongation(const Operator *P)
Mesh * GetMesh() const
Returns the mesh.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
HYPRE_BigInt GlobalVSize() const
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
int * WriteJ(bool on_dev=true)
HYPRE_BigInt * GetDofOffsets() const
int GetNE() const
Returns number of elements.
constexpr MemoryClass GetHypreMemoryClass()
The MemoryClass used by Hypre objects.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
HypreParMatrix * FormDiscreteDivergenceMatrix(ParFiniteElementSpace &fes_rt, ParFiniteElementSpace &fes_l2, const Array< int > &ess_dofs)
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
void OverrideSize(int height_, int width_)
Sets the height and width of the matrix.
Lexicographic ordering for tensor-product FiniteElements.
int Size() const
Return the logical size of the array.
void EliminateColumns(HypreParMatrix &D, const Array< int > &ess_dofs)
Eliminates columns in the given HypreParMatrix.
ID for class HypreParMatrix.
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
Wrapper for hypre's ParCSR matrix class.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
HYPRE_BigInt * GetTrueDofOffsets() const
double * WriteData(bool on_dev=true)
void HypreReadWrite()
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.