10 #ifndef TPETRA_DETAILS_COPYCONVERT_HPP
11 #define TPETRA_DETAILS_COPYCONVERT_HPP
18 #include "TpetraCore_config.h"
19 #include "Kokkos_Core.hpp"
20 #if KOKKOS_VERSION >= 40799
21 #include "KokkosKernels_ArithTraits.hpp"
23 #include "Kokkos_ArithTraits.hpp"
27 #include <type_traits>
41 template <
class OutputValueType,
43 const bool outputIsComplex =
44 #if KOKKOS_VERSION >= 40799
45 KokkosKernels::ArithTraits<OutputValueType>::is_complex,
47 Kokkos::ArithTraits<OutputValueType>::is_complex,
49 const bool inputIsComplex =
50 #if KOKKOS_VERSION >= 40799
51 KokkosKernels::ArithTraits<InputValueType>::is_complex>
53 Kokkos::ArithTraits<InputValueType>::is_complex>
56 static KOKKOS_INLINE_FUNCTION
void
57 convert(OutputValueType& dst,
const InputValueType& src) {
62 dst = OutputValueType(src);
66 template <
class OutputRealType,
class InputComplexType>
67 struct ConvertValue<OutputRealType, InputComplexType, false, true> {
68 static KOKKOS_INLINE_FUNCTION
void
69 convert(OutputRealType& dst,
70 const InputComplexType& src) {
73 #if KOKKOS_VERSION >= 40799
74 using KAI = KokkosKernels::ArithTraits<InputComplexType>;
76 using KAI = Kokkos::ArithTraits<InputComplexType>;
78 dst = OutputRealType(KAI::real(src));
82 template <
class OutputComplexType,
class InputRealType>
83 struct ConvertValue<OutputComplexType, InputRealType, true, false> {
84 static KOKKOS_INLINE_FUNCTION
void
85 convert(OutputComplexType& dst,
86 const InputRealType& src) {
89 using output_mag_type =
90 #if KOKKOS_VERSION >= 40799
91 typename KokkosKernels::ArithTraits<OutputComplexType>::mag_type;
93 typename Kokkos::ArithTraits<OutputComplexType>::mag_type;
95 #if KOKKOS_VERSION >= 40799
96 using KAM = KokkosKernels::ArithTraits<output_mag_type>;
98 using KAM = Kokkos::ArithTraits<output_mag_type>;
100 dst = OutputComplexType(src, KAM::zero());
104 template <
class OutputValueType,
105 class InputValueType>
106 KOKKOS_INLINE_FUNCTION
void
107 convertValue(OutputValueType& dst,
const InputValueType& src) {
108 ConvertValue<OutputValueType, InputValueType>::convert(dst, src);
115 template <
class OutputViewType,
117 const int rank =
static_cast<int>(OutputViewType::rank)>
118 class CopyConvertFunctor {};
120 template <
class OutputViewType,
122 class CopyConvertFunctor<OutputViewType, InputViewType, 1> {
124 static_assert(static_cast<int>(OutputViewType::rank) == 1 &&
125 static_cast<int>(InputViewType::rank) == 1,
126 "CopyConvertFunctor (implements Tpetra::Details::copyConvert): "
127 "OutputViewType and InputViewType must both have rank 1.");
132 using index_type =
typename OutputViewType::size_type;
134 CopyConvertFunctor(
const OutputViewType& dst,
135 const InputViewType& src)
139 KOKKOS_INLINE_FUNCTION
void
140 operator()(
const index_type i)
const {
141 convertValue(dst_(i), src_(i));
145 template <
class OutputViewType,
147 class CopyConvertFunctor<OutputViewType, InputViewType, 2> {
149 using index_type =
typename OutputViewType::size_type;
152 static_assert(static_cast<int>(OutputViewType::rank) == 2 &&
153 static_cast<int>(InputViewType::rank) == 2,
154 "CopyConvertFunctor (implements Tpetra::Details::copyConvert): "
155 "OutputViewType and InputViewType must both have rank 2.");
161 CopyConvertFunctor(
const OutputViewType& dst,
162 const InputViewType& src)
165 , numCols_(dst.extent(1)) {}
167 KOKKOS_INLINE_FUNCTION
void
168 operator()(
const index_type i)
const {
169 const index_type numCols = numCols_;
170 for (index_type j = 0; j < numCols; ++j) {
171 convertValue(dst_(i, j), src_(i, j));
177 template <
class OutputViewType,
class InputViewType>
178 class CanUseKokkosDeepCopy {
180 static constexpr
bool sameValueType =
181 std::is_same<
typename OutputViewType::non_const_value_type,
182 typename InputViewType::non_const_value_type>::value;
183 static constexpr
bool sameMemorySpace =
184 std::is_same<
typename OutputViewType::memory_space,
185 typename InputViewType::memory_space>::value;
186 static constexpr
bool sameLayout =
187 std::is_same<
typename OutputViewType::array_layout,
188 typename InputViewType::array_layout>::value;
191 static constexpr
bool value =
192 sameValueType && (sameMemorySpace || sameLayout);
213 template <
class OutputViewType,
215 const bool canUseKokkosDeepCopy =
216 CanUseKokkosDeepCopy<OutputViewType, InputViewType>::value,
217 const bool outputExecSpaceCanAccessInputMemSpace =
218 Kokkos::SpaceAccessibility<
219 typename OutputViewType::memory_space,
220 typename InputViewType::memory_space>::accessible>
221 struct CopyConvertImpl {
223 run(
const OutputViewType& dst,
224 const InputViewType& src);
228 template <
class OutputViewType,
230 const bool outputExecSpaceCanAccessInputMemSpace>
231 struct CopyConvertImpl<OutputViewType, InputViewType,
232 true, outputExecSpaceCanAccessInputMemSpace> {
234 run(
const OutputViewType& dst,
235 const InputViewType& src) {
241 const ptrdiff_t dst_beg =
reinterpret_cast<ptrdiff_t
>(dst.data());
242 const ptrdiff_t dst_end =
243 reinterpret_cast<ptrdiff_t
>(dst.data() + dst.span());
244 const ptrdiff_t src_beg =
reinterpret_cast<ptrdiff_t
>(src.data());
245 const ptrdiff_t src_end =
246 reinterpret_cast<ptrdiff_t
>(src.data() + src.span());
248 if (dst_end > src_beg && src_end > dst_beg) {
256 auto src_copy = Kokkos::create_mirror(Kokkos::HostSpace(), src);
263 using execution_space =
typename OutputViewType::execution_space;
271 template <
class OutputViewType,
273 struct CopyConvertImpl<OutputViewType,
278 run(
const OutputViewType& dst,
279 const InputViewType& src) {
280 using functor_type = CopyConvertFunctor<OutputViewType, InputViewType>;
281 using execution_space =
typename OutputViewType::execution_space;
282 using index_type =
typename OutputViewType::size_type;
283 using range_type = Kokkos::RangePolicy<execution_space, index_type>;
284 Kokkos::parallel_for(
"Tpetra::Details::copyConvert",
285 range_type(0, dst.extent(0)),
286 functor_type(dst, src));
296 template <
class OutputViewType,
298 struct CopyConvertImpl<OutputViewType, InputViewType, false, false> {
300 run(
const OutputViewType& dst,
301 const InputViewType& src) {
302 using output_memory_space =
typename OutputViewType::memory_space;
303 using output_execution_space =
typename OutputViewType::execution_space;
304 auto src_outputSpaceCopy =
305 Kokkos::create_mirror_view(output_memory_space(), src);
311 using output_space_copy_type = decltype(src_outputSpaceCopy);
313 CopyConvertFunctor<OutputViewType, output_space_copy_type>;
314 using execution_space =
typename OutputViewType::execution_space;
315 using index_type =
typename OutputViewType::size_type;
316 using range_type = Kokkos::RangePolicy<execution_space, index_type>;
317 Kokkos::parallel_for(
"Tpetra::Details::copyConvert",
318 range_type(0, dst.extent(0)),
319 functor_type(dst, src_outputSpaceCopy));
332 template <
class OutputViewType,
335 const InputViewType& src) {
336 static_assert(Kokkos::is_view<OutputViewType>::value,
337 "OutputViewType must be a Kokkos::View.");
338 static_assert(Kokkos::is_view<InputViewType>::value,
339 "InputViewType must be a Kokkos::View.");
340 static_assert(std::is_same<
typename OutputViewType::value_type,
341 typename OutputViewType::non_const_value_type>::value,
342 "OutputViewType must be a nonconst Kokkos::View.");
343 static_assert(static_cast<int>(OutputViewType::rank) ==
344 static_cast<int>(InputViewType::rank),
345 "src and dst must have the same rank.");
347 if (dst.extent(0) != src.extent(0)) {
348 std::ostringstream os;
349 os <<
"Tpetra::Details::copyConvert: "
350 <<
"dst.extent(0) = " << dst.extent(0)
351 <<
" != src.extent(0) = " << src.extent(0)
353 throw std::invalid_argument(os.str());
355 if (static_cast<int>(OutputViewType::rank) > 1 &&
356 dst.extent(1) != src.extent(1)) {
357 std::ostringstream os;
358 os <<
"Tpetra::Details::copyConvert: "
359 <<
"dst.extent(1) = " << dst.extent(1)
360 <<
" != src.extent(1) = " << src.extent(1)
362 throw std::invalid_argument(os.str());
366 using output_view_type =
367 Kokkos::View<
typename OutputViewType::non_const_data_type,
368 typename OutputViewType::array_layout,
369 typename OutputViewType::device_type>;
370 using input_view_type =
371 Kokkos::View<
typename InputViewType::const_data_type,
372 typename InputViewType::array_layout,
373 typename InputViewType::device_type>;
374 CopyConvertImpl<output_view_type, input_view_type>::run(dst, src);
380 #endif // TPETRA_DETAILS_COPYCONVERT_HPP
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void copyConvert(const OutputViewType &dst, const InputViewType &src)
Copy values from the 1-D Kokkos::View src, to the 1-D Kokkos::View dst, of the same length...