8#include <compile_time_options.h>
11#include <deal.II/base/tensor.h>
12#include <deal.II/base/utilities.h>
13#include <deal.II/base/vectorization.h>
34#define AssertThrowSIMD(variable, condition, exception) \
35 if constexpr (std::is_same< \
36 typename std::remove_const<decltype(variable)>::type, \
39 typename std::remove_const<decltype(variable)>::type, \
41 AssertThrow(condition(variable), exception); \
43 for (unsigned int k = 0; k < decltype(variable)::size(); ++k) { \
44 AssertThrow(condition((variable)[k]), exception); \
71 template <
typename T, std::
size_t w
idth>
81 template <
typename Functor,
size_t... Is>
82 auto generate_iterators_impl(Functor f, std::index_sequence<Is...>)
83 -> std::array<
decltype(f(0)),
sizeof...(Is)>
102 template <
unsigned int length,
typename Functor>
104 -> std::array<
decltype(f(0)), length>
106 return generate_iterators_impl<>(f, std::make_index_sequence<length>());
115 template <
typename T>
118 for (
auto &it : iterators)
133 template <
typename Number>
136 return std::max(Number(0.), number);
145 template <
typename Number>
148 return -std::min(Number(0.), number);
162 template <
typename Number>
163 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
167 constexpr ScalarNumber
min = std::numeric_limits<ScalarNumber>::min();
169 return std::max(numerator, Number(0.)) / std::max(denominator, Number(
min));
180 template <dealii::SIMDComparison predicate,
typename Number>
181 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
184 const Number &true_value,
185 const Number &false_value)
187 static_assert(std::is_floating_point_v<Number>,
188 "Only scalar number types are allowed");
191 if constexpr (predicate == dealii::SIMDComparison::equal)
192 mask = (left == right);
193 else if constexpr (predicate == dealii::SIMDComparison::not_equal)
194 mask = (left != right);
195 else if constexpr (predicate == dealii::SIMDComparison::less_than)
196 mask = (left < right);
197 else if constexpr (predicate == dealii::SIMDComparison::less_than_or_equal)
198 mask = (left <= right);
199 else if constexpr (predicate == dealii::SIMDComparison::greater_than)
200 mask = (left > right);
202 mask = (left >= right);
204 return mask ? true_value : false_value;
214 template <dealii::SIMDComparison predicate,
typename T, std::
size_t w
idth>
215 DEAL_II_ALWAYS_INLINE
inline dealii::VectorizedArray<T, width>
217 const dealii::VectorizedArray<T, width> &right,
218 const dealii::VectorizedArray<T, width> &true_value,
219 const dealii::VectorizedArray<T, width> &false_value)
221 return dealii::compare_and_apply_mask<predicate>(
222 left, right, true_value, false_value);
233 template <
int N,
typename T>
236 return dealii::Utilities::fixed_power<N, T>(x);
245 template <
typename T>
246 DEAL_II_HOST_DEVICE T
pow(
const T x,
const T b);
254 template <
typename T, std::
size_t w
idth>
255 dealii::VectorizedArray<T, width>
256 pow(
const dealii::VectorizedArray<T, width> x,
const T b);
265 template <
typename T, std::
size_t w
idth>
266 dealii::VectorizedArray<T, width>
267 pow(
const dealii::VectorizedArray<T, width> x,
268 const dealii::VectorizedArray<T, width> b);
272 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
float pow(
const float x,
const float b)
274#ifdef RYUJIN_DEVICE_COMPILATION_PASS
276 return std::pow(x, b);
277#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
279 return pow(dealii::VectorizedArray<float, 4>(x), b)[0];
282 return std::pow(x, b);
288 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
double pow(
const double x,
const double b)
290#ifdef RYUJIN_DEVICE_COMPILATION_PASS
292 return std::pow(x, b);
293#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
295 return pow(dealii::VectorizedArray<double, 2>(x), b)[0];
298 return std::pow(x, b);
329 template <
typename T>
340 template <
typename T, std::
size_t w
idth>
341 dealii::VectorizedArray<T, width>
342 fast_pow(
const dealii::VectorizedArray<T, width> x,
353 template <
typename T, std::
size_t w
idth>
354 dealii::VectorizedArray<T, width>
355 fast_pow(
const dealii::VectorizedArray<T, width> x,
356 const dealii::VectorizedArray<T, width> b,
361 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
float
362 fast_pow(
const float x,
const float b, [[maybe_unused]]
const Bias bias)
364#ifdef RYUJIN_DEVICE_COMPILATION_PASS
366 return std::pow(x, b);
367#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
369 return fast_pow(dealii::VectorizedArray<float, 4>(x), b, bias)[0];
372 return std::pow(x, b);
378 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
double
379 fast_pow(
const double x,
const double b, [[maybe_unused]]
const Bias bias)
381#ifdef RYUJIN_DEVICE_COMPILATION_PASS
383 return std::pow(
static_cast<float>(x),
static_cast<float>(b));
384#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 1 && defined(__SSE2__)
386 return fast_pow(dealii::VectorizedArray<double, 2>(x), b, bias)[0];
389 return std::pow(
static_cast<float>(x),
static_cast<float>(b));
405 template <
typename T,
typename V>
406 DEAL_II_ALWAYS_INLINE
inline T
read_entry(
const V &vector,
unsigned int i)
408 static_assert(std::is_same_v<typename get_value_type<T>::type,
409 typename V::value_type>,
413 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
415 result = vector.local_element(i);
418 result.load(vector.get_values() + i);
429 template <
typename T,
typename T2>
430 DEAL_II_ALWAYS_INLINE
inline T
read_entry(
const std::vector<T2> &vector,
433 if constexpr (std::is_same_v<typename get_value_type<T>::type, T2>) {
437 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
442 result.load(vector.data() + i);
449 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
453 for (
unsigned int k = 0; k < T::size(); ++k)
454 result[k] = vector[i + k];
467 template <
typename T,
typename V>
469 const unsigned int *js)
471 static_assert(std::is_same_v<typename get_value_type<T>::type,
472 typename V::value_type>,
476 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
478 result = vector.local_element(js[0]);
481 result.gather(vector.get_values(), js);
492 template <
typename T,
typename T2>
493 DEAL_II_ALWAYS_INLINE
inline T
read_entry(
const std::vector<T2> &vector,
494 const unsigned int *js)
496 static_assert(std::is_same_v<typename get_value_type<T>::type, T2>,
500 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
502 result = vector[js[0]];
505 result.load(vector.data(), js);
517 template <
typename T,
typename V>
518 DEAL_II_ALWAYS_INLINE
inline void
521 static_assert(std::is_same_v<typename get_value_type<T>::type,
522 typename V::value_type>,
525 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
527 vector.local_element(i) = values;
530 values.store(vector.get_values() + i);
539 template <
typename T,
typename T2>
540 DEAL_II_ALWAYS_INLINE
inline void
541 write_entry(std::vector<T2> &vector,
const T &values,
unsigned int i)
543 if constexpr (std::is_same_v<typename get_value_type<T>::type, T2>) {
546 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
551 values.store(vector.data() + i);
556 if constexpr (std::is_same_v<T, typename get_value_type<T>::type>) {
560 for (
unsigned int k = 0; k < T::size(); ++k)
561 vector[i + k] = values[k];
572 template <
int rank,
int dim, std::
size_t w
idth,
typename Number>
573 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<rank, dim, Number>
575 const dealii::Tensor<rank, dim, dealii::VectorizedArray<Number, width>>
577 const unsigned int k)
579 Assert(k < width, dealii::ExcMessage(
"Index past VectorizedArray width"));
580 dealii::Tensor<rank, dim, Number> result;
581 if constexpr (rank == 1) {
582 for (
unsigned int d = 0; d < dim; ++d)
583 result[d] = vectorized[d][k];
585 for (
unsigned int d = 0; d < dim; ++d)
598 template <
int rank,
int dim,
typename Number>
599 DEAL_II_ALWAYS_INLINE
inline dealii::Tensor<rank, dim, Number>
601 const unsigned int k [[maybe_unused]])
605 "The given index k must be zero for a serial tensor"));
615 template <
int rank,
int dim, std::
size_t w
idth,
typename Number>
617 dealii::Tensor<rank, dim, dealii::VectorizedArray<Number, width>> &result,
618 const dealii::Tensor<rank, dim, Number> &
serial,
619 const unsigned int k)
621 Assert(k < width, dealii::ExcMessage(
"Index past VectorizedArray width"));
622 if constexpr (rank == 1) {
623 for (
unsigned int d = 0; d < dim; ++d)
626 for (
unsigned int d = 0; d < dim; ++d)
638 template <
int rank,
int dim,
typename Number>
639 DEAL_II_ALWAYS_INLINE
inline void
641 const dealii::Tensor<rank, dim, Number> &
serial,
642 const unsigned int k [[maybe_unused]])
646 "The given index k must be zero for a serial tensor"));
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_ALWAYS_INLINE T read_entry(const V &vector, unsigned int i)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)
DEAL_II_ALWAYS_INLINE void assign_serial_tensor(dealii::Tensor< rank, dim, dealii::VectorizedArray< Number, width > > &result, const dealii::Tensor< rank, dim, Number > &serial, const unsigned int k)
DEAL_II_ALWAYS_INLINE auto generate_iterators(Functor f) -> std::array< auto, length >
DEAL_II_HOST_DEVICE T fast_pow(const T x, const T b, const Bias bias=Bias::none)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE T fixed_power(const T x)
DEAL_II_ALWAYS_INLINE void increment_iterators(T &iterators)
DEAL_II_ALWAYS_INLINE void write_entry(V &vector, const T &values, unsigned int i)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number compare_and_apply_mask(const Number &left, const Number &right, const Number &true_value, const Number &false_value)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number safe_division(const Number &numerator, const Number &denominator)
DEAL_II_ALWAYS_INLINE dealii::Tensor< rank, dim, Number > serialize_tensor(const dealii::Tensor< rank, dim, dealii::VectorizedArray< Number, width > > &vectorized, const unsigned int k)