16#ifndef CABANA_GRID_FASTFOURIERTRANSFORM_HPP
17#define CABANA_GRID_FASTFOURIERTRANSFORM_HPP
22#include <Kokkos_Core.hpp>
23#include <Kokkos_Profiling_ScopedRegion.hpp>
25#include <heffte_fft3d.h>
64struct FFTBackendDefault
71template <
class ArrayEntity,
class ArrayMesh,
class ArrayMemorySpace,
72 class ArrayScalar,
class Entity,
class Mesh,
class MemorySpace,
73 class Scalar,
typename SFINAE =
void>
76 static_assert( std::is_same<ArrayEntity, Entity>::value,
77 "Array entity type mush match FFT entity type." );
78 static_assert( std::is_same<ArrayMesh, Mesh>::value,
79 "Array mesh type mush match FFT mesh type." );
80 static_assert( std::is_same<ArrayMemorySpace, MemorySpace>::value,
81 "Array memory space must match FFT memory space." );
85template <
class ArrayEntity,
class ArrayMesh,
class ArrayMemorySpace,
86 class ArrayScalar,
class Entity,
class Mesh,
class MemorySpace,
89 ArrayEntity, ArrayMesh, ArrayMemorySpace, ArrayScalar, Entity, Mesh,
91 typename std::enable_if<
92 std::is_same<ArrayEntity, Entity>::value &&
93 std::is_same<ArrayMesh, Mesh>::value &&
94 std::is_same<ArrayMemorySpace, MemorySpace>::value>::type>
95 :
public std::true_type
133 FFTcomm = FFTCommPattern::alltoallv;
135 FFTcomm = FFTCommPattern::p2p;
170template <
class EntityType,
class MeshType,
class Scalar,
class MemorySpace,
188 Cabana::Impl::deprecated( Kokkos::is_device<MemorySpace>() ) );
195 using device_type [[deprecated]] =
typename memory_space::device_type;
217 const auto& global_grid = layout.
localGrid()->globalGrid();
226 int local_num_entity =
239 throw std::logic_error(
240 "Only 1 complex value per entity allowed in FFT" );
248 template <
class Array_t,
class ScaleType>
250 const Array_t& x,
const ScaleType scaling,
251 typename std::enable_if<
254 typename Array_t::entity_type,
typename Array_t::mesh_type,
255 typename Array_t::memory_space,
typename Array_t::value_type,
259 Kokkos::Profiling::ScopedRegion region(
"Cabana::FFT::forward" );
262 static_cast<Derived*
>( this )->forwardImpl( x, scaling );
270 template <
class Array_t,
class ScaleType>
272 const Array_t& x,
const ScaleType scaling,
273 typename std::enable_if<
276 typename Array_t::entity_type,
typename Array_t::mesh_type,
277 typename Array_t::memory_space,
typename Array_t::value_type,
281 Kokkos::Profiling::ScopedRegion region(
"Cabana::FFT::reverse" );
284 static_cast<Derived*
>( this )->reverseImpl( x, scaling );
290 template <
class ExecutionSpace,
class IndexSpaceType,
class LViewType,
292 std::enable_if_t<3 == NSD, void>
293 copyToLocal( ExecutionSpace exec_space,
const IndexSpaceType own_space,
294 LViewType& l_view,
const LGViewType lg_view )
296 Kokkos::parallel_for(
298 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
299 auto iw = i - own_space.min( Dim::I );
300 auto jw = j - own_space.min( Dim::J );
301 auto kw = k - own_space.min( Dim::K );
302 l_view( iw, jw, kw, 0 ) = lg_view( i, j, k, 0 );
303 l_view( iw, jw, kw, 1 ) = lg_view( i, j, k, 1 );
310 template <
class ExecutionSpace,
class IndexSpaceType,
class LViewType,
312 std::enable_if_t<2 == NSD, void>
313 copyToLocal( ExecutionSpace space,
const IndexSpaceType own_space,
314 LViewType& l_view,
const LGViewType lg_view )
316 Kokkos::parallel_for(
318 KOKKOS_LAMBDA(
const int i,
const int j ) {
319 auto iw = i - own_space.min( Dim::I );
320 auto jw = j - own_space.min( Dim::J );
321 l_view( iw, jw, 0 ) = lg_view( i, j, 0 );
322 l_view( iw, jw, 1 ) = lg_view( i, j, 1 );
329 template <
class ExecutionSpace,
class IndexSpaceType,
class LViewType,
331 std::enable_if_t<3 == NSD, void>
333 const LViewType l_view, LGViewType& lg_view )
335 Kokkos::parallel_for(
337 KOKKOS_LAMBDA(
const int i,
const int j,
const int k ) {
338 auto iw = i - own_space.min( Dim::I );
339 auto jw = j - own_space.min( Dim::J );
340 auto kw = k - own_space.min( Dim::K );
341 lg_view( i, j, k, 0 ) = l_view( iw, jw, kw, 0 );
342 lg_view( i, j, k, 1 ) = l_view( iw, jw, kw, 1 );
349 template <
class ExecutionSpace,
class IndexSpaceType,
class LViewType,
351 std::enable_if_t<2 == NSD, void>
353 const LViewType l_view, LGViewType& lg_view )
355 Kokkos::parallel_for(
357 KOKKOS_LAMBDA(
const int i,
const int j ) {
358 auto iw = i - own_space.min( Dim::I );
359 auto jw = j - own_space.min( Dim::J );
360 lg_view( i, j, 0 ) = l_view( iw, jw, 0 );
361 lg_view( i, j, 1 ) = l_view( iw, jw, 1 );
372template <
class ExecutionSpace,
class BackendType>
373struct HeffteBackendTraits
376#ifdef Heffte_ENABLE_MKL
377template <
class ExecutionSpace>
378struct HeffteBackendTraits<ExecutionSpace, FFTBackendMKL>
380 using backend_type = heffte::backend::mkl;
383#ifdef Heffte_ENABLE_FFTW
384template <
class ExecutionSpace>
385struct HeffteBackendTraits<ExecutionSpace, FFTBackendFFTW>
387 using backend_type = heffte::backend::fftw;
390#ifdef Heffte_ENABLE_FFTW
391template <
class ExecutionSpace>
392struct HeffteBackendTraits<ExecutionSpace, Impl::FFTBackendDefault>
394 using backend_type = heffte::backend::fftw;
397#ifdef Heffte_ENABLE_MKL
398template <
class ExecutionSpace>
399struct HeffteBackendTraits<ExecutionSpace, Impl::FFTBackendDefault>
401 using backend_type = heffte::backend::mkl;
404throw std::runtime_error(
"Must enable at least one heFFTe host backend." );
407#ifdef Heffte_ENABLE_CUDA
408#ifdef KOKKOS_ENABLE_CUDA
410struct HeffteBackendTraits<Kokkos::Cuda, Impl::FFTBackendDefault>
412 using backend_type = heffte::backend::cufft;
416#ifdef Heffte_ENABLE_ROCM
417#ifdef KOKKOS_ENABLE_HIP
419struct HeffteBackendTraits<Kokkos::Experimental::HIP, Impl::FFTBackendDefault>
421 using backend_type = heffte::backend::rocfft;
425#ifdef Heffte_ENABLE_ONEAPI
426#ifdef KOKKOS_ENABLE_SYCL
428struct HeffteBackendTraits<Kokkos::Experimental::SYCL, Impl::FFTBackendDefault>
430 using backend_type = heffte::backend::onemkl;
435template <
class ScaleType>
436struct HeffteScalingTraits
440struct HeffteScalingTraits<FFTScaleNone>
442 static const auto scaling_type = heffte::scale::none;
445struct HeffteScalingTraits<FFTScaleFull>
447 static const auto scaling_type = heffte::scale::full;
450struct HeffteScalingTraits<FFTScaleSymmetric>
452 static const auto scaling_type = heffte::scale::symmetric;
455#ifdef KOKKOS_ENABLE_SYCL
457template <
class ExecSpace,
class HeffteBackendType>
458auto createHeffteFft3d(
459 ExecSpace exec_space, HeffteBackendType, heffte::box3d<> inbox,
460 heffte::box3d<> outbox, MPI_Comm comm, heffte::plan_options params,
461 typename std::enable_if<
462 std::is_same<HeffteBackendType, heffte::backend::onemkl>::value,
467 sycl::queue& q = exec_space.sycl_queue();
468 return std::make_shared<heffte::fft3d<HeffteBackendType>>( q, inbox, outbox,
473template <
class ExecSpace,
class HeffteBackendType>
474auto createHeffteFft3d(
475 ExecSpace, HeffteBackendType, heffte::box3d<> inbox, heffte::box3d<> outbox,
476 MPI_Comm comm, heffte::plan_options params,
477 typename std::enable_if<
478 std::is_same<HeffteBackendType, heffte::backend::fftw>::value ||
479 std::is_same<HeffteBackendType, heffte::backend::mkl>::value ||
480 std::is_same<HeffteBackendType, heffte::backend::cufft>::value ||
481 std::is_same<HeffteBackendType, heffte::backend::rocfft>::value,
486 return std::make_shared<heffte::fft3d<HeffteBackendType>>( inbox, outbox,
497template <
class EntityType,
class MeshType,
class Scalar,
class MemorySpace,
498 class ExecSpace,
class BackendType>
501 EntityType, MeshType, Scalar, MemorySpace,
502 HeffteFastFourierTransform<EntityType, MeshType, Scalar, MemorySpace,
503 ExecSpace, BackendType>>
515 Cabana::Impl::deprecated( Kokkos::is_device<MemorySpace>() ) );
522 using device_type [[deprecated]] =
typename memory_space::device_type;
549 EntityType, MeshType, Scalar, MemorySpace,
551 MemorySpace, ExecSpace, BackendType>>(
556 heffte::box3d<> inbox = { this->global_low, this->global_high };
557 heffte::box3d<> outbox = { this->global_low, this->global_high };
559 heffte::plan_options heffte_params =
560 heffte::default_options<heffte_backend_type>();
564 case Cabana::Grid::Experimental::FFTCommPattern::p2p:
565 heffte_params.algorithm = heffte::reshape_algorithm::p2p;
567 case Cabana::Grid::Experimental::FFTCommPattern::alltoallv:
568 heffte_params.algorithm = heffte::reshape_algorithm::alltoallv;
570 case Cabana::Grid::Experimental::FFTCommPattern::alltoall:
571 heffte_params.algorithm = heffte::reshape_algorithm::alltoall;
573 case Cabana::Grid::Experimental::FFTCommPattern::p2p_plined:
574 heffte_params.algorithm = heffte::reshape_algorithm::p2p_plined;
577 heffte_params.algorithm = heffte::reshape_algorithm::alltoallv;
581 heffte_params.use_pencils = params.
getPencils();
582 heffte_params.use_reorder = params.
getReorder();
586 _fft = Impl::createHeffteFft3d(
588 layout.
localGrid()->globalGrid().comm(), heffte_params );
589 long long fftsize = std::max( _fft->size_outbox(), _fft->size_inbox() );
594 if ( fftsize < (
int)entity_space.size() )
595 throw std::logic_error(
"Expected FFT allocation size smaller "
596 "than local grid size" );
598 _fft_work = Kokkos::View<Scalar*, memory_space>(
599 Kokkos::ViewAllocateWithoutInitializing(
"fft_work" ),
601 _workspace = Kokkos::View<Scalar* [2], memory_space>(
602 Kokkos::ViewAllocateWithoutInitializing(
"workspace" ),
603 _fft->size_workspace() );
611 template <
class Array_t,
class ScaleType>
614 compute( x, 1, Impl::HeffteScalingTraits<ScaleType>().scaling_type );
622 template <
class Array_t,
class ScaleType>
625 compute( x, -1, Impl::HeffteScalingTraits<ScaleType>().scaling_type );
634 template <
class Array_t>
635 void compute(
const Array_t& x,
const int flag,
const heffte::scale scale )
639 x.layout()->localGrid()->indexSpace(
Own(), EntityType(),
Local() );
642 local_view_space, _fft_work.data() );
646 auto localghost_view = x.view();
648 this->
copyToLocal( heffte_execution_space, own_space, local_view,
654 reinterpret_cast<std::complex<Scalar>*
>( _fft_work.data() ),
655 reinterpret_cast<std::complex<Scalar>*
>( _fft_work.data() ),
656 reinterpret_cast<std::complex<Scalar>*
>( _workspace.data() ),
659 else if ( flag == -1 )
662 reinterpret_cast<std::complex<Scalar>*
>( _fft_work.data() ),
663 reinterpret_cast<std::complex<Scalar>*
>( _fft_work.data() ),
664 reinterpret_cast<std::complex<Scalar>*
>( _workspace.data() ),
669 throw std::logic_error(
670 "Only 1:forward and -1:backward are allowed as compute flag" );
674 this->
copyFromLocal( heffte_execution_space, own_space, local_view,
680 std::shared_ptr<heffte::fft3d<heffte_backend_type>> _fft;
681 Kokkos::View<Scalar*, memory_space> _fft_work;
682 Kokkos::View<Scalar* [2], memory_space> _workspace;
692template <
class Scalar,
class MemorySpace,
class BackendType,
class EntityType,
693 class MeshType,
class ExecSpace>
699 EntityType, MeshType, Scalar, MemorySpace, ExecSpace, BackendType>>(
700 exec_space, layout, params );
707template <
class Scalar,
class MemorySpace,
class EntityType,
class MeshType,
714 Impl::FFTBackendDefault>(
715 exec_space, layout, params );
722template <
class Scalar,
class MemorySpace,
class BackendType,
class EntityType,
723 class MeshType,
class ExecSpace>
727 using heffte_backend_type =
728 typename Impl::HeffteBackendTraits<ExecSpace,
729 BackendType>::backend_type;
732 const heffte::plan_options heffte_params =
733 heffte::default_options<heffte_backend_type>();
736 params.
setPencils( heffte_params.use_pencils );
737 params.
setReorder( heffte_params.use_reorder );
740 EntityType, MeshType, Scalar, MemorySpace, ExecSpace, BackendType>>(
741 exec_space, layout, params );
748template <
class Scalar,
class MemorySpace,
class EntityType,
class MeshType,
754 Scalar, MemorySpace, Impl::FFTBackendDefault, EntityType, MeshType>(
755 exec_space, layout );
761template <
class Scalar,
class MemorySpace,
class BackendType,
class EntityType,
767 using exec_space =
typename MemorySpace::execution_space;
769 EntityType, MeshType>(
770 exec_space{}, layout, params );
776template <
class Scalar,
class MemorySpace,
class EntityType,
class MeshType>
781 using exec_space =
typename MemorySpace::execution_space;
783 Scalar, MemorySpace, Impl::FFTBackendDefault, EntityType, MeshType>(
784 exec_space{}, layout, params );
790template <
class Scalar,
class MemorySpace,
class BackendType,
class EntityType,
795 using exec_space =
typename MemorySpace::execution_space;
797 EntityType, MeshType>( exec_space{},
804template <
class Scalar,
class MemorySpace,
class EntityType,
class MeshType>
808 using exec_space =
typename MemorySpace::execution_space;
810 Scalar, MemorySpace, Impl::FFTBackendDefault, EntityType, MeshType>(
811 exec_space{}, layout );
Kokkos::RangePolicy< ExecutionSpace > createExecutionPolicy(const IndexSpace< 1 > &index_space, const ExecutionSpace &)
Create a multi-dimensional execution policy over an index space.
Definition Cabana_Grid_IndexSpace.hpp:175
Kokkos::View< Scalar *, Params... > createView(const std::string &label, const IndexSpace< 1 > &index_space)
Given an index space create a view over the extent of that index space.
Definition Cabana_Grid_IndexSpace.hpp:235
IndexSpace< N+1 > appendDimension(const IndexSpace< N > &index_space, const long size)
Given an N-dimensional index space append an additional dimension with the given size.
Definition Cabana_Grid_IndexSpace.hpp:442
Entity layout for array data on the local mesh.
Definition Cabana_Grid_Array.hpp:46
int dofsPerEntity() const
Get the number of degrees-of-freedom on each grid entity.
Definition Cabana_Grid_Array.hpp:77
const std::shared_ptr< LocalGrid< MeshType > > localGrid() const
Get the local grid over which this layout is defined.
Definition Cabana_Grid_Array.hpp:71
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
Tag specifying FFTW backend for FFT (host default).
Definition Cabana_Grid_FastFourierTransform.hpp:54
Tag specifying MKL backend for FFT.
Definition Cabana_Grid_FastFourierTransform.hpp:58
Tag for full scaling of FFT.
Definition Cabana_Grid_FastFourierTransform.hpp:41
Tag for no scaling of FFT.
Definition Cabana_Grid_FastFourierTransform.hpp:45
Tag for symmetric scaling of FFT.
Definition Cabana_Grid_FastFourierTransform.hpp:49
Matching Array static type checker.
Definition Cabana_Grid_FastFourierTransform.hpp:75
Local index tag.
Definition Cabana_Grid_Types.hpp:208
Owned decomposition tag.
Definition Cabana_Grid_Types.hpp:190
Definition Cabana_Grid_Array.hpp:322