82 template <
class Patch>
87 template <
class Patch>
100 template <
class Patch>
105 template <
class Patch>
110 template <
class Patch>
115 template <
class Patch>
121 template <
class Patch>
126 template <
class Patch>
131 template <
class Patch>
139 template <
class Patch>
145 template <
class Patch>
150 template <
class Patch>
155 template <
class Patch>
160 template <
class Patch>
162 = Coord<typename Grid1OnPatch<Patch>::continuous_dimension_type,
163 typename Grid2OnPatch<Patch>::continuous_dimension_type>;
166 template <
class Patch>
167 using CoordConstFieldOnPatch
176 template <
class Patch>
186 using PatchOrdering = ddc::detail::TypeSeq<Patches...>;
190 static constexpr std::size_t
n_patches = ddc::type_seq_size_v<PatchOrdering>;
194 template <
class Patch>
195 static bool constexpr same_evaluation_idx_range_types = std::
199 (same_evaluation_idx_range_types<Patches> && ...),
200 "Operator not yet implemented for batched domains.");
203 ((std::is_same_v<typename ValuesOnPatch<Patches>::memory_space,
memory_space>)&&...),
204 "Template ValuesOnPatch<Patch> need to be defined on the memory space than the"
205 "MultipatchSplineEvaluator2D class.");
208 is_onion_patch_locator_v<PatchLocator>,
209 "Operator currently works only on analytical mappings and patches on the same logical "
210 "continous dimension. E.g. OnionPatchLocator.");
215 ExtrapolationRule
const m_extrapolation_rule;
230 ExtrapolationRule
const& extrapolation_rule)
231 : m_patch_locator(patch_locator)
232 , m_extrapolation_rule(extrapolation_rule)
253 template <
class Coord>
255 Coord
const coord_eval,
258 int const patch_idx = get_patch_idx(coord_eval);
259 return recursive_dispatch_patch_function<
261 eval_type>(coord_eval, patches_splines, patch_idx);
279 (apply_evaluator<eval_type, eval_type, Patches>(
280 patches_values.template get<Patches>(),
281 patches_coords.template get<Patches>(),
304 template <
class Coord>
306 Coord
const& coord_eval,
309 int const patch_idx = get_patch_idx(coord_eval);
311 Kokkos::abort(
"The evaluation coordinate has to be on a patch."
312 "No extrapolation rule for derivatives. \n");
314 return recursive_dispatch_patch_function<
316 eval_type>(coord_eval, patches_splines, patch_idx);
334 template <
class Coord>
336 Coord
const& coord_eval,
339 int const patch_idx = get_patch_idx(coord_eval);
341 Kokkos::abort(
"The evaluation coordinate has to be on a patch."
342 "No extrapolation rule for derivatives. \n");
344 return recursive_dispatch_patch_function<
363 template <
class Coord>
365 Coord
const& coord_eval,
368 int const patch_idx = get_patch_idx(coord_eval);
370 Kokkos::abort(
"The evaluation coordinate has to be on a patch."
371 "No extrapolation rule for derivatives. \n");
373 return recursive_dispatch_patch_function<
396 template <
class InterestDim,
class Dim1,
class Dim2>
398 Coord<Dim1, Dim2>
const& coord_eval,
401 static_assert((std::is_same_v<InterestDim, Dim1>) || (std::is_same_v<InterestDim, Dim2>));
402 if constexpr (std::is_same_v<InterestDim, Dim1>) {
404 }
else if constexpr (std::is_same_v<InterestDim, Dim2>) {
427 (apply_evaluator<eval_deriv_type, eval_type, Patches>(
428 patches_deriv_1.template get<Patches>(),
429 patches_coords.template get<Patches>(),
452 (apply_evaluator<eval_type, eval_deriv_type, Patches>(
453 patches_deriv_2.template get<Patches>(),
454 patches_coords.template get<Patches>(),
475 (apply_evaluator<eval_deriv_type, eval_deriv_type, Patches>(
476 patches_deriv_12.template get<Patches>(),
477 patches_coords.template get<Patches>(),
492 DKokkosView_h<n_patches>
const& integrals,
495 (apply_integrate<Patches>(
496 integrals(ddc::type_seq_rank_v<Patches, PatchOrdering>),
497 patches_splines.template get<Patches>()),
518 template <
class EvalType1,
class EvalType2,
class StoringPatch>
520 ValuesOnPatch<StoringPatch>
const& patch_values,
521 CoordConstFieldOnPatch<StoringPatch>
const& patch_coords,
524 assert(get_idx_range(patch_values) == get_idx_range(patch_coords));
530 ddc::parallel_for_each(
533 KOKKOS_CLASS_LAMBDA(Index
const& idx) {
534 CoordOnPatch<StoringPatch>
const coord = patch_coords(idx);
535 int const patch_idx = get_patch_idx(coord);
537 && !((std::is_same_v<EvalType1, eval_type>)&&(
538 std::is_same_v<EvalType2, eval_type>))) {
539 Kokkos::abort(
"The evaluation coordinate has to be on a patch."
540 "No extrapolation rule for derivatives. \n");
542 patch_values(idx) = recursive_dispatch_patch_function<
544 EvalType2>(coord, patches_splines, patch_idx);
553 template <
class Patch>
557 std::is_same_v<exec_space, Kokkos::DefaultHostExecutionSpace>,
558 "Can only be called on CPU: .integrals() not defined yet on GPU.");
560 Kokkos::SpaceAccessibility<exec_space, memory_space>::accessible,
561 "Execution space and memory space have to be compatible.");
567 DFieldMem<IdxRange<bsplines_1>,
memory_space> values1_alloc(
568 get_idx_range<bsplines_1>(spline_coef));
569 DField<IdxRange<bsplines_1>,
memory_space> values1 = get_field(values1_alloc);
570 DFieldMem<IdxRange<bsplines_2>,
memory_space> values2_alloc(
571 get_idx_range<bsplines_2>(spline_coef));
572 DField<IdxRange<bsplines_2>,
memory_space> values2 = get_field(values2_alloc);
576 integral = ddc::parallel_transform_reduce(
578 get_idx_range(spline_coef),
580 ddc::reducer::sum<double>(),
581 KOKKOS_LAMBDA(IdxBS12
const i12) {
582 return spline_coef(i12) * values1(ddc::select<bsplines_1>(i12))
583 * values2(ddc::select<bsplines_2>(i12));
593 template <
class EvalType1,
class EvalType2,
class Dim1,
class Dim2,
int TestPatchIdx = 0>
594 KOKKOS_INLINE_FUNCTION
double recursive_dispatch_patch_function(
595 Coord<Dim1, Dim2> coord,
596 MultipatchSplineCoeff
const& patches_splines,
597 int const patch_idx)
const
599 if constexpr (TestPatchIdx == ddc::type_seq_size_v<PatchOrdering>) {
600 if (patch_idx >= 0) {
601 Kokkos::abort(
"The recursion has reached the end without finding where "
602 "the coordinate is physically located.");
606 std::is_same_v<EvalType1, eval_type> && std::is_same_v<EvalType2, eval_type>) {
613 using AnyPatch = ddc::type_seq_element_t<0, PatchOrdering>;
614 replace_periodic_coord_inside<AnyPatch>(coord);
615 return m_extrapolation_rule(coord, patches_splines, patch_idx);
617 Kokkos::abort(
"The spline derivatives cannot be evaluated at coordinates "
618 "outside of the domain.");
621 if (patch_idx == TestPatchIdx) {
622 using TestPatch = ddc::type_seq_element_t<TestPatchIdx, PatchOrdering>;
623 CoordOnPatch<TestPatch> test_coord = get_equivalent_coord<
624 typename TestPatch::Dim1,
625 typename TestPatch::Dim2,
628 replace_periodic_coord_inside<TestPatch>(test_coord);
630 SplineCoeffOnPatch<TestPatch>
const test_spline
631 = patches_splines.template get<TestPatch>();
632 return eval_no_bc<EvalType1, EvalType2, TestPatch>(test_coord, test_spline);
634 return recursive_dispatch_patch_function<
639 TestPatchIdx + 1>(coord, patches_splines, patch_idx);
649 template <
class Dim1,
class Dim2>
650 KOKKOS_INLINE_FUNCTION
int get_patch_idx(Coord<Dim1, Dim2>
const coord)
const
652 using Mapping =
typename PatchLocator::template get_mapping_on_logical_dim_t<Dim1, Dim2>;
653 Mapping
const mapping(m_patch_locator.template get_mapping_on_logical_dim<Dim1, Dim2>());
654 return m_patch_locator(mapping(coord));
659 template <
class TargetDim1,
class TargetDim2,
class CurrentDim1,
class CurrentDim2>
660 KOKKOS_INLINE_FUNCTION Coord<TargetDim1, TargetDim2> get_equivalent_coord(
661 Coord<CurrentDim1, CurrentDim2>
const& current_coord)
const
663 if constexpr (std::is_same_v<
664 Coord<TargetDim1, TargetDim2>,
665 Coord<CurrentDim1, CurrentDim2>>) {
666 return current_coord;
668 using CurrentMapping =
typename PatchLocator::
669 template get_mapping_on_logical_dim_t<CurrentDim1, CurrentDim2>;
670 using TargetMapping =
typename PatchLocator::
671 template get_mapping_on_logical_dim_t<TargetDim1, TargetDim2>;
673 static_assert(is_curvilinear_2d_mapping_v<CurrentMapping>);
674 static_assert((std::is_same_v<
675 Coord<
typename CurrentMapping::curvilinear_tag_r,
676 typename CurrentMapping::curvilinear_tag_theta>,
677 Coord<CurrentDim1, CurrentDim2>>));
678 static_assert(is_curvilinear_2d_mapping_v<TargetMapping>);
679 static_assert((std::is_same_v<
680 Coord<
typename TargetMapping::curvilinear_tag_r,
681 typename TargetMapping::curvilinear_tag_theta>,
682 Coord<TargetDim1, TargetDim2>>));
684 CurrentMapping
const current_mapping(
686 .
template get_mapping_on_logical_dim<CurrentDim1, CurrentDim2>());
687 TargetMapping
const target_mapping(
688 m_patch_locator.template get_mapping_on_logical_dim<TargetDim1, TargetDim2>());
690 return target_mapping(current_mapping(current_coord));
695 template <
class Patch>
696 KOKKOS_INLINE_FUNCTION
void replace_periodic_coord_inside(CoordOnPatch<Patch>& coord)
const
698 using bsplines_1 = bsplines_type1<Patch>;
699 using bsplines_2 = bsplines_type2<Patch>;
701 using Dim1 = continuous_dimension_type1<Patch>;
702 using Dim2 = continuous_dimension_type2<Patch>;
704 Coord<Dim1> coord_1(coord);
705 Coord<Dim2> coord_2(coord);
707 ddcHelper::restrict_to_bspline_domain<bsplines_1>(coord_1);
708 ddcHelper::restrict_to_bspline_domain<bsplines_2>(coord_2);
710 coord = CoordOnPatch<Patch>(coord_1, coord_2);
718 template <
class EvalType1,
class EvalType2,
class Patch,
class Layout>
719 KOKKOS_INLINE_FUNCTION
double eval_no_bc(
720 CoordOnPatch<Patch>
const& coord_eval,
721 DConstField<spline_idx_range_type<Patch>,
memory_space, Layout>
const& spline_coef)
725 std::is_same_v<EvalType1, eval_type> || std::is_same_v<EvalType1, eval_deriv_type>);
727 std::is_same_v<EvalType2, eval_type> || std::is_same_v<EvalType2, eval_deriv_type>);
729 using bsplines_1 = bsplines_type1<Patch>;
730 using bsplines_2 = bsplines_type2<Patch>;
732 Idx<bsplines_1> jmin1;
733 Idx<bsplines_2> jmin2;
735 std::array<double, bsplines_1::degree() + 1> vals1_ptr;
736 DSpan1D
const vals1(vals1_ptr.data(), bsplines_1::degree() + 1);
737 std::array<double, bsplines_2::degree() + 1> vals2_ptr;
738 DSpan1D
const vals2(vals2_ptr.data(), bsplines_2::degree() + 1);
740 Coord<continuous_dimension_type1<Patch>> coord_eval_interest1
741 = ddc::select<continuous_dimension_type1<Patch>>(coord_eval);
742 Coord<continuous_dimension_type2<Patch>> coord_eval_interest2
743 = ddc::select<continuous_dimension_type2<Patch>>(coord_eval);
745 if constexpr (std::is_same_v<EvalType1, eval_type>) {
746 jmin1 = ddc::discrete_space<bsplines_1>().eval_basis(vals1, coord_eval_interest1);
747 }
else if constexpr (std::is_same_v<EvalType1, eval_deriv_type>) {
748 jmin1 = ddc::discrete_space<bsplines_1>().eval_deriv(vals1, coord_eval_interest1);
751 if constexpr (std::is_same_v<EvalType2, eval_type>) {
752 jmin2 = ddc::discrete_space<bsplines_2>().eval_basis(vals2, coord_eval_interest2);
753 }
else if constexpr (std::is_same_v<EvalType2, eval_deriv_type>) {
754 jmin2 = ddc::discrete_space<bsplines_2>().eval_deriv(vals2, coord_eval_interest2);
758 for (std::size_t i = 0; i < bsplines_1::degree() + 1; ++i) {
759 for (std::size_t j = 0; j < bsplines_2::degree() + 1; ++j) {
760 y += spline_coef(jmin1 + i, jmin2 + j) * vals1[i] * vals2[j];