69 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace*
>(fes);
70 MFEM_VERIFY(pfes,
"Restriction setup requires ParFiniteElementSpace");
71 cache->restr_v = fes->GetElementRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC);
72 cache->restr_f = pfes->GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC,
73 mfem::FaceType::Interior,
74 mfem::L2FaceValues::DoubleValued);
75 cache->restr_b = pfes->GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC,
76 mfem::FaceType::Boundary,
77 mfem::L2FaceValues::SingleValued);
85 const int nelem = cache->num_elements;
86 const int p = cache->p;
87 const int Np = cache->Np;
88 const int dim = cache->dim;
90 const int Np_y = dim > 1 ? Np : 1;
91 const int Np_z = dim > 2 ? Np : 1;
92 const int neq = cache->num_equations;
93 mfem::Mesh *mesh = fes->GetMesh();
96 const int IntegrationOrder = 2 * Np_x - 3;
97 cache->ir = &cache->GLIntRules.Get(mfem::Geometry::SEGMENT, IntegrationOrder);
98 auto vol_topo = (dim == 1 ? mfem::Geometry::SEGMENT :
99 (dim == 2 ? mfem::Geometry::SQUARE : mfem::Geometry::CUBE));
100 auto face_topo = (dim == 1 ? mfem::Geometry::POINT :
101 (dim == 2 ? mfem::Geometry::SEGMENT : mfem::Geometry::SQUARE));
103 cache->ir_face = &cache->GLIntRules.Get(face_topo, IntegrationOrder);
104 cache->ir_vol = &cache->GLIntRules.Get(vol_topo, IntegrationOrder);
106 MFEM_ASSERT(cache->ir->GetNPoints() == Np_x,
"");
107 MFEM_ASSERT(cache->ir_vol->GetNPoints() == Np_x*Np_y*Np_z,
"");
110 cache->elJac.SetSize(Np_x*Np_y*Np_z*nelem);
111 cache->elMetric.SetSize(dim*dim*Np_x*Np_y*Np_z*nelem);
112 cache->elQuadratureWeights.SetSize(Np_x*Np_y*Np_z*nelem);
114 Np_x*Np_y*Np_z*nelem : 0);
115 for (
int i = 0; i < nelem; i++)
117 mfem::ElementTransformation *T = fes->GetElementTransformation(i);
118 assert(T->ElementNo == i);
123 mfem::DenseMatrix D_T, Dhat_T, Dhat2_T;
125 Dhat_T.SetSize(Np_x);
126 Dhat2_T.SetSize(Np_x);
128 mfem::Vector wBary(Np_x);
131 for (
int i = 1; i < Np_x; i++)
133 for (
int j = 0; j < i; j++)
135 wBary(j) *= (cache->ir->IntPoint(j).x - cache->ir->IntPoint(i).x);
136 wBary(i) *= (cache->ir->IntPoint(i).x - cache->ir->IntPoint(j).x);
142 for (
int iL = 0; iL < Np_x; iL++)
144 for (
int i = 0; i < Np_x; i++)
148 D_T(i, iL) = wBary(iL) / wBary(i) / (cache->ir->IntPoint(i).x - cache->ir->IntPoint(iL).x);
149 D_T(i, i) -= D_T(i, iL);
155 Dhat_T(0, 0) += 1.0 / cache->ir->IntPoint(0).weight;
156 Dhat_T(Np - 1, Np - 1) -= 1.0 / cache->ir->IntPoint(Np - 1).weight;
161 Dhat2_T(0, 0) += 1.0 / cache->ir->IntPoint(0).weight;
162 Dhat2_T(Np - 1, Np - 1) -= 1.0 / cache->ir->IntPoint(Np - 1).weight;
167 cache->D.SetSize(Np_x*Np_x);
168 cache->Dhat.SetSize(Np_x*Np_x);
169 cache->Dhat2.SetSize(Np_x*Np_x);
170 std::memcpy(cache->D.HostWrite(), D_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
171 std::memcpy(cache->Dhat.HostWrite(), Dhat_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
172 std::memcpy(cache->Dhat2.HostWrite(), Dhat2_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
174 cache->elWaveSpeed.SetSize(nelem);
175 cache->elWaveSpeed = 0.0;
176 cache->elWaveSpeed.UseDevice();
177 cache->elWaveSpeed.Read();
179 cache->elJac.UseDevice();
180 cache->elMetric.UseDevice();
181 cache->elRadius.UseDevice();
182 cache->D.UseDevice();
183 cache->Dhat.UseDevice();
184 cache->Dhat2.UseDevice();
186 cache->elMetric.Read();
187 cache->elRadius.Read();
193 const int nfp = cache->ir_face->GetNPoints();
194 cache->num_face_points = nfp;
196 const int nfaces_restr = cache->restr_f->Height() / (nfp * neq * 2);
197 cache->num_interior_faces = nfaces_restr;
198 MFEM_VERIFY(nfaces_restr > 0,
"nfaces_restr is 0");
202 cache->face_normals.UseDevice();
203 cache->face_wt_minus.UseDevice();
204 cache->face_wt_plus.UseDevice();
205 cache->face_radius.UseDevice();
206 cache->face_normals.Read();
207 cache->face_wt_minus.Read();
208 cache->face_wt_plus.Read();
209 cache->face_radius.Read();
211 cache->ifWaveSpeed.SetSize(cache->num_interior_faces);
212 cache->ifWaveSpeed = 0.0;
213 cache->ifWaveSpeed.UseDevice();
214 cache->ifWaveSpeed.Read();
221 mfem::Mesh *mesh = fes->GetMesh();
223 cache->num_attr = mesh->attributes.Size() ? mesh->attributes.Max() : 0;
224 cache->vol_attr_marker.SetSize(cache->num_attr);
225 cache->vol_attr_marker = 1;
227 cache->domain_attr_marker.SetSize(cache->num_attr);
228 cache->domain_attr_marker = 1;
231 const int ne = mesh->GetNE();
232 cache->elem_attr.SetSize(ne);
233 for (
int e = 0; e < ne; ++e)
235 const int attr = mesh->GetAttribute(e);
236 cache->elem_attr[e] = attr;
240 if (cache->num_attr > 0)
242 for (
int e = 0; e < ne; ++e)
244 const int a = cache->elem_attr[e];
245 MFEM_VERIFY(a >= 1 && a <= cache->num_attr,
246 "element attribute out of range: attr=" << a
247 <<
" num_attr=" << cache->num_attr);
251 cache->elem_attr.UseDevice();
252 cache->vol_attr_marker.UseDevice();
253 cache->domain_attr_marker.UseDevice();
254 cache->elem_attr.Read();
255 cache->vol_attr_marker.Read();
256 cache->domain_attr_marker.Read();
283 const std::vector<mfem::Array<int>> &bdr_marker_vector,
286 auto &bnd_faces = pmesh->GetFaceIndices(mfem::FaceType::Boundary);
287 const auto &bnd_face_attr = pmesh->GetBdrFaceAttributes();
289 const int nbnd_faces = bnd_faces.Size();
291 MFEM_VERIFY(bnd_face_attr.Size() == nbnd_faces,
292 "Expected compact boundary-face attribute array");
294 cache->bnd_attr.SetSize(nbnd_faces);
295 cache->bnd_marker_index.SetSize(nbnd_faces);
297 for (
int fslot = 0; fslot < nbnd_faces; ++fslot)
299 const int attr = bnd_face_attr[fslot];
300 cache->bnd_attr[fslot] = attr;
301 cache->bnd_marker_index[fslot] = -1;
303 if (attr <= 0) {
continue; }
305 for (
int mindex = 0; mindex < (int)bdr_marker_vector.size(); ++mindex)
307 const auto &marker = bdr_marker_vector[mindex];
308 MFEM_VERIFY(attr-1 < marker.Size(),
"boundary attribute out of marker range");
312 cache->bnd_marker_index[fslot] = mindex;
338 const std::vector<mfem::Array<int>> &bdr_marker_vector,
341 auto *mesh = fes->GetMesh();
342 auto *pmesh =
dynamic_cast<mfem::ParMesh*
>(mesh);
343 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace*
>(fes);
345 MFEM_VERIFY(pmesh,
"need ParMesh");
346 MFEM_VERIFY(pfes,
"need ParFiniteElementSpace");
347 MFEM_VERIFY(cache,
"need cache");
348 MFEM_VERIFY(cache->ir_face,
"cache->ir_face must exist");
349 MFEM_VERIFY(cache->ir,
"cache->ir must exist");
351 cache->fqs_bnd.reset(
new mfem::FaceQuadratureSpace(*mesh, *cache->ir_face,
352 mfem::FaceType::Boundary));
354 const int dim = mesh->Dimension();
355 const int nfp = cache->ir_face->GetNPoints();
357 auto &bnd_faces = pmesh->GetFaceIndices(mfem::FaceType::Boundary);
358 const int nbnd_faces = bnd_faces.Size();
360 cache->bndWaveSpeed.SetSize(nbnd_faces*nfp);
361 cache->bndWaveSpeed = 0.0;
362 cache->bndWaveSpeed.Read();
365 mfem::Array<int> face_to_be;
375 cache->bnd_normals.SetSize(nbnd_faces * nfp * dim);
376 cache->bnd_wt.SetSize(nbnd_faces * nfp);
377 cache->bnd_xyz.SetSize(nbnd_faces * nfp * dim);
379 nbnd_faces * nfp : 0);
381 mfem::real_t *nor_d = cache->bnd_normals.HostWrite();
382 mfem::real_t *wt_d = cache->bnd_wt.HostWrite();
383 mfem::real_t *xyz_d = cache->bnd_xyz.HostWrite();
384 mfem::real_t *rad_d = cache->bnd_radius.Size() > 0 ?
385 cache->bnd_radius.HostWrite() :
nullptr;
387 const mfem::real_t w0 = cache->ir->IntPoint(0).weight;
389 mfem::Vector nor(dim);
390 mfem::Vector phys(dim);
392 auto store = [&](
int fslot,
int fp_restr,
393 const mfem::Vector &nor,
394 const mfem::Vector &phys,
395 mfem::real_t inv_wJ1)
397 const int base_scl = fslot * nfp + fp_restr;
398 const int base_vec = base_scl * dim;
400 for (
int d = 0; d < dim; ++d)
402 nor_d[base_vec + d] = nor(d);
403 xyz_d[base_vec + d] = phys(d);
406 wt_d[base_scl] = inv_wJ1;
409 const mfem::real_t radius =
411 rad_d[base_scl] = cache->axisymmetric ?
413 radius,
"boundary face " + std::to_string(fslot) +
414 ", point " + std::to_string(fp_restr)) : radius;
418 for (
int fslot = 0; fslot < nbnd_faces; ++fslot)
420 const int face_id = bnd_faces[fslot];
421 const int be_match = face_to_be[face_id];
424 MFEM_VERIFY(be_match >= 0,
"Could not find boundary element for boundary face");
425 auto *tr = mesh->GetBdrFaceTransformations(be_match);
426 MFEM_VERIFY(tr,
"expected boundary face transformation");
428 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
430 const int fp_geom = cache->inv_fp_map_bnd[fslot * nfp + fp_restr];
431 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
432 tr->SetAllIntPoints(&ip);
434 const mfem::real_t J1 = tr->GetElement1Transformation().Weight();
437 nor(0) = (tr->GetElement1IntPoint().x - 0.5) * 2.0;
441 mfem::CalcOrtho(tr->Jacobian(), nor);
443 tr->Transform(ip, phys);
444 store(fslot, fp_restr, nor, phys, 1.0 / (w0 * J1));
447 cache->bnd_xyz.UseDevice();
448 cache->bnd_radius.UseDevice();
449 cache->bnd_xyz.Read();
450 cache->bnd_radius.Read();
458 mfem::real_t *Jinv_h = cache->elJac.HostWrite();
459 mfem::real_t *Met_h = cache->elMetric.HostWrite();
460 mfem::real_t *qWgts_h = cache->elQuadratureWeights.HostWrite();
461 mfem::real_t *radius_h = cache->elRadius.Size() > 0 ?
462 cache->elRadius.HostWrite() :
nullptr;
464 int dim = cache->dim;
465 mfem::Vector metric1(dim);
466 mfem::Vector physical(dim);
467 const int e = Tr.ElementNo;
468 const int nq = cache->Np_x * cache->Np_y * cache->Np_z;
470 for (
int q = 0; q < nq; ++q)
472 const mfem::IntegrationPoint &ip = cache->ir_vol->IntPoint(q);
474 const mfem::real_t J = Tr.Weight();
475 Jinv_h[e*nq + q] = J;
476 qWgts_h[e*nq + q] = J * ip.weight;
479 Tr.Transform(ip, physical);
480 const mfem::real_t radius =
482 radius_h[e*nq + q] = cache->axisymmetric ?
484 radius,
"element " + std::to_string(e) +
485 ", point " + std::to_string(q)) : radius;
487 const mfem::DenseMatrix &adj = Tr.AdjugateJacobian();
488 for (
int dir = 0; dir < dim; ++dir)
490 adj.GetRow(dir, metric1);
492 for (
int d = 0; d < dim; ++d)
494 const int idxM = (((e*nq + q)*dim + dir)*dim + d);
495 Met_h[idxM] = metric1(d);
504 auto *mesh = fes->GetMesh();
505 auto *pmesh =
dynamic_cast<mfem::ParMesh*
>(mesh);
506 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace*
>(fes);
507 cache->fqs_int.reset(
new mfem::FaceQuadratureSpace(*mesh, *cache->ir_face,
508 mfem::FaceType::Interior));
509 MFEM_VERIFY(pfes,
"need ParFiniteElementSpace");
511 const int dim = mesh->Dimension();
512 const int neq = pfes->GetVDim();
513 const int nfp = cache->ir_face->GetNPoints();
515 auto &int_faces = pmesh->GetFaceIndices(mfem::FaceType::Interior);
516 const int ninterior_faces = int_faces.Size();
518 cache->inv_fp_map.SetSize(ninterior_faces * nfp);
519 for (
int face_slot = 0; face_slot < ninterior_faces; ++face_slot)
521 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
523 int fp_perm = cache->fqs_int->GetPermutedIndex(face_slot, fp_restr);
524 cache->inv_fp_map[face_slot*nfp + fp_perm] = fp_restr;
528 cache->face_normals.SetSize(ninterior_faces * nfp * dim);
529 cache->face_wt_minus.SetSize(ninterior_faces * nfp);
530 cache->face_wt_plus.SetSize(ninterior_faces * nfp);
531 cache->face_radius.SetSize(
533 ninterior_faces * nfp : 0);
535 mfem::real_t *nor_d = cache->face_normals.HostWrite();
536 mfem::real_t *inv1_d = cache->face_wt_minus.HostWrite();
537 mfem::real_t *inv2_d = cache->face_wt_plus.HostWrite();
538 mfem::real_t *radius_d = cache->face_radius.Size() > 0 ?
539 cache->face_radius.HostWrite() :
nullptr;
540 const mfem::real_t w0 = cache->ir->IntPoint(0).weight;
542 auto store = [&](
int fslot,
int fp,
const mfem::Vector &nor,
543 const mfem::Vector &physical,
544 mfem::real_t inv_wJ1, mfem::real_t inv_wJ2)
546 const int nbase = (fslot * nfp + fp) * dim;
547 for (
int d = 0; d < dim; ++d) { nor_d[nbase + d] = nor(d); }
548 inv1_d[fslot * nfp + fp] = inv_wJ1;
549 inv2_d[fslot * nfp + fp] = inv_wJ2;
552 const mfem::real_t radius =
554 radius_d[fslot*nfp + fp] = cache->axisymmetric ?
556 radius,
"interior face " + std::to_string(fslot) +
557 ", point " + std::to_string(fp)) : radius;
561 mfem::Vector nor(dim);
562 mfem::Vector physical(dim);
566 for (
int fslot = 0; fslot < ninterior_faces; ++fslot)
568 const int face_id = int_faces[fslot];
577 auto *tr = mesh->GetInteriorFaceTransformations(face_id);
580 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
582 const int fp_geom = cache->MapFp(fslot, fp_restr);
583 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
584 tr->SetAllIntPoints(&ip);
586 const mfem::real_t J1 = tr->GetElement1Transformation().Weight();
587 const mfem::real_t J2 = tr->GetElement2Transformation().Weight();
589 if (dim == 1) { nor(0) = (tr->GetElement1IntPoint().x - 0.5)*2.0; }
590 else { mfem::CalcOrtho(tr->Jacobian(), nor); }
591 tr->Transform(ip, physical);
594 const mfem::real_t fac = 1.0;
595 store(fslot, fp_restr, nor, physical,
596 fac/(w0*J1), fac/(w0*J2));
601 auto *sh_tr = pmesh->GetSharedFaceTransformationsByLocalIndex(face_id,
true);
602 MFEM_VERIFY(sh_tr,
"expected shared face");
603 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
605 const int fp_geom = cache->MapFp(fslot, fp_restr);
606 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
607 sh_tr->SetAllIntPoints(&ip);
609 const mfem::real_t J1 = sh_tr->GetElement1Transformation().Weight();
610 const mfem::real_t J2 = sh_tr->GetElement2Transformation().Weight();
612 if (dim == 1) { nor(0) = (sh_tr->GetElement1IntPoint().x - 0.5)*2.0; }
613 else { mfem::CalcOrtho(sh_tr->Jacobian(), nor); }
614 sh_tr->Transform(ip, physical);
617 const mfem::real_t fac1 = 1.0;
618 const mfem::real_t fac2 = 0.0;
619 store(fslot, fp_restr, nor, physical,
620 fac1/(w0*J1), fac2/(w0*J2));
629 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace *
>(fes);
630 auto *pmesh = pfes->GetMesh();
631 const int dim = cache->dim;
632 const int ne = pmesh->GetNE();
633 const int Np_x = cache->Np_x;
634 const int Np_y = cache->Np_y;
635 const int Np_z = cache->Np_z;
636 const mfem::real_t *D = cache->D.HostRead();
638 mfem::DenseTensor SubcellMetricXi, SubcellMetricEta, SubcellMetricZeta;
639 SubcellMetricXi.SetSize(dim, Np_z * Np_y * (Np_x + 1), ne);
641 SubcellMetricEta.SetSize(dim, Np_z * (Np_y + 1) * Np_x, ne);
643 SubcellMetricZeta.SetSize(dim, (Np_z + 1) * Np_y * Np_x, ne);
645 for (
int el = 0; el < ne; el++)
647 mfem::ElementTransformation *Tr = pmesh->GetElementTransformation(el);
648 mfem::DenseMatrix &nor_mat_xi = SubcellMetricXi(el);
650 mfem::Vector tmp(dim);
651 mfem::Vector nor(dim);
652 mfem::Vector metric1(dim);
653 mfem::Vector metric2(dim);
655 for (
int k = 0; k < Np_z; k++)
657 const int pos1 = k * Np_y * Np_x;
658 for (
int j = 0; j < Np_y; j++)
660 const int pos = pos1 + j * Np_x;
661 const mfem::IntegrationPoint &ip1 = cache->ir_vol->IntPoint(pos);
662 Tr->SetIntPoint(&ip1);
663 Tr->AdjugateJacobian().GetRow(0, metric1);
664 for (
int i = 0; i < Np_x + 1; i++)
667 for (
int l = 0; l < i; l++)
669 const mfem::real_t *Dcol = D + l*Np_x;
671 mfem::real_t weight = cache->ir->IntPoint(l).weight;
672 for (
int m = 0; m < Np_x; m++)
674 const mfem::IntegrationPoint &ip2 = cache->ir_vol->IntPoint(pos + m);
675 Tr->SetIntPoint(&ip2);
676 Tr->AdjugateJacobian().GetRow(0, metric2);
683 nor_mat_xi.SetCol(pos + i, nor);
690 mfem::DenseMatrix &nor_mat_eta = SubcellMetricEta(el);
691 for (
int k = 0; k < Np_z; k++)
693 const int pos1 = k * Np_y * Np_x;
694 for (
int i = 0; i < Np_x; i++)
696 const mfem::IntegrationPoint &ip1 = cache->ir_vol->IntPoint(pos1 + i);
697 Tr->SetIntPoint(&ip1);
698 Tr->AdjugateJacobian().GetRow(1, metric1);
699 for (
int j = 0; j < Np_y + 1; j++)
702 for (
int l = 0; l < j; l++)
704 const mfem::real_t *Dcol = D + l*Np_x;
706 mfem::real_t weight = cache->ir->IntPoint(l).weight;
707 for (
int m = 0; m < Np_y; m++)
709 const int pos = pos1 + m * Np_x;
710 const mfem::IntegrationPoint &ip2 = cache->ir_vol->IntPoint(pos + i);
711 Tr->SetIntPoint(&ip2);
712 Tr->AdjugateJacobian().GetRow(1, metric2);
719 nor_mat_eta.SetCol(pos1 + j * Np_x + i, nor);
726 mfem::DenseMatrix &nor_mat_zeta = SubcellMetricZeta(el);
727 for (
int j = 0; j < Np_y; j++)
729 const int pos1 = j * Np_x;
730 for (
int i = 0; i < Np_x; i++)
732 const mfem::IntegrationPoint &ip1 = cache->ir_vol->IntPoint(pos1 + i);
733 Tr->SetIntPoint(&ip1);
734 Tr->AdjugateJacobian().GetRow(2, metric1);
735 for (
int k = 0; k < Np_z + 1; k++)
738 for (
int l = 0; l < k; l++)
740 const mfem::real_t *Dcol = D + l*Np_x;
742 mfem::real_t weight = cache->ir->IntPoint(l).weight;
743 for (
int m = 0; m < Np_z; m++)
745 const int pos = m * Np_y * Np_x + pos1 + i;
746 const mfem::IntegrationPoint &ip2 = cache->ir_vol->IntPoint(pos);
747 Tr->SetIntPoint(&ip2);
748 Tr->AdjugateJacobian().GetRow(2, metric2);
755 nor_mat_zeta.SetCol(k * Np_y * Np_x + pos1 + i, nor);
768 const mfem::DenseTensor &SubcellMetricEta,
769 const mfem::DenseTensor &SubcellMetricZeta,
772 const int ne = cache->num_elements;
773 const int dim = cache->dim;
776 const int Np_x = cache->Np_x;
777 const int Np_y = cache->Np_y;
778 const int Np_z = cache->Np_z;
781 const int n_metric_xi = (Np_x + 1) * Np_y * Np_z;
782 const int n_metric_eta = Np_x * (Np_y + 1) * Np_z;
783 const int n_metric_zeta = Np_x * Np_y * (Np_z + 1);
786 const int nq_metric_xi = n_metric_xi * dim;
787 const int nq_metric_eta = n_metric_eta * dim;
788 const int nq_metric_zeta = n_metric_zeta * dim;
790 cache->subcellWeights.SetSize(Np_x);
791 mfem::real_t *wgts = cache->subcellWeights.HostWrite();
792 for (
int i = 0;i < Np_x;i++){
793 wgts[i] = cache->ir->IntPoint(i).weight;
796 cache->subcellMetricXi.SetSize(nq_metric_xi*ne);
798 cache->subcellMetricEta.SetSize(nq_metric_eta*ne);
800 cache->subcellMetricZeta.SetSize(nq_metric_zeta*ne);
802 mfem::real_t *xi_h = cache->subcellMetricXi.HostWrite();
803 mfem::real_t *eta_h = (dim > 1 ? cache->subcellMetricEta.HostWrite() :
nullptr);
804 mfem::real_t *zeta_h = (dim > 2 ? cache->subcellMetricZeta.HostWrite() :
nullptr);
806 for (
int el = 0; el < ne; ++el){
807 const mfem::DenseMatrix &Mxi = SubcellMetricXi(el);
808 MFEM_VERIFY(Mxi.Height() == dim && Mxi.Width() == n_metric_xi,
809 "SubcellMetricXi has unexpected shape.");
810 for (
int id = 0;
id < n_metric_xi; ++id){
811 for (
int d = 0; d < dim; ++d){
812 xi_h [((el * n_metric_xi + id) * dim) + d] = Mxi(d,
id);
816 const mfem::DenseMatrix &Meta = SubcellMetricEta(el);
817 MFEM_VERIFY(Meta.Height() == dim && Meta.Width() == n_metric_eta,
818 "SubcellMetricEta has unexpected shape.");
819 for (
int id = 0;
id < n_metric_eta; ++id)
821 for (
int d = 0; d < dim; ++d)
823 eta_h[((el * n_metric_eta + id) * dim) + d] = Meta(d,
id);
829 const mfem::DenseMatrix &Mzeta = SubcellMetricZeta(el);
830 MFEM_VERIFY(Mzeta.Height() == dim && Mzeta.Width() == n_metric_zeta,
831 "SubcellMetricZeta has unexpected shape.");
832 for (
int id = 0;
id < n_metric_zeta; ++id)
834 for (
int d = 0; d < dim; ++d)
836 zeta_h[((el * n_metric_zeta + id) * dim) + d] = Mzeta(d,
id);
848 device_cache.ndof_scalar_el = cache.ndof_scalar_el;
849 device_cache.num_attr = cache.num_attr;
850 device_cache.attr_marker_d = cache.vol_attr_marker.Read();
851 device_cache.elem_attr_d = cache.elem_attr.Read();
852 device_cache.num_face_points = cache.num_face_points;
853 device_cache.p = cache.p;
854 device_cache.dim = cache.dim;
855 device_cache.Np = cache.Np;
856 device_cache.Np_x = cache.Np_x;
857 device_cache.Np_y = cache.Np_y;
858 device_cache.Np_z = cache.Np_z;
859 device_cache.num_elements = cache.num_elements;
860 device_cache.num_equations = cache.num_equations;
861 device_cache.axisymmetric = cache.axisymmetric;
864 device_cache.elJac_d = cache.elJac.Read();
865 device_cache.elMetric_d = cache.elMetric.Read();
866 device_cache.D_d = cache.D.Read();
867 device_cache.Dhat_d = cache.Dhat.Read();
868 device_cache.Dhat2_d = cache.Dhat2.Read();
869 device_cache.elQWgts_d = cache.elQuadratureWeights.Read();
870 device_cache.elRadius_d = cache.elRadius.Read();
873 device_cache.nor_d = cache.face_normals.Read();
874 device_cache.fw_minus_d = cache.face_wt_minus.Read();
875 device_cache.fw_plus_d = cache.face_wt_plus.Read();
876 device_cache.face_radius_d = cache.face_radius.Read();
879 device_cache.bnd_nor_d = cache.bnd_normals.Read();
880 device_cache.bnd_wt_d = cache.bnd_wt.Read();
881 device_cache.bnd_radius_d = cache.bnd_radius.Read();
882 device_cache.bnd_marker_index_d = cache.bnd_marker_index.Read();
883 device_cache.bnd_marker_to_bc_descr_d = cache.bnd_marker_to_bc_descr.Read();
884 device_cache.bc_scalar_d = cache.bc_scalar_data.Read();
885 device_cache.bc_vector_d = cache.bc_vector_data.Read();
886 device_cache.bc_descr_d = cache.bc_descriptors.Read();
889 device_cache.elWaveSpeed_d = cache.elWaveSpeed.ReadWrite();
890 device_cache.ifWaveSpeed_d = cache.ifWaveSpeed.ReadWrite();
891 device_cache.bndWaveSpeed_d = cache.bndWaveSpeed.ReadWrite();
894 device_cache.gas = cache.gas.to_device(cache);
895 device_cache.iflux = cache.iflux;
897#ifdef SUBCELL_FV_BLENDING
898 device_cache.subcell_metric_xi_d = cache.subcellMetricXi.Read();
899 device_cache.subcell_metric_eta_d = cache.subcellMetricEta.Read();
900 device_cache.subcell_metric_zeta_d = cache.subcellMetricZeta.Read();
901 device_cache.subcell_weights_d = cache.subcellWeights.Read();
909 const int points_per_face = cache.num_face_points;
910 const int boundary_faces = cache.bnd_marker_index.Size();
911 const int *marker_index = cache.bnd_marker_index.HostRead();
913 cache.bc_descriptors.HostRead();
914 const mfem::real_t *radius = cache.bnd_radius.HostRead();
915 for (
int face = 0; face < boundary_faces; ++face)
917 const int descriptor_index = marker_index[face];
918 if (descriptor_index < 0 ||
919 descriptor_index >= cache.bc_descriptors.Size() ||
920 descriptors[descriptor_index].
type !=
925 if (cache.bnd_radius.Size() != boundary_faces*points_per_face)
929 for (
int point = 0; point < points_per_face; ++point)
931 const mfem::real_t point_radius =
932 radius[face*points_per_face + point];
959 int ndofs = c.ndof_scalar_el;
960 int ne = c.num_elements;
961 const mfem::Array2D<int> ubdegs(modalBasis.
GetPolyDegs());
963 c.modal.SetSize(ndofs * ndofs);
964 c.keep_M1.SetSize(ndofs);
965 c.keep_M2.SetSize(ndofs);
969 c.keep_M1.UseDevice();
970 c.keep_M2.UseDevice();
973 auto *modal_h = c.modal.HostWrite();
974 auto *m1_h = c.keep_M1.HostWrite();
975 auto *m2_h = c.keep_M2.HostWrite();
977 mfem::Vector nodal(ndofs), modes(ndofs);
979 for (
int q = 0; q < ndofs; ++q)
986 for (
int m = 0; m < ndofs; ++m)
988 modal_h[m * ndofs + q] = modes(m);
992 mfem::Array<int> row;
993 for (
int m = 0; m < ndofs; ++m)
995 ubdegs.GetRow(m, row);
1000 for (
int d = 0; d < dim; ++d)
1002 if (row[d] > order - 2)
1007 if (row[d] > order - 1)
1013 m1_h[m] = keep1 ? 1.0 : 0.0;
1014 m2_h[m] = keep2 ? 1.0 : 0.0;
1017 c.modal_d = c.modal.Read();
1018 c.keep_M1_d = c.keep_M1.Read();
1019 c.keep_M2_d = c.keep_M2.Read();
1020 c.eta_d = c.eta.ReadWrite();
1027 std::cout <<
"Cache Contents:" << std::endl
1028 <<
"p = " << cache.p << std::endl
1029 <<
"dim = " << cache.dim << std::endl
1030 <<
"num_elements = " << cache.num_elements << std::endl
1031 <<
"Np,Np_x,Np_y,Np_z = " << cache.Np <<
"," << cache.Np_x
1032 <<
"," << cache.Np_y <<
"," << cache.Np_z << std::endl
1033 <<
"num_face_points = " << cache.num_face_points << std::endl
1034 <<
"num_attr = " << cache.num_attr << std::endl
1035 <<
"ndof_scalar_el = " << cache.ndof_scalar_el << std::endl
1036 <<
"num_interior_faces = " << cache.num_interior_faces << std::endl;
1037 MFEM_VERIFY(cache.ir,
"IR is not set");
1038 MFEM_VERIFY(cache.ir_face,
"Face IR not set");
1039 MFEM_VERIFY(cache.ir_vol,
"Volume IR not set");
1040 MFEM_VERIFY(cache.restr_v,
"Volume Restriction not set");
1041 MFEM_VERIFY(cache.restr_f,
"Facial Restriction not set");
1042 MFEM_VERIFY(cache.ndof_scalar_el == cache.Np_x*cache.Np_y*cache.Np_z,
1043 "Element dof count not equal to num quadrature points.");
1044 int ds_size = cache.elem_attr.Size();
1045 MFEM_VERIFY(ds_size > 0,
"Elem attr not set");
1047 ds_size = cache.elWaveSpeed.Size();
1048 MFEM_VERIFY(ds_size == cache.num_elements,
"Element wavespeeds missized.");
1049 ds_size = cache.bndWaveSpeed.Size();
1050 ds_size = cache.elJac.Size();
1051 MFEM_VERIFY(ds_size > 0,
"Element Jacobians not set");
1052 ds_size = cache.elMetric.Size();
1053 MFEM_VERIFY(ds_size > 0,
"Element Metrics not set");
1054 ds_size = cache.D.Size();
1055 MFEM_VERIFY(ds_size > 0,
"Deriv operator not set");
1056 ds_size = cache.Dhat2.Size();
1057 MFEM_VERIFY(ds_size > 0,
"Dhat2 operator not set");
1058 ds_size = cache.face_normals.Size();
1059 MFEM_VERIFY(ds_size == cache.num_face_points*cache.num_interior_faces*cache.dim,
1060 "Inapropriately sized face normals");
1061 ds_size = cache.face_wt_minus.Size();
1062 ds_size = cache.face_wt_plus.Size();
1063 MFEM_VERIFY(ds_size > 0,
"Face weights not set.");