10#include <Kokkos_Core.hpp>
20 std::fprintf(stderr, "CHECK failed: %s\n at %s:%d\n", #cond, __FILE__, __LINE__); \
29constexpr int N = 12,
G = 2;
30const C3 E{
N + 2 *
G,
N + 2 *
G,
N + 2 *
G};
31const std::size_t
NE = (std::size_t)E.x * E.y * E.z;
38 "test_skr_apply",
C3{
G,
G,
G},
C3{E.x -
G, E.y -
G, E.z -
G},
40 const int xm = (
lx -
G +
N - 1) %
N +
G, xp = (
lx -
G + 1) %
N +
G;
41 const int ym = (
ly -
G +
N - 1) %
N +
G, yp = (
ly -
G + 1) %
N +
G;
42 const int zm = (
lz -
G +
N - 1) %
N +
G, zp = (
lz -
G + 1) %
N +
G;
43 const long sy = E.x, sz = (
long)E.x * E.y;
45 const long nb[6] = {xm +
ly * sy +
lz * sz, xp +
ly * sy +
lz * sz,
lx + ym * sy +
lz * sz,
46 lx + yp * sy +
lz * sz,
lx +
ly * sy + zm * sz,
lx +
ly * sy + zp * sz};
47 const double u = 0.7 + 0.3 * Kokkos::sin(0.5 *
ly);
48 const double up[6] = {u, 0.0, 0.2, 0.0, 0.0, 0.1};
50 for (
int f = 0; f < 6; ++f)
51 s += (d +
up[f]) * (x(i) - x(nb[f]));
58 "test_skr_couple",
C3{
G,
G,
G},
C3{E.x -
G, E.y -
G, E.z -
G},
60 const long i = (
long)
lx + (
long)
ly * E.x + (
long)
lz * (
long)E.x * E.y;
68 "test_skr_jacobi",
C3{
G,
G,
G},
C3{E.x -
G, E.y -
G, E.z -
G},
70 const long i = (
long)
lx + (
long)
ly * E.x + (
long)
lz * (
long)E.x * E.y;
82 f((
long)
lx + (
long)
ly * E.x + (
long)
lz * (
long)E.x * E.y) = 0.0;
87 std::vector<double> xf, xs;
90 bool restarted =
false;
96 auto mk = [](
const char* n) {
return CCField(n,
NE); };
107 auto hb = Kokkos::create_mirror_view(b.f);
108 for (std::size_t k = 0; k <
NE; ++k)
109 hb(k) = std::cos(1.3 * (
double)k) + 0.25;
110 Kokkos::deep_copy(b.f, hb);
112 for (std::size_t k = 0; k <
NE; ++k)
113 hb(k) = std::sin(0.7 * (
double)k);
115 Kokkos::deep_copy(b.s, hb);
120 const double m = 1.0, d = 1.0, ms = 0.3,
dsd = 2.0, w = 0.4;
133 1.0 / (ms + 6.0 *
dsd + 1.0),
two);
142 Kokkos::deep_copy(s,
poison);
166 Kokkos::View<double*, CCMem> ks;
167 Kokkos::View<double*, Kokkos::HostSpace> pk;
194 scalarBiCGStab(
ops, b, x, r,
rh, p, v, t, z,
z2, 200, 1e-12,
false);
196 out.its = res.iterations;
197 out.trueRes = res.trueRes;
198 out.restarted = res.restarted;
199 auto hx = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), x.f);
200 out.xf.assign(
hx.data(),
hx.data() +
NE);
202 auto hs = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), x.s);
203 out.xs.assign(
hs.data(),
hs.data() +
NE);
212 h.xf.size() == d.xf.size() &&
213 std::memcmp(h.xf.data(), d.xf.data(), h.xf.size() *
sizeof(
double)) == 0 &&
214 h.xs.size() == d.xs.size() &&
215 (h.xs.empty() || std::memcmp(h.xs.data(), d.xs.data(), h.xs.size() *
sizeof(
double)) == 0);
216 const bool resSame = std::memcmp(&h.trueRes, &d.trueRes,
sizeof(
double)) == 0;
218 " %-34s %s: iterations host %3d resident %3d, true residual %.3e / %.3e%s, iterate %s\n",
219 tag,
two ?
"two fields" :
"one field ", h.its, d.its, h.trueRes, d.trueRes,
220 h.restarted ?
" (restarted)" :
"",
same ?
"bitwise" :
"DIFFERS");
222 CHECK(h.its == d.its);
224 CHECK(h.restarted == d.restarted);
229 Kokkos::initialize(
argc, argv);
231 const double nan = std::numeric_limits<double>::quiet_NaN();
232 std::printf(
"scalarBiCGStab: the resident pass against the host-scalar pass (%d^3, g = %d)\n",
234 for (
const bool two : {
false,
true}) {
236 compare(
"(rh, r) NaN at iteration 3",
two, 5, 0, nan,
true);
237 compare(
"(rh, v) NaN at iteration 2",
two, 4, 0, nan,
true);
238 compare(
"(rh, r) = 0 at iteration 2",
two, 3, 0, 0.0,
true);
239 compare(
"(t, t) NaN at iteration 2",
two, 0, 2, nan,
true);
240 compare(
"(t, t) = 0 at iteration 1",
two, 0, 1, 0.0,
true);
241 compare(
"omega = 0 ((t, r) = 0) at iteration 3",
two, 0, 3, 0.0,
false);
249 std::printf(
"all checks passed\n");
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
double dotTwoLocal(CCConst af, CCConst bf, CCConst as, CCConst bs, C3 e, int g)
void dot2TwoReduce(CCConst af, CCConst bf, CCConst cf, CCConst as, CCConst bs, CCConst cs, C3 e, int g, R1 &&r1, R2 &&r2)
(sum a b, sum c c) over inner cells, both fields, in one pass, into (r1, r2).
void dot2Reduce(CCConst a, CCConst b, CCConst c, C3 e, int g, R1 &&r1, R2 &&r2)
(sum a b, sum c c) over inner cells in one pass, into (r1, r2).
void dot2Local(CCConst a, CCConst b, CCConst c, C3 e, int g, double &ab, double &cc)
void maxabsReduce(CCConst a, C3 e, int g, Red red)
max over inner cells of |a|, through the Max reducer red (Kokkos::Max over a host double or a device ...
double dotLocal(CCConst a, CCConst b, C3 e, int g)
void dot2TwoLocal(CCConst af, CCConst bf, CCConst cf, CCConst as, CCConst bs, CCConst cs, C3 e, int g, double &ab, double &cc)
void dotTwoReduce(CCConst af, CCConst bf, CCConst as, CCConst bs, C3 e, int g, R &&result)
sum over inner cells of af bf + as bs (the two-field dot).
double maxabsLocal(CCConst a, C3 e, int g)
void dotReduce(CCConst a, CCConst b, C3 e, int g, R &&result)
sum over inner cells of a(i) b(i), into result.
Kokkos::View< double, CCMem > Slot
ScalarKrylovResult scalarBiCGStab(Ops &ops, const ScalarVec &b, const ScalarVec &x, const ScalarVec &r, const ScalarVec &rh, const ScalarVec &p, const ScalarVec &v, const ScalarVec &t, const ScalarVec &z, const ScalarVec &z2, int maxit, double rtol, bool singular)
BiCGStab on A x = b.
void residentKrylov(State &st, ScalarKrylovOps &ops)
Arm ops for the resident pass with the persistent slots of st (ks, pk, allocated once).
void ccFor3(const char *name, C3 lo, C3 hi, F f)
Kokkos::View< double *, CCMem > CCField
Kokkos::View< const double *, CCMem > CCConst
The injected pieces as callables (host-side calls that launch kernels; the overhead of the indirectio...
Outcome of one scalarBiCGStab call.
A Krylov vector (§5.1): the fluid field and, for a conjugate scalar, the solid field (WO-7).
static bool compare(const char *what, const std::vector< Row > &built, const std::vector< Row > &predicted, int rank)
static bool same(double a, double b)