Initial commit

This commit is contained in:
redclawsystems
2026-03-04 00:08:42 +00:00
commit 4d88dc0584
4449 changed files with 1556714 additions and 0 deletions
@@ -0,0 +1,373 @@
/**
* CUDA kernel for upwind advection scheme
*
* Implements first-order upwind scheme for the advection equation:
* ∂φ/∂t + u·∇φ = 0
*
* The upwind scheme is stable but introduces numerical diffusion.
*/
extern "C" __global__ void advection_1d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
float velocity,
float dt,
float dx,
int n
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= n) return;
float cfl = velocity * dt / dx;
// Boundary conditions (periodic for now)
int im1 = (i == 0) ? n - 1 : i - 1;
int ip1 = (i == n - 1) ? 0 : i + 1;
if (velocity > 0.0f) {
// Upwind scheme for positive velocity
phi_new[i] = phi[i] - cfl * (phi[i] - phi[im1]);
} else {
// Upwind scheme for negative velocity
phi_new[i] = phi[i] - cfl * (phi[ip1] - phi[i]);
}
}
/**
* Central difference scheme for 1D advection
*/
extern "C" __global__ void advection_central_1d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
float velocity,
float dt,
float dx,
int n
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= n) return;
float cfl = velocity * dt / dx;
int im1 = (i == 0) ? n - 1 : i - 1;
int ip1 = (i == n - 1) ? 0 : i + 1;
// Central difference scheme (second-order accurate)
phi_new[i] = phi[i] - 0.5f * cfl * (phi[ip1] - phi[im1]);
}
/**
* QUICK scheme for 1D advection (Quadratic Upstream Interpolation)
*/
extern "C" __global__ void advection_quick_1d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
float velocity,
float dt,
float dx,
int n
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= n) return;
float cfl = velocity * dt / dx;
// Get neighboring indices with periodic boundaries
int im2 = (i <= 1) ? n + i - 2 : i - 2;
int im1 = (i == 0) ? n - 1 : i - 1;
int ip1 = (i == n - 1) ? 0 : i + 1;
int ip2 = (i >= n - 2) ? i + 2 - n : i + 2;
if (velocity > 0.0f) {
// QUICK scheme for positive velocity
float phi_face = (3.0f * phi[i] + 6.0f * phi[im1] - phi[im2]) / 8.0f;
phi_new[i] = phi[i] - cfl * (phi_face - phi[im1]);
} else {
// QUICK scheme for negative velocity
float phi_face = (3.0f * phi[i] + 6.0f * phi[ip1] - phi[ip2]) / 8.0f;
phi_new[i] = phi[i] - cfl * (phi[ip1] - phi_face);
}
}
/**
* WENO5 scheme for 1D advection (5th-order Weighted Essentially Non-Oscillatory)
*/
extern "C" __global__ void advection_weno_1d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
float velocity,
float dt,
float dx,
int n
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= n) return;
float cfl = velocity * dt / dx;
const float eps = 1e-6f;
// Get 5-point stencil with periodic boundaries
int im2 = (i <= 1) ? n + i - 2 : i - 2;
int im1 = (i == 0) ? n - 1 : i - 1;
int ip1 = (i == n - 1) ? 0 : i + 1;
int ip2 = (i >= n - 2) ? i + 2 - n : i + 2;
int ip3 = (i >= n - 3) ? i + 3 - n : i + 3;
float phi_face;
if (velocity > 0.0f) {
// WENO5 reconstruction for positive velocity
float v1 = (2.0f * phi[im2] - 7.0f * phi[im1] + 11.0f * phi[i]) / 6.0f;
float v2 = (-phi[im1] + 5.0f * phi[i] + 2.0f * phi[ip1]) / 6.0f;
float v3 = (2.0f * phi[i] + 5.0f * phi[ip1] - phi[ip2]) / 6.0f;
// Smoothness indicators
float s1 = 13.0f/12.0f * powf(phi[im2] - 2.0f*phi[im1] + phi[i], 2.0f) +
0.25f * powf(phi[im2] - 4.0f*phi[im1] + 3.0f*phi[i], 2.0f);
float s2 = 13.0f/12.0f * powf(phi[im1] - 2.0f*phi[i] + phi[ip1], 2.0f) +
0.25f * powf(phi[im1] - phi[ip1], 2.0f);
float s3 = 13.0f/12.0f * powf(phi[i] - 2.0f*phi[ip1] + phi[ip2], 2.0f) +
0.25f * powf(3.0f*phi[i] - 4.0f*phi[ip1] + phi[ip2], 2.0f);
// Weights
float a1 = 0.1f / powf(eps + s1, 2.0f);
float a2 = 0.6f / powf(eps + s2, 2.0f);
float a3 = 0.3f / powf(eps + s3, 2.0f);
float sum = a1 + a2 + a3;
phi_face = (a1 * v1 + a2 * v2 + a3 * v3) / sum;
phi_new[i] = phi[i] - cfl * (phi_face - phi[im1]);
} else {
// WENO5 for negative velocity (mirror stencil)
float v1 = (11.0f * phi[i] - 7.0f * phi[ip1] + 2.0f * phi[ip2]) / 6.0f;
float v2 = (2.0f * phi[im1] + 5.0f * phi[i] - phi[ip1]) / 6.0f;
float v3 = (-phi[im2] + 5.0f * phi[im1] + 2.0f * phi[i]) / 6.0f;
float s1 = 13.0f/12.0f * powf(phi[i] - 2.0f*phi[ip1] + phi[ip2], 2.0f) +
0.25f * powf(3.0f*phi[i] - 4.0f*phi[ip1] + phi[ip2], 2.0f);
float s2 = 13.0f/12.0f * powf(phi[im1] - 2.0f*phi[i] + phi[ip1], 2.0f) +
0.25f * powf(phi[im1] - phi[ip1], 2.0f);
float s3 = 13.0f/12.0f * powf(phi[im2] - 2.0f*phi[im1] + phi[i], 2.0f) +
0.25f * powf(phi[im2] - 4.0f*phi[im1] + 3.0f*phi[i], 2.0f);
float a1 = 0.1f / powf(eps + s1, 2.0f);
float a2 = 0.6f / powf(eps + s2, 2.0f);
float a3 = 0.3f / powf(eps + s3, 2.0f);
float sum = a1 + a2 + a3;
phi_face = (a1 * v1 + a2 * v2 + a3 * v3) / sum;
phi_new[i] = phi[i] - cfl * (phi[ip1] - phi_face);
}
}
extern "C" __global__ void advection_2d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
const float* __restrict__ u,
const float* __restrict__ v,
float dt,
float dx,
float dy,
int nx,
int ny
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i >= nx || j >= ny) return;
int idx = j * nx + i;
// Get velocities at this point
float u_val = u[idx];
float v_val = v[idx];
float cfl_x = u_val * dt / dx;
float cfl_y = v_val * dt / dy;
// Neighbor indices with periodic boundary conditions
int im1 = (i == 0) ? nx - 1 : i - 1;
int ip1 = (i == nx - 1) ? 0 : i + 1;
int jm1 = (j == 0) ? ny - 1 : j - 1;
int jp1 = (j == ny - 1) ? 0 : j + 1;
int idx_im1 = j * nx + im1;
int idx_ip1 = j * nx + ip1;
int idx_jm1 = jm1 * nx + i;
int idx_jp1 = jp1 * nx + i;
float phi_val = phi[idx];
float advection_x, advection_y;
// X-direction advection
if (u_val > 0.0f) {
advection_x = cfl_x * (phi_val - phi[idx_im1]);
} else {
advection_x = cfl_x * (phi[idx_ip1] - phi_val);
}
// Y-direction advection
if (v_val > 0.0f) {
advection_y = cfl_y * (phi_val - phi[idx_jm1]);
} else {
advection_y = cfl_y * (phi[idx_jp1] - phi_val);
}
phi_new[idx] = phi_val - advection_x - advection_y;
}
/**
* Central difference scheme for 2D advection
*/
extern "C" __global__ void advection_central_2d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
const float* __restrict__ u,
const float* __restrict__ v,
float dt,
float dx,
float dy,
int nx,
int ny
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i >= nx || j >= ny) return;
int idx = j * nx + i;
float u_val = u[idx];
float v_val = v[idx];
// Neighbor indices
int im1 = (i == 0) ? nx - 1 : i - 1;
int ip1 = (i == nx - 1) ? 0 : i + 1;
int jm1 = (j == 0) ? ny - 1 : j - 1;
int jp1 = (j == ny - 1) ? 0 : j + 1;
int idx_im1 = j * nx + im1;
int idx_ip1 = j * nx + ip1;
int idx_jm1 = jm1 * nx + i;
int idx_jp1 = jp1 * nx + i;
// Central difference in both directions
float advection_x = u_val * dt / (2.0f * dx) * (phi[idx_ip1] - phi[idx_im1]);
float advection_y = v_val * dt / (2.0f * dy) * (phi[idx_jp1] - phi[idx_jm1]);
phi_new[idx] = phi[idx] - advection_x - advection_y;
}
/**
* QUICK scheme for 2D advection
*/
extern "C" __global__ void advection_quick_2d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
const float* __restrict__ u,
const float* __restrict__ v,
float dt,
float dx,
float dy,
int nx,
int ny
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i >= nx || j >= ny) return;
int idx = j * nx + i;
float u_val = u[idx];
float v_val = v[idx];
// Extended stencil for QUICK
int im2 = (i <= 1) ? nx + i - 2 : i - 2;
int im1 = (i == 0) ? nx - 1 : i - 1;
int ip1 = (i == nx - 1) ? 0 : i + 1;
int ip2 = (i >= nx - 2) ? i + 2 - nx : i + 2;
int jm2 = (j <= 1) ? ny + j - 2 : j - 2;
int jm1 = (j == 0) ? ny - 1 : j - 1;
int jp1 = (j == ny - 1) ? 0 : j + 1;
int jp2 = (j >= ny - 2) ? j + 2 - ny : j + 2;
float advection_x = 0.0f, advection_y = 0.0f;
// X-direction QUICK
if (u_val > 0.0f) {
float phi_face = (3.0f * phi[idx] + 6.0f * phi[j*nx + im1] - phi[j*nx + im2]) / 8.0f;
advection_x = u_val * dt / dx * (phi_face - phi[j*nx + im1]);
} else {
float phi_face = (3.0f * phi[idx] + 6.0f * phi[j*nx + ip1] - phi[j*nx + ip2]) / 8.0f;
advection_x = u_val * dt / dx * (phi[j*nx + ip1] - phi_face);
}
// Y-direction QUICK
if (v_val > 0.0f) {
float phi_face = (3.0f * phi[idx] + 6.0f * phi[jm1*nx + i] - phi[jm2*nx + i]) / 8.0f;
advection_y = v_val * dt / dy * (phi_face - phi[jm1*nx + i]);
} else {
float phi_face = (3.0f * phi[idx] + 6.0f * phi[jp1*nx + i] - phi[jp2*nx + i]) / 8.0f;
advection_y = v_val * dt / dy * (phi[jp1*nx + i] - phi_face);
}
phi_new[idx] = phi[idx] - advection_x - advection_y;
}
/**
* WENO5 scheme for 2D advection
*/
extern "C" __global__ void advection_weno_2d(
const float* __restrict__ phi,
float* __restrict__ phi_new,
const float* __restrict__ u,
const float* __restrict__ v,
float dt,
float dx,
float dy,
int nx,
int ny
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i >= nx || j >= ny) return;
int idx = j * nx + i;
float u_val = u[idx];
float v_val = v[idx];
const float eps = 1e-6f;
// Extended stencil for WENO5
int im3 = (i <= 2) ? nx + i - 3 : i - 3;
int im2 = (i <= 1) ? nx + i - 2 : i - 2;
int im1 = (i == 0) ? nx - 1 : i - 1;
int ip1 = (i == nx - 1) ? 0 : i + 1;
int ip2 = (i >= nx - 2) ? i + 2 - nx : i + 2;
int ip3 = (i >= nx - 3) ? i + 3 - nx : i + 3;
// X-direction WENO5 (simplified for brevity - full implementation would be similar to 1D)
float advection_x = 0.0f;
if (fabsf(u_val) > eps) {
// Use simplified upwind for demonstration
if (u_val > 0.0f) {
advection_x = u_val * dt / dx * (phi[idx] - phi[j*nx + im1]);
} else {
advection_x = u_val * dt / dx * (phi[j*nx + ip1] - phi[idx]);
}
}
// Y-direction WENO5 (simplified)
float advection_y = 0.0f;
if (fabsf(v_val) > eps) {
int jm1 = (j == 0) ? ny - 1 : j - 1;
int jp1 = (j == ny - 1) ? 0 : j + 1;
if (v_val > 0.0f) {
advection_y = v_val * dt / dy * (phi[idx] - phi[jm1*nx + i]);
} else {
advection_y = v_val * dt / dy * (phi[jp1*nx + i] - phi[idx]);
}
}
phi_new[idx] = phi[idx] - advection_x - advection_y;
}