5#ifndef IPPL_OPERATIONS_H
6#define IPPL_OPERATIONS_H
8#include <Kokkos_MathematicalFunctions.hpp>
21 template <
typename View,
typename Coords,
size_t... Idx>
22 KOKKOS_INLINE_FUNCTION
constexpr decltype(
auto)
apply_impl(
const View& view,
24 const std::index_sequence<Idx...>&) {
25 return view(coords[Idx]...);
38 template <
typename Coords, std::enable_if_t<std::is_array_v<Coords>,
int> = 0>
39 KOKKOS_INLINE_FUNCTION
constexpr static unsigned getRank() {
40 return std::extent_v<Coords>;
48 template <
typename Coords, std::enable_if_t<std::is_
class_v<Coords>,
int> = 0>
49 KOKKOS_INLINE_FUNCTION
constexpr static unsigned getRank() {
63 template <
typename View,
typename Coords>
64 KOKKOS_INLINE_FUNCTION
constexpr decltype(
auto)
apply(
const View& view,
const Coords& coords) {
65 using Indices = std::make_index_sequence<ExtractExpressionRank::getRank<Coords>()>;
69#define DefineUnaryOperation(fun, name, op1, op2) \
70 template <typename E> \
71 struct fun : public detail::Expression<fun<E>, sizeof(E)> { \
72 constexpr static unsigned dim = E::dim; \
73 using value_type = typename E::value_type; \
79 KOKKOS_INLINE_FUNCTION auto operator[](size_t i) const { return op1; } \
81 template <typename... Args> \
82 KOKKOS_INLINE_FUNCTION auto operator()(Args... args) const { \
90 template <typename E, size_t N> \
91 KOKKOS_INLINE_FUNCTION fun<E> name(const detail::Expression<E, N>& u) { \
92 return fun<E>(*static_cast<const E*>(&u)); \
98 DefineUnaryOperation(UnaryMinus,
operator-, -u_m[i], -u_m(args...))
99 DefineUnaryOperation(UnaryPlus, operator+, +u_m[i], +u_m(args...))
100 DefineUnaryOperation(BitwiseNot, operator~, ~u_m[i], ~u_m(args...))
101 DefineUnaryOperation(Not, operator!, !u_m[i], !u_m(args...))
103 DefineUnaryOperation(ArcCos, acos, Kokkos::acos(u_m[i]), Kokkos::acos(u_m(args...)))
104 DefineUnaryOperation(ArcSin, asin, Kokkos::asin(u_m[i]), Kokkos::asin(u_m(args...)))
105 DefineUnaryOperation(ArcTan, atan, Kokkos::atan(u_m[i]), Kokkos::atan(u_m(args...)))
106 DefineUnaryOperation(Ceil, ceil, Kokkos::ceil(u_m[i]), Kokkos::ceil(u_m(args...)))
107 DefineUnaryOperation(Cos, cos, Kokkos::cos(u_m[i]), Kokkos::cos(u_m(args...)))
108 DefineUnaryOperation(HypCos, cosh, Kokkos::cosh(u_m[i]), Kokkos::cosh(u_m(args...)))
109 DefineUnaryOperation(Exp, exp, Kokkos::exp(u_m[i]), Kokkos::exp(u_m(args...)))
110 DefineUnaryOperation(Fabs, fabs, Kokkos::fabs(u_m[i]), Kokkos::fabs(u_m(args...)))
111 DefineUnaryOperation(Floor, floor, Kokkos::floor(u_m[i]), Kokkos::floor(u_m(args...)))
112 DefineUnaryOperation(Log, log, Kokkos::log(u_m[i]), Kokkos::log(u_m(args...)))
113 DefineUnaryOperation(Log10, log10, Kokkos::log10(u_m[i]), Kokkos::log10(u_m(args...)))
114 DefineUnaryOperation(Sin, sin, Kokkos::sin(u_m[i]), Kokkos::sin(u_m(args...)))
115 DefineUnaryOperation(HypSin, sinh, Kokkos::sinh(u_m[i]), Kokkos::sinh(u_m(args...)))
116 DefineUnaryOperation(Sqrt, sqrt, Kokkos::sqrt(u_m[i]), Kokkos::sqrt(u_m(args...)))
117 DefineUnaryOperation(Tan, tan, Kokkos::tan(u_m[i]), Kokkos::tan(u_m(args...)))
118 DefineUnaryOperation(HypTan, tanh, Kokkos::tanh(u_m[i]), Kokkos::tanh(u_m(args...)))
119 DefineUnaryOperation(Erf, erf, Kokkos::erf(u_m[i]), Kokkos::erf(u_m(args...)))
130#define DefineBinaryOperation(fun, name, op1, op2) \
131 template <typename E1, typename E2> \
132 struct fun : public detail::Expression<fun<E1, E2>, sizeof(E1) + sizeof(E2)> { \
133 constexpr static unsigned dim = std::max(E1::dim, E2::dim); \
134 using value_type = typename E1::value_type; \
137 fun(const E1& u, const E2& v) \
141 KOKKOS_INLINE_FUNCTION auto operator[](size_t i) const { return op1; } \
143 template <typename... Args> \
144 KOKKOS_INLINE_FUNCTION auto operator()(Args... args) const { \
145 static_assert(sizeof...(Args) == dim || dim == 0); \
154 template <typename E1, size_t N1, typename E2, size_t N2> \
155 KOKKOS_INLINE_FUNCTION fun<E1, E2> name(const detail::Expression<E1, N1>& u, \
156 const detail::Expression<E2, N2>& v) { \
157 return fun<E1, E2>(*static_cast<const E1*>(&u), *static_cast<const E2*>(&v)); \
160 template <typename E, size_t N, typename T, \
161 typename = std::enable_if_t<std::is_scalar<T>::value>> \
162 KOKKOS_INLINE_FUNCTION fun<E, detail::Scalar<T>> name(const detail::Expression<E, N>& u, \
164 return fun<E, detail::Scalar<T>>(*static_cast<const E*>(&u), v); \
167 template <typename E, size_t N, typename T, \
168 typename = std::enable_if_t<std::is_scalar<T>::value>> \
169 KOKKOS_INLINE_FUNCTION fun<detail::Scalar<T>, E> name(const T& u, \
170 const detail::Expression<E, N>& v) { \
171 return fun<detail::Scalar<T>, E>(u, *static_cast<const E*>(&v)); \
196 Kokkos::copysign(u_m(args...), v_m(args...)))
200 Kokkos::fmod(u_m(args...), v_m(args...)))
202 Kokkos::pow(u_m(args...), v_m(args...)))
204 Kokkos::atan2(u_m(args...), v_m(args...)))
212 template <
typename E1,
typename E2>
214 constexpr static unsigned dim = E1::dim;
215 static_assert(E1::dim == E2::dim);
225 KOKKOS_INLINE_FUNCTION
auto operator[](
size_t i)
const {
226 const size_t j = (i + 1) % 3;
227 const size_t k = (i + 2) % 3;
228 return u_m[j] * v_m[k] - u_m[k] * v_m[j];
234 template <
typename... Args>
235 KOKKOS_INLINE_FUNCTION
auto operator()(Args... args)
const {
236 return cross(u_m(args...), v_m(args...));
245 template <
typename E1,
size_t N1,
typename E2,
size_t N2>
255 template <
typename E1,
typename E2>
256 struct meta_dot :
public Expression<meta_dot<E1, E2>, sizeof(E1) + sizeof(E2)> {
257 constexpr static unsigned dim = E1::dim;
258 static_assert(E1::dim == E2::dim);
261 meta_dot(
const E1& u,
const E2& v)
268 KOKKOS_INLINE_FUNCTION
auto apply()
const {
269 typename E1::value_type res = 0.0;
272 for (
size_t i = 0; i < E1::dim; ++i) {
273 res += u_m[i] * v_m[i];
281 template <
typename... Args>
282 KOKKOS_INLINE_FUNCTION
auto operator()(Args... args)
const {
283 return dot(u_m(args...), v_m(args...)).apply();
292 template <
typename E1,
size_t N1,
typename E2,
size_t N2>
293 KOKKOS_INLINE_FUNCTION detail::meta_dot<E1, E2> dot(
const detail::Expression<E1, N1>& u,
294 const detail::Expression<E2, N2>& v) {
295 return detail::meta_dot<E1, E2>(*
static_cast<const E1*
>(&u), *
static_cast<const E2*
>(&v));
303 template <
typename E>
307 sizeof(E) + sizeof(typename E::Mesh_t::vector_type[E::Mesh_t::Dimension])> {
308 constexpr static unsigned dim = E::dim;
309 using value_type =
typename E::value_type;
312 meta_grad(
const E& u,
const typename E::Mesh_t::vector_type vectors[])
314 for (
unsigned d = 0; d < E::Mesh_t::Dimension; d++) {
315 vectors_m[d] = vectors[d];
322 template <
typename... Idx>
323 KOKKOS_INLINE_FUNCTION
auto operator()(
const Idx... args)
const {
324 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
334 for (
unsigned d = 0; d < dim; d++) {
335 index_type coords[dim] = {args...};
338 auto&& right =
apply(u_m, coords);
341 auto&& left =
apply(u_m, coords);
343 res += vectors_m[d] * (right - left);
349 using Mesh_t =
typename E::Mesh_t;
352 vector_type vectors_m[dim];
361 template <
typename E>
365 sizeof(E) + sizeof(typename E::Mesh_t::vector_type[E::Mesh_t::Dimension])> {
366 constexpr static unsigned dim = E::dim;
369 meta_div(
const E& u,
const typename E::Mesh_t::vector_type vectors[])
371 for (
unsigned d = 0; d < E::Mesh_t::Dimension; d++) {
372 vectors_m[d] = vectors[d];
379 template <
typename... Idx>
380 KOKKOS_INLINE_FUNCTION
auto operator()(
const Idx... args)
const {
381 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
389 typename E::Mesh_t::value_type res = 0;
390 for (
unsigned d = 0; d < dim; d++) {
391 index_type coords[dim] = {args...};
394 auto&& right =
apply(u_m, coords);
397 auto&& left =
apply(u_m, coords);
399 res += dot(vectors_m[d], right - left).apply();
405 using Mesh_t =
typename E::Mesh_t;
408 vector_type vectors_m[dim];
414 template <
typename E>
416 :
public Expression<meta_laplace<E>,
417 sizeof(E) + sizeof(typename E::Mesh_t::vector_type)> {
418 constexpr static unsigned dim = E::dim;
419 using value_type =
typename E::value_type;
422 meta_laplace(
const E& u,
const typename E::Mesh_t::vector_type& hvector)
424 , hvector_m(hvector) {}
429 template <
typename... Idx>
430 KOKKOS_INLINE_FUNCTION
auto operator()(
const Idx... args)
const {
431 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
432 using T =
typename E::Mesh_t::value_type;
441 for (
unsigned d = 0; d < dim; d++) {
442 index_type coords[dim] = {args...};
443 auto&& center =
apply(u_m, coords);
446 auto&& left =
apply(u_m, coords);
449 auto&& right =
apply(u_m, coords);
451 res += hvector_m[d] * (left - 2 * center + right);
457 using Mesh_t =
typename E::Mesh_t;
460 const vector_type hvector_m;
469 template <
typename E>
471 :
public Expression<meta_curl<E>,
472 sizeof(E) + 4 * sizeof(typename E::Mesh_t::vector_type)> {
473 constexpr static unsigned dim = E::dim;
476 meta_curl(
const E& u,
const typename E::Mesh_t::vector_type& xvector,
477 const typename E::Mesh_t::vector_type& yvector,
478 const typename E::Mesh_t::vector_type& zvector,
479 const typename E::Mesh_t::vector_type& hvector)
484 , hvector_m(hvector) {}
489 KOKKOS_INLINE_FUNCTION
auto operator()(
size_t i,
size_t j,
size_t k)
const {
491 * ((u_m(i, j + 1, k)[2] - u_m(i, j - 1, k)[2]) / (2 * hvector_m[1])
492 - (u_m(i, j, k + 1)[1] - u_m(i, j, k - 1)[1]) / (2 * hvector_m[2]))
494 * ((u_m(i, j, k + 1)[0] - u_m(i, j, k - 1)[0]) / (2 * hvector_m[2])
495 - (u_m(i + 1, j, k)[2] - u_m(i - 1, j, k)[2]) / (2 * hvector_m[0]))
497 * ((u_m(i + 1, j, k)[1] - u_m(i - 1, j, k)[1]) / (2 * hvector_m[0])
498 - (u_m(i, j + 1, k)[0] - u_m(i, j - 1, k)[0]) / (2 * hvector_m[1]));
502 using Mesh_t =
typename E::Mesh_t;
505 const vector_type xvector_m;
506 const vector_type yvector_m;
507 const vector_type zvector_m;
508 const vector_type hvector_m;
517 template <
typename E>
519 :
public Expression<meta_hess<E>,
521 + sizeof(typename E::Mesh_t::vector_type[E::Mesh_t::Dimension])
522 + sizeof(typename E::Mesh_t::vector_type)> {
523 constexpr static unsigned dim = E::dim;
526 meta_hess(
const E& u,
const typename E::Mesh_t::vector_type vectors[],
527 const typename E::Mesh_t::vector_type& hvector)
529 , hvector_m(hvector) {
530 for (
unsigned d = 0; d < E::Mesh_t::Dimension; d++) {
531 vectors_m[d] = vectors[d];
538 template <
typename... Idx>
539 KOKKOS_INLINE_FUNCTION
auto operator()(
const Idx... args)
const {
541 computeHessian(std::make_index_sequence<dim>{}, hessian, args...);
546 using Mesh_t =
typename E::Mesh_t;
551 vector_type vectors_m[dim];
552 const vector_type hvector_m;
563 template <
size_t... row,
typename... Idx>
564 KOKKOS_INLINE_FUNCTION
constexpr void computeHessian(
565 const std::index_sequence<row...>& is, matrix_type& hessian,
566 const Idx... args)
const {
570 [[maybe_unused]]
auto _ = (hessianRow<row>(is, hessian, args...) + ...);
584 template <
size_t row,
size_t... col,
typename... Idx>
585 KOKKOS_INLINE_FUNCTION
constexpr int hessianRow(
const std::index_sequence<col...>&,
586 matrix_type& hessian,
587 const Idx... args)
const {
588 hessian[row] = (hessianEntry<row, col>(args...) + ...);
601 template <
size_t row,
size_t col,
typename... Idx>
602 KOKKOS_INLINE_FUNCTION
constexpr vector_type hessianEntry(
const Idx... args)
const {
603 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
604 index_type coords[dim] = {args...};
605 if constexpr (row == col) {
606 auto&& center =
apply(u_m, coords);
609 auto&& right =
apply(u_m, coords);
612 auto&& left =
apply(u_m, coords);
616 return vectors_m[row] * (right - 2. * center + left)
617 / (hvector_m[row] * hvector_m[row]);
621 auto&& uu =
apply(u_m, coords);
624 auto&& ud =
apply(u_m, coords);
627 auto&& dd =
apply(u_m, coords);
630 auto&& du =
apply(u_m, coords);
634 return vectors_m[col] * (uu - du - ud + dd)
635 / (4. * hvector_m[row] * hvector_m[col]);
639 return vector_type{};
#define DefineBinaryOperation(fun, name, op1, op2)
Definition IpplOperations.h:130
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
Definition IpplOperations.h:64
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply_impl(const View &view, const Coords &coords, const std::index_sequence< Idx... > &)
Definition IpplOperations.h:22
Definition IpplExpressions.h:26