flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_mg.cpp
Go to the documentation of this file.
1// Convergence test of the Kokkos geometric multigrid V-cycle (peclet::flow::MgPoisson) for the
2// periodic Poisson Lap(phi)=d. Random mean-zero rhs; solve with increasing V-cycle counts and check
3// the residual drops by ~an order of magnitude per cycle (vs ~0.99/sweep for plain RB-GS). Runs on
4// any Kokkos backend.
5#include <cmath>
6#include <cstdio>
7#include <Kokkos_Core.hpp>
8#include <random>
9#include <vector>
10
11#include "mac_mg.hpp"
12
13using namespace peclet::flow;
14
15int main(int argc, char** argv) {
16 Kokkos::initialize(argc, argv);
17 int status = 0;
18 {
19 const int N = 64, g = 1;
20 I3 e{N + 2 * g, N + 2 * g, N + 2 * g};
21 const std::size_t n = (std::size_t)e.x * e.y * e.z;
22
23 // random mean-zero d on inner cells (periodic solvability)
24 std::mt19937 rng(3);
25 std::uniform_real_distribution<double> uf(-1.0, 1.0);
26 std::vector<double> hd(n, 0.0);
27 double sum = 0;
28 long cnt = 0;
29 for (int z = g; z < e.z - g; ++z)
30 for (int y = g; y < e.y - g; ++y)
31 for (int x = g; x < e.x - g; ++x) {
32 long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
33 hd[i] = uf(rng);
34 sum += hd[i];
35 ++cnt;
36 }
37 double mean = sum / cnt;
38 for (int z = g; z < e.z - g; ++z)
39 for (int y = g; y < e.y - g; ++y)
40 for (int x = g; x < e.x - g; ++x) {
41 long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
42 hd[i] -= mean;
43 }
44
45 SField d("d", n);
46 {
47 auto m = Kokkos::create_mirror_view(d);
48 for (std::size_t i = 0; i < n; ++i)
49 m(i) = hd[i];
50 Kokkos::deep_copy(d, m);
51 }
52
53 MgPoisson mg(N);
54 std::printf("[mg] N=%d levels=%d\n", N, mg.numLevels());
55
56 double prev = 0;
57 for (int nv = 1; nv <= 6; ++nv) {
58 SField phi("phi", n); // start from zero each time
59 mg.solve(phi, SConst(d), nv);
60 double res = mg.finestResidualMax();
61 double factor = (nv > 1) ? res / prev : 0.0;
62 std::printf("[mg] %d V-cycle(s): max|resid|=%.3e (factor vs prev %.3f)\n", nv, res, factor);
63 prev = res;
64 }
65
66 // require strong convergence: a few V-cycles drive the residual far below the rhs scale.
67 SField phi("phi", n);
68 mg.solve(phi, SConst(d), 8);
69 double res8 = mg.finestResidualMax();
70 if (!(res8 < 1e-6)) {
71 std::fprintf(stderr, "FAIL: 8 V-cycles did not converge (resid %.3e)\n", res8);
72 status = 1;
73 } else
74 std::printf("[mg] PASS: 8 V-cycles -> max|resid|=%.3e (exec %s)\n", res8, SExec::name());
75 }
76 Kokkos::finalize();
77 return status;
78}
double finestResidualMax()
Definition mac_mg.hpp:85
int numLevels() const
Definition mac_mg.hpp:65
void solve(SField phi, SConst d, int nVcycles, int nu1=2, int nu2=2)
Definition mac_mg.hpp:68
flow — portable (Kokkos) geometric multigrid V-cycle for the periodic pressure Poisson.
Kokkos::View< const double *, SMem > SConst
Kokkos::View< double *, SMem > SField
static constexpr int N
int main(int argc, char **argv)
Definition test_mg.cpp:15