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>
294 dx[0] = rhs[0] / jac[0];
298template <>
struct InvTLinSolve<1, 2>
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>
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>
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>
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>
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)
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);
518 hit_bdr[0] = prev_hit_bdr[0] =
false;
525 for (
int d = 0; d < SDim; ++d)
527 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
529 for (
int i = 0; i < SDim * Dim; ++i)
531 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
534 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
537 basis1d.eval_d1(b0, db0, ref_coord[0], j0);
538 for (
int d = 0; d < SDim; ++d)
540 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
541 mptr[j0 + (eptr[idx] * SDim + d) * basis1d.pN] * b0;
542 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
543 mptr[j0 + (eptr[idx] * SDim + d) * basis1d.pN] * db0;
547 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
550 int a = MFEM_THREAD_ID(x);
552 if (
a < i &&
b < basis1d.pN)
554 for (
int d = 0; d < SDim; ++d)
556 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
557 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
559 for (
int j = 0; j < SDim * Dim; ++j)
561 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
562 jac[
b + j * MFEM_THREAD_SIZE(x)];
569 if (MFEM_THREAD_ID(x) == 0)
574 for (
int d = 0; d < SDim; ++d)
577 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
578 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
583 if (dist <= phys_tol)
586 res[0] = eltrans::GeometryUtils<Geometry::SEGMENT>::inside(
588 ? InverseElementTransformation::Inside
589 : InverseElementTransformation::Outside;
591 for (
int d = 0; d < Dim; ++d)
593 xptr[idx + d * npts] = ref_coord[d];
597 iter_ptr[idx] = iter + 1;
601 else if (iter >= max_iter)
604 tptr[idx] = InverseElementTransformation::Unknown;
605 res[0] = InverseElementTransformation::Unknown;
607 for (
int d = 0; d < Dim; ++d)
609 xptr[idx + d * npts] = ref_coord[d];
613 iter_ptr[idx] = iter + 1;
620 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
622 hit_bdr[0] = ProjectType<Geometry::SEGMENT, SType>::project(
623 ref_coord[0], dx[0]);
631 for (
int d = 0; d < Dim; ++d)
633 real_t tmp = dx[d] - prev_dx[d];
634 dx_change += tmp * tmp;
636 if (dx_change <= ref_tol * ref_tol)
639 tptr[idx] = InverseElementTransformation::Outside;
640 res[0] = InverseElementTransformation::Outside;
641 for (
int d = 0; d < Dim; ++d)
643 xptr[idx + d * npts] = ref_coord[d];
647 iter_ptr[idx] = iter + 1;
654 prev_hit_bdr[0] = hit_bdr[0];
663 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
671struct InvTNewtonSolver<Geometry::SQUARE, SDim, SType, max_team_x>
672 :
public InvTNewtonSolverBase
674 static int ndofs(
int ndof1d) {
return ndof1d * ndof1d; }
676 static constexpr MFEM_HOST_DEVICE
int max_dof1d() {
return 32; }
678 int MFEM_HOST_DEVICE operator()(
int idx)
const
681 constexpr int Dim = 2;
683 MFEM_SHARED
real_t ref_coord[Dim];
685 MFEM_SHARED
real_t phys_coord[SDim * max_team_x];
686 MFEM_SHARED
real_t basis0[max_dof1d()];
687 MFEM_SHARED
real_t dbasis0[max_dof1d()];
688 MFEM_SHARED
real_t basis1[max_dof1d()];
689 MFEM_SHARED
real_t dbasis1[max_dof1d()];
691 MFEM_SHARED
real_t jac[SDim * Dim * max_team_x];
692 MFEM_SHARED
bool term_flag[1];
693 MFEM_SHARED
int res[1];
694 MFEM_SHARED
real_t dx[Dim];
695 MFEM_SHARED
real_t prev_dx[Dim];
696 MFEM_SHARED
bool hit_bdr[1];
697 MFEM_SHARED
bool prev_hit_bdr[1];
699 if (MFEM_THREAD_ID(x) == 0)
701 term_flag[0] =
false;
702 res[0] = InverseElementTransformation::Unknown;
704 prev_hit_bdr[0] =
false;
705 for (
int d = 0; d < Dim; ++d)
707 ref_coord[d] = xptr[idx + d * npts];
711 for (
int d = 0; d < SDim; ++d)
713 phys_tol += pptr[idx + d * npts] * pptr[idx + d * npts];
715 phys_tol = fmax(phys_rtol * phys_rtol, phys_tol * phys_rtol * phys_rtol);
722 for (
int d = 0; d < SDim; ++d)
724 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
726 for (
int i = 0; i < SDim * Dim; ++i)
728 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
730 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
732 basis1d.eval_d1(basis0[j0], dbasis0[j0], ref_coord[0], j0);
733 basis1d.eval_d1(basis1[j0], dbasis1[j0], ref_coord[1], j0);
736 MFEM_FOREACH_THREAD(jidx, x, basis1d.pN * basis1d.pN)
739 idcs[0] = jidx % basis1d.pN;
740 idcs[1] = jidx / basis1d.pN;
741 for (
int d = 0; d < SDim; ++d)
743 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
745 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
747 basis0[idcs[0]] * basis1[idcs[1]];
748 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
750 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
752 dbasis0[idcs[0]] * basis1[idcs[1]];
753 jac[MFEM_THREAD_ID(x) + (d + 1 * SDim) * MFEM_THREAD_SIZE(x)] +=
755 (idcs[1] + (eptr[idx] * SDim + d) * basis1d.pN) *
757 basis0[idcs[0]] * dbasis1[idcs[1]];
761 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
764 int a = MFEM_THREAD_ID(x);
766 if (
a < i &&
b < basis1d.pN * basis1d.pN)
768 for (
int d = 0; d < SDim; ++d)
770 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
771 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
773 for (
int j = 0; j < SDim * Dim; ++j)
775 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
776 jac[
b + j * MFEM_THREAD_SIZE(x)];
783 if (MFEM_THREAD_ID(x) == 0)
788 for (
int d = 0; d < SDim; ++d)
791 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
792 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
797 if (dist <= phys_tol)
800 res[0] = eltrans::GeometryUtils<Geometry::SQUARE>::inside(
801 ref_coord[0], ref_coord[1])
802 ? InverseElementTransformation::Inside
803 : InverseElementTransformation::Outside;
805 for (
int d = 0; d < Dim; ++d)
807 xptr[idx + d * npts] = ref_coord[d];
811 iter_ptr[idx] = iter + 1;
815 else if (iter >= max_iter)
818 tptr[idx] = InverseElementTransformation::Unknown;
819 res[0] = InverseElementTransformation::Unknown;
821 for (
int d = 0; d < Dim; ++d)
823 xptr[idx + d * npts] = ref_coord[d];
827 iter_ptr[idx] = iter + 1;
834 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
836 hit_bdr[0] = ProjectType<Geometry::SQUARE, SType>::project(
837 ref_coord[0], ref_coord[1], dx[0], dx[1]);
845 for (
int d = 0; d < Dim; ++d)
847 real_t tmp = dx[d] - prev_dx[d];
848 dx_change += tmp * tmp;
850 if (dx_change <= ref_tol * ref_tol)
853 tptr[idx] = InverseElementTransformation::Outside;
854 res[0] = InverseElementTransformation::Outside;
855 for (
int d = 0; d < Dim; ++d)
857 xptr[idx + d * npts] = ref_coord[d];
861 iter_ptr[idx] = iter + 1;
868 prev_hit_bdr[0] = hit_bdr[0];
877 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
886struct InvTNewtonSolver<Geometry::CUBE, SDim, SType, max_team_x>
887 :
public InvTNewtonSolverBase
889 static int ndofs(
int ndof1d) {
return ndof1d * ndof1d * ndof1d; }
891 static constexpr MFEM_HOST_DEVICE
int max_dof1d() {
return 32; }
893 int MFEM_HOST_DEVICE operator()(
int idx)
const
896 constexpr int Dim = 3;
898 MFEM_SHARED
real_t ref_coord[Dim];
900 MFEM_SHARED
real_t phys_coord[SDim * max_team_x];
901 MFEM_SHARED
real_t basis0[max_dof1d()];
902 MFEM_SHARED
real_t dbasis0[max_dof1d()];
903 MFEM_SHARED
real_t basis1[max_dof1d()];
904 MFEM_SHARED
real_t dbasis1[max_dof1d()];
905 MFEM_SHARED
real_t basis2[max_dof1d()];
906 MFEM_SHARED
real_t dbasis2[max_dof1d()];
908 MFEM_SHARED
real_t jac[SDim * Dim * max_team_x];
909 MFEM_SHARED
bool term_flag[1];
910 MFEM_SHARED
int res[1];
911 MFEM_SHARED
real_t dx[Dim];
912 MFEM_SHARED
real_t prev_dx[Dim];
913 MFEM_SHARED
bool hit_bdr[1];
914 MFEM_SHARED
bool prev_hit_bdr[1];
916 if (MFEM_THREAD_ID(x) == 0)
918 term_flag[0] =
false;
919 res[0] = InverseElementTransformation::Unknown;
921 prev_hit_bdr[0] =
false;
922 for (
int d = 0; d < Dim; ++d)
924 ref_coord[d] = xptr[idx + d * npts];
928 for (
int d = 0; d < SDim; ++d)
930 phys_tol += pptr[idx + d * npts] * pptr[idx + d * npts];
932 phys_tol = fmax(phys_rtol * phys_rtol, phys_tol * phys_rtol * phys_rtol);
939 for (
int d = 0; d < SDim; ++d)
941 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] = 0;
943 for (
int i = 0; i < SDim * Dim; ++i)
945 jac[MFEM_THREAD_ID(x) + i * MFEM_THREAD_SIZE(x)] = 0;
947 MFEM_FOREACH_THREAD(j0, x, basis1d.pN)
949 basis1d.eval_d1(basis0[j0], dbasis0[j0], ref_coord[0], j0);
950 basis1d.eval_d1(basis1[j0], dbasis1[j0], ref_coord[1], j0);
951 basis1d.eval_d1(basis2[j0], dbasis2[j0], ref_coord[2], j0);
954 MFEM_FOREACH_THREAD(jidx, x, basis1d.pN * basis1d.pN * basis1d.pN)
957 idcs[0] = jidx % basis1d.pN;
958 idcs[1] = jidx / basis1d.pN;
959 idcs[2] = idcs[1] / basis1d.pN;
960 idcs[1] %= basis1d.pN;
961 for (
int d = 0; d < SDim; ++d)
963 phys_coord[MFEM_THREAD_ID(x) + d * MFEM_THREAD_SIZE(x)] +=
964 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
968 basis0[idcs[0]] * basis1[idcs[1]] * basis2[idcs[2]];
969 jac[MFEM_THREAD_ID(x) + (d + 0 * SDim) * MFEM_THREAD_SIZE(x)] +=
970 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
974 dbasis0[idcs[0]] * basis1[idcs[1]] * basis2[idcs[2]];
975 jac[MFEM_THREAD_ID(x) + (d + 1 * SDim) * MFEM_THREAD_SIZE(x)] +=
976 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
980 basis0[idcs[0]] * dbasis1[idcs[1]] * basis2[idcs[2]];
981 jac[MFEM_THREAD_ID(x) + (d + 2 * SDim) * MFEM_THREAD_SIZE(x)] +=
982 mptr[idcs[0] + (idcs[1] + (idcs[2] + (eptr[idx] * SDim + d) *
986 basis0[idcs[0]] * basis1[idcs[1]] * dbasis2[idcs[2]];
990 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
993 int a = MFEM_THREAD_ID(x);
995 if (
a < i &&
b < basis1d.pN * basis1d.pN * basis1d.pN)
997 for (
int d = 0; d < SDim; ++d)
999 phys_coord[
a + d * MFEM_THREAD_SIZE(x)] +=
1000 phys_coord[
b + d * MFEM_THREAD_SIZE(x)];
1002 for (
int j = 0; j < SDim * Dim; ++j)
1004 jac[
a + j * MFEM_THREAD_SIZE(x)] +=
1005 jac[
b + j * MFEM_THREAD_SIZE(x)];
1012 if (MFEM_THREAD_ID(x) == 0)
1017 for (
int d = 0; d < SDim; ++d)
1020 pptr[idx + d * npts] - phys_coord[d * MFEM_THREAD_SIZE(x)];
1021 phys_coord[d * MFEM_THREAD_SIZE(x)] = tmp;
1026 if (dist <= phys_tol)
1029 res[0] = eltrans::GeometryUtils<Geometry::CUBE>::inside(
1030 ref_coord[0], ref_coord[1], ref_coord[2])
1031 ? InverseElementTransformation::Inside
1032 : InverseElementTransformation::Outside;
1034 for (
int d = 0; d < Dim; ++d)
1036 xptr[idx + d * npts] = ref_coord[d];
1040 iter_ptr[idx] = iter + 1;
1042 term_flag[0] =
true;
1044 else if (iter >= max_iter)
1047 tptr[idx] = InverseElementTransformation::Unknown;
1048 res[0] = InverseElementTransformation::Unknown;
1050 for (
int d = 0; d < Dim; ++d)
1052 xptr[idx + d * npts] = ref_coord[d];
1056 iter_ptr[idx] = iter + 1;
1058 term_flag[0] =
true;
1063 InvTLinSolve<Dim, SDim>::solve(jac, phys_coord, dx);
1065 hit_bdr[0] = ProjectType<Geometry::CUBE, SType>::project(
1066 ref_coord[0], ref_coord[1], ref_coord[2], dx[0], dx[1],
1072 if (prev_hit_bdr[0])
1075 for (
int d = 0; d < Dim; ++d)
1077 real_t tmp = dx[d] - prev_dx[d];
1078 dx_change += tmp * tmp;
1080 if (dx_change <= ref_tol * ref_tol)
1083 tptr[idx] = InverseElementTransformation::Outside;
1084 res[0] = InverseElementTransformation::Outside;
1085 for (
int d = 0; d < Dim; ++d)
1087 xptr[idx + d * npts] = ref_coord[d];
1091 iter_ptr[idx] = iter + 1;
1093 term_flag[0] =
true;
1105 MFEM_FOREACH_THREAD(d, x, Dim) { prev_dx[d] = dx[d]; }
1124 eltrans::Lagrange basis1d;
1130template <
int Geom,
int SDim,
int max_team_x>
1131struct PhysDofFinder;
1133template <
int SDim,
int max_team_x>
1134struct PhysDofFinder<Geometry::SEGMENT, SDim, max_team_x>
1135 :
public DofFinderBase
1137 static int ndofs(
int ndofs1d) {
return ndofs1d; }
1139 void MFEM_HOST_DEVICE operator()(
int idx)
const
1141 constexpr int Dim = 1;
1143 MFEM_SHARED
real_t dists[max_team_x];
1144 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1145 MFEM_FOREACH_THREAD(i, x, max_team_x)
1147#ifdef MFEM_USE_DOUBLE
1148 dists[i] = HUGE_VAL;
1150 dists[i] = HUGE_VALF;
1155 MFEM_FOREACH_THREAD(i, x, basis1d.pN)
1158 for (
int d = 0; d < SDim; ++d)
1160 phys_coord[d] = mptr[i + (d + eptr[idx] * SDim) * basis1d.pN];
1164 for (
int d = 0; d < SDim; ++d)
1166 real_t tmp = phys_coord[d] - pptr[idx + d * npts];
1169 if (dist < dists[MFEM_THREAD_ID(x)])
1172 dists[MFEM_THREAD_ID(x)] = dist;
1173 ref_buf[MFEM_THREAD_ID(x)] = basis1d.z[i];
1177 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1180 if (MFEM_THREAD_ID(x) < i)
1182 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1184 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1185 ref_buf[MFEM_THREAD_ID(x)] = ref_buf[MFEM_THREAD_ID(x) + i];
1192 if (MFEM_THREAD_ID(x) == 0)
1194 xptr[idx] = ref_buf[0];
1199template <
int SDim,
int max_team_x>
1200struct PhysDofFinder<Geometry::SQUARE, SDim, max_team_x>
1201 :
public DofFinderBase
1203 static int ndofs(
int ndofs1d) {
return ndofs1d * ndofs1d; }
1205 void MFEM_HOST_DEVICE operator()(
int idx)
const
1207 constexpr int Dim = 2;
1208 int n = basis1d.pN * basis1d.pN;
1214 MFEM_SHARED
real_t dists[max_team_x];
1215 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1216 MFEM_FOREACH_THREAD(i, x, max_team_x)
1218#ifdef MFEM_USE_DOUBLE
1219 dists[i] = HUGE_VAL;
1221 dists[i] = HUGE_VALF;
1225 MFEM_FOREACH_THREAD(j, x, basis1d.pN * basis1d.pN)
1227 real_t phys_coord[SDim] = {0};
1229 idcs[0] = j % basis1d.pN;
1230 idcs[1] = j / basis1d.pN;
1231 for (
int d = 0; d < SDim; ++d)
1234 mptr[idcs[0] + (idcs[1] + (d + eptr[idx] * SDim) * basis1d.pN) *
1239 for (
int d = 0; d < SDim; ++d)
1241 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1244 if (dist < dists[MFEM_THREAD_ID(x)])
1247 dists[MFEM_THREAD_ID(x)] = dist;
1248 for (
int d = 0; d < Dim; ++d)
1250 ref_buf[MFEM_THREAD_ID(x) + d * n] = basis1d.z[idcs[d]];
1255 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1258 if (MFEM_THREAD_ID(x) < i)
1260 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1262 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1263 for (
int d = 0; d < Dim; ++d)
1265 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1266 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1273 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1277template <
int SDim,
int max_team_x>
1278struct PhysDofFinder<Geometry::CUBE, SDim, max_team_x>
1279 :
public DofFinderBase
1281 static int ndofs(
int ndofs1d) {
return ndofs1d * ndofs1d * ndofs1d; }
1283 void MFEM_HOST_DEVICE operator()(
int idx)
const
1285 constexpr int Dim = 3;
1286 int n = basis1d.pN * basis1d.pN * basis1d.pN;
1292 MFEM_SHARED
real_t dists[max_team_x];
1293 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1294 MFEM_FOREACH_THREAD(i, x, max_team_x)
1296#ifdef MFEM_USE_DOUBLE
1297 dists[i] = HUGE_VAL;
1299 dists[i] = HUGE_VALF;
1303 MFEM_FOREACH_THREAD(j, x, basis1d.pN * basis1d.pN * basis1d.pN)
1305 real_t phys_coord[SDim] = {0};
1307 idcs[0] = j % basis1d.pN;
1308 idcs[1] = j / basis1d.pN;
1309 idcs[2] = idcs[1] / basis1d.pN;
1310 idcs[1] = idcs[1] % basis1d.pN;
1311 for (
int d = 0; d < SDim; ++d)
1314 mptr[idcs[0] + (idcs[1] + (idcs[2] + (d + eptr[idx] * SDim) *
1321 for (
int d = 0; d < SDim; ++d)
1323 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1326 if (dist < dists[MFEM_THREAD_ID(x)])
1329 dists[MFEM_THREAD_ID(x)] = dist;
1330 for (
int d = 0; d < Dim; ++d)
1332 ref_buf[MFEM_THREAD_ID(x) + d * n] = basis1d.z[idcs[d]];
1337 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1340 if (MFEM_THREAD_ID(x) < i)
1342 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1344 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1345 for (
int d = 0; d < Dim; ++d)
1347 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1348 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1355 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1360struct NodeFinderBase
1372 eltrans::Lagrange basis1d;
1382template <
int Geom,
int SDim,
int max_team_x,
int max_q1d>
1383struct PhysNodeFinder;
1385template <
int SDim,
int max_team_x,
int max_q1d>
1386struct PhysNodeFinder<Geometry::SEGMENT, SDim, max_team_x, max_q1d>
1387 :
public NodeFinderBase
1390 static int compute_nq(
int nq1d) {
return nq1d; }
1392 static int ndofs(
int ndof1d) {
return ndof1d; }
1394 void MFEM_HOST_DEVICE operator()(
int idx)
const
1396 constexpr int Dim = 1;
1398 MFEM_SHARED
real_t dists[max_team_x];
1399 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1400 MFEM_FOREACH_THREAD(i, x, max_team_x)
1402#ifdef MFEM_USE_DOUBLE
1403 dists[i] = HUGE_VAL;
1405 dists[i] = HUGE_VALF;
1410 MFEM_FOREACH_THREAD(i, x, nq)
1412 real_t phys_coord[SDim] = {0};
1413 for (
int j0 = 0; j0 < basis1d.pN; ++j0)
1415 real_t b = basis1d.eval(qptr[i], j0);
1416 for (
int d = 0; d < SDim; ++d)
1419 mptr[j0 + (d + eptr[idx] * SDim) * basis1d.pN] *
b;
1424 for (
int d = 0; d < SDim; ++d)
1426 real_t tmp = phys_coord[d] - pptr[idx + d * npts];
1429 if (dist < dists[MFEM_THREAD_ID(x)])
1432 dists[MFEM_THREAD_ID(x)] = dist;
1433 ref_buf[MFEM_THREAD_ID(x)] = qptr[i];
1437 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1440 if (MFEM_THREAD_ID(x) < i)
1442 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1444 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1445 ref_buf[MFEM_THREAD_ID(x)] = ref_buf[MFEM_THREAD_ID(x) + i];
1452 if (MFEM_THREAD_ID(x) == 0)
1454 xptr[idx] = ref_buf[0];
1459template <
int SDim,
int max_team_x,
int max_q1d>
1460struct PhysNodeFinder<Geometry::SQUARE, SDim, max_team_x, max_q1d>
1461 :
public NodeFinderBase
1464 static int compute_nq(
int nq1d) {
return nq1d * nq1d; }
1466 static int ndofs(
int ndof1d)
1468 return ndof1d * ndof1d;
1471 void MFEM_HOST_DEVICE operator()(
int idx)
const
1473 constexpr int Dim = 2;
1474 constexpr int max_dof1d = 32;
1475 int n = (nq < max_team_x) ? nq : max_team_x;
1477 MFEM_SHARED
real_t dists[max_team_x];
1478 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1479 MFEM_SHARED
real_t basis[max_dof1d * max_q1d];
1480 MFEM_FOREACH_THREAD(i, x, max_team_x)
1482#ifdef MFEM_USE_DOUBLE
1483 dists[i] = HUGE_VAL;
1485 dists[i] = HUGE_VALF;
1488 MFEM_FOREACH_THREAD(j0, x, nq1d)
1490 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1492 basis[j0 + i0 * nq1d] = basis1d.eval(qptr[j0], i0);
1497 MFEM_FOREACH_THREAD(j, x, nq)
1499 real_t phys_coord[SDim] = {0};
1503 for (
int i1 = 0; i1 < basis1d.pN; ++i1)
1505 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1507 real_t b = basis[idcs[0] + i0 * nq1d] * basis[idcs[1] + i1 * nq1d];
1508 for (
int d = 0; d < SDim; ++d)
1511 mptr[i0 + (i1 + (d + eptr[idx] * SDim) * basis1d.pN) *
1519 for (
int d = 0; d < SDim; ++d)
1521 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1524 if (dist < dists[MFEM_THREAD_ID(x)])
1527 dists[MFEM_THREAD_ID(x)] = dist;
1528 for (
int d = 0; d < Dim; ++d)
1530 ref_buf[MFEM_THREAD_ID(x) + d * n] = qptr[idcs[d]];
1535 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1538 if (MFEM_THREAD_ID(x) < i)
1540 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1542 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1543 for (
int d = 0; d < Dim; ++d)
1545 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1546 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1553 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1557template <
int SDim,
int max_team_x,
int max_q1d>
1558struct PhysNodeFinder<Geometry::CUBE, SDim, max_team_x, max_q1d>
1559 :
public NodeFinderBase
1562 static int compute_nq(
int nq1d) {
return nq1d * nq1d * nq1d; }
1564 static int ndofs(
int ndof1d)
1566 return ndof1d * ndof1d * ndof1d;
1569 void MFEM_HOST_DEVICE operator()(
int idx)
const
1571 constexpr int Dim = 3;
1572 constexpr int max_dof1d = 32;
1573 int n = (nq < max_team_x) ? nq : max_team_x;
1575 MFEM_SHARED
real_t dists[max_team_x];
1576 MFEM_SHARED
real_t ref_buf[Dim * max_team_x];
1578 MFEM_SHARED
real_t basis[max_dof1d * max_q1d];
1579 MFEM_FOREACH_THREAD(i, x, max_team_x)
1581#ifdef MFEM_USE_DOUBLE
1582 dists[i] = HUGE_VAL;
1584 dists[i] = HUGE_VALF;
1587 MFEM_FOREACH_THREAD(j0, x, nq1d)
1589 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1591 basis[j0 + i0 * nq1d] = basis1d.eval(qptr[j0], i0);
1596 MFEM_FOREACH_THREAD(j, x, nq)
1598 real_t phys_coord[SDim] = {0};
1602 idcs[2] = idcs[1] / nq1d;
1603 idcs[1] = idcs[1] % nq1d;
1604 for (
int i2 = 0; i2 < basis1d.pN; ++i2)
1606 for (
int i1 = 0; i1 < basis1d.pN; ++i1)
1608 for (
int i0 = 0; i0 < basis1d.pN; ++i0)
1610 real_t b = basis[idcs[0] + i0 * nq1d] * basis[idcs[1] + i1 * nq1d] *
1611 basis[idcs[2] + i2 * nq1d];
1612 for (
int d = 0; d < SDim; ++d)
1616 (i1 + (i2 + (d + eptr[idx] * SDim) * basis1d.pN) *
1626 for (
int d = 0; d < SDim; ++d)
1628 real_t tmp = pptr[idx + d * npts] - phys_coord[d];
1631 if (dist < dists[MFEM_THREAD_ID(x)])
1634 dists[MFEM_THREAD_ID(x)] = dist;
1635 for (
int d = 0; d < Dim; ++d)
1637 ref_buf[MFEM_THREAD_ID(x) + d * n] = qptr[idcs[d]];
1642 for (
int i = (MFEM_THREAD_SIZE(x) >> 1); i > 0; i >>= 1)
1645 if (MFEM_THREAD_ID(x) < i)
1647 if (dists[MFEM_THREAD_ID(x) + i] < dists[MFEM_THREAD_ID(x)])
1649 dists[MFEM_THREAD_ID(x)] = dists[MFEM_THREAD_ID(x) + i];
1650 for (
int d = 0; d < Dim; ++d)
1652 ref_buf[MFEM_THREAD_ID(x) + d * n] =
1653 ref_buf[MFEM_THREAD_ID(x) + i + d * n];
1660 MFEM_FOREACH_THREAD(d, x, Dim) { xptr[idx + d * npts] = ref_buf[d * n]; }
1664template <
int Geom,
int SDim,
bool use_device>
1665static void ClosestPhysNodeImpl(
int npts,
int nelems,
int ndof1d,
int nq1d,
1667 const int *eptr,
const real_t *nptr,
1670 constexpr int max_team_x = 64;
1671 constexpr int max_q1d = 128;
1672 PhysNodeFinder<Geom, SDim, max_team_x, max_q1d> func;
1673 MFEM_VERIFY(ndof1d <= 32,
"maximum of 32 dofs per dim is allowed");
1674 MFEM_VERIFY(nq1d <= max_q1d,
"maximum of 128 test points per dim is allowed");
1675 func.basis1d.z = nptr;
1676 func.basis1d.pN = ndof1d;
1684 func.nq = func.compute_nq(nq1d);
1688 int team_x = max_team_x;
1691 if (team_x <= func.nq)
1697 team_x = std::min<int>(max_team_x, 2 * team_x);
1706template <
int Geom,
int SDim,
bool use_device>
1707static void ClosestPhysDofImpl(
int npts,
int nelems,
int ndof1d,
1709 const int *eptr,
const real_t *nptr,
1712 constexpr int max_team_x = 64;
1713 PhysDofFinder<Geom, SDim, max_team_x> func;
1714 func.basis1d.z = nptr;
1715 func.basis1d.pN = ndof1d;
1723 int team_x = max_team_x;
1724 int ndof = func.ndofs(ndof1d);
1733 team_x = std::min<int>(max_team_x, 2 * team_x);
1742template <
int Geom,
int SDim,
bool use_device>
1743static void ClosestRefDofImpl(
int npts,
int nelems,
int ndof1d,
1745 const int *eptr,
const real_t *nptr,
1749 MFEM_ABORT(
"ClostestRefDofImpl not implemented yet");
1752template <
int Geom,
int SDim,
bool use_device>
1753static void ClosestRefNodeImpl(
int npts,
int nelems,
int ndof1d,
int nq1d,
1755 const int *eptr,
const real_t *nptr,
1759 MFEM_ABORT(
"ClostestRefNodeImpl not implemented yet");
1764static void NewtonSolveImpl(
real_t ref_tol,
real_t phys_rtol,
int max_iter,
1765 int npts,
int nelems,
int ndof1d,
1767 const int *eptr,
const real_t *nptr,
int *tptr,
1768 int *iter_ptr,
real_t *xptr)
1770 constexpr int max_team_x = use_device ? 64 : 1;
1771 InvTNewtonSolver<Geom, SDim, SType, max_team_x> func;
1772 MFEM_VERIFY(ndof1d <= func.max_dof1d(),
1773 "exceeded max_dof1d limit (32 for 2D/3D)");
1774 func.ref_tol = ref_tol;
1775 func.phys_rtol = phys_rtol;
1776 func.max_iter = max_iter;
1777 func.basis1d.z = nptr;
1778 func.basis1d.pN = ndof1d;
1783 func.iter_ptr = iter_ptr;
1788 int team_x = max_team_x;
1789 int ndof = func.ndofs(ndof1d);
1798 team_x = std::min<int>(max_team_x, 2 * team_x);
1807template <
int Geom,
int SDim,
1809struct InvTNewtonEdgeScanner
1811 InvTNewtonSolver<Geom, SDim, SolverType, max_team_x> solver;
1817 void MFEM_HOST_DEVICE operator()(
int idx)
const
1820 int res = InverseElementTransformation::Outside;
1821 for (
int i = 0; i < nq1d; ++i)
1823 for (
int d = 0; d < eltrans::GeometryUtils<Geom>::Dimension();
1826 if (MFEM_THREAD_ID(x) == 0)
1829 d2 < eltrans::GeometryUtils<Geom>::Dimension();
1832 solver.xptr[idx + d2 * solver.npts] = 0;
1834 solver.xptr[idx + d * solver.npts] = qptr[i];
1837 int res_tmp = solver(idx);
1840 case InverseElementTransformation::Inside:
1842 case InverseElementTransformation::Outside:
1844 case InverseElementTransformation::Unknown:
1845 res = InverseElementTransformation::Unknown;
1855 if (MFEM_THREAD_ID(x) == 0)
1857 solver.tptr[idx] = res;
1864static void NewtonEdgeScanImpl(
real_t ref_tol,
real_t phys_rtol,
int max_iter,
1865 int npts,
int nelems,
int ndof1d,
1867 const int *eptr,
const real_t *nptr,
1868 const real_t *qptr,
int nq1d,
int *tptr,
1869 int *iter_ptr,
real_t *xptr)
1871 constexpr int max_team_x = use_device ? 64 : 1;
1872 InvTNewtonEdgeScanner<Geom, SDim, SType, max_team_x> func;
1873 MFEM_VERIFY(ndof1d <= func.solver.max_dof1d(),
1874 "exceeded max_dof1d limit (32 for 2D/3D)");
1875 func.solver.ref_tol = ref_tol;
1876 func.solver.phys_rtol = phys_rtol;
1877 func.solver.max_iter = max_iter;
1878 func.solver.basis1d.z = nptr;
1879 func.solver.basis1d.pN = ndof1d;
1880 func.solver.mptr = mptr;
1881 func.solver.pptr = pptr;
1882 func.solver.eptr = eptr;
1883 func.solver.xptr = xptr;
1884 func.solver.iter_ptr = iter_ptr;
1885 func.solver.tptr = tptr;
1886 func.solver.npts = npts;
1891 int team_x = max_team_x;
1892 int ndof = func.solver.ndofs(ndof1d);
1901 team_x = std::min<int>(max_team_x, 2 * team_x);
1912template <
int Geom,
int SDim,
bool use_device>
1914BatchInverseElementTransformation::FindClosestPhysPoint::Kernel()
1916 return internal::ClosestPhysNodeImpl<Geom, SDim, use_device>;
1919template <
int Geom,
int SDim,
bool use_device>
1921BatchInverseElementTransformation::FindClosestPhysDof::Kernel()
1923 return internal::ClosestPhysDofImpl<Geom, SDim, use_device>;
1926template <
int Geom,
int SDim,
bool use_device>
1928BatchInverseElementTransformation::FindClosestRefPoint::Kernel()
1930 return internal::ClosestRefNodeImpl<Geom, SDim, use_device>;
1933template <
int Geom,
int SDim,
bool use_device>
1935BatchInverseElementTransformation::FindClosestRefDof::Kernel()
1937 return internal::ClosestRefDofImpl<Geom, SDim, use_device>;
1943BatchInverseElementTransformation::NewtonSolve::Kernel()
1945 return internal::NewtonSolveImpl<Geom, SDim, SType, use_device>;
1951BatchInverseElementTransformation::NewtonEdgeScan::Kernel()
1953 return internal::NewtonEdgeScanImpl<Geom, SDim, SType, use_device>;
1957BatchInverseElementTransformation::FindClosestPhysPoint::Fallback(
int,
int,
1960 MFEM_ABORT(
"Invalid Geom/SDim combination");
1964BatchInverseElementTransformation::FindClosestRefPoint::Fallback(
int,
int,
1967 MFEM_ABORT(
"Invalid Geom/SDim combination");
1971BatchInverseElementTransformation::NewtonSolve::Fallback(
1974 MFEM_ABORT(
"Invalid Geom/SDim/SolverType combination");
1978BatchInverseElementTransformation::NewtonEdgeScan::Fallback(
1981 MFEM_ABORT(
"Invalid Geom/SDim/SolverType combination");
1985BatchInverseElementTransformation::FindClosestPhysDof::Fallback(
int,
int,
bool)
1987 MFEM_ABORT(
"Invalid Geom/SDim combination");
1991BatchInverseElementTransformation::FindClosestRefDof::Fallback(
int,
int,
bool)
1993 MFEM_ABORT(
"Invalid Geom/SDim combination");
1996BatchInverseElementTransformation::Kernels::Kernels()
2004 constexpr auto NewtonElementProject =
2007 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 1>();
2008 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 2>();
2009 BatchInvTr::AddFindClosestSpecialization<SEGMENT, 3>();
2011 BatchInvTr::AddFindClosestSpecialization<SQUARE, 2>();
2012 BatchInvTr::AddFindClosestSpecialization<SQUARE, 3>();
2014 BatchInvTr::AddFindClosestSpecialization<CUBE, 3>();
2017 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 1, Newton>();
2018 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 2, Newton>();
2019 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 3, Newton>();
2021 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 1, NewtonElementProject>();
2022 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 2, NewtonElementProject>();
2023 BatchInvTr::AddNewtonSolveSpecialization<SEGMENT, 3, NewtonElementProject>();
2025 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 2, Newton>();
2026 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 3, Newton>();
2027 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 2, NewtonElementProject>();
2028 BatchInvTr::AddNewtonSolveSpecialization<SQUARE, 3, NewtonElementProject>();
2030 BatchInvTr::AddNewtonSolveSpecialization<CUBE, 3, Newton>();
2031 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[])