17#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
18#pragma GCC diagnostic push
19#pragma GCC diagnostic ignored "-Wunused-function"
22#ifndef GSLIB_RELEASE_VERSION
23#define GSLIB_RELEASE_VERSION 10007
25#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
26#pragma GCC diagnostic pop
31#if GSLIB_RELEASE_VERSION >= 10009
32#define CODE_INTERNAL 0
34#define CODE_NOT_FOUND 2
39struct findptsElementPoint_t
41 double x[sDIM], r[rDIM], oldr[rDIM], dist2, dist2p, tr;
45struct findptsElementGEdge_t
47 double *x[sDIM], *dxdn[sDIM], *d2xdn[sDIM];
50struct findptsElementGPT_t
52 double x[sDIM], jac[sDIM*rDIM], hes[sDIM*(rDIM+1)];
56using obbox_t = gslib::obbox_t<sDIM>;
74#define CONVERGED_FLAG (1u<<4)
75#define FLAG_MASK 0x1fu
79static MFEM_HOST_DEVICE
inline int num_constrained(
const int flags)
81 const int y = (flags | flags>>1);
82 return (y & 1u) + (y>>2 & 1u);
87static MFEM_HOST_DEVICE
inline int plus_1_mod_2(
const int x)
95static MFEM_HOST_DEVICE
inline int which_bit(
const int x)
98 return (y-(y>>2)) | ((x-1)&4u);
104static MFEM_HOST_DEVICE
inline int edge_index(
const int x)
106 return which_bit(x) - 1;
109static MFEM_HOST_DEVICE
inline int point_index(
const int x)
111 return ((x>>1)&1u) | ((x>>2)&2u);
114static MFEM_HOST_DEVICE
inline void
115get_edge(
const double *elx[3],
const double *wtend,
int ei,
116 int &side_init,
int jidx,
int pN, findptsElementGEdge_t &edge)
119 const int dn = ei>>1,
120 de = plus_1_mod_2(dn);
121 const int side_n = ei&1,
122 side_n_offset = side_n*(pN-1);
123 const double *wt1 = wtend + 3*pN*side_n;
125 const int jj = jidx%pN;
126 const int dd = jidx/pN;
127 if (
static_cast<unsigned>(side_init) != (1u << ei))
129 const int elx_stride[2] = {1,pN};
130#define ELX(d,j,k) elx[d][j*elx_stride[de] + k*elx_stride[dn]]
132 edge.x[dd][jj] = ELX(dd, jj, side_n_offset);
133 double sums_k[2] = {0,0};
134 for (
int k=0; k<pN; ++k)
136 sums_k[0] += wt1[pN+k] * ELX(dd,jj,k);
137 sums_k[1] += wt1[2*pN+k] * ELX(dd,jj,k);
139 edge.dxdn[dd][jj] = sums_k[0];
140 edge.d2xdn[dd][jj] = sums_k[1];
145static MFEM_HOST_DEVICE
inline findptsElementGPT_t get_pt(
const double *elx[3],
150 const int side_n1 = pi&1,
152 const int in1 = side_n1*(pN-1),
153 in2 = side_n2*(pN-1);
154 const int hes_stride = rDIM + 1;
156 findptsElementGPT_t pt;
158#define ELX(d,j,k) elx[d][j + k*pN]
159 for (
int d=0; d<sDIM; ++d)
161 pt.x[d] = ELX(d,in1,in2);
164 const double *wt1 = wtend + pN + side_n1*3*pN;
165 const double *wt2 = wtend + pN + side_n2*3*pN;
167 for (
int i=0; i<rDIM; ++i)
169 pt.jac[rDIM*d + i] = 0;
171 for (
int i=0; i<hes_stride; ++i)
173 pt.hes[hes_stride*d + i] = 0;
176 for (
int j=0; j<pN; ++j)
178 pt.jac[rDIM*d+0] += wt1[j] * ELX(d,j,in2);
179 pt.jac[rDIM*d+1] += wt2[j] * ELX(d,in1,j);
182 for (
int k=0; k<pN; ++k)
184 sum_k += wt1[k] * ELX(d,k,j);
186 pt.hes[hes_stride*d+0] += wt1[pN+j] * ELX(d,j,in2);
187 pt.hes[hes_stride*d+1] += wt2[j] * sum_k;
188 pt.hes[hes_stride*d+2] += wt2[pN+j] * ELX(d,in1,j);
200static MFEM_HOST_DEVICE
bool reject_prior_step_q(findptsElementPoint_t *out_pt,
201 const double resid[3],
202 const findptsElementPoint_t *
p,
205 const double dist2 = l2norm2<sDIM>(resid);
206 const double decr =
p->dist2 - dist2;
207 const double pred =
p->dist2p;
208 for (
int d=0; d<sDIM; ++d)
210 out_pt->x[d] =
p->x[d];
212 for (
int d=0; d<rDIM; ++d)
214 out_pt->oldr[d] =
p->r[d];
216 out_pt->dist2 = dist2;
221 out_pt->tr = 2*
p->tr;
235 double v0 = fabs(
p->r[0] -
p->oldr[0]),
236 v1 = fabs(
p->r[1] -
p->oldr[1]);
237 out_pt->tr = ( v0>v1 ? v0 : v1 )/4;
238 out_pt->dist2 =
p->dist2;
239 out_pt->flags =
p->flags >> 5;
240 out_pt->dist2p = -HUGE_VAL;
241 for (
int d=0; d<rDIM; ++d)
243 out_pt->r[d] =
p->oldr[d];
247 out_pt->flags |= CONVERGED_FLAG;
255static MFEM_HOST_DEVICE
void newton_face( findptsElementPoint_t *
const out_pt,
256 const double jac[sDIM*rDIM],
257 const double rhes[3],
258 const double resid[sDIM],
260 const findptsElementPoint_t *
const p,
263 const double tr =
p->tr;
265 double r[2], dr[2] = {0, 0};
269 double A[3], y[2], r0[2];
275 A[0] = jac[0]*jac[0] + jac[2]*jac[2] + jac[4]*jac[4] - rhes[0];
276 A[1] = jac[0]*jac[1] + jac[2]*jac[3] + jac[4]*jac[5] - rhes[1];
277 A[2] = jac[1]*jac[1] + jac[3]*jac[3] + jac[5]*jac[5] - rhes[2];
280 y[0] = jac[0]*resid[0] + jac[2]*resid[1] + jac[4]*resid[2];
281 y[1] = jac[1]*resid[0] + jac[3]*resid[1] + jac[5]*resid[2];
297 bnd[0] = -
tr, mask ^= 1u;
305 bnd[1] =
tr, mask ^= 2u;
313 bnd[2] = -
tr, mask ^= 1u<<2;
321 bnd[3] =
tr, mask ^= 2u << 2;
331 if (A[0]+A[2]<=0 || A[0]*A[2]<=A[1]*A[1])
333 goto newton_face_constrained;
336 lin_solve_sym_2(dr, A, y);
338#define EVAL(r,s) -(y[0]*r + y[1]*s) + (r*A[0]*r + (2*r*A[1] + s*A[2])*s)/2
339 if ((dr[0]-bnd[0])*(bnd[1]-dr[0])>=0 && (dr[1]-bnd[2])*(bnd[3]-dr[1])>=0)
341 r[0] = r0[0] + dr[0], r[1] = r0[1] + dr[1];
342 v = EVAL(dr[0], dr[1]);
343 goto newton_face_fin;
346newton_face_constrained:
347 v = EVAL(bnd[0], bnd[2]);
349 tv = EVAL(bnd[1], bnd[2]);
352 v = tv, i = 2u|(1u<<2);
354 tv = EVAL(bnd[0], bnd[3]);
357 v = tv, i = 1u|(2u<<2);
359 tv = EVAL(bnd[1], bnd[3]);
362 v = tv, i = 2u|(2u<<2);
368 drc = (y[0] - A[1]*bnd[2])/A[0];
369 if ( (drc-bnd[0])*(bnd[1]-drc)>=0 &&
370 (tv=EVAL(drc,bnd[2]))<v )
373 v = tv, i = 1u<<2, dr[0] = drc;
375 drc = (y[0] - A[1]*bnd[3])/A[0];
376 if ( (drc-bnd[0])*(bnd[1]-drc)>=0 &&
377 (tv=EVAL(drc,bnd[3]))<v )
380 v = tv, i = 2u<<2, dr[0] = drc;
386 drc = (y[1] - A[1]*bnd[0])/A[2];
387 if ( (drc-bnd[2])*(bnd[3]-drc)>=0 &&
388 (tv = EVAL(bnd[0], drc)) < v)
390 v = tv, i = 1u, dr[1] = drc;
392 drc = (y[1] - A[1]*bnd[1])/A[2];
393 if ((drc-bnd[2])*(bnd[3]-drc)>=0 &&
394 (tv = EVAL(bnd[1], drc))<v)
396 v = tv, i = 2u, dr[1] = drc;
402 for (
int d=0; d<rDIM; ++d)
406 const int f = (i>>2*d) & 3u;
409 r[d] = r0[d] + dr[d];
413 if ( (
f&(mask>>(2*d)) ) == 0 )
415 r[d] = r0[d] + (
f==1 ? -
tr :
tr);
419 r[d] = (
f==1 ? -1 : 1), new_flags |=
f<<(2*d);
426 out_pt->dist2p = -2*v;
427 dr[0] = r[0] -
p->r[0];
428 dr[1] = r[1] -
p->r[1];
429 if ( fabs(dr[0])+fabs(dr[1]) < tol)
431 new_flags |= CONVERGED_FLAG;
433 out_pt->r[0] = r[0], out_pt->r[1] = r[1];
434 out_pt->flags = new_flags | ((
p->flags & FLAG_MASK)<<5);
437static MFEM_HOST_DEVICE
inline void newton_edge(findptsElementPoint_t *
const
439 const double jac[sDIM*rDIM],
441 const double resid[sDIM],
445 const findptsElementPoint_t *
const p,
448 const double tr =
p->tr;
450 const double A = jac[de] *jac[de]
451 + jac[de+rDIM] *jac[de+rDIM]
452 + jac[de+2*rDIM]*jac[de+2*rDIM]
455 const double y = jac[de] *resid[0]
456 + jac[de+rDIM] *resid[1]
457 + jac[de+2*rDIM]*resid[2];
459 const double oldr =
p->r[de];
460 double dr, nr, tdr, tnr;
462 int new_flags = 0, tnew_flags = 0;
464#define EVAL(dr) (dr*A - 2*y)*dr
485 if ( fabs(dr)<tr && fabs(nr)<1 )
488 goto newton_edge_fin;
492 if ( (nr=oldr-tr)>-1 )
498 nr = -1, dr = -1-oldr, new_flags = flags | 1u<<2*de;
502 if ( (tnr = oldr+tr)<1 )
508 tnr = 1, tdr = 1-oldr, tnew_flags = flags | 2u<<2*de;
514 nr = tnr, dr = tdr, v = tv, new_flags = tnew_flags;
521 new_flags |= CONVERGED_FLAG;
524 out_pt->r[dn] =
p->r[dn];
526 out_pt->flags = flags | new_flags | ((
p->flags & FLAG_MASK)<<5);
530static MFEM_HOST_DEVICE
void seed_j(
const double *elx[sDIM],
531 const double x[sDIM],
540 for (
int k=0; k<pN; ++k)
543 const int jk = j + k*pN;
545 for (
int d=0; d<sDIM; ++d)
547 dx[d] = x[d] - elx[d][jk];
549 const double dist2_jk = l2norm2(dx);
550 if (dist2[j]>dist2_jk)
561template<
int T_D1D = 0>
562static void FindPointsSurfLocal3DKernel(
const int npt,
564 const double dist2tol,
566 const int point_pos_ordering,
567 const double *xElemCoord,
570 const double *boxinfo,
571 const bool obb_check,
573 const double *hashMin,
574 const double *hashFac,
575 unsigned int *hashOffset,
576 unsigned int *
const code_base,
577 unsigned int *
const el_base,
578 double *
const r_base,
579 double *
const dist2_base,
581 const double *lagcoeff,
584 const int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
585 const int D1D = T_D1D ? T_D1D : pN;
586 const int p_NE = D1D*D1D;
587 MFEM_VERIFY(MD1<=DofQuadLimits::MAX_D1D,
588 "Increase Max allowable polynomial order.");
589 MFEM_VERIFY(pN<=DofQuadLimits::MAX_D1D,
590 "Increase Max allowable polynomial order.");
591 MFEM_VERIFY(D1D!=0,
"Polynomial order not specified.");
592 const int nThreads = D1D*sDIM > 9 ? D1D*sDIM : 9;
596 constexpr int size1 = 18*MD1 + 12;
597 constexpr int size2 = 9*MD1;
598 constexpr int size3 = MD1*MD1*sDIM;
600 MFEM_SHARED
double r_workspace[size1];
601 MFEM_SHARED findptsElementPoint_t el_pts[2];
603 MFEM_SHARED
double constraint_workspace[size2];
604 MFEM_SHARED
int edge_init;
606 MFEM_SHARED
double elem_coords[MD1 <= 6 ? size3 : 1];
608 double *r_workspace_ptr = r_workspace;
609 findptsElementPoint_t *fpt, *tmp;
613 int id_x = point_pos_ordering==0 ? i : i*sDIM;
614 int id_y = point_pos_ordering==0 ? npt+i : 1+i*sDIM;
615 int id_z = point_pos_ordering==0 ? 2*npt+i : 2+i*sDIM;
616 double x_i[3] = {x[id_x], x[id_y], x[id_z]};
618 unsigned int *code_i = code_base + i;
619 double *dist2_i = dist2_base + i;
623 for (
int d=0; d<sDIM; ++d)
625 hash.bnd[d].min = hashMin[d];
626 hash.fac[d] = hashFac[d];
628 hash.hash_n = hash_n;
629 hash.offset = hashOffset;
630 const unsigned int hi = hash_index(&hash, x_i);
631 const unsigned int *elp = hash.offset + hash.offset[hi],
632 *
const ele = hash.offset + hash.offset[hi+1];
633 *code_i = CODE_NOT_FOUND;
636 for (; elp!=ele; ++elp)
638 const unsigned int el = *elp;
640 const int n_box_ents = obb_check ? (3*sDIM + sDIM2) : (2*sDIM);
646 for (
int idx = 0; idx < sDIM; ++idx)
648 box.c0[idx] = boxinfo[n_box_ents*el + idx];
649 box.x[idx].min = boxinfo[n_box_ents*el + sDIM + idx];
650 box.x[idx].max = boxinfo[n_box_ents*el + 2*sDIM + idx];
653 for (
int idx = 0; idx < sDIM2; ++idx)
655 box.A[idx] = boxinfo[n_box_ents*el + 3*sDIM + idx];
657 pass_bb = (bbox_test(&box, x_i) >= 0);
661 for (
int d = 0; d < sDIM; ++d)
663 box.x[d].min = boxinfo[n_box_ents*el + d];
664 box.x[d].max = boxinfo[n_box_ents*el + sDIM + d];
666 pass_bb = (AABB_test(&box, x_i) >= 0);
669 if (!pass_bb) {
continue; }
675 MFEM_FOREACH_THREAD(j,x,D1D*sDIM)
677 const int qp = j % D1D;
678 const int d = j / D1D;
679 for (
int k = 0; k < D1D; ++k)
681 const int jk = qp + k * D1D;
682 elem_coords[jk + d*p_NE] =
683 xElemCoord[jk + el*p_NE + d*p_NE*nel];
689 const double *elx[sDIM];
690 for (
int d=0; d<sDIM; d++)
692 elx[d] = MD1<= 6 ? &elem_coords[d*p_NE] :
693 xElemCoord + d*nel*p_NE + el*p_NE;
699 MFEM_FOREACH_THREAD(j,x,1)
702 fpt->dist2 = HUGE_VAL;
707 MFEM_FOREACH_THREAD(j,x,sDIM)
715 double *dist2_temp = r_workspace_ptr;
716 double *r_temp[rDIM];
717 for (
int d=0; d<rDIM; ++d)
719 r_temp[d] = dist2_temp+(1+d)*D1D;
721 MFEM_FOREACH_THREAD(j,x,D1D)
723 seed_j(elx, x_i, gll1D, dist2_temp, r_temp, j, D1D);
727 MFEM_FOREACH_THREAD(j,x,1)
729 fpt->dist2 = HUGE_VAL;
730 for (
int jj = 0; jj < D1D; ++jj)
732 if (dist2_temp[jj] < fpt->dist2)
734 fpt->dist2 = dist2_temp[jj];
735 for (
int d = 0; d < rDIM; ++d)
737 fpt->r[d] = r_temp[d][jj];
745 MFEM_FOREACH_THREAD(j,x,1)
747 tmp->dist2 = HUGE_VAL;
752 MFEM_FOREACH_THREAD(j,x,rDIM)
754 tmp->r[j] = fpt->r[j];
756 MFEM_FOREACH_THREAD(j,x,sDIM)
758 tmp->x[j] = fpt->x[j];
762 for (
int step=0; step<50; step++)
764 switch (num_constrained(tmp->flags & FLAG_MASK))
768 double *wt1 = r_workspace_ptr;
769 double *resid = wt1 + 6*D1D;
770 double *jac = resid + sDIM;
771 double *resid_temp = jac + sDIM*rDIM;
772 double *jac_temp = resid_temp + sDIM*D1D;
775 double *hes = jac_temp + sDIM*rDIM*D1D;
776 double *hes_temp = hes + 3;
779 MFEM_FOREACH_THREAD(j,x,D1D*rDIM)
781 const int qp = j % D1D;
782 const int d = j / D1D;
783 lag_eval_second_der(wt1+3*d*D1D, tmp->r[d], qp,
784 gll1D, lagcoeff, D1D);
788 double *J1 = wt1, *D1 = wt1+D1D, *DD1 = D1+D1D;
789 double *J2 = wt1 + 3*D1D, *D2 = J2+D1D, *DD2 = D2+D1D;
791 MFEM_FOREACH_THREAD(j,x,D1D*sDIM)
793 const int qp = j % D1D;
794 const int d = j / D1D;
795 const double *
u = elx[d];
796 double sums_k[3] = {0.0, 0.0, 0.0};
797 for (
int k=0; k<D1D; ++k)
799 sums_k[0] +=
u[qp + k*D1D] * J2[k];
800 sums_k[1] +=
u[qp + k*D1D] * D2[k];
801 sums_k[2] +=
u[qp + k*D1D] * DD2[k];
804 resid_temp[sDIM*qp+d] = sums_k[0] * J1[qp];
805 jac_temp[sDIM*rDIM*qp+rDIM*d+0] = sums_k[0]*D1[qp];
806 jac_temp[sDIM*rDIM*qp+rDIM*d+1] = sums_k[1]*J1[qp];
809 hes_temp[3*qp + 0] = sums_k[0] * DD1[qp];
810 hes_temp[3*qp + 1] = sums_k[1] * D1[qp];
811 hes_temp[3*qp + 2] = sums_k[2] * J1[qp];
816 MFEM_FOREACH_THREAD(l,x,sDIM)
818 resid[l] = tmp->x[l];
819 for (
int j=0; j<D1D; ++j)
821 resid[l] -= resid_temp[l + j*sDIM];
824 MFEM_FOREACH_THREAD(l,x,sDIM*rDIM)
827 for (
int j=0; j<D1D; ++j)
829 jac[l] += jac_temp[l + j*sDIM*rDIM];
834 for (
int j=0; j<D1D; ++j)
836 hes[l] += hes_temp[l + sDIM*j];
843 MFEM_FOREACH_THREAD(l,x,1)
845 if (!reject_prior_step_q(fpt,resid,tmp,tol))
847 newton_face(fpt,jac,hes,resid,
848 (tmp->flags&CONVERGED_FLAG),
857 const int ei = edge_index(tmp->flags & FLAG_MASK);
858 const int dn = ei>>1;
859 const int de = plus_1_mod_2(dn);
860 const int d_j[2] = {de,dn};
861 const int hes_count = 3;
863 double *wt = r_workspace_ptr;
864 double *resid = wt + 3*D1D;
865 double *jac = resid + sDIM;
866 double *hes_T = jac + sDIM*rDIM;
867 double *hes = hes_T + hes_count*sDIM;
868 findptsElementGEdge_t edge;
869 for (
int d=0; d<sDIM; ++d)
871 edge.x[d] = constraint_workspace + d*D1D;
872 edge.dxdn[d] = constraint_workspace + d*D1D
874 edge.d2xdn[d] = constraint_workspace + d*D1D
878 MFEM_FOREACH_THREAD(j,x,D1D*sDIM)
881 get_edge(elx, wtend, ei, edge_init, j, D1D, edge);
885 MFEM_FOREACH_THREAD(j,x,D1D)
887 if (j == 0) { edge_init = (1u << ei); }
888 lag_eval_second_der(wt,tmp->r[de],j,gll1D,
893 const double *
const *e_x[4] = {edge.x, edge.x,
894 edge.dxdn, edge.d2xdn
896 MFEM_FOREACH_THREAD(j,x,hes_count*3)
898 const int d = j%sDIM;
899 const int row = j/sDIM;
901 double *wt_j = wt + (row==1 ? D1D : 0);
902 const double *x = e_x[row][d];
904 for (
int k=0; k<D1D; ++k)
910 resid[j] = tmp->x[j] - sum;
914 jac[ d*rDIM + d_j[row-1] ] = sum;
920 double *wt_j = wt + (2-row)*D1D;
922 for (
int k=0; k<D1D; ++k)
924 hes_T[j] += wt_j[k] * e_x[row+1][d][k];
930 MFEM_FOREACH_THREAD(j,x,hes_count)
933 for (
int d=0; d<sDIM; ++d)
935 hes[j] += resid[d] * hes_T[hes_count*j + d];
940 MFEM_FOREACH_THREAD(l,x,1)
942 if ( !reject_prior_step_q(fpt,resid,tmp,tol))
945 for (
int d=0; d<sDIM; ++d)
947 steep += jac[d*rDIM + dn] * resid[d];
954 dn == 0 ? hes[2] : hes[0],
956 dn == 0 ? hes[0] : hes[2]
958 newton_face(fpt, jac, face_hes, resid,
959 tmp->flags & CONVERGED_FLAG,
964 newton_edge(fpt,jac,hes[0],resid,de,dn,tmp->flags&FLAG_MASK,tmp,tol);
973 MFEM_FOREACH_THREAD(j,x,1)
975 const int pi=point_index(tmp->flags & FLAG_MASK);
976 const findptsElementGPT_t gpt=get_pt(elx,wtend,pi,D1D);
977 const double *
const pt_x = gpt.x;
978 const double *
const jac = gpt.jac;
979 const double *
const hes = gpt.hes;
981 double resid[sDIM], steep[rDIM];
982 for (
int d=0; d<sDIM; ++d)
984 resid[d] = fpt->x[d]-pt_x[d];
986 if (!reject_prior_step_q(fpt,resid,tmp,tol))
988 for (
int d=0; d<rDIM; ++d)
991 for (
int e=0; e<sDIM; ++e)
993 steep[d] += jac[e*rDIM+d] * resid[e];
995 steep[d] *= tmp->r[d];
1004 for (
int rd=0; rd<3; ++rd)
1007 for (
int d=0; d<sDIM; ++d)
1009 rh[rd] += resid[d] * hes[3*d + rd];
1012 newton_face(fpt,jac,rh,resid,
1013 (tmp->flags & CONVERGED_FLAG),
1020 const double rh=resid[0] * hes[0] +
1021 resid[1] * hes[3+ 0] +
1022 resid[2] * hes[6 + 0];
1023 newton_edge(fpt,jac,rh,resid,de,dn,
1024 (tmp->flags & ~(3u<<2*de)),tmp,tol);
1033 const double rh = resid[0] * hes[2] +
1036 newton_edge(fpt,jac,rh,resid,de,dn,
1037 (tmp->flags & ~(3u<<2*de)),tmp,tol);
1041 fpt->r[0] = tmp->r[0];
1042 fpt->r[1] = tmp->r[1];
1044 fpt->flags = tmp->flags | CONVERGED_FLAG;
1053 if (fpt->flags & CONVERGED_FLAG)
1059 MFEM_FOREACH_THREAD(j,x,nThreads)
1070 bool converged_internal =
1071 ((fpt->flags&FLAG_MASK)==CONVERGED_FLAG ) &&
1072 fpt->dist2<dist2tol;
1073 if (*code_i==CODE_NOT_FOUND || converged_internal ||
1074 fpt->dist2<*dist2_i)
1076 MFEM_FOREACH_THREAD(j,x,1)
1079 *code_i = converged_internal ? CODE_INTERNAL :
1081 *dist2_i = fpt->dist2;
1083 MFEM_FOREACH_THREAD(j,x,rDIM)
1085 *(r_base+rDIM*i+j) = fpt->r[j];
1088 if (converged_internal)
1099 int point_pos_ordering,
1110 MFEM_VERIFY(
dim == 2 &&
spacedim==3,
"Function for 3D surfaces only");
1112 auto pp = point_pos.
Read(use_dev);
1119 auto pcode = code.
Write(use_dev);
1120 auto pelem = elem.
Write(use_dev);
1121 auto pref = ref.
Write(use_dev);
1122 auto pdist = dist.
Write(use_dev);
1131 FindPointsSurfLocal3DKernel<2>(npt,
DEV.
newt_tol, dist2tol,
1132 pp, point_pos_ordering, pgslm,
1135 pcode, pelem, pref, pdist,
1139 FindPointsSurfLocal3DKernel<3>(npt,
DEV.
newt_tol, dist2tol,
1140 pp, point_pos_ordering, pgslm,
1143 pcode, pelem, pref, pdist,
1147 FindPointsSurfLocal3DKernel<4>(npt,
DEV.
newt_tol, dist2tol,
1148 pp, point_pos_ordering, pgslm,
1151 pcode, pelem, pref, pdist,
1155 FindPointsSurfLocal3DKernel(npt,
DEV.
newt_tol, dist2tol, pp,
1156 point_pos_ordering, pgslm,
1159 pcode, pelem, pref, pdist,
1170#undef CODE_NOT_FOUND
1173 int point_pos_ordering,
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 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.
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 void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
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 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)
MFEM_HOST_DEVICE double AABB_test(const obbox_t< SDIM > *const b, const double(&x)[SDIM])
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