flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
property_closures.hpp
Go to the documentation of this file.
1
15#ifndef PECLET_FLOW_PROPERTY_CLOSURES_HPP
16#define PECLET_FLOW_PROPERTY_CLOSURES_HPP
17
18#include <array>
19#include <Kokkos_Core.hpp>
20
21#include "mac_cutcell.hpp"
22
23namespace peclet::flow {
24
25enum class ClosureKind {
26 LinearMix, // out = p0 + p1*in0 + p2*in1
27 BoussinesqForce, // out = p0*p1*p2*(in0 - p3) [rho0, g, beta, T0] -> buoyancy body force
28 ArrheniusMu, // out = p0*exp(p1*(1/in0 - 1/p2)) [mu_ref, B, Tref]
29 Table1D // out = piecewise-linear interp of (tabX, tabY) at in0
30};
31
32// A registered closure. `out`/`in0`/`in1` are resolved from the field registry at registration; a
33// later redistribution that reallocates fields must re-resolve them.
34struct Closure {
38 std::array<double, 4> p{{0, 0, 0, 0}};
39 CCField tabX, tabY; // Table1D nodes (ascending tabX)
40 int nTab = 0;
41};
42
43// Apply one closure over the inner cells (ghosts untouched — refilled by the field's own exchange).
44inline void applyClosure(const Closure& cl, C3 e, int g) {
45 CCExec space;
46 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
47 const ClosureKind kind = cl.kind;
48 CCField out = cl.out;
49 CCConst in0 = cl.in0, in1 = cl.in1;
50 const double p0 = cl.p[0], p1 = cl.p[1], p2 = cl.p[2], p3 = cl.p[3];
51 const bool haveIn1 = (in1.data() != nullptr) && (in1.extent(0) == out.extent(0));
52 CCConst tx = cl.tabX, ty = cl.tabY;
53 const int nTab = cl.nTab;
54 Kokkos::parallel_for(
55 "peclet::flow::apply_closure", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
56 KOKKOS_LAMBDA(int x, int y, int z) {
57 const long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
58 double v;
59 switch (kind) {
61 v = p0 + p1 * in0(i) + (haveIn1 ? p2 * in1(i) : 0.0);
62 break;
64 v = p0 * p1 * p2 * (in0(i) - p3);
65 break;
67 v = p0 * Kokkos::exp(p1 * (1.0 / in0(i) - 1.0 / p2));
68 break;
69 default: { // Table1D: clamped piecewise-linear interpolation
70 const double s = in0(i);
71 if (nTab <= 0) {
72 v = 0.0;
73 } else if (s <= tx(0)) {
74 v = ty(0);
75 } else if (s >= tx(nTab - 1)) {
76 v = ty(nTab - 1);
77 } else {
78 int lo = 0, hi = nTab - 1; // binary search for the bracketing node
79 while (hi - lo > 1) {
80 const int mid = (lo + hi) / 2;
81 if (tx(mid) <= s)
82 lo = mid;
83 else
84 hi = mid;
85 }
86 const double t = (s - tx(lo)) / (tx(hi) - tx(lo));
87 v = ty(lo) + t * (ty(hi) - ty(lo));
88 }
89 }
90 }
91 out(i) = v;
92 });
93}
94
95} // namespace peclet::flow
96
97#endif // PECLET_FLOW_PROPERTY_CLOSURES_HPP
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
Kokkos::View< double *, CCMem > CCField
Kokkos::DefaultExecutionSpace CCExec
void applyClosure(const Closure &cl, C3 e, int g)
Kokkos::View< const double *, CCMem > CCConst
std::array< double, 4 > p