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;
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;
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();
216 const int two_dim = 2*
dim;
219 MFEM_FORALL(ii, n_l2*2*
dim,
221 const int k = ii % (two_dim);
222 const int i = ii / (two_dim);
223 const int i_loc = i%nvol_per_el;
224 const int i_el = i/nvol_per_el;
226 const int sjv_loc = e2f(k, i_loc);
227 const int jv_loc = (sjv_loc >= 0) ? sjv_loc : -1 - sjv_loc;
228 const int sgn1 = (sjv_loc >= 0) ? 1 : -1;
229 const int sj = gather_rt(jv_loc, i_el);
230 const int j = (sj >= 0) ? sj : -1 - sj;
231 const int sgn2 = (sj >= 0) ? 1 : -1;
234 V[k + 2*
dim*i] = sgn1*sgn2;
239 D_diag.MakeRectangularBlockDiag(fes_rt.
GetComm(),
251 D_diag.SetOperatorOwner(
false);
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Operator that converts FiniteElementSpace L-vectors to E-vectors.
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Mesh * GetMesh() const
Returns the mesh.
int GetMaxElementOrder() const
Return the maximum polynomial order.
Wrapper for hypre's ParCSR matrix class.
void HypreReadWrite()
Update the internal hypre_ParCSRMatrix object, A, to be in hypre memory space.
Class used by MFEM to store pointers to host and/or device memory.
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
void Delete()
Delete the owned pointers and reset the Memory object.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the 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().
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...
@ Hypre_ParCSR
ID for class HypreParMatrix.
Abstract parallel finite element space.
HYPRE_BigInt * GetTrueDofOffsets() const
HYPRE_BigInt GlobalVSize() const
HYPRE_BigInt GlobalTrueVSize() const
HYPRE_BigInt * GetDofOffsets() const
const Operator * GetProlongationMatrix() const override
The returned Operator is owned by the FiniteElementSpace.
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
const SparseMatrix * GetRestrictionMatrix() const override
Get the R matrix which restricts a local dof vector to true dof vector.
int * WriteJ(bool on_dev=true)
Memory< int > & GetMemoryI()
int * WriteI(bool on_dev=true)
void OverrideSize(int height_, int width_)
Sets the height and width of the matrix.
Memory< int > & GetMemoryJ()
Memory< real_t > & GetMemoryData()
real_t * WriteData(bool on_dev=true)
void EliminateColumns(HypreParMatrix &D, const Array< int > &ess_dofs)
Eliminates columns in the given HypreParMatrix.
HypreParMatrix * FormDiscreteDivergenceMatrix(ParFiniteElementSpace &fes_rt, ParFiniteElementSpace &fes_l2, const Array< int > &ess_dofs)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
MemoryClass GetHypreMemoryClass()
The MemoryClass used by Hypre objects.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
bool IsIdentityProlongation(const Operator *P)
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
void FormElementToFace3D(int order, Array< int > &element2face)
void hypre_forall(int N, lambda &&body)
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
@ LEXICOGRAPHIC
Lexicographic ordering for tensor-product FiniteElements.
void FormElementToFace2D(int order, Array< int > &element2face)