25 hypre_ParCSRMatrix *A_hypre = D;
28 hypre_CSRMatrix *diag = hypre_ParCSRMatrixDiag(A_hypre);
29 hypre_CSRMatrix *offd = hypre_ParCSRMatrixOffd(A_hypre);
31 HYPRE_Int diag_ncols = hypre_CSRMatrixNumCols(diag);
32 HYPRE_Int offd_ncols = hypre_CSRMatrixNumCols(offd);
34 const int n_ess_dofs = ess_dofs.
Size();
38 hypre_ParCSRCommHandle *comm_handle;
39 HYPRE_Int *int_buf_data, *eliminate_col_diag, *eliminate_col_offd;
41 eliminate_col_diag = mfem_hypre_CTAlloc_host(HYPRE_Int, diag_ncols);
42 eliminate_col_offd = mfem_hypre_CTAlloc_host(HYPRE_Int, offd_ncols);
45 hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
48 hypre_MatvecCommPkgCreate(A_hypre);
49 comm_pkg = hypre_ParCSRMatrixCommPkg(A_hypre);
53 for (
int i = 0; i < diag_ncols; i++)
55 eliminate_col_diag[i] = 0;
59 for (
int i = 0; i < n_ess_dofs; i++)
61 eliminate_col_diag[ess_dofs[i]] = 1;
66 HYPRE_Int num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg);
67 HYPRE_Int int_buf_sz = hypre_ParCSRCommPkgSendMapStart(comm_pkg, num_sends);
68 int_buf_data = mfem_hypre_CTAlloc_host(HYPRE_Int, int_buf_sz);
69 HYPRE_Int *send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg);
70 for (
int i = 0; i < int_buf_sz; ++i)
72 const int k = send_map_elmts[i];
73 int_buf_data[i] = eliminate_col_diag[k];
75 comm_handle = hypre_ParCSRCommHandleCreate(
76 11, comm_pkg, int_buf_data, eliminate_col_offd);
83 const int nrows_diag = hypre_CSRMatrixNumRows(diag);
84 const auto I = diag->i;
85 const auto J = diag->j;
86 auto data = diag->data;
89 for (
int jj=I[i]; jj<I[i+1]; ++jj)
92 data[jj] *= 1 - cols[j];
99 hypre_ParCSRCommHandleDestroy(comm_handle);
100 mfem_hypre_TFree_host(int_buf_data);
101 mfem_hypre_TFree_host(eliminate_col_diag);
107 const int nrows_offd = hypre_CSRMatrixNumRows(offd);
108 const auto I = offd->i;
109 const auto J = offd->j;
110 auto data = offd->data;
113 for (
int jj=I[i]; jj<I[i+1]; ++jj)
116 data[jj] *= 1 - cols[j];
122 mfem_hypre_TFree_host(eliminate_col_offd);
128 const int op1 = order + 1;
130 for (
int iy = 0; iy < o; ++iy)
132 for (
int ix = 0; ix < o; ++ix)
134 const int ivol = ix + iy*o;
135 element2face[0 + 4*ivol] = -1 - (ix + iy*op1);
136 element2face[1 + 4*ivol] = ix+1 + iy*op1;
137 element2face[2 + 4*ivol] = -1 - (ix + iy*o + o*op1);
138 element2face[3 + 4*ivol] = ix + (iy+1)*o + o*op1;
146 const int op1 = order + 1;
148 const int n = o*o*op1;
150 for (
int iz = 0; iz < o; ++iz)
152 for (
int iy = 0; iy < o; ++iy)
154 for (
int ix = 0; ix < o; ++ix)
156 const int ivol = ix + iy*o + iz*o*o;
157 element2face[0 + 6*ivol] = -1 - (ix + iy*op1 + iz*o*op1);
158 element2face[1 + 6*ivol] = ix+1 + iy*op1 + iz*o*op1;
159 element2face[2 + 6*ivol] = -1 - (ix + iy*o + iz*o*op1 + n);
160 element2face[3 + 6*ivol] = ix + (iy+1)*o + iz*o*op1 + n;
161 element2face[4 + 6*ivol] = -1 - (ix + iy*o + iz*o*o + 2*n);
162 element2face[5 + 6*ivol] = ix + iy*o + (iz+1)*o*o + 2*n;
184 const int nnz = n_l2*2*
dim;
185 auto I = D_local.
WriteI();
186 MFEM_FORALL(i, n_l2+1, I[i] = 2*
dim*i; );
188 const int nel_ho = mesh.
GetNE();
189 const int nface_per_el =
dim*pow(order,
dim-1)*(order+1);
190 const int nvol_per_el = pow(order,
dim);
200 else { MFEM_ABORT(
"Unsupported dimension.") }
205 const auto gather_rt =
Reshape(R_rt->GatherMap().Read(), nface_per_el, nel_ho);
206 const auto e2f =
Reshape(element2face.
Read(), 2*
dim, nvol_per_el);
212 auto J = D_local.
WriteJ();
215 const int two_dim = 2*
dim;
218 MFEM_FORALL(ii, n_l2*2*
dim,
220 const int k = ii % (two_dim);
221 const int i = ii / (two_dim);
222 const int i_loc = i%nvol_per_el;
223 const int i_el = i/nvol_per_el;
225 const int sjv_loc = e2f(k, i_loc);
226 const int jv_loc = (sjv_loc >= 0) ? sjv_loc : -1 - sjv_loc;
227 const int sgn1 = (sjv_loc >= 0) ? 1 : -1;
228 const int sj = gather_rt(jv_loc, i_el);
229 const int j = (sj >= 0) ? sj : -1 - sj;
230 const int sgn2 = (sj >= 0) ? 1 : -1;
233 V[k + 2*
dim*i] = sgn1*sgn2;
238 D_diag.MakeRectangularBlockDiag(fes_rt.
GetComm(),
250 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.
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.
int GetMaxElementOrder() const override
Returns the maximum polynomial order over all elements globally.
HYPRE_BigInt * GetTrueDofOffsets() const
HYPRE_BigInt GlobalVSize() const
HYPRE_BigInt GlobalTrueVSize() const
HYPRE_BigInt * GetDofOffsets() const
const Operator * GetProlongationMatrix() const override
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.
void FormElementToFace2D(int order, Array< int > &element2face)