|
52 | 52 | #include <bout/utils.hxx> |
53 | 53 |
|
54 | 54 | #include <fmt/format.h> |
| 55 | +#include <fmt/ranges.h> |
55 | 56 |
|
56 | 57 | #include <algorithm> |
57 | 58 | #include <cmath> |
@@ -106,6 +107,9 @@ BoutMesh::~BoutMesh() { |
106 | 107 | if (comm_outer != MPI_COMM_NULL) { |
107 | 108 | MPI_Comm_free(&comm_outer); |
108 | 109 | } |
| 110 | + if (comm_xz != MPI_COMM_NULL) { |
| 111 | + MPI_Comm_free(&comm_xz); |
| 112 | + } |
109 | 113 | } |
110 | 114 |
|
111 | 115 | BoutMesh::YDecompositionIndices |
@@ -665,10 +669,43 @@ int BoutMesh::load() { |
665 | 669 | return 0; |
666 | 670 | } |
667 | 671 |
|
| 672 | +namespace { |
| 673 | +auto make_XZ_communicator(const BoutMesh& mesh, MPI_Group group_world) -> MPI_Comm { |
| 674 | + std::vector<int> ranks; |
| 675 | + |
| 676 | + const int yp = mesh.getYProcIndex(); |
| 677 | + |
| 678 | + // All processors with the same Y index |
| 679 | + for (int xp = 0; xp < mesh.getNXPE(); ++xp) { |
| 680 | + for (int zp = 0; zp < mesh.getNZPE(); ++zp) { |
| 681 | + ranks.push_back(mesh.getProcIndex(xp, yp, zp)); |
| 682 | + } |
| 683 | + } |
| 684 | + MPI_Group group{}; |
| 685 | + if (MPI_Group_incl(group_world, static_cast<int>(ranks.size()), ranks.data(), &group) |
| 686 | + != MPI_SUCCESS) { |
| 687 | + throw BoutException("Could not create X-Z communication group for ranks {}", |
| 688 | + fmt::join(ranks, ", ")); |
| 689 | + } |
| 690 | + |
| 691 | + MPI_Comm comm_xz{}; |
| 692 | + if (MPI_Comm_create(BoutComm::get(), group, &comm_xz) != MPI_SUCCESS) { |
| 693 | + throw BoutException("Could not create X-Z communicator for yp={} (xind={}, yind={}, " |
| 694 | + "zind={}) ranks={}", |
| 695 | + yp, mesh.getXProcIndex(), mesh.getYProcIndex(), |
| 696 | + mesh.getZProcIndex(), fmt::join(ranks, ", ")); |
| 697 | + } |
| 698 | + |
| 699 | + return comm_xz; |
| 700 | +} |
| 701 | +} // namespace |
| 702 | + |
668 | 703 | void BoutMesh::createCommunicators() { |
669 | 704 | MPI_Group group_world{}; |
670 | 705 | MPI_Comm_group(BoutComm::get(), &group_world); // Get the entire group |
671 | 706 |
|
| 707 | + comm_xz = make_XZ_communicator(*this, group_world); |
| 708 | + |
672 | 709 | ////////////////////////////////////////////////////// |
673 | 710 | /// Communicator in X |
674 | 711 |
|
@@ -1038,7 +1075,9 @@ void BoutMesh::createXBoundaries() { |
1038 | 1075 | } |
1039 | 1076 | } |
1040 | 1077 |
|
1041 | | -int BoutMesh::getProcIndex(int X, int Y, int Z) const { return Y * NXPE + X; } |
| 1078 | +int BoutMesh::getProcIndex(int X, int Y, int Z) const { |
| 1079 | + return (((Z * NYPE) + Y) * NXPE) + X; |
| 1080 | +} |
1042 | 1081 |
|
1043 | 1082 | void BoutMesh::createYBoundaries() { |
1044 | 1083 | if (MYG <= 0) { |
@@ -2218,9 +2257,9 @@ void BoutMesh::topology() { |
2218 | 2257 | } |
2219 | 2258 |
|
2220 | 2259 | for (int i = 0; i < limiter_count; ++i) { |
2221 | | - int const yind = limiter_yinds[i]; |
2222 | | - int const xstart = limiter_xstarts[i]; |
2223 | | - int const xend = limiter_xends[i]; |
| 2260 | + const int yind = limiter_yinds[i]; |
| 2261 | + const int xstart = limiter_xstarts[i]; |
| 2262 | + const int xend = limiter_xends[i]; |
2224 | 2263 | output_info.write("Adding a limiter between y={} and {}. X indices {} to {}\n", |
2225 | 2264 | yind, yind + 1, xstart, xend); |
2226 | 2265 | add_target(yind, xstart, xend); |
|
0 commit comments