3#include <Kokkos_Core.hpp>
9template <
unsigned a,
unsigned b>
10constexpr KOKKOS_INLINE_FUNCTION
auto first() {
13template <
unsigned a,
unsigned b>
14constexpr KOKKOS_INLINE_FUNCTION
auto second() {
33template <
typename _scalar,
unsigned _main_axis,
unsigned... _side_axes>
55 constexpr unsigned side_axes[2] = {_side_axes...};
57 (
main_axis == 0 &&
first<_side_axes...>() == 1 && second<_side_axes...>() == 2)
58 || (
main_axis == 1 && first<_side_axes...>() == 0 &&
second<_side_axes...>() == 2)
59 || (
main_axis == 2 &&
first<_side_axes...>() == 0 && second<_side_axes...>() == 1));
60 assert(_main_axis != side_axes[0]);
61 assert(_main_axis != side_axes[1]);
62 assert(side_axes[0] != side_axes[1]);
71 Cweights[2] = (1.0 / (
c * dt * dt) -
c / (2.0 * hr[side_axes[0]] * hr[side_axes[0]])
72 -
c / (2.0 * hr[side_axes[1]] * hr[side_axes[1]]))
74 Cweights[3] = (
c / (4.0 * hr[side_axes[0]] * hr[side_axes[0]])) / d;
75 Cweights[4] = (
c / (4.0 * hr[side_axes[1]] * hr[side_axes[1]])) / d;
86 template <
typename view_type,
typename Coords>
88 const view_type& A_np1,
const Coords&
c)
const ->
89 typename view_type::value_type {
94 constexpr unsigned side_axes[2] = {_side_axes...};
111 A_nm1(i, j, k), A_n(i, j, k),
apply(A_nm1,
c + mainaxis_off),
112 apply(A_n,
c + mainaxis_off),
apply(A_np1,
c + mainaxis_off),
113 apply(A_n,
c + side_axis1_onehot + mainaxis_off),
114 apply(A_n,
c - side_axis1_onehot + mainaxis_off),
115 apply(A_n,
c + side_axis2_onehot + mainaxis_off),
116 apply(A_n,
c - side_axis2_onehot + mainaxis_off),
apply(A_n,
c + side_axis1_onehot),
117 apply(A_n,
c - side_axis1_onehot),
apply(A_n,
c + side_axis2_onehot),
118 apply(A_n,
c - side_axis2_onehot));
124 template <
typename value_type>
126 const value_type& v3,
const value_type& v4,
127 const value_type& v5,
const value_type& v6,
128 const value_type& v7,
const value_type& v8,
129 const value_type& v9,
const value_type& v10,
130 const value_type& v11,
const value_type& v12,
131 const value_type& v13)
const noexcept {
133 + (
Cweights[3]) * (v6 + v7 + v10 + v11)
134 + (
Cweights[4]) * (v8 + v9 + v12 + v13);
159template <
typename _scalar,
unsigned edge_axis,
unsigned normal_axis1,
unsigned normal_axis2,
160 bool na1_zero,
bool na2_zero>
174 static_assert(normal_axis1 != normal_axis2);
175 static_assert(edge_axis != normal_axis2);
176 static_assert(edge_axis != normal_axis1);
178 static_assert((edge_axis == 2 && normal_axis1 == 0 && normal_axis2 == 1)
179 || (edge_axis == 0 && normal_axis1 == 1 && normal_axis2 == 2)
180 || (edge_axis == 1 && normal_axis1 == 2 && normal_axis2 == 0));
186 scalar d = (1.0 / hr[normal_axis1] + 1.0 / hr[normal_axis2]) / (4.0 * dt)
187 + 3.0 / (8.0 * c0_ * dt * dt);
190 Eweights[0] = (-(1.0 / hr[normal_axis2] - 1.0 / hr[normal_axis1]) / (4.0 * dt)
191 - 3.0 / (8.0 * c0_ * dt * dt))
193 Eweights[1] = ((1.0 / hr[normal_axis2] - 1.0 / hr[normal_axis1]) / (4.0 * dt)
194 - 3.0 / (8.0 * c0_ * dt * dt))
196 Eweights[2] = ((1.0 / hr[normal_axis2] + 1.0 / hr[normal_axis1]) / (4.0 * dt)
197 - 3.0 / (8.0 * c0_ * dt * dt))
200 (3.0 / (4.0 * c0_ * dt * dt) - c0_ / (4.0 * hr[edge_axis] * hr[edge_axis])) / d;
201 Eweights[4] = c0_ / (8.0 * hr[edge_axis] * hr[edge_axis]) / d;
212 template <
typename view_type,
typename Coords>
214 const view_type& A_np1,
const Coords&
c)
const ->
215 typename view_type::value_type {
225 * int32_t(na1_zero ? 1 : -1);
228 * int32_t(na2_zero ? 1 : -1);
240 return advanceEdgeS(A_n(i, j, k), A_nm1(i, j, k),
apply(A_np1, acc1),
apply(A_n, acc1),
243 apply(A_nm1, acc3),
apply(A_n, acc0 - axisp),
apply(A_n, acc1 - axisp),
244 apply(A_n, acc2 - axisp),
apply(A_n, acc3 - axisp),
245 apply(A_n, acc0 + axisp),
apply(A_n, acc1 + axisp),
246 apply(A_n, acc2 + axisp),
apply(A_n, acc3 + axisp));
252 template <
typename value_type>
253 KOKKOS_INLINE_FUNCTION value_type
advanceEdgeS(value_type v1, value_type v2, value_type v3,
254 value_type v4, value_type v5, value_type v6,
255 value_type v7, value_type v8, value_type v9,
256 value_type v10, value_type v11, value_type v12,
257 value_type v13, value_type v14, value_type v15,
258 value_type v16, value_type v17, value_type v18,
259 value_type v19)
const noexcept {
261 +
Eweights[3] * (v1 + v4 + v7 + v10)
262 +
Eweights[4] * (v12 + v13 + v14 + v15 + v16 + v17 + v18 + v19) - v11;
286template <
typename _scalar,
bool x0,
bool y0,
bool z0>
300 (-1.0 / hr[0] - 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
302 (1.0 / hr[0] - 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
304 (-1.0 / hr[0] + 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
306 (-1.0 / hr[0] - 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
308 (1.0 / hr[0] + 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
310 (1.0 / hr[0] - 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
312 (-1.0 / hr[0] + 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
314 (1.0 / hr[0] + 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
316 -(-1.0 / hr[0] - 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
318 -(1.0 / hr[0] - 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
320 -(-1.0 / hr[0] + 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
322 -(-1.0 / hr[0] - 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
324 -(1.0 / hr[0] + 1.0 / hr[1] - 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
326 -(1.0 / hr[0] - 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
328 -(-1.0 / hr[0] + 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
330 -(1.0 / hr[0] + 1.0 / hr[1] + 1.0 / hr[2]) / (8.0 * dt) - 1.0 / (4.0 * c0_ * dt * dt);
331 Cweights[16] = 1.0 / (2.0 * c0_ * dt * dt);
342 template <
typename view_type,
typename Coords>
344 const view_type& A_np1,
const Coords&
c)
const ->
345 typename view_type::value_type {
347 constexpr uint32_t xoff = (x0) ? 1 : uint32_t(-1);
348 constexpr uint32_t yoff = (y0) ? 1 : uint32_t(-1);
349 constexpr uint32_t zoff = (z0) ? 1 : uint32_t(-1);
363 apply(A_n,
c + offsets[1]),
apply(A_nm1,
c + offsets[1]),
apply(A_np1,
c + offsets[2]),
364 apply(A_n,
c + offsets[2]),
apply(A_nm1,
c + offsets[2]),
apply(A_np1,
c + offsets[3]),
365 apply(A_n,
c + offsets[3]),
apply(A_nm1,
c + offsets[3]),
apply(A_np1,
c + offsets[4]),
366 apply(A_n,
c + offsets[4]),
apply(A_nm1,
c + offsets[4]),
apply(A_np1,
c + offsets[5]),
367 apply(A_n,
c + offsets[5]),
apply(A_nm1,
c + offsets[5]),
apply(A_np1,
c + offsets[6]),
368 apply(A_n,
c + offsets[6]),
apply(A_nm1,
c + offsets[6]),
apply(A_np1,
c + offsets[7]),
369 apply(A_n,
c + offsets[7]),
apply(A_nm1,
c + offsets[7]));
375 template <
typename value_type>
376 KOKKOS_INLINE_FUNCTION value_type
377 advanceCornerS(value_type v1, value_type v2, value_type v3, value_type v4, value_type v5,
378 value_type v6, value_type v7, value_type v8, value_type v9, value_type v10,
379 value_type v11, value_type v12, value_type v13, value_type v14, value_type v15,
380 value_type v16, value_type v17, value_type v18, value_type v19, value_type v20,
381 value_type v21, value_type v22, value_type v23)
const noexcept {
417 template <
typename field_type,
typename dt_type>
418 void apply(field_type& FA_n, field_type& FA_nm1, field_type& FA_np1, dt_type dt,
420 using scalar =
decltype(dt);
426 auto A_n = FA_n.getView();
427 auto A_np1 = FA_np1.getView();
428 auto A_nm1 = FA_nm1.getView();
432 uint32_t(A_n.extent(2))};
434 constexpr uint32_t min_abc_boundary = 1;
435 constexpr uint32_t max_abc_boundary_sub = min_abc_boundary + 1;
441 uint32_t ig = i + lDom.
first()[0];
442 uint32_t jg = j + lDom.
first()[1];
443 uint32_t kg = k + lDom.
first()[2];
446 uint32_t lval = uint32_t(i == 0) + (uint32_t(j == 0) << 1) + (uint32_t(k == 0) << 2)
447 + (uint32_t(i == local_nr[0] - 1) << 3)
448 + (uint32_t(j == local_nr[1] - 1) << 4)
449 + (uint32_t(k == local_nr[2] - 1) << 5);
452 if (Kokkos::popcount(lval) > 1)
456 uint32_t val = uint32_t(ig == min_abc_boundary)
457 + (uint32_t(jg == min_abc_boundary) << 1)
458 + (uint32_t(kg == min_abc_boundary) << 2)
459 + (uint32_t(ig == true_nr[0] - max_abc_boundary_sub) << 3)
460 + (uint32_t(jg == true_nr[1] - max_abc_boundary_sub) << 4)
461 + (uint32_t(kg == true_nr[2] - max_abc_boundary_sub) << 5);
464 if (Kokkos::popcount(val) == 1) {
465 if (ig == min_abc_boundary) {
469 if (jg == min_abc_boundary) {
473 if (kg == min_abc_boundary) {
477 if (ig == true_nr[0] - max_abc_boundary_sub) {
481 if (jg == true_nr[1] - max_abc_boundary_sub) {
485 if (kg == true_nr[2] - max_abc_boundary_sub) {
497 uint32_t ig = i + lDom.
first()[0];
498 uint32_t jg = j + lDom.
first()[1];
499 uint32_t kg = k + lDom.
first()[2];
502 uint32_t lval = uint32_t(i == 0) + (uint32_t(j == 0) << 1) + (uint32_t(k == 0) << 2)
503 + (uint32_t(i == local_nr[0] - 1) << 3)
504 + (uint32_t(j == local_nr[1] - 1) << 4)
505 + (uint32_t(k == local_nr[2] - 1) << 5);
508 if (Kokkos::popcount(lval) > 2)
512 uint32_t val = uint32_t(ig == min_abc_boundary)
513 + (uint32_t(jg == min_abc_boundary) << 1)
514 + (uint32_t(kg == min_abc_boundary) << 2)
515 + (uint32_t(ig == true_nr[0] - max_abc_boundary_sub) << 3)
516 + (uint32_t(jg == true_nr[1] - max_abc_boundary_sub) << 4)
517 + (uint32_t(kg == true_nr[2] - max_abc_boundary_sub) << 5);
520 if (Kokkos::popcount(val) == 2) {
521 if (ig == min_abc_boundary && kg == min_abc_boundary) {
524 }
else if (ig == min_abc_boundary && jg == min_abc_boundary) {
527 }
else if (jg == min_abc_boundary && kg == min_abc_boundary) {
530 }
else if (ig == min_abc_boundary && kg == true_nr[2] - max_abc_boundary_sub) {
533 }
else if (ig == min_abc_boundary && jg == true_nr[1] - max_abc_boundary_sub) {
536 }
else if (jg == min_abc_boundary && kg == true_nr[2] - max_abc_boundary_sub) {
539 }
else if (ig == true_nr[0] - max_abc_boundary_sub && kg == min_abc_boundary) {
542 }
else if (ig == true_nr[0] - max_abc_boundary_sub && jg == min_abc_boundary) {
545 }
else if (jg == true_nr[1] - max_abc_boundary_sub && kg == min_abc_boundary) {
548 }
else if (ig == true_nr[0] - max_abc_boundary_sub
549 && kg == true_nr[2] - max_abc_boundary_sub) {
552 }
else if (ig == true_nr[0] - max_abc_boundary_sub
553 && jg == true_nr[1] - max_abc_boundary_sub) {
556 }
else if (jg == true_nr[1] - max_abc_boundary_sub
557 && kg == true_nr[2] - max_abc_boundary_sub) {
571 uint32_t ig = i + lDom.
first()[0];
572 uint32_t jg = j + lDom.
first()[1];
573 uint32_t kg = k + lDom.
first()[2];
576 uint32_t val = uint32_t(ig == min_abc_boundary)
577 + (uint32_t(jg == min_abc_boundary) << 1)
578 + (uint32_t(kg == min_abc_boundary) << 2)
579 + (uint32_t(ig == true_nr[0] - max_abc_boundary_sub) << 3)
580 + (uint32_t(jg == true_nr[1] - max_abc_boundary_sub) << 4)
581 + (uint32_t(kg == true_nr[2] - max_abc_boundary_sub) << 5);
584 if (Kokkos::popcount(val) == 3) {
585 if (ig == min_abc_boundary && jg == min_abc_boundary
586 && kg == min_abc_boundary) {
589 }
else if (ig == true_nr[0] - max_abc_boundary_sub && jg == min_abc_boundary
590 && kg == min_abc_boundary) {
593 }
else if (ig == min_abc_boundary && jg == true_nr[1] - max_abc_boundary_sub
594 && kg == min_abc_boundary) {
597 }
else if (ig == true_nr[0] - max_abc_boundary_sub
598 && jg == true_nr[1] - max_abc_boundary_sub
599 && kg == min_abc_boundary) {
602 }
else if (ig == min_abc_boundary && jg == min_abc_boundary
603 && kg == true_nr[2] - max_abc_boundary_sub) {
606 }
else if (ig == true_nr[0] - max_abc_boundary_sub && jg == min_abc_boundary
607 && kg == true_nr[2] - max_abc_boundary_sub) {
610 }
else if (ig == min_abc_boundary && jg == true_nr[1] - max_abc_boundary_sub
611 && kg == true_nr[2] - max_abc_boundary_sub) {
614 }
else if (ig == true_nr[0] - max_abc_boundary_sub
615 && jg == true_nr[1] - max_abc_boundary_sub
616 && kg == true_nr[2] - max_abc_boundary_sub) {
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
constexpr KOKKOS_INLINE_FUNCTION auto second()
constexpr KOKKOS_INLINE_FUNCTION auto first()
constexpr double e
The value of.
constexpr double c
The velocity of light in m/s.
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
RangePolicy< View::rank, typenameView::execution_space, PolicyArgs... >::policy_type getRangePolicy(const View &view, int shift=0)
void parallel_for(const std::string &name, const ExecPolicy &policy, const FunctorType &functor)
KOKKOS_INLINE_FUNCTION Vector< int, Dim > first() const
KOKKOS_INLINE_FUNCTION auto operator()(const view_type &A_n, const view_type &A_nm1, const view_type &A_np1, const Coords &c) const -> typename view_type::value_type
Applies the second-order ABC to the boundary of the field.
KOKKOS_FUNCTION value_type advanceBoundaryS(const value_type &v1, const value_type &v2, const value_type &v3, const value_type &v4, const value_type &v5, const value_type &v6, const value_type &v7, const value_type &v8, const value_type &v9, const value_type &v10, const value_type &v11, const value_type &v12, const value_type &v13) const noexcept
Advances the boundary condition using the precomputed weights.
KOKKOS_FUNCTION second_order_abc_face(ippl::Vector< scalar, 3 > hr, scalar dt, int _sign)
Constructor for the second-order ABC face.
static constexpr unsigned main_axis
KOKKOS_INLINE_FUNCTION value_type advanceEdgeS(value_type v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6, value_type v7, value_type v8, value_type v9, value_type v10, value_type v11, value_type v12, value_type v13, value_type v14, value_type v15, value_type v16, value_type v17, value_type v18, value_type v19) const noexcept
Advances the edge boundary condition using the precomputed weights.
KOKKOS_INLINE_FUNCTION auto operator()(const view_type &A_n, const view_type &A_nm1, const view_type &A_np1, const Coords &c) const -> typename view_type::value_type
Applies the second-order ABC to the edge of the field.
KOKKOS_FUNCTION second_order_abc_edge(ippl::Vector< scalar, 3 > hr, scalar dt)
Constructor for the second-order ABC edge.
KOKKOS_FUNCTION second_order_abc_corner(ippl::Vector< scalar, 3 > hr, scalar dt)
Constructor for the second-order ABC corner.
KOKKOS_INLINE_FUNCTION value_type advanceCornerS(value_type v1, value_type v2, value_type v3, value_type v4, value_type v5, value_type v6, value_type v7, value_type v8, value_type v9, value_type v10, value_type v11, value_type v12, value_type v13, value_type v14, value_type v15, value_type v16, value_type v17, value_type v18, value_type v19, value_type v20, value_type v21, value_type v22, value_type v23) const noexcept
Advances the corner boundary condition using the precomputed weights.
KOKKOS_INLINE_FUNCTION auto operator()(const view_type &A_n, const view_type &A_nm1, const view_type &A_np1, const Coords &c) const -> typename view_type::value_type
Applies the second-order ABC to the corner of the field.
void apply(field_type &FA_n, field_type &FA_nm1, field_type &FA_np1, dt_type dt, ippl::Vector< uint32_t, 3 > true_nr, ippl::NDIndex< 3 > lDom)
Applies second-order Mur ABC to the boundaries of the field.