flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
owner_gate.py
Go to the documentation of this file.
1"""Layer 3 rung 1 gate (flow side): every CUT cell's owner is the brute-force nearest sphere.
2
3A cut cell is a fluid cell (sdf>0) with at least one solid face-neighbour -- the cells whose
4stencils the IBM overlay modifies, and therefore the only cells whose ownership a moving wall
5velocity (R2) or a CFD-DEM force integration (L4-R2) ever reads.
6
7Coordinates: the solver samples the scene at INTEGER cell coordinates (cell (i,j,k) at (i,j,k)),
8so the reference lattice here is arange(N) -- not the i+0.5 convention scene_check.py uses for
9its own sampled-array reference.
10"""
11import numpy as np
12from peclet import flow as sdflow
13
14N = 32
15R = 0.18 * N
16CEN = [(0.25*N, 0.25*N, 0.25*N), (0.75*N, 0.75*N, 0.25*N),
17 (0.75*N, 0.25*N, 0.75*N), (0.25*N, 0.75*N, 0.75*N)]
18
19KN_R, KI_I, KI_R = 16, 2, 17
20node_ints = np.array([1, -1, -1], dtype=np.int32) # kSphere
21node_reals = np.zeros(KN_R); node_reals[0] = R
22node_reals[14] = 1.0; node_reals[15] = 1.0 # quat w, scale
23inst_ints = np.zeros((len(CEN), KI_I), dtype=np.int32)
24inst_reals = np.zeros((len(CEN), KI_R))
25for m, c in enumerate(CEN):
26 inst_ints[m] = (0, -1)
27 inst_reals[m, 0:3] = c
28 inst_reals[m, 6] = 1.0 # quat w
29 inst_reals[m, 7] = 1.0 # scale
30
31s = sdflow.Solver(N, N, N)
32s.set_rho(1.0); s.set_mu(1.0); s.set_dt(50.0)
33s.set_scene(node_ints, node_reals, inst_ints.ravel(), inst_reals.ravel(), periodic=True)
34s.set_solid_from_scene(True)
35owner = np.asarray(s.get_cut_owner())
36
37g = np.arange(N).astype(float)
38X, Y, Z = np.meshgrid(g, g, g, indexing="ij")
39d = np.empty((len(CEN), N, N, N))
40for k, (cx, cy, cz) in enumerate(CEN):
41 dx = np.abs(X-cx); dx = np.minimum(dx, N-dx)
42 dy = np.abs(Y-cy); dy = np.minimum(dy, N-dy)
43 dz = np.abs(Z-cz); dz = np.minimum(dz, N-dz)
44 d[k] = np.sqrt(dx*dx+dy*dy+dz*dz) - R
45ref_owner = np.argmin(d, axis=0) # numpy argmin: lowest index wins ties, same rule
46ref_sdf = d.min(axis=0)
47
48fluid = ref_sdf > 0.0
49solid = ~fluid
50nbr_solid = np.zeros_like(solid)
51for ax in (0, 1, 2):
52 for sh in (+1, -1):
53 nbr_solid |= np.roll(solid, sh, axis=ax)
54cut = fluid & nbr_solid
55
56srt = np.sort(d, axis=0)
57tied = int(((srt[1] - srt[0]) == 0.0).sum())
58bad_cut = int((owner[cut] != ref_owner[cut]).sum())
59bad_all = int((owner != ref_owner).sum())
60print("cut cells %d of %d" % (int(cut.sum()), owner.size))
61print("exact ties on lattice %d" % tied)
62print("owner mismatches cut=%d all-cells=%d" % (bad_cut, bad_all))
63print("GATE %s" % ("PASS" if bad_cut == 0 and bad_all == 0 else "FAIL"))