Files
CelerisLab/src/CelerisLab/lbm/kernels/step/esopull_sync.cu
T

79 lines
2.6 KiB
Plaintext

// CelerisLab -- step/esopull_sync.cu
// Compact-list EsoPull decode/encode for runtime body topology sync.
//
// Decodes a subset of cells from EsoPull backing layout to physical DDF,
// or encodes physical DDF back to EsoPull backing layout.
// Each thread handles one cell from a compact index list.
//
// Included by kernel_v2.cu. No standalone compilation.
// ============================================================================
#ifndef CELERIS_STEP_ESOPULL_SYNC_CU
#define CELERIS_STEP_ESOPULL_SYNC_CU
// ---------------------------------------------------------------------------
// DecodeCellsToPhysical: backing layout -> physical DDF (compact list)
//
// Uses ``t`` as the step count for EsoPull semantic parity decoding.
// ---------------------------------------------------------------------------
__global__ void DecodeCellsToPhysical(
const fpxx* fi,
float* fi_phys,
const unsigned int* cell_idx,
unsigned int n_cells,
unsigned long t)
{
unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
if (tid >= n_cells) return;
unsigned long k = (unsigned long)cell_idx[tid];
unsigned int x, y; coordinates(k, x, y);
unsigned long j[NQ]; compute_neighbors(x, y, j);
float f[NQ];
load_physical_node_esopull(k, fi, j, t, f);
// DDF-shifting: backing layout stores f-w, unshift to physical for host patch
#if USE_DDF_SHIFTING
#pragma unroll
for (int i = 0; i < NQ; i++)
f[i] += (float)d_w[i];
#endif
for (int i = 0; i < NQ; i++)
fi_phys[tid * NQ + i] = f[i];
}
// ---------------------------------------------------------------------------
// EncodePhysicalToCells: physical DDF -> backing layout (compact list)
//
// Inverse of DecodeCellsToPhysical at the SAME completed step count.
// Conversion only: no collision or time advancement, including unchanged halo.
// ---------------------------------------------------------------------------
__global__ void EncodePhysicalToCells(
fpxx* fi,
const float* fi_phys,
const unsigned int* cell_idx,
unsigned int n_cells,
unsigned long t)
{
unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
if (tid >= n_cells) return;
unsigned long k = (unsigned long)cell_idx[tid];
unsigned int x, y; coordinates(k, x, y);
unsigned long j[NQ]; compute_neighbors(x, y, j);
float f[NQ];
for (int i = 0; i < NQ; i++)
f[i] = fi_phys[tid * NQ + i];
#if USE_DDF_SHIFTING
for (int i = 0; i < NQ; ++i) f[i] -= (float)d_w[i];
#endif
store_physical_node_esopull(k, f, fi, j, t);
}
#endif // CELERIS_STEP_ESOPULL_SYNC_CU