flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_velocitymg_mpi.cpp
Go to the documentation of this file.
1// cfd-gpu — the PRODUCTION VelocityMG (staircase velocity multigrid), multi-rank.
2//
3// Folds the distributed halo into the real velocity-MG (gated behind PECLET_FLOW_MPI). VelocityMG
4// has NO global reductions (the backward-Euler velocity operator is non-singular -> no mean
5// removal, and the V-cycle is a fixed iteration, not a Krylov method), so the fold is purely
6// fill()->per-level halo exchange + the block- origin red-black parity -- and the distributed
7// V-cycle is therefore BIT-tight to the single-rank one (no Allreduce reordering at all). Solves an
8// all-fluid periodic backward-Euler diffusion (fine stencil = idiag*I - beta*Lap; staircase coarse
9// op with theta=1, no pin, full clean-fluid mask) distributed (initMpi) vs single-rank (init() on
10// the full grid). Build with -DCFD_MPI.
11#include <mpi.h>
12
13#include <cmath>
14#include <cstdio>
15#include <Kokkos_Core.hpp>
16
17#include "mac_velocity_mg.hpp"
18#include "peclet/core/common/types.hpp"
19#include "peclet/core/decomp/block_decomposer.hpp"
20#include "peclet/core/halo/grid_halo_topology.hpp"
21
22using peclet::core::IVec;
29
30static constexpr int G = 2, NLEV = 4, NVCYC = 6;
31static constexpr double IDIAG = 1.0, BETA = 0.2;
32static double source(int gx, int gy, int gz, IVec<3> gs) {
33 return std::sin(2.0 * M_PI * gx / gs[0]) +
34 std::cos(4.0 * M_PI * gy / gs[1]) * std::sin(2.0 * M_PI * gz / gs[2]);
35}
36
37static void fillSource(CCField b, C3 ext, C3 og, IVec<3> gs) {
38 auto hb = Kokkos::create_mirror_view(b);
39 for (std::size_t c = 0; c < b.extent(0); ++c)
40 hb(c) = 0.0;
41 for (int z = G; z < ext.z - G; ++z)
42 for (int y = G; y < ext.y - G; ++y)
43 for (int x = G; x < ext.x - G; ++x)
44 hb((long)x + (long)y * ext.x + (long)z * (long)ext.x * ext.y) =
45 source(x - G + og.x, y - G + og.y, z - G + og.z, gs);
46 Kokkos::deep_copy(b, hb);
47}
48
49int main(int argc, char** argv) {
50 MPI_Init(&argc, &argv);
51 Kokkos::initialize(argc, argv);
52 int fail = 0, size = 1, rank = 0;
53 {
54 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
55 MPI_Comm_size(MPI_COMM_WORLD, &size);
56 IVec<3> gs{32, 32, 32};
57
58 auto setupAndSolve = [&](VelocityMG& vmg, C3 ext, C3 og) {
59 const std::size_t n = (std::size_t)ext.x * ext.y * ext.z;
60 // fine stencil = backward-Euler diffusion (idiag+6beta diagonal, -beta off-diagonals)
61 FPV AC("AC", n), AW("AW", n), AE("AE", n), AS("AS", n), AN("AN", n), AB("AB", n), AT("AT", n);
62 Kokkos::deep_copy(AC, (float)(IDIAG + 6.0 * BETA));
63 for (FPV* p : {&AW, &AE, &AS, &AN, &AB, &AT})
64 Kokkos::deep_copy(*p, (float)(-BETA));
65 vmg.setFineStencil(FPC(AC), FPC(AW), FPC(AE), FPC(AS), FPC(AN), FPC(AB), FPC(AT));
66 // all-fluid geometry: theta=1, no solid pin, full clean-fluid mask
67 CCField th("th", n), solid("solid", n), clean("clean", n);
68 Kokkos::deep_copy(th, 1.0);
69 Kokkos::deep_copy(solid, 0.0);
70 Kokkos::deep_copy(clean, 1.0);
71 vmg.setStaircase(CCConst(th), CCConst(solid), CCConst(clean), BETA, IDIAG, 0.5);
72 CCField b("b", n), x("x", n);
73 fillSource(b, ext, og, gs);
74 Kokkos::deep_copy(x, 0.0);
75 vmg.solve(CCConst(b), x, NVCYC, 2, 2, 8);
76 auto hx = Kokkos::create_mirror_view(x);
77 Kokkos::deep_copy(hx, x);
78 return hx;
79 };
80
81 VelocityMG vmg;
82 vmg.initMpi(gs[0], gs[1], gs[2], NLEV, MPI_COMM_WORLD);
83 VelocityMG::Level& l0 = vmg.level(0);
84 auto hx = setupAndSolve(vmg, l0.ext, l0.og);
85
86 VelocityMG ref;
87 ref.init(gs[0], gs[1], gs[2], NLEV);
88 const C3 re{(int)gs[0] + 2 * G, (int)gs[1] + 2 * G, (int)gs[2] + 2 * G}, ro{0, 0, 0};
89 auto hr = setupAndSolve(ref, re, ro);
90
91 double maxdiff = 0.0;
92 for (int z = G; z < l0.ext.z - G; ++z)
93 for (int y = G; y < l0.ext.y - G; ++y)
94 for (int x = G; x < l0.ext.x - G; ++x) {
95 const int gx = x - G + l0.og.x, gy = y - G + l0.og.y, gz = z - G + l0.og.z;
96 const double a = hx((long)x + (long)y * l0.ext.x + (long)z * (long)l0.ext.x * l0.ext.y);
97 const double rr =
98 hr((long)(gx + G) + (long)(gy + G) * re.x + (long)(gz + G) * (long)re.x * re.y);
99 const double d = std::fabs(a - rr);
100 if (d > maxdiff)
101 maxdiff = d;
102 }
103 if (maxdiff > 1e-11) {
104 ++fail;
105 std::fprintf(stderr, "[rank %d] max|distributed - single-rank VelocityMG| = %.3e\n", rank,
106 maxdiff);
107 } else if (rank == 0)
108 std::printf(" max|distributed - single-rank| = %.3e (np=%d)\n", maxdiff, size);
109 }
110 int totalFail = 0;
111 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
112 if (rank == 0) {
113 if (totalFail == 0)
114 std::printf("OK (np=%d): production VelocityMG V-cycle distributed == single-rank\n", size);
115 else
116 std::fprintf(stderr, "FAILED (np=%d): %d ranks differ\n", size, totalFail);
117 }
118 Kokkos::finalize();
119 MPI_Finalize();
120 return totalFail == 0 ? 0 : 1;
121}
void setFineStencil(FPC AC, FPC AW, FPC AE, FPC AS, FPC AN, FPC AB, FPC AT)
int solve(CCConst b, CCField x, int nvc, int pre, int post, int bottom, double tol=0.0, Comm comm=nullComm(), double resTol=0.0)
void setStaircase(CCConst theta0, CCConst solid0, CCConst resmask0, double nu_dt, double idiag, double thresh)
int main()
Definition dbg_scene.cpp:13
flow — portable (Kokkos) velocity (momentum) multigrid for the IBM diffusion solve: the STAIRCASE coa...
Kokkos::View< const MReal *, CCMem > FPC
Kokkos::View< double *, CCMem > CCField
Kokkos::View< MReal *, CCMem > FPV
Kokkos::View< const double *, CCMem > CCConst
static HostVec setupAndSolve(CutcellMG &mg, C3 ext, C3 og, int nx, int ny, int nz, bool collective, int *iters)
static constexpr double AC
static constexpr int NVCYC
static constexpr double IDIAG
static void fillSource(CCField b, C3 ext, C3 og, IVec< 3 > gs)
static double source(int gx, int gy, int gz, IVec< 3 > gs)
static constexpr int G
static constexpr int NLEV
static constexpr double BETA