26static int GetNFacesPerElement(
const Mesh &mesh)
33 default: MFEM_ABORT(
"Invalid dimension.");
37static bool IsParFESpace(
const FiniteElementSpace &fes)
40 return dynamic_cast<const ParFiniteElementSpace *
>(&fes) !=
nullptr;
59 Vector emat(m * n * 2 * nf);
72 const auto d_emat =
Reshape(emat.
Read(), m, n, 2, nf);
73 const int *d_dof_map = dof_map.
Read();
81 const int i_lex = idx % m;
82 const int j = (idx / m) % n;
83 const int ie = (idx / m / n) % 2;
84 const int f = idx / m / n / 2;
86 const int fi = d_face_to_el(1, ie,
f);
92 const int i_s = d_dof_map[i_lex];
93 const int i = (i_s >= 0) ? i_s : -1 - i_s;
94 d_Ct_mat(i, j, fi) = d_emat(i_lex, j, ie,
f);
101 if (pc_fes->Nonconforming())
103 P_pc.reset(pc_fes->GetPartialConformingInterpolation());
111template <
typename T,
int SIZE>
115 MFEM_HOST_DEVICE
inline operator T *()
const {
return (T*)data; }
119struct LocalMemory<T,0>
121 MFEM_HOST_DEVICE
inline operator T *()
const {
return (T*)
nullptr; }
125template <
int MID,
int MBD>
129 const int ne = mesh.
GetNE();
139 static constexpr int MD1D = DofQuadLimits::HDIV_MAX_D1D;
140 static constexpr int MAX_DOFS = 3*MD1D*(MD1D-1)*(MD1D-1);
141 static constexpr int MAX_IDOFS = (MID == 0 && MBD == 0) ? MAX_DOFS : MID;
142 static constexpr int MAX_BDOFS = (MID == 0 && MBD == 0) ? MAX_DOFS : MBD;
144 MFEM_VERIFY(nidofs <= MAX_IDOFS,
"");
145 MFEM_VERIFY(nbdofs <= MAX_BDOFS,
"");
172 static constexpr bool GLOBAL = (MID == 0 && MBD == 0);
174 using internal::LocalMemory;
178 LocalMemory<int,MAX_IDOFS> idofs_loc;
179 LocalMemory<int,MAX_BDOFS> bdofs_loc;
180 for (
int i = 0; i < nidofs; i++) { idofs_loc[i] = d_idofs[i]; }
181 for (
int i = 0; i < nbdofs; i++) { bdofs_loc[i] = d_bdofs[i]; }
183 LocalMemory<int,MAX_BDOFS> essdofs_loc;
186 for (
int i = 0; i < nbdofs; i++)
188 const int dof_idx = bdofs_loc[i];
189 if (d_hat_dof_marker(dof_idx, e) ==
ESSENTIAL)
191 essdofs_loc[nessdofs] = dof_idx;
196 bdofs_loc[nbfdofs] = dof_idx;
201 LocalMemory<real_t, MID*MID> A_ii_loc;
202 LocalMemory<real_t, MBD*MID> A_bi_loc;
203 LocalMemory<real_t, MID*MBD> A_ib_loc;
204 LocalMemory<real_t, MBD*MBD> A_bb_loc;
206 DeviceMatrix A_ii(GLOBAL ? &d_A_ii(0,0,e) : A_ii_loc, nidofs, nidofs);
207 DeviceMatrix A_ib(GLOBAL ? &d_A_ib_all(0,e) : A_ib_loc, nidofs, nbfdofs);
208 DeviceMatrix A_bi(GLOBAL ? &d_A_bi_all(0,e) : A_bi_loc, nbfdofs, nidofs);
209 DeviceMatrix A_bb(GLOBAL ? &d_A_bb_all(0,e) : A_bb_loc, nbfdofs, nbfdofs);
211 for (
int j = 0; j < nidofs; j++)
213 const int jj = idofs_loc[j];
214 for (
int i = 0; i < nidofs; i++)
216 A_ii(i,j) = d_Ahat(idofs_loc[i], jj, e);
218 for (
int i = 0; i < nbfdofs; i++)
220 A_bi(i,j) = d_Ahat(bdofs_loc[i], jj, e);
223 for (
int j = 0; j < nbfdofs; j++)
225 const int jj = bdofs_loc[j];
226 for (
int i = 0; i < nidofs; i++)
228 A_ib(i,j) = d_Ahat(idofs_loc[i], jj, e);
230 for (
int i = 0; i < nbfdofs; i++)
232 A_bb(i,j) = d_Ahat(bdofs_loc[i], jj, e);
236 LocalMemory<int,MID> ipiv_ii_loc;
237 LocalMemory<int,MBD> ipiv_bb_loc;
239 auto ipiv_ii = GLOBAL ? &d_ipiv_ii(0,e) : ipiv_ii_loc;
240 auto ipiv_bb = GLOBAL ? &d_ipiv_bb(0,e) : ipiv_bb_loc;
246 const int begin = d_el_face_offsets[e];
247 const int end = d_el_face_offsets[e + 1];
248 for (
int f = begin;
f < end; ++
f)
250 for (
int j = 0; j < n; ++j)
252 LocalMemory<real_t,MAX_BDOFS> Sb_inv_Cb_t;
253 for (
int i = 0; i < nbfdofs; ++i)
255 Sb_inv_Cb_t[i] = d_Ct_mat(bdofs_loc[i], j,
f);
258 for (
int i = 0; i < nbfdofs; ++i)
260 const int b_i = bdofs_loc[i];
261 d_AhatInvCt(b_i, j,
f) = Sb_inv_Cb_t[i];
263 for (
int i = 0; i < nidofs; ++i)
265 d_AhatInvCt(idofs_loc[i], j,
f) = 0.0;
267 for (
int i = 0; i < nessdofs; ++i)
269 d_AhatInvCt(essdofs_loc[i], j,
f) = 0.0;
280 &d_A_bi_all(0,e) :
nullptr,
283 &d_A_ib_all(0,e) :
nullptr,
285 DeviceMatrix d_A_bb((nbfdofs) ? &d_A_bb_all(0,e) :
nullptr,
288 for (
int j = 0; j < nidofs; j++)
290 d_ipiv_ii(j,e) = ipiv_ii[j];
291 for (
int i = 0; i < nidofs; i++)
293 d_A_ii(i,j,e) = A_ii(i,j);
295 for (
int i = 0; i < nbfdofs; i++)
297 d_A_bi(i,j) = A_bi(i,j);
300 for (
int j = 0; j < nbfdofs; j++)
302 d_ipiv_bb(j,e) = ipiv_bb[j];
303 for (
int i = 0; i < nidofs; i++)
305 d_A_ib(i,j) = A_ib(i,j);
307 for (
int i = 0; i < nbfdofs; i++)
309 d_A_bb(i,j) = A_bb(i,j);
319 const int ne = mesh.
GetNE();
353 const auto d_AhatInvCt =
375 const int begin_f = d_face_face_offsets[fi];
378 for (
int ei = 0; ei < 2; ++ei)
380 const int e = d_face_to_el(0, ei, fi);
381 if (e < 0 || e >= ne) {
continue; }
382 const int begin_i = d_el_face_offsets[e];
383 const int end_i = d_el_face_offsets[e + 1];
384 for (
int fj_i = begin_i; fj_i < end_i; ++fj_i)
386 const int fj = d_el_to_face[fj_i];
392 for (
int i = 0; i < idx; ++i)
394 if (d_face_to_face[begin_f + i] == fj)
403 d_face_to_face[begin_f + idx] = fj;
409 const int end_f = d_face_face_offsets[fi + 1];
410 for (
int i = begin_f + idx; i < end_f; ++i)
412 d_face_to_face[i] = -1;
418 const int begin = d_face_face_offsets[fi];
419 const int end = d_face_face_offsets[fi + 1];
420 for (
int idx_j = begin; idx_j < end; ++idx_j)
422 const int fj = d_face_to_face[idx_j];
423 if (fj < 0) {
break; }
424 for (
int ei = 0; ei < 2; ++ei)
426 const int e = d_face_to_el(0, ei, fi);
427 if (e < 0 || e >= ne) {
continue; }
428 const int fi_i = d_face_to_el(1, ei, fi);
431 for (
int ej = 0; ej < 2; ++ej)
433 if (d_face_to_el(0, ej, fj) == e)
435 fj_i = d_face_to_el(1, ej, fj);
441 const real_t *Ct_i = &d_Ct(0, 0, fi_i);
442 const real_t *AhatInvCt_i = &d_AhatInvCt(0, 0, fj_i);
443 real_t *CAhatInvCt_i = &d_CAhatInvCt(0, 0, idx_j);
455 const int ncdofs_face_nbr = [&]()
460 if (c_pfes && c_pfes->Nonconforming())
463 return c_pfes->GetFaceNbrVSize();
470 const int ncdofs = ncdofs_local + ncdofs_face_nbr;
474 const auto *l2_face_restr =
476 MFEM_ASSERT(l2_face_restr,
"");
477 const auto c_scatter_map =
Reshape(l2_face_restr->ScatterMap().Read(), n, nf);
480 h.
H->OverrideSize(ncdofs, ncdofs);
482 h.
H->GetMemoryI().New(ncdofs + 1,
h.
H->GetMemoryI().GetMemoryType());
485 int *I =
h.
H->WriteI();
487 mfem::forall(ncdofs, [=] MFEM_HOST_DEVICE (
int i) { I[i] = 0; });
491 const int i = idx_i % n;
492 const int fi = idx_i / n;
493 const int ii = c_scatter_map(i, fi);
495 const int begin = d_face_face_offsets[fi];
496 const int end = d_face_face_offsets[fi + 1];
497 for (
int idx = begin; idx < end; ++idx)
499 for (
int j = 0; j < n; ++j)
501 if (d_CAhatInvCt(i, j, idx) != 0)
518 int *I =
h.
H->HostReadWriteI();
519 int empty_row_count = 0;
520 for (
int i = 0; i < ncdofs_local; i++)
522 if (I[i] == 0) { empty_row_count++; }
524 empty_rows.
SetSize(empty_row_count);
526 int empty_row_idx = 0;
528 for (
int i = 0; i < ncdofs; i++)
531 if (nnz == 0 && i < ncdofs_local)
533 empty_rows[empty_row_idx] = i;
543 const int nnz =
h.
H->HostReadI()[ncdofs];
544 h.
H->GetMemoryJ().New(nnz,
h.
H->GetMemoryJ().GetMemoryType());
545 h.
H->GetMemoryData().New(nnz,
h.
H->GetMemoryData().GetMemoryType());
548 int *I =
h.
H->ReadWriteI();
549 int *J =
h.
H->WriteJ();
554 const int i = idx_i % n;
555 const int fi = idx_i / n;
556 const int ii = c_scatter_map[i + fi*n];
557 const int begin = d_face_face_offsets[fi];
558 const int end = d_face_face_offsets[fi + 1];
559 for (
int idx = begin; idx < end; ++idx)
561 const int fj = d_face_to_face[idx];
562 for (
int j = 0; j < n; ++j)
564 const real_t val = d_CAhatInvCt(i, j, idx);
568 const int jj = c_scatter_map(j, fj);
577 const int *d_empty_rows = empty_rows.
Read();
580 const int i = d_empty_rows[idx];
590 int *I =
h.
H->HostReadWriteI();
591 for (
int i = ncdofs - 1; i > 0; --i)
603 if (ncdofs_face_nbr > 0)
610 ParMesh &pmesh = *c_pfes->GetParMesh();
620 auto d_I = I.
Write();
621 mfem::forall(ncdofs + 1, [=] MFEM_HOST_DEVICE (
int i) { d_I[i] = i; });
625 auto d_J = J.
Write();
630 const HYPRE_BigInt *map = c_pfes->GetFaceNbrGlobalDofMapArray().Read();
631 mfem::forall(ncdofs_face_nbr, [=] MFEM_HOST_DEVICE (
int i)
633 d_J[ncdofs_local + i] = map[i];
641 std::make_unique<HypreParMatrix>(
642 c_pfes->GetComm(), ncdofs, global_ncdofs, c_pfes->GlobalVSize(),
644 c_pfes->GetDofOffsets());
647 dH.
Reset(
RAP(&H_diag, P_face_nbr.get()));
649 P_nbr = std::move(P_face_nbr);
654 c_pfes->GetDofOffsets(),
h.
H.get());
659 P_pc ?
P_pc.get() : c_pfes->Dof_TrueDof_Matrix());
670 const int ne = mesh.
GetNE();
681 face_restr->
Mult(x, x_evec);
687 const auto d_x_evec =
Reshape(x_evec.
Read(), n_c_dof_per_face, nf);
690 mfem::forall(ne * n_hat_dof_per_el, [=] MFEM_HOST_DEVICE (
int idx)
692 const int e = idx / n_hat_dof_per_el;
693 const int i = idx % n_hat_dof_per_el;
695 const int begin = d_el_face_offsets[e];
696 const int end = d_el_face_offsets[e+1];
697 for (
int fi = begin; fi < end; ++fi)
699 const int f = d_el_to_face[fi];
700 for (
int j = 0; j < n_c_dof_per_face; ++j)
702 d_y(i, e) += d_Ct(i, j, fi)*d_x_evec(j,
f);
711 const int ne = mesh.
GetNE();
725 auto d_x =
Reshape(x.
Read(), n_hat_dof_per_el, ne);
726 auto d_y_evec =
Reshape(y_evec.
Write(), n_c_dof_per_face, nf);
728 mfem::forall(nf * n_c_dof_per_face, [=] MFEM_HOST_DEVICE (
int idx)
730 const int f = idx / n_c_dof_per_face;
731 const int j = idx % n_c_dof_per_face;
732 d_y_evec(j,
f) = 0.0;
733 for (
int el_i = 0; el_i < 2; ++el_i)
735 const int e = d_face_to_el(0, el_i,
f);
736 const int fi = d_face_to_el(1, el_i,
f);
739 if (e >= ne) {
continue; }
741 for (
int i = 0; i < n_hat_dof_per_el; ++i)
743 d_y_evec(j,
f) += d_Ct(i, j, fi)*d_x(i, e);
754 MFEM_ASSERT(l2_face_restr !=
nullptr,
"");
757 l2_face_restr->MultTransposeShared(y_evec, y_s);
758 P_nbr->MultTranspose(y_s, y);
768 const int n = elmat.
Width();
771 const int offset = el*n*n;
774 d_Ahat[offset + i] += d_elmat[i];
797 Ordering::DofsToVDofs<Ordering::byNODES>(n/vdim, vdim, lvdofs);
798 MFEM_ASSERT(lvdofs.
Size() == elmat.
Height(),
"internal error");
803 for (
int i = 0; i < lvdofs.
Size(); i++)
809 const int offset = el*n*n;
811 for (
int j = 0; j < n; ++j)
813 const int j_f = e2f[j];
814 if (j_f < 0) {
continue; }
815 for (
int i = 0; i < n; ++i)
817 const int i_f = e2f[i];
818 if (i_f < 0) {
continue; }
819 Ahat[offset + i + j*n] += B(i_f, j_f);
830 d_Ahat[i] += d_elmats[i];
845 MFEM_VERIFY(
dim == 2 ||
dim == 3,
"");
852 MFEM_VERIFY(tbe !=
nullptr,
"");
855 const int n_faces_per_el = GetNFacesPerElement(mesh);
858 for (
int f = 0;
f < n_faces_per_el; ++
f)
862 all_face_dofs.
Append(face_map);
867 for (
int i = 0; i < all_face_dofs.
Size(); ++i)
869 const int j_s = all_face_dofs[i];
870 const int j = (j_s >= 0) ? j_s : -1 - j_s;
871 const int j_nat_s = dof_map[j];
872 const int j_nat = (j_nat_s >= 0) ? j_nat_s : -1 - j_nat_s;
873 b_marker[j_nat] =
true;
876 for (
int i = 0; i < ndof_per_el; ++i)
939 for (
int i = ne; i > 0; i--)
952 mfem::forall(nf + 1, [=] MFEM_HOST_DEVICE (
int i) { d_face_face_offsets[i] = 0; });
955 int n_connections = 0;
956 for (
int ie = 0; ie < 2; ++ie)
959 const int e = d_face_to_el(0, ie,
f);
962 n_connections += d_el_face_offsets[e + 1] - d_el_face_offsets[e];
965 if (ie > 0) { n_connections -= 1; }
968 d_face_face_offsets[
f + 1] = n_connections;
983 d_hat_offsets[i] = i*ndof_per_el;
1005 int *d_free_tdof_marker = free_tdof_marker.
Write();
1008 d_free_tdof_marker[i] = 1;
1014 d_free_tdof_marker[d_ess_tdof_list[i]] = 0;
1036 cP->
BooleanMult(free_tdof_marker, free_vdofs_marker);
1040 free_vdofs_marker.
MakeRef(free_tdof_marker);
1049 const int *gather_map = R->GatherMap().Read();
1050 const int *d_free_vdofs_marker = free_vdofs_marker.
Read();
1062 const int j_s = gather_map[i];
1063 const int j = (j_s >= 0) ? j_s : -1 - j_s;
1064 if (d_free_vdofs_marker[j])
1066 const int i_loc = i % ndof_per_el;
1067 const int e = i / ndof_per_el;
1069 const int begin = d_el_face_offsets[e];
1070 const int end = d_el_face_offsets[e + 1];
1071 for (
int f = begin;
f < end; ++
f)
1073 for (
int k = 0; k < ndof_per_face; ++k)
1075 if (d_Ct_mat(i_loc, k,
f) != 0.0)
1096 const int *d_offsets = R->Offsets().Read();
1097 const int *d_indices = R->Indices().Read();
1101 d_hat_dof_gather_map[i] = -1;
1105 const int offset = d_offsets[i];
1106 const int j_s = d_indices[offset];
1107 const int hat_dof_index = (j_s >= 0) ? j_s : -1 - j_s;
1110 d_hat_dof_gather_map[hat_dof_index] = (j_s >= 0) ? i : (-2 - i);
1145 if (d_hat_dof_marker[i] ==
ESSENTIAL) {
return; }
1147 const int j_s = gather_map[i];
1148 const int sgn = (j_s >= 0) ? 1 : -1;
1149 const int j = (j_s >= 0) ? j_s : -1 - j_s;
1151 d_lvec[j] = sgn*d_evec[i];
1179 const int j_s = d_hat_dof_gather_map[i];
1186 const int sgn = (j_s >= 0) ? 1 : -1;
1187 const int j = (j_s >= 0) ? j_s : -2 - j_s;
1188 d_b_hat[i] = sgn*d_b_lvec[j];
1223 constexpr int MD1D = DofQuadLimits::HDIV_MAX_D1D;
1224 constexpr int MAX_DOFS = 3*MD1D*(MD1D-1)*(MD1D-1);
1225 internal::LocalMemory<int,MAX_DOFS> bdofs_loc;
1228 for (
int i = 0; i < nbdofs; i++)
1230 const int dof_idx = d_bdofs[i];
1231 if (d_hat_dof_marker(dof_idx, e) !=
ESSENTIAL)
1233 bdofs_loc[nbfdofs] = dof_idx;
1238 for (
int i = 0; i < nidofs; ++i)
1240 d_ivals(i, e) = d_x(d_idofs[i], e);
1242 for (
int i = 0; i < nbfdofs; ++i)
1244 d_bvals(i, e) = d_x(bdofs_loc[i], e);
1251 kernels::LSolve(&d_A_ii(0,0,e), nidofs, &d_ipiv_ii(0,e), &d_ivals(0,e));
1254 nidofs, nbfdofs, 1, &d_A_bi(0,e), &d_ivals(0,e), &d_bvals(0, e));
1265 nbfdofs, nidofs, 1, &d_A_ib(0,e), &d_bvals(0,e), &d_ivals(0, e));
1270 for (
int i = 0; i < nidofs; ++i)
1272 d_x(d_idofs[i], e) = d_ivals(i, e);
1274 for (
int i = 0; i < nbfdofs; ++i)
1276 d_x(bdofs_loc[i], e) = d_bvals(i, e);
1290 if (d_hat_dof_marker[i] ==
ESSENTIAL) { d_b_hat[i] = 0.0; }
1295 if (IsParFESpace(
h.
c_fes))
1318 if (IsParFESpace(
h.
c_fes))
1322 P.
Mult(sol_r, sol_l);
1336 if (d_hat_dof_marker[i] ==
ESSENTIAL) { d_tmp1[i] = 0.0; }
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
T & Last()
Return the last element in the array.
Data type dense matrix using column-major storage.
void AdjustDofDirection(const Array< int > &dofs)
const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
Rank 3 tensor (array of matrices)
const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
A basic generic Tensor class, appropriate for use on the GPU.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
const Array< int > & GatherMap() const
virtual MFEM_DEPRECATED int GetNFaces(int &nFaceVertices) const =0
virtual int GetNEdges() const =0
Base class for operators that extracts Face degrees of freedom.
void MultTranspose(const Vector &x, Vector &y) const override
Set the face degrees of freedom in the element degrees of freedom y to the values given in x.
void Mult(const Vector &x, Vector &y) const override=0
Extract the face degrees of freedom from x into y.
void SubDofOrder(Geometry::Type Geom, int SDim, int Info, Array< int > &dofs) const
Get the local dofs for a given sub-manifold.
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
static void AdjustVDofs(Array< int > &vdofs)
Remove the orientation information encoded into an array of dofs Some basis function types have a rel...
virtual const Operator * GetProlongationMatrix() const
virtual const Operator * GetRestrictionOperator() const
An abstract operator that performs the same action as GetRestrictionMatrix.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int GetNE() const
Returns number of elements in the mesh.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
const FiniteElement * GetTypicalTraceElement() const
Return a "typical" trace element.
const FiniteElement * GetFaceElement(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th face in the ...
int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type.
const SparseMatrix * GetConformingProlongation() const
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
int GetVDim() const
Returns the vector dimension of the finite element space.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
virtual const FaceRestriction * GetFaceRestriction(ElementDofOrdering f_ordering, FaceType, L2FaceValues mul=L2FaceValues::DoubleValued) const
Return an Operator that converts L-vectors to E-vectors on each face.
virtual void GetFaceMap(const int face_id, Array< int > &face_map) const
Return the mapping from lexicographic face DOFs to lexicographic element DOFs for the given local fac...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Vector Ct_mat
Constraint matrix (transposed) stored element-wise.
std::unique_ptr< Operator > P_nbr
Face-neighbor prolongation.
void ConstructC()
Construct the constraint matrix.
void Init(const Array< int > &ess_tdof_list)
Prepare for assembly; form the constraint matrix.
Array< int > face_to_el
Face-to-element connectivity.
std::unique_ptr< Operator > P_pc
Partially conforming prolongation.
int n_face_face
Total number of face-to-face connections.
void FactorElementMatrices(Vector &AhatInvCt_mat)
void ReduceRHS(const Vector &b, Vector &b_r) const
Given a right-hand side on the original space, compute the corresponding right-hand side for the Lagr...
Array< int > el_to_face
Element to face connectivity.
Array< int > hat_dof_gather_map
void ComputeSolution(const Vector &b, const Vector &sol_r, Vector &sol) const
Given Lagrange multipliers sol_r and the original right-hand side b, recover the solution sol on the ...
Array< DofType > hat_dof_marker
HybridizationExtension(class Hybridization &hybridization_)
Constructor.
Array< int > face_face_offsets
Face-to-face offsets.
Vector tmp2
Temporary vectors.
void ConstructH()
Form the Schur complement matrix .
void MultR(const Vector &b, Vector &b_hat) const
Apply the action of R mapping from "hat DOFs" to T-vector.
Array< int > el_face_offsets
Per-element offsets into el_to_face.
const Operator & GetProlongation() const
Return the (partially) conforming prolongation on the constraint space.
void MultC(const Vector &x, Vector &y) const
Compute the action of C x.
void MultAhatInv(Vector &x) const
Apply the elementwise A_hat^{-1}.
int num_hat_dofs
Number of Lagrange multipliers.
void AssembleMatrix(int el, const class DenseMatrix &elmat)
Assemble the element matrix A into the hybridized system matrix.
int n_el_face
Total number of element-to-face connections.
void MultCt(const Vector &x, Vector &y) const
Compute the action of C^t x.
class Hybridization & h
The associated Hybridization object.=.
void MultRt(const Vector &b, Vector &b_hat) const
Apply the action of R^t mapping into the "hat DOF" space.
void AssembleBdrMatrix(int bdr_el, const class DenseMatrix &elmat)
Assemble the boundary element matrix A into the hybridized system matrix.
void AssembleElementMatrices(const class DenseTensor &el_mats)
Invert and store the element matrices Ahat.
Auxiliary class Hybridization, used to implement BilinearForm hybridization.
FiniteElementSpace & c_fes
std::unique_ptr< SparseMatrix > H
The Schur complement system for the Lagrange multiplier.
FiniteElementSpace & fes
The finite element space.
std::unique_ptr< BilinearFormIntegrator > c_bfi
The constraint integrator.
Wrapper for hypre's ParCSR matrix class.
void BooleanMult(int alpha, const int *x, int beta, int *y)
The "Boolean" analog of y = alpha * A * x + beta * y, where elements in the sparsity pattern of the m...
Operator that extracts face degrees of freedom for L2 interface spaces.
Geometry::Type GetElementGeometry(int i) const
virtual int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type, does not count master nonconforming face...
const Element * GetElement(int i) const
Return pointer to the i'th element object.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
FaceInformation GetFaceInformation(int f) const
int GetNumFacesWithGhost() const
Return the number of faces (3D), edges (2D) or vertices (1D) including ghost faces.
void GetBdrElementAdjacentElement(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i....
Pointer to an Operator of a specified type.
void ConvertFrom(OperatorHandle &A)
Convert the given OperatorHandle A to the currently set type id.
void MakePtAP(OperatorHandle &A, OperatorHandle &P)
Reset the OperatorHandle to hold the product P^t A P.
void MakeSquareBlockDiag(MPI_Comm comm, HYPRE_BigInt glob_size, HYPRE_BigInt *row_starts, SparseMatrix *diag)
Reset the OperatorHandle to hold a parallel square block-diagonal matrix using the currently set type...
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Operator::Type Type() const
Get the currently set operator type id.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
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 ...
Abstract parallel finite element space.
void ExchangeFaceNbrData()
Class for parallel meshes.
long long ReduceInt(int value) const override
Utility function: sum integers from all processors (Allreduce).
void GenerateOffsets(int N, HYPRE_BigInt loc_sizes[], Array< HYPRE_BigInt > *offsets[]) const
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
const int * ess_tdof_list
MFEM_HOST_DEVICE void AddMultAtB(const int Aheight, const int Awidth, const int Bwidth, const TA *Adata, const TB *Bdata, TC *Cdata, const TB alpha, const TA beta)
Compute C = alpha*At*B + beta*C.
MFEM_HOST_DEVICE void LSolve(const real_t *data, const int m, const int *ipiv, real_t *x)
Assuming L.U = P.A factored matrix of size (m x m), compute X <- L^{-1} P X, for a vector X of length...
MFEM_HOST_DEVICE void USolve(const real_t *data, const int m, real_t *x)
Assuming L.U = P.A factored matrix of size (m x m), compute X <- U^{-1} X, for a vector X of length m...
MFEM_HOST_DEVICE void BlockFactor(const real_t *data, int m, const int *ipiv, int n, real_t *A12, real_t *A21, real_t *A22)
MFEM_HOST_DEVICE bool LUFactor(real_t *A, const int m, int *ipiv, const real_t tol=0.0)
Compute the LU factorization of the m x m matrix A.
MFEM_HOST_DEVICE void SubMult(const int m, const int n, const int r, const real_t *A21, const real_t *X1, real_t *X2)
Given an (n x m) matrix A21, compute X2 <- X2 - A21 X1, for matrices X1, and X2 of size (m x r) and (...
MFEM_HOST_DEVICE void LUSolve(const real_t *data, const int m, const int *ipiv, real_t *x)
Assuming L.U = P.A for a factored matrix (m x m),.
void add(const Vector &v1, const Vector &v2, Vector &v)
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 UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
@ SIZE
Number of host and device memory types.
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
@ NATIVE
Native ordering as defined by the FiniteElement.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void forall(int N, lambda &&body)
real_t sol(const Vector &x)