@@ -7,29 +7,53 @@ namespace pfc {
77namespace fft {
88namespace layout {
99
10- const FFTLayout create (const Decomposition &decomposition, int r2c_direction,
11- int num_domains) {
12- if (num_domains <= 0 ) {
13- throw std::logic_error (" Cannot construct domain decomposition: !(nprocs > 0)" );
10+ #include < array>
11+ #include < iostream>
12+ #include < sstream>
13+
14+ // Helper function to print std::array
15+ template <typename T, std::size_t N>
16+ std::ostream &operator <<(std::ostream &os, const std::array<T, N> &arr) {
17+ os << " {" ;
18+ for (std::size_t i = 0 ; i < N; ++i) {
19+ os << arr[i];
20+ if (i < N - 1 ) {
21+ os << " , " ;
22+ }
1423 }
15- auto world = get_world (decomposition);
16- auto [N1r, N2r, N3r] = get_size (world); // real size
17- auto [N1c, N2c, N3c] = get_size (world); // complex size
24+ os << " }" ;
25+ return os;
26+ }
27+
28+ using heffte::split_world;
29+
30+ const auto get_real_indices (const Decomposition &decomposition) {
31+ auto world = get_global_world (decomposition);
32+ auto [N1, N2, N3] = get_size (world);
33+ return heffte::box3d<int >({0 , 0 , 0 }, {N1 - 1 , N2 - 1 , N3 - 1 });
34+ }
35+
36+ const auto get_complex_indices (const Decomposition &decomposition,
37+ int r2c_direction) {
38+ auto [N1, N2, N3] = get_size (get_global_world (decomposition));
1839 if (r2c_direction == 0 ) {
19- N1c = N1c / 2 + 1 ;
40+ return heffte::box3d< int >({ 0 , 0 , 0 }, {N1 / 2 , N2 - 1 , N3 - 1 }) ;
2041 } else if (r2c_direction == 1 ) {
21- N2c = N2c / 2 + 1 ;
42+ return heffte::box3d< int >({ 0 , 0 , 0 }, {N1 - 1 , N2 / 2 , N3 - 1 }) ;
2243 } else if (r2c_direction == 2 ) {
23- N3c = N3c / 2 + 1 ;
44+ return heffte::box3d< int >({ 0 , 0 , 0 }, {N1 - 1 , N2 - 1 , N3 / 2 }) ;
2445 } else {
2546 throw std::logic_error (" Invalid r2c_direction: " +
2647 std::to_string (r2c_direction));
2748 }
28- box3di real_indices ({0 , 0 , 0 }, {N1r - 1 , N2r - 1 , N3r - 1 });
29- box3di complex_indices ({0 , 0 , 0 }, {N1c - 1 , N2c - 1 , N3c - 1 });
30- Int3 grid = heffte::proc_setup_min_surface (real_indices, num_domains);
31- std::vector<box3di> real_boxes = heffte::split_world (real_indices, grid);
32- std::vector<box3di> complex_boxes = heffte::split_world (complex_indices, grid);
49+ }
50+
51+ const FFTLayout create (const Decomposition &decomposition, int r2c_direction) {
52+ auto real_indices = get_real_indices (decomposition);
53+ auto complex_indices = get_complex_indices (decomposition, r2c_direction);
54+ auto grid = get_grid (decomposition);
55+ auto real_boxes = split_world (real_indices, grid);
56+ auto complex_boxes = split_world (complex_indices, grid);
3357 return FFTLayout{decomposition, r2c_direction, real_boxes, complex_boxes};
3458}
3559
@@ -49,25 +73,42 @@ int get_mpi_size(MPI_Comm comm) {
4973 return size;
5074}
5175
52- FFT create (const Decomposition &decomposition, MPI_Comm comm,
53- heffte::plan_options options) {
54- int rank = get_mpi_rank (comm);
55- int mpi_num_ranks = get_mpi_size (comm);
56- if (mpi_num_ranks <= 0 ) {
57- throw std::logic_error (" Cannot construct domain decomposition: !(nprocs > 0)" );
58- }
59- auto r2c_dir = 0 ;
60- auto fft_layout = fft::layout::create (decomposition, r2c_dir, mpi_num_ranks);
61- auto inbox = get_real_box (fft_layout, rank);
62- auto outbox = get_complex_box (fft_layout, rank);
63- using fft_r2c = heffte::fft3d_r2c<heffte::backend::fftw>;
76+ using heffte::plan_options;
77+ using layout::FFTLayout;
78+ using fft_r2c = heffte::fft3d_r2c<heffte::backend::fftw>;
79+
80+ FFT create (const FFTLayout &fft_layout, int rank_id, plan_options options) {
81+ auto inbox = get_real_box (fft_layout, rank_id);
82+ auto outbox = get_complex_box (fft_layout, rank_id);
83+ auto r2c_dir = get_r2c_direction (fft_layout);
84+ auto comm = get_comm ();
6485 return FFT (fft_r2c (inbox, outbox, r2c_dir, comm, options));
6586}
6687
88+ FFT create (const Decomposition &decomposition, int rank_id) {
89+ auto options = heffte::default_options<heffte::backend::fftw>();
90+ auto r2c_dir = 0 ;
91+ auto fft_layout = layout::create (decomposition, r2c_dir);
92+ return create (fft_layout, rank_id, options);
93+ }
94+
6795FFT create (const Decomposition &decomposition) {
6896 auto comm = get_comm ();
69- auto options = heffte::default_options<heffte::backend::fftw>();
70- return create (decomposition, comm, options);
97+ auto mpi_comm_size = get_mpi_size (comm);
98+ auto rank_id = get_mpi_rank (comm);
99+ auto decomposition_size = get_num_domains (decomposition);
100+ if (mpi_comm_size != decomposition_size) {
101+ throw std::logic_error (
102+ " Mismatch between MPI communicator size and domain decomposition size: " +
103+ std::to_string (mpi_comm_size) + " != " + std::to_string (decomposition_size) +
104+ " . This indicates that the number of MPI ranks does not match the number of "
105+ " domains in the decomposition. To resolve this issue, you can manually "
106+ " specify the rank by calling fft::create(decomposition, rank_id) instead." );
107+ }
108+ // if mpi communicator size matches decomposition size, we can safely assume
109+ // that the intention is to decompose the whole communicator into the
110+ // decomposition
111+ return create (decomposition, rank_id);
71112}
72113
73114} // namespace fft
0 commit comments