// CelerisLab – boundary/inlet/common.cuh
// Shared helpers for west velocity inlet source-state generation.
//
// Important semantic contract in this solver:
// - x=0 inlet cells are SOLID|BC_INLET ghost source nodes
// - they generate the state later pulled by the first interior fluid column
// - inlet methods therefore construct a source state, not a textbook fluid-node
//   boundary update in isolation
// ============================================================================

#ifndef CELERIS_BOUNDARY_INLET_COMMON_CUH
#define CELERIS_BOUNDARY_INLET_COMMON_CUH

#ifndef INLET_PROFILE
#define INLET_PROFILE 1
#endif

#ifndef INLET_SCHEME
#define INLET_SCHEME 0
#endif

#ifndef INLET_TRT_NEQ_DAMP
#define INLET_TRT_NEQ_DAMP 0.50f
#endif

#ifndef INLET_REGULARIZED_NEQ_DAMP
#define INLET_REGULARIZED_NEQ_DAMP 0.50f
#endif

__device__ __forceinline__ float inlet_target_u(float y_coord) {
#if INLET_PROFILE == 0
    return U0;
#else
    const float y_clamped = fminf((float)(NY - 2), fmaxf(1.0f, y_coord));
    const float H = fmaxf((float)(NY - 2), 1.0f);
    const float eta = (y_clamped - 0.5f) / H;
    const float shape = fmaxf(0.0f, 4.0f * eta * (1.0f - eta));
    return U0 * 1.5f * shape;
#endif
}

#if LATTICE_MODEL == LATTICE_D2Q9
__device__ __forceinline__ float west_velocity_rho_closure_d2q9(
    const float* __restrict__ f,
    float ux_target)
{
    float rho_num = f[0] + f[3] + f[4] + 2.0f * (f[2] + f[6] + f[8]);
#if USE_DDF_SHIFTING
    // f[i] = physical_f[i] - w[i]; restore the sum of weights for
    // the directions appearing in the numerator (w[0]=4/9, w[3]=w[4]=1/9,
    // w[2]=w[6]=w[8]=1/36, with f[2],f[6],f[8] double-counted):
    // sum(w) = 4/9 + 1/9 + 1/9 + 2*(1/36+1/36+1/36) = 6/9 + 6/36 = 5/6
    rho_num += 5.0f / 6.0f;
#endif
    return rho_num / (1.0f - ux_target);
}
#endif

#if LATTICE_MODEL == LATTICE_D3Q19
__device__ __forceinline__ float west_velocity_rho_closure_d3q19(
    const float* __restrict__ f,
    float ux_target)
{
    float rho_num = f[0] + f[3] + f[4] + f[5] + f[6] + f[11] + f[12] + f[17] + f[18]
                  + 2.0f * (f[2] + f[8] + f[10] + f[14] + f[16]);
#if USE_DDF_SHIFTING
    // f[i] = physical_f[i] - w[i]; restore the sum of weights for
    // the directions appearing in the numerator (w[0]=1/3, w[3..6,11,12,17,18]=1/18,
    // w[2,8,10,14,16]=1/36 double-counted):
    // sum(w) = 1/3 + 8*(1/18) + 5*(2/36) = 12/36 + 16/36 + 10/36 = 38/36 = 19/18
    rho_num += 19.0f / 18.0f;
#endif
    return rho_num / (1.0f - ux_target);
}
#endif

__device__ __forceinline__ bool inlet_scheme_uses_post_collision_ghost()
{
#if INLET_SCHEME == 0
    return true;
#else
    return false;
#endif
}

#endif // CELERIS_BOUNDARY_INLET_COMMON_CUH
