18#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
19#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wunused-function"
23#ifndef GSLIB_RELEASE_VERSION
24#define GSLIB_RELEASE_VERSION 10007
26#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
27#pragma GCC diagnostic pop
31#if GSLIB_RELEASE_VERSION >= 10009
32#define CODE_INTERNAL 0
34#define CODE_NOT_FOUND 2
41 double x[
DIM], r[
DIM], oldr[
DIM], dist2, dist2p, tr;
47 double *x[
DIM], *dxdn[
DIM];
61using obbox_t = gslib::obbox_t<DIM>;
71static MFEM_HOST_DEVICE
inline void lin_solve_3(
double x[3],
const double A[9],
74 const double a = A[4]*A[8]-A[5]*A[7],
b = A[5]*A[6]-A[3]*A[8],
75 c = A[3]*A[7]-A[4]*A[6],
76 idet = 1 / (A[0]*
a+A[1]*
b+A[2]*c);
77 const double inv0 =
a, inv1 = A[2]*A[7]-A[1]*A[8],
78 inv2 = A[1]*A[5]-A[2]*A[4], inv3 =
b,
79 inv4 = A[0]*A[8]-A[2]*A[6], inv5 = A[2]*A[3]-A[0]*A[5],
80 inv6 = c, inv7 = A[1]*A[6]-A[0]*A[7],
81 inv8 = A[0]*A[4]-A[1]*A[3];
82 x[0] = idet*(inv0*y[0]+inv1*y[1]+inv2*y[2]);
83 x[1] = idet*(inv3*y[0]+inv4*y[1]+inv5*y[2]);
84 x[2] = idet*(inv6*y[0]+inv7*y[1]+inv8*y[2]);
95#define CONVERGED_FLAG (1u << 6)
96#define FLAG_MASK 0x7fu
99static MFEM_HOST_DEVICE
inline int num_constrained(
const int flags)
101 const int y = flags | flags >> 1;
102 return (y & 1u)+(y >> 2 & 1u)+(((3 == 2) | y >> 4) & 1u);
106static MFEM_HOST_DEVICE
inline int plus_1_mod_3(
const int x)
108 return ((x | x >> 1)+1) & 3u;
110static MFEM_HOST_DEVICE
inline int plus_2_mod_3(
const int x)
112 const int y = (x-1) & 3u;
117static MFEM_HOST_DEVICE
inline int which_bit(
const int x)
119 const int y = x & 7u;
120 return (y-(y >> 2)) | ((x-1) & 4u) | (x >> 4);
124static MFEM_HOST_DEVICE
inline int face_index(
const int x)
126 return which_bit(x)-1;
130static MFEM_HOST_DEVICE
inline int edge_index(
const int x)
132 const int y = ~((x >> 1) | x);
133 const int RTSR = ((x >> 1) & 1u) | ((x >> 2) & 2u) |
134 ((x >> 3) & 4u) | ((x << 2) & 8u);
135 const int re = RTSR >> 1;
136 const int se = 4u | RTSR >> 2;
137 const int te = 8u | (RTSR & 3u);
138 return ((0
u-(y & 1u)) & re) | ((0
u-((y >> 2) & 1u)) & se) |
139 ((0
u-((y >> 4) & 1u)) & te);
143static MFEM_HOST_DEVICE
inline int point_index(
const int x)
145 return ((x >> 1) & 1u) | ((x >> 2) & 2u) | ((x >> 3) & 4u);
150static MFEM_HOST_DEVICE
inline findptsElemFace
151get_face(
const double *elx[3],
const double *wtend,
int fi,
double *workspace,
152 int &side_init,
int jidx,
int pN)
154 const int dn = fi >> 1, d1 = plus_1_mod_3(dn), d2 = plus_2_mod_3(dn);
155 const int side_n = fi & 1;
156 const int p_Nfr = pN*pN;
157 findptsElemFace face;
158 const int jj = jidx % pN;
159 const int dd = jidx / pN;
160 for (
int d = 0; d < 3; ++d)
162 face.x[d] = workspace+d*p_Nfr;
163 face.dxdn[d] = workspace+(3+d)*p_Nfr;
166 if (
static_cast<unsigned>(side_init) != (1u << fi))
168 const int e_stride[3] = {1, pN, pN*pN};
169#define ELX(d, j, k, l) elx[d][j*e_stride[d1]+k*e_stride[d2]+l*e_stride[dn]]
170 for (
int k = 0; k < pN; ++k)
173 face.x[dd][jj+k*pN] = ELX(dd, jj, k, side_n*(pN-1));
177 for (
int l = 0; l < pN; ++l)
179 sum_l += wtend[pN+l]*ELX(dd, jj, k, l);
181 face.dxdn[dd][jj+k*pN] = sum_l;
190static MFEM_HOST_DEVICE
inline findptsElemEdge
191get_edge(
const double *elx[3],
const double *wtend,
int ei,
double *workspace,
192 int &side_init,
int jidx,
int pN)
194 findptsElemEdge edge;
195 const int de = ei >> 2, dn1 = plus_1_mod_3(de), dn2 = plus_2_mod_3(de);
196 const int side_n1 = ei & 1, side_n2 = (ei & 2) >> 1;
198 const int in1 = side_n1*(pN-1), in2 = side_n2*(pN-1);
199 const double *wt1 = wtend+side_n1*pN*3;
200 const double *wt2 = wtend+side_n2*pN*3;
201 const int jj = jidx % pN;
202 const int dd = jidx / pN;
203 for (
int d = 0; d < 3; ++d)
205 edge.x[d] = workspace+d*pN;
206 edge.dxdn1[d] = workspace+(3+d)*pN;
207 edge.dxdn2[d] = workspace+(6+d)*pN;
208 edge.d2xdn1[d] = workspace+(9+d)*pN;
209 edge.d2xdn2[d] = workspace+(12+d)*pN;
212 if (jidx >= 3*pN) {
return edge; }
214 if (
static_cast<unsigned>(side_init) != (64u << ei))
216 const int e_stride[3] = {1, pN, pN*pN};
217#define ELX(d, j, k, l) elx[d][j*e_stride[de]+k*e_stride[dn1]+l*e_stride[dn2]]
219 edge.x[dd][jj] = ELX(dd, jj, in1, in2);
222 double sums_k[2] = {0, 0};
223 for (
int k = 0; k < pN; ++k)
225 sums_k[0] += wt1[pN+k]*ELX(dd, jj, k, in2);
226 sums_k[1] += wt1[2*pN+k]*ELX(dd, jj, k, in2);
228 edge.dxdn1[dd][jj] = sums_k[0];
229 edge.d2xdn1[dd][jj] = sums_k[1];
232 sums_k[0] = 0, sums_k[1] = 0;
233 for (
int k = 0; k < pN; ++k)
235 sums_k[0] += wt2[pN+k]*ELX(dd, jj, in1, k);
236 sums_k[1] += wt2[2*pN+k]*ELX(dd, jj, in1, k);
238 edge.dxdn2[dd][jj] = sums_k[0];
239 edge.d2xdn2[dd][jj] = sums_k[1];
246static MFEM_HOST_DEVICE
inline findptsElemPt get_pt(
const double *elx[3],
250 const int side_n1 = pi & 1, side_n2 = (pi >> 1) & 1, side_n3 = (pi >> 2) & 1;
251 const int in1 = side_n1*(pN-1), in2 = side_n2*(pN-1),
252 in3 = side_n3*(pN-1);
253 const int hes_stride = (3+1)*3 / 2;
256#define ELX(d, j, k, l) elx[d][j+k*pN+l*pN*pN]
257 for (
int d = 0; d < 3; ++d)
259 pt.x[d] = ELX(d, side_n1*(pN-1), side_n2*(pN-1),
262 const double *wt1 = wtend+pN*(1+3*side_n1);
263 const double *wt2 = wtend+pN*(1+3*side_n2);
264 const double *wt3 = wtend+pN*(1+3*side_n3);
266 for (
int i = 0; i < 3; ++i)
270 for (
int i = 0; i < hes_stride; ++i)
272 pt.hes[hes_stride*d+i] = 0;
275 for (
int j = 0; j < pN; ++j)
277 pt.jac[3*d+0] += wt1[j]*ELX(d, j, in2, in3);
278 pt.hes[hes_stride*d] += wt1[pN+j]*ELX(d, j, in2, in3);
281 const int hes_off = hes_stride*d+hes_stride / 2;
282 for (
int k = 0; k < pN; ++k)
284 pt.jac[3*d+1] += wt2[k]*ELX(d, in1, k, in3);
285 pt.hes[hes_off] += wt2[pN+k]*ELX(d, in1, k, in3);
288 for (
int l = 0; l < pN; ++l)
290 pt.jac[3*d+2] += wt3[l]*ELX(d, in1, in2, l);
291 pt.hes[hes_stride*d+5] += wt3[pN+l]*ELX(d, in1, in2, l);
294 for (
int l = 0; l < pN; ++l)
296 double sum_k = 0, sum_j = 0;
297 for (
int k = 0; k < pN; ++k)
299 sum_k += wt2[k]*ELX(d, in1, k, l);
301 for (
int j = 0; j < pN; ++j)
303 sum_j += wt1[j]*ELX(d, j, in2, l);
305 pt.hes[hes_stride*d+2] += wt3[l]*sum_j;
306 pt.hes[hes_stride*d+4] += wt3[l]*sum_k;
308 for (
int k = 0; k < pN; ++k)
311 for (
int j = 0; j < pN; ++j)
313 sum_j += wt1[j]*ELX(d, j, k, in3);
315 pt.hes[hes_stride*d+1] += wt2[k]*sum_j;
326static MFEM_HOST_DEVICE
bool reject_prior_step_q(findptsPt *res,
327 const double resid[3],
331 const double dist2 = l2norm2<3>(resid);
332 const double decr =
p->dist2-dist2;
333 const double pred =
p->dist2p;
334 for (
int d = 0; d < 3; ++d)
337 res->oldr[d] =
p->r[d];
340 if (decr >= 0.01*pred)
342 if (decr >= 0.9*pred)
360 double v0 = fabs(
p->r[0]-
p->oldr[0]);
361 double v1 = fabs(
p->r[1]-
p->oldr[1]);
362 double v2 = fabs(
p->r[2]-
p->oldr[2]);
363 res->tr = (v1 > v2 ? (v0 > v1 ? v0 : v1) : (v0 > v2 ? v0 : v2)) / 4;
364 res->dist2 =
p->dist2;
365 for (
int d = 0; d < 3; ++d)
367 res->r[d] =
p->oldr[d];
369 res->flags =
p->flags >> 7;
370 res->dist2p = -HUGE_VAL;
371 if (pred < dist2*tol)
373 res->flags |= CONVERGED_FLAG;
381static MFEM_HOST_DEVICE
void newton_vol(findptsPt *
const res,
383 const double resid[3],
384 const findptsPt *
const p,
387 const double tr =
p->tr;
388 double bnd[6] = {-1, 1, -1, 1, -1, 1};
392 r0[0] =
p->r[0], r0[1] =
p->r[1], r0[2] =
p->r[2];
395 for (d = 0; d < 3; ++d)
399 bnd[2*d] = r0[d]-
tr, mask ^= 1u << (2*d);
403 bnd[2*d+1] = r0[d]+
tr, mask ^= 2u << (2*d);
407 lin_solve_3(dr, jac, resid);
410 for (d = 0; d < 3; ++d)
412 double nr = r0[d]+dr[d];
413 if ((nr-bnd[2*d])*(bnd[2*d+1]-nr) >= 0)
419 double f = (bnd[2*d]-r0[d]) / dr[d];
422 fac =
f, flags = 1u << (2*d);
427 double f = (bnd[2*d+1]-r0[d]) / dr[d];
430 fac =
f, flags = 2u << (2*d);
440 for (d = 0; d < 3; ++d)
447 const int fi = face_index(flags);
448 const int dn = fi >> 1, d1 = plus_1_mod_3(dn), d2 = plus_2_mod_3(dn);
449 double drc[2], facc = 1;
451 double ress[3], y[2], JtJ[3];
452 ress[0] = resid[0]-(jac[0]*dr[0]+jac[1]*dr[1]+jac[2]*dr[2]);
453 ress[1] = resid[1]-(jac[3]*dr[0]+jac[4]*dr[1]+jac[5]*dr[2]);
454 ress[2] = resid[2]-(jac[6]*dr[0]+jac[7]*dr[1]+jac[8]*dr[2]);
456 y[0] = jac[d1]*ress[0]+jac[3+d1]*ress[1]+jac[6+d1]*ress[2];
457 y[1] = jac[d2]*ress[0]+jac[3+d2]*ress[1]+jac[6+d2]*ress[2];
459 JtJ[0] = jac[d1]*jac[d1]+jac[3+d1]*jac[3+d1] +
460 jac[6+d1]*jac[6 +d1];
461 JtJ[1] = jac[d1]*jac[d2]+jac[3+d1]*jac[3+d2] +
463 JtJ[2] = jac[d2]*jac[d2]+jac[3+d2]*jac[3+d2] +
465 lin_solve_sym_2(drc, JtJ, y);
466#define CHECK_CONSTRAINT(drcd, d3) \
468 const double rz = r0[d3]+dr[d3], lb = bnd[2*d3], ub = bnd[2*d3+1]; \
469 const double delta = drcd, nr = r0[d3]+(dr[d3]+delta); \
470 if ((nr-lb)*(ub-nr) < 0) { \
472 double f = (lb-rz) / delta; \
474 fac = f; new_flags = 1u << (2*d3); \
478 double f = (ub-rz) / delta; \
480 fac = f; new_flags = 2u << (2*d3); \
485 CHECK_CONSTRAINT(drc[0], d1);
486 CHECK_CONSTRAINT(drc[1], d2);
487 dr[d1] += facc*drc[0], dr[d2] += facc*drc[1];
497 const int ei = edge_index(flags);
498 const int de = ei >> 2;
501 double ress[3], y, JtJ, drc;
502 ress[0] = resid[0]-(jac[0]*dr[0]+jac[1]*dr[1]+jac[2]*dr[2]);
503 ress[1] = resid[1]-(jac[3]*dr[0]+jac[4]*dr[1]+jac[5]*dr[2]);
504 ress[2] = resid[2]-(jac[6]*dr[0]+jac[7]*dr[1]+jac[8]*dr[2]);
506 y = jac[de]*ress[0]+jac[3+de]*ress[1]+jac[6+de]*ress[2];
508 JtJ = jac[de]*jac[de]+jac[3+de]*jac[3+de] +
511 CHECK_CONSTRAINT(drc, de);
512#undef CHECK_CONSTRAINT
515 goto newton_vol_relax;
521 const int old_flags = flags;
522 double ress[3], y[3];
524 ress[0] = resid[0]-(jac[0]*dr[0]+jac[1]*dr[1]+jac[2]*dr[2]);
525 ress[1] = resid[1]-(jac[3]*dr[0]+jac[4]*dr[1]+jac[5]*dr[2]);
526 ress[2] = resid[2]-(jac[6]*dr[0]+jac[7]*dr[1]+jac[8]*dr[2]);
528 y[0] = jac[0]*ress[0]+jac[3]*ress[1]+jac[6]*ress[2];
529 y[1] = jac[1]*ress[0]+jac[4]*ress[1]+jac[7]*ress[2];
530 y[2] = jac[2]*ress[0]+jac[5]*ress[1]+jac[8]*ress[2];
531 for (
int dd = 0; dd < 3; ++dd)
533 int f = flags >> (2*dd) & 3u;
536 dr[dd] = bnd[2*dd+(
f-1)]-r0[dd];
537 if (dr[dd]*y[dd] < 0)
539 flags &= ~(3u << (2*dd));
543 if (flags == old_flags)
547 switch (num_constrained(flags))
550 goto newton_vol_face;
552 goto newton_vol_edge;
558 if (fabs(dr[0])+fabs(dr[1])+fabs(dr[2]) < tol)
560 flags |= CONVERGED_FLAG;
563 const double res0 = resid[0]-(jac[0]*dr[0]+jac[1]*dr[1] +
565 const double res1 = resid[1]-(jac[3]*dr[0]+jac[4]*dr[1] +
567 const double res2 = resid[2]-(jac[6]*dr[0]+jac[7]*dr[1] +
569 res->dist2p = resid[0]*resid[0]+resid[1]*resid[1] +
571 (res0*res0+res1*res1+res2*res2);
573 for (
int dd = 0; dd < 3; ++dd)
575 int f = flags >> (2*dd) & 3u;
576 res->r[dd] =
f == 0 ? r0[dd]+dr[dd] : (
f == 1 ? -1 : 1);
578 res->flags = flags | ((
p->flags & FLAG_MASK) << 7);
582static MFEM_HOST_DEVICE
void newton_face(findptsPt *
const res,
584 const double rhes[3],
585 const double resid[3],
590 const findptsPt *
const p,
593 const double tr =
p->tr;
595 double r[2], dr[2] = {0, 0};
599 double A[3], y[2], r0[2];
601 A[0] = jac[d1]*jac[d1]+jac[3+d1]*jac[3+d1] +
602 jac[6+d1]*jac[6+d1]-rhes[0];
603 A[1] = jac[d1]*jac[d2]+jac[3+d1]*jac[3+d2] +
604 jac[6+d1]*jac[6+d2]-rhes[1];
605 A[2] = jac[d2]*jac[d2]+jac[3+d2]*jac[3+d2] +
606 jac[6+d2]*jac[6+d2]-rhes[2];
608 y[0] = jac[d1]*resid[0]+jac[3+d1]*resid[1]+jac[6+d1]*resid[2];
609 y[1] = jac[d2]*resid[0]+jac[3+d2]*resid[1]+jac[6+d2]*resid[2];
652 if (A[0]+A[2] <= 0 || A[0]*A[2] <= A[1]*A[1])
654 goto newton_face_constrained;
656 lin_solve_sym_2(dr, A, y);
658#define EVAL(r, s) -(y[0]*r+y[1]*s)+(r*A[0]*r+(2*r*A[1]+s*A[2])*s) / 2
659 if ((dr[0]-bnd[0])*(bnd[1]-dr[0]) >= 0 &&
660 (dr[1]-bnd[2])*(bnd[3]-dr[1]) >= 0)
662 r[0] = r0[0]+dr[0], r[1] = r0[1]+dr[1];
663 v = EVAL(dr[0], dr[1]);
664 goto newton_face_fin;
666newton_face_constrained:
667 v = EVAL(bnd[0], bnd[2]);
669 tv = EVAL(bnd[1], bnd[2]);
675 tv = EVAL(bnd[0], bnd[3]);
681 tv = EVAL(bnd[1], bnd[3]);
690 drc = (y[0]-A[1]*bnd[2]) / A[0];
691 if ((drc-bnd[0])*(bnd[1]-drc) >= 0 && (tv = EVAL(drc, bnd[2])) < v)
697 drc = (y[0]-A[1]*bnd[3]) / A[0];
698 if ((drc-bnd[0])*(bnd[1]-drc) >= 0 && (tv = EVAL(drc, bnd[3])) < v)
708 drc = (y[1]-A[1]*bnd[0]) / A[2];
709 if ((drc-bnd[2])*(bnd[3]-drc) >= 0 && (tv = EVAL(bnd[0], drc)) < v)
715 drc = (y[1]-A[1]*bnd[1]) / A[2];
716 if ((drc-bnd[2])*(bnd[3]-drc) >= 0 && (tv = EVAL(bnd[1], drc)) < v)
729 for (
int d = 0; d < 2; ++d)
731 const int f = i >> (2*d) & 3u;
738 if ((
f & (mask >> (2*d))) == 0)
740 r[d] = r0[d]+(
f == 1 ? -
tr :
tr);
744 r[d] = (
f == 1 ? -1 : 1);
745 new_flags |=
f << (2*dir[d]);
752 dr[0] = r[0]-
p->r[d1];
753 dr[1] = r[1]-
p->r[d2];
754 if (fabs(dr[0])+fabs(dr[1]) < tol)
756 new_flags |= CONVERGED_FLAG;
758 res->r[dn] =
p->r[dn];
761 res->flags = new_flags | ((
p->flags & FLAG_MASK) << 7);
765static MFEM_HOST_DEVICE
inline void newton_edge(findptsPt *
const res,
768 const double resid[3],
773 const findptsPt *
const p,
776 const double tr =
p->tr;
778 const double A = jac[de]*jac[de]+jac[3+de]*jac[3+de]+jac[6+de] *
781 const double y = jac[de]*resid[0]+jac[3+de]*resid[1]+jac[6+de] *
784 const double oldr =
p->r[de];
785 double dr, nr, tdr, tnr;
787 int new_flags = 0, tnew_flags = 0;
789#define EVAL(dr) (dr*A-2*y)*dr
796 if (fabs(dr) < tr && fabs(nr) < 1)
799 goto newton_edge_fin;
803 if ((nr = oldr-tr) > -1)
811 new_flags = flags | 1u << (2*de);
815 if ((tnr = oldr+tr) < 1)
823 tnew_flags = flags | 2u << (2*de);
832 new_flags = tnew_flags;
839 new_flags |= CONVERGED_FLAG;
842 res->r[dn1] =
p->r[dn1];
843 res->r[dn2] =
p->r[dn2];
845 res->flags = flags | new_flags | ((
p->flags & FLAG_MASK) << 7);
850static MFEM_HOST_DEVICE
void seed_j(
const double *elx[3],
861 for (
int l = 0; l < pN; ++l)
863 const double zt = z[l];
864 for (
int k = 0; k < pN; ++k)
868 const int jkl = j+k*pN+l*pN*pN;
870 for (
int d = 0; d < 3; ++d)
872 dx[d] = x[d]-elx[d][jkl];
874 const double dist2_jkl = l2norm2(dx);
875 if (dist2[j] > dist2_jkl)
877 dist2[j] = dist2_jkl;
888static MFEM_HOST_DEVICE
double tensor_ig3_j(
double *g_partials,
902 for (
int k = 0; k < pN; ++k)
906 for (
int l = 0; l < pN; ++l)
908 uJt +=
u[j+k*pN+l*pN*pN]*Jt[l];
909 uDt +=
u[j+k*pN+l*pN*pN]*Dt[l];
917 g_partials[0] = uJtJs*Dr[j];
918 g_partials[1] = uJtDs*Jr[j];
919 g_partials[2] = uDtJs*Jr[j];
923template<
int T_D1D = 0>
924static void FindPointsLocal3DKernel(
const int npt,
927 const int point_pos_ordering,
928 const double *xElemCoord,
931 const double *boxinfo,
933 const double *hashMin,
934 const double *hashFac,
935 unsigned int *hashOffset,
936 unsigned int *
const code_base,
937 unsigned int *
const el_base,
938 double *
const r_base,
939 double *
const dist2_base,
941 const double *lagcoeff,
944 const int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
945 const int D1D = T_D1D ? T_D1D : pN;
946 const int p_NE = D1D*D1D*D1D;
947 MFEM_VERIFY(MD1 <= DofQuadLimits::MAX_D1D,
948 "Increase Max allowable polynomial order.");
949 MFEM_VERIFY(D1D != 0,
"Polynomial order not specified.");
950#define MAXC(a, b) (((a) > (b)) ? (a) : (b))
951 const int nThreads = MAXC(D1D*
DIM, 15);
956 constexpr int size1 = 21*MD1+15;
958 constexpr int size2 = MAXC(MD1*MD1*6, MD1*3*5);
960 constexpr int size3 = MD1*MD1*MD1*
DIM;
962 MFEM_SHARED
double r_workspace[size1];
963 MFEM_SHARED findptsPt el_pts[2];
965 MFEM_SHARED
double constraint_workspace[size2];
966 MFEM_SHARED
int face_edge_init;
968 MFEM_SHARED
double elem_coords[MD1 <= 6 ? size3 : 1];
970 double *r_workspace_ptr;
971 findptsPt *fpt, *tmp;
972 MFEM_FOREACH_THREAD(j,x,nThreads)
974 r_workspace_ptr = r_workspace;
980 int id_x = point_pos_ordering == 0 ? i : i*
DIM;
981 int id_y = point_pos_ordering == 0 ? i+npt : i*
DIM+1;
982 int id_z = point_pos_ordering == 0 ? i+2*npt : i*
DIM+2;
983 double x_i[3] = {x[id_x], x[id_y], x[id_z]};
985 unsigned int *code_i = code_base+i;
986 double *dist2_i = dist2_base+i;
990 for (
int d = 0; d <
DIM; ++d)
992 hash.bnd[d].min = hashMin[d];
993 hash.fac[d] = hashFac[d];
995 hash.hash_n = hash_n;
996 hash.offset = hashOffset;
997 const unsigned int hi = hash_index(&hash, x_i);
998 const unsigned int *elp = hash.offset+hash.offset[hi],
999 *
const ele = hash.offset+hash.offset[hi+1];
1000 *code_i = CODE_NOT_FOUND;
1001 *dist2_i = HUGE_VAL;
1003 for (; elp != ele; ++elp)
1007 const int el = *elp;
1011 int n_box_ents = 3*
DIM+DIM2;
1012 for (
int idx = 0; idx <
DIM; ++idx)
1014 box.c0[idx] = boxinfo[n_box_ents*el+idx];
1015 box.x[idx].min = boxinfo[n_box_ents*el+
DIM+idx];
1016 box.x[idx].max = boxinfo[n_box_ents*el+2*
DIM+idx];
1019 for (
int idx = 0; idx < DIM2; ++idx)
1021 box.A[idx] = boxinfo[n_box_ents*el+3*
DIM+idx];
1024 if (bbox_test(&box, x_i) < 0) {
continue; }
1031 MFEM_FOREACH_THREAD(j,x,D1D*
DIM)
1033 const int qp = j % D1D;
1034 const int d = j / D1D;
1035 for (
int l = 0; l < D1D; ++l)
1037 for (
int k = 0; k < D1D; ++k)
1039 const int jkl = qp+k*D1D+l*D1D*D1D;
1040 elem_coords[jkl+d*p_NE] =
1041 xElemCoord[jkl+el*p_NE+d*nel*p_NE];
1048 const double *elx[
DIM];
1049 for (
int d = 0; d <
DIM; d++)
1051 elx[d] = MD1<= 6 ? &elem_coords[d*p_NE] :
1052 xElemCoord+d*nel*p_NE+el*p_NE;
1058 MFEM_FOREACH_THREAD(j,x,1)
1060 fpt->dist2 = HUGE_VAL;
1065 MFEM_FOREACH_THREAD(j,x,
DIM)
1073 double *dist2_temp = r_workspace_ptr;
1074 double *r_temp[
DIM];
1075 for (
int d = 0; d <
DIM; ++d)
1077 r_temp[d] = dist2_temp+(1+d)*D1D;
1080 MFEM_FOREACH_THREAD(j,x,D1D)
1082 seed_j(elx, x_i, gll1D, dist2_temp, r_temp, j, D1D);
1086 MFEM_FOREACH_THREAD(j,x,1)
1088 fpt->dist2 = HUGE_VAL;
1089 for (
int jj = 0; jj < D1D; ++jj)
1091 if (dist2_temp[jj] < fpt->dist2)
1093 fpt->dist2 = dist2_temp[jj];
1094 for (
int d = 0; d <
DIM; ++d)
1096 fpt->r[d] = r_temp[d][jj];
1104 MFEM_FOREACH_THREAD(j,x,1)
1106 tmp->dist2 = HUGE_VAL;
1111 MFEM_FOREACH_THREAD(j,x,
DIM)
1113 tmp->x[j] = fpt->x[j];
1114 tmp->r[j] = fpt->r[j];
1118 for (
int step = 0; step < 50; step++)
1120 switch (num_constrained(tmp->flags & FLAG_MASK))
1124 double *wtr = r_workspace_ptr;
1125 double *resid = wtr+6*D1D;
1126 double *jac = resid+3;
1127 double *resid_temp = jac+9;
1128 double *jac_temp = resid_temp+3*D1D;
1130 MFEM_FOREACH_THREAD(j,x,D1D*
DIM)
1132 const int qp = j % D1D;
1133 const int d = j / D1D;
1134 lag_eval_first_der(wtr+2*d*D1D, tmp->r[d], qp,
1135 gll1D, lagcoeff, D1D);
1139 MFEM_FOREACH_THREAD(j,x,D1D*
DIM)
1141 const int qp = j % D1D;
1142 const int d = j / D1D;
1143 double *idx = jac_temp+3*d+9*qp;
1144 resid_temp[d+qp*3] = tensor_ig3_j(idx,
1156 MFEM_FOREACH_THREAD(l,x,3)
1158 resid[l] = tmp->x[l];
1159 for (
int j = 0; j < D1D; ++j)
1161 resid[l] -= resid_temp[l+j*3];
1164 MFEM_FOREACH_THREAD(l,x,9)
1167 for (
int j = 0; j < D1D; ++j)
1169 jac[l] += jac_temp[l+j*9];
1174 MFEM_FOREACH_THREAD(l,x,1)
1178 if (!reject_prior_step_q(fpt, resid, tmp, tol))
1180 newton_vol(fpt, jac, resid, tmp, tol);
1189 const int fi = face_index(tmp->flags & FLAG_MASK);
1190 const int dn = fi >> 1;
1191 const int d1 = plus_1_mod_3(dn), d2 = plus_2_mod_3(dn);
1193 double *wt1 = r_workspace_ptr;
1194 double *resid = wt1+6*D1D;
1195 double *jac = resid+3;
1196 double *resid_temp = jac+9;
1197 double *jac_temp = resid_temp+3*D1D;
1198 double *hes = jac_temp+9*D1D;
1199 double *hes_temp = hes+3;
1202 MFEM_FOREACH_THREAD(j,x,D1D*2)
1207 const int d = j / D1D;
1208 const int qp = j % D1D;
1209 lag_eval_second_der(wt1+3*d*D1D, tmp->r[dd[d]],
1210 qp, gll1D, lagcoeff, D1D);
1214 double *J1 = wt1, *D1 = wt1+D1D;
1215 double *J2 = wt1+3*D1D, *D2 = J2+D1D;
1216 double *DD1 = D1+D1D, *DD2 = D2+D1D;
1217 findptsElemFace face;
1219 MFEM_FOREACH_THREAD(j,x,D1D*
DIM)
1222 face = get_face(elx, wtend, fi, constraint_workspace,
1223 face_edge_init, j, D1D);
1227 MFEM_FOREACH_THREAD(j,x,D1D*
DIM)
1229 if (j == 0) { face_edge_init = (1 << fi); }
1230 const int qp = j % D1D;
1231 const int d = j / D1D;
1232 const double *
u = face.x[d];
1233 const double *du = face.dxdn[d];
1234 double sums_k[4] = {0.0, 0.0, 0.0, 0.0};
1235 for (
int k = 0; k < D1D; ++k)
1237 sums_k[0] +=
u[qp+k*D1D]*J2[k];
1238 sums_k[1] +=
u[qp+k*D1D]*D2[k];
1239 sums_k[2] +=
u[qp+k*D1D]*DD2[k];
1240 sums_k[3] += du[qp+k*D1D]*J2[k];
1243 resid_temp[3*qp+d] = sums_k[0]*J1[qp];
1244 jac_temp[9*qp+3*d+d1] = sums_k[0]*D1[qp];
1245 jac_temp[9*qp+3*d+d2] = sums_k[1]*J1[qp];
1246 jac_temp[9*qp+3*d+dn] = sums_k[3]*J1[qp];
1249 hes_temp[3*qp] = sums_k[0]*DD1[qp];
1250 hes_temp[3*qp+1] = sums_k[1]*D1[qp];
1251 hes_temp[3*qp+2] = sums_k[2]*J1[qp];
1256 MFEM_FOREACH_THREAD(l,x,3)
1258 resid[l] = fpt->x[l];
1260 for (
int j = 0; j < D1D; ++j)
1262 resid[l] -= resid_temp[l+j*3];
1263 hes[l] += hes_temp[l+3*j];
1268 MFEM_FOREACH_THREAD(l,x,9)
1271 for (
int j = 0; j < D1D; ++j)
1273 jac[l] += jac_temp[l+j*9];
1278 MFEM_FOREACH_THREAD(l,x,1)
1280 if (!reject_prior_step_q(fpt, resid, tmp, tol))
1282 const double steep = resid[0]*jac[dn]+
1285 if (steep*tmp->r[dn] < 0)
1288 newton_vol(fpt, jac, resid, tmp, tol);
1292 newton_face(fpt, jac, hes, resid, d1,
1293 d2, dn, tmp->flags&FLAG_MASK,
1303 const int ei = edge_index(tmp->flags & FLAG_MASK);
1304 const int de = ei >> 2,
1305 dn1 = plus_1_mod_3(de),
1306 dn2 = plus_2_mod_3(de);
1311 const int hes_count = 2*3-1;
1313 double *wt = r_workspace_ptr;
1314 double *resid = wt+3*D1D;
1315 double *jac = resid+3;
1316 double *hes_T = jac+9;
1317 double *hes = hes_T+hes_count*3;
1318 findptsElemEdge edge;
1320 MFEM_FOREACH_THREAD(j,x,nThreads)
1323 edge = get_edge(elx, wtend, ei,
1324 constraint_workspace,
1330 const double *
const *e_x[3+3] = {edge.x, edge.x,
1337 MFEM_FOREACH_THREAD(j,x,D1D)
1339 if (j == 0) { face_edge_init = (64 << ei); }
1340 lag_eval_second_der(wt, tmp->r[de], j, gll1D,
1345 MFEM_FOREACH_THREAD(j,x,hes_count*3)
1347 const int d = j % 3;
1348 const int row = j / 3;
1353 double *wt_j = wt+(row == 1 ? D1D : 0);
1354 const double *x = e_x[row][d];
1356 for (
int k = 0; k < D1D; ++k)
1359 sum += wt_j[k]*x[k];
1363 resid[j] = tmp->x[j]-sum;
1367 jac[d*3+d_j[row-1]] = sum;
1375 double *wt_j = wt+D1D*(2 - (row+1)/2);
1376 const double *x = e_x[row+1][d];
1378 for (
int k = 0; k < D1D; ++k)
1380 hes_T[j] += wt_j[k]*x[k];
1386 MFEM_FOREACH_THREAD(j,x,hes_count)
1389 for (
int d = 0; d < 3; ++d)
1391 hes[j] += resid[d]*hes_T[j*3+d];
1396 MFEM_FOREACH_THREAD(l,x,1)
1399 if (!reject_prior_step_q(fpt, resid, tmp, tol))
1403 for (
int k = 0; k < 3-1; ++k)
1407 for (
int d = 0; d < 3; ++d)
1409 steep[k] += jac[dn+d*3]*resid[d];
1411 steep[k] *= tmp->r[dn];
1417 newton_vol(fpt, jac, resid, tmp, tol);
1425 newton_face(fpt, jac, rh, resid, de,
1427 tmp->flags&(3u<<(dn2*2)),
1439 newton_face(fpt, jac, rh, resid, dn2,
1441 tmp->flags&(3u<<(dn1*2)),
1446 newton_edge(fpt, jac, hes[0], resid,
1448 tmp->flags & FLAG_MASK,
1459 MFEM_FOREACH_THREAD(j,x,1)
1462 const int pi=point_index(tmp->flags & FLAG_MASK);
1463 const findptsElemPt gpt=get_pt(elx,wtend,pi,D1D);
1464 const double *
const pt_x = gpt.x;
1465 const double *
const jac = gpt.jac;
1466 const double *
const hes = gpt.hes;
1468 double resid[3], steep[3];
1469 for (
int d = 0; d < 3; ++d)
1471 resid[d] = fpt->x[d]-pt_x[d];
1473 if (!reject_prior_step_q(fpt, resid, tmp, tol))
1475 for (
int d = 0; d < 3; ++d)
1478 for (
int e = 0; e < 3; ++e)
1480 steep[d] += jac[d+e*3]*resid[e];
1482 steep[d] *= tmp->r[d];
1484 int de, dn1, dn2, d1, d2, dn, hi0, hi1, hi2;
1491 newton_vol(fpt,jac,resid,tmp,tol);
1495 d1 = 0; d2 = 1; dn = 2; hi0 = 0;
1498 rh[0] = resid[0]*hes[hi0] +
1499 resid[1]*hes[6+hi0] +
1500 resid[2]*hes[12+hi0];
1501 rh[1] = resid[0]*hes[hi1] +
1502 resid[1]*hes[6+hi1] +
1503 resid[2]*hes[12+hi1];
1504 rh[2] = resid[0]*hes[hi2] +
1505 resid[1]*hes[6+hi2] +
1506 resid[2]*hes[12+hi2];
1507 newton_face(fpt, jac, rh, resid,
1509 (tmp->flags)&(3u<<(2*dn)),
1517 d1 = 2; d2 = 0; dn = 1; hi0 = 5;
1520 rh[0] = resid[0]*hes[hi0] +
1521 resid[1]*hes[6+hi0] +
1522 resid[2]*hes[12+hi0];
1523 rh[1] = resid[0]*hes[hi1] +
1524 resid[1]*hes[6+hi1] +
1525 resid[2]*hes[12+hi1];
1526 rh[2] = resid[0]*hes[hi2] +
1527 resid[1]*hes[6+hi2] +
1528 resid[2]*hes[12+hi2];
1529 newton_face(fpt, jac, rh, resid,
1531 (tmp->flags)&(3u<<(2*dn)),
1536 de = 0, dn1 = 1, dn2 = 2, hi0 = 0;
1539 resid[1]*hes[6+hi0] +
1540 resid[2]*hes[12+hi0];
1541 newton_edge(fpt, jac, rh, resid,
1543 tmp->flags&(~(3u<<(2*de))),
1554 d1 = 1, d2 = 2, dn = 0;
1555 hi0 = 3, hi1 = 4, hi2 = 5;
1557 rh[0] = resid[0]*hes[hi0] +
1558 resid[1]*hes[6+hi0] +
1559 resid[2]*hes[12+hi0];
1560 rh[1] = resid[0]*hes[hi1] +
1561 resid[1]*hes[6+hi1] +
1562 resid[2]*hes[12+hi1];
1563 rh[2] = resid[0]*hes[hi2] +
1564 resid[1]*hes[6+hi2] +
1565 resid[2]*hes[12+hi2];
1566 newton_face(fpt, jac, rh, resid,
1568 (tmp->flags)&(3u<<(2*dn)),
1573 de = 1, dn1 = 2, dn2 = 0, hi0 = 3;
1576 resid[1]*hes[6+hi0] +
1577 resid[2]*hes[12+hi0];
1578 newton_edge(fpt, jac, rh, resid,
1580 tmp->flags&(~(3u<<(2*de))),
1588 de = 2, dn1 = 0, dn2 = 1, hi0 = 5;
1591 resid[1]*hes[6+hi0] +
1592 resid[2]*hes[12+hi0];
1593 newton_edge(fpt, jac, rh, resid,
1595 tmp->flags&(~(3u<<(2*de))),
1600 fpt->r[0] = tmp->r[0];
1601 fpt->r[1] = tmp->r[1];
1602 fpt->r[2] = tmp->r[2];
1604 fpt->flags =tmp->flags|CONVERGED_FLAG;
1614 if (fpt->flags & CONVERGED_FLAG)
1619 MFEM_FOREACH_THREAD(j,x,1)
1627 bool converged_internal = (fpt->flags&FLAG_MASK)==CONVERGED_FLAG;
1628 if (*code_i == CODE_NOT_FOUND || converged_internal ||
1629 fpt->dist2 < *dist2_i)
1631 MFEM_FOREACH_THREAD(j,x,1)
1634 *code_i = converged_internal ? CODE_INTERNAL :
1636 *dist2_i = fpt->dist2;
1638 MFEM_FOREACH_THREAD(j,x,
DIM)
1640 *(r_base+
DIM*i+j) = fpt->r[j];
1643 if (converged_internal)
1655 int point_pos_ordering,
1664 auto pp = point_pos.
Read();
1671 auto pcode = code.
Write();
1672 auto pelem = elem.
Write();
1673 auto pref = ref.
Write();
1674 auto pdist = dist.
Write();
1680 FindPointsLocal3DKernel<2>(npt,
DEV.
newt_tol, pp, point_pos_ordering,
1683 pcode, pelem, pref, pdist, pgll1d, plc);
1686 FindPointsLocal3DKernel<3>(npt,
DEV.
newt_tol, pp, point_pos_ordering,
1689 pcode, pelem, pref, pdist, pgll1d, plc);
1692 FindPointsLocal3DKernel<4>(npt,
DEV.
newt_tol, pp, point_pos_ordering,
1695 pcode, pelem, pref, pdist, pgll1d, plc);
1698 FindPointsLocal3DKernel<5>(npt,
DEV.
newt_tol, pp, point_pos_ordering,
1701 pcode, pelem, pref, pdist, pgll1d, plc);
1705 point_pos_ordering, pgslm,
1708 pcode, pelem, pref, pdist, pgll1d, plc,
1718#undef CODE_NOT_FOUND
1721 int point_pos_ordering,
1724 Vector &dist,
int npt) {};
T * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
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.
struct mfem::FindPointsGSLIB::DevStruct DEV
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).
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
MFEM_HOST_DEVICE T tr(const tensor< T, n, n > &A)
Returns the trace of a square matrix.
MFEM_HOST_DEVICE double bbox_test(const obbox_t< SDIM > *const b, const double(&x)[SDIM])
MFEM_HOST_DEVICE void lag_eval_first_der(double *p0, double x, int i, const double *z, const double *lCoeff, int pN)
MFEM_HOST_DEVICE void lin_solve_sym_2(double x[2], const double A[3], const double y[2])
MFEM_HOST_DEVICE double l2norm2(const double(&x)[SDIM])
MFEM_HOST_DEVICE int hash_index(const findptsLocalHashData_t< SDIM > *const p, const double(&x)[SDIM])
MFEM_HOST_DEVICE void lag_eval_second_der(double *p0, double x, int i, const double *z, const double *lCoeff, int pN)
real_t u(const Vector &xvec)
gslib::obbox_t< DIM > obbox_t
gslib::findptsLocalHashData_t< DIM > findptsLocalHashData_t
void forall_2D(int N, int X, int Y, lambda &&body)
gslib::dbl_range_t dbl_range_t
std::function< real_t(const Vector &)> f(real_t mass_coeff)
real_t p(const Vector &x, real_t t)
Array< unsigned int > lh_offset