56 const int ndof1d = max_order + 1;
60 "Mixed meshes are not supported.");
61 for (
int d = 1; d <
dim; ++d)
65 const int vdim = fespace->
GetVDim();
66 const int NE = fespace->
GetNE();
67 node_pos.
SetSize(vdim * ND * NE, my_d_mt);
76 "unsupported geometry type");
88 for (
int e = 0; e < NE; ++e)
90 fe = fespace->
GetFE(e);
91 for (
int i = 0; i < ND; ++i)
95 idcs[2] = idcs[1] / ndof1d;
96 idcs[1] = idcs[1] % ndof1d;
97 ip.
x = (*points1d)[idcs[0]];
98 ip.
y = (*points1d)[idcs[1]];
99 ip.
z = (*points1d)[idcs[2]];
101 for (
int d = 0; d < sdim; ++d)
103 node_pos[i + (d + e * sdim) * ND] = pos[d];
112 elem_restr->
Mult(gf, node_pos);
121 Vector &refs,
bool use_device,
132 const int vdim = fespace->
GetVDim();
133 const int NE = fespace->
GetNE();
135 int npts = elems.
Size();
141 auto pptr =
pts.Read(use_device);
142 auto eptr = elems.
Read(use_device);
143 auto mptr = node_pos.
Read(use_device);
144 auto tptr = types.
Write(use_device);
146 int* iter_ptr =
nullptr;
147 if (iters !=
nullptr)
150 iter_ptr = iters->
Write(use_device);
152 auto nptr = points1d->
Read(use_device);
153 int ndof1d = points1d->
Size();
155 switch (init_guess_type)
168 [=] MFEM_HOST_DEVICE(
int i) { xptr[i] = cx; });
182 xptr[i + 2 * npts] = cz;
190 int nq1d = (qpts_order >= 0 ? qpts_order
191 : std::max(order + rel_qpts_order, 0)) +
199 if (init_guess_type ==
202 FindClosestPhysDof::Run(geom, vdim, use_device, npts, NE, ndof1d,
203 mptr, pptr, eptr, nptr, xptr);
207 FindClosestRefDof::Run(geom, vdim, use_device, npts, NE, ndof1d, mptr,
208 pptr, eptr, nptr, xptr);
215 auto qptr = qpoints->
Read(use_device);
216 if (init_guess_type ==
219 FindClosestPhysPoint::Run(geom, vdim, use_device, npts, NE, ndof1d,
220 nq1d, mptr, pptr, eptr, nptr, qptr,
225 FindClosestRefPoint::Run(geom, vdim, use_device, npts, NE, ndof1d,
226 nq1d, mptr, pptr, eptr, nptr, qptr, xptr);
235 int nq1d = (qpts_order >= 0 ? qpts_order
236 : std::max(order + rel_qpts_order, 0)) +
245 auto qptr = qpoints->
Read(use_device);
246 NewtonEdgeScan::Run(geom, vdim, solver_type, use_device, ref_tol,
247 phys_rtol, max_iter, npts, NE, ndof1d, mptr, pptr,
248 eptr, nptr, qptr, nq1d, tptr, iter_ptr,
254 NewtonSolve::Run(geom, vdim, solver_type, use_device, ref_tol, phys_rtol,
255 max_iter, npts, NE, ndof1d, mptr, pptr, eptr, nptr, tptr,
263struct InvTNewtonSolverBase
287template <
int Dim,
int SDim>
struct InvTLinSolve;
289template <>
struct InvTLinSolve<1, 1>
291 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
294 dx[0] = rhs[0] / jac[0];
298template <>
struct InvTLinSolve<1, 2>
300 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
304 auto a10 = jac[1 * MFEM_THREAD_SIZE(x)];
307 dx[0] = (a00 * rhs[0] + a10 * rhs[1 * MFEM_THREAD_SIZE(x)]) / den;
311template <>
struct InvTLinSolve<1, 3>
313 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
317 auto a10 = jac[1 * MFEM_THREAD_SIZE(x)];
318 auto a20 = jac[2 * MFEM_THREAD_SIZE(x)];
319 real_t den = a00 * a00 + a10 * a10 + a20 * a20;
320 dx[0] = (a00 * rhs[0] + a10 * rhs[1 * MFEM_THREAD_SIZE(x)] +
321 a20 * rhs[2 * MFEM_THREAD_SIZE(x)]) /
326template <>
struct InvTLinSolve<2, 2>
328 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
331 auto a00 = jac[(0 + 0 * 2) * MFEM_THREAD_SIZE(x)];
332 auto a10 = jac[(1 + 0 * 2) * MFEM_THREAD_SIZE(x)];
333 auto a01 = jac[(0 + 1 * 2) * MFEM_THREAD_SIZE(x)];
334 auto a11 = jac[(1 + 1 * 2) * MFEM_THREAD_SIZE(x)];
335 real_t den = 1 / (a00 * a11 - a01 * a10);
336 dx[0] = (a11 * rhs[0 * MFEM_THREAD_SIZE(x)] -
337 a01 * rhs[1 * MFEM_THREAD_SIZE(x)]) *
339 dx[1] = (a00 * rhs[1 * MFEM_THREAD_SIZE(x)] -
340 a10 * rhs[0 * MFEM_THREAD_SIZE(x)]) *
345template <>
struct InvTLinSolve<2, 3>
347 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
350 auto a00 = jac[(0 + 0 * 3) * MFEM_THREAD_SIZE(x)];
351 auto a01 = jac[(0 + 1 * 3) * MFEM_THREAD_SIZE(x)];
352 auto a10 = jac[(1 + 0 * 3) * MFEM_THREAD_SIZE(x)];
353 auto a11 = jac[(1 + 1 * 3) * MFEM_THREAD_SIZE(x)];
354 auto a20 = jac[(2 + 0 * 3) * MFEM_THREAD_SIZE(x)];
355 auto a21 = jac[(2 + 1 * 3) * MFEM_THREAD_SIZE(x)];
359 real_t den = 1 / (a00 * a00 * a11 * a11 + a00 * a00 * a21 * a21 -
360 2 * a00 * a01 * a10 * a11 - 2 * a00 * a01 * a20 * a21 +
361 a01 * a01 * a10 * a10 + a01 * a01 * a20 * a20 +
362 a10 * a10 * a21 * a21 - 2 * a10 * a11 * a20 * a21 +
363 a11 * a11 * a20 * a20);
367 dx[0] = (rhs[0 * MFEM_THREAD_SIZE(x)] *
368 (a00 * (a01 * a01 + a11 * a11 + a21 * a21) -
369 a01 * (a00 * a01 + a10 * a11 + a20 * a21)) +
370 rhs[1 * MFEM_THREAD_SIZE(x)] *
371 (a10 * (a01 * a01 + a11 * a11 + a21 * a21) -
372 a11 * (a00 * a01 + a10 * a11 + a20 * a21)) +
373 rhs[2 * MFEM_THREAD_SIZE(x)] *
374 (a20 * (a01 * a01 + a11 * a11 + a21 * a21) -
375 a21 * (a00 * a01 + a10 * a11 + a20 * a21))) *
380 dx[1] = (rhs[0 * MFEM_THREAD_SIZE(x)] *
381 (a01 * (a00 * a00 + a10 * a10 + a20 * a20) -
382 a00 * (a00 * a01 + a10 * a11 + a20 * a21)) +
383 rhs[1 * MFEM_THREAD_SIZE(x)] *
384 (a11 * (a00 * a00 + a10 * a10 + a20 * a20) -
385 a10 * (a00 * a01 + a10 * a11 + a20 * a21)) +
386 rhs[2 * MFEM_THREAD_SIZE(x)] *
387 (a21 * (a00 * a00 + a10 * a10 + a20 * a20) -
388 a20 * (a00 * a01 + a10 * a11 + a20 * a21))) *
393template <>
struct InvTLinSolve<3, 3>
395 static void MFEM_HOST_DEVICE
solve(
const real_t *jac,
const real_t *rhs,
398 auto a00 = jac[(0 + 0 * 3) * MFEM_THREAD_SIZE(x)];
399 auto a01 = jac[(0 + 1 * 3) * MFEM_THREAD_SIZE(x)];
400 auto a02 = jac[(0 + 2 * 3) * MFEM_THREAD_SIZE(x)];
401 auto a10 = jac[(1 + 0 * 3) * MFEM_THREAD_SIZE(x)];
402 auto a11 = jac[(1 + 1 * 3) * MFEM_THREAD_SIZE(x)];
403 auto a12 = jac[(1 + 2 * 3) * MFEM_THREAD_SIZE(x)];
404 auto a20 = jac[(2 + 0 * 3) * MFEM_THREAD_SIZE(x)];
405 auto a21 = jac[(2 + 1 * 3) * MFEM_THREAD_SIZE(x)];
406 auto a22 = jac[(2 + 2 * 3) * MFEM_THREAD_SIZE(x)];
408 real_t den = 1 / (a00 * a11 * a22 - a00 * a12 * a22 - a01 * a10 * a22 +
409 a01 * a12 * a20 + a02 * a10 * a21 - a02 * a11 * a20);
410 dx[0] = (rhs[0 * MFEM_THREAD_SIZE(x)] * (a11 * a22 - a12 * a21) -
411 rhs[1 * MFEM_THREAD_SIZE(x)] * (a01 * a22 - a02 * a21) +
412 rhs[2 * MFEM_THREAD_SIZE(x)] * (a01 * a12 - a02 * a11)) *
414 dx[1] = (rhs[0 * MFEM_THREAD_SIZE(x)] * (a12 * a20 - a10 * a22) +
415 rhs[1 * MFEM_THREAD_SIZE(x)] * (a00 * a22 - a02 * a20) -
416 rhs[2 * MFEM_THREAD_SIZE(x)] * (a00 * a12 - a02 * a10)) *
418 dx[2] = (rhs[0 * MFEM_THREAD_SIZE(x)] * (a10 * a21 - a11 * a20) -
419 rhs[1 * MFEM_THREAD_SIZE(x)] * (a00 * a21 - a01 * a20) +
420 rhs[2 * MFEM_THREAD_SIZE(x)] * (a00 * a11 - a01 * a10)) *
425template <
int Geom, InverseElementTransformation::SolverType SolverType>
431 static MFEM_HOST_DEVICE
bool project(real_t &x, real_t &dx)
441 static MFEM_HOST_DEVICE
bool project(real_t &x, real_t &y, real_t &dx,
453 static MFEM_HOST_DEVICE
bool project(real_t &x, real_t &y, real_t &z,
454 real_t &dx, real_t &dy, real_t &dz)
464struct ProjectType<Geom, InverseElementTransformation::NewtonElementProject>
466 template <
class... Ts>
static MFEM_HOST_DEVICE
bool project(Ts &&...args)
468 return eltrans::GeometryUtils<Geom>::project(args...);
472template <
int Geom,
int SDim,
474struct InvTNewtonSolver;
478struct InvTNewtonSolver<Geometry::SEGMENT, SDim, SType, max_team_x>
479 :
public InvTNewtonSolverBase
481 static int ndofs(
int ndof1d) {
return ndof1d; }
484 static constexpr MFEM_HOST_DEVICE
int max_dof1d() {
return 0x1000; }
486 int MFEM_HOST_DEVICE operator()(
int idx)
const
489 constexpr int Dim = 1;
491 MFEM_SHARED
real_t ref_coord[Dim];
493 MFEM_SHARED
real_t phys_coord[SDim * max_team_x];
495 MFEM_SHARED
real_t jac[SDim * Dim * max_team_x];
496 MFEM_SHARED
bool term_flag[1];
497 MFEM_SHARED
int res[1];
498 MFEM_SHARED
real_t dx[Dim];
499 MFEM_SHARED
real_t prev_dx[Dim];
500 MFEM_SHARED
bool hit_bdr[1];
501 MFEM_SHARED
bool prev_hit_bdr[1];
503 if (MFEM_THREAD_ID(x) == 0)
505 term_flag[0] =
false;
506 res[0] = InverseElementTransformation::Unknown;
507 for (
int d = 0; d < Dim; ++d)
509 ref_coord[d] = xptr[idx + d * npts];
513 for (
int d = 0; d < SDim; ++d)
515 phys_tol += pptr[idx + d * npts] * pptr[idx + d * npts];
517 phys_tol = fmax(phys_rtol * phys_rtol, phys_tol * phys_rtol * phys_rtol);
524 for (
int d = 0; d < SDim; ++d)
526 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
528 for (
int i = 0; i < SDim * Dim; ++i)
530 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
533 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
536 basis1d.eval_d1(b0, db0, ref_coord[0], j0);
537 for (
int d = 0; d < SDim; ++d)
539 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
540 mptr[j0 + (eptr[idx] * SDim + d) * basis1d.pN] * b0;
541 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
542 mptr[j0 + (eptr[idx] * SDim + d) * basis1d.pN] * db0;
546 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
549 int a = MFEM_THREAD_ID(x);
551 if (
a < i &&
b < basis1d.pN)
553 for (
int d = 0; d < SDim; ++d)
555 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
556 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
558 for (
int j = 0; j < SDim * Dim; ++j)
560 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
561 jac[
b + j * MFEM_THREAD_SIZE(x)];
568 if (MFEM_THREAD_ID(x) == 0)
573 for (
int d = 0; d < SDim; ++d)
576 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
577 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
582 if (dist <= phys_tol)
585 res[0] = eltrans::GeometryUtils<Geometry::SEGMENT>::inside(
587 ? InverseElementTransformation::Inside
588 : InverseElementTransformation::Outside;
590 for (
int d = 0; d < Dim; ++d)
592 xptr[idx + d * npts] = ref_coord[d];
596 iter_ptr[idx] = iter + 1;
600 else if (iter >= max_iter)
603 tptr[idx] = InverseElementTransformation::Unknown;
604 res[0] = InverseElementTransformation::Unknown;
606 for (
int d = 0; d < Dim; ++d)
608 xptr[idx + d * npts] = ref_coord[d];
612 iter_ptr[idx] = iter + 1;
619 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
621 hit_bdr[0] = ProjectType<Geometry::SEGMENT, SType>::project(
622 ref_coord[0], dx[0]);
630 for (
int d = 0; d < Dim; ++d)
632 real_t tmp = dx[d] - prev_dx[d];
633 dx_change += tmp * tmp;
635 if (dx_change <= ref_tol * ref_tol)
638 tptr[idx] = InverseElementTransformation::Outside;
639 res[0] = InverseElementTransformation::Outside;
640 for (
int d = 0; d < Dim; ++d)
642 xptr[idx + d * npts] = ref_coord[d];
646 iter_ptr[idx] = iter + 1;
653 prev_hit_bdr[0] = hit_bdr[0];
662 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
670struct InvTNewtonSolver<Geometry::SQUARE, SDim, SType, max_team_x>
671 :
public InvTNewtonSolverBase
673 static int ndofs(
int ndof1d) {
return ndof1d * ndof1d; }
675 static constexpr MFEM_HOST_DEVICE
int max_dof1d() {
return 32; }
677 int MFEM_HOST_DEVICE operator()(
int idx)
const
680 constexpr int Dim = 2;
682 MFEM_SHARED
real_t ref_coord[Dim];
684 MFEM_SHARED
real_t phys_coord[SDim * max_team_x];
685 MFEM_SHARED
real_t basis0[max_dof1d()];
686 MFEM_SHARED
real_t dbasis0[max_dof1d()];
687 MFEM_SHARED
real_t basis1[max_dof1d()];
688 MFEM_SHARED
real_t dbasis1[max_dof1d()];
690 MFEM_SHARED
real_t jac[SDim * Dim * max_team_x];
691 MFEM_SHARED
bool term_flag[1];
692 MFEM_SHARED
int res[1];
693 MFEM_SHARED
real_t dx[Dim];
694 MFEM_SHARED
real_t prev_dx[Dim];
695 MFEM_SHARED
bool hit_bdr[1];
696 MFEM_SHARED
bool prev_hit_bdr[1];
698 if (MFEM_THREAD_ID(x) == 0)
700 term_flag[0] =
false;
701 res[0] = InverseElementTransformation::Unknown;
703 prev_hit_bdr[0] =
false;
704 for (
int d = 0; d < Dim; ++d)
706 ref_coord[d] = xptr[idx + d * npts];
710 for (
int d = 0; d < SDim; ++d)
712 phys_tol += pptr[idx + d * npts] * pptr[idx + d * npts];
714 phys_tol = fmax(phys_rtol * phys_rtol, phys_tol * phys_rtol * phys_rtol);
721 for (
int d = 0; d < SDim; ++d)
723 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
725 for (
int i = 0; i < SDim * Dim; ++i)
727 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
729 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
731 basis1d.eval_d1(basis0[j0], dbasis0[j0], ref_coord[0], j0);
732 basis1d.eval_d1(basis1[j0], dbasis1[j0], ref_coord[1], j0);
735 MFEM_FOREACH_THREAD(jidx, x, basis1d.pN * basis1d.pN)
738 idcs[0] = jidx % basis1d.pN;
739 idcs[1] = jidx / basis1d.pN;
740 for (
int d = 0; d < SDim; ++d)
742 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
744 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
746 basis0[idcs[0]] * basis1[idcs[1]];
747 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
749 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
751 dbasis0[idcs[0]] * basis1[idcs[1]];
752 jac[MFEM_THREAD_ID(x) + (d + 1 * SDim) * MFEM_THREAD_SIZE(x)] +=
754 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
756 basis0[idcs[0]] * dbasis1[idcs[1]];
760 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
763 int a = MFEM_THREAD_ID(x);
765 if (
a < i &&
b < basis1d.pN * basis1d.pN)
767 for (
int d = 0; d < SDim; ++d)
769 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
770 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
772 for (
int j = 0; j < SDim * Dim; ++j)
774 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
775 jac[
b + j * MFEM_THREAD_SIZE(x)];
782 if (MFEM_THREAD_ID(x) == 0)
787 for (
int d = 0; d < SDim; ++d)
790 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
791 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
796 if (dist <= phys_tol)
799 res[0] = eltrans::GeometryUtils<Geometry::SQUARE>::inside(
800 ref_coord[0], ref_coord[1])
801 ? InverseElementTransformation::Inside
802 : InverseElementTransformation::Outside;
804 for (
int d = 0; d < Dim; ++d)
806 xptr[idx + d * npts] = ref_coord[d];
810 iter_ptr[idx] = iter + 1;
814 else if (iter >= max_iter)
817 tptr[idx] = InverseElementTransformation::Unknown;
818 res[0] = InverseElementTransformation::Unknown;
820 for (
int d = 0; d < Dim; ++d)
822 xptr[idx + d * npts] = ref_coord[d];
826 iter_ptr[idx] = iter + 1;
833 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
835 hit_bdr[0] = ProjectType<Geometry::SQUARE, SType>::project(
836 ref_coord[0], ref_coord[1], dx[0], dx[1]);
844 for (
int d = 0; d < Dim; ++d)
846 real_t tmp = dx[d] - prev_dx[d];
847 dx_change += tmp * tmp;
849 if (dx_change <= ref_tol * ref_tol)
852 tptr[idx] = InverseElementTransformation::Outside;
853 res[0] = InverseElementTransformation::Outside;
854 for (
int d = 0; d < Dim; ++d)
856 xptr[idx + d * npts] = ref_coord[d];
860 iter_ptr[idx] = iter + 1;
867 prev_hit_bdr[0] = hit_bdr[0];
876 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
885struct InvTNewtonSolver<Geometry::CUBE, SDim, SType, max_team_x>
886 :
public InvTNewtonSolverBase
888 static int ndofs(
int ndof1d) {
return ndof1d * ndof1d * ndof1d; }
890 static constexpr MFEM_HOST_DEVICE
int max_dof1d() {
return 32; }
892 int MFEM_HOST_DEVICE operator()(
int idx)
const
895 constexpr int Dim = 3;
897 MFEM_SHARED
real_t ref_coord[Dim];
899 MFEM_SHARED
real_t phys_coord[SDim * max_team_x];
900 MFEM_SHARED
real_t basis0[max_dof1d()];
901 MFEM_SHARED
real_t dbasis0[max_dof1d()];
902 MFEM_SHARED
real_t basis1[max_dof1d()];
903 MFEM_SHARED
real_t dbasis1[max_dof1d()];
904 MFEM_SHARED
real_t basis2[max_dof1d()];
905 MFEM_SHARED
real_t dbasis2[max_dof1d()];
907 MFEM_SHARED
real_t jac[SDim * Dim * max_team_x];
908 MFEM_SHARED
bool term_flag[1];
909 MFEM_SHARED
int res[1];
910 MFEM_SHARED
real_t dx[Dim];
911 MFEM_SHARED
real_t prev_dx[Dim];
912 MFEM_SHARED
bool hit_bdr[1];
913 MFEM_SHARED
bool prev_hit_bdr[1];
915 if (MFEM_THREAD_ID(x) == 0)
917 term_flag[0] =
false;
918 res[0] = InverseElementTransformation::Unknown;
920 prev_hit_bdr[0] =
false;
921 for (
int d = 0; d < Dim; ++d)
923 ref_coord[d] = xptr[idx + d * npts];
927 for (
int d = 0; d < SDim; ++d)
929 phys_tol += pptr[idx + d * npts] * pptr[idx + d * npts];
931 phys_tol = fmax(phys_rtol * phys_rtol, phys_tol * phys_rtol * phys_rtol);
938 for (
int d = 0; d < SDim; ++d)
940 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
942 for (
int i = 0; i < SDim * Dim; ++i)
944 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
946 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
948 basis1d.eval_d1(basis0[j0], dbasis0[j0], ref_coord[0], j0);
949 basis1d.eval_d1(basis1[j0], dbasis1[j0], ref_coord[1], j0);
950 basis1d.eval_d1(basis2[j0], dbasis2[j0], ref_coord[2], j0);
953 MFEM_FOREACH_THREAD(jidx, x, basis1d.pN * basis1d.pN * basis1d.pN)
956 idcs[0] = jidx % basis1d.pN;
957 idcs[1] = jidx / basis1d.pN;
958 idcs[2] = idcs[1] / basis1d.pN;
959 idcs[1] %= basis1d.pN;
960 for (
int d = 0; d < SDim; ++d)
962 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
963 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
967 basis0[idcs[0]] * basis1[idcs[1]] * basis2[idcs[2]];
968 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
969 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
973 dbasis0[idcs[0]] * basis1[idcs[1]] * basis2[idcs[2]];
974 jac[MFEM_THREAD_ID(x) + (d + 1 * SDim) * MFEM_THREAD_SIZE(x)] +=
975 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
979 basis0[idcs[0]] * dbasis1[idcs[1]] * basis2[idcs[2]];
980 jac[MFEM_THREAD_ID(x) + (d + 2 * SDim) * MFEM_THREAD_SIZE(x)] +=
981 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
985 basis0[idcs[0]] * basis1[idcs[1]] * dbasis2[idcs[2]];
989 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
992 int a = MFEM_THREAD_ID(x);
994 if (
a < i &&
b < basis1d.pN * basis1d.pN * basis1d.pN)
996 for (
int d = 0; d < SDim; ++d)
998 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
999 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
1001 for (
int j = 0; j < SDim * Dim; ++j)
1003 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
1004 jac[
b + j * MFEM_THREAD_SIZE(x)];
1011 if (MFEM_THREAD_ID(x) == 0)
1016 for (
int d = 0; d < SDim; ++d)
1019 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
1020 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
1025 if (dist <= phys_tol)
1028 res[0] = eltrans::GeometryUtils<Geometry::CUBE>::inside(
1029 ref_coord[0], ref_coord[1], ref_coord[2])
1030 ? InverseElementTransformation::Inside
1031 : InverseElementTransformation::Outside;
1033 for (
int d = 0; d < Dim; ++d)
1035 xptr[idx + d * npts] = ref_coord[d];
1039 iter_ptr[idx] = iter + 1;
1041 term_flag[0] =
true;
1043 else if (iter >= max_iter)
1046 tptr[idx] = InverseElementTransformation::Unknown;
1047 res[0] = InverseElementTransformation::Unknown;
1049 for (
int d = 0; d < Dim; ++d)
1051 xptr[idx + d * npts] = ref_coord[d];
1055 iter_ptr[idx] = iter + 1;
1057 term_flag[0] =
true;
1062 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
1064 hit_bdr[0] = ProjectType<Geometry::CUBE, SType>::project(
1065 ref_coord[0], ref_coord[1], ref_coord[2], dx[0], dx[1],
1071 if (prev_hit_bdr[0])
1074 for (
int d = 0; d < Dim; ++d)
1076 real_t tmp = dx[d] - prev_dx[d];
1077 dx_change += tmp * tmp;
1079 if (dx_change <= ref_tol * ref_tol)
1082 tptr[idx] = InverseElementTransformation::Outside;
1083 res[0] = InverseElementTransformation::Outside;
1084 for (
int d = 0; d < Dim; ++d)
1086 xptr[idx + d * npts] = ref_coord[d];
1090 iter_ptr[idx] = iter + 1;
1092 term_flag[0] =
true;
1104 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
1123 eltrans::Lagrange basis1d;
1129template <
int Geom,
int SDim,
int max_team_x>
1130struct PhysDofFinder;
1132template <
int SDim,
int max_team_x>
1133struct PhysDofFinder<Geometry::SEGMENT, SDim, max_team_x>
1134 :
public DofFinderBase
1136 static int ndofs(
int ndofs1d) {
return ndofs1d; }
1138 void MFEM_HOST_DEVICE operator()(
int idx)
const
1140 constexpr int Dim = 1;
1142 MFEM_SHARED
real_t dists[max_team_x];
1143 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1144 MFEM_FOREACH_THREAD(i, x, max_team_x)
1146#ifdef MFEM_USE_DOUBLE
1147 dists[i] = HUGE_VAL;
1149 dists[i] = HUGE_VALF;
1154 MFEM_FOREACH_THREAD(i, x, basis1d.pN)
1157 for (
int d = 0; d < SDim; ++d)
1159 phys_coord[d] = mptr[i + (d + eptr[idx] * SDim) * basis1d.pN];
1163 for (
int d = 0; d < SDim; ++d)
1165 real_t tmp = phys_coord[d] - pptr[idx + d * npts];
1168 if (dist < dists[MFEM_THREAD_ID(x)])
1171 dists[MFEM_THREAD_ID(x)] = dist;
1172 ref_buf[MFEM_THREAD_ID(x)] = basis1d.z[i];
1176 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1179 if (MFEM_THREAD_ID(x) < i)
1181 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1183 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1184 ref_buf[MFEM_THREAD_ID(x)] = ref_buf[MFEM_THREAD_ID(x) + i];
1191 if (MFEM_THREAD_ID(x) == 0)
1193 xptr[idx] = ref_buf[0];
1198template <
int SDim,
int max_team_x>
1199struct PhysDofFinder<Geometry::SQUARE, SDim, max_team_x>
1200 :
public DofFinderBase
1202 static int ndofs(
int ndofs1d) {
return ndofs1d * ndofs1d; }
1204 void MFEM_HOST_DEVICE operator()(
int idx)
const
1206 constexpr int Dim = 2;
1207 int n = basis1d.pN * basis1d.pN;
1213 MFEM_SHARED
real_t dists[max_team_x];
1214 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1215 MFEM_FOREACH_THREAD(i, x, max_team_x)
1217#ifdef MFEM_USE_DOUBLE
1218 dists[i] = HUGE_VAL;
1220 dists[i] = HUGE_VALF;
1224 MFEM_FOREACH_THREAD(j, x, basis1d.pN * basis1d.pN)
1226 real_t phys_coord[SDim] = {0};
1228 idcs[0] = j % basis1d.pN;
1229 idcs[1] = j / basis1d.pN;
1230 for (
int d = 0; d < SDim; ++d)
1233 mptr[idcs[0] + (idcs[1] + (d + eptr[idx] * SDim) * basis1d.pN) *
1238 for (
int d = 0; d < SDim; ++d)
1240 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1243 if (dist < dists[MFEM_THREAD_ID(x)])
1246 dists[MFEM_THREAD_ID(x)] = dist;
1247 for (
int d = 0; d < Dim; ++d)
1249 ref_buf[MFEM_THREAD_ID(x) + d * n] = basis1d.z[idcs[d]];
1254 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1257 if (MFEM_THREAD_ID(x) < i)
1259 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1261 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1262 for (
int d = 0; d < Dim; ++d)
1264 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1265 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1272 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1276template <
int SDim,
int max_team_x>
1277struct PhysDofFinder<Geometry::CUBE, SDim, max_team_x>
1278 :
public DofFinderBase
1280 static int ndofs(
int ndofs1d) {
return ndofs1d * ndofs1d * ndofs1d; }
1282 void MFEM_HOST_DEVICE operator()(
int idx)
const
1284 constexpr int Dim = 3;
1285 int n = basis1d.pN * basis1d.pN * basis1d.pN;
1291 MFEM_SHARED
real_t dists[max_team_x];
1292 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1293 MFEM_FOREACH_THREAD(i, x, max_team_x)
1295#ifdef MFEM_USE_DOUBLE
1296 dists[i] = HUGE_VAL;
1298 dists[i] = HUGE_VALF;
1302 MFEM_FOREACH_THREAD(j, x, basis1d.pN * basis1d.pN * basis1d.pN)
1304 real_t phys_coord[SDim] = {0};
1306 idcs[0] = j % basis1d.pN;
1307 idcs[1] = j / basis1d.pN;
1308 idcs[2] = idcs[1] / basis1d.pN;
1309 idcs[1] = idcs[1] % basis1d.pN;
1310 for (
int d = 0; d < SDim; ++d)
1313 mptr[idcs[0] + (idcs[1] + (idcs[2] + (d + eptr[idx] * SDim) *
1320 for (
int d = 0; d < SDim; ++d)
1322 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1325 if (dist < dists[MFEM_THREAD_ID(x)])
1328 dists[MFEM_THREAD_ID(x)] = dist;
1329 for (
int d = 0; d < Dim; ++d)
1331 ref_buf[MFEM_THREAD_ID(x) + d * n] = basis1d.z[idcs[d]];
1336 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1339 if (MFEM_THREAD_ID(x) < i)
1341 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1343 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1344 for (
int d = 0; d < Dim; ++d)
1346 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1347 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1354 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1359struct NodeFinderBase
1371 eltrans::Lagrange basis1d;
1381template <
int Geom,
int SDim,
int max_team_x,
int max_q1d>
1382struct PhysNodeFinder;
1384template <
int SDim,
int max_team_x,
int max_q1d>
1385struct PhysNodeFinder<Geometry::SEGMENT, SDim, max_team_x, max_q1d>
1386 :
public NodeFinderBase
1389 static int compute_nq(
int nq1d) {
return nq1d; }
1391 static int ndofs(
int ndof1d) {
return ndof1d; }
1393 void MFEM_HOST_DEVICE operator()(
int idx)
const
1395 constexpr int Dim = 1;
1397 MFEM_SHARED
real_t dists[max_team_x];
1398 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1399 MFEM_FOREACH_THREAD(i, x, max_team_x)
1401#ifdef MFEM_USE_DOUBLE
1402 dists[i] = HUGE_VAL;
1404 dists[i] = HUGE_VALF;
1409 MFEM_FOREACH_THREAD(i, x, nq)
1411 real_t phys_coord[SDim] = {0};
1412 for (
int j0 = 0; j0 < basis1d.pN; ++j0)
1414 real_t b = basis1d.eval(qptr[i], j0);
1415 for (
int d = 0; d < SDim; ++d)
1418 mptr[j0 + (d + eptr[idx] * SDim) * basis1d.pN] *
b;
1423 for (
int d = 0; d < SDim; ++d)
1425 real_t tmp = phys_coord[d] - pptr[idx + d * npts];
1428 if (dist < dists[MFEM_THREAD_ID(x)])
1431 dists[MFEM_THREAD_ID(x)] = dist;
1432 ref_buf[MFEM_THREAD_ID(x)] = qptr[i];
1436 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1439 if (MFEM_THREAD_ID(x) < i)
1441 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1443 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1444 ref_buf[MFEM_THREAD_ID(x)] = ref_buf[MFEM_THREAD_ID(x) + i];
1451 if (MFEM_THREAD_ID(x) == 0)
1453 xptr[idx] = ref_buf[0];
1458template <
int SDim,
int max_team_x,
int max_q1d>
1459struct PhysNodeFinder<Geometry::SQUARE, SDim, max_team_x, max_q1d>
1460 :
public NodeFinderBase
1463 static int compute_nq(
int nq1d) {
return nq1d * nq1d; }
1465 static int ndofs(
int ndof1d)
1467 return ndof1d * ndof1d;
1470 void MFEM_HOST_DEVICE operator()(
int idx)
const
1472 constexpr int Dim = 2;
1473 constexpr int max_dof1d = 32;
1474 int n = (nq < max_team_x) ? nq : max_team_x;
1476 MFEM_SHARED
real_t dists[max_team_x];
1477 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1478 MFEM_SHARED
real_t basis[max_dof1d * max_q1d];
1479 MFEM_FOREACH_THREAD(i, x, max_team_x)
1481#ifdef MFEM_USE_DOUBLE
1482 dists[i] = HUGE_VAL;
1484 dists[i] = HUGE_VALF;
1487 MFEM_FOREACH_THREAD(j0, x, nq1d)
1489 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1491 basis[j0 + i0 * nq1d] = basis1d.eval(qptr[j0], i0);
1496 MFEM_FOREACH_THREAD(j, x, nq)
1498 real_t phys_coord[SDim] = {0};
1502 for (
int i1 = 0; i1 < basis1d.pN; ++i1)
1504 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1506 real_t b = basis[idcs[0] + i0 * nq1d] * basis[idcs[1] + i1 * nq1d];
1507 for (
int d = 0; d < SDim; ++d)
1510 mptr[i0 + (i1 + (d + eptr[idx] * SDim) * basis1d.pN) *
1518 for (
int d = 0; d < SDim; ++d)
1520 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1523 if (dist < dists[MFEM_THREAD_ID(x)])
1526 dists[MFEM_THREAD_ID(x)] = dist;
1527 for (
int d = 0; d < Dim; ++d)
1529 ref_buf[MFEM_THREAD_ID(x) + d * n] = qptr[idcs[d]];
1534 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1537 if (MFEM_THREAD_ID(x) < i)
1539 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1541 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1542 for (
int d = 0; d < Dim; ++d)
1544 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1545 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1552 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1556template <
int SDim,
int max_team_x,
int max_q1d>
1557struct PhysNodeFinder<Geometry::CUBE, SDim, max_team_x, max_q1d>
1558 :
public NodeFinderBase
1561 static int compute_nq(
int nq1d) {
return nq1d * nq1d * nq1d; }
1563 static int ndofs(
int ndof1d)
1565 return ndof1d * ndof1d * ndof1d;
1568 void MFEM_HOST_DEVICE operator()(
int idx)
const
1570 constexpr int Dim = 3;
1571 constexpr int max_dof1d = 32;
1572 int n = (nq < max_team_x) ? nq : max_team_x;
1574 MFEM_SHARED
real_t dists[max_team_x];
1575 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1577 MFEM_SHARED
real_t basis[max_dof1d * max_q1d];
1578 MFEM_FOREACH_THREAD(i, x, max_team_x)
1580#ifdef MFEM_USE_DOUBLE
1581 dists[i] = HUGE_VAL;
1583 dists[i] = HUGE_VALF;
1586 MFEM_FOREACH_THREAD(j0, x, nq1d)
1588 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1590 basis[j0 + i0 * nq1d] = basis1d.eval(qptr[j0], i0);
1595 MFEM_FOREACH_THREAD(j, x, nq)
1597 real_t phys_coord[SDim] = {0};
1601 idcs[2] = idcs[1] / nq1d;
1602 idcs[1] = idcs[1] % nq1d;
1603 for (
int i2 = 0; i2 < basis1d.pN; ++i2)
1605 for (
int i1 = 0; i1 < basis1d.pN; ++i1)
1607 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1609 real_t b = basis[idcs[0] + i0 * nq1d] * basis[idcs[1] + i1 * nq1d] *
1610 basis[idcs[2] + i2 * nq1d];
1611 for (
int d = 0; d < SDim; ++d)
1615 (i1 + (i2 + (d + eptr[idx] * SDim) * basis1d.pN) *
1625 for (
int d = 0; d < SDim; ++d)
1627 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1630 if (dist < dists[MFEM_THREAD_ID(x)])
1633 dists[MFEM_THREAD_ID(x)] = dist;
1634 for (
int d = 0; d < Dim; ++d)
1636 ref_buf[MFEM_THREAD_ID(x) + d * n] = qptr[idcs[d]];
1641 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1644 if (MFEM_THREAD_ID(x) < i)
1646 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1648 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1649 for (
int d = 0; d < Dim; ++d)
1651 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1652 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1659 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1663template <
int Geom,
int SDim,
bool use_device>
1664static void ClosestPhysNodeImpl(
int npts,
int nelems,
int ndof1d,
int nq1d,
1666 const int *eptr,
const real_t *nptr,
1669 constexpr int max_team_x = 64;
1670 constexpr int max_q1d = 128;
1671 PhysNodeFinder<Geom, SDim, max_team_x, max_q1d> func;
1672 MFEM_VERIFY(ndof1d <= 32,
"maximum of 32 dofs per dim is allowed");
1673 MFEM_VERIFY(nq1d <= max_q1d,
"maximum of 128 test points per dim is allowed");
1674 func.basis1d.z = nptr;
1675 func.basis1d.pN = ndof1d;
1683 func.nq = func.compute_nq(nq1d);
1687 int team_x = max_team_x;
1690 if (team_x <= func.nq)
1696 team_x = std::min<int>(max_team_x, 2 * team_x);
1705template <
int Geom,
int SDim,
bool use_device>
1706static void ClosestPhysDofImpl(
int npts,
int nelems,
int ndof1d,
1708 const int *eptr,
const real_t *nptr,
1711 constexpr int max_team_x = 64;
1712 PhysDofFinder<Geom, SDim, max_team_x> func;
1713 func.basis1d.z = nptr;
1714 func.basis1d.pN = ndof1d;
1722 int team_x = max_team_x;
1723 int ndof = func.ndofs(ndof1d);
1732 team_x = std::min<int>(max_team_x, 2 * team_x);
1741template <
int Geom,
int SDim,
bool use_device>
1742static void ClosestRefDofImpl(
int npts,
int nelems,
int ndof1d,
1744 const int *eptr,
const real_t *nptr,
1748 MFEM_ABORT(
"ClostestRefDofImpl not implemented yet");
1751template <
int Geom,
int SDim,
bool use_device>
1752static void ClosestRefNodeImpl(
int npts,
int nelems,
int ndof1d,
int nq1d,
1754 const int *eptr,
const real_t *nptr,
1758 MFEM_ABORT(
"ClostestRefNodeImpl not implemented yet");
1763static void NewtonSolveImpl(
real_t ref_tol,
real_t phys_rtol,
int max_iter,
1764 int npts,
int nelems,
int ndof1d,
1766 const int *eptr,
const real_t *nptr,
int *tptr,
1767 int *iter_ptr,
real_t *xptr)
1769 constexpr int max_team_x = use_device ? 64 : 1;
1770 InvTNewtonSolver<Geom, SDim, SType, max_team_x> func;
1771 MFEM_VERIFY(ndof1d <= func.max_dof1d(),
1772 "exceeded max_dof1d limit (32 for 2D/3D)");
1773 func.ref_tol = ref_tol;
1774 func.phys_rtol = phys_rtol;
1775 func.max_iter = max_iter;
1776 func.basis1d.z = nptr;
1777 func.basis1d.pN = ndof1d;
1782 func.iter_ptr = iter_ptr;
1787 int team_x = max_team_x;
1788 int ndof = func.ndofs(ndof1d);
1797 team_x = std::min<int>(max_team_x, 2 * team_x);
1806template <
int Geom,
int SDim,
1808struct InvTNewtonEdgeScanner
1810 InvTNewtonSolver<Geom, SDim, SolverType, max_team_x> solver;
1816 void MFEM_HOST_DEVICE operator()(
int idx)
const
1819 int res = InverseElementTransformation::Outside;
1820 for (
int i = 0; i < nq1d; ++i)
1822 for (
int d = 0; d < eltrans::GeometryUtils<Geom>::Dimension();
1825 if (MFEM_THREAD_ID(x) == 0)
1828 d2 < eltrans::GeometryUtils<Geom>::Dimension();
1831 solver.xptr[idx + d2 * solver.npts] = 0;
1833 solver.xptr[idx + d * solver.npts] = qptr[i];
1836 int res_tmp = solver(idx);
1839 case InverseElementTransformation::Inside:
1841 case InverseElementTransformation::Outside:
1843 case InverseElementTransformation::Unknown:
1844 res = InverseElementTransformation::Unknown;
1854 if (MFEM_THREAD_ID(x) == 0)
1856 solver.tptr[idx] = res;
1863static void NewtonEdgeScanImpl(
real_t ref_tol,
real_t phys_rtol,
int max_iter,
1864 int npts,
int nelems,
int ndof1d,
1866 const int *eptr,
const real_t *nptr,
1867 const real_t *qptr,
int nq1d,
int *tptr,
1868 int *iter_ptr,
real_t *xptr)
1870 constexpr int max_team_x = use_device ? 64 : 1;
1871 InvTNewtonEdgeScanner<Geom, SDim, SType, max_team_x> func;
1872 MFEM_VERIFY(ndof1d <= func.solver.max_dof1d(),
1873 "exceeded max_dof1d limit (32 for 2D/3D)");
1874 func.solver.ref_tol = ref_tol;
1875 func.solver.phys_rtol = phys_rtol;
1876 func.solver.max_iter = max_iter;
1877 func.solver.basis1d.z = nptr;
1878 func.solver.basis1d.pN = ndof1d;
1879 func.solver.mptr = mptr;
1880 func.solver.pptr = pptr;
1881 func.solver.eptr = eptr;
1882 func.solver.xptr = xptr;
1883 func.solver.iter_ptr = iter_ptr;
1884 func.solver.tptr = tptr;
1885 func.solver.npts = npts;
1890 int team_x = max_team_x;
1891 int ndof = func.solver.ndofs(ndof1d);
1900 team_x = std::min<int>(max_team_x, 2 * team_x);
1911template <
int Geom,
int SDim,
bool use_device>
1913BatchInverseElementTransformation::FindClosestPhysPoint::Kernel()
1915 return internal::ClosestPhysNodeImpl<Geom, SDim, use_device>;
1918template <
int Geom,
int SDim,
bool use_device>
1920BatchInverseElementTransformation::FindClosestPhysDof::Kernel()
1922 return internal::ClosestPhysDofImpl<Geom, SDim, use_device>;
1925template <
int Geom,
int SDim,
bool use_device>
1927BatchInverseElementTransformation::FindClosestRefPoint::Kernel()
1929 return internal::ClosestRefNodeImpl<Geom, SDim, use_device>;
1932template <
int Geom,
int SDim,
bool use_device>
1934BatchInverseElementTransformation::FindClosestRefDof::Kernel()
1936 return internal::ClosestRefDofImpl<Geom, SDim, use_device>;
1942BatchInverseElementTransformation::NewtonSolve::Kernel()
1944 return internal::NewtonSolveImpl<Geom, SDim, SType, use_device>;
1950BatchInverseElementTransformation::NewtonEdgeScan::Kernel()
1952 return internal::NewtonEdgeScanImpl<Geom, SDim, SType, use_device>;
1956BatchInverseElementTransformation::FindClosestPhysPoint::Fallback(
int,
int,
1959 MFEM_ABORT(
"Invalid Geom/SDim combination");
1963BatchInverseElementTransformation::FindClosestRefPoint::Fallback(
int,
int,
1966 MFEM_ABORT(
"Invalid Geom/SDim combination");
1970BatchInverseElementTransformation::NewtonSolve::Fallback(
1973 MFEM_ABORT(
"Invalid Geom/SDim/SolverType combination");
1977BatchInverseElementTransformation::NewtonEdgeScan::Fallback(
1980 MFEM_ABORT(
"Invalid Geom/SDim/SolverType combination");
1984BatchInverseElementTransformation::FindClosestPhysDof::Fallback(
int,
int,
bool)
1986 MFEM_ABORT(
"Invalid Geom/SDim combination");
1990BatchInverseElementTransformation::FindClosestRefDof::Fallback(
int,
int,
bool)
1992 MFEM_ABORT(
"Invalid Geom/SDim combination");
2003 constexpr auto NewtonElementProject =
2006 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 1>();
2007 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 2>();
2008 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 3>();
2010 BatchInvTr::AddFindClosestSpecialization<SQUARE, 2>();
2011 BatchInvTr::AddFindClosestSpecialization<SQUARE, 3>();
2013 BatchInvTr::AddFindClosestSpecialization<CUBE, 3>();
2016 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 1, Newton>();
2017 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 2, Newton>();
2018 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 3, Newton>();
2020 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 1, NewtonElementProject>();
2021 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 2, NewtonElementProject>();
2022 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 3, NewtonElementProject>();
2024 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 2, Newton>();
2025 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 3, Newton>();
2026 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 2, NewtonElementProject>();
2027 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 3, NewtonElementProject>();
2029 BatchInvTr::AddNewtonSolveSpecialization<CUBE, 3, Newton>();
2030 BatchInvTr::AddNewtonSolveSpecialization<CUBE, 3, NewtonElementProject>();
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
static int Check(int b_type)
If the input does not represents a valid BasisType, abort with an error; otherwise return the input.
@ GaussLobatto
Closed type.
@ ClosedUniform
Nodes: x_i = i/(n-1), i=0,...,n-1.
static int GetNodalBasis(int qpt_type)
Return the nodal BasisType corresponding to the Quadrature1D type.
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
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.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
int GetNE() const
Returns number of elements in the mesh.
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
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...
int GetDim() const
Returns the reference space dimension for the finite element.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
const IntegrationPoint & GetCenter(int GeomType) const
Return the center of the given Geometry::Type, GeomType.
Class for grid function - Vector with associated FE space.
FiniteElementSpace * FESpace()
virtual void GetVectorValue(int i, const IntegrationPoint &ip, Vector &val) const
Class for integration point with weight.
int Dimension() const
Dimension of the reference space used within the elements.
void GetNodes(Vector &node_coord) const
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
const Array< real_t > * GetPointsArray(const int p, const int btype)
Get the coordinates of the points of the given BasisType, btype.
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 SetSize(int s)
Resize the vector to size s.
virtual real_t * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
1D Lagrange basis from [0, 1]
void forall_2D(int N, int X, int Y, lambda &&body)
MemoryType
Memory types supported by MFEM.
void forall_switch(bool use_dev, int N, lambda &&body)
void solve(Mesh &mesh, GridFunction &color, socketstream &sock)
@ DEVICE_MASK
Biwise-OR of all device backends.
void pts(int iphi, int t, real_t x[])