* Constructor from tensors with different underlying scalar type. This
* obviously requires that the @p OtherNumber type is convertible to @p
* Number.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- constexpr Tensor(const Tensor<0, dim, OtherNumber> &initializer);
+ constexpr DEAL_II_CUDA_HOST_DEV
+ Tensor(const Tensor<0, dim, OtherNumber> &initializer);
/**
* Constructor, where the data is copied from a C-style array.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- constexpr Tensor(const OtherNumber &initializer);
+ constexpr DEAL_II_CUDA_HOST_DEV
+ Tensor(const OtherNumber &initializer);
/**
* Return a pointer to the first element of the underlying storage.
* Assignment from tensors with different underlying scalar type. This
* obviously requires that the @p OtherNumber type is convertible to @p
* Number.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator=(const Tensor<0, dim, OtherNumber> &rhs);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator=(const Tensor<0, dim, OtherNumber> &rhs);
#ifdef __INTEL_COMPILER
/**
* This is needed for ICC15 because it can't generate a suitable
* copy constructor for Sacado::Rad::ADvar types automatically.
* See https://github.com/dealii/dealii/pull/5865.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- DEAL_II_CONSTEXPR Tensor &
- operator=(const Tensor<0, dim, Number> &rhs);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator=(const Tensor<0, dim, Number> &rhs);
#endif
/**
* This operator assigns a scalar to a tensor. This obviously requires
* that the @p OtherNumber type is convertible to @p Number.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator=(const OtherNumber &d);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator=(const OtherNumber &d);
/**
* Test for equality of two tensors.
operator!=(const Tensor<0, dim, OtherNumber> &rhs) const;
/**
- * Add another scalar
+ * Add another scalar.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator+=(const Tensor<0, dim, OtherNumber> &rhs);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator+=(const Tensor<0, dim, OtherNumber> &rhs);
/**
* Subtract another scalar.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator-=(const Tensor<0, dim, OtherNumber> &rhs);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator-=(const Tensor<0, dim, OtherNumber> &rhs);
/**
* Multiply the scalar with a <tt>factor</tt>.
/**
* Divide the scalar by <tt>factor</tt>.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator/=(const OtherNumber &factor);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator/=(const OtherNumber &factor);
/**
* Tensor with inverted entries.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- constexpr Tensor
- operator-() const;
+ constexpr DEAL_II_CUDA_HOST_DEV Tensor
+ operator-() const;
/**
* Reset all values to zero.
* Return the Frobenius-norm of a tensor, i.e. the square root of the sum of
* the absolute squares of all entries. For the present case of rank-1
* tensors, this equals the usual <tt>l<sub>2</sub></tt> norm of the vector.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- DEAL_II_CONSTEXPR real_type
- norm() const;
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV real_type
+ norm() const;
/**
* Return the square of the Frobenius-norm of a tensor, i.e. the sum of the
/**
* Constructor, where the data is copied from a C-style array.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- constexpr explicit Tensor(const array_type &initializer);
+ constexpr DEAL_II_CUDA_HOST_DEV explicit Tensor(
+ const array_type &initializer);
/**
* Constructor from tensors with different underlying scalar type. This
* obviously requires that the @p OtherNumber type is convertible to @p
* Number.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- constexpr Tensor(const Tensor<rank_, dim, OtherNumber> &initializer);
+ constexpr DEAL_II_CUDA_HOST_DEV
+ Tensor(const Tensor<rank_, dim, OtherNumber> &initializer);
/**
* Constructor that converts from a "tensor of tensors".
* Assignment operator from tensors with different underlying scalar type.
* This obviously requires that the @p OtherNumber type is convertible to @p
* Number.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator=(const Tensor<rank_, dim, OtherNumber> &rhs);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator=(const Tensor<rank_, dim, OtherNumber> &rhs);
/**
* This operator assigns a scalar to a tensor. To avoid confusion with what
/**
* Add another tensor.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator+=(const Tensor<rank_, dim, OtherNumber> &);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator+=(const Tensor<rank_, dim, OtherNumber> &);
/**
* Subtract another tensor.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator-=(const Tensor<rank_, dim, OtherNumber> &);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator-=(const Tensor<rank_, dim, OtherNumber> &);
/**
* Scale the tensor by <tt>factor</tt>, i.e. multiply all components by
/**
* Scale the vector by <tt>1/factor</tt>.
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename OtherNumber>
- DEAL_II_CONSTEXPR Tensor &
- operator/=(const OtherNumber &factor);
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor &
+ operator/=(const OtherNumber &factor);
/**
* Unary minus operator. Negate all entries of a tensor.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- DEAL_II_CONSTEXPR Tensor
- operator-() const;
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV Tensor
+ operator-() const;
/**
* Reset all values to zero.
* Return the Frobenius-norm of a tensor, i.e. the square root of the sum of
* the absolute squares of all entries. For the present case of rank-1
* tensors, this equals the usual <tt>l<sub>2</sub></tt> norm of the vector.
+ *
+ * @note This function can also be used in CUDA device code.
*/
- DEAL_II_CONSTEXPR typename numbers::NumberTraits<Number>::real_type
- norm() const;
+ DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV
+ typename numbers::NumberTraits<Number>::real_type
+ norm() const;
/**
* Return the square of the Frobenius-norm of a tensor, i.e. the sum of the
/**
* This constructor is for internal use. It provides a way
- * to create constexpr constructors for Tensor<rank, dim, Number>
+ * to create constexpr constructors for Tensor<rank, dim, Number>
+ *
+ * @note This function can also be used in CUDA device code.
*/
template <typename ArrayLike, std::size_t... Indices>
- constexpr Tensor(const ArrayLike &initializer,
- std_cxx14::index_sequence<Indices...>);
+ constexpr DEAL_II_CUDA_HOST_DEV
+ Tensor(const ArrayLike &initializer, std_cxx14::index_sequence<Indices...>);
/**
* Allow an arbitrary Tensor to access the underlying values.
template <int dim, typename Number>
template <typename OtherNumber>
-constexpr Tensor<0, dim, Number>::Tensor(const OtherNumber &initializer)
+constexpr DEAL_II_CUDA_HOST_DEV
+Tensor<0, dim, Number>::Tensor(const OtherNumber &initializer)
: value(internal::NumberType<Number>::value(initializer))
{}
template <int dim, typename Number>
template <typename OtherNumber>
-constexpr Tensor<0, dim, Number>::Tensor(const Tensor<0, dim, OtherNumber> &p)
+constexpr DEAL_II_CUDA_HOST_DEV
+Tensor<0, dim, Number>::Tensor(const Tensor<0, dim, OtherNumber> &p)
: Tensor{p.value}
{}
template <int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator=(const Tensor<0, dim, OtherNumber> &p)
{
value = internal::NumberType<Number>::value(p);
#ifdef __INTEL_COMPILER
template <int dim, typename Number>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOS_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator=(const Tensor<0, dim, Number> &p)
{
value = p.value;
template <int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator=(const OtherNumber &d)
{
value = internal::NumberType<Number>::value(d);
DEAL_II_CONSTEXPR inline bool
Tensor<0, dim, Number>::operator==(const Tensor<0, dim, OtherNumber> &p) const
{
-#ifdef DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
+#if defined(DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING) && \
+ !defined(DEAL_II_COMPILER_CUDA_AWARE)
Assert(!(std::is_same<Number, adouble>::value ||
std::is_same<OtherNumber, adouble>::value),
ExcMessage(
template <int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator+=(const Tensor<0, dim, OtherNumber> &p)
{
value += p.value;
template <int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator-=(const Tensor<0, dim, OtherNumber> &p)
{
value -= p.value;
template <int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<0, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number> &
Tensor<0, dim, Number>::operator/=(const OtherNumber &s)
{
value /= s;
template <int dim, typename Number>
-constexpr Tensor<0, dim, Number>
+constexpr DEAL_II_CUDA_HOST_DEV Tensor<0, dim, Number>
Tensor<0, dim, Number>::operator-() const
{
return -value;
template <int rank_, int dim, typename Number>
template <typename ArrayLike, std::size_t... indices>
-DEAL_II_ALWAYS_INLINE constexpr Tensor<rank_, dim, Number>::Tensor(
- const ArrayLike &initializer,
- std_cxx14::index_sequence<indices...>)
+DEAL_II_ALWAYS_INLINE constexpr DEAL_II_CUDA_HOST_DEV
+Tensor<rank_, dim, Number>::Tensor(const ArrayLike &initializer,
+ std_cxx14::index_sequence<indices...>)
: values{Tensor<rank_ - 1, dim, Number>(initializer[indices])...}
{
static_assert(sizeof...(indices) == dim,
template <int rank_, int dim, typename Number>
-DEAL_II_ALWAYS_INLINE constexpr Tensor<rank_, dim, Number>::Tensor(
- const array_type &initializer)
+DEAL_II_ALWAYS_INLINE constexpr DEAL_II_CUDA_HOST_DEV
+Tensor<rank_, dim, Number>::Tensor(const array_type &initializer)
: Tensor(initializer, std_cxx14::make_index_sequence<dim>{})
{}
template <int rank_, int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_ALWAYS_INLINE constexpr Tensor<rank_, dim, Number>::Tensor(
+DEAL_II_ALWAYS_INLINE constexpr DEAL_II_CUDA_HOST_DEV
+Tensor<rank_, dim, Number>::Tensor(
const Tensor<rank_, dim, OtherNumber> &initializer)
: Tensor(initializer, std_cxx14::make_index_sequence<dim>{})
{}
Number>::value_type &Tensor<rank_, dim, Number>::
operator[](const unsigned int i) const
{
- return dealii::internal::TensorSubscriptor::subscript(
- values, i, std::integral_constant<int, dim>());
+ return values[i]; /*dealii::internal::TensorSubscriptor::subscript(
+ values, i, std::integral_constant<int, dim>());*/
}
template <int rank_, int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<rank_, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<rank_, dim, Number> &
Tensor<rank_, dim, Number>::operator+=(const Tensor<rank_, dim, OtherNumber> &p)
{
for (unsigned int i = 0; i < dim; ++i)
template <int rank_, int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<rank_, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<rank_, dim, Number> &
Tensor<rank_, dim, Number>::operator-=(const Tensor<rank_, dim, OtherNumber> &p)
{
for (unsigned int i = 0; i < dim; ++i)
template <int rank_, int dim, typename Number>
template <typename OtherNumber>
-DEAL_II_CONSTEXPR inline Tensor<rank_, dim, Number> &
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<rank_, dim, Number> &
Tensor<rank_, dim, Number>::operator/=(const OtherNumber &s)
{
for (unsigned int i = 0; i < dim; ++i)
template <int rank_, int dim, typename Number>
-DEAL_II_CONSTEXPR inline Tensor<rank_, dim, Number>
+DEAL_II_CONSTEXPR inline DEAL_II_CUDA_HOST_DEV Tensor<rank_, dim, Number>
Tensor<rank_, dim, Number>::operator-() const
{
Tensor<rank_, dim, Number> tmp;
* This function unwraps the underlying @p Number stored in the Tensor and
* multiplies @p object with it.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename Other>
-constexpr DEAL_II_ALWAYS_INLINE typename ProductType<Other, Number>::type
-operator*(const Other &object, const Tensor<0, dim, Number> &t)
+constexpr DEAL_II_CUDA_HOST_DEV DEAL_II_ALWAYS_INLINE
+ typename ProductType<Other, Number>::type
+ operator*(const Other &object, const Tensor<0, dim, Number> &t)
{
return object * static_cast<const Number &>(t);
}
* This function unwraps the underlying @p Number stored in the Tensor and
* multiplies @p object with it.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename Other>
-constexpr DEAL_II_ALWAYS_INLINE typename ProductType<Number, Other>::type
-operator*(const Tensor<0, dim, Number> &t, const Other &object)
+constexpr DEAL_II_CUDA_HOST_DEV DEAL_II_ALWAYS_INLINE
+ typename ProductType<Number, Other>::type
+ operator*(const Tensor<0, dim, Number> &t, const Other &object)
{
return static_cast<const Number &>(t) * object;
}
* OtherNumber that are stored within the Tensor and multiplies them. It
* returns an unwrapped number of product type.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename OtherNumber>
-constexpr DEAL_II_ALWAYS_INLINE typename ProductType<Number, OtherNumber>::type
-operator*(const Tensor<0, dim, Number> & src1,
- const Tensor<0, dim, OtherNumber> &src2)
+DEAL_II_CUDA_HOST_DEV constexpr DEAL_II_ALWAYS_INLINE
+ typename ProductType<Number, OtherNumber>::type
+ operator*(const Tensor<0, dim, Number> & src1,
+ const Tensor<0, dim, OtherNumber> &src2)
{
return static_cast<const Number &>(src1) *
static_cast<const OtherNumber &>(src2);
/**
* Division of a tensor of rank 0 by a scalar number.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename OtherNumber>
-constexpr DEAL_II_ALWAYS_INLINE
+DEAL_II_CUDA_HOST_DEV constexpr DEAL_II_ALWAYS_INLINE
Tensor<0,
dim,
typename ProductType<Number,
/**
* Add two tensors of rank 0.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename OtherNumber>
-constexpr DEAL_II_ALWAYS_INLINE
- Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
- operator+(const Tensor<0, dim, Number> & p,
+constexpr DEAL_II_ALWAYS_INLINE DEAL_II_CUDA_HOST_DEV
+ Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
+ operator+(const Tensor<0, dim, Number> & p,
const Tensor<0, dim, OtherNumber> &q)
{
return static_cast<const Number &>(p) + static_cast<const OtherNumber &>(q);
/**
* Subtract two tensors of rank 0.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor<0,dim,Number>
*/
template <int dim, typename Number, typename OtherNumber>
-constexpr DEAL_II_ALWAYS_INLINE
- Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
- operator-(const Tensor<0, dim, Number> & p,
+constexpr DEAL_II_ALWAYS_INLINE DEAL_II_CUDA_HOST_DEV
+ Tensor<0, dim, typename ProductType<Number, OtherNumber>::type>
+ operator-(const Tensor<0, dim, Number> & p,
const Tensor<0, dim, OtherNumber> &q)
{
return static_cast<const Number &>(p) - static_cast<const OtherNumber &>(q);
* number, a complex floating point number, etc.) is allowed, see the
* documentation of EnableIfScalar for details.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor
*/
template <int rank, int dim, typename Number, typename OtherNumber>
-DEAL_II_CONSTEXPR inline DEAL_II_ALWAYS_INLINE
- Tensor<rank,
+DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE
+ Tensor<rank,
dim,
typename ProductType<Number,
typename EnableIfScalar<OtherNumber>::type>::type>
- operator*(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
+ operator*(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
{
// recurse over the base objects
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tt;
* number, a complex floating point number, etc.) is allowed, see the
* documentation of EnableIfScalar for details.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor
*/
template <int rank, int dim, typename Number, typename OtherNumber>
-constexpr DEAL_II_ALWAYS_INLINE
+DEAL_II_CUDA_HOST_DEV constexpr DEAL_II_ALWAYS_INLINE
Tensor<rank,
dim,
typename ProductType<typename EnableIfScalar<Number>::type,
* discussion on operator*() above for more information about template
* arguments and the return type.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor
*/
template <int rank, int dim, typename Number, typename OtherNumber>
-DEAL_II_CONSTEXPR inline DEAL_II_ALWAYS_INLINE
- Tensor<rank,
+DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE
+ Tensor<rank,
dim,
typename ProductType<Number,
typename EnableIfScalar<OtherNumber>::type>::type>
- operator/(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
+ operator/(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
{
// recurse over the base objects
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tt;
*
* @tparam rank The rank of both tensors.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor
*/
template <int rank, int dim, typename Number, typename OtherNumber>
-DEAL_II_CONSTEXPR inline DEAL_II_ALWAYS_INLINE
- Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
- operator+(const Tensor<rank, dim, Number> & p,
+DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE
+ Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
+ operator+(const Tensor<rank, dim, Number> & p,
const Tensor<rank, dim, OtherNumber> &q)
{
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tmp(p);
*
* @tparam rank The rank of both tensors.
*
+ * @note This function can also be used in CUDA device code.
+ *
* @relatesalso Tensor
*/
template <int rank, int dim, typename Number, typename OtherNumber>
-DEAL_II_CONSTEXPR inline DEAL_II_ALWAYS_INLINE
- Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
- operator-(const Tensor<rank, dim, Number> & p,
+DEAL_II_CONSTEXPR DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE
+ Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type>
+ operator-(const Tensor<rank, dim, Number> & p,
const Tensor<rank, dim, OtherNumber> &q)
{
Tensor<rank, dim, typename ProductType<Number, OtherNumber>::type> tmp(p);
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+// Test operator[] and norm_square of cuda_tensor.
+
+#include <deal.II/base/tensor.h>
+
+#include "../tests.h"
+
+template <int rank, int dim, typename Number>
+__global__ void
+miscellaneous_kernel()
+{
+ // constructors
+ typename Tensor<rank, dim, Number>::array_type array{};
+ Tensor<rank, dim, Number> dummy_1(array);
+ Tensor<rank, dim, Number> dummy_2;
+ Tensor<rank, dim, Number> dummy_3 = dummy_2;
+
+ // access
+ Tensor<rank + 1, dim, Number> initializer_1;
+ const auto dummy_5 = initializer_1[0];
+
+ // assignment
+ dummy_2 = dummy_3;
+}
+
+template <int rank, int dim, typename Number>
+__global__ void
+summation_kernel(Tensor<rank, dim, Number> *t,
+ Tensor<rank, dim, Number> *t1,
+ Tensor<rank, dim, Number> *t2)
+{
+ *t2 += *t;
+ *t1 = *t1 + *t;
+}
+
+template <int rank, int dim, typename Number>
+__global__ void
+subtraction_kernel(Tensor<rank, dim, Number> *t,
+ Tensor<rank, dim, Number> *t1,
+ Tensor<rank, dim, Number> *t2)
+{
+ *t2 -= *t;
+ *t1 = *t1 - *t;
+}
+
+template <int rank, int dim, typename Number>
+__global__ void
+multiplication_kernel(Tensor<rank, dim, Number> *t,
+ Tensor<rank, dim, Number> *t1,
+ Tensor<rank, dim, Number> *t2)
+{
+ *t1 = *t * Number(2.);
+ *t2 = Number(2.) * *t;
+ *t *= 2.;
+}
+
+template <int rank, int dim, typename Number>
+__global__ void
+division_kernel(Tensor<rank, dim, Number> *t,
+ Tensor<rank, dim, Number> *t1,
+ Tensor<rank, dim, Number> *t2)
+{
+ *t1 = *t / Number(2.);
+ *t /= 2.;
+ *t2 = *t1;
+}
+
+template <int dim, typename Number>
+__global__ void init_kernel(Tensor<0, dim, Number> *t)
+{
+ if (threadIdx.x == 0)
+ *t = 1.;
+}
+
+template <int dim, typename Number>
+__global__ void init_kernel(Tensor<1, dim, Number> *t)
+{
+ const unsigned int i = threadIdx.x;
+ if (i < dim)
+ (*t)[i] = i + 1.;
+}
+
+template <int dim, typename Number>
+__global__ void init_kernel(Tensor<2, dim, Number> *t)
+{
+ const unsigned int i = threadIdx.y;
+ const unsigned int j = threadIdx.x;
+ if ((i < dim) && (j < dim))
+ (*t)[i][j] = j + i * dim + 1.;
+}
+
+
+template <int rank, int dim, typename Number>
+void
+test_gpu()
+{
+ const double tolerance = 1.e-8;
+
+ Tensor<rank, dim, Number> *t_dev;
+ Tensor<rank, dim, Number> *t1_dev;
+ Tensor<rank, dim, Number> *t2_dev;
+
+ Tensor<rank, dim, Number> t_host;
+ Tensor<rank, dim, Number> t1_host;
+ Tensor<rank, dim, Number> t2_host;
+
+ Tensor<rank, dim, Number> reference_host;
+
+ // Allocate objects on the device
+ cudaError_t cuda_error =
+ cudaMalloc(&t_dev, sizeof(Tensor<rank, dim, Number>));
+ AssertCuda(cuda_error);
+ cuda_error = cudaMalloc(&t1_dev, sizeof(Tensor<rank, dim, Number>));
+ AssertCuda(cuda_error);
+ cuda_error = cudaMalloc(&t2_dev, sizeof(Tensor<rank, dim, Number>));
+ AssertCuda(cuda_error);
+
+ // Initialize
+ dim3 block_dim(dim, dim);
+ init_kernel<<<1, block_dim>>>(t_dev);
+ cuda_error = cudaMemcpy(&reference_host,
+ t_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+
+ // Test multiplication.
+ multiplication_kernel<<<1, 1>>>(t_dev, t1_dev, t2_dev);
+
+ cuda_error = cudaMemcpy(&t_host,
+ t_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+ cuda_error = cudaMemcpy(&t1_host,
+ t1_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+ cuda_error = cudaMemcpy(&t2_host,
+ t2_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+
+ reference_host *= 2;
+ AssertThrow((t_host - reference_host).norm() < tolerance, ExcInternalError());
+ AssertThrow((t1_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+ AssertThrow((t2_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+
+ deallog << "multiplication OK" << std::endl;
+
+ // Test division.
+ division_kernel<<<1, 1>>>(t_dev, t1_dev, t2_dev);
+ cuda_error = cudaMemcpy(&t_host,
+ t_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+ cuda_error = cudaMemcpy(&t1_host,
+ t1_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+
+ reference_host /= 2.;
+ AssertThrow((t_host - reference_host).norm() < tolerance, ExcInternalError());
+ AssertThrow((t1_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+
+ deallog << "division OK" << std::endl;
+
+ // Test summation
+ summation_kernel<<<1, 1>>>(t_dev, t1_dev, t2_dev);
+ cuda_error = cudaMemcpy(&t1_host,
+ t1_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+ cuda_error = cudaMemcpy(&t2_host,
+ t2_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+
+ reference_host *= 2.;
+ AssertThrow((t1_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+ AssertThrow((t2_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+
+
+ // Test subtraction
+ subtraction_kernel<<<1, 1>>>(t_dev, t1_dev, t2_dev);
+ cuda_error = cudaMemcpy(&t1_host,
+ t1_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+ AssertCuda(cuda_error);
+ cuda_error = cudaMemcpy(&t2_host,
+ t2_dev,
+ sizeof(Tensor<rank, dim, Number>),
+ cudaMemcpyDeviceToHost);
+
+ reference_host /= 2.;
+ AssertThrow((t1_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+ AssertThrow((t2_host - reference_host).norm() < tolerance,
+ ExcInternalError());
+
+ // Miscellaneous
+ miscellaneous_kernel<rank, dim, Number><<<1, 1>>>();
+
+ // Free memory
+ cuda_error = cudaFree(t_dev);
+ AssertCuda(cuda_error);
+ cuda_error = cudaFree(t1_dev);
+ AssertCuda(cuda_error);
+ cuda_error = cudaFree(t2_dev);
+ AssertCuda(cuda_error);
+}
+
+int
+main()
+{
+ initlog();
+
+ init_cuda();
+
+ test_gpu<0, 3, double>();
+ test_gpu<1, 3, double>();
+ test_gpu<2, 3, double>();
+ test_gpu<0, 3, float>();
+ test_gpu<1, 3, float>();
+ test_gpu<2, 3, float>();
+}