12 #include "transfer.hpp" 14 #include "../general/forall.hpp" 21 : dom_fes(dom_fes_), ran_fes(ran_fes_),
23 fw_t_oper(), bw_t_oper()
28 MFEM_VERIFY(par_dom == par_ran,
"the domain and range FE spaces must both" 29 " be either serial or parallel");
50 MFEM_VERIFY(mat != NULL,
"Operator is not a SparseMatrix");
53 t_oper.
Reset(const_cast<SparseMatrix*>(mat),
false);
66 const int RP_case = bool(out_cR) + 2*bool(in_cP);
70 t_oper.
Reset(const_cast<Operator*>(&oper),
false);
83 out_cR, &oper, in_cP,
false,
false,
false));
89 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
111 else if ((hy_mat = dynamic_cast<const HypreParMatrix *>(&oper)))
120 MFEM_ABORT(
"unknown Operator type");
128 false,
false,
false));
132 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
137 return *t_oper.
Ptr();
172 for (
int i = 0; i < elem_geoms.Size(); i++)
175 localP[elem_geoms[i]]);
183 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
213 MFEM_ABORT(
"unknown type of FE space");
224 MFEM_ABORT(
"Operator::Type is not supported: " <<
oper_type);
233 :
Operator(fes_lor_.GetVSize(), fes_ho_.GetVSize()),
243 ho2lor.MakeI(nel_ho);
244 for (
int ilor = 0; ilor < nel_lor; ++ilor)
247 ho2lor.AddAColumnInRow(iho);
250 for (
int ilor = 0; ilor < nel_lor; ++ilor)
253 ho2lor.AddConnection(iho, ilor);
291 int nel_ho = mesh_ho->
GetNE();
292 int nel_lor = mesh_lor->
GetNE();
299 if (nel_ho == 0) {
return; }
306 for (
int ig = 0; ig < geoms.
Size(); ++ig)
316 for (
int iho = 0; iho < nel_ho; ++iho)
321 offsets[iho+1] = offsets[iho] + fe_ho.
GetDof()*fe_lor.
GetDof()*nref;
335 for (
int iho = 0; iho < nel_ho; ++iho)
344 int ndof_ho = fe_ho.
GetDof();
345 int ndof_lor = fe_lor.
GetDof();
350 DenseMatrix R_iho(&R[offsets[iho]], ndof_lor*nref, ndof_ho);
352 DenseMatrix Minv_lor(ndof_lor*nref, ndof_lor*nref);
368 for (
int iref = 0; iref < nref; ++iref)
371 int ilor = lor_els[iref];
374 M_lor.
CopyMN(M_lor_el, iref*ndof_lor, iref*ndof_lor);
378 Minv_lor.
CopyMN(M_lor_el, iref*ndof_lor, iref*ndof_lor);
388 ElemMixedMass(geom, fe_ho, fe_lor, el_tr, ip_tr, M_mixed_el);
390 M_mixed.
CopyMN(M_mixed_el, iref*ndof_lor, 0);
396 DenseMatrix P_iho(&P[offsets[iho]], ndof_ho, ndof_lor*nref);
401 RtMlorR_inv.
Mult(RtMlor, P_iho);
409 int vdim = fes_ho.GetVDim();
412 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
414 int nref = ho2lor.RowSize(iho);
415 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
416 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
417 xel_mat.
SetSize(ndof_ho, vdim);
418 yel_mat.
SetSize(ndof_lor*nref, vdim);
419 DenseMatrix R_iho(&R[offsets[iho]], ndof_lor*nref, ndof_ho);
421 fes_ho.GetElementVDofs(iho, vdofs);
425 for (
int iref = 0; iref < nref; ++iref)
427 int ilor = ho2lor.GetRow(iho)[iref];
428 for (
int vd=0; vd<vdim; ++vd)
430 fes_lor.GetElementDofs(ilor, vdofs);
431 fes_lor.DofsToVDofs(vd, vdofs);
441 int vdim = fes_ho.GetVDim();
445 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
447 int nref = ho2lor.RowSize(iho);
448 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
449 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
450 xel_mat.
SetSize(ndof_lor*nref, vdim);
451 yel_mat.
SetSize(ndof_ho, vdim);
452 DenseMatrix R_iho(&R[offsets[iho]], ndof_lor*nref, ndof_ho);
455 for (
int iref=0; iref<nref; ++iref)
457 int ilor = ho2lor.GetRow(iho)[iref];
458 for (
int vd=0; vd<vdim; ++vd)
460 fes_lor.GetElementDofs(ilor, vdofs);
461 fes_lor.DofsToVDofs(vd, vdofs);
468 fes_ho.GetElementVDofs(iho, vdofs);
476 if (fes_ho.GetNE() == 0) {
return; }
477 MFEM_VERIFY(P.Size() > 0,
"Prolongation not supported for these spaces.")
478 int vdim = fes_ho.GetVDim();
482 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
484 int nref = ho2lor.RowSize(iho);
485 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
486 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
487 xel_mat.
SetSize(ndof_lor*nref, vdim);
488 yel_mat.
SetSize(ndof_ho, vdim);
489 DenseMatrix P_iho(&P[offsets[iho]], ndof_ho, ndof_lor*nref);
492 for (
int iref = 0; iref < nref; ++iref)
494 int ilor = ho2lor.GetRow(iho)[iref];
495 for (
int vd = 0; vd < vdim; ++vd)
497 fes_lor.GetElementDofs(ilor, vdofs);
498 fes_lor.DofsToVDofs(vd, vdofs);
505 fes_ho.GetElementVDofs(iho, vdofs);
513 if (fes_ho.GetNE() == 0) {
return; }
514 MFEM_VERIFY(P.Size() > 0,
"Prolongation not supported for these spaces.")
515 int vdim = fes_ho.GetVDim();
518 for (
int iho = 0; iho < fes_ho.GetNE(); ++iho)
520 int nref = ho2lor.RowSize(iho);
521 int ndof_ho = fes_ho.GetFE(iho)->GetDof();
522 int ndof_lor = fes_lor.GetFE(ho2lor.GetRow(iho)[0])->GetDof();
523 xel_mat.
SetSize(ndof_ho, vdim);
524 yel_mat.
SetSize(ndof_lor*nref, vdim);
525 DenseMatrix P_iho(&P[offsets[iho]], ndof_ho, ndof_lor*nref);
527 fes_ho.GetElementVDofs(iho, vdofs);
532 for (
int iref = 0; iref < nref; ++iref)
534 int ilor = ho2lor.GetRow(iho)[iref];
535 for (
int vd=0; vd<vdim; ++vd)
537 fes_lor.GetElementDofs(ilor, vdofs);
538 fes_lor.DofsToVDofs(vd, vdofs);
549 std::unique_ptr<SparseMatrix> R_mat, M_LH_mat;
555 const SparseMatrix *P_ho = fes_ho_scalar.GetConformingProlongation();
556 const SparseMatrix *P_lor = fes_lor_scalar.GetConformingProlongation();
562 R_mat.reset(
RAP(*P_lor, *R_mat, *P_ho));
563 M_LH_mat.reset(
RAP(*P_lor, *M_LH_mat, *P_ho));
573 M_LH_mat.reset(
mfem::Mult(*P_lor, *M_LH_mat));
582 R = std::move(R_mat);
583 M_LH = std::move(M_LH_mat);
593 pcg(pfes_ho.GetComm())
603 pfes_lor_scalar.GlobalVSize(),
604 pfes_ho_scalar.GlobalVSize(),
605 pfes_lor_scalar.GetDofOffsets(),
606 pfes_ho_scalar.GetDofOffsets(),
609 pfes_lor_scalar.GlobalVSize(),
610 pfes_ho_scalar.GlobalVSize(),
611 pfes_lor_scalar.GetDofOffsets(),
612 pfes_ho_scalar.GetDofOffsets(),
616 &R_local, pfes_ho_scalar.Dof_TrueDof_Matrix());
618 &M_LH_local, pfes_ho_scalar.Dof_TrueDof_Matrix());
620 std::unique_ptr<HypreParMatrix> R_T(R_mat->
Transpose());
624 amg->SetPrintLevel(0);
627 M_LH.reset(M_LH_mat);
641 pcg.SetPrintLevel(0);
643 pcg.SetMaxIter(1000);
645 pcg.SetRelTol(1e-13);
646 pcg.SetAbsTol(1e-13);
647 pcg.SetPreconditioner(*precon);
648 pcg.SetOperator(*RTxM_LH);
654 Vector X(fes_ho.GetTrueVSize());
657 Vector Y_dim(R->Height());
658 Vector Y(fes_lor.GetTrueVSize());
662 GetTDofs(fes_ho, x, X);
664 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
666 TDofsListByVDim(fes_ho, d, vdofs_list);
667 X.GetSubVector(vdofs_list, X_dim);
668 R->Mult(X_dim, Y_dim);
669 TDofsListByVDim(fes_lor, d, vdofs_list);
670 Y.SetSubVector(vdofs_list, Y_dim);
673 SetFromTDofs(fes_lor, Y, y);
679 Vector X(fes_lor.GetTrueVSize());
680 Vector X_dim(R->Height());
683 Vector Y(fes_ho.GetTrueVSize());
687 GetTDofsTranspose(fes_lor, x, X);
689 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
691 TDofsListByVDim(fes_lor, d, vdofs_list);
692 X.GetSubVector(vdofs_list, X_dim);
693 R->MultTranspose(X_dim, Y_dim);
694 TDofsListByVDim(fes_ho, d, vdofs_list);
695 Y.SetSubVector(vdofs_list, Y_dim);
698 SetFromTDofsTranspose(fes_ho, Y, y);
704 Vector X(fes_lor.GetTrueVSize());
705 Vector X_dim(M_LH->Height());
708 Vector Y_dim(pcg.Height());
709 Vector Y(fes_ho.GetTrueVSize());
713 GetTDofs(fes_lor, x, X);
715 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
717 TDofsListByVDim(fes_lor, d, vdofs_list);
718 X.GetSubVector(vdofs_list, X_dim);
720 M_LH->MultTranspose(X_dim, Xbar);
722 pcg.Mult(Xbar, Y_dim);
723 TDofsListByVDim(fes_ho, d, vdofs_list);
724 Y.SetSubVector(vdofs_list, Y_dim);
727 SetFromTDofs(fes_ho, Y, y);
733 Vector X(fes_ho.GetTrueVSize());
734 Vector X_dim(pcg.Width());
735 Vector Xbar(pcg.Height());
737 Vector Y_dim(M_LH->Height());
738 Vector Y(fes_lor.GetTrueVSize());
742 GetTDofsTranspose(fes_ho, x, X);
744 for (
int d = 0; d < fes_ho.GetVDim(); ++d)
746 TDofsListByVDim(fes_ho, d, vdofs_list);
747 X.GetSubVector(vdofs_list, X_dim);
750 pcg.Mult(X_dim, Xbar);
751 M_LH->Mult(Xbar, Y_dim);
752 TDofsListByVDim(fes_lor, d, vdofs_list);
753 Y.SetSubVector(vdofs_list, Y_dim);
756 SetFromTDofsTranspose(fes_lor, Y, y);
761 pcg.SetRelTol(p_rtol_);
766 pcg.SetAbsTol(p_atol_);
770 std::unique_ptr<SparseMatrix>,
771 std::unique_ptr<SparseMatrix>>
774 std::pair<std::unique_ptr<SparseMatrix>,
775 std::unique_ptr<SparseMatrix>> r_and_mlh;
777 Mesh* mesh_ho = fes_ho.GetMesh();
778 Mesh* mesh_lor = fes_lor.GetMesh();
779 int nel_ho = mesh_ho->
GetNE();
780 int nel_lor = mesh_lor->
GetNE();
781 int ndof_lor = fes_lor.GetNDofs();
784 if (nel_ho == 0) {
return {
nullptr,
nullptr}; }
791 for (
int ig = 0; ig < geoms.
Size(); ++ig)
797 BuildHo2Lor(nel_ho, nel_lor, cf_tr);
806 for (
int iho = 0; iho < nel_ho; ++iho)
809 ho2lor.GetRow(iho, lor_els);
810 int nref = ho2lor.RowSize(iho);
814 int nedof_lor = fe_lor.
GetDof();
819 Vector shape_lor(nedof_lor);
822 for (
int iref = 0; iref < nref; ++iref)
824 int ilor = lor_els[iref];
835 ML_el += (shape_lor *= (el_tr->
Weight() * ip_lor.
weight));
837 fes_lor.GetElementDofs(ilor, dofs_lor);
842 LumpedMassInverse(ML_inv);
845 r_and_mlh.first = AllocR();
850 for (
int icol = 0; icol < r_and_mlh.first->Height() + 1; ++icol)
852 I[icol] = r_and_mlh.first->GetI()[icol];
855 for (
int jcol = 0; jcol < r_and_mlh.first->NumNonZeroElems(); ++jcol)
857 J[jcol] = r_and_mlh.first->GetJ()[jcol];
859 r_and_mlh.second = std::unique_ptr<SparseMatrix>(
861 r_and_mlh.first->Width(),
true,
true,
true));
867 for (
int iho = 0; iho < nel_ho; ++iho)
870 ho2lor.GetRow(iho, lor_els);
871 int nref = ho2lor.RowSize(iho);
880 int nedof_ho = fe_ho.
GetDof();
881 int nedof_lor = fe_lor.
GetDof();
885 for (
int iref = 0; iref < nref; ++iref)
887 int ilor = lor_els[iref];
894 ElemMixedMass(geom, fe_ho, fe_lor, el_tr, ip_tr, M_LH_el);
897 fes_lor.GetElementDofs(ilor, dofs_lor);
899 for (
int i = 0; i < nedof_lor; ++i)
902 R_el.
SetRow(i, R_row.
Set(ML_inv[dofs_lor[i]], R_row));
905 fes_ho.GetElementDofs(iho, dofs_ho);
906 r_and_mlh.second->AddSubMatrix(dofs_lor, dofs_ho, M_LH_el);
907 r_and_mlh.first->AddSubMatrix(dofs_lor, dofs_ho, R_el);
981 R_mat->
BooleanMult(x_vdofs_marker, X_vdofs_marker);
994 Vector ML_inv_full(fes_lor.GetVSize());
997 fes_lor.GetVDofs(0, vdofs_list);
998 ML_inv_full.SetSubVector(vdofs_list, ML_inv);
1000 Vector ML_inv_true(fes_lor.GetTrueVSize());
1001 const Operator *P = fes_lor.GetProlongationMatrix();
1003 else { ML_inv_true = ML_inv_full; }
1005 for (
int i = 0; i < ML_inv_true.Size(); ++i)
1007 ML_inv_true[i] = 1.0 / ML_inv_true[i];
1010 if (P) { P->Mult(ML_inv_true, ML_inv_full); }
1011 else { ML_inv_full = ML_inv_true; }
1013 ML_inv_full.GetSubVector(vdofs_list, ML_inv);
1016 std::unique_ptr<SparseMatrix>
1019 const Table& elem_dof_ho = fes_ho.GetElementToDofTable();
1020 const Table& elem_dof_lor = fes_lor.GetElementToDofTable();
1021 const int ndof_ho = fes_ho.GetNDofs();
1022 const int ndof_lor = fes_lor.GetNDofs();
1025 Transpose(elem_dof_lor, dof_elem_lor, ndof_lor);
1027 Mesh* mesh_lor = fes_lor.GetMesh();
1031 const int* elem_dof_hoI = elem_dof_ho.
GetI();
1032 const int* elem_dof_hoJ = elem_dof_ho.
GetJ();
1033 const int* dof_elem_lorI = dof_elem_lor.
GetI();
1034 const int* dof_elem_lorJ = dof_elem_lor.
GetJ();
1040 dof_used_ho.
SetSize(ndof_ho, -1);
1043 for (
int ilor = 0; ilor < ndof_lor; ++ilor)
1045 for (
int jlor = dof_elem_lorI[ilor]; jlor < dof_elem_lorI[ilor + 1]; ++jlor)
1047 int el_lor = dof_elem_lorJ[jlor];
1049 for (
int jho = elem_dof_hoI[iho]; jho < elem_dof_hoI[iho + 1]; ++jho)
1051 int dof_ho = elem_dof_hoJ[jho];
1052 if (dof_used_ho[dof_ho] != ilor)
1054 dof_used_ho[dof_ho] = ilor;
1062 Table dof_lor_dof_ho;
1063 dof_lor_dof_ho.
SetDims(ndof_lor, sizeJ);
1065 for (
int i = 0; i < ndof_ho; ++i)
1067 dof_used_ho[i] = -1;
1071 int* dof_dofI = dof_lor_dof_ho.
GetI();
1072 int* dof_dofJ = dof_lor_dof_ho.
GetJ();
1074 for (
int ilor = 0; ilor < ndof_lor; ++ilor)
1076 dof_dofI[ilor] = sizeJ;
1077 for (
int jlor = dof_elem_lorI[ilor]; jlor < dof_elem_lorI[ilor + 1]; ++jlor)
1079 int el_lor = dof_elem_lorJ[jlor];
1081 for (
int jho = elem_dof_hoI[iho]; jho < elem_dof_hoI[iho + 1]; ++jho)
1083 int dof_ho = elem_dof_hoJ[jho];
1084 if (dof_used_ho[dof_ho] != ilor)
1086 dof_used_ho[dof_ho] = ilor;
1087 dof_dofJ[sizeJ] = dof_ho;
1097 std::unique_ptr<SparseMatrix> R_local(
new SparseMatrix(
1098 dof_dofI, dof_dofJ, data, ndof_lor,
1099 ndof_ho,
true,
true,
true));
1115 if (!
F) { BuildF(); }
1123 if (!
F) { BuildF(); }
1129 void L2ProjectionGridTransfer::BuildF()
1145 F =
new L2ProjectionH1Space(dom_pfes, ran_pfes);
1163 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize())
1166 if (lFESpace_.
FEColl() == hFESpace_.
FEColl() && !isvar_order)
1178 && dynamic_cast<const TensorBasisElement*>(hFESpace_.
GetFE(0))
1208 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), lFESpace(lFESpace_),
1228 int vdim = lFESpace.
GetVDim();
1230 for (
int i = 0; i < mesh->
GetNE(); i++)
1236 if (geom != cached_geom || isvar_order)
1238 h_fe = hFESpace.
GetFE(i);
1239 l_fe = lFESpace.
GetFE(i);
1246 for (
int vd = 0; vd < vdim; vd++)
1248 l_dofs.
Copy(l_vdofs);
1250 h_dofs.
Copy(h_vdofs);
1257 loc_prol.
Mult(subX, subY);
1285 int vdim = lFESpace.
GetVDim();
1287 for (
int i = 0; i < mesh->
GetNE(); i++)
1293 if (geom != cached_geom || isvar_order)
1295 h_fe = hFESpace.
GetFE(i);
1296 l_fe = lFESpace.
GetFE(i);
1304 for (
int vd = 0; vd < vdim; vd++)
1306 l_dofs.
Copy(l_vdofs);
1308 h_dofs.
Copy(h_vdofs);
1316 for (
int p = 0;
p < h_dofs.
Size(); ++
p)
1318 if (processed[lFESpace.
DecodeDof(h_dofs[
p])])
1324 loc_prol.
Mult(subX, subY);
1332 for (
int p = 0;
p < h_dofs.
Size(); ++
p)
1334 processed[lFESpace.
DecodeDof(h_dofs[
p])] = 1;
1344 :
Operator(hFESpace_.GetVSize(), lFESpace_.GetVSize()), lFESpace(lFESpace_),
1350 if (mesh->
GetNE() == 0)
1358 MFEM_VERIFY(ltel,
"Low order FE space must be tensor product space");
1362 MFEM_VERIFY(htel,
"High order FE space must be tensor product space");
1372 int j = hdofmap[i] >=0 ? hdofmap[i] : -1 - hdofmap[i];
1376 NE = lFESpace.
GetNE();
1384 elem_restrict_lex_l =
1387 MFEM_VERIFY(elem_restrict_lex_l,
1388 "Low order ElementRestriction not available");
1390 elem_restrict_lex_h =
1393 MFEM_VERIFY(elem_restrict_lex_h,
1394 "High order ElementRestriction not available");
1401 MFEM_VERIFY(dynamic_cast<const ElementRestriction*>(elem_restrict_lex_h),
1402 "High order element restriction is of unsupported type");
1406 ->BooleanMask(mask);
1410 namespace TransferKernels
1425 for (
int dy = 0; dy < D1D; ++dy)
1427 double sol_x[DofQuadLimits::MAX_Q1D];
1428 for (
int qy = 0; qy < Q1D; ++qy)
1432 for (
int dx = 0; dx < D1D; ++dx)
1434 const double s = x_(dx, dy, e);
1435 for (
int qx = 0; qx < Q1D; ++qx)
1437 sol_x[qx] += B_(qx, dx) *
s;
1440 for (
int qy = 0; qy < Q1D; ++qy)
1442 const double d2q = B_(qy, dy);
1443 for (
int qx = 0; qx < Q1D; ++qx)
1445 y_(qx, qy, e) += d2q * sol_x[qx];
1449 for (
int qy = 0; qy < Q1D; ++qy)
1451 for (
int qx = 0; qx < Q1D; ++qx)
1453 y_(qx, qy, e) *= m_(qx, qy, e);
1463 auto x_ =
Reshape(localL.
Read(), D1D, D1D, D1D, NE);
1466 auto m_ =
Reshape(mask.
Read(), Q1D, Q1D, Q1D, NE);
1472 for (
int dz = 0; dz < D1D; ++dz)
1474 double sol_xy[DofQuadLimits::MAX_Q1D][DofQuadLimits::MAX_Q1D];
1475 for (
int qy = 0; qy < Q1D; ++qy)
1477 for (
int qx = 0; qx < Q1D; ++qx)
1479 sol_xy[qy][qx] = 0.0;
1482 for (
int dy = 0; dy < D1D; ++dy)
1484 double sol_x[DofQuadLimits::MAX_Q1D];
1485 for (
int qx = 0; qx < Q1D; ++qx)
1489 for (
int dx = 0; dx < D1D; ++dx)
1491 const double s = x_(dx, dy, dz, e);
1492 for (
int qx = 0; qx < Q1D; ++qx)
1494 sol_x[qx] += B_(qx, dx) *
s;
1497 for (
int qy = 0; qy < Q1D; ++qy)
1499 const double wy = B_(qy, dy);
1500 for (
int qx = 0; qx < Q1D; ++qx)
1502 sol_xy[qy][qx] += wy * sol_x[qx];
1506 for (
int qz = 0; qz < Q1D; ++qz)
1508 const double wz = B_(qz, dz);
1509 for (
int qy = 0; qy < Q1D; ++qy)
1511 for (
int qx = 0; qx < Q1D; ++qx)
1513 y_(qx, qy, qz, e) += wz * sol_xy[qy][qx];
1518 for (
int qz = 0; qz < Q1D; ++qz)
1520 for (
int qy = 0; qy < Q1D; ++qy)
1522 for (
int qx = 0; qx < Q1D; ++qx)
1524 y_(qx, qy, qz, e) *= m_(qx, qy, qz, e);
1544 for (
int qy = 0; qy < Q1D; ++qy)
1546 double sol_x[DofQuadLimits::MAX_D1D];
1547 for (
int dx = 0; dx < D1D; ++dx)
1551 for (
int qx = 0; qx < Q1D; ++qx)
1553 const double s = m_(qx, qy, e) * x_(qx, qy, e);
1554 for (
int dx = 0; dx < D1D; ++dx)
1556 sol_x[dx] += Bt_(dx, qx) *
s;
1559 for (
int dy = 0; dy < D1D; ++dy)
1561 const double q2d = Bt_(dy, qy);
1562 for (
int dx = 0; dx < D1D; ++dx)
1564 y_(dx, dy, e) += q2d * sol_x[dx];
1574 auto x_ =
Reshape(localH.
Read(), Q1D, Q1D, Q1D, NE);
1577 auto m_ =
Reshape(mask.
Read(), Q1D, Q1D, Q1D, NE);
1583 for (
int qz = 0; qz < Q1D; ++qz)
1585 double sol_xy[DofQuadLimits::MAX_D1D][DofQuadLimits::MAX_D1D];
1586 for (
int dy = 0; dy < D1D; ++dy)
1588 for (
int dx = 0; dx < D1D; ++dx)
1593 for (
int qy = 0; qy < Q1D; ++qy)
1595 double sol_x[DofQuadLimits::MAX_D1D];
1596 for (
int dx = 0; dx < D1D; ++dx)
1600 for (
int qx = 0; qx < Q1D; ++qx)
1602 const double s = m_(qx, qy, qz, e) * x_(qx, qy, qz, e);
1603 for (
int dx = 0; dx < D1D; ++dx)
1605 sol_x[dx] += Bt_(dx, qx) *
s;
1608 for (
int dy = 0; dy < D1D; ++dy)
1610 const double wy = Bt_(dy, qy);
1611 for (
int dx = 0; dx < D1D; ++dx)
1613 sol_xy[dy][dx] += wy * sol_x[dx];
1617 for (
int dz = 0; dz < D1D; ++dz)
1619 const double wz = Bt_(dz, qz);
1620 for (
int dy = 0; dy < D1D; ++dy)
1622 for (
int dx = 0; dx < D1D; ++dx)
1624 y_(dx, dy, dz, e) += wz * sol_xy[dy][dx];
1647 elem_restrict_lex_l->
Mult(x, localL);
1658 MFEM_ABORT(
"TensorProductPRefinementTransferOperator::Mult not " 1659 "implemented for dim = " 1673 elem_restrict_lex_h->
Mult(x, localH);
1684 MFEM_ABORT(
"TensorProductPRefinementTransferOperator::MultTranspose not " 1685 "implemented for dim = " 1694 :
Operator(hFESpace_.GetTrueVSize(), lFESpace_.GetTrueVSize()),
1695 lFESpace(lFESpace_),
1707 if (P) { MFEM_VERIFY(R,
"Both P and R have to be not NULL") }
1723 delete localTransferOperator;
1731 localTransferOperator->
Mult(tmpL, tmpH);
1736 localTransferOperator->
Mult(x, tmpH);
1741 localTransferOperator->
Mult(x, y);
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Abstract class for all finite elements.
std::pair< std::unique_ptr< SparseMatrix >, std::unique_ptr< SparseMatrix > > ComputeSparseRAndM_LH()
Computes on-rank R and M_LH matrices.
virtual ~InterpolationGridTransfer()
const Operator & MakeTrueOperator(FiniteElementSpace &fes_in, FiniteElementSpace &fes_out, const Operator &oper, OperatorHandle &t_oper)
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 ...
virtual void Prolongate(const Vector &x, Vector &y) const
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
int GetNPoints() const
Returns the number of the points in the integration rule.
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
Class for an integration rule - an Array of IntegrationPoint.
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
virtual void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
Data type for scaled Jacobi-type smoother of sparse matrix.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
BilinearFormIntegrator * mass_integ
Ownership depends on own_mass_integ.
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
L2ProjectionH1Space(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_)
void SetRow(int r, const double *row)
virtual ~TensorProductPRefinementTransferOperator()
Destructor.
Geometry::Type GetElementBaseGeometry(int i) const
Field is discontinuous across element interfaces.
virtual void Mult(const Vector &x, Vector &y) const
FiniteElementSpace & dom_fes
Domain FE space.
int Dimension() const
Dimension of the reference space used within the elements.
virtual int GetContType() const =0
Matrix-free transfer operator between finite element spaces on the same mesh.
void Mult(const double *x, double *y) const
Matrix vector multiplication with the inverse of dense matrix.
std::unique_ptr< Operator > R
void SortRows()
Sort the column (TYPE II) indices in each row.
void SetSize(int s)
Resize the vector to size s.
void GetInverseMatrix(DenseMatrix &Ainv) const
Compute and return the inverse matrix in Ainv.
static int DecodeDof(int dof)
Helper to return the DOF associated with a sign encoded DOF.
const SparseMatrix * GetConformingRestriction() const
The returned SparseMatrix is owned by the FiniteElementSpace.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Pointer to an Operator of a specified type.
void SetDims(int rows, int nnz)
virtual void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
int Size() const
Returns the size of the vector.
virtual const Operator * GetRestrictionOperator() const
An abstract operator that performs the same action as GetRestrictionMatrix.
int nqpt
Number of quadrature points. When mode is TENSOR, this is the 1D number.
Data type dense matrix using column-major storage.
virtual ~TransferOperator()
Destructor.
Operator::Type oper_type
Desired Operator::Type for the construction of all operators defined by the underlying transfer algor...
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number...
std::unique_ptr< Operator > M_LH
~TrueTransferOperator()
Destructor.
virtual 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 LoseData()
Call this if data has been stolen.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Abstract parallel finite element space.
virtual const Operator & ForwardOperator()
Return an Operator that transfers GridFunctions from the domain FE space to GridFunctions in the rang...
void Factor()
Factor the current DenseMatrix, *a.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
void GetVDofs(int vd, Array< int > &dofs, int ndofs=-1) const
Returns the indices of all of the VDofs for the specified dimension 'vd'.
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...
virtual void Prolongate(const Vector &x, Vector &y) const
HypreParMatrix * ParMult(const HypreParMatrix *A, const HypreParMatrix *B, bool own_matrix)
virtual void ProlongateTranspose(const Vector &x, Vector &y) const
std::unique_ptr< SparseMatrix > AllocR()
Computes sparsity pattern and initializes R matrix.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
std::unique_ptr< Solver > precon
void BuildHo2Lor(int nel_ho, int nel_lor, const CoarseFineTransformations &cf_tr)
virtual ~PRefinementTransferOperator()
Destructor.
static void MarkerToList(const Array< int > &marker, Array< int > &list)
Convert a Boolean marker array to a list containing all marked indices.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Derefinement operator, used by the friend class InterpolationGridTransfer.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
FiniteElementSpace & ran_fes
Range FE space.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
ID for class SparseMatrix.
const Table * GetElementToFaceOrientationTable() const
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...
The BoomerAMG solver in hypre.
const FiniteElementSpace & fes_ho
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
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...
virtual const Operator & BackwardOperator()
Return an Operator that transfers GridFunctions from the range FE space back to GridFunctions in the ...
virtual void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
General product operator: x -> (A*B)(x) = A(B(x)).
ID for the base class Operator, i.e. any type.
virtual void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
double * GetData() const
Returns the matrix data array.
void ElemMixedMass(Geometry::Type geom, const FiniteElement &fe_ho, const FiniteElement &fe_lor, ElementTransformation *el_tr, IntegrationPointTransformation &ip_tr, DenseMatrix &M_mixed_el) const
const FiniteElementCollection * FEColl() const
OperatorHandle F
Forward, coarse-to-fine, operator.
GridTransfer(FiniteElementSpace &dom_fes_, FiniteElementSpace &ran_fes_)
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
void SetFromTDofs(const FiniteElementSpace &fes, const Vector &X, Vector &x) const
Sets dof values given a vector of tdofs and a finite element space.
ParMesh * GetParMesh() const
TensorProductPRefinementTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
Constructs a transfer operator from lFESpace to hFESpace which have different FE collections.
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...
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...
void Restriction2D(const int NE, const int D1D, const int Q1D, const Vector &localH, Vector &localL, const Array< double > &Bt, const Vector &mask)
virtual void SetAbsTol(double p_atol_)
Sets absolute tolerance in preconditioned conjugate gradient solver.
const SparseMatrix * GetConformingProlongation() const
The returned SparseMatrix is owned by the FiniteElementSpace.
L2Projection(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_)
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...
virtual void Mult(const Vector &x, Vector &y) const
void LumpedMassInverse(Vector &ML_inv) const
Returns the inverse of an on-rank lumped mass matrix.
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
void GetRow(int i, Array< int > &row) const
Return row i in array row (the Table must be finalized)
void Mult(const double *x, double *y) const
Matrix vector multiplication.
int GetNE() const
Returns number of elements in the mesh.
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...
OperatorHandle B
Backward, fine-to-coarse, operator.
List of mesh geometries stored as Array<Geometry::Type>.
int GetVDim() const
Returns vector dimension.
virtual const Operator & BackwardOperator()
Return an Operator that transfers GridFunctions from the range FE space back to GridFunctions in the ...
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, transfer operator.
Array< double > Bt
Transpose of B.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
virtual void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
Mesh * GetMesh() const
Returns the mesh.
double p(const Vector &x, double t)
virtual void MultTranspose(const Vector &x, Vector &y) const override
Restriction by applying the transpose of the Mult method.
void Transpose()
(*this) = (*this)^t
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 forall(int N, lambda &&body)
Matrix-free transfer operator between finite element spaces.
Operator that converts FiniteElementSpace L-vectors to E-vectors.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
SparseMatrix * RefinementMatrix_main(const int coarse_ndofs, const Table &coarse_elem_dof, const Table *coarse_elem_fos, const DenseTensor localP[]) const
Matrix-free transfer operator between finite element spaces on the same mesh exploiting the tensor pr...
void GetRow(int r, Vector &row) const
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
virtual 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...
L2Prolongation * B
Backward, fine-to-coarse, operator.
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
void SetupPCG()
Sets up the PCG solver (sets parameters, operator, and preconditioner)
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...
void Restriction3D(const int NE, const int D1D, const int Q1D, const Vector &localH, Vector &localL, const Array< double > &Bt, const Vector &mask)
int GetDof() const
Returns the number of degrees of freedom in the finite element.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Structure representing the matrices/tensors needed to evaluate (in reference space) the values...
virtual 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...
bool own_mass_integ
Ownership flag for mass_integ.
HypreParMatrix * Transpose() const
Returns the transpose of *this.
const CoarseFineTransformations & GetRefinementTransforms()
Vector & Set(const double a, const Vector &x)
(*this) = a * x
void GetGeometries(int dim, Array< Geometry::Type > &el_geoms) const
Return all element geometries of the given dimension present in the mesh.
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
virtual void MultTranspose(const Vector &x, Vector &y) const
L2Projection * F
Forward, coarse-to-fine, operator.
Array< double > B
Basis functions evaluated at quadrature points.
int GetNE() const
Returns number of elements.
virtual const Operator * GetProlongationMatrix() const
The returned Operator is owned by the FiniteElementSpace.
virtual const Operator & ForwardOperator()
Return an Operator that transfers GridFunctions from the domain FE space to GridFunctions in the rang...
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Class for integration point with weight.
void SetOperatorOwner(bool own=true)
Set the ownership flag for the held Operator.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
GridFunction interpolation operator applicable after mesh refinement.
virtual 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...
SparseMatrix * TransposeMult(const SparseMatrix &A, const SparseMatrix &B)
C = A^T B.
std::unique_ptr< Operator > RTxM_LH
const FiniteElementSpace & fes_lor
General triple product operator x -> A*B*C*x, with ownership of the factors.
PRefinementTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
Constructs a transfer operator from lFESpace to hFESpace which have different FE collections.
TrueTransferOperator(const FiniteElementSpace &lFESpace_, const FiniteElementSpace &hFESpace_)
Constructs a transfer operator working on true degrees of freedom from lFESpace to hFESpace...
virtual void Mult(const Vector &x, Vector &y) const override
Interpolation or prolongation of a true dof vector x to a true dof vector y.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
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.
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Lexicographic ordering for tensor-product FiniteElements.
Operator * Ptr() const
Access the underlying Operator pointer.
int Size() const
Return the logical size of the array.
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...
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
virtual ~L2ProjectionGridTransfer()
ID for class HypreParMatrix.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void ProlongateTranspose(const Vector &x, Vector &y) const
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.
Field is continuous across element interfaces.
HypreParMatrix * Dof_TrueDof_Matrix() const
The true dof-to-dof interpolation matrix.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Wrapper for hypre's ParCSR matrix class.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Rank 3 tensor (array of matrices)
L2ProjectionL2Space(const FiniteElementSpace &fes_ho_, const FiniteElementSpace &fes_lor_)
HYPRE_BigInt * GetTrueDofOffsets() const
void Prolongation2D(const int NE, const int D1D, const int Q1D, const Vector &localL, Vector &localH, const Array< double > &B, const Vector &mask)
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element...
virtual const SparseMatrix * GetHpRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
void GetLocalRefinementMatrices(Geometry::Type geom, DenseTensor &localP) const
virtual void SetRelTol(double p_rtol_)
Sets relative tolerance in preconditioned conjugate gradient solver.
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const
Compute the full set of vdofs corresponding to each entry in dofs.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
virtual bool SupportsBackwardsOperator() const
TransferOperator(const FiniteElementSpace &lFESpace, const FiniteElementSpace &hFESpace)
Constructs a transfer operator from lFESpace to hFESpace.
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 void MultTranspose(const Vector &x, Vector &y) const
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
void Prolongation3D(const int NE, const int D1D, const int Q1D, const Vector &localL, Vector &localH, const Array< double > &B, const Vector &mask)
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i-th element.