70 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace*
>(fes);
71 MFEM_VERIFY(pfes,
"Restriction setup requires ParFiniteElementSpace");
72 cache->restr_v = fes->GetElementRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC);
73 cache->restr_f = pfes->GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC,
74 mfem::FaceType::Interior,
75 mfem::L2FaceValues::DoubleValued);
76 cache->restr_b = pfes->GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC,
77 mfem::FaceType::Boundary,
78 mfem::L2FaceValues::SingleValued);
86 const int nelem = cache->num_elements;
87 const int p = cache->p;
88 const int Np = cache->Np;
89 const int dim = cache->dim;
91 const int Np_y = dim > 1 ? Np : 1;
92 const int Np_z = dim > 2 ? Np : 1;
93 const int neq = cache->num_equations;
94 mfem::Mesh *mesh = fes->GetMesh();
97 const int IntegrationOrder = 2 * Np_x - 3;
98 cache->ir = &cache->GLIntRules.Get(mfem::Geometry::SEGMENT, IntegrationOrder);
99 auto vol_topo = (dim == 1 ? mfem::Geometry::SEGMENT :
100 (dim == 2 ? mfem::Geometry::SQUARE : mfem::Geometry::CUBE));
101 auto face_topo = (dim == 1 ? mfem::Geometry::POINT :
102 (dim == 2 ? mfem::Geometry::SEGMENT : mfem::Geometry::SQUARE));
104 cache->ir_face = &cache->GLIntRules.Get(face_topo, IntegrationOrder);
105 cache->ir_vol = &cache->GLIntRules.Get(vol_topo, IntegrationOrder);
107 MFEM_ASSERT(cache->ir->GetNPoints() == Np_x,
"");
108 MFEM_ASSERT(cache->ir_vol->GetNPoints() == Np_x*Np_y*Np_z,
"");
111 cache->elJac.SetSize(Np_x*Np_y*Np_z*nelem);
112 cache->elMetric.SetSize(dim*dim*Np_x*Np_y*Np_z*nelem);
113 cache->elQuadratureWeights.SetSize(Np_x*Np_y*Np_z*nelem);
115 Np_x*Np_y*Np_z*nelem : 0);
116 for (
int i = 0; i < nelem; i++)
118 mfem::ElementTransformation *T = fes->GetElementTransformation(i);
119 assert(T->ElementNo == i);
124 mfem::DenseMatrix D_T, Dhat_T, Dhat2_T;
126 Dhat_T.SetSize(Np_x);
127 Dhat2_T.SetSize(Np_x);
129 mfem::Vector wBary(Np_x);
132 for (
int i = 1; i < Np_x; i++)
134 for (
int j = 0; j < i; j++)
136 wBary(j) *= (cache->ir->IntPoint(j).x - cache->ir->IntPoint(i).x);
137 wBary(i) *= (cache->ir->IntPoint(i).x - cache->ir->IntPoint(j).x);
143 for (
int iL = 0; iL < Np_x; iL++)
145 for (
int i = 0; i < Np_x; i++)
149 D_T(i, iL) = wBary(iL) / wBary(i) / (cache->ir->IntPoint(i).x - cache->ir->IntPoint(iL).x);
150 D_T(i, i) -= D_T(i, iL);
156 Dhat_T(0, 0) += 1.0 / cache->ir->IntPoint(0).weight;
157 Dhat_T(Np - 1, Np - 1) -= 1.0 / cache->ir->IntPoint(Np - 1).weight;
162 Dhat2_T(0, 0) += 1.0 / cache->ir->IntPoint(0).weight;
163 Dhat2_T(Np - 1, Np - 1) -= 1.0 / cache->ir->IntPoint(Np - 1).weight;
167 const mfem::real_t endpoint_lift =
168 1.0 / cache->ir->IntPoint(0).weight;
169 cache->stabilitySurfaceScale =
170 cache->stabilityAdvectionScale / endpoint_lift;
176 cache->D.SetSize(Np_x*Np_x);
177 cache->Dhat.SetSize(Np_x*Np_x);
178 cache->Dhat2.SetSize(Np_x*Np_x);
179 std::memcpy(cache->D.HostWrite(), D_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
180 std::memcpy(cache->Dhat.HostWrite(), Dhat_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
181 std::memcpy(cache->Dhat2.HostWrite(), Dhat2_T.Data(),
sizeof(mfem::real_t)*Np_x*Np_x);
183 cache->elJac.UseDevice();
184 cache->elMetric.UseDevice();
185 cache->elRadius.UseDevice();
186 cache->D.UseDevice();
187 cache->Dhat.UseDevice();
188 cache->Dhat2.UseDevice();
190 cache->elMetric.Read();
191 cache->elRadius.Read();
197 const int nfp = cache->ir_face->GetNPoints();
198 cache->num_face_points = nfp;
200 const int nfaces_restr = cache->restr_f->Height() / (nfp * neq * 2);
201 cache->num_interior_faces = nfaces_restr;
202 MFEM_VERIFY(nfaces_restr > 0,
"nfaces_restr is 0");
206 cache->face_normals.UseDevice();
207 cache->face_wt_minus.UseDevice();
208 cache->face_wt_plus.UseDevice();
209 cache->face_radius.UseDevice();
210 cache->face_normals.Read();
211 cache->face_wt_minus.Read();
212 cache->face_wt_plus.Read();
213 cache->face_radius.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();
263 MFEM_VERIFY(cache->ir_face,
"cache->ir_face must exist");
265 auto &bnd_faces = pmesh->GetFaceIndices(mfem::FaceType::Boundary);
266 const int nbnd_faces = bnd_faces.Size();
267 const int nfp = cache->ir_face->GetNPoints();
269 cache->inv_fp_map_bnd.SetSize(nbnd_faces * nfp);
271 for (
int fslot = 0; fslot < nbnd_faces; ++fslot)
273 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
275 const int fp_perm = cache->fqs_bnd->GetPermutedIndex(fslot, fp_restr);
276 cache->inv_fp_map_bnd[fslot * nfp + fp_perm] = fp_restr;
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();
361 mfem::Array<int> face_to_be;
371 cache->bnd_normals.SetSize(nbnd_faces * nfp * dim);
372 cache->bnd_wt.SetSize(nbnd_faces * nfp);
373 cache->bnd_xyz.SetSize(nbnd_faces * nfp * dim);
375 nbnd_faces * nfp : 0);
377 mfem::real_t *nor_d = cache->bnd_normals.HostWrite();
378 mfem::real_t *wt_d = cache->bnd_wt.HostWrite();
379 mfem::real_t *xyz_d = cache->bnd_xyz.HostWrite();
380 mfem::real_t *rad_d = cache->bnd_radius.Size() > 0 ?
381 cache->bnd_radius.HostWrite() :
nullptr;
383 const mfem::real_t w0 = cache->ir->IntPoint(0).weight;
385 mfem::Vector nor(dim);
386 mfem::Vector phys(dim);
388 auto store = [&](
int fslot,
int fp_restr,
389 const mfem::Vector &nor,
390 const mfem::Vector &phys,
391 mfem::real_t inv_wJ1)
393 const int base_scl = fslot * nfp + fp_restr;
394 const int base_vec = base_scl * dim;
396 for (
int d = 0; d < dim; ++d)
398 nor_d[base_vec + d] = nor(d);
399 xyz_d[base_vec + d] = phys(d);
402 wt_d[base_scl] = inv_wJ1;
405 const mfem::real_t radius =
407 rad_d[base_scl] = cache->axisymmetric ?
409 radius,
"boundary face " + std::to_string(fslot) +
410 ", point " + std::to_string(fp_restr)) : radius;
414 for (
int fslot = 0; fslot < nbnd_faces; ++fslot)
416 const int face_id = bnd_faces[fslot];
417 const int be_match = face_to_be[face_id];
420 MFEM_VERIFY(be_match >= 0,
"Could not find boundary element for boundary face");
421 auto *tr = mesh->GetBdrFaceTransformations(be_match);
422 MFEM_VERIFY(tr,
"expected boundary face transformation");
424 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
426 const int fp_geom = cache->inv_fp_map_bnd[fslot * nfp + fp_restr];
427 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
428 tr->SetAllIntPoints(&ip);
430 const mfem::real_t J1 = tr->GetElement1Transformation().Weight();
433 nor(0) = (tr->GetElement1IntPoint().x - 0.5) * 2.0;
437 mfem::CalcOrtho(tr->Jacobian(), nor);
439 tr->Transform(ip, phys);
440 store(fslot, fp_restr, nor, phys, 1.0 / (w0 * J1));
443 cache->bnd_xyz.UseDevice();
444 cache->bnd_radius.UseDevice();
445 cache->bnd_xyz.Read();
446 cache->bnd_radius.Read();
454 mfem::real_t *Jinv_h = cache->elJac.HostWrite();
455 mfem::real_t *Met_h = cache->elMetric.HostWrite();
456 mfem::real_t *qWgts_h = cache->elQuadratureWeights.HostWrite();
457 mfem::real_t *radius_h = cache->elRadius.Size() > 0 ?
458 cache->elRadius.HostWrite() :
nullptr;
460 int dim = cache->dim;
461 mfem::Vector metric1(dim);
462 mfem::Vector physical(dim);
463 const int e = Tr.ElementNo;
464 const int nq = cache->Np_x * cache->Np_y * cache->Np_z;
466 for (
int q = 0; q < nq; ++q)
468 const mfem::IntegrationPoint &ip = cache->ir_vol->IntPoint(q);
470 const mfem::real_t J = Tr.Weight();
471 Jinv_h[e*nq + q] = J;
472 qWgts_h[e*nq + q] = J * ip.weight;
475 Tr.Transform(ip, physical);
476 const mfem::real_t radius =
478 radius_h[e*nq + q] = cache->axisymmetric ?
480 radius,
"element " + std::to_string(e) +
481 ", point " + std::to_string(q)) : radius;
483 const mfem::DenseMatrix &adj = Tr.AdjugateJacobian();
484 for (
int dir = 0; dir < dim; ++dir)
486 adj.GetRow(dir, metric1);
488 for (
int d = 0; d < dim; ++d)
490 const int idxM = (((e*nq + q)*dim + dir)*dim + d);
491 Met_h[idxM] = metric1(d);
500 auto *mesh = fes->GetMesh();
501 auto *pmesh =
dynamic_cast<mfem::ParMesh*
>(mesh);
502 auto *pfes =
dynamic_cast<mfem::ParFiniteElementSpace*
>(fes);
503 cache->fqs_int.reset(
new mfem::FaceQuadratureSpace(*mesh, *cache->ir_face,
504 mfem::FaceType::Interior));
505 MFEM_VERIFY(pfes,
"need ParFiniteElementSpace");
507 const int dim = mesh->Dimension();
508 const int neq = pfes->GetVDim();
509 const int nfp = cache->ir_face->GetNPoints();
511 auto &int_faces = pmesh->GetFaceIndices(mfem::FaceType::Interior);
512 const int ninterior_faces = int_faces.Size();
514 cache->inv_fp_map.SetSize(ninterior_faces * nfp);
515 for (
int face_slot = 0; face_slot < ninterior_faces; ++face_slot)
517 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
519 int fp_perm = cache->fqs_int->GetPermutedIndex(face_slot, fp_restr);
520 cache->inv_fp_map[face_slot*nfp + fp_perm] = fp_restr;
524 cache->face_normals.SetSize(ninterior_faces * nfp * dim);
525 cache->face_wt_minus.SetSize(ninterior_faces * nfp);
526 cache->face_wt_plus.SetSize(ninterior_faces * nfp);
527 cache->face_radius.SetSize(
529 ninterior_faces * nfp : 0);
531 mfem::real_t *nor_d = cache->face_normals.HostWrite();
532 mfem::real_t *inv1_d = cache->face_wt_minus.HostWrite();
533 mfem::real_t *inv2_d = cache->face_wt_plus.HostWrite();
534 mfem::real_t *radius_d = cache->face_radius.Size() > 0 ?
535 cache->face_radius.HostWrite() :
nullptr;
536 const mfem::real_t w0 = cache->ir->IntPoint(0).weight;
538 auto store = [&](
int fslot,
int fp,
const mfem::Vector &nor,
539 const mfem::Vector &physical,
540 mfem::real_t inv_wJ1, mfem::real_t inv_wJ2)
542 const int nbase = (fslot * nfp + fp) * dim;
543 for (
int d = 0; d < dim; ++d) { nor_d[nbase + d] = nor(d); }
544 inv1_d[fslot * nfp + fp] = inv_wJ1;
545 inv2_d[fslot * nfp + fp] = inv_wJ2;
548 const mfem::real_t radius =
550 radius_d[fslot*nfp + fp] = cache->axisymmetric ?
552 radius,
"interior face " + std::to_string(fslot) +
553 ", point " + std::to_string(fp)) : radius;
557 mfem::Vector nor(dim);
558 mfem::Vector physical(dim);
562 for (
int fslot = 0; fslot < ninterior_faces; ++fslot)
564 const int face_id = int_faces[fslot];
573 auto *tr = mesh->GetInteriorFaceTransformations(face_id);
576 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
578 const int fp_geom = cache->MapFp(fslot, fp_restr);
579 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
580 tr->SetAllIntPoints(&ip);
582 const mfem::real_t J1 = tr->GetElement1Transformation().Weight();
583 const mfem::real_t J2 = tr->GetElement2Transformation().Weight();
585 if (dim == 1) { nor(0) = (tr->GetElement1IntPoint().x - 0.5)*2.0; }
586 else { mfem::CalcOrtho(tr->Jacobian(), nor); }
587 tr->Transform(ip, physical);
590 const mfem::real_t fac = 1.0;
591 store(fslot, fp_restr, nor, physical,
592 fac/(w0*J1), fac/(w0*J2));
597 auto *sh_tr = pmesh->GetSharedFaceTransformationsByLocalIndex(face_id,
true);
598 MFEM_VERIFY(sh_tr,
"expected shared face");
599 for (
int fp_restr = 0; fp_restr < nfp; ++fp_restr)
601 const int fp_geom = cache->MapFp(fslot, fp_restr);
602 const mfem::IntegrationPoint &ip = cache->ir_face->IntPoint(fp_geom);
603 sh_tr->SetAllIntPoints(&ip);
605 const mfem::real_t J1 = sh_tr->GetElement1Transformation().Weight();
606 const mfem::real_t J2 = sh_tr->GetElement2Transformation().Weight();
608 if (dim == 1) { nor(0) = (sh_tr->GetElement1IntPoint().x - 0.5)*2.0; }
609 else { mfem::CalcOrtho(sh_tr->Jacobian(), nor); }
610 sh_tr->Transform(ip, physical);
613 const mfem::real_t fac1 = 1.0;
614 const mfem::real_t fac2 = 0.0;
615 store(fslot, fp_restr, nor, physical,
616 fac1/(w0*J1), fac2/(w0*J2));
625 MFEM_VERIFY(fes !=
nullptr,
"A finite element space is required.");
626 const int dim = cache->dim;
627 const int ne = cache->num_elements;
628 const int Np_x = cache->Np_x;
629 const int Np_y = cache->Np_y;
630 const int Np_z = cache->Np_z;
631 const int nq = cache->ndof_scalar_el;
632 const int n_metric_xi = (Np_x + 1) * Np_y * Np_z;
633 const int n_metric_eta = Np_x * (Np_y + 1) * Np_z;
634 const int n_metric_zeta = Np_x * Np_y * (Np_z + 1);
636 cache->subcellWeights.SetSize(Np_x);
637 mfem::real_t *wgts = cache->subcellWeights.HostWrite();
638 for (
int i = 0;i < Np_x;i++){
639 wgts[i] = cache->ir->IntPoint(i).weight;
642 cache->subcellMetricXi.SetSize(n_metric_xi*dim*ne);
644 cache->subcellMetricEta.SetSize(n_metric_eta*dim*ne);
646 cache->subcellMetricZeta.SetSize(n_metric_zeta*dim*ne);
648 const mfem::real_t *metric = cache->elMetric.Read();
649 const mfem::real_t *D = cache->D.Read();
650 const mfem::real_t *weights = cache->subcellWeights.Read();
651 mfem::real_t *xi = cache->subcellMetricXi.Write();
653 const int xi_work = ne*Np_z*Np_y*(Np_x - 1)*dim;
654 mfem::forall(xi_work, [=] MFEM_HOST_DEVICE (
int tid) {
655 const int d = tid % dim;
656 int item = tid / dim;
657 const int i = item % (Np_x - 1) + 1;
659 const int j = item % Np_y;
661 const int k = item % Np_z;
662 const int el = item / Np_z;
663 const int line = k*Np_y*Np_x + j*Np_x;
664 mfem::real_t normal = metric[((el*nq + line)*dim)*dim + d];
665 for (
int l = 0; l < i; ++l)
667 mfem::real_t sum = 0.0;
668 for (
int m = 0; m < Np_x; ++m)
670 mfem::real_t contribution =
671 metric[((el*nq + line + m)*dim)*dim + d];
672 contribution *= D[l*Np_x + m];
678 xi[((el*n_metric_xi + line + i)*dim) + d] = normal;
683 mfem::real_t *eta = cache->subcellMetricEta.Write();
684 const int eta_work = ne*Np_z*Np_x*(Np_y - 1)*dim;
685 mfem::forall(eta_work, [=] MFEM_HOST_DEVICE (
int tid) {
686 const int d = tid % dim;
687 int item = tid / dim;
688 const int j = item % (Np_y - 1) + 1;
690 const int i = item % Np_x;
692 const int k = item % Np_z;
693 const int el = item / Np_z;
694 const int line = k*Np_y*Np_x + i;
695 mfem::real_t normal = metric[((el*nq + line)*dim + 1)*dim + d];
696 for (
int l = 0; l < j; ++l)
698 mfem::real_t sum = 0.0;
699 for (
int m = 0; m < Np_y; ++m)
701 mfem::real_t contribution =
702 metric[((el*nq + line + m*Np_x)*dim + 1)*dim + d];
703 contribution *= D[l*Np_x + m];
709 eta[((el*n_metric_eta + k*Np_y*Np_x + j*Np_x + i)*dim) + d] = normal;
715 mfem::real_t *zeta = cache->subcellMetricZeta.Write();
716 const int zeta_work = ne*Np_y*Np_x*(Np_z - 1)*dim;
717 mfem::forall(zeta_work, [=] MFEM_HOST_DEVICE (
int tid) {
718 const int d = tid % dim;
719 int item = tid / dim;
720 const int k = item % (Np_z - 1) + 1;
722 const int i = item % Np_x;
724 const int j = item % Np_y;
725 const int el = item / Np_y;
726 const int line = j*Np_x + i;
727 mfem::real_t normal = metric[((el*nq + line)*dim + 2)*dim + d];
728 for (
int l = 0; l < k; ++l)
730 mfem::real_t sum = 0.0;
731 for (
int m = 0; m < Np_z; ++m)
733 mfem::real_t contribution = metric[
734 ((el*nq + line + m*Np_y*Np_x)*dim + 2)*dim + d];
735 contribution *= D[l*Np_x + m];
741 zeta[((el*n_metric_zeta + k*Np_y*Np_x + line)*dim) + d] = normal;
751 device_cache.ndof_scalar_el = cache.ndof_scalar_el;
752 device_cache.num_attr = cache.num_attr;
753 device_cache.attr_marker_d = cache.vol_attr_marker.Read();
754 device_cache.elem_attr_d = cache.elem_attr.Read();
755 device_cache.num_face_points = cache.num_face_points;
756 device_cache.p = cache.p;
757 device_cache.dim = cache.dim;
758 device_cache.Np = cache.Np;
759 device_cache.Np_x = cache.Np_x;
760 device_cache.Np_y = cache.Np_y;
761 device_cache.Np_z = cache.Np_z;
762 device_cache.num_elements = cache.num_elements;
763 device_cache.num_equations = cache.num_equations;
764 device_cache.axisymmetric = cache.axisymmetric;
767 device_cache.elJac_d = cache.elJac.Read();
768 device_cache.elMetric_d = cache.elMetric.Read();
769 device_cache.D_d = cache.D.Read();
770 device_cache.Dhat_d = cache.Dhat.Read();
771 device_cache.Dhat2_d = cache.Dhat2.Read();
772 device_cache.elQWgts_d = cache.elQuadratureWeights.Read();
773 device_cache.elRadius_d = cache.elRadius.Read();
776 device_cache.nor_d = cache.face_normals.Read();
777 device_cache.fw_minus_d = cache.face_wt_minus.Read();
778 device_cache.fw_plus_d = cache.face_wt_plus.Read();
779 device_cache.face_radius_d = cache.face_radius.Read();
782 device_cache.bnd_nor_d = cache.bnd_normals.Read();
783 device_cache.bnd_wt_d = cache.bnd_wt.Read();
784 device_cache.bnd_radius_d = cache.bnd_radius.Read();
785 device_cache.bnd_marker_index_d = cache.bnd_marker_index.Read();
786 device_cache.bnd_marker_to_bc_descr_d = cache.bnd_marker_to_bc_descr.Read();
787 device_cache.bc_scalar_d = cache.bc_scalar_data.Read();
788 device_cache.bc_vector_d = cache.bc_vector_data.Read();
789 device_cache.bc_descr_d = cache.bc_descriptors.Read();
792 device_cache.gas = cache.gas.to_device(cache);
793 device_cache.iflux = cache.iflux;
795#ifdef SUBCELL_FV_BLENDING
796 device_cache.subcell_metric_xi_d = cache.subcellMetricXi.Read();
797 device_cache.subcell_metric_eta_d = cache.subcellMetricEta.Read();
798 device_cache.subcell_metric_zeta_d = cache.subcellMetricZeta.Read();
799 device_cache.subcell_weights_d = cache.subcellWeights.Read();
807 const int points_per_face = cache.num_face_points;
808 const int boundary_faces = cache.bnd_marker_index.Size();
809 const int *marker_index = cache.bnd_marker_index.HostRead();
811 cache.bc_descriptors.HostRead();
812 const mfem::real_t *radius = cache.bnd_radius.HostRead();
813 for (
int face = 0; face < boundary_faces; ++face)
815 const int descriptor_index = marker_index[face];
816 if (descriptor_index < 0 ||
817 descriptor_index >= cache.bc_descriptors.Size() ||
818 descriptors[descriptor_index].
type !=
823 if (cache.bnd_radius.Size() != boundary_faces*points_per_face)
827 for (
int point = 0; point < points_per_face; ++point)
829 const mfem::real_t point_radius =
830 radius[face*points_per_face + point];
857 int ndofs = c.ndof_scalar_el;
858 int ne = c.num_elements;
859 const mfem::Array2D<int> ubdegs(modalBasis.
GetPolyDegs());
861 c.modal.SetSize(ndofs * ndofs);
862 c.keep_M1.SetSize(ndofs);
863 c.keep_M2.SetSize(ndofs);
867 c.keep_M1.UseDevice();
868 c.keep_M2.UseDevice();
871 auto *modal_h = c.modal.HostWrite();
872 auto *m1_h = c.keep_M1.HostWrite();
873 auto *m2_h = c.keep_M2.HostWrite();
875 mfem::Vector nodal(ndofs), modes(ndofs);
877 for (
int q = 0; q < ndofs; ++q)
884 for (
int m = 0; m < ndofs; ++m)
889 modal_h[q * ndofs + m] = modes(m);
893 mfem::Array<int> row;
894 for (
int m = 0; m < ndofs; ++m)
896 ubdegs.GetRow(m, row);
901 for (
int d = 0; d < dim; ++d)
903 if (row[d] > order - 2)
908 if (row[d] > order - 1)
914 m1_h[m] = keep1 ? 1.0 : 0.0;
915 m2_h[m] = keep2 ? 1.0 : 0.0;
918 c.modal_d = c.modal.Read();
919 c.keep_M1_d = c.keep_M1.Read();
920 c.keep_M2_d = c.keep_M2.Read();
921 c.eta_d = c.eta.ReadWrite();
928 std::cout <<
"Cache Contents:" << std::endl
929 <<
"p = " << cache.p << std::endl
930 <<
"dim = " << cache.dim << std::endl
931 <<
"num_elements = " << cache.num_elements << std::endl
932 <<
"Np,Np_x,Np_y,Np_z = " << cache.Np <<
"," << cache.Np_x
933 <<
"," << cache.Np_y <<
"," << cache.Np_z << std::endl
934 <<
"num_face_points = " << cache.num_face_points << std::endl
935 <<
"num_attr = " << cache.num_attr << std::endl
936 <<
"ndof_scalar_el = " << cache.ndof_scalar_el << std::endl
937 <<
"num_interior_faces = " << cache.num_interior_faces << std::endl;
938 MFEM_VERIFY(cache.ir,
"IR is not set");
939 MFEM_VERIFY(cache.ir_face,
"Face IR not set");
940 MFEM_VERIFY(cache.ir_vol,
"Volume IR not set");
941 MFEM_VERIFY(cache.restr_v,
"Volume Restriction not set");
942 MFEM_VERIFY(cache.restr_f,
"Facial Restriction not set");
943 MFEM_VERIFY(cache.ndof_scalar_el == cache.Np_x*cache.Np_y*cache.Np_z,
944 "Element dof count not equal to num quadrature points.");
945 int ds_size = cache.elem_attr.Size();
946 MFEM_VERIFY(ds_size > 0,
"Elem attr not set");
948 ds_size = cache.elJac.Size();
949 MFEM_VERIFY(ds_size > 0,
"Element Jacobians not set");
950 ds_size = cache.elMetric.Size();
951 MFEM_VERIFY(ds_size > 0,
"Element Metrics not set");
952 ds_size = cache.D.Size();
953 MFEM_VERIFY(ds_size > 0,
"Deriv operator not set");
954 ds_size = cache.Dhat2.Size();
955 MFEM_VERIFY(ds_size > 0,
"Dhat2 operator not set");
956 ds_size = cache.face_normals.Size();
957 MFEM_VERIFY(ds_size == cache.num_face_points*cache.num_interior_faces*cache.dim,
958 "Inapropriately sized face normals");
959 ds_size = cache.face_wt_minus.Size();
960 ds_size = cache.face_wt_plus.Size();
961 MFEM_VERIFY(ds_size > 0,
"Face weights not set.");