flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_telescope_varrho_mpi.cpp
Go to the documentation of this file.
1// Telescoping across a variable-density OUTFLOW (the WO-R2 outflow-coefficient path): the
2// hierarchy with a telescope FORCED at level 1 must reproduce the in-place hierarchy on the same
3// problem -- a sharp density jump advected out of the domain through a +z outflow with a -z inflow.
4// The coarse boundary coefficient across the telescope point is coarsened from the merged stage
5// (teleGatherPlane carried the high-side outflow plane), so the two hierarchies build the same
6// coarse operators and the solves agree to the pressure driver's tolerance.
7#include <mpi.h>
8
9#include <cmath>
10#include <cstdio>
11#include <Kokkos_Core.hpp>
12#include <vector>
13
14#include "flow_ibm.hpp"
15#include "peclet/core/common/types.hpp"
16#include "peclet/core/decomp/block_decomposer.hpp"
17
19
20static constexpr int N = 32, STEPS = 4;
21static constexpr double RHO0 = 1.0, RATIO = 100.0, MU = 0.1, DT = 0.5, WIN = 0.05;
22
23static double rhoAt(int gz) {
24 return (gz < N / 2) ? RATIO * RHO0 : RHO0;
25}
26
27static void run(IbmSolver& s, int ox, int oy, int oz, int lnx, int lny, int lnz, int forceLevel,
28 bool telescope, std::vector<double>& u, std::vector<double>& p, int& teleCount) {
29 s.setRho(RHO0);
30 s.setMu(MU);
31 s.setDt(DT);
32 s.setAdvection(false);
33 for (int f = 0; f < 4; ++f)
34 s.setDomainBc(f, 1, 0, 0, 0); // x/y walls
35 s.setDomainBc(4, 2, 0, 0, WIN); // -z inflow
36 s.setDomainBc(5, 3, 0, 0, 0); // +z outflow
37 s.setPressureLevels(4);
38 s.setPressurePcg(true, 400, 1e-11);
39 s.setPressureTelescope(telescope);
40 if (telescope)
41 s.setPressureTelescopeForceLevel(forceLevel);
42 s.setPressureGeometry(std::vector<double>((std::size_t)lnx * lny * lnz, 10.0));
43 s.setDensityMode(true);
44 std::vector<double> rho((std::size_t)lnx * lny * lnz);
45 for (int z = 0; z < lnz; ++z)
46 for (int y = 0; y < lny; ++y)
47 for (int x = 0; x < lnx; ++x)
48 rho[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] = rhoAt(z + oz);
49 s.setField("rho", rho);
50 s.exchangeField("rho");
51 for (int it = 0; it < STEPS; ++it)
52 s.step();
53 u = s.getVelocity(2);
54 p = s.getPressure();
55 teleCount = s.pressureTelescopeCount();
56}
57
58int main(int argc, char** argv) {
59 MPI_Init(&argc, &argv);
60 Kokkos::initialize(argc, argv);
61 int fail = 0, size = 1, rank = 0;
62 {
63 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
64 MPI_Comm_size(MPI_COMM_WORLD, &size);
65 peclet::core::decomp::BlockDecomposer<3> dec =
66 peclet::flow::CutcellMG::decomposition(static_cast<std::size_t>(size), N, N, N);
67 auto blk = dec.block(rank);
68 const int ox = (int)blk.origin[0], oy = (int)blk.origin[1], oz = (int)blk.origin[2];
69 const int lnx = (int)blk.size[0], lny = (int)blk.size[1], lnz = (int)blk.size[2];
70 std::vector<double> uT, pT, uI, pI;
71 int cT = 0, cI = 0;
72 {
73 IbmSolver s(lnx, lny, lnz);
74 s.initMpi(N, N, N, MPI_COMM_WORLD);
75 run(s, ox, oy, oz, lnx, lny, lnz, 1, true, uT, pT, cT);
76 }
77 {
78 IbmSolver s(lnx, lny, lnz);
79 s.initMpi(N, N, N, MPI_COMM_WORLD);
80 run(s, ox, oy, oz, lnx, lny, lnz, -1, false, uI, pI, cI);
81 }
82 double du = 0, dp = 0, um = 0, pm = 0;
83 for (std::size_t i = 0; i < uT.size(); ++i) {
84 du = std::max(du, std::fabs(uT[i] - uI[i]));
85 um = std::max(um, std::fabs(uI[i]));
86 }
87 for (std::size_t i = 0; i < pT.size(); ++i) {
88 dp = std::max(dp, std::fabs(pT[i] - pI[i]));
89 pm = std::max(pm, std::fabs(pI[i]));
90 }
91 double l[4] = {du, dp, um, pm}, g[4];
92 MPI_Allreduce(l, g, 4, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
93 int cTg = 0;
94 MPI_Allreduce(&cT, &cTg, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
95 const double relU = g[0] / (g[2] + 1e-300), relP = g[1] / (g[3] + 1e-300);
96 const double tol =
97 1e-8; // the PCG tolerance's footprint on two different-but-equivalent hierarchies
98 const bool teleOk = (size == 1) || cTg >= 1; // np=1 has one block: nothing to merge
99 if (rank == 0)
100 std::printf(
101 " telescoped(force L1) vs in-place: rel du %.2e rel dp %.2e (tol %.0e) "
102 "telescopes %d |u| %.3e |p| %.3e (np=%d)\n",
103 relU, relP, tol, cTg, g[2], g[3], size);
104 if (!(relU <= tol) || !(relP <= tol) || !teleOk)
105 fail = 1;
106 }
107 int totalFail = 0;
108 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
109 if (rank == 0) {
110 if (totalFail == 0)
111 std::printf("OK (np=%d): variable-density outflow across a telescope point == in-place\n",
112 size);
113 else
114 std::fprintf(stderr, "FAILED (np=%d)\n", size);
115 }
116 Kokkos::finalize();
117 MPI_Finalize();
118 return totalFail == 0 ? 0 : 1;
119}
int main()
Definition dbg_scene.cpp:13
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
Solver< Staggered > IbmSolver
static constexpr double RHO0
static constexpr double MU
static constexpr int STEPS
static constexpr int N
static constexpr double DT
static constexpr double RATIO
static void run(IbmSolver &s, int ox, int oy, int oz, int lnx, int lny, int lnz, int forceLevel, bool telescope, std::vector< double > &u, std::vector< double > &p, int &teleCount)
static double rhoAt(int gz)
static constexpr double WIN