22 : dom_fes(dom_fes_), ran_fes(ran_fes_),
24 fw_t_oper(), bw_t_oper(), use_ea(false), d_mt(
Device::GetHostMemoryType())
29 MFEM_VERIFY(par_dom == par_ran,
"the domain and range FE spaces must both"
30 " be either serial or parallel");
51 MFEM_VERIFY(mat != NULL,
"Operator is not a SparseMatrix");
67 const int RP_case = bool(out_cR) + 2*bool(in_cP);
84 out_cR, &oper, in_cP,
false,
false,
false));
90 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
121 MFEM_ABORT(
"unknown Operator type");
129 false,
false,
false));
133 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
138 return *t_oper.
Ptr();
173 for (
int i = 0; i < elem_geoms.
Size(); i++)
176 localP[elem_geoms[i]]);
184 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
214 MFEM_ABORT(
"unknown type of FE space");
225 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
236 :
Operator(fes_lor_.GetVSize(), fes_ho_.GetVSize()),
237 fes_ho(fes_ho_), fes_lor(fes_lor_), coeff_ho(coeff_ho_),
238 coeff_lor(coeff_lor_), d_mt(d_mt_)
246 ho2lor.MakeI(nel_ho);
247 for (
int ilor = 0; ilor < nel_lor; ++ilor)
250 ho2lor.AddAColumnInRow(iho);
253 for (
int ilor = 0; ilor < nel_lor; ++ilor)
256 ho2lor.AddConnection(iho, ilor);
316 for (
int j=0; j<shape_lor.
Size(); ++j)
318 B_L(i, j) = shape_lor(j);
321 for (
int j=0; j<shape_ho.
Size(); ++j)
323 B_H(i, j) = shape_ho(j);
336 const int nel_ho = mesh_ho.
GetNE();
337 const int nel_lor = mesh_lor.
GetNE();
350 for (
int ig = 0; ig < geoms.
Size(); ++ig)
356 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
367 ho2lor.GetRow(iho, lor_els);
368 const int nref = ho2lor.RowSize(iho);
369 MFEM_VERIFY(nel_ho*nref == nel_lor,
"we expect nel_ho*nref == nel_lor");
394 Vector coeff_vec(qPts*nel_lor);
398 const int nq1d = (int)floor(pow(ir_ea.
Size(), 1.0/
dim) + 0.5);
399 const int nref_1d = (int)floor(pow(nref, 1.0/
dim) + 0.5);
422 for (
int iref = 0; iref < nref_1d; ++iref)
426 for (
int iq = 0; iq < nq1d; ++iq)
428 ir_ho_1d[iq + iref*nq1d].x =
a + ir_ea[iq].x*(
b -
a);
431 if (
dim == 1) {
return ir_ho_1d; }
441 const int nq_ho = ir_ho.
Size();
442 const auto d_Q_ho =
Reshape(coeff_vec_ho.
Read(), nq_ho, nel_ho);
443 const auto d_Q =
Reshape(coeff_vec.
Write(), qPts, nel_lor);
445 mfem::forall(nq_ho * nel_ho, [=] MFEM_HOST_DEVICE (
int ii)
447 const int e_ho = ii / nq_ho;
448 const int iq_ho = ii % nq_ho;
450 int iq_tensor = iq_ho;
455 const int nq_ho_1d = nq1d*nref_1d;
456 for (
int d = 0; d <
dim; ++d)
458 const int iq_ho_1d = iq_tensor % nq_ho_1d;
459 iq_tensor /= nq_ho_1d;
461 iq_lor += (iq_ho_1d % nq1d)*iq_stride;
462 iref += (iq_ho_1d / nq1d)*iref_stride;
464 iref_stride *= nref_1d;
466 const int e_lor = iref + e_ho*nref;
468 d_Q(iq_lor, e_lor) = d_Q_ho(iq_ho, e_ho);
477 for (
int e_ho = 0; e_ho < nel_ho; ++e_ho)
480 for (
int iref = 0; iref < nref; ++iref)
482 const int e_lor = iref + e_ho*nref;
485 for (
int iq = 0; iq < qPts; ++iq)
499 const auto d_D =
Reshape(D.
Write(), qPts, nref, nel_ho);
500 const auto d_Q =
Reshape(coeff_vec.
Read(), qPts, nel_lor);
502 mfem::forall(qPts * nref * nel_ho, [=] MFEM_HOST_DEVICE (
int tid)
504 const int q = tid % qPts;
505 const int iref = (tid / qPts) % nref;
506 const int iho = (tid / (qPts * nref)) % nel_ho;
508 const int lo_el_id = iref + nref*iho;
509 const real_t detJ = J(q, lo_el_id);
511 d_D(q, iref, iho) = W(q) * d_Q(q, lo_el_id) * detJ;
515 for (
int iref = 0; iref < nref; ++iref)
517 int ilor = lor_els[iref];
529 ElemMixedEvaluation(geom, fe_ho, fe_lor, ip_tr, ir_ea, b_lo, b_ho);
537 ho2lor.GetRow(iho, lor_els);
538 int nref = ho2lor.RowSize(iho);
542 const int ndof_ho = fe_ho.
GetDof();
543 const int ndof_lor = fe_lor.
GetDof();
545 const int qPts = D.
SizeI();
552 auto v_M_LH =
Reshape(M_LH.
Write(), ndof_lor, ndof_ho, nref,
555 const int fe_ho_ndof = fe_ho.
GetDof();
556 const int fe_lor_ndof = fe_lor.
GetDof();
558 auto d_B_L =
Reshape(B_L.
Read(), qPts, fe_lor_ndof, nref);
559 auto d_B_H =
Reshape(B_H.
Read(), qPts, fe_ho_ndof, nref);
562 mfem::forall(fe_ho_ndof*nref*nel_ho, [=] MFEM_HOST_DEVICE (
int idx)
564 const int bh = idx % fe_ho_ndof;
565 const int iref = (idx / fe_ho_ndof) % nref;
566 const int iho = idx / fe_ho_ndof / nref;
568 for (
int bl = 0; bl < fe_lor_ndof; ++bl)
571 for (
int qi=0; qi<qPts; ++qi)
573 dot += d_B_L(qi, bl, iref) * d_D(qi, iref, iho) * d_B_H(qi, bh, iref);
576 v_M_LH(bl, bh, iref, iho) = dot;
595 int nel_ho = mesh_ho->
GetNE();
596 int nel_lor = mesh_lor->
GetNE();
603 if (nel_ho == 0) {
return; }
610 for (
int ig = 0; ig < geoms.
Size(); ++ig)
620 for (
int iho = 0; iho < nel_ho; ++iho)
639 for (
int iho = 0; iho < nel_ho; ++iho)
648 int ndof_ho = fe_ho.
GetDof();
649 int ndof_lor = fe_lor.
GetDof();
658 DenseMatrix Minv_lor(ndof_lor*nref, ndof_lor*nref);
678 for (
int iref = 0; iref < nref; ++iref)
681 int ilor = lor_els[iref];
688 M_lor.
CopyMN(M_lor_el, iref*ndof_lor, iref*ndof_lor);
692 Minv_lor.
CopyMN(M_lor_el, iref*ndof_lor, iref*ndof_lor);
702 ElemMixedMass(geom, fe_ho, fe_lor, tr_ho, tr_lor, ip_tr, M_mixed_el);
704 M_mixed.
CopyMN(M_mixed_el, iref*ndof_lor, 0);
715 RtMlorR_inv.
Mult(RtMlor, P_iho);
724 Mesh *mesh_ho = fes_ho.GetMesh();
725 Mesh *mesh_lor = fes_lor.GetMesh();
726 int nel_ho = mesh_ho->
GetNE();
727 int nel_lor = mesh_lor->
GetNE();
731 const bool build_P = fes_lor.GetTrueVSize() >= fes_ho.GetTrueVSize();
734 if (nel_ho == 0) {
return; }
741 for (
int ig = 0; ig < geoms.
Size(); ++ig)
747 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
749 offsets.SetSize(nel_ho+1);
751 for (
int iho = 0; iho < nel_ho; ++iho)
753 int nref = ho2lor.RowSize(iho);
755 const FiniteElement &fe_lor = *fes_lor.GetFE(ho2lor.GetRow(iho)[0]);
756 offsets[iho+1] = offsets[iho] + fe_ho.
GetDof()*fe_lor.
GetDof()*nref;
761 R.SetSize(offsets[nel_ho]);
766 P.SetSize(offsets[nel_ho]);
771 MixedMassEA(fes_ho, fes_lor, M_mixed_all,
d_mt);
783 const int order = 2*fes_lor.GetMaxElementOrder()
790 const int ndof_lor = fes_lor.GetTypicalFE()->GetDof();
791 const int ndof_ho = fes_ho.GetTypicalFE()->GetDof();
792 const int nref = ho2lor.RowSize(0);
795 const bool add =
false;
799 Minv_ear_lor.
SetSize(ndof_lor, ndof_lor, nel_lor,
d_mt);
806 auto v_M_mixed_all =
Reshape(M_mixed_all.
Read(), ndof_lor, ndof_ho, nref,
810 auto v_Minv_ear_lor =
Reshape(Minv_ear_lor.
Read(), ndof_lor, ndof_lor,
814 auto v_R =
Reshape(R.Write(), ndof_lor, nref, ndof_ho, nel_ho);
816 MFEM_VERIFY(nel_lor==nel_ho*nref,
"nel_lor != nel_ho*nref");
819 mfem::forall(ndof_lor * nref * ndof_ho * nel_ho, [=] MFEM_HOST_DEVICE (
int tid)
822 const int i = tid % ndof_lor;
823 const int iref = (tid / ndof_lor) % nref;
824 const int j = (tid / (ndof_lor * nref) ) % ndof_ho;
825 const int iho = (tid / (ndof_lor * nref * ndof_ho)) % nel_ho;
827 const int lor_idx = iref + iho * nref;
831 for (
int k=0; k<ndof_lor; ++k)
833 dot += v_Minv_ear_lor(i, k, lor_idx) * v_M_mixed_all(k, j, iref, iho);
835 v_R(i, iref, j, iho) = dot;
846 auto v_M_ea_lor =
Reshape(M_ea_lor.
Read(), ndof_lor, ndof_lor, nel_lor);
847 auto v_R =
Reshape(R.Read(), ndof_lor, nref, ndof_ho, nel_ho);
851 Vector RtM_L(ndof_ho*nref*ndof_lor*nel_ho,
d_mt);
852 auto v_RtM_L =
Reshape(RtM_L.
Write(), ndof_ho, ndof_lor, nref, nel_ho);
854 mfem::forall(ndof_lor * nref * ndof_ho * nel_ho, [=] MFEM_HOST_DEVICE (
int tid)
857 const int jlo = tid % ndof_lor;
858 const int iref = (tid / ndof_lor) % nref;
859 const int iho = (tid / (ndof_lor * nref)) % ndof_ho;
860 const int e = (tid / (ndof_lor * nref * ndof_ho)) % nel_ho;
862 const int lor_idx = iref + e * nref;
865 for (
int t=0; t<ndof_lor; ++t)
867 dot += v_R(t, iref, iho, e) * v_M_ea_lor(t, jlo, lor_idx);
870 v_RtM_L(iho, jlo, iref, e) = dot;
881 Vector RtM_LR(ndof_ho * ndof_ho * nel_ho,
d_mt);
912 int vdim = fes_ho.GetVDim();
915 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
917 int nref = ho2lor.RowSize(iho);
918 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
919 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
920 xel_mat.
SetSize(ndof_ho, vdim);
921 yel_mat.
SetSize(ndof_lor*nref, vdim);
922 DenseMatrix R_iho(&R[offsets[iho]], ndof_lor*nref, ndof_ho);
924 fes_ho.GetElementVDofs(iho, vdofs);
928 for (
int iref = 0; iref < nref; ++iref)
930 int ilor = ho2lor.GetRow(iho)[iref];
931 for (
int vd=0; vd<vdim; ++vd)
933 fes_lor.GetElementDofs(ilor, vdofs);
934 fes_lor.DofsToVDofs(vd, vdofs);
944 const int nel_ho = fes_ho.GetMesh()->GetNE();
952 const int nref = ho2lor.RowSize(iho);
953 const int ndof_ho = fes_ho.GetFE(iho)->GetDof();
954 const int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
957 R_dt.
NewMemoryAndSize(R.GetMemory(), ndof_lor*nref, ndof_ho, nel_ho,
false);
967 return EAMultTranspose(x,y);
970 int vdim = fes_ho.GetVDim();
974 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
976 int nref = ho2lor.RowSize(iho);
977 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
978 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
979 xel_mat.
SetSize(ndof_lor*nref, vdim);
980 yel_mat.
SetSize(ndof_ho, vdim);
981 DenseMatrix R_iho(&R[offsets[iho]], ndof_lor*nref, ndof_ho);
984 for (
int iref=0; iref<nref; ++iref)
986 int ilor = ho2lor.GetRow(iho)[iref];
987 for (
int vd=0; vd<vdim; ++vd)
989 fes_lor.GetElementDofs(ilor, vdofs);
990 fes_lor.DofsToVDofs(vd, vdofs);
997 fes_ho.GetElementVDofs(iho, vdofs);
1006 const int nel_ho = fes_ho.GetMesh()->GetNE();
1014 const int nref = ho2lor.RowSize(iho);
1015 const int ndof_ho = fes_ho.GetFE(iho)->GetDof();
1016 const int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
1019 R_dt.
NewMemoryAndSize(R.GetMemory(), ndof_lor*nref, ndof_ho, nel_ho,
false);
1026 if (fes_ho.GetNE() == 0) {
return; }
1030 return EAProlongate(x,y);
1033 MFEM_VERIFY(P.Size() > 0,
"Prolongation not supported for these spaces.")
1034 int vdim = fes_ho.GetVDim();
1038 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
1040 int nref = ho2lor.RowSize(iho);
1041 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
1042 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
1043 xel_mat.
SetSize(ndof_lor*nref, vdim);
1044 yel_mat.
SetSize(ndof_ho, vdim);
1045 DenseMatrix P_iho(&P[offsets[iho]], ndof_ho, ndof_lor*nref);
1048 for (
int iref = 0; iref < nref; ++iref)
1050 int ilor = ho2lor.GetRow(iho)[iref];
1051 for (
int vd = 0; vd < vdim; ++vd)
1053 fes_lor.GetElementDofs(ilor, vdofs);
1054 fes_lor.DofsToVDofs(vd, vdofs);
1061 fes_ho.GetElementVDofs(iho, vdofs);
1071 const int nref = ho2lor.RowSize(iho);
1072 const int ndof_ho = fes_ho.GetFE(iho)->GetDof();
1073 const int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
1074 const int nel_ho = fes_ho.GetMesh()->GetNE();
1077 P_dt.
NewMemoryAndSize(P.GetMemory(), ndof_ho, ndof_lor * nref, nel_ho,
false);
1084 if (fes_ho.GetNE() == 0) {
return; }
1088 return EAProlongateTranspose(x,y);
1091 MFEM_VERIFY(P.Size() > 0,
"Prolongation not supported for these spaces.")
1092 int vdim = fes_ho.GetVDim();
1095 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
1097 int nref = ho2lor.RowSize(iho);
1098 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
1099 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
1100 xel_mat.
SetSize(ndof_ho, vdim);
1101 yel_mat.
SetSize(ndof_lor*nref, vdim);
1102 DenseMatrix P_iho(&P[offsets[iho]], ndof_ho, ndof_lor*nref);
1104 fes_ho.GetElementVDofs(iho, vdofs);
1109 for (
int iref = 0; iref < nref; ++iref)
1111 int ilor = ho2lor.GetRow(iho)[iref];
1112 for (
int vd=0; vd<vdim; ++vd)
1114 fes_lor.GetElementDofs(ilor, vdofs);
1115 fes_lor.DofsToVDofs(vd, vdofs);
1127 const int nref = ho2lor.RowSize(iho);
1128 const int ndof_ho = fes_ho.GetFE(iho)->GetDof();
1129 const int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
1130 const int nel_ho = fes_ho.GetMesh()->GetNE();
1133 P_dt.
NewMemoryAndSize(P.GetMemory(), ndof_ho, ndof_lor * nref, nel_ho,
false);
1141 :
L2Projection(fes_ho_, fes_lor_, coeff_ho_, coeff_lor_, d_mt_),
1159 std::unique_ptr<SparseMatrix> R_mat, M_LH_mat;
1170 R_mat.reset(
RAP(*P_lor, *R_mat, *P_ho));
1171 M_LH_mat.reset(
RAP(*P_lor, *M_LH_mat, *P_ho));
1176 M_LH_mat.reset(
mfem::Mult(*M_LH_mat, *P_ho));
1181 M_LH_mat.reset(
mfem::Mult(*P_lor, *M_LH_mat));
1190 R = std::move(R_mat);
1191 M_LH = std::move(M_LH_mat);
1202 :
L2Projection(pfes_ho, pfes_lor, coeff_ho_, coeff_lor_, d_mt_),
1203 use_ea(use_ea_), pcg(pfes_ho.GetComm())
1241 std::unique_ptr<HypreParMatrix> R_T(R_mat->
Transpose());
1248 M_LH.reset(M_LH_mat);
1262 pcg.SetPrintLevel(0);
1264 pcg.SetMaxIter(1000);
1266 pcg.SetRelTol(1e-13);
1267 pcg.SetAbsTol(1e-13);
1268 pcg.SetPreconditioner(*precon);
1269 pcg.SetOperator(*RTxM_LH);
1274 Mesh &mesh_ho = *fes_ho.GetMesh();
1275 Mesh &mesh_lor = *fes_lor.GetMesh();
1276 const int nel_ho = mesh_ho.
GetNE();
1277 const int nel_lor = mesh_lor.
GetNE();
1278 const int ndof_ho = fes_ho.GetNDofs();
1279 const int ndof_lor = fes_lor.GetNDofs();
1292 for (
int ig = 0; ig < geoms.
Size(); ++ig)
1298 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
1321 Mho.
Mult(ones_ho, M_H);
1328 const int order = 2*fes_lor.GetMaxElementOrder()
1338 Mlor.
Mult(ones_lor, ML_inv_ea);
1341 LumpedMassInverse(ML_inv_ea);
1344 MixedMassEA(fes_ho, fes_lor, M_LH_ea,
d_mt);
1348 fes_lor_scalar.get(),
1353 fes_lor_scalar.get(),
1373 int nel_ho = mesh_ho.
GetNE();
1374 int nel_lor = mesh_lor.
GetNE();
1376 int ndof_lor = pfes_lor.
GetNDofs();
1383 for (
int ig = 0; ig < geoms.
Size(); ++ig)
1389 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
1412 pMho.
Mult(ones_ho, M_H);
1419 const int order = 2*fes_lor.GetMaxElementOrder()
1429 pMlor.
Mult(ones_lor, ML_inv_ea);
1433 LumpedMassInverse(ML_inv_ea);
1436 MixedMassEA(*pfes_ho_scalar.get(), *pfes_lor_scalar.get(), M_LH_ea,
d_mt);
1440 pfes_lor_scalar.get(),
1443 const Operator *P_ho = pfes_ho_scalar->GetProlongationMatrix();
1444 const Operator *P_lor = pfes_lor_scalar->GetProlongationMatrix();
1453 RML_inv.SetSize(pfes_lor_scalar->GetTrueVSize());
1454 GetTDofs(*pfes_lor_scalar, ML_inv_ea, RML_inv);
1456 pfes_lor_scalar.get(),
1461 Vector RM_H(pfes_ho_scalar->GetTrueVSize());
1462 GetTDofsTranspose(*pfes_ho_scalar, M_H, RM_H);
1468 pfes_lor_scalar.get(),
1472 Vector RM_H(pfes_ho_scalar->GetTrueVSize());
1473 GetTDofsTranspose(*pfes_ho_scalar.get(), M_H, RM_H);
1479 RML_inv.SetSize(pfes_lor_scalar->GetTrueVSize());
1480 GetTDofsTranspose(*pfes_lor_scalar, ML_inv_ea, RML_inv);
1482 pfes_lor_scalar.get(),
1493 pfes_lor_scalar.get(),
1495 M_LH.reset(M_LH_local_op);
1514 Vector X(fes_ho.GetTrueVSize());
1515 Vector X_dim(R->Width());
1517 Vector Y_dim(R->Height());
1518 Vector Y(fes_lor.GetTrueVSize());
1522 GetTDofs(fes_ho, x, X);
1524 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
1526 TDofsListByVDim(fes_ho, d, vdofs_list);
1528 R->Mult(X_dim, Y_dim);
1529 TDofsListByVDim(fes_lor, d, vdofs_list);
1533 SetFromTDofs(fes_lor, Y, y);
1540 Vector X(fes_lor.GetTrueVSize());
1541 Vector X_dim(R->Height());
1543 Vector Y_dim(R->Width());
1544 Vector Y(fes_ho.GetTrueVSize());
1548 GetTDofsTranspose(fes_lor, x, X);
1550 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
1552 TDofsListByVDim(fes_lor, d, vdofs_list);
1554 R->MultTranspose(X_dim, Y_dim);
1555 TDofsListByVDim(fes_ho, d, vdofs_list);
1559 SetFromTDofsTranspose(fes_ho, Y, y);
1567 Vector X(fes_lor.GetTrueVSize());
1568 Vector X_dim(M_LH->Height());
1569 Vector Xbar(pcg.Width());
1571 Vector Y_dim(pcg.Height());
1573 Vector Y(fes_ho.GetTrueVSize());
1577 GetTDofs(fes_lor, x, X);
1579 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
1581 TDofsListByVDim(fes_lor, d, vdofs_list);
1584 M_LH->MultTranspose(X_dim, Xbar);
1585 pcg.Mult(Xbar, Y_dim);
1586 TDofsListByVDim(fes_ho, d, vdofs_list);
1590 SetFromTDofs(fes_ho, Y, y);
1597 Vector X(fes_ho.GetTrueVSize());
1598 Vector X_dim(pcg.Width());
1599 Vector Xbar(pcg.Height());
1601 Vector Y_dim(M_LH->Height());
1602 Vector Y(fes_lor.GetTrueVSize());
1606 GetTDofsTranspose(fes_ho, x, X);
1608 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
1610 TDofsListByVDim(fes_ho, d, vdofs_list);
1614 pcg.Mult(X_dim, Xbar);
1615 M_LH->Mult(Xbar, Y_dim);
1616 TDofsListByVDim(fes_lor, d, vdofs_list);
1620 SetFromTDofsTranspose(fes_lor, Y, y);
1626 pcg.SetRelTol(p_rtol_);
1631 pcg.SetAbsTol(p_atol_);
1635std::unique_ptr<SparseMatrix>,
1636std::unique_ptr<SparseMatrix>>
1639 std::pair<std::unique_ptr<SparseMatrix>,
1640 std::unique_ptr<SparseMatrix>> r_and_mlh;
1642 Mesh* mesh_ho = fes_ho.GetMesh();
1643 Mesh* mesh_lor = fes_lor.GetMesh();
1644 int nel_ho = mesh_ho->
GetNE();
1645 int nel_lor = mesh_lor->
GetNE();
1646 int ndof_lor = fes_lor.GetNDofs();
1651 return std::make_pair(
1662 for (
int ig = 0; ig < geoms.
Size(); ++ig)
1668 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
1677 for (
int iho = 0; iho < nel_ho; ++iho)
1680 ho2lor.GetRow(iho, lor_els);
1681 int nref = ho2lor.RowSize(iho);
1685 int nedof_lor = fe_lor.
GetDof();
1690 Vector shape_lor(nedof_lor);
1693 for (
int iref = 0; iref < nref; ++iref)
1695 int ilor = lor_els[iref];
1711 shape_lor *= el_tr->
Weight() * w;
1714 fes_lor.GetElementDofs(ilor, dofs_lor);
1719 LumpedMassInverse(ML_inv);
1722 r_and_mlh.first = AllocR();
1727 for (
int icol = 0; icol < r_and_mlh.first->Height() + 1; ++icol)
1729 I[icol] = r_and_mlh.first->GetI()[icol];
1731 Memory<int> J(r_and_mlh.first->NumNonZeroElems());
1732 for (
int jcol = 0; jcol < r_and_mlh.first->NumNonZeroElems(); ++jcol)
1734 J[jcol] = r_and_mlh.first->GetJ()[jcol];
1736 r_and_mlh.second = std::unique_ptr<SparseMatrix>(
1737 new SparseMatrix(I, J, NULL, r_and_mlh.first->Height(),
1738 r_and_mlh.first->Width(),
true,
true,
true));
1744 offsets.SetSize(nel_ho+1);
1746 for (
int iho = 0; iho < nel_ho; ++iho)
1749 ho2lor.GetRow(iho, lor_els);
1750 int nref = ho2lor.RowSize(iho);
1755 offsets[iho+1] = offsets[iho] + fe_ho.
GetDof()*fe_lor.
GetDof()*nref;
1762 int nedof_ho = fe_ho.
GetDof();
1763 int nedof_lor = fe_lor.
GetDof();
1767 for (
int iref = 0; iref < nref; ++iref)
1769 int ilor = lor_els[iref];
1776 ElemMixedMass(geom, fe_ho, fe_lor, tr_ho, tr_lor, ip_tr, M_LH_el);
1779 fes_lor.GetElementDofs(ilor, dofs_lor);
1781 for (
int i = 0; i < nedof_lor; ++i)
1783 M_LH_el.
GetRow(i, R_row);
1784 R_el.
SetRow(i, R_row.
Set(ML_inv[dofs_lor[i]], R_row));
1787 fes_ho.GetElementDofs(iho, dofs_ho);
1788 r_and_mlh.second->AddSubMatrix(dofs_lor, dofs_ho, M_LH_el);
1789 r_and_mlh.first->AddSubMatrix(dofs_lor, dofs_ho, R_el);
1864 R_mat->
BooleanMult(x_vdofs_marker, X_vdofs_marker);
1881 auto * fes = pfes_lor_scalar ==
nullptr ? fes_lor_scalar.get() :
1882 pfes_lor_scalar.get();
1884 auto * fes = fes_lor_scalar.get();
1886 MFEM_ASSERT(fes !=
nullptr,
"[p]fes_lor_scalar is nullptr");
1888 Vector ML_inv_true(fes->GetTrueVSize());
1889 const Operator *P = fes->GetProlongationMatrix();
1891 else { ML_inv_true = ML_inv; }
1895 if (P) { P->
Mult(ML_inv_true, ML_inv); }
1896 else { ML_inv = ML_inv_true; }
1900std::unique_ptr<SparseMatrix>
1903 const Table& elem_dof_ho = fes_ho.GetElementToDofTable();
1904 const Table& elem_dof_lor = fes_lor.GetElementToDofTable();
1905 const int ndof_ho = fes_ho.GetNDofs();
1906 const int ndof_lor = fes_lor.GetNDofs();
1909 Transpose(elem_dof_lor, dof_elem_lor, ndof_lor);
1911 Mesh* mesh_lor = fes_lor.GetMesh();
1915 const int* elem_dof_hoI = elem_dof_ho.
GetI();
1916 const int* elem_dof_hoJ = elem_dof_ho.
GetJ();
1917 const int* dof_elem_lorI = dof_elem_lor.
GetI();
1918 const int* dof_elem_lorJ = dof_elem_lor.
GetJ();
1924 dof_used_ho.
SetSize(ndof_ho, -1);
1927 for (
int ilor = 0; ilor < ndof_lor; ++ilor)
1929 for (
int jlor = dof_elem_lorI[ilor]; jlor < dof_elem_lorI[ilor + 1]; ++jlor)
1931 int el_lor = dof_elem_lorJ[jlor];
1933 for (
int jho = elem_dof_hoI[iho]; jho < elem_dof_hoI[iho + 1]; ++jho)
1935 int dof_ho = elem_dof_hoJ[jho];
1936 if (dof_used_ho[dof_ho] != ilor)
1938 dof_used_ho[dof_ho] = ilor;
1946 Table dof_lor_dof_ho;
1947 dof_lor_dof_ho.
SetDims(ndof_lor, sizeJ);
1949 for (
int i = 0; i < ndof_ho; ++i)
1951 dof_used_ho[i] = -1;
1955 int* dof_dofI = dof_lor_dof_ho.
GetI();
1956 int* dof_dofJ = dof_lor_dof_ho.
GetJ();
1958 for (
int ilor = 0; ilor < ndof_lor; ++ilor)
1960 dof_dofI[ilor] = sizeJ;
1961 for (
int jlor = dof_elem_lorI[ilor]; jlor < dof_elem_lorI[ilor + 1]; ++jlor)
1963 int el_lor = dof_elem_lorJ[jlor];
1965 for (
int jho = elem_dof_hoI[iho]; jho < elem_dof_hoI[iho + 1]; ++jho)
1967 int dof_ho = elem_dof_hoJ[jho];
1968 if (dof_used_ho[dof_ho] != ilor)
1970 dof_used_ho[dof_ho] = ilor;
1971 dof_dofJ[sizeJ] = dof_ho;
1981 std::unique_ptr<SparseMatrix> R_local(
new SparseMatrix(
1982 dof_dofI, dof_dofJ, data, ndof_lor,
1983 ndof_ho,
true,
true,
true));
1996 fes_ho(fes_ho_), fes_lor(fes_lor_), ho2lor(ho2lor_),
2003 if (fes_ho->GetNE() == 0)
2008 const Operator* elem_restrict_ho = fes_ho->GetElementRestriction(
2010 const Operator* elem_restrict_lor = fes_lor->GetElementRestriction(
2013 const int vdim = fes_ho->GetVDim();
2015 const int nref = ho2lor->RowSize(iho);
2016 const int ndof_ho = fes_ho->GetFE(iho)->GetDof();
2017 const int ndof_lor = fes_lor->GetFE(ho2lor->GetRow(iho)[0])->GetDof();
2018 const Mesh *mesh_ho = fes_ho->GetMesh();
2019 const int nel_ho = mesh_ho->
GetNE();
2022 elem_restrict_ho->
Mult(x, tempx);
2024 Vector tempy(ndof_lor*nref*vdim*nel_ho);
2026 auto v_M_mixed_ea =
Reshape(M_LH_ea->Read(), ndof_lor, ndof_ho, nref,
2028 auto v_tempx =
Reshape(tempx.
Read(), ndof_ho, vdim, nel_ho);
2029 auto v_tempy =
Reshape(tempy.
Write(), ndof_lor, nref, vdim, nel_ho);
2032 mfem::forall(ndof_lor * nref * vdim * nel_ho, [=] MFEM_HOST_DEVICE (
int tid)
2034 const int j = tid % ndof_lor;
2035 const int i = (tid / ndof_lor) % nref;
2036 const int v = (tid / (ndof_lor * nref)) % vdim;
2037 const int iho = (tid / (ndof_lor * nref * vdim)) % nel_ho;
2040 for (
int k=0; k<ndof_ho; ++k)
2042 dot += v_M_mixed_ea(j, k, i, iho) * v_tempx(k, v, iho);
2045 v_tempy(j, i, v, iho) = dot;
2054 if (fes_ho->GetNE() == 0)
2059 const Operator* elem_restrict_ho = fes_ho->GetElementRestriction(
2061 const Operator* elem_restrict_lor = fes_lor->GetElementRestriction(
2064 const int vdim = fes_ho->GetVDim();
2066 const int nref = ho2lor->RowSize(iho);
2067 const int ndof_ho = fes_ho->GetFE(iho)->GetDof();
2068 const int ndof_lor = fes_lor->GetFE(ho2lor->GetRow(iho)[0])->GetDof();
2069 const Mesh *mesh_ho = fes_ho->GetMesh();
2070 const int nel_ho = mesh_ho->
GetNE();
2073 elem_restrict_lor->
Mult(x, tempx);
2075 Vector tempy(ndof_ho*vdim*nel_ho);
2077 auto v_M_mixed_ea =
Reshape(M_LH_ea->Read(), ndof_lor, ndof_ho, nref,
2079 auto v_tempx =
Reshape(tempx.
Read(), ndof_lor, nref, vdim, nel_ho);
2080 auto v_tempy =
Reshape(tempy.
Write(), ndof_ho, vdim, nel_ho);
2082 mfem::forall(ndof_ho * vdim * nel_ho, [=] MFEM_HOST_DEVICE (
int tid)
2084 const int k = tid % ndof_ho;
2085 const int v = (tid / ndof_ho) % vdim;
2086 const int iho = (tid / (ndof_ho * vdim)) % nel_ho;
2089 for (
int i=0; i<nref; ++i)
2091 for (
int j=0; j<ndof_lor; ++j)
2093 dot += v_M_mixed_ea(j, k, i, iho) * v_tempx(j, i, v, iho);
2095 v_tempy(k, v, iho) = dot;
2106 Operator(ML_inv_.Size(), ML_inv_.Size()),
2107 fes_ho(fes_ho_), fes_lor(fes_lor_),
2114 MFEM_ASSERT(ML_inv->Size() == x.
Size(),
"sizes not the same");
2115 auto v_ML_inv =
Reshape(ML_inv->Read(), ML_inv->Size());
2119 mfem::forall(ML_inv->Size(), [=] MFEM_HOST_DEVICE(
int i)
2120 { v_y(i) = v_ML_inv(i) * v_x(i); });
2137 if (!
F) { BuildF(); }
2145 if (!
F) { BuildF(); }
2151void L2ProjectionGridTransfer::BuildF()
2158 F =
new L2ProjectionH1Space(
2168 F =
new L2ProjectionH1Space(
2175 F =
new L2ProjectionL2Space(
2188 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize())
2191 bool is_trace_space =
2195 if (lFESpace_.
FEColl() == hFESpace_.
FEColl() && !isvar_order)
2202 else if (lFESpace_.
GetVDim() == 1
2236 bool assemble_matrix)
2237 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), lFESpace(lFESpace_),
2244 "Incompatible finite element space continuity types.");
2251 if (assemble_matrix) { AssembleMatrix(); }
2255void PRefinementTransferOperator::AssembleMatrix()
2258 const int nL = lFESpace.
GetVSize();
2259 const int nH = hFESpace.
GetVSize();
2270 int vdim = lFESpace.
GetVDim();
2276 for (
int i = 0; i < iend; i++)
2292 if (geom != cached_geom || isvar_order)
2301 DenseMatrix Aeff(loc_prol);
2303 for (
int vd = 0; vd < vdim; vd++)
2305 DenseMatrix temp_Aeff(Aeff);
2307 l_dofs.
Copy(l_vdofs);
2310 h_dofs.
Copy(h_vdofs);
2313 temp_Aeff.AdjustDofDirection(h_vdofs, l_vdofs);
2315 P->AddSubMatrix(h_vdofs, l_vdofs, temp_Aeff);
2317 for (
int rr = 0; rr < h_vdofs.
Size(); rr++)
2319 w(h_vdofs[rr]) += 1.0;
2328 for (
int i = 0; i < nH; i++)
2330 inv_w(i) = (w(i) > 0.0) ? (1.0 / w(i)) : 1.0;
2333 P->ScaleRows(inv_w);
2339std::unique_ptr<SparseMatrix>
2340PRefinementTransferOperator::BuildConformingTransferMatrix()
const
2342 MFEM_VERIFY(assembled && P,
"Matrix path requires assembled P.");
2352 return std::unique_ptr<SparseMatrix>(RhPPl);
2356 return std::unique_ptr<SparseMatrix>(
mfem::Mult(*P, *Pl));
2360 return std::unique_ptr<SparseMatrix>(
mfem::Mult(*Rh, *P));
2364 return std::make_unique<SparseMatrix>(*P);
2368std::unique_ptr<Operator>
2369PRefinementTransferOperator::BuildConformingTransferOperator()
const
2376 return std::make_unique<TripleProductOperator>(Rh,
2378 false,
false,
false);
2382 return std::make_unique<ProductOperator>
2388 return std::make_unique<ProductOperator>(Rh,
2402 if (tP) {
return tP.get(); }
2408 bool parallel = (lpfes) && (hpfes);
2432 tP = std::make_unique<TripleProductOperator>(Rh,
this, Pl,
false,
false,
false);
2440 auto M = BuildConformingTransferMatrix();
2441 tP.reset(M.release());
2446 tP = BuildConformingTransferOperator();
2447 return tP ? tP.get() :
this;
2454 auto M = BuildConformingTransferMatrix();
2455 tP.reset(M.release());
2460 tP = BuildConformingTransferOperator();
2461 return tP ? tP.get() :
this;
2472 if (assembled) { P->Mult(x, y);
return; }
2484 int vdim = lFESpace.
GetVDim();
2491 for (
int i = 0; i < iend; i++)
2507 if (geom != cached_geom || isvar_order)
2517 for (
int vd = 0; vd < vdim; vd++)
2519 l_dofs.
Copy(l_vdofs);
2521 h_dofs.
Copy(h_vdofs);
2526 loc_prol.
Mult(subX, subY);
2540 P->MultTranspose(x, y);
2557 int vdim = lFESpace.
GetVDim();
2563 for (
int i = 0; i < iend; i++)
2579 if (geom != cached_geom || isvar_order)
2590 for (
int vd = 0; vd < vdim; vd++)
2592 l_dofs.
Copy(l_vdofs);
2594 h_dofs.
Copy(h_vdofs);
2599 for (
int p = 0;
p < h_dofs.
Size(); ++
p)
2601 if (processed[lFESpace.
DecodeDof(h_dofs[
p])])
2607 loc_prol.
Mult(subX, subY);
2612 for (
int p = 0;
p < h_dofs.
Size(); ++
p)
2614 processed[lFESpace.
DecodeDof(h_dofs[
p])] = 1;
2624 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), lFESpace(lFESpace_),
2634 MFEM_VERIFY(ltel,
"Low order FE space must be tensor product space");
2638 MFEM_VERIFY(htel,
"High order FE space must be tensor product space");
2648 int j = hdofmap[i] >=0 ? hdofmap[i] : -1 - hdofmap[i];
2652 NE = lFESpace.
GetNE();
2660 elem_restrict_lex_l =
2663 MFEM_VERIFY(elem_restrict_lex_l,
2664 "Low order ElementRestriction not available");
2666 elem_restrict_lex_h =
2669 MFEM_VERIFY(elem_restrict_lex_h,
2670 "High order ElementRestriction not available");
2678 "High order element restriction is of unsupported type");
2682 ->BooleanMask(mask);
2686namespace TransferKernels
2699 for (
int qy = 0; qy < Q1D; ++qy)
2701 for (
int qx = 0; qx < Q1D; ++qx)
2703 y_(qx, qy, e) = 0.0;
2707 for (
int dy = 0; dy < D1D; ++dy)
2709 real_t sol_x[DofQuadLimits::MAX_Q1D];
2710 for (
int qy = 0; qy < Q1D; ++qy)
2714 for (
int dx = 0; dx < D1D; ++dx)
2716 const real_t s = x_(dx, dy, e);
2717 for (
int qx = 0; qx < Q1D; ++qx)
2719 sol_x[qx] += B_(qx, dx) * s;
2722 for (
int qy = 0; qy < Q1D; ++qy)
2724 const real_t d2q = B_(qy, dy);
2725 for (
int qx = 0; qx < Q1D; ++qx)
2727 y_(qx, qy, e) += d2q * sol_x[qx];
2731 for (
int qy = 0; qy < Q1D; ++qy)
2733 for (
int qx = 0; qx < Q1D; ++qx)
2735 y_(qx, qy, e) *= m_(qx, qy, e);
2745 auto x_ =
Reshape(localL.
Read(), D1D, D1D, D1D, NE);
2748 auto m_ =
Reshape(mask.
Read(), Q1D, Q1D, Q1D, NE);
2752 for (
int qz = 0; qz < Q1D; ++qz)
2754 for (
int qy = 0; qy < Q1D; ++qy)
2756 for (
int qx = 0; qx < Q1D; ++qx)
2758 y_(qx, qy, qz, e) = 0.0;
2763 for (
int dz = 0; dz < D1D; ++dz)
2765 real_t sol_xy[DofQuadLimits::MAX_Q1D][DofQuadLimits::MAX_Q1D];
2766 for (
int qy = 0; qy < Q1D; ++qy)
2768 for (
int qx = 0; qx < Q1D; ++qx)
2770 sol_xy[qy][qx] = 0.0;
2773 for (
int dy = 0; dy < D1D; ++dy)
2775 real_t sol_x[DofQuadLimits::MAX_Q1D];
2776 for (
int qx = 0; qx < Q1D; ++qx)
2780 for (
int dx = 0; dx < D1D; ++dx)
2782 const real_t s = x_(dx, dy, dz, e);
2783 for (
int qx = 0; qx < Q1D; ++qx)
2785 sol_x[qx] += B_(qx, dx) * s;
2788 for (
int qy = 0; qy < Q1D; ++qy)
2790 const real_t wy = B_(qy, dy);
2791 for (
int qx = 0; qx < Q1D; ++qx)
2793 sol_xy[qy][qx] += wy * sol_x[qx];
2797 for (
int qz = 0; qz < Q1D; ++qz)
2799 const real_t wz = B_(qz, dz);
2800 for (
int qy = 0; qy < Q1D; ++qy)
2802 for (
int qx = 0; qx < Q1D; ++qx)
2804 y_(qx, qy, qz, e) += wz * sol_xy[qy][qx];
2809 for (
int qz = 0; qz < Q1D; ++qz)
2811 for (
int qy = 0; qy < Q1D; ++qy)
2813 for (
int qx = 0; qx < Q1D; ++qx)
2815 y_(qx, qy, qz, e) *= m_(qx, qy, qz, e);
2833 for (
int dy = 0; dy < D1D; ++dy)
2835 for (
int dx = 0; dx < D1D; ++dx)
2837 y_(dx, dy, e) = 0.0;
2841 for (
int qy = 0; qy < Q1D; ++qy)
2843 real_t sol_x[DofQuadLimits::MAX_D1D];
2844 for (
int dx = 0; dx < D1D; ++dx)
2848 for (
int qx = 0; qx < Q1D; ++qx)
2850 const real_t s = m_(qx, qy, e) * x_(qx, qy, e);
2851 for (
int dx = 0; dx < D1D; ++dx)
2853 sol_x[dx] += Bt_(dx, qx) * s;
2856 for (
int dy = 0; dy < D1D; ++dy)
2858 const real_t q2d = Bt_(dy, qy);
2859 for (
int dx = 0; dx < D1D; ++dx)
2861 y_(dx, dy, e) += q2d * sol_x[dx];
2871 auto x_ =
Reshape(localH.
Read(), Q1D, Q1D, Q1D, NE);
2874 auto m_ =
Reshape(mask.
Read(), Q1D, Q1D, Q1D, NE);
2878 for (
int dz = 0; dz < D1D; ++dz)
2880 for (
int dy = 0; dy < D1D; ++dy)
2882 for (
int dx = 0; dx < D1D; ++dx)
2884 y_(dx, dy, dz, e) = 0.0;
2889 for (
int qz = 0; qz < Q1D; ++qz)
2891 real_t sol_xy[DofQuadLimits::MAX_D1D][DofQuadLimits::MAX_D1D];
2892 for (
int dy = 0; dy < D1D; ++dy)
2894 for (
int dx = 0; dx < D1D; ++dx)
2899 for (
int qy = 0; qy < Q1D; ++qy)
2901 real_t sol_x[DofQuadLimits::MAX_D1D];
2902 for (
int dx = 0; dx < D1D; ++dx)
2906 for (
int qx = 0; qx < Q1D; ++qx)
2908 const real_t s = m_(qx, qy, qz, e) * x_(qx, qy, qz, e);
2909 for (
int dx = 0; dx < D1D; ++dx)
2911 sol_x[dx] += Bt_(dx, qx) * s;
2914 for (
int dy = 0; dy < D1D; ++dy)
2916 const real_t wy = Bt_(dy, qy);
2917 for (
int dx = 0; dx < D1D; ++dx)
2919 sol_xy[dy][dx] += wy * sol_x[dx];
2923 for (
int dz = 0; dz < D1D; ++dz)
2925 const real_t wz = Bt_(dz, qz);
2926 for (
int dy = 0; dy < D1D; ++dy)
2928 for (
int dx = 0; dx < D1D; ++dx)
2930 y_(dx, dy, dz, e) += wz * sol_xy[dy][dx];
2947 elem_restrict_lex_l->
Mult(x, localL);
2958 MFEM_ABORT(
"TensorProductPRefinementTransferOperator::Mult not "
2959 "implemented for dim = "
2973 elem_restrict_lex_h->
Mult(x, localH);
2984 MFEM_ABORT(
"TensorProductPRefinementTransferOperator::MultTranspose not "
2985 "implemented for dim = "
2994 :
Operator(hFESpace_.GetTrueVSize(), lFESpace_.GetTrueVSize()),
2995 lFESpace(lFESpace_),
3007 if (P) { MFEM_VERIFY(R,
"Both P and R have to be not NULL") }
3023 delete localTransferOperator;
3031 localTransferOperator->
Mult(tmpL, tmpH);
3036 localTransferOperator->
Mult(x, tmpH);
3041 localTransferOperator->
Mult(x, y);
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 Copy(Array ©) const
Create a copy of the internal array to the provided copy.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
static void Mult(const DenseTensor &A, const Vector &x, Vector &y)
Computes (e.g. by calling AddMult(A,x,y,1,0,Op::N)).
static void MultTranspose(const DenseTensor &A, const Vector &x, Vector &y)
Computes (e.g. by calling AddMult(A,x,y,1,0,Op::T)).
static void Invert(DenseTensor &A)
Replaces the block diagonal matrix with its inverse .
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Class to represent a coefficient evaluated at quadrature points.
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
Jacobi-type diagonal smoother of a sparse matrix.
void Factor()
Factor the current DenseMatrix, *a.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication with the inverse of dense matrix.
void GetInverseMatrix(DenseMatrix &Ainv) const
Compute and return the inverse matrix in Ainv.
Data type dense matrix using column-major storage.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
void Transpose()
(*this) = (*this)^t
void SetRow(int r, const real_t *row)
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco)
Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this.
void GetRow(int r, Vector &row) const
Rank 3 tensor (array of matrices)
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
Memory< real_t > & GetMemory()
void NewMemoryAndSize(const Memory< real_t > &mem, int i, int j, int k, bool own_mem)
Reset the DenseTensor to use the given external Memory mem and dimensions i, j, and k.
const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(GetMemory(), TotalSize(), on_dev).
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Structure representing the matrices/tensors needed to evaluate (in reference space) the values,...
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Array< real_t > B
Basis functions evaluated at quadrature points.
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Array< real_t > Bt
Transpose of B.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
virtual int GetContType() const =0
@ DISCONTINUOUS
Field is discontinuous across element interfaces.
@ CONTINUOUS
Field is continuous across element interfaces.
Derefinement operator, used by the friend class InterpolationGridTransfer.
GridFunction interpolation operator applicable after mesh refinement.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void GetVDofs(int vd, Array< int > &dofs, int ndofs=-1) const
Returns the indices of all of the VDofs for the specified dimension 'vd'.
const SparseMatrix * GetConformingRestriction() const
The returned SparseMatrix is owned by the FiniteElementSpace.
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const
Compute the full set of vdofs corresponding to each entry in dofs.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
ElementTransformation * GetElementTransformation(int i) const
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
virtual int GetFaceDofs(int face, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified face, including the DOFs for the edge...
static void ListToMarker(const Array< int > &list, int marker_size, Array< int > &marker, int mark_val=-1)
Convert an array of indices (list) to a Boolean marker array where all indices in the list are marked...
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
void GetLocalRefinementMatrices(Geometry::Type geom, DenseTensor &localP) const
void GetTransferOperator(const FiniteElementSpace &coarse_fes, OperatorHandle &T) const
Construct and return an Operator that can be used to transfer GridFunction data from coarse_fes,...
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.
SparseMatrix * RefinementMatrix_main(const int coarse_ndofs, const Table &coarse_elem_dof, const Table *coarse_elem_fos, const DenseTensor localP[]) const
static void MarkerToList(const Array< int > &marker, Array< int > &list)
Convert a Boolean marker array to a list containing all marked indices.
const FiniteElement * GetFaceElement(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th face in the ...
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().
const Table * GetElementToFaceOrientationTable() const
int GetVDim() const
Returns the vector dimension of the finite element space.
virtual const SparseMatrix * GetHpRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
static int DecodeDof(int dof)
Helper to return the DOF associated with a sign encoded DOF.
Abstract class for all finite elements.
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
virtual void GetTransferMatrix(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
Return interpolation matrix, I, which maps dofs from a coarse element, fe, to the fine dofs on this f...
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
void CalcPhysShape(ElementTransformation &Trans, Vector &shape) const
Evaluate the values of all shape functions of a scalar finite element in physical space at the point ...
Structure for storing mesh geometric factors: coordinates, Jacobians, and determinants of the Jacobia...
Vector detJ
Determinants of the Jacobians at all quadrature points.
FiniteElementSpace & dom_fes
Domain FE space.
FiniteElementSpace & ran_fes
Range FE space.
Operator::Type oper_type
Desired Operator::Type for the construction of all operators defined by the underlying transfer algor...
const Operator & MakeTrueOperator(FiniteElementSpace &fes_in, FiniteElementSpace &fes_out, const Operator &oper, OperatorHandle &t_oper)
GridTransfer(FiniteElementSpace &dom_fes_, FiniteElementSpace &ran_fes_)
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
The BoomerAMG solver in hypre.
void SetPrintLevel(int print_level)
Wrapper for hypre's ParCSR matrix class.
HypreParMatrix * LeftDiagMult(const SparseMatrix &D, HYPRE_BigInt *row_starts=NULL) const
Multiply the HypreParMatrix on the left by a block-diagonal parallel matrix D and return the result a...
HypreParMatrix * Transpose() const
Returns the transpose of *this.
Class for integration point with weight.
Class for an integration rule - an Array of IntegrationPoint.
int GetNPoints() const
Returns the number of the points in the integration rule.
const Array< real_t > & GetWeights() const
Return the quadrature weights in a contiguous array.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void SetIntegrationRule(const IntegrationRule &ir)
Prescribe a fixed IntegrationRule to use. Sets the NURBS patch integration rule to null.
virtual ~InterpolationGridTransfer()
BilinearFormIntegrator * mass_integ
Ownership depends on own_mass_integ.
OperatorHandle F
Forward, coarse-to-fine, operator.
bool own_mass_integ
Ownership flag for mass_integ.
const Operator & BackwardOperator() override
Return an Operator that transfers GridFunctions from the range FE space back to GridFunctions in the ...
OperatorHandle B
Backward, fine-to-coarse, operator.
void SetMassIntegrator(BilinearFormIntegrator *mass_integ_, bool own_mass_integ_=true)
Assign a mass integrator to be used in the construction of the backward, fine-to-coarse,...
const Operator & ForwardOperator() override
Return an Operator that transfers GridFunctions from the domain FE space to GridFunctions in the rang...
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
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 ...
H1SpaceLumpedMassOperator(const FiniteElementSpace *fes_ho_, const FiniteElementSpace *fes_lor_, Vector &ML_inv_)
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
void Mult(const Vector &x, Vector &y) const
Operator application: y=A(x).
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 ...
H1SpaceMixedMassOperator(const FiniteElementSpace *fes_ho_, const FiniteElementSpace *fes_lor_, Table *ho2lor_, Vector *M_LH_ea_)
void Mult(const Vector &x, Vector &y) const override
void EAL2ProjectionH1Space()
void SetFromTDofsTranspose(const FiniteElementSpace &fes, const Vector &X, Vector &x) const
Sets dual field coefficients given a vector of dual field coefficients on the tdofs and a finite elem...
std::unique_ptr< FiniteElementSpace > fes_ho_scalar
std::unique_ptr< ParFiniteElementSpace > pfes_ho_scalar
void TDofsListByVDim(const FiniteElementSpace &fes, int vdim, Array< int > &vdofs_list) const
Fills the vdofs_list array with a list of vdofs for a given vdim and a given finite element space.
std::unique_ptr< Solver > precon
void SetupPCG()
Sets up the PCG solver (sets parameters, operator, and preconditioner)
void Prolongate(const Vector &x, Vector &y) const override
void GetTDofs(const FiniteElementSpace &fes, const Vector &x, Vector &X) const
Recovers vector of tdofs given a vector of dofs and a finite element space.
void SetFromTDofs(const FiniteElementSpace &fes, const Vector &X, Vector &x) const
Sets dof values given a vector of tdofs and a finite element space.
std::unique_ptr< Operator > RTxM_LH
void GetTDofsTranspose(const FiniteElementSpace &fes, const Vector &x, Vector &X) const
Recovers a vector of dual field coefficients on the tdofs given a vector of dual coefficients and a f...
L2ProjectionH1Space(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_, CoefficientWithOrder coeff_ho_, CoefficientWithOrder coeff_lor_, const bool use_ea_, MemoryType d_mt_=Device::GetHostMemoryType())
std::unique_ptr< SparseMatrix > AllocR()
Computes sparsity pattern and initializes R matrix. Based on BilinearForm::AllocMat(),...
std::unique_ptr< Operator > M_LH
void MultTranspose(const Vector &x, Vector &y) const override
void LumpedMassInverse(Vector &ML_inv) const
Returns the inverse of an on-rank lumped mass matrix.
std::unique_ptr< FiniteElementSpace > fes_lor_scalar
void SetAbsTol(real_t p_atol_) override
Sets absolute tolerance in preconditioned conjugate gradient solver.
void ProlongateTranspose(const Vector &x, Vector &y) const override
std::pair< std::unique_ptr< SparseMatrix >, std::unique_ptr< SparseMatrix > > ComputeSparseRAndM_LH()
Computes on-rank R and M_LH matrices. If true, computes mixed mass and/or inverse lumped mass matrix ...
std::unique_ptr< Operator > R
void SetRelTol(real_t p_rtol_) override
Sets relative tolerance in preconditioned conjugate gradient solver.
std::unique_ptr< ParFiniteElementSpace > pfes_lor_scalar
void ProlongateTranspose(const Vector &x, Vector &y) const override
void EAMultTranspose(const Vector &x, Vector &y) const
void EAProlongate(const Vector &x, Vector &y) const
L2ProjectionL2Space(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_, CoefficientWithOrder coeff_ho_, CoefficientWithOrder coeff_lor_, const bool use_ea_, MemoryType d_mt_=Device::GetHostMemoryType())
void MultTranspose(const Vector &x, Vector &y) const override
void EAMult(const Vector &x, Vector &y) const
Perform mult on the device (same as above)
void EAL2ProjectionL2Space()
void EAProlongateTranspose(const Vector &x, Vector &y) const
void Prolongate(const Vector &x, Vector &y) const override
void Mult(const Vector &x, Vector &y) const override
L2Projection(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_, CoefficientWithOrder coeff_ho_, CoefficientWithOrder coeff_lor_, MemoryType d_mt_=Device::GetHostMemoryType())
void BuildHo2Lor(int nel_ho, int nel_lor, const CoarseFineTransformations &cf_tr)
const FiniteElementSpace & fes_ho
void MixedMassEA(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_, Vector &M_LH, MemoryType d_mt_=Device::GetHostMemoryType())
const FiniteElementSpace & fes_lor
CoefficientWithOrder coeff_lor
void ElemMixedEvaluation(Geometry::Type geom, const FiniteElement &fe_ho, const FiniteElement &fe_lor, IntegrationPointTransformation &ip_tr, const IntegrationRule &ir, DenseMatrix &B_L, DenseMatrix &B_H) const
void ElemMixedMass(Geometry::Type geom, const FiniteElement &fe_ho, const FiniteElement &fe_lor, ElementTransformation *tr_ho, ElementTransformation *tr_lor, IntegrationPointTransformation &ip_tr, DenseMatrix &M_mixed_el) const
L2Projection * F
Forward, coarse-to-fine, operator.
CoefficientWithOrder coeff_ho
Coefficient for the mixed L2 inner product.
CoefficientWithOrder coeff_lor
Coefficient for the low-order L2 inner product.
const Operator & BackwardOperator() override
Return an Operator that transfers GridFunctions from the range FE space back to GridFunctions in the ...
bool SupportsBackwardsOperator() const override
L2Prolongation * B
Backward, fine-to-coarse, operator.
const Operator & ForwardOperator() override
Return an Operator that transfers GridFunctions from the domain FE space to GridFunctions in the rang...
virtual ~L2ProjectionGridTransfer()
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleEA(const FiniteElementSpace &fes, Vector &emat, const bool add) override
Method defining element assembly.
Class used by MFEM to store pointers to host and/or device memory.
void SyncAlias(const Memory &base, int alias_size) const
Update the alias Memory *this to match the memory location (all valid locations) of its base Memory,...
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
List of mesh geometries stored as Array<Geometry::Type>.
void GetGeometries(int dim, Array< Geometry::Type > &el_geoms) const
Return all element geometries of the given dimension present in the mesh.
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Geometry::Type GetFaceGeometry(int i) const
Return the Geometry::Type associated with face i.
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
const CoarseFineTransformations & GetRefinementTransforms() const
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
ElementTransformation * GetTypicalElementTransformation()
If the local mesh is not empty return GetElementTransformation(0); otherwise, return the identity tra...
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags, MemoryType d_mt=MemoryType::DEFAULT)
Return the mesh geometric factors corresponding to the given integration rule.
Geometry::Type GetElementBaseGeometry(int i) const
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces,...
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 SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
Operator * Ptr() const
Access the underlying Operator pointer.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Jacobi smoothing for a given bilinear form (no matrix necessary).
Operator(int s=0)
Construct a square Operator with given size s (default 0).
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().
@ ANY_TYPE
ID for the base class Operator, i.e. any type.
@ MFEM_SPARSEMAT
ID for class SparseMatrix.
@ Hypre_ParCSR
ID for class HypreParMatrix.
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 ...
Matrix-free transfer operator between finite element spaces on the same mesh.
void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
PRefinementTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_, bool assemble_matrix=false)
Constructs a transfer operator from lFESpace to hFESpace which have different FE collections.
void Mult(const Vector &x, Vector &y) const override
Interpolation or prolongation of a vector x corresponding to the coarse space to the vector y corresp...
Operator * GetTrueTransferOperator()
Return the true-dof transfer operator.
Abstract parallel finite element space.
HYPRE_BigInt * GetTrueDofOffsets() const
HYPRE_BigInt GlobalVSize() const
const Operator * GetRestrictionOperator() const override
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.
ParMesh * GetParMesh() const
General product operator: x -> (A*B)(x) = A(B(x)).
Class representing the storage layout of a QuadratureFunction.
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
void MultTranspose(const Vector &x, Vector &y) const override
Multiply a vector with the transposed matrix. y = At * x.
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
Table stores the connectivity of elements of TYPE I to elements of TYPE II. For example,...
void LoseData()
Releases ownership of and null-ifies the data.
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void SortRows()
Sort the column (TYPE II) indices in each row.
void SetDims(int rows, int nnz)
Set the rows and the number of all connections for the table.
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Matrix-free transfer operator between finite element spaces on the same mesh exploiting the tensor pr...
void Mult(const Vector &x, Vector &y) const override
Interpolation or prolongation of a vector x corresponding to the coarse space to the vector y corresp...
TensorProductPRefinementTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
Constructs a transfer operator from lFESpace to hFESpace which have different FE collections.
void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
Matrix-free transfer operator between finite element spaces.
virtual ~TransferOperator()
Destructor.
void Mult(const Vector &x, Vector &y) const override
Interpolation or prolongation of a vector x corresponding to the coarse space to the vector y corresp...
void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
TransferOperator(const FiniteElementSpace &lFESpace, const FiniteElementSpace &hFESpace)
Constructs a transfer operator from lFESpace to hFESpace.
The transpose of a given operator. Switches the roles of the methods Mult() and MultTranspose().
General triple product operator x -> A*B*C*x, with ownership of the factors.
~TrueTransferOperator()
Destructor.
void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
TrueTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
Constructs a transfer operator working on true degrees of freedom from lFESpace to hFESpace.
void Mult(const Vector &x, Vector &y) const override
Interpolation or prolongation of a true dof vector x to a true dof vector y.
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Memory< real_t > & GetMemory()
Return a reference to the Memory object used by the Vector.
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...
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
void NewMemoryAndSize(const Memory< real_t > &mem, int s, bool own_mem)
Reset the Vector to use the given external Memory mem and size s.
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.
void Reciprocal()
(*this)(i) = 1.0 / (*this)(i)
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
const int * ess_tdof_list
void Prolongation2D(const int NE, const int D1D, const int Q1D, const Vector &localL, Vector &localH, const Array< real_t > &B, const Vector &mask)
void Restriction3D(const int NE, const int D1D, const int Q1D, const Vector &localH, Vector &localL, const Array< real_t > &Bt, const Vector &mask)
void Restriction2D(const int NE, const int D1D, const int Q1D, const Vector &localH, Vector &localL, const Array< real_t > &Bt, const Vector &mask)
void Prolongation3D(const int NE, const int D1D, const int Q1D, const Vector &localL, Vector &localH, const Array< real_t > &B, const Vector &mask)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void add(const Vector &v1, const Vector &v2, Vector &v)
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
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)
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
void TransformPrimal(const DofTransformation &ran_dof_trans, const DofTransformation &dom_dof_trans, DenseMatrix &elmat)
MemoryType
Memory types supported by MFEM.
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
@ NATIVE
Native ordering as defined by the FiniteElement.
SparseMatrix * TransposeMult(const SparseMatrix &A, const SparseMatrix &B)
C = A^T B.
void forall(int N, lambda &&body)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
real_t p(const Vector &x, real_t t)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.
int MAX_Q1D
Maximum number of 1D quadrature points.