63#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
64#pragma GCC diagnostic push
65#pragma GCC diagnostic ignored "-Wunused-function"
68#define CODE_INTERNAL 0
70#define CODE_NOT_FOUND 2
76#ifndef GSLIB_RELEASE_VERSION
77#define GSLIB_RELEASE_VERSION 10007
79static_assert(std::is_same_v<uint,unsigned int>,
80 "GSLIB's integer-type, 'uint', defined in gslib.h, must be the same as 'unsigned int'!");
86 struct dbl_range bnd[3];
94 struct dbl_range bnd[2];
99 struct findpts_dummy_ms_data
105 struct findpts_data_3
108 struct findpts_local_data_3 local;
109 struct hash_data_3 hash;
111 struct findpts_dummy_ms_data fdms;
115 struct findpts_data_2
118 struct findpts_local_data_2 local;
119 struct hash_data_2 hash;
121 struct findpts_dummy_ms_data fdms;
128#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
129#pragma GCC diagnostic pop
137static void FindPointsDeviceSetCode(
int pts_cnt,
141 unsigned int *d_gsl_code,
144 const unsigned int *d_gsl_elem,
146 unsigned int *d_gsl_mfem_elem)
150 if (d_gsl_code[
index] == CODE_NOT_FOUND)
156 bool internal =
true;
157 for (
int d = 0; d < ddim; d++)
160 const real_t val = 0.5 * (r_val + 1.0);
161 d_gsl_mfem_ref[
index * ddim + d] = val;
162 if (val < rbtol || val > 1.0 - rbtol)
168 const int setcode = internal ? CODE_INTERNAL : CODE_BORDER;
169 d_gsl_code[
index] = (setcode == CODE_BORDER &&
170 d_gsl_dist[
index] > bdr_t)
171 ? CODE_NOT_FOUND : setcode;
177static void InterpolateDeviceScatter(
int nlocal,
178 const int *d_index_temp,
179 const real_t *d_interp_vals,
186 if (nlocal == 0 || ncomp == 0) {
return; }
190 const int j = k % nlocal;
191 const int i = k / nlocal;
192 const int pt_index = d_index_temp[j];
194 pt_index + i*pts_cnt :
196 d_field_out[idx] = d_interp_vals[j + interp_offset*i];
203 fdataD(NULL), cr(NULL), gsl_comm(NULL),
204 dim(-1), spacedim(-1), points_cnt(-1), setupflag(false),
205 default_interp_value(0),
206 avgtype(
AvgType::ARITHMETIC), bdr_tol(1e-8)
225 MPI_Comm comm = MPI_COMM_WORLD;
233 const double bbox_rel_size_inc,
234 const double newt_tol,
const int npt_max)
237 Setup(mesh_in, bbox_rel_size_inc, newt_tol, npt_max);
265 fdataD(NULL), cr(NULL), gsl_comm(NULL),
266 dim(-1), spacedim(-1), points_cnt(-1), setupflag(false),
267 default_interp_value(0),
268 avgtype(
AvgType::ARITHMETIC), bdr_tol(1e-8)
289 const double bbox_rel_size_inc,
290 const double newt_tol,
const int npt_max)
293 Setup(mesh_in, bbox_rel_size_inc, newt_tol, npt_max);
301 cr =
new gslib::crystal;
308 if (
cr == NULL) {
return; }
322 const double newt_tol,
325 MFEM_VERIFY(m.
GetNodes() !=
nullptr,
"Mesh nodes are required.");
326 const int meshOrder = m.
GetNodes()->FESpace()->GetMaxElementOrder();
331 SetupSurf(m, bbox_rel_size_inc, newt_tol);
341 const unsigned dof1D = meshOrder + 1;
353 unsigned nr[2] = { dof1D, dof1D };
354 unsigned mr[2] = { 2*dof1D, 2*dof1D };
355 double *
const elx[2] =
366 unsigned nr[3] = { dof1D, dof1D, dof1D };
367 unsigned mr[3] = { 2*dof1D, 2*dof1D, 2*dof1D };
368 double *
const elx[3] =
388 double l[2] = {
b[0].max-
b[0].min,
b[1].max-
b[1].min };
389 double len = sqrt(l[0]*l[0] + l[1]*l[1])*0.5*tol;
390 for (
int i=0; i<2; i++)
392 b[i].min =
b[i].min - len;
393 b[i].max =
b[i].max + len;
400 double l[3] = {
b[0].max-
b[0].min,
b[1].max-
b[1].min,
b[2].max-
b[2].min };
401 double len = sqrt(l[0]*l[0] + l[1]*l[1] + l[2]*l[2])*0.5*tol;
402 for (
int i=0; i<3; i++)
404 b[i].min =
b[i].min - len;
405 b[i].max =
b[i].max + len;
410static void bbox_2_tfm(
double *tfm,
const double x0[2],
const double Ji[4],
411 const double *x,
const double *y,
unsigned n)
416 const double dx = x[i]-x0[0], dy = y[i]-x0[1];
417 tfm[ i] = Ji[0]*dx + Ji[1]*dy;
418 tfm[n+i] = Ji[2]*dx + Ji[3]*dy;
422static void bbox_3_tfm(
double *tfm,
const double x0[3],
const double Ji[9],
423 const double *x,
const double *y,
const double *z,
429 const double dx = x[i]-x0[0], dy = y[i]-x0[1], dz = z[i]-x0[2];
430 tfm[ i] = Ji[0]*dx + Ji[1]*dy + Ji[2]*dz;
431 tfm[ n+i] = Ji[3]*dx + Ji[4]*dy + Ji[5]*dz;
432 tfm[2*n+i] = Ji[6]*dx + Ji[7]*dy + Ji[8]*dz;
436static struct gslib::dbl_range dbl_range_expand(struct
gslib::dbl_range
b,
439 double a = (
b.min+
b.max)/2, l = (
b.max-
b.min)*(1+tol)/2;
440 struct gslib::dbl_range m;
441 m.min =
a-l, m.max =
a+l;
445static MFEM_HOST_DEVICE
inline void MapSplitTriangleQuadToTriangle(
446 const int tri_id,
const double u,
const double v,
double &tx,
double &ty)
448 const double N0 = (1.0-
u)*(1.0-v);
449 const double N1 =
u*(1.0-v);
450 const double N2 =
u*v;
451 const double N3 = (1.0-
u)*v;
454 const double vx[3][4] =
456 {0.0, 0.5, 1.0/3.0, 0.0 },
457 {0.5, 1.0, 0.5, 1.0/3.0},
458 {0.0, 1.0/3.0, 0.5, 0.0 }
460 const double vy[3][4] =
462 {0.0, 0.0, 1.0/3.0, 0.5 },
463 {0.0, 0.0, 0.5, 1.0/3.0},
464 {0.5, 1.0/3.0, 0.5, 1.0 }
467 tx = N0*vx[tri_id][0] + N1*vx[tri_id][1]
468 + N2*vx[tri_id][2] + N3*vx[tri_id][3];
469 ty = N0*vy[tri_id][0] + N1*vy[tri_id][1]
470 + N2*vy[tri_id][2] + N3*vy[tri_id][3];
473static void VerifyAABBPadLayout(
const Vector *aabb_sz_inc,
const uint nel,
476 if (!aabb_sz_inc) {
return; }
478 const int sz = aabb_sz_inc->Size();
479 MFEM_VERIFY(sz == 1 || sz == (
int)nel || sz == sd || sz == (
int)nel*sd,
480 "Invalid aabb_sz_inc length for SetupSurfWithAABBExpansion: "
481 "expected 1, NE, SpaceDim, or NE*SpaceDim.");
484static double GetAABBPad(
const Vector *aabb_sz_inc,
const int aabb_sz_inc_size,
485 const uint nel,
const int sd,
const uint e,
488 if (!aabb_sz_inc) {
return 0.0; }
490 MFEM_ASSERT(aabb_sz_inc_size == 1 || aabb_sz_inc_size == (
int)nel ||
491 aabb_sz_inc_size == sd || aabb_sz_inc_size == (
int)nel*sd,
492 "Invalid aabb_sz_inc layout.");
495 if (aabb_sz_inc_size == 1) { s = (*aabb_sz_inc)(0); }
496 else if (aabb_sz_inc_size == (
int)nel) { s = (*aabb_sz_inc)((int)e); }
497 else if (aabb_sz_inc_size == sd) { s = (*aabb_sz_inc)(d); }
498 else { s = (*aabb_sz_inc)((int)e*sd + d); }
500 MFEM_VERIFY(s >= 0.0,
501 "aabb_sz_inc absolute AABB expansion must be non-negative.");
506 const double *
const elx[3],
511 const bool store_obb)
514 const double *x = elx[0], *y = elx[1], *z = elx[2];
515 const int n_el_ents = store_obb ? 18 : 6;
518 const unsigned n2 = n*n;
519 const unsigned lbsize = gslib::lob_bnd_size(n, m);
524 unsigned wsize = std::max(2*m*(n+m+1), store_obb?gslib::gll_lag_size(n):0
u);
526 Vector datavec(lbsize +
wsize + (store_obb ? 2*n : 0));
529 double *
const I0 = store_obb ? data :
nullptr;
530 double *
const lob_bnd_data = store_obb ? (data + 2*n) : data;
531 double *
const work = lob_bnd_data + lbsize;
533 gslib::lob_bnd_setup(lob_bnd_data, n, m);
537 for (
int ie = 0; ie < (int)nel; ie++, x += n2, y += n2, z += n2)
539 struct gslib::dbl_range ab[3];
540 ab[0] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, x, work);
541 ab[1] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, y, work);
542 ab[2] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, z, work);
546 h_bb[n_el_ents*ie + 0] = ab[0].min;
547 h_bb[n_el_ents*ie + 1] = ab[1].min;
548 h_bb[n_el_ents*ie + 2] = ab[2].min;
549 h_bb[n_el_ents*ie + 3] = ab[0].max;
550 h_bb[n_el_ents*ie + 4] = ab[1].max;
551 h_bb[n_el_ents*ie + 5] = ab[2].max;
556 gslib::lagrange_fun *
const lag = gslib::gll_lag_setup(work, n);
557 lag(I0, work, n, 1, 0);
559 for (
int ie = 0; (unsigned)ie < nel; ie++,x+=n2,y+=n2,z+=n2)
561 struct gslib::dbl_range ab[3];
562 struct gslib::dbl_range tb[3];
563 double x0[3], tv[9], A[9];
573 x0[0] = gslib::tensor_ig2(tv+3, I0,n, I0,n, x, work);
574 x0[1] = gslib::tensor_ig2(tv+5, I0,n, I0,n, y, work);
575 x0[2] = gslib::tensor_ig2(tv+7, I0,n, I0,n, z, work);
578 tv[0] = tv[3], tv[1] = tv[5], tv[2] = tv[7];
580 tv[3] = tv[4], tv[4] = tv[6], tv[5] = tv[8];
583 tv[6] = tv[1]*tv[5] - tv[2]*tv[4];
584 tv[7] = tv[2]*tv[3] - tv[0]*tv[5];
585 tv[8] = tv[0]*tv[4] - tv[1]*tv[3];
587 const double nmag = sqrt(tv[6]*tv[6] + tv[7]*tv[7] + tv[8]*tv[8]);
595 double nmag2 = tv[6]*tv[6] + tv[7]*tv[7];
610 A[0] = 1.0 + st*0.0 + (1.0-ct)*(-ky*ky-kz*kz);
611 A[1] = 0.0 + st*(0.0) + (1.0-ct)*(kx*ky);
612 A[2] = 0.0 + st*(ky) + (1.0-ct)*(kx*kz);
614 A[3] = 0.0 + st*(0.0) + (1.0-ct)*(kx*ky);
615 A[4] = 1.0 + st*(0.0) + (1.0-ct)*(-kx*kx-kz*kz);
616 A[5] = 0.0 + st*(-kx) + (1.0-ct)*(ky*kz);
618 A[6] = 0.0 + st*(-ky) + (1.0-ct)*(kx*kz);
619 A[7] = 0.0 + st*(kx) + (1.0-ct)*(ky*kz);
620 A[8] = 1.0 + st*(0.0) + (1.0-ct)*(-kx*kx-ky*ky);
623 ab[0] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, x, work);
624 ab[1] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, y, work);
625 ab[2] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m, z, work);
629 h_bb[n_el_ents*ie + 3] = ab[0].min;
630 h_bb[n_el_ents*ie + 4] = ab[1].min;
631 h_bb[n_el_ents*ie + 5] = ab[2].min;
632 h_bb[n_el_ents*ie + 6] = ab[0].max;
633 h_bb[n_el_ents*ie + 7] = ab[1].max;
634 h_bb[n_el_ents*ie + 8] = ab[2].max;
638 bbox_3_tfm(xtfm.
GetData(), x0,A, x,y,z,n2);
640 tb[2] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m,
643 tb[2].min -= aabb_diag_len;
644 tb[2].max += aabb_diag_len;
651 J[0] = A[0]*tv[0] + A[1]*tv[1] + A[2]*tv[2];
652 J[1] = A[0]*tv[3] + A[1]*tv[4] + A[2]*tv[5];
653 J[2] = A[3]*tv[0] + A[4]*tv[1] + A[5]*tv[2];
654 J[3] = A[3]*tv[3] + A[4]*tv[4] + A[5]*tv[5];
663 for (
unsigned i=0; i<n2; ++i)
665 const double xt = xtfm[i], yt = xtfm[n2+i];
666 xtfm[ i] = Ji[0]*xt + Ji[1]*yt;
667 xtfm[n2+i] = Ji[2]*xt + Ji[3]*yt;
670 tb[0] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m,
672 tb[1] = gslib::lob_bnd_2(lob_bnd_data,n,m, lob_bnd_data,n,m,
675 tb[0] = dbl_range_expand(tb[0],tol);
676 tb[1] = dbl_range_expand(tb[1],tol);
696 const double av0 = (tb[0].min+tb[0].max)/2,
697 av1 = (tb[1].min+tb[1].max)/2,
698 av2 = (tb[2].min+tb[2].max)/2;
701 const double Jav0 = J[0]*av0 + J[1]*av1,
702 Jav1 = J[2]*av0 + J[3]*av1;
708 h_bb[n_el_ents*ie + 0] = x0[0] + A[0]*Jav0 + A[3]*Jav1 + A[6]*av2;
709 h_bb[n_el_ents*ie + 1] = x0[1] + A[1]*Jav0 + A[4]*Jav1 + A[7]*av2;
710 h_bb[n_el_ents*ie + 2] = x0[2] + A[2]*Jav0 + A[5]*Jav1 + A[8]*av2;
717 const double di0 = 2/(tb[0].max-tb[0].min),
718 di1 = 2/(tb[1].max-tb[1].min),
719 di2 = 2/(tb[2].max-tb[2].min);
724 h_bb[n_el_ents*ie + 9 ]=di0*(Ji[0]*A[0] + Ji[1]*A[3]);
725 h_bb[n_el_ents*ie + 10]=di0*(Ji[0]*A[1] + Ji[1]*A[4]);
726 h_bb[n_el_ents*ie + 11]=di0*(Ji[0]*A[2] + Ji[1]*A[5]);
727 h_bb[n_el_ents*ie + 12]=di1*(Ji[2]*A[0] + Ji[3]*A[3]);
728 h_bb[n_el_ents*ie + 13]=di1*(Ji[2]*A[1] + Ji[3]*A[4]);
729 h_bb[n_el_ents*ie + 14]=di1*(Ji[2]*A[2] + Ji[3]*A[5]);
730 h_bb[n_el_ents*ie + 15]=di2*A[6];
731 h_bb[n_el_ents*ie + 16]=di2*A[7];
732 h_bb[n_el_ents*ie + 17]=di2*A[8];
738 const double *
const elx[2],
743 const bool store_obb)
746 const double *x = elx[0];
747 const double *y = elx[1];
749 const int n_el_ents = store_obb ? 10 : 4;
751 const unsigned lbsize0 = gslib::lob_bnd_size(nr,mr);
752 unsigned wsize = std::max(2*nr+2*mr,store_obb ? gslib::gll_lag_size(nr) : 0);
753 Vector datavec(lbsize0 +
wsize + (store_obb ? 2*nr : 0));
754 double *data = datavec.GetData();
756 double *
const I0r = store_obb ? data :
nullptr;
757 double *
const lob_bnd_data_r = store_obb ? data + 2*nr : data;
758 double *
const work = lob_bnd_data_r + lbsize0;
760 gslib::lob_bnd_setup(lob_bnd_data_r, nr, mr);
764 for (
int ie = 0; ie < (int)nel; ie++, x+=nr, y+=nr)
766 struct gslib::dbl_range ab[2];
767 ab[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, x, work);
768 ab[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, y, work);
772 h_bb[n_el_ents*ie + 0] = ab[0].min;
773 h_bb[n_el_ents*ie + 1] = ab[1].min;
774 h_bb[n_el_ents*ie + 2] = ab[0].max;
775 h_bb[n_el_ents*ie + 3] = ab[1].max;
780 gslib::lagrange_fun *
const lag = gslib::gll_lag_setup(work, nr);
781 lag(I0r, work, nr,1, 0);
783 for (
int ie = 0; (unsigned)ie < nel; ie++,x+=nr,y+=nr)
786 struct gslib::dbl_range ab[2], tb[2];
790 x0[0] = gslib::tensor_ig1(A,I0r,nr,x);
791 x0[1] = gslib::tensor_ig1(A+1,I0r,nr,y);
794 A[2] = sqrt(A[0]*A[0] + A[1]*A[1]);
801 ab[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, x, work);
802 ab[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, y, work);
804 bbox_2_tfm(work, x0, A, x, y, nr);
805 tb[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, work, work+2*nr);
806 tb[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, work+nr, work+2*nr);
812 const double av0 = (tb[0].min+tb[0].max)/2,
813 av1 = (tb[1].min+tb[1].max)/2;
816 const double dx0 = A[0]*av0 - A[1]*av1,
817 dx1 = -A[2]*av0 + A[3]*av1;
818 h_bb[n_el_ents*ie + 0] = x0[0] + dx0;
819 h_bb[n_el_ents*ie + 1] = x0[1] + dx1;
820 h_bb[n_el_ents*ie + 2] = ab[0].min;
821 h_bb[n_el_ents*ie + 3] = ab[1].min;
822 h_bb[n_el_ents*ie + 4] = ab[0].max;
823 h_bb[n_el_ents*ie + 5] = ab[1].max;
828 tb[0].min -= aabb_diag_len;
829 tb[0].max += aabb_diag_len;
830 tb[1].min -= aabb_diag_len;
831 tb[1].max += aabb_diag_len;
832 const double di0 = 2/(tb[0].max-tb[0].min),
833 di1 = 2/(tb[1].max-tb[1].min);
834 h_bb[n_el_ents*ie + 6]=di0*A[0];
835 h_bb[n_el_ents*ie + 7]=di0*A[1];
836 h_bb[n_el_ents*ie + 8]=di1*A[2];
837 h_bb[n_el_ents*ie + 9]=di1*A[3];
842 const double *
const elx[3],
847 const bool store_obb)
850 const double *x = elx[0];
851 const double *y = elx[1];
852 const double *z = elx[2];
853 const int n_el_ents = store_obb ? 18 : 6;
855 const unsigned lbsize0 = gslib::lob_bnd_size(nr,mr);
858 const unsigned wsize = store_obb ?
859 std::max(3*nr+2*mr, gslib::gll_lag_size(nr)) :
862 Vector datavec(lbsize0 +
wsize + (store_obb ? 2*nr : 0));
863 double *data = datavec.
GetData();
865 double *
const I0r = store_obb ? data :
nullptr;
866 double *
const lob_bnd_data_r = store_obb ? data + 2*nr : data;
867 double *
const work = lob_bnd_data_r + lbsize0;
869 gslib::lob_bnd_setup(lob_bnd_data_r, nr, mr);
873 for (
int ie = 0; ie < (int)nel; ie++, x += nr, y += nr, z += nr)
875 struct gslib::dbl_range ab[3];
876 ab[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, x, work);
877 ab[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, y, work);
878 ab[2] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, z, work);
882 h_bb[n_el_ents*ie + 0] = ab[0].min;
883 h_bb[n_el_ents*ie + 1] = ab[1].min;
884 h_bb[n_el_ents*ie + 2] = ab[2].min;
885 h_bb[n_el_ents*ie + 3] = ab[0].max;
886 h_bb[n_el_ents*ie + 4] = ab[1].max;
887 h_bb[n_el_ents*ie + 5] = ab[2].max;
892 gslib::lagrange_fun *
const lag = gslib::gll_lag_setup(work, nr);
893 lag(I0r, work, nr, 1, 0);
895 for (
int ie = 0; (unsigned)ie < nel; ie++,x+=nr,y+=nr,z+=nr)
897 double x0[3], A[9], Ai[9];
898 struct gslib::dbl_range ab[3], tb[3];
902 x0[0] = gslib::tensor_ig1(A,I0r,nr,x);
903 x0[1] = gslib::tensor_ig1(A+1,I0r,nr,y);
904 x0[2] = gslib::tensor_ig1(A+2,I0r,nr,z);
907 double nmag = A[0]*A[0] + A[1]*A[1] + A[2]*A[2];
916 double nmag2 = A[0]*A[0] + A[1]*A[1];
934 A[0] = 1.0 + st*0.0 + (1.0-ct)*(-ky*ky-kz*kz);
935 A[1] = 0.0 + st*(0.0) + (1.0-ct)*(kx*ky);
936 A[2] = 0.0 + st*(ky) + (1.0-ct)*(kx*kz);
938 A[3] = 0.0 + st*(0.0) + (1.0-ct)*(kx*ky);
939 A[4] = 1.0 + st*(0.0) + (1.0-ct)*(-kx*kx-kz*kz);
940 A[5] = 0.0 + st*(-kx) + (1.0-ct)*(ky*kz);
942 A[6] = 0.0 + st*(-ky) + (1.0-ct)*(kx*kz);
943 A[7] = 0.0 + st*(kx) + (1.0-ct)*(ky*kz);
944 A[8] = 1.0 + st*(0.0) + (1.0-ct)*(-kx*kx-ky*ky);
951 ab[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, x, work);
952 ab[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, y, work);
953 ab[2] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, z, work);
955 bbox_3_tfm(work, x0, A, x, y, z, nr);
956 tb[0] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, work, work+3*nr);
957 tb[1] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, work+nr, work+3*nr);
958 tb[2] = gslib::lob_bnd_1(lob_bnd_data_r, nr, mr, work+2*nr, work+3*nr);
964 const double av0 = (tb[0].min+tb[0].max)/2,
965 av1 = (tb[1].min+tb[1].max)/2,
966 av2 = (tb[2].min+tb[2].max)/2;
969 h_bb[n_el_ents*ie + 0] = x0[0] + Ai[0]*av0 + Ai[1]*av1 + Ai[2]*av2;
970 h_bb[n_el_ents*ie + 1] = x0[1] + Ai[3]*av0 + Ai[4]*av1 + Ai[5]*av2;
971 h_bb[n_el_ents*ie + 2] = x0[2] + Ai[6]*av0 + Ai[7]*av1 + Ai[8]*av2;
972 h_bb[n_el_ents*ie + 3] = ab[0].min;
973 h_bb[n_el_ents*ie + 4] = ab[1].min;
974 h_bb[n_el_ents*ie + 5] = ab[2].min;
975 h_bb[n_el_ents*ie + 6] = ab[0].max;
976 h_bb[n_el_ents*ie + 7] = ab[1].max;
977 h_bb[n_el_ents*ie + 8] = ab[2].max;
982 tb[0].min -= aabb_diag_len;
983 tb[0].max += aabb_diag_len;
984 tb[1].min -= aabb_diag_len;
985 tb[1].max += aabb_diag_len;
986 tb[2].min -= aabb_diag_len;
987 tb[2].max += aabb_diag_len;
988 const double di0 = 2/((1+tol)*(tb[0].max-tb[0].min)),
989 di1 = 2/((1+tol)*(tb[1].max-tb[1].min)),
990 di2 = 2/((1+tol)*(tb[2].max-tb[2].min));
991 h_bb[n_el_ents*ie + 9 ]=di0*A[0];
992 h_bb[n_el_ents*ie + 10]=di0*A[1];
993 h_bb[n_el_ents*ie + 11]=di0*A[2];
994 h_bb[n_el_ents*ie + 12]=di1*A[3];
995 h_bb[n_el_ents*ie + 13]=di1*A[4];
996 h_bb[n_el_ents*ie + 14]=di1*A[5];
997 h_bb[n_el_ents*ie + 15]=di2*A[6];
998 h_bb[n_el_ents*ie + 16]=di2*A[7];
999 h_bb[n_el_ents*ie + 17]=di2*A[8];
1004 const double *
const elx[3],
1008 const double bbox_rel_size_inc,
1009 const uint local_hash_size,
1010 const uint global_hash_size,
1012 const Vector *aabb_sz_inc)
1017 const int n_box_ents = store_obb ? (3*sd + sd*sd) : (2*sd);
1029 MFEM_ABORT(
"FindPointsGSLIB::FindPointsSurfSetup3: rD must be 1 or 2");
1033 VerifyAABBPadLayout(aabb_sz_inc, nel, sd);
1034 const int aabb_sz_inc_size = aabb_sz_inc ? aabb_sz_inc->
Size() : 0;
1036 Vector elmin(3*nel), elmax(3*nel);
1037 for (uint i = 0; i < nel; i++)
1039 const int min_off = (store_obb ? sd : 0) + n_box_ents*i;
1040 const int max_off = (store_obb ? 2*sd : sd) + n_box_ents*i;
1041 for (
int d = 0; d < 3; d++)
1043 const double pad = GetAABBPad(aabb_sz_inc, aabb_sz_inc_size,
1047 h_bb[min_off + d] -= pad;
1048 h_bb[max_off + d] += pad;
1051 elmin(i) = h_bb[min_off + 0];
1052 elmin(i + nel) = h_bb[min_off + 1];
1053 elmin(i + 2*nel) = h_bb[min_off + 2];
1054 elmax(i) = h_bb[max_off + 0];
1055 elmax(i + nel) = h_bb[max_off + 1];
1056 elmax(i + 2*nel) = h_bb[max_off + 2];
1084 nel, 3, global_hash_size,
true);
1094 const double *
const elx[2],
1098 const double bbox_rel_size_inc,
1099 const uint local_hash_size,
1100 const uint global_hash_size,
1101 const Vector *aabb_sz_inc)
1106 const int n_box_ents = store_obb ? (3*sd + sd*sd) : (2*sd);
1111 VerifyAABBPadLayout(aabb_sz_inc, nel, sd);
1112 const int aabb_sz_inc_size = aabb_sz_inc ? aabb_sz_inc->
Size() : 0;
1114 Vector elmin(2*nel), elmax(2*nel);
1115 for (uint i = 0; i < nel; i++)
1117 const int min_off = (store_obb ? sd : 0) + n_box_ents*i;
1118 const int max_off = (store_obb ? 2*sd : sd) + n_box_ents*i;
1119 for (
int d = 0; d < 2 && aabb_sz_inc; d++)
1121 const double pad = GetAABBPad(aabb_sz_inc, aabb_sz_inc_size,
1125 h_bb[min_off+d] -= pad;
1126 h_bb[max_off+d] += pad;
1129 elmin(i) = h_bb[min_off + 0];
1130 elmin(i + nel) = h_bb[min_off + 1];
1131 elmax(i) = h_bb[max_off + 0];
1132 elmax(i + nel) = h_bb[max_off + 1];
1159 nel, 2, global_hash_size,
true);
1171static void lagrange_eval_second_derivative(
double *p0,
double x,
int i,
1173 const double *lagrangeCoeff,
1176 double u0 = 1, u1 = 0, u2 = 0;
1177 for (
int j=0; j<pN; ++j)
1181 double d_j = 2 * (x-z[j]);
1187 double *p1 = p0 + pN, *p2 = p0 + 2 * pN;
1188 p0[i] = lagrangeCoeff[i] * u0;
1189 p1[i] = 2.0 * lagrangeCoeff[i] * u1;
1190 p2[i] = 8.0 * lagrangeCoeff[i] * u2;
1194 const double bbox_rel_size_inc,
1195 const double newt_tol)
1201 const Vector &aabb_sz_inc,
1202 const double newt_tol)
1208 const double bbox_rel_size_inc,
1209 const Vector *aabb_sz_inc,
1210 const double newt_tol)
1213 MFEM_VERIFY(m.
GetNodes() !=
nullptr,
"Mesh nodes are required.");
1224 MFEM_VERIFY(
dim < 3,
"Configuration not supported yet.");
1226 "Surface setup is only for surface meshes.");
1228 bool supported_surf_elem =
true;
1229 for (
int e = 0; e <
mesh->
GetNE() && supported_surf_elem; e++)
1236 MFEM_VERIFY(supported_surf_elem,
1237 "FindPointsGSLIB surface mesh support: only SEGMENT, "
1238 "QUADRILATERAL, and TRIANGLE elements are supported.");
1240 "FindPointsGSLIB surface setup only supports surface meshes.");
1242 const int meshOrder = m.
GetNodes()->FESpace()->GetMaxElementOrder();
1243 unsigned dof1D = meshOrder + 1;
1253 unsigned nr = dof1D;
1254 unsigned mr = 2*dof1D;
1257 double *
const elx[2] =
1274 double *
const elx[3] =
1301 constexpr double bdr_tol_inflate = 1.01;
1309 const double lenx = h_bb[e*n_box_ents + max_off + d] -
1310 h_bb[e*n_box_ents + min_off + d];
1313 max_diag2 = std::max(max_diag2,
1314 diag2 * bdr_tol_inflate * bdr_tol_inflate);
1317 MPI_Allreduce(MPI_IN_PLACE, &max_diag2, 1, MPI_DOUBLE, MPI_MAX,
1333 MPI_Allreduce(MPI_IN_PLACE, &nelem, 1, MPI_INT, MPI_SUM,
gsl_comm->c);
1343 gslib::lobatto_nodes(gll1dtemp.GetData(),
DEV.
dof1d);
1344 gslib::gll_lag_setup(lagcoefftemp.GetData(),
DEV.
dof1d);
1348 lagrange_eval_second_derivative(wtendtemp.
GetData(), -1.0, i,
1349 gll1dtemp.GetData(),
1350 lagcoefftemp.GetData(),
DEV.
dof1d);
1351 lagrange_eval_second_derivative(wtendtemp.
GetData()+3*
DEV.
dof1d, 1.0, i,
1352 gll1dtemp.GetData(),
1353 lagcoefftemp.GetData(),
DEV.
dof1d);
1358 for (
int i = 0; i < 6*
DEV.
dof1d; i++) { h_wtend[i] = wtendtemp[i]; }
1362 for (
int i = 0; i <
DEV.
dof1d; i++) { h_gll1d[i] = gll1dtemp[i]; }
1366 for (
int i = 0; i <
DEV.
dof1d; i++) { h_lagcoeff[i] = lagcoefftemp[i]; }
1373 const int point_pos_ordering)
1375 MFEM_VERIFY(
setupflag,
"Use FindPointsGSLIB::Setup before finding points.");
1389 bool tensor_product_only =
mesh->
GetNE() == 0 ||
1394 MPI_Allreduce(MPI_IN_PLACE, &tensor_product_only, 1, MFEM_MPI_CXX_BOOL,
1398 if (dev_mode && tensor_product_only)
1400#if GSLIB_RELEASE_VERSION == 10007
1403 MFEM_ABORT(
"Either update to gslib v1.0.9 for GPU support "
1404 "or use SetGPUtoCPUFallback to use host-functions. See "
1405 "INSTALL for instructions to update GSLIB.");
1414 auto xvFill = [&](
const double *xv_base[],
unsigned xv_stride[])
1416 for (
int d = 0; d <
dim; d++)
1421 xv_stride[d] =
sizeof(double);
1425 xv_base[d] = pp + d;
1426 xv_stride[d] =
dim*
sizeof(double);
1433 auto *findptsData = (gslib::findpts_data_2 *)this->
fdataD;
1434 const double *xv_base[2];
1435 unsigned xv_stride[2];
1436 xvFill(xv_base, xv_stride);
1442 xv_base, xv_stride,
points_cnt, findptsData);
1446 auto *findptsData = (gslib::findpts_data_3 *)this->
fdataD;
1447 const double *xv_base[3];
1448 unsigned xv_stride[3];
1449 xvFill(xv_base, xv_stride);
1478#if GSLIB_RELEASE_VERSION >= 10009
1485 const slong i =
lfloor((x - low) * fac);
1486 return i < 0 ? 0 : (n - 1 < (ulong)i ? n - 1 : (ulong)i);
1492 const ulong n =
p->hash_n;
1502 const ulong n =
p->hash_n;
1509 auto *findptsData3 = (gslib::findpts_data_3 *)this->
fdataD;
1510 auto *findptsData2 = (gslib::findpts_data_2 *)this->
fdataD;
1512 DEV.
newt_tol =
dim == 2 ? findptsData2->local.tol : findptsData3->local.tol;
1521 DEV.
cr =
dim == 2 ? &findptsData2->cr : &findptsData3->cr;
1530 const int dim2 =
dim*
dim;
1535 auto box = findptsData3->local.obb[e];
1536 for (
int d = 0; d <
dim; d++)
1538 p_bb[n_box_ents*e + d] = box.c0[d];
1539 p_bb[n_box_ents*e +
dim + d] = box.x[d].min;
1540 p_bb[n_box_ents*e + 2*
dim + d] = box.x[d].max;
1544 for (
int d = 0; d < dim2; ++d)
1546 p_bb[n_box_ents*e + 3*
dim + d] = box.A[d];
1554 auto box = findptsData2->local.obb[e];
1555 for (
int d = 0; d <
dim; d++)
1557 p_bb[n_box_ents*e + d] = box.c0[d];
1558 p_bb[n_box_ents*e +
dim + d] = box.x[d].min;
1559 p_bb[n_box_ents*e + 2*
dim + d] = box.x[d].max;
1563 for (
int d = 0; d < dim2; ++d)
1565 p_bb[n_box_ents*e + 3*
dim + d] = box.A[d];
1574 auto hash = findptsData2->local.hd;
1577 for (
int d = 0; d <
dim; d++)
1579 p_loc_hash_min[d] = hash.bnd[d].min;
1580 p_loc_hash_fac[d] = hash.fac[d];
1586 auto hash = findptsData3->local.hd;
1589 for (
int d = 0; d <
dim; d++)
1591 p_loc_hash_min[d] = hash.bnd[d].min;
1592 p_loc_hash_fac[d] = hash.fac[d];
1597 int h_o_size =
dim == 2 ?
1598 findptsData2->local.hd.offset[(int)std::pow(
DEV.
lh_nx,
dim)] :
1599 findptsData3->local.hd.offset[(int)std::pow(
DEV.
lh_nx,
dim)];
1603 for (
int i = 0; i < h_o_size; i++)
1605 p_ou_offset[i] =
dim == 2 ? findptsData2->local.hd.offset[i] :
1606 findptsData3->local.hd.offset[i];
1612 double *src_wtend =
dim == 2 ? findptsData2->local.fed.wtend[0] :
1613 findptsData3->local.fed.wtend[0];
1614 for (
int i = 0; i < 6*
DEV.
dof1d; i++) { h_wtend[i] = src_wtend[i]; }
1620 double *src_gll1d =
dim == 2 ? findptsData2->local.fed.z[0] :
1621 findptsData3->local.fed.z[0];
1622 for (
int i = 0; i <
DEV.
dof1d; i++) { h_gll1d[i] = src_gll1d[i]; }
1627 double *src_lagcoeff =
dim == 2 ? findptsData2->local.fed.lag_data[0] :
1628 findptsData3->local.fed.lag_data[0];
1629 for (
int i = 0; i <
DEV.
dof1d; i++) { h_lagcoeff[i] = src_lagcoeff[i]; }
1635 const int point_pos_ordering)
1644 const int ddim =
dim;
1669 double rbtol = 1e-12;
1683 FindPointsDeviceSetCode(pts_cnt, ddim, rbtol, bdr_t, d_gsl_code,
1684 d_gsl_ref, d_gsl_dist, d_gsl_elem,
1685 d_gsl_mfem_ref, d_gsl_mfem_elem);
1693 struct gslib::array hash_pt, src_pt, out_pt;
1698 unsigned int index, proc;
1704 unsigned int index, code, el, proc;
1715 array_init(
struct srcPt_t, &hash_pt,
points_cnt);
1716 pt = (
struct srcPt_t *)hash_pt.ptr;
1718 auto x =
new double[
dim];
1721 const int code_i = h_gsl_code[
index];
1722 if (code_i != CODE_INTERNAL)
1724 for (
int d = 0; d <
dim; ++d)
1726 int idx = point_pos_ordering == 0 ?
1733 for (
int d = 0; d <
dim; ++d)
1743 hash_pt.n = pt - (
struct srcPt_t *)hash_pt.ptr;
1744 sarray_transfer(
struct srcPt_t, &hash_pt, proc, 1,
DEV.
cr);
1752 const unsigned int *
const hash_offset =
dim == 2 ?
DEV.
hash2->offset :
1755 unsigned int *proc, *proc_p;
1756 const struct srcPt_t *
p = (
struct srcPt_t *)hash_pt.ptr,
1757 *
const pe =
p + hash_pt.n;
1760 for (;
p != pe; ++
p)
1764 const int i = hash_offset[hi], ie = hash_offset[hi + 1];
1771 array_init(
struct srcPt_t, &src_pt, count);
1772 q = (
struct srcPt_t *)src_pt.ptr;
1774 p = (
struct srcPt_t *)hash_pt.ptr;
1775 for (;
p != pe; ++
p)
1779 int i = hash_offset[hi];
1780 const int ie = hash_offset[hi + 1];
1781 for (; i != ie; ++i)
1783 const unsigned int pp = hash_offset[i];
1794 array_free(&hash_pt);
1795 src_pt.n = proc_p - proc;
1797 sarray_transfer_ext(
struct srcPt_t, &src_pt, proc,
sizeof(uint),
DEV.
cr);
1806 const struct srcPt_t *spt;
1807 struct outPt_t *opt;
1808 array_init(
struct outPt_t, &out_pt, n);
1810 spt = (
struct srcPt_t *)src_pt.ptr;
1811 opt = (
struct outPt_t *)out_pt.ptr;
1812 for (; n; --n, ++spt, ++opt)
1814 opt->index = spt->index;
1815 opt->proc = spt->proc;
1817 spt = (
struct srcPt_t *)src_pt.ptr;
1818 opt = (
struct outPt_t *)out_pt.ptr;
1821 Vector gsl_ref_l, gsl_dist_l;
1827 auto h_ptr_ppl = point_pos_l.
HostWrite();
1831 for (
int point = 0; point < n; ++point)
1833 for (
int d = 0; d <
dim; d++)
1835 int idx = point_pos_ordering == 0 ? point + d*n : point*
dim + d;
1836 h_ptr_ppl[idx] = spt[point].x[d];
1843 gsl_elem_l, gsl_ref_l, gsl_dist_l, n);
1848 gsl_elem_l, gsl_ref_l, gsl_dist_l, n);
1853 gsl_code_l.HostRead();
1857 for (
int point = 0; point < n; point++)
1859 opt[point].code =
AsConst(gsl_code_l)[point];
1860 if (opt[point].code == CODE_NOT_FOUND)
1864 opt[point].el =
AsConst(gsl_elem_l)[point];
1865 opt[point].dist2 =
AsConst(gsl_dist_l)[point];
1866 for (
int d = 0; d <
dim; ++d)
1868 opt[point].r[d] =
AsConst(gsl_ref_l)[
dim * point + d];
1874 ip.
Set2(0.5*opt[point].r[0]+0.5, 0.5*opt[point].r[1]+0.5);
1878 ip.
Set3(0.5*opt[point].r[0]+0.5, 0.5*opt[point].r[1]+0.5,
1879 0.5*opt[point].r[2]+0.5);
1884 CODE_INTERNAL : CODE_BORDER;
1885 opt[point].code = setcode==CODE_BORDER && opt[point].dist2>
bdr_tol ?
1886 CODE_NOT_FOUND : setcode;
1889 array_free(&src_pt);
1892 sarray_sort(
struct outPt_t, opt, out_pt.n, code, 0, &
DEV.
cr->data);
1895 while (n && opt[n - 1].code == CODE_NOT_FOUND)
1901 sarray_transfer(
struct outPt_t, &out_pt, proc, 1,
DEV.
cr);
1918 struct outPt_t *opt = (
struct outPt_t *)out_pt.ptr;
1919 for (
int i = 0; i < n; i++)
1921 const int index = opt[i].index;
1922 if (h_gsl_code[
index] == CODE_INTERNAL)
1926 if (h_gsl_code[
index] == CODE_NOT_FOUND ||
1927 opt[i].code == CODE_INTERNAL ||
1928 opt[i].dist2 < h_gsl_dist[
index])
1930 for (
int d = 0; d <
dim; ++d)
1934 h_gsl_mfem_ref[
dim*
index + d] = 0.5*(rv + 1.);
1936 h_gsl_dist[
index] = opt[i].dist2;
1937 h_gsl_proc[
index] = opt[i].proc;
1938 h_gsl_elem[
index] = opt[i].el;
1939 h_gsl_mfem_elem[
index] = opt[i].el;
1940 h_gsl_code[
index] = opt[i].code;
1943 array_free(&out_pt);
1950 if (h_gsl_code[
index] == CODE_NOT_FOUND || h_gsl_proc[
index] !=
id)
1956 bool internal =
true;
1957 for (
int k = 0; k <
dim; k++)
1959 double r_val = h_gsl_ref[
index *
dim + k];
1960 double val = 0.5 * (r_val + 1.0);
1961 h_gsl_mfem_ref[
index *
dim + k] = val;
1962 if (val < rbtol || val > 1.0 - rbtol)
1968 int setcode = internal ? CODE_INTERNAL : CODE_BORDER;
1969 h_gsl_code[
index] = (setcode == CODE_BORDER &&
1979 unsigned int index, proc, el;
1985 unsigned int index, proc;
2015 struct gslib::array src, outpt;
2032 numSend += (h_code[
index] != CODE_NOT_FOUND &&
2034 nlocal += (h_code[
index] != CODE_NOT_FOUND &&
2038 gsl_elem_temp.
SetSize(nlocal);
2048 array_init(evalSrcPt_t, &src, numSend);
2049 pt = (evalSrcPt_t *)src.ptr;
2056 for (
int d = 0; d <
dim; ++d)
2061 pt->proc = h_proc[
index];
2062 pt->el = h_el[
index];
2065 else if (h_code[
index] != CODE_NOT_FOUND &&
2068 gsl_elem_temp[ctr] = h_el[
index];
2069 for (
int d = 0; d <
dim; ++d)
2073 index_temp[ctr] =
index;
2078 src.n = pt - (evalSrcPt_t *)src.ptr;
2079 sarray_transfer(evalSrcPt_t, &src, proc, 1,
cr);
2084 Vector interp_vals(nlocal*ncomp);
2110 auto d_interp_vals = interp_vals.
Read();
2111 auto d_index_temp = index_temp.
Read();
2112 auto d_field_out = field_out.
ReadWrite();
2114 const int interp_Offset = interp_vals.
Size()/ncomp;
2117 InterpolateDeviceScatter(nlocal, d_index_temp, d_interp_vals,
2118 d_field_out, interp_Offset, ncomp, pts_cnt,
2134 const evalSrcPt_t *spt;
2135 spt = (evalSrcPt_t *)src.ptr;
2144 spt = (evalSrcPt_t *)src.ptr;
2145 for (
int i = 0; i < n; i++, ++spt)
2147 gsl_elem_temp[i] = spt->el;
2148 for (
int d = 0; d <
dim; d++)
2150 gsl_ref_temp(i*
dim + d) = spt->r[d];
2154 Vector interp_vals(n*ncomp);
2161 interp_vals, n, ncomp, dof1Dsol);
2168 interp_vals, n, ncomp, dof1Dsol);
2173 auto h_interp_vals = interp_vals.
HostRead();
2177 int Offset = interp_vals.
Size()/ncomp;
2178 for (
int i = 0; i < ncomp; i++)
2180 spt = (evalSrcPt_t *)src.ptr;
2181 array_init(evalOutPt_t, &outpt, n);
2183 evalOutPt_t *opt = (evalOutPt_t *)outpt.ptr;
2185 for (
int j = 0; j < n; j++)
2187 opt->index = spt->index;
2188 opt->proc = spt->proc;
2189 opt->out = h_interp_vals[j + Offset*i];
2194 sarray_transfer(
struct evalOutPt_t, &outpt, proc, 1,
cr);
2196 opt = (evalOutPt_t *)outpt.ptr;
2201 opt->index*ncomp + i;
2202 h_field_out[idx] = opt->out;
2215 const int n,
const Vector &x)
2220 return (
hash_index_1(hash_min(1), hash_fac(1), n, x[1])) * n
2225 return (
hash_index_1(hash_min(2), hash_fac(2), n, x[2]) * n +
2231 MFEM_ABORT(
"hash_index_nd only supports 2D and 3D cases.");
2236 int point_pos_ordering)
2238 MFEM_VERIFY(
setupflag,
"Use FindPointsGSLIB::Setup before finding points.");
2239 MFEM_VERIFY(
dim <
spacedim,
"FindPointsSurf is only for surface meshes.");
2241 bool supported_surf_elem =
true;
2249 supported_surf_elem =
false;
2253 MPI_Allreduce(MPI_IN_PLACE, &supported_surf_elem, 1, MFEM_MPI_CXX_BOOL,
2256 MFEM_VERIFY(supported_surf_elem,
2257 "FindPointsGSLIB surface mesh support: only SEGMENT, "
2258 "QUADRILATERAL, and TRIANGLE elements are supported.");
2311 const unsigned int id =
gsl_comm->id,
2320 const double rbtol = 1e-12;
2328 const int ddim =
dim;
2329 const double dbdr_tol =
bdr_tol;
2340 if (d_gsl_code[
index] == CODE_NOT_FOUND) {
return; }
2347 d_gsl_mfem_ref[
index] = ipx;
2348 if (ipx < rbtol || ipx > 1.0 - rbtol)
2350 d_gsl_code[
index] = CODE_BORDER;
2355 const int loc_id = d_gsl_elem[
index];
2356 d_gsl_mfem_elem[
index] = d_split_elem_map[loc_id];
2361 const int tri_id = d_split_elem_idx[loc_id];
2363 const double u = 0.5*(d_gsl_ref[
index*2 + 0] + 1.0);
2364 const double v = 0.5*(d_gsl_ref[
index*2 + 1] + 1.0);
2366 MapSplitTriangleQuadToTriangle(tri_id,
u, v, tx, ty);
2368 d_gsl_mfem_ref[
index*2 + 0] = tx;
2369 d_gsl_mfem_ref[
index*2 + 1] = ty;
2372 if (tx < rbtol || ty < rbtol || tx + ty > 1.0 - rbtol)
2374 d_gsl_code[
index] = CODE_BORDER;
2380 const real_t ipx = 0.5*(d_gsl_ref[
index*2 + 0] + 1.0);
2381 const real_t ipy = 0.5*(d_gsl_ref[
index*2 + 1] + 1.0);
2382 d_gsl_mfem_ref[
index*2 + 0] = ipx;
2383 d_gsl_mfem_ref[
index*2 + 1] = ipy;
2384 if (ipx < rbtol || ipx > 1.0 - rbtol ||
2385 ipy < rbtol || ipy > 1.0 - rbtol)
2387 d_gsl_code[
index] = CODE_BORDER;
2391 if (d_gsl_code[
index] == CODE_BORDER && d_gsl_dist[
index] > dbdr_tol)
2393 d_gsl_code[
index] = CODE_NOT_FOUND;
2396 if (np == 1) {
return; }
2403 struct gslib::array hash_pt, src_pt, out_pt;
2408 unsigned int index, proc;
2414 unsigned int index, code, el, proc;
2415 unsigned int mfem_el, loc_id, geom;
2426 array_init(
struct srcPt_t, &hash_pt,
points_cnt);
2427 pt = (
struct srcPt_t *)hash_pt.ptr;
2432 if (h_gsl_code[
index] != CODE_INTERNAL)
2436 int idx = point_pos_ordering == 0 ?
2451 hash_pt.n = pt - (
struct srcPt_t *)hash_pt.ptr;
2452 sarray_transfer(
struct srcPt_t, &hash_pt, proc, 1,
DEV.
cr);
2462 unsigned int *proc, *proc_p;
2463 const struct srcPt_t *
p = (
struct srcPt_t *)hash_pt.ptr,
2464 *
const pe =
p + hash_pt.n;
2470 for (
int d = 0; d <
spacedim; d++) { x[d] =
p->x[d]; }
2472 const int i = hash_offset[hi], ie = hash_offset[hi + 1];
2479 array_init(
struct srcPt_t, &src_pt, count);
2480 q = (
struct srcPt_t *)src_pt.ptr;
2481 p = (
struct srcPt_t *)hash_pt.ptr;
2484 for (
int d = 0; d <
spacedim; d++) { x[d] =
p->x[d]; }
2486 int i = hash_offset[hi];
2487 const int ie = hash_offset[hi + 1];
2490 const unsigned int pp = hash_offset[i];
2500 array_free(&hash_pt);
2501 src_pt.n = proc_p - proc;
2503 sarray_transfer_ext(
struct srcPt_t, &src_pt, proc,
sizeof(uint),
DEV.
cr);
2512 const struct srcPt_t *spt;
2513 struct outPt_t *opt;
2514 array_init(
struct outPt_t, &out_pt, n);
2516 spt = (
struct srcPt_t *)src_pt.ptr;
2517 opt = (
struct outPt_t *)out_pt.ptr;
2518 for (; n; --n, ++spt, ++opt)
2520 opt->index = spt->index;
2521 opt->proc = spt->proc;
2523 spt = (
struct srcPt_t *)src_pt.ptr;
2524 opt = (
struct outPt_t *)out_pt.ptr;
2528 gsl_ref_l.UseDevice(use_dev);
2537 for (
int point=0; point<n; ++point)
2541 int idx = point_pos_ordering==0 ? point + d*n :
2543 pointl[idx] = spt[point].x[d];
2582 gsl_ref_l.HostRead();
2584 gsl_code_l.HostRead();
2591 for (
int point=0; point<n; ++point)
2593 opt[point].code =
AsConst(gsl_code_l)[point];
2594 if (opt[point].code == CODE_NOT_FOUND)
2598 opt[point].el =
AsConst(gsl_elem_l)[point];
2599 opt[point].dist2 =
AsConst(gsl_dist_l)[point];
2600 for (
int d = 0; d <
dim; ++d)
2602 opt[point].r[d] =
AsConst(gsl_ref_l)[
dim * point + d];
2605 const int loc_id =
AsConst(gsl_elem_l)[point];
2606 opt[point].mfem_el = h_split_element_map[loc_id];
2607 opt[point].loc_id = h_split_element_index[loc_id];
2608 opt[point].geom = h_split_element_geom[loc_id];
2616 real_t ipx = 0.5*opt[point].r[0]+0.5;
2617 if (ipx < rbtol || ipx > 1.0 - rbtol)
2619 opt[point].code = CODE_BORDER;
2627 const int loc_id = opt[point].loc_id;
2628 const double u = 0.5*opt[point].r[0] + 0.5;
2629 const double v = 0.5*opt[point].r[1] + 0.5;
2631 MapSplitTriangleQuadToTriangle(loc_id,
u, v, tx, ty);
2633 if (tx < rbtol || ty < rbtol || tx + ty > 1.0 - rbtol)
2635 opt[point].code = CODE_BORDER;
2640 real_t ipx = 0.5*opt[point].r[0]+0.5;
2641 real_t ipy = 0.5*opt[point].r[1]+0.5;
2642 if (ipx < rbtol || ipx > 1.0 - rbtol ||
2643 ipy < rbtol || ipy > 1.0 - rbtol)
2645 opt[point].code = CODE_BORDER;
2649 if (opt[point].code == CODE_BORDER && opt[point].dist2 >
bdr_tol)
2651 opt[point].code = CODE_NOT_FOUND;
2654 array_free(&src_pt);
2657 sarray_sort(
struct outPt_t, opt, out_pt.n, code, 0, &
DEV.
cr->data);
2660 while (n && opt[n-1].code == CODE_NOT_FOUND)
2666 sarray_transfer(
struct outPt_t, &out_pt, proc, 1,
DEV.
cr);
2683 struct outPt_t *opt = (
struct outPt_t *)out_pt.ptr;
2684 for (; n; --n, ++opt)
2686 const int index = opt->index;
2687 if (h_gsl_code[
index] == CODE_INTERNAL)
2691 if ( h_gsl_code[
index]==CODE_NOT_FOUND
2692 || opt->code==CODE_INTERNAL
2693 || opt->dist2<h_gsl_dist[
index] )
2695 for (
int d=0; d<
dim; ++d)
2697 h_gsl_ref[
dim*
index + d] = opt->r[d];
2699 h_gsl_dist[
index] = opt->dist2;
2700 h_gsl_proc[
index] = opt->proc;
2701 h_gsl_elem[
index] = opt->el;
2702 h_gsl_code[
index] = opt->code;
2703 h_gsl_mfem_elem[
index] = opt->mfem_el;
2707 const int loc_id = opt->loc_id;
2708 const double u = 0.5*opt->r[0] + 0.5;
2709 const double v = 0.5*opt->r[1] + 0.5;
2710 MapSplitTriangleQuadToTriangle(loc_id,
u, v,
2716 for (
int d=0; d<
dim; ++d)
2718 h_gsl_mfem_ref[
dim*
index + d] = 0.5*(opt->r[d] + 1.);
2723 array_free(&out_pt);
2735 const int field_out_ordering)
2738 struct gslib::array src, outpt;
2755 numSend += (h_code[
index] != CODE_NOT_FOUND &&
2757 nlocal += (h_code[
index] != CODE_NOT_FOUND &&
2761 gsl_elem_temp.
SetSize(nlocal);
2771 array_init(evalSrcPt_t, &src, numSend);
2772 pt = (evalSrcPt_t *)src.ptr;
2779 for (
int d=0; d<
dim; ++d)
2784 pt->proc = h_proc[
index];
2785 pt->el = h_el[
index];
2790 gsl_elem_temp[ctr] = h_el[
index];
2791 for (
int d=0; d<
dim; ++d)
2795 index_temp[ctr] =
index;
2800 src.n = pt - (evalSrcPt_t *)src.ptr;
2801 sarray_transfer(evalSrcPt_t, &src, proc, 1,
cr);
2806 Vector interp_vals(nlocal*ncomp);
2812 interp_vals, nlocal, ncomp, dof1Dsol);
2817 interp_vals, nlocal, ncomp, dof1Dsol);
2824 auto d_interp_vals = interp_vals.
Read(use_dev);
2825 auto d_index_temp = index_temp.
Read(use_dev);
2826 auto d_field_out = field_out.
ReadWrite(use_dev);
2827 const int interp_offset = interp_vals.
Size()/ncomp;
2828 InterpolateDeviceScatter(nlocal, d_index_temp, d_interp_vals,
2829 d_field_out, interp_offset, ncomp,
points_cnt,
2830 field_out_ordering);
2845 const evalSrcPt_t *spt;
2847 spt = (evalSrcPt_t *)src.ptr;
2856 spt = (evalSrcPt_t *)src.ptr;
2858 for (
int i=0; i<n; i++, ++spt)
2860 gsl_elem_temp[i] = spt->el;
2861 for (
int d=0; d<
dim; d++)
2863 gsl_ref_temp(i*
dim + d) = spt->r[d];
2867 Vector interp_vals(n*ncomp);
2872 interp_vals, n, ncomp, dof1Dsol);
2877 interp_vals, n, ncomp, dof1Dsol);
2882 auto h_interp_vals = interp_vals.
HostRead();
2886 int Offset = interp_vals.
Size()/ncomp;
2887 for (
int i=0; i<ncomp; i++)
2889 spt = (evalSrcPt_t *)src.ptr;
2890 array_init(evalOutPt_t, &outpt, n);
2892 opt = (evalOutPt_t *)outpt.ptr;
2894 for (
int j=0; j<n; j++)
2896 opt->index = spt->index;
2897 opt->proc = spt->proc;
2898 opt->out = h_interp_vals[j + Offset*i];
2903 sarray_transfer(
struct evalOutPt_t, &outpt, proc, 1,
cr);
2905 opt = (evalOutPt_t *)outpt.ptr;
2910 opt->index*ncomp + i;
2911 h_field_out[idx] = opt->out;
2924 const int point_pos_ordering) {};
2927 const int nel,
const int ncomp,
2929 const int ordering) {};
2932 int point_pos_ordering)
2934 MFEM_ABORT(
"FindPointsGSLIB::FindPoints only supports surface meshes "
2935 "with GSLIB v1.0.9 or later.");
2939 const int nel,
const int ncomp,
2941 const int field_out_ordering) {};
2945 const int point_pos_ordering,
2946 const double bbox_rel_size_inc,
2947 const double newt_tol,
const int npt_max)
2951 Setup(m, bbox_rel_size_inc, newt_tol, npt_max);
2959 const int point_pos_ordering)
2968 const int point_pos_ordering,
2969 const int field_out_ordering)
2972 Interpolate(field_in, field_out, field_out_ordering);
2978 const int point_pos_ordering)
2980 FindPoints(m, point_pos, point_pos_ordering);
2996 findpts_free_2((gslib::findpts_data_2 *)this->
fdataD);
3000 findpts_free_3((gslib::findpts_data_3 *)this->
fdataD);
3010 for (
int i = 0; i < 4; i++)
3039 const double quad_v[7][2] =
3041 {0, 0}, {0.5, 0}, {1, 0}, {0, 0.5},
3042 {1./3., 1./3.}, {0.5, 0.5}, {0, 1}
3044 const int quad_e[3][4] =
3046 {0, 1, 4, 3}, {1, 2, 5, 4}, {3, 4, 5, 6}
3049 for (
int j = 0; j < Nvert; j++)
3053 for (
int j = 0; j < NEsplit; j++)
3055 int attribute = j + 1;
3056 mesh_split[0]->AddQuad(quad_e[j], attribute);
3064 for (
int k = 0; k <
dim; k++)
3066 for (
int j = 0; j < npt; j++)
3085 const double hex_v[15][3] =
3087 {0, 0, 0.}, {1, 0., 0.}, {0., 1., 0.}, {0, 0., 1.},
3088 {0.5, 0., 0.}, {0.5, 0.5, 0.}, {0., 0.5, 0.},
3089 {0., 0., 0.5}, {0.5, 0., 0.5}, {0., 0.5, 0.5},
3090 {1./3., 0., 1./3.}, {1./3., 1./3., 1./3.}, {0, 1./3., 1./3.},
3091 {1./3., 1./3., 0}, {0.25, 0.25, 0.25}
3093 const int hex_e[4][8] =
3095 {7, 10, 4, 0, 12, 14, 13, 6},
3096 {10, 8, 1, 4, 14, 11, 5, 13},
3097 {14, 11, 5, 13, 12, 9, 2, 6},
3098 {7, 3, 8, 10, 12, 9, 11, 14}
3101 for (
int j = 0; j < Nvert; j++)
3105 for (
int j = 0; j < NEsplit; j++)
3107 int attribute = j + 1;
3116 for (
int k = 0; k <
dim; k++)
3118 for (
int j = 0; j < npt; j++)
3130 const double hex_v[14][3] =
3132 {0, 0, 0}, {0.5, 0, 0}, {1, 0, 0}, {0, 0.5, 0},
3133 {1./3., 1./3., 0}, {0.5, 0.5, 0}, {0, 1, 0},
3134 {0, 0, 1}, {0.5, 0, 1}, {1, 0, 1}, {0, 0.5, 1},
3135 {1./3., 1./3., 1}, {0.5, 0.5, 1}, {0, 1, 1}
3137 const int hex_e[3][8] =
3139 {0, 1, 4, 3, 7, 8, 11, 10},
3140 {1, 2, 5, 4, 8, 9, 12, 11},
3141 {3, 4, 5, 6, 10, 11, 12, 13}
3144 for (
int j = 0; j < Nvert; j++)
3148 for (
int j = 0; j < NEsplit; j++)
3150 int attribute = j + 1;
3159 for (
int k = 0; k <
dim; k++)
3161 for (
int j = 0; j < npt; j++)
3173 const double hex_v[23][3] =
3175 {0.0000, 0.0000, 0.0000}, {0.5000, 0.0000, 0.0000},
3176 {0.0000, 0.0000, 0.5000}, {0.3333, 0.0000, 0.3333},
3177 {0.0000, 0.5000, 0.0000}, {0.3333, 0.3333, 0.0000},
3178 {0.0000, 0.3333, 0.3333}, {0.2500, 0.2500, 0.2500},
3179 {1.0000, 0.0000, 0.0000}, {0.5000, 0.0000, 0.5000},
3180 {0.5000, 0.5000, 0.0000}, {0.3333, 0.3333, 0.3333},
3181 {0.0000, 1.0000, 0.0000}, {0.0000, 0.5000, 0.5000},
3182 {0.0000, 0.0000, 1.0000}, {1.0000, 0.5000, 0.0000},
3183 {0.6667, 0.3333, 0.3333}, {0.6667, 0.6667, 0.0000},
3184 {0.5000, 0.5000, 0.2500}, {1.0000, 1.0000, 0.0000},
3185 {0.5000, 0.5000, 0.5000}, {0.5000, 1.0000, 0.0000},
3186 {0.3333, 0.6667, 0.3333}
3188 const int hex_e[8][8] =
3190 {2, 3, 1, 0, 6, 7, 5, 4}, {3, 9, 8, 1, 7, 11, 10, 5},
3191 {7, 11, 10, 5, 6, 13, 12, 4}, {2, 14, 9, 3, 6, 13, 11, 7},
3192 {9, 16, 15, 8, 11, 18, 17, 10}, {16, 20, 19, 15, 18, 22, 21, 17},
3193 {18, 22, 21, 17, 11, 13, 12, 10}, {9, 14, 20, 16, 11, 13, 22, 18}
3196 for (
int j = 0; j < Nvert; j++)
3200 for (
int j = 0; j < NEsplit; j++)
3202 int attribute = j + 1;
3211 for (
int k = 0; k <
dim; k++)
3213 for (
int j = 0; j < npt; j++)
3230 const int NEsplit = meshin->
GetNE();
3233 pts_cnt = NEsplit * dof_cnt;
3238 MFEM_VERIFY(tbe !=
nullptr,
"TensorBasis FiniteElement expected.");
3246 MFEM_ASSERT(irule->
GetNPoints() == pts_cnt,
"IntegrationRule does not have"
3247 "the correct number of points.");
3249 for (
int i = 0; i < NEsplit; i++)
3253 for (
int j = 0; j < dof_cnt; j++)
3255 for (
int d = 0; d <
dim; d++)
3257 irlist(pts_cnt * d + pt_id) = pos(dof_map[j], d);
3259 irule->
IntPoint(pt_id).
x = irlist(pt_id);
3262 irule->
IntPoint(pt_id).
y = irlist(pts_cnt + pt_id);
3266 irule->
IntPoint(pt_id).
z = irlist(2*pts_cnt + pt_id);
3276 MFEM_VERIFY(
mesh,
"Setup FindPointsGSLIB with mesh first.");
3277 const int dof1D = order+1;
3282 if (ir_out[0]) {
delete ir_out[0]; ir_out[0] =
nullptr; }
3288 if (ir_out[0]) {
delete ir_out[0]; ir_out[0] =
nullptr; }
3292 if (ir_out[1]) {
delete ir_out[1]; ir_out[1] =
nullptr; }
3298 if (ir_out[0]) {
delete ir_out[0]; ir_out[0] =
nullptr; }
3302 if (ir_out[1]) {
delete ir_out[1]; ir_out[1] =
nullptr; }
3306 if (ir_out[2]) {
delete ir_out[2]; ir_out[2] =
nullptr; }
3310 if (ir_out[3]) {
delete ir_out[3]; ir_out[3] =
nullptr; }
3318 MFEM_VERIFY(
mesh,
"Setup FindPointsGSLIB with mesh first.");
3352 MFEM_ABORT(
"Unsupported geometry type.");
3355 for (
int i = 0; i < NEsplit; i++)
3367 bool by_element)
const
3372 const int vdim = fes->
GetVDim();
3378 const int dof_1D = maxOrder+1;
3379 const int pts_el = std::pow(dof_1D,
dim);
3381 node_vals.
SetSize(vdim * pts_cnt);
3388 int gsl_mesh_pt_index = 0;
3390 for (
int e = 0; e < NE; e++)
3394 bool el_to_split =
true;
3397 ir_split_temp = ir[0];
3401 ir_split_temp = ir[1];
3405 ir_split_temp = ir[2];
3409 ir_split_temp = ir[3];
3413 ir_split_temp = ir[1];
3421 ir_split_temp = ir[0];
3429 MFEM_ABORT(
"Unsupported geometry type.");
3436 for (
int i = 0; i < ir_split_temp->
GetNPoints(); i++)
3439 nodes->GetVectorValue(e, ip, locval);
3442 const int ei = gsl_mesh_pt_index / pts_el;
3443 const int pi = gsl_mesh_pt_index % pts_el;
3444 for (
int d = 0; d < vdim; d++)
3446 node_vals(ei * pts_el * vdim + d * pts_el + pi) = locval(d);
3451 for (
int d = 0; d < vdim; d++)
3453 node_vals(pts_cnt*d + gsl_mesh_pt_index) = locval(d);
3456 gsl_mesh_pt_index++;
3461 const int dof_cnt_split = fe->
GetDof();
3465 MFEM_VERIFY(tbe !=
nullptr,
"TensorBasis FiniteElement expected.");
3468 if (dm.
Size() > 0) { dof_map = dm; }
3469 else {
for (
int i = 0; i < dof_cnt_split; i++) { dof_map[i] = i; } }
3472 Vector posV(pos.
Data(), dof_cnt_split * vdim);
3476 nodes->GetSubVector(xdofs, posV);
3477 for (
int j = 0; j < dof_cnt_split; j++)
3481 const int ei = gsl_mesh_pt_index / pts_el;
3482 const int pi = gsl_mesh_pt_index % pts_el;
3483 for (
int d = 0; d < vdim; d++)
3485 node_vals(ei * pts_el * vdim + d * pts_el + pi) =
3491 for (
int d = 0; d < vdim; d++)
3493 node_vals(pts_cnt * d + gsl_mesh_pt_index) = pos(dof_map[j], d);
3496 gsl_mesh_pt_index++;
3517 double rbtol = 1e-12;
3531 struct gslib::array *outpt =
new gslib::array;
3532 struct out_pt {
double r[3]; uint
index, el, proc, code; };
3534 array_init(
struct out_pt, outpt, nptsend);
3536 pt = (
struct out_pt *)outpt->ptr;
3543 for (
int d = 0; d <
dim; ++d)
3555 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
3559 pt = (
struct out_pt *)outpt->ptr;
3564 const int elem = pt->el;
3600 for (
int d = 0; d <
dim; d++)
3602 pt->r[d] = mfem_ref(d);
3612 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
3616 pt = (
struct out_pt *)outpt->ptr;
3620 for (
int d = 0; d <
dim; d++)
3639 if (
dim == 3) { ip.
z = mfem_ref(2); }
3673 if (
dim == 3) { ip.
z = mfem_ref(2); }
3687 const int field_out_ordering)
3689 MFEM_VERIFY(
setupflag,
"FindPointsGSLIB::Setup must be called first.");
3702 bool tensor_product_only =
mesh->
GetNE() == 0 ||
3707 MPI_Allreduce(MPI_IN_PLACE, &tensor_product_only, 1, MFEM_MPI_CXX_BOOL,
3714 if (field_in_on_dev && fec_h1 &&
3717#if GSLIB_RELEASE_VERSION == 10007
3720 MFEM_ABORT(
"Either update to gslib v1.0.9 for GPU support "
3721 "or use SetGPUtoCPUFallback to use host-functions. See "
3722 "INSTALL for instructions to update GSLIB");
3726 "basis not supported");
3732 R->
Mult(field_in, node_vals);
3739 maxOrder+1, field_out_ordering);
3756 if (fec_h1 && gf_order == mesh_order &&
3762 if (field_in_on_dev || field_out_on_dev)
3773 if (field_in_on_dev || field_out_on_dev)
3788 if (h_gsl_code[i] == 1) { indl2.
Append(i); }
3790 int borderPts = indl2.
Size();
3792 MPI_Allreduce(MPI_IN_PLACE, &borderPts, 1, MPI_INT, MPI_SUM,
gsl_comm->c);
3796 if (field_in_on_dev || field_out_on_dev)
3805 int gf_order_h1 = std::max(gf_order, 1);
3809 std::unique_ptr<FiniteElementSpace> fes;
3810 std::unique_ptr<GridFunction> field_in_h1;
3814 fes = std::make_unique<ParFiniteElementSpace>(
3817 field_in_h1 = std::make_unique<ParGridFunction>(
3823 fes = std::make_unique<FiniteElementSpace>(
3826 field_in_h1 = std::make_unique<GridFunction>(fes.get());
3829 field_in_h1->UseDevice(
false);
3841 MFEM_ABORT(
"Invalid averaging type.");
3844 if (gf_order_h1 == mesh_order)
3846 InterpolateH1(*field_in_h1, field_out_l2, field_out_ordering);
3856 for (
int j = 0; j < ncomp; j++)
3858 for (
int i = 0; i < indl2.
Size(); i++)
3863 h_field_out[idx] = h_field_out_l2[idx];
3866 if (field_in_on_dev || field_out_on_dev)
3881 const int field_out_ordering)
3883 MFEM_VERIFY(
setupflag,
"FindPointsGSLIB::Setup must be called first.");
3884#if GSLIB_RELEASE_VERSION < 10009
3885 MFEM_ABORT(
"Update to gslib v1.0.9 for surface mesh support.");
3890 MFEM_VERIFY(fec_h1,
"Only h1 functions supported for surface meshes.");
3892 "basis not supported");
3893 MFEM_VERIFY(
dim <
spacedim,
"InterpolateSurf is only for surface meshes.");
3895 bool has_split_elems =
false;
3896 bool supported_surf_elem =
true;
3903 supported_surf_elem =
false;
3907 MPI_Allreduce(MPI_IN_PLACE, &supported_surf_elem, 1, MFEM_MPI_CXX_BOOL,
3910 MFEM_VERIFY(supported_surf_elem,
3911 "FindPointsGSLIB surface mesh support: only SEGMENT, "
3912 "QUADRILATERAL, and TRIANGLE elements are supported.");
3913 MFEM_VERIFY(
dim <
spacedim,
"InterpolateSurf only supports surface meshes.");
3921 if (has_split_elems)
3924 const int meshOrder =
DEV.
dof1d - 1;
3927 if (fieldOrder == meshOrder)
3949 R->
Mult(field_in, node_vals);
3974 h_gll1d_sol[i] = h_gll1d[i];
3975 h_lagcoeff_sol[i] = h_lagcoeff[i];
3989 MFEM_ABORT(
"Variable order functions not supported for surface meshes!!");
3995 const int field_out_ordering)
4000 for (
int e = 0; e < ind_fes.
GetMesh()->GetNE(); e++)
4011 points_fld = field_in.
Size() / ncomp;
4013 "FindPointsGSLIB::InterpolateH1: Inconsistent size of gsl_code");
4017 std::fill(h_field_out, h_field_out + field_out.
Size(),
4020 for (
int i = 0; i < ncomp; i++)
4022 const int dataptrin = i*points_fld,
4031 for (
int j = 0; j < points_fld; j++)
4033 field_in_scalar(j) = field_in(i + j*ncomp);
4040 findpts_eval_2(h_field_out+dataptrout,
sizeof(
double),
4046 (gslib::findpts_data_2 *)this->fdataD);
4050 findpts_eval_3(h_field_out+dataptrout,
sizeof(
double),
4056 (gslib::findpts_data_3 *)this->fdataD);
4062 field_out_temp = h_field_out;
4063 for (
int i = 0; i < ncomp; i++)
4067 h_field_out[i + j*ncomp] = field_out_temp(j + i*
points_cnt);
4075 const int field_out_ordering)
4083 std::fill(h_field_out, h_field_out + field_out.
Size(),
4096 if (h_gsl_code[
index] == 2) {
continue; }
4103 for (
int i = 0; i < ncomp; i++)
4105 h_field_out[
index + i*npt] = localval(i);
4110 for (
int i = 0; i < ncomp; i++)
4112 h_field_out[
index*ncomp + i] = localval(i);
4123 if (h_gsl_code[
index] != 2) { nptsend +=1; }
4127 struct gslib::array *outpt =
new gslib::array;
4128 struct out_pt {
double r[3], ival; uint
index, el, proc; };
4130 array_init(
struct out_pt, outpt, nptsend);
4132 pt = (
struct out_pt *)outpt->ptr;
4135 if (h_gsl_code[
index] == 2) {
continue; }
4136 for (
int d = 0; d <
dim; ++d)
4138 pt->r[d]= h_gsl_mfem_ref[
index*
dim + d];
4141 pt->proc = h_gsl_proc[
index];
4142 pt->el = h_gsl_mfem_elem[
index];
4147 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
4153 pt = (
struct out_pt *)outpt->ptr;
4158 pt->ival = field_in.
GetValue(pt->el, ip, 1);
4163 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
4165 pt = (
struct out_pt *)outpt->ptr;
4168 h_field_out[pt->index] = pt->ival;
4178 pt = (
struct out_pt *)outpt->ptr;
4179 Vector vec_int_vals(npt*ncomp);
4190 struct gslib::array *savpt =
new gslib::array;
4191 struct sav_pt { uint
index, proc; };
4193 array_init(
struct sav_pt, savpt, npt);
4195 spt = (
struct sav_pt *)savpt->ptr;
4196 pt = (
struct out_pt *)outpt->ptr;
4199 spt->index = pt->index;
4200 spt->proc = pt->proc;
4208 struct gslib::array *sendpt =
new gslib::array;
4209 struct send_pt {
double ival; uint
index, proc; };
4210 struct send_pt *sdpt;
4211 for (
int j = 0; j < ncomp; j++)
4213 array_init(
struct send_pt, sendpt, npt);
4215 spt = (
struct sav_pt *)savpt->ptr;
4216 sdpt = (
struct send_pt *)sendpt->ptr;
4219 sdpt->index = spt->index;
4220 sdpt->proc = spt->proc;
4221 sdpt->ival = vec_int_vals(j +
index*ncomp);
4225 sarray_transfer(
struct send_pt, sendpt, proc, 1,
cr);
4226 sdpt = (
struct send_pt *)sendpt->ptr;
4230 sdpt->index + j*nptorig :
4231 sdpt->index*ncomp + j;
4232 h_field_out[idx] = sdpt->ival;
4250 if (h_gsl_code[i] == 2)
4263 "Invalid size. Please make sure to call FindPoints method "
4264 "before calling this function.");
4267 struct gslib::array *outpt =
new gslib::array;
4269 struct out_pt {
double rst[3]; uint
index, elem, proc, code; };
4271 array_init(
struct out_pt, outpt,
points_cnt);
4273 pt = (
struct out_pt *)outpt->ptr;
4281 for (
int d = 0; d <
dim; ++d)
4289 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
4292 const int points_recv = outpt->n;
4294 recv_elem.
SetSize(points_recv);
4296 recv_code.
SetSize(points_recv);
4299 pt = (
struct out_pt *)outpt->ptr;
4303 recv_elem[
index] = pt->elem;
4305 recv_code[
index] = pt->code;
4306 for (
int d = 0; d <
dim; ++d)
4308 recv_ref(
index*
dim + d)= pt->rst[d];
4323 MFEM_VERIFY(points_recv == 0 ||
4324 int_vals.
Size() % points_recv == 0,
4325 "Incompatible size. Please return interpolated values"
4326 "corresponding to points received using"
4327 "SendCoordinatesToOwningProcessors.");
4330 for (
int v = 0; v < vdim; v++)
4333 struct gslib::array *outpt =
new gslib::array;
4334 struct out_pt {
double val; uint
index, proc; };
4336 array_init(
struct out_pt, outpt, points_recv);
4337 outpt->n=points_recv;
4338 pt = (
struct out_pt *)outpt->ptr;
4344 int_vals(
index + v*points_recv) :
4345 int_vals(
index*vdim + v);
4350 sarray_transfer(
struct out_pt, outpt, proc, 1,
cr);
4353 MFEM_VERIFY(outpt->n ==
static_cast<size_t>(
points_cnt),
4354 "Incompatible size. Number of points "
4355 "received does not match the number of points originally "
4356 "found using FindPoints.");
4358 pt = (
struct out_pt *)outpt->ptr;
4364 field_out(idx) = pt->val;
4375 MFEM_VERIFY(
setupflag,
"Call FindPointsGSLIB::Setup method first");
4376 auto *findptsData3 = (gslib::findpts_data_3 *)this->
fdataD;
4377 auto *findptsData2 = (gslib::findpts_data_2 *)this->
fdataD;
4385 for (
int e = 0; e < nel; e++)
4390 auto box = findptsData3->local.obb[e];
4393 minn[d] = box.x[d].min;
4394 maxx[d] = box.x[d].max;
4405 minn[d] = h_bb_ptr[e*n_el_ents + min_off + d];
4406 maxx[d] = h_bb_ptr[e*n_el_ents + max_off + d];
4410 aabb(e*nve*
spacedim + c++) = minn[0];
4411 aabb(e*nve*
spacedim + c++) = minn[1];
4412 aabb(e*nve*
spacedim + c++) = minn[2];
4413 aabb(e*nve*
spacedim + c++) = maxx[0];
4414 aabb(e*nve*
spacedim + c++) = minn[1];
4415 aabb(e*nve*
spacedim + c++) = minn[2];
4416 aabb(e*nve*
spacedim + c++) = maxx[0];
4417 aabb(e*nve*
spacedim + c++) = maxx[1];
4418 aabb(e*nve*
spacedim + c++) = minn[2];
4419 aabb(e*nve*
spacedim + c++) = minn[0];
4420 aabb(e*nve*
spacedim + c++) = maxx[1];
4421 aabb(e*nve*
spacedim + c++) = minn[2];
4422 aabb(e*nve*
spacedim + c++) = minn[0];
4423 aabb(e*nve*
spacedim + c++) = minn[1];
4424 aabb(e*nve*
spacedim + c++) = maxx[2];
4425 aabb(e*nve*
spacedim + c++) = maxx[0];
4426 aabb(e*nve*
spacedim + c++) = minn[1];
4427 aabb(e*nve*
spacedim + c++) = maxx[2];
4428 aabb(e*nve*
spacedim + c++) = maxx[0];
4429 aabb(e*nve*
spacedim + c++) = maxx[1];
4430 aabb(e*nve*
spacedim + c++) = maxx[2];
4431 aabb(e*nve*
spacedim + c++) = minn[0];
4432 aabb(e*nve*
spacedim + c++) = maxx[1];
4433 aabb(e*nve*
spacedim + c++) = maxx[2];
4438 for (
int e = 0; e < nel; e++)
4443 auto box = findptsData2->local.obb[e];
4446 minn[d] = box.x[d].min;
4447 maxx[d] = box.x[d].max;
4458 minn[d] = h_bb_ptr[e*n_el_ents + min_off + d];
4459 maxx[d] = h_bb_ptr[e*n_el_ents + max_off + d];
4462 aabb(e*nve*
spacedim + 0) = minn[0];
4463 aabb(e*nve*
spacedim + 1) = minn[1];
4464 aabb(e*nve*
spacedim + 2) = maxx[0];
4465 aabb(e*nve*
spacedim + 3) = minn[1];
4466 aabb(e*nve*
spacedim + 4) = maxx[0];
4467 aabb(e*nve*
spacedim + 5) = maxx[1];
4468 aabb(e*nve*
spacedim + 6) = minn[0];
4469 aabb(e*nve*
spacedim + 7) = maxx[1];
4476 MFEM_VERIFY(
setupflag,
"Call FindPointsGSLIB::Setup method first");
4480 "Oriented bounding boxes are not available when obb_check is false");
4482 const unsigned int save_rank = 0;
4483 const unsigned int myid =
gsl_comm->id;
4499 MPI_Allreduce(&nel, &ne_glob, 1, MPI_INT, MPI_SUM,
gsl_comm->c);
4503 int nverts = nve*ne_glob;
4504 Mesh *meshbb =
nullptr;
4505 if (myid == save_rank)
4511 MFEM_VERIFY(nsend == bbvert.
Size(),
4512 "Inconsistent size of bounding box vertices");
4519 if (myid == save_rank)
4523 if (
static_cast<unsigned int>(
p) != save_rank)
4526 MPI_Recv(&nrecv, 1, MPI_INT,
p, 444,
gsl_comm->c, &status);
4530 MPI_Recv(bbvert.
GetData(), nrecv, MPI_DOUBLE,
p, 445,
gsl_comm->c, &status);
4538 int nel_recv = nrecv/(
spacedim*nve);
4539 for (
int e = 0; e < nel_recv; e++)
4541 for (
int j = 0; j < nve; j++)
4549 const int inds[4] = {vidx++, vidx++, vidx++, vidx++};
4556 const int inds[8] = {vidx++, vidx++, vidx++, vidx++,
4557 vidx++, vidx++, vidx++, vidx++
4559 meshbb->
AddHex(inds, (eidx++)+1);
4575 MPI_Send(&nsend, 1, MPI_INT, save_rank, 444,
gsl_comm->c);
4578 MPI_Send(bbvert.
GetData(), nsend, MPI_DOUBLE, save_rank, 445,
gsl_comm->c);
4592 MFEM_VERIFY(
setupflag,
"Call FindPointsGSLIB::Setup method first");
4594 "Oriented bounding boxes are not available when obb_check is false");
4595 auto *findptsData3 = (gslib::findpts_data_3 *)this->
fdataD;
4596 auto *findptsData2 = (gslib::findpts_data_2 *)this->
fdataD;
4605 for (
int e = 0; e < nel; e++)
4610 auto box = findptsData3->local.obb[e];
4645 v1(0) = -1.0; v1(1) = -1.0; v1(2) = -1.0;
4647 Amat.
Mult(v1, temp);
4649 v1(0) = 1.0; v1(1) = -1.0; v1(2) = -1.0;
4651 Amat.
Mult(v1, temp);
4653 v1(0) = 1.0; v1(1) = 1.0; v1(2) = -1.0;
4655 Amat.
Mult(v1, temp);
4657 v1(0) = -1.0; v1(1) = 1.0; v1(2) = -1.0;
4659 Amat.
Mult(v1, temp);
4661 v1(0) = -1.0; v1(1) = -1.0; v1(2) = 1.0;
4663 Amat.
Mult(v1, temp);
4665 v1(0) = 1.0; v1(1) = -1.0; v1(2) = 1.0;
4667 Amat.
Mult(v1, temp);
4669 v1(0) = 1.0; v1(1) = 1.0; v1(2) = 1.0;
4671 Amat.
Mult(v1, temp);
4673 v1(0) = -1.0; v1(1) = 1.0; v1(2) = 1.0;
4675 Amat.
Mult(v1, temp);
4681 for (
int e = 0; e < nel; e++)
4686 auto box = findptsData2->local.obb[e];
4722 v1(0) = -1.0; v1(1) = -1.0;
4724 Amat.
Mult(v1, temp);
4726 v1(0) = 1.0; v1(1) = -1.0;
4728 Amat.
Mult(v1, temp);
4730 v1(0) = 1.0; v1(1) = 1.0;
4732 Amat.
Mult(v1, temp);
4734 v1(0) = -1.0; v1(1) = 1.0;
4736 Amat.
Mult(v1, temp);
4744 const double bbox_rel_size_inc,
4745 const double newt_tol,
4748 MFEM_VERIFY(m.
GetNodes() !=
nullptr,
"Mesh nodes are required.");
4749 const int meshOrder = m.
GetNodes()->FESpace()->GetMaxElementOrder();
4752 MFEM_VERIFY(meshOrder == gfOrder,
4753 "Mesh order must match gfmax order in OversetFindPointsGSLIB.");
4763 unsigned dof1D = fe->
GetOrder() + 1;
4769 MFEM_ASSERT(meshid>=0,
" The ID should be greater than or equal to 0.");
4772 NEtot = pts_cnt/(int)pow(dof1D,
dim);
4787 unsigned nr[2] = { dof1D, dof1D };
4788 unsigned mr[2] = { 2*dof1D, 2*dof1D };
4789 double *
const elx[2] =
4791 pts_cnt == 0 ? nullptr : &
gsl_mesh(0),
4792 pts_cnt == 0 ? nullptr : &
gsl_mesh(pts_cnt)
4795 bbox_rel_size_inc, pts_cnt, pts_cnt,
4801 unsigned nr[3] = { dof1D, dof1D, dof1D };
4802 unsigned mr[3] = { 2*dof1D, 2*dof1D, 2*dof1D };
4803 double *
const elx[3] =
4805 pts_cnt == 0 ? nullptr : &
gsl_mesh(0),
4806 pts_cnt == 0 ? nullptr : &
gsl_mesh(pts_cnt),
4807 pts_cnt == 0 ? nullptr : &
gsl_mesh(2*pts_cnt)
4810 bbox_rel_size_inc, pts_cnt, pts_cnt,
4820 const int point_pos_ordering)
4822 MFEM_VERIFY(
setupflag,
"Use OversetFindPointsGSLIB::Setup before "
4824 MFEM_VERIFY(
overset,
"Please use OversetFindPoints for overlapping grids.");
4826 unsigned int match = 0;
4834 auto xvFill = [&](
const double *xv_base[],
unsigned xv_stride[])
4836 for (
int d = 0; d <
dim; d++)
4841 xv_stride[d] =
sizeof(double);
4845 xv_base[d] = point_pos.
GetData() + d;
4846 xv_stride[d] =
dim*
sizeof(double);
4852 auto *findptsData = (gslib::findpts_data_2 *)this->
fdataD;
4853 const double *xv_base[2];
4854 unsigned xv_stride[2];
4855 xvFill(xv_base, xv_stride);
4862 point_id.
GetData(),
sizeof(
unsigned int), &match,
4867 auto *findptsData = (gslib::findpts_data_3 *)this->
fdataD;
4868 const double *xv_base[3];
4869 unsigned xv_stride[3];
4870 xvFill(xv_base, xv_stride);
4877 point_id.
GetData(),
sizeof(
unsigned int), &match,
4902 const int point_pos_ordering)
4904 FindPoints(point_pos, point_id, point_pos_ordering);
4911 cr =
new gslib::crystal;
4914 MPI_Comm comm = MPI_COMM_WORLD;
4925 : cr(NULL), gsl_comm(NULL)
4928 cr =
new gslib::crystal;
4951 long long minval = ids.
Min();
4953 MPI_Allreduce(MPI_IN_PLACE, &minval, 1, MPI_LONG_LONG_INT,
4956 MFEM_VERIFY(minval >= 0,
"Unique identifier cannot be negative.");
4962 gslib::gs_crystal_router, 0);
4968 "Incompatible setup and GOP operation.");
4971 gslib_gs(senddata.
GetData(),gslib::gs_double,gslib::gs_add,0,
gsl_data,0);
4975 gslib_gs(senddata.
GetData(),gslib::gs_double,gslib::gs_mul,0,
gsl_data,0);
4979 gslib_gs(senddata.
GetData(),gslib::gs_double,gslib::gs_max,0,
gsl_data,0);
4983 gslib_gs(senddata.
GetData(),gslib::gs_double,gslib::gs_min,0,
gsl_data,0);
4987 MFEM_ABORT(
"Invalid GSOp operation.");
4991#if defined(MFEM_USE_MPI)
4992void GlobalBBoxTensorGridMap::SetupCrystal(
const MPI_Comm &comm_)
4994#if GSLIB_RELEASE_VERSION < 10009
4995 MFEM_ABORT(
"GSLIB version 1.0.9 or higher is required.");
4997 gsl_comm =
new gslib::comm;
4998 cr =
new gslib::crystal;
4999 comm_init(gsl_comm, comm_);
5000 gslib::crystal_init(cr, gsl_comm);
5006 const int nel = pmesh.
GetNE();
5008 Vector elmin(nel*sdim), elmax(nel*sdim);
5009 elmin = std::numeric_limits<real_t>::max();
5010 elmax = -std::numeric_limits<real_t>::max();
5016 for (
int e = 0; e < nel; e++)
5020 for (
int v = 0; v < verts.
Size(); v++)
5023 for (
int d = 0; d < sdim; d++)
5025 elmin(d*nel + e) = std::min(elmin(d*nel + e), coord[d]);
5026 elmax(d*nel + e) = std::max(elmax(d*nel + e), coord[d]);
5034 nodes->GetElementBounds(elmin, elmax, nref);
5038 Setup(pmesh.
GetComm(), elmin, elmax, nel, nx_arr);
5048 MFEM_VERIFY(0 < sdim && sdim <= 3,
5049 "GlobalBBoxTensorGridMap only supports spatial dimensions 1, 2, and 3.");
5052 MFEM_VERIFY(elmin.
Size() == sdim * nel && elmax.
Size() == sdim * nel,
5053 "Element bounds size must match dim * nel.");
5062 long long int nx = n;
5063 MPI_Allreduce(MPI_IN_PLACE, &nx, 1, MPI_LONG_LONG, MPI_SUM, comm);
5064 nx = ceil(pow((
double)nx,1./sdim));
5067 Setup(comm, elmin, elmax, nel, nx_arr);
5076 Setup(comm, elmin, elmax, nel, nx);
5079void GlobalBBoxTensorGridMap::Setup(
const MPI_Comm &comm,
5084 MFEM_VERIFY(0 < sdim && sdim <= 3,
5085 "GlobalBBoxTensorGridMap only supports spatial dimensions 1, 2, and 3.");
5086 MFEM_VERIFY(nx.
Size() == sdim,
5087 "GlobalBBoxTensorGridMap requires nx to have the same size as the number of dimensions.");
5090 MFEM_VERIFY(elmin.
Size() == sdim * nel && elmax.
Size() == sdim * nel,
5091 "Element bounds size must match dim * nel.");
5099 long long int global_nel = nel;
5100 MPI_Allreduce(MPI_IN_PLACE, &global_nel, 1, MPI_LONG_LONG, MPI_SUM, comm);
5102 MPI_Comm_size(comm, &num_procs);
5103 int gmap_nd = gmap_n[0];
5104 for (
int d = 1; d < sdim; d++)
5106 gmap_nd *= gmap_n[d];
5109 if (global_nel == 0)
5119 n_local_cells = (gmap_nd - 1) / num_procs + 1;
5120 ggrid_map.
SetSize(n_local_cells + 1);
5121 ggrid_map = n_local_cells + 1;
5125 for (
int d = 0; d < nx.
Size(); d++)
5127 MFEM_VERIFY(nx[d] > 0,
5128 "GlobalBBoxTensorGridMap requires positive number of divisions in each dimension.");
5130 gmap_bnd_min = std::numeric_limits<real_t>::max();
5131 gmap_bnd_max = -std::numeric_limits<real_t>::max();
5134 for (
int d = 0; d < sdim; d++)
5136 Vector elmind(elmin.
GetData() + d*nel, nel);
5137 Vector elmaxd(elmax.
GetData() + d*nel, nel);
5138 gmap_bnd_min[d] = elmind.
Min();
5139 gmap_bnd_max[d] = elmaxd.
Max();
5143 Vector gmap_bnd_min_loc = gmap_bnd_min;
5144 Vector gmap_bnd_max_loc = gmap_bnd_max;
5146 MPI_Allreduce(MPI_IN_PLACE, gmap_bnd_min.
GetData(), sdim,
5147 MFEM_MPI_REAL_T, MPI_MIN, comm);
5148 MPI_Allreduce(MPI_IN_PLACE, gmap_bnd_max.
GetData(), sdim,
5149 MFEM_MPI_REAL_T, MPI_MAX, comm);
5154 Array<int> elmin_h, elmax_h;
5161 Array<int> loc_idx_min(sdim), loc_idx_max(sdim), lh_n(sdim);
5162 int loc_idx_tot = 1;
5166 for (
int d = 0; d < sdim; d++)
5170 gmap_bnd_min_loc[d],
5171 gmap_bnd_max_loc[d],
5172 loc_idx_min[d], loc_idx_max[d]);
5173 lh_n[d] = loc_idx_max[d] - loc_idx_min[d];
5174 loc_idx_tot *= lh_n[d];
5186 unsigned int index, proc;
5188 struct gslib::array hashInfo_pt;
5189 array_init(
struct hashInfo_s, &hashInfo_pt, store_size);
5190 hashInfo_pt.n=store_size;
5192 struct hashInfo_s *pt = (
struct hashInfo_s *)hashInfo_pt.ptr;
5193 Array<int> marker(loc_idx_tot);
5196 for (
int e = 0; e < nel; e++)
5198 int klim = sdim < 3 ? 1 : (elmax_h[2*nel+e]-elmin_h[2*nel+e]);
5199 int jlim = sdim < 2 ? 1 : (elmax_h[1*nel+e]-elmin_h[1*nel+e]);
5200 int ilim = (elmax_h[0*nel+e]-elmin_h[0*nel+e]);
5201 for (
int k = 0; k < klim; k++)
5203 int koff = sdim < 3 ? 0 : (elmin_h[2*nel+e] + k) * gmap_n[0] * gmap_n[1];
5204 int koff_loc = sdim < 3 ? 0 :
5205 (elmin_h[2*nel+e]+k - loc_idx_min[2])*lh_n[0] * lh_n[1];
5206 for (
int j = 0; j < jlim; j++)
5208 int joff = sdim < 2 ? 0 : (elmin_h[1*nel + e] + j) * gmap_n[0];
5209 int joff_loc = sdim < 2 ? 0 :
5210 (elmin_h[1*nel+e]+j - loc_idx_min[1])*lh_n[0];
5211 for (
int i = 0; i < ilim; i++)
5213 int ioff = elmin_h[0*nel + e] + i;
5214 int ioff_loc = elmin_h[0*nel+e]+i - loc_idx_min[0];
5215 int idx = ioff + joff + koff;
5216 int idx_loc = ioff_loc + joff_loc + koff_loc;
5217 if (marker[idx_loc] == 1) {
continue; }
5218 pt->proc = idx % num_procs;
5219 pt->index = idx / num_procs;
5220 marker[idx_loc] = 1;
5227 int npts = marker.Sum();
5228 hashInfo_pt.n = npts;
5231#if GSLIB_RELEASE_VERSION >= 10009
5232 sarray_transfer(
struct hashInfo_s, &hashInfo_pt, proc, 1, cr);
5233 sarray_sort(
struct hashInfo_s, hashInfo_pt.ptr, hashInfo_pt.n,
5234 index, 0, &(cr->data));
5237 int nrecv = hashInfo_pt.n;
5239 n_local_cells = (gmap_nd-1)/num_procs+1;
5240 ggrid_map.
SetSize(n_local_cells + 1 + nrecv);
5242 Array<int> hash_el_count(n_local_cells);
5245 pt = (
struct hashInfo_s *)hashInfo_pt.ptr;
5246 for (
int i = 0; i < nrecv; i++)
5248 int idx = pt->index;
5249 hash_el_count[idx]++;
5253 ggrid_map[0] = n_local_cells + 1;
5254 for (
int e = 0; e < n_local_cells; e++)
5256 ggrid_map[e + 1] = ggrid_map[e] + hash_el_count[e];
5259 pt = (
struct hashInfo_s *)hashInfo_pt.ptr;
5260 for (
int i = 0; i < nrecv; i++)
5262 int idx = pt->index;
5263 int proc = pt->proc;
5264 ggrid_map[ggrid_map[idx+1]-hash_el_count[idx]]=proc;
5265 hash_el_count[idx]--;
5269 array_free(&hashInfo_pt);
5273int GlobalBBoxTensorGridMap::GetGlobalGridCellFromPoint(Vector &xyz)
const
5275 MFEM_ASSERT(xyz.Size() == sdim,
5276 "Point must have the same dimension as the hash.");
5278 for (
int d = sdim-1; d >= 0; --d)
5280 if (xyz(d) < gmap_bnd_min(d) || xyz(d) > gmap_bnd_max(d))
5285 int i = (int)floor((xyz(d) - gmap_bnd_min(d)) * gmap_fac[d]);
5286 sum += i < 0 ? 0 : (gmap_n[d] - 1 < i ? gmap_n[d] - 1 : i);
5291void GlobalBBoxTensorGridMap::GlobalGridCellToProcAndLocalIndex(
int i,
5295 proc = i % num_procs;
5296 idx = i / num_procs;
5299void GlobalBBoxTensorGridMap::GetProcAndLocalIndexFromPoint(Vector &xyz,
5300 int &proc,
int &idx)
const
5302 int cell = GetGlobalGridCellFromPoint(xyz);
5309 GlobalGridCellToProcAndLocalIndex(cell, proc, idx);
5314 std::vector<int>> &pt_to_procs)
const
5316 MFEM_ASSERT(xyz.
Size() % sdim == 0,
5317 "Point array size must be a multiple of the grid dimension.");
5318 int npts = xyz.
Size() / sdim;
5319 pt_to_procs.clear();
5320 for (
int i = 0; i < npts; i++)
5332 unsigned int info, proc, loc_index;
5334 struct gslib::array ptInfo_pt;
5335 array_init(
struct ptInfo_s, &ptInfo_pt, npts);
5336 struct ptInfo_s *pt = (
struct ptInfo_s *)ptInfo_pt.ptr;
5337 struct ptInfo_s *pt_begin = pt;
5339 for (
int i = 0; i < npts; i++)
5342 for (
int d = 0; d < sdim; d++)
5344 pt_xyz(d) = ordering == 0 ? xyz(d*npts + i) : xyz(i*sdim + d);
5347 int cell = GetGlobalGridCellFromPoint(pt_xyz);
5353 GlobalGridCellToProcAndLocalIndex(cell, proc, idx);
5359 ptInfo_pt.n = pt - pt_begin;
5360 MPI_Barrier(gsl_comm->c);
5363 sarray_transfer(
struct ptInfo_s, &ptInfo_pt, proc, 1, cr);
5365 int nrecv = ptInfo_pt.n;
5366 pt = (
struct ptInfo_s *)ptInfo_pt.ptr;
5368 for (
int i = 0; i < nrecv; i++)
5371 int loc_count = ggrid_map[idx+1]-ggrid_map[idx];
5372 ncount += loc_count;
5376 struct gslib::array sendptInfo_pt;
5377 array_init(
struct ptInfo_s, &sendptInfo_pt, ncount);
5378 sendptInfo_pt.n=ncount;
5379 struct ptInfo_s *spt = (
struct ptInfo_s *)sendptInfo_pt.ptr;
5380 pt = (
struct ptInfo_s *)ptInfo_pt.ptr;
5382 for (
int i = 0; i < nrecv; i++)
5385 for (
int k = 0; k < procs.
Size(); k++)
5387 spt->info = procs[k];
5388 spt->proc = pt->proc;
5389 spt->loc_index = pt->loc_index;
5395 array_free(&ptInfo_pt);
5397 sarray_transfer(
struct ptInfo_s, &sendptInfo_pt, proc, 1, cr);
5399 nrecv = sendptInfo_pt.n;
5400 spt = (
struct ptInfo_s *)sendptInfo_pt.ptr;
5402 for (
int i =0; i < nrecv; i++)
5404 int pt_idx = spt->loc_index;
5405 int proc = spt->info;
5406 pt_to_procs[pt_idx].push_back(proc);
5410 array_free(&sendptInfo_pt);
5411 MPI_Barrier(gsl_comm->c);
5414Array<int> GlobalBBoxTensorGridMap::MapCellToProcs(
int l_idx)
const
5416 MFEM_ASSERT(l_idx >= 0 && l_idx < n_local_cells,
5417 "Access element " << l_idx <<
" of local hash with cells = "
5419 int start = ggrid_map[l_idx];
5420 int end = ggrid_map[l_idx + 1];
5422 for (
int j = start; j < end; j++)
5424 elements[j - start] = ggrid_map[j];
5434 comm_free(gsl_comm);
5445#undef CODE_NOT_FOUND
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
T * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
int Size() const
Return the logical size of the array.
void DeleteAll()
Delete the whole array.
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T * GetData()
Returns the data.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
Map a point in physical space to candidate elements of a curved mesh.
const Array< int > & GetGridN() const
Return the grid resolution (number of cells) in each direction.
static void GetGridRange(const int d, const Array< int > &lh_n, const Vector &lh_fac, const Vector &lh_bnd_min, const real_t &xmin, const real_t &xmax, int &imin, int &imax)
Get local (1D) indices for cells of tensor grid that intersect with the given bounding box.
const Vector & GetGridFac() const
Return the number of grid cells per unit extent in each direction.
static void SetGridFac(Vector &lh_fac, const Array< int > &nx, const Vector &lh_bnd_min, const Vector &lh_bnd_max)
Set grid fac - number of grid cells per unit grid extent.
const Vector & GetGridMin() const
Return the minimum extent of the grid in each direction.
static int GetGridCountAndRange(const Array< int > &lh_n, const Vector &lh_fac, const Vector &lh_bnd_min, const Vector &lh_bnd_max, const Vector &elmin, const Vector &elmax, Array< int > &elmin_h, Array< int > &elmax_h)
Get grid count and range - total number of grid cells that intersect with all elements of the mesh an...
const Array< unsigned int > & GetGridMap() const
@ GaussLobatto
Closed type.
Data type dense matrix using column-major storage.
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
void Invert()
Replaces the current matrix with its inverse.
Rank 3 tensor (array of matrices)
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
Geometry::Type GetGeometryType() const
Type
Constants for the classes derived from Element.
FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary collection of points....
virtual void DistributePointInfoToOwningMPIRanks(Array< unsigned int > &recv_elem, Vector &recv_ref, Array< unsigned int > &recv_code)
void GetAxisAlignedBoundingBoxes(Vector &aabb) const
virtual ~FindPointsGSLIB()
void FindPointsEdgeLocal2(const Vector &point_pos, int point_pos_ordering, Array< unsigned int > &gsl_code_dev_l, Array< unsigned int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &gsl_dist_l, int npt)
FindPoints locally on device for 2D edge elements.
void FindPointsOnDevice(const Vector &point_pos, const int point_pos_ordering=Ordering::byNODES)
Searches positions given in physical space by point_pos. These positions can be ordered byNodes: (XXX...
Array< unsigned int > gsl_code
Array< Mesh * > mesh_split
virtual void GetNodalValues(const GridFunction *gf_in, Vector &node_vals, const Array< IntegrationRule * > *ir_in=nullptr, bool by_element=false) const
Get GridFunction value at the points expected by GSLIB.
virtual void InterpolateGeneral(const GridFunction &field_in, Vector &field_out, const int field_out_ordering)
virtual void InterpolateH1(const GridFunction &field_in, Vector &field_out, const int field_out_ordering)
void FindPoints(const Vector &point_pos, int point_pos_ordering=Ordering::byNODES)
Searches positions given in physical space by point_pos.
void Setup(Mesh &m, const double bbox_rel_size_inc=0.1, const double newt_tol=1.0e-12, const int npt_max=256)
Preprocess the internal mesh in gslib.
void FindPointsSurfSetup3(DevStruct &devs, const double *const elx[3], const unsigned n, const unsigned int nel, const unsigned m, const double bbox_rel_size_inc, const unsigned int local_hash_size, const unsigned int global_hash_size, const int rD, const Vector *aabb_sz_inc)
Preprocess 3D surface mesh needed for FindPoints.
void FindPointsLocal3(const Vector &point_pos, int point_pos_ordering, Array< unsigned int > &gsl_code_dev_l, Array< unsigned int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &gsl_dist_l, int npt)
FindPoints locally on device for 3D.
void SetupSurf(Mesh &m, const double bbox_rel_size_inc=0.1, const double newt_tol=1.0e-12)
Preprocess the surface mesh to compute data for FindPoints.
Array< int > split_element_geom
virtual void Interpolate(const GridFunction &field_in, Vector &field_out)
Interpolation of field values at prescribed reference space positions.
Array< FiniteElementSpace * > fes_rst_map
Mesh * GetBoundingBoxMesh(int type)
Return the bounding boxes as a mesh on rank 0.
Array< int > split_element_index
FiniteElementCollection * fec_map_lin
FindPointsGSLIB()
Serial constructor.
virtual void DistributeInterpolatedValues(const Vector &int_vals, const int vdim, const int ordering, Vector &field_out) const
struct gslib::comm * gsl_comm
Array< unsigned int > gsl_elem
Array< unsigned int > recv_proc
virtual void SetupSplitMeshesAndIntegrationRules(const int order)
Helper function that calls SetupSplitMeshes and SetupIntegrationRules.
Array< unsigned int > gsl_proc
virtual void SetupIntegrationRuleForSplitMesh(Mesh *mesh, IntegrationRule *irule, int order)
Setup integration points that will be used to interpolate the nodal location at points expected by GS...
void InterpolateLocal3(const Vector &field_in, Array< int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &field_out, int npt, int ncomp, int dof1dsol)
Interpolate on device for 3D.
Array< unsigned int > gsl_mfem_elem
Array< IntegrationRule * > ir_split
void FindPointsEdgeLocal3(const Vector &point_pos, int point_pos_ordering, Array< unsigned int > &gsl_code_dev_l, Array< unsigned int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &gsl_dist_l, int npt)
FindPoints locally on device for 3D edge elements.
void GetOrientedBoundingBoxes(DenseTensor &obbA, Vector &obbC, Vector &obbV) const
double default_interp_value
void FindPointsEdgeSetup2(DevStruct &devs, const double *const elx[2], const unsigned n, const unsigned int nel, const unsigned m, const double bbox_rel_size_inc, const unsigned int local_hash_size, const unsigned int global_hash_size, const Vector *aabb_sz_inc)
Preprocess 2D surface mesh needed for FindPoints.
Array< IntegrationRule * > ir_split_sol
virtual void SetupSplitMeshes()
Since GSLIB is designed to work with quads/hexes, we split every triangle/tet/prism/pyramid element i...
virtual void MapRefPosAndElemIndices()
Map {r,s,t} coordinates from [-1,1] to [0,1] for MFEM. For simplices, find the original element numbe...
virtual void FreeData()
Cleans up memory allocated internally by gslib.
virtual void InterpolateSurf(const GridFunction &field_in, Vector &field_out)
Same as Interpolate but for surface meshes.
Array< unsigned int > GetPointsNotFoundIndices() const
Get array of indices of not-found points.
void InterpolateLocal1(const Vector &field_in, Array< int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &field_out, int npt, int ncomp, int dof1dsol)
Interpolate on device for 1D.
void SetupSurfWithAABBExpansion(Mesh &m, const Vector &aabb_sz_inc, const double newt_tol=1.0e-12)
Preprocess the surface mesh to compute data for FindPoints using absolute AABB expansion.
Array< GridFunction * > gf_rst_map
void FindPointsSurfLocal3(const Vector &point_pos, int point_pos_ordering, Array< unsigned int > &gsl_code_dev_l, Array< unsigned int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &gsl_dist_l, int npt)
FindPoints locally on device for 3D surface elements.
Array< int > split_element_map
void SetupSurfBase(Mesh &m, const double bbox_rel_size_inc, const Vector *aabb_sz_inc, const double newt_tol)
Shared implementation for the public surface-setup methods.
void FindPointsSurf(const Vector &point_pos, int point_pos_ordering=Ordering::byNODES)
Searches positions given in physical space by point_pos on surface mesh.
void InterpolateOnDevice(const Vector &field_in_evec, Vector &field_out, const int nel, const int ncomp, const int dof1dsol, const int ordering)
Interpolation of field values at prescribed reference space positions.
Array< unsigned int > recv_index
struct mfem::FindPointsGSLIB::DevStruct DEV
int ir_split_sol_order
Order at which ir_split_sol was built; -1 means not built.
void InterpolateLocal2(const Vector &field_in, Array< int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &field_out, int npt, int ncomp, int dof1dsol)
Interpolate on device for 2D.
void FindPointsLocal2(const Vector &point_pos, int point_pos_ordering, Array< unsigned int > &gsl_code_dev_l, Array< unsigned int > &gsl_elem_dev_l, Vector &gsl_ref_l, Vector &gsl_dist_l, int npt)
FindPoints locally on device for 2D.
virtual void SetupIntegrationRules(const int order, Array< IntegrationRule * > &ir_out)
Build integration rules at the given order for each split mesh and store them in ir_out....
void SetupDevice()
Prepare data for device execution for volume meshes.
struct gslib::crystal * cr
void InterpolateSurfBase(const Vector &field_in, Vector &field_out, const int nel, const int ncomp, const int dof1dsol, const int field_out_ordering)
Interpolation of field values at prescribed reference space positions for surface meshes.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Ordering::Type GetOrdering() const
Return the ordering method.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
int GetElementOrder(int i) const
Returns the order of the i'th finite element.
void SetElementOrder(int i, int p)
Sets the order of the i'th finite element.
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
int GetVDim() const
Returns the vector dimension of the finite element space.
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
Abstract class for all finite elements.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
int GetDof() const
Returns the number of degrees of freedom in the finite element.
struct gslib::comm * gsl_comm
void GS(Vector &senddata, GSOp op)
GSOPGSLIB(Array< long long > &ids)
GSOp
Supported operation types. See class description.
struct gslib::crystal * cr
struct gslib::gs_data * gsl_data
void UpdateIdentifiers(const Array< long long > &ids)
static bool CheckPoint(int GeomType, const IntegrationPoint &ip)
Check if the given point is inside the given reference element.
Class to map a point in physical space to candidate ranks.
const Array< int > & GetGridMap() const
const Vector & GetGridFac() const
Return the number of grid cells per unit extent in each direction.
const Vector & GetGridMin() const
Return the minimum extent of the grid in each direction.
GlobalBBoxTensorGridMap(ParMesh &pmesh, int nx)
Constructor for a given mesh and number of tensor grid divisions.
void MapPointsToProcs(Vector &xyz, int ordering, std::map< int, std::vector< int > > &pt_to_procs) const
Get list of procs corresponding to the list of points.
const Array< int > & GetGridN() const
Return the grid resolution (number of cells) in each direction.
~GlobalBBoxTensorGridMap()
Class for grid function - Vector with associated FE space.
virtual real_t GetValue(int i, const IntegrationPoint &ip, int vdim=1) const
FiniteElementSpace * FESpace()
int VectorDim() const
Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying fes.
virtual void GetVectorValue(int i, const IntegrationPoint &ip, Vector &val) const
Arbitrary order H1-conforming (continuous) finite elements.
Class for integration point with weight.
void Set2(const real_t x1, const real_t x2)
void Set(const real_t x1, const real_t x2, const real_t x3, const real_t w)
void Set3(const real_t x1, const real_t x2, const real_t x3)
Class for an integration rule - an Array of IntegrationPoint.
int GetNPoints() const
Returns the number of the points in the integration rule.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Arbitrary order "L2-conforming" discontinuous finite elements.
Element::Type GetElementType(int i) const
Returns the type of element i.
static Mesh MakeCartesian1D(int n, real_t sx=1.0)
Creates 1D mesh, divided into n equal intervals.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
Adds a quadrilateral to the mesh given by 4 vertices v1 through v4.
const FiniteElementSpace * GetNodalFESpace() const
const Element * GetElement(int i) const
Return pointer to the i'th element object.
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
void FinalizeHexMesh(int generate_edges=0, int refine=0, bool fix_orientation=true)
Finalize the construction of a hexahedral Mesh.
void FinalizeQuadMesh(int generate_edges=0, int refine=0, bool fix_orientation=true)
Finalize the construction of a quadrilateral Mesh.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
void GetNodes(Vector &node_coord) const
real_t GetElementVolume(int i)
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
Adds a hexahedron to the mesh given by 8 vertices v1 through v8.
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
static bool IsFinalized()
Return true if MPI has been finalized.
static bool IsInitialized()
Return true if MPI has been initialized.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
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).
void Interpolate(const Vector &point_pos, const Array< unsigned int > &point_id, const GridFunction &field_in, Vector &field_out, const int point_pos_ordering=Ordering::byNODES)
void Setup(Mesh &m, const int meshid, GridFunction *gfmax=nullptr, const double bbox_rel_size_inc=0.1, const double newt_tol=1.0e-12, const int npt_max=256)
void FindPoints(const Vector &point_pos, const Array< unsigned int > &point_id, const int point_pos_ordering=Ordering::byNODES)
Abstract parallel finite element space.
Class for parallel meshes.
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Vector coefficient defined by a vector GridFunction.
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
real_t Max() const
Returns the maximal element of the vector.
void Destroy()
Destroy a vector.
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void SetSize(int s)
Resize the vector to size s.
virtual real_t * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
void NewDataAndSize(real_t *d, int s)
Set the Vector data and size, deleting the old data, if owned.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
virtual real_t * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
real_t Min() const
Returns the minimal element of the vector.
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).
int index(int i, int j, int nx, int ny)
ulong hash_index_2(const gslib::hash_data_2 *p, const double x[2])
real_t u(const Vector &xvec)
ulong hash_index_1(double low, double fac, ulong n, double x)
ulong hash_index_3(const gslib::hash_data_3 *p, const double x[3])
void obboxsurf_calc_3(Vector &bb, const double *const elx[3], const unsigned n, uint nel, const unsigned m, const double tol, const bool store_obb)
ulong hash_index_nd(const Vector &hash_min, const Vector &hash_fac, const int n, const Vector &x)
double dbl_range_diag_expand_2(struct gslib::dbl_range *b, double tol)
double dbl_range_diag_expand_3(struct gslib::dbl_range *b, double tol)
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
void obboxedge_calc_2(Vector &bb, const double *const elx[2], const unsigned nr, uint nel, const unsigned mr, const double tol, const bool store_obb)
const T & AsConst(const T &a)
Utility function similar to std::as_const in c++17.
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
void forall(int N, lambda &&body)
void obboxedge_calc_3(Vector &bb, const double *const elx[3], const unsigned nr, uint nel, const unsigned mr, const double tol, const bool store_obb)
real_t p(const Vector &x, real_t t)
struct gslib::hash_data_3 * hash3
Array< unsigned int > lh_offset
struct gslib::crystal * cr
Array< unsigned int > gh_offset
struct gslib::hash_data_2 * hash2
std::array< int, NCMesh::MaxFaceNodes > nodes