Introduction
Introduction Statistics Contact Development Disclaimer Help
tFirst LB implementation - sphere - GPU-based 3D discrete element method algori…
git clone git://src.adamsgaard.dk/sphere
Log
Files
Refs
LICENSE
---
commit a1814d9713a6767e9c6e8ef614aad8219ef61dc9
parent 89410ac23699c2d57aac5c6ac5b99bb8793e7670
Author: Anders Damsgaard <[email protected]>
Date: Mon, 29 Apr 2013 14:13:38 +0200
First LB implementation
Diffstat:
A src/latticeboltzmann.cuh | 447 +++++++++++++++++++++++++++++…
1 file changed, 447 insertions(+), 0 deletions(-)
---
diff --git a/src/latticeboltzmann.cuh b/src/latticeboltzmann.cuh
t@@ -0,0 +1,447 @@
+#ifndef LATTICEBOLTZMANN_CUH_
+#define LATTICEBOLTZMANN_CUH_
+
+// latticeboltzmann.cuh
+// Functions for solving the Navier-Stokes equations using the Lattice-Boltzma…
+// method with D3Q19 stencils
+
+// Calculate linear cell index from position (x,y,z)
+// and fluid position vector (i).
+// From A. Monitzer 2013
+__device__ unsigned int grid2index(
+ unsigned int x, unsigned int y, unsigned int z,
+ unsigned int i)
+{
+ return x + ((y + z*devC_grid.num[1])*devC_grid.num[0])
+ + (devC_grid.num[0]*devC_grid.num[1]*devC_grid.num[2]*i);
+}
+
+// Equilibrium distribution
+__device__ Float feq(Float3 v, Float rho, Float3 e, Float omega)
+{
+ return omega*rho * (1.0 - 3.0/2.0 * dot(v,v) + 3.0*dot(e,v) +
+ 9.0/2.0*dot(e,v)*dot(e,v));
+}
+
+// Collision operator
+// Bhatnagar-Gross-Krook approximation (BGK), Thurey (2003).
+__device__ Float bgk(
+ Float f,
+ Float tau,
+ Float3 v,
+ Float rho,
+ Float3 e,
+ Float omega,
+ Float3 extF)
+{
+ return devC_dt / tau * (f - feq(v, rho, e, omega))
+ - (1.0 - 1.0/(2.0*tau)) * 3.0/omega * dot(extF, e);
+}
+
+// Initialize the fluid distributions on the base of the densities provided
+__global__ void initfluid(
+ Float4* dev_v_rho,
+ Float* dev_f)
+{
+ // 1D thread index
+ const unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;
+
+ // Check if the thread is outside the cell grid
+ if (idx >= devC_grid.num[0]*devC_grid.num[1]*devC_grid.num[2])
+ return;
+
+ // 3D thread index
+ const unsigned int z = idx % devC_grid.num[2];
+ const unsigned int y = (idx / devC_grid.num[2]) % devC_grid.num[1];
+ const unsigned int x = idx / (devC_grid.num[1] * devC_grid.num[2]);
+
+ // Read velocity and density, zero velocity
+ Float4 v_rho = dev_v_rho[idx];
+ v_rho = MAKE_FLOAT4(0.0, 0.0, 0.0, v_rho.w);
+
+ // Set values to equilibrium distribution (f_i = omega_i * rho_0)
+ __syncthreads();
+ dev_v_rho[idx] = v_rho;
+ dev_f[grid2index(x,y,z,0)] = 1.0/3.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,1)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,2)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,3)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,4)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,5)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,6)] = 1.0/18.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,7)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,8)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,9)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,10)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,11)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,12)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,13)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,14)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,15)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,16)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,17)] = 1.0/36.0 * v_rho.w;
+ dev_f[grid2index(x,y,z,18)] = 1.0/36.0 * v_rho.w;
+}
+
+// Swap two arrays pointers
+void swapFloatArrays(Float* arr1, Float* arr2)
+{
+ Float* tmp = arr1;
+ arr1 = arr2;
+ arr2 = tmp;
+}
+
+// Combined streaming and collision step with particle coupling and optional
+// periodic boundaries. Derived from A. Monitzer 2013
+__global__ void latticeBoltzmannD3Q19(
+ Float* dev_f,
+ Float* dev_f_new,
+ Float4* dev_v_rho, // fluid velocities and densities
+ unsigned int* dev_cellStart, // first particle in cells
+ unsigned int* dev_cellEnd, // last particle in cells
+ Float4* dev_x_sorted, // particle positions + radii
+ Float4* dev_vel_sorted, // particle velocities + fixvel
+ Float4* dev_force,
+ unsigned int* dev_gridParticleIndex)
+{
+ // 1D thread index
+ const unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;
+
+ // Check if the thread is outside the cell grid
+ if (idx >= devC_grid.num[0]*devC_grid.num[1]*devC_grid.num[2])
+ return;
+
+ // 3D thread index
+ unsigned int z = idx % devC_grid.num[2];
+ unsigned int y = (idx / devC_grid.num[2]) % devC_grid.num[1];
+ unsigned int x = idx / (devC_grid.num[1] * devC_grid.num[2]);
+
+
+ // Load the fluid distribution into local registers
+ __syncthreads();
+ Float f_0 = dev_f[grid2index(x,y,z,0)];
+ Float f_1 = dev_f[grid2index(x,y,z,1)];
+ Float f_2 = dev_f[grid2index(x,y,z,2)];
+ Float f_3 = dev_f[grid2index(x,y,z,3)];
+ Float f_4 = dev_f[grid2index(x,y,z,4)];
+ Float f_5 = dev_f[grid2index(x,y,z,5)];
+ Float f_6 = dev_f[grid2index(x,y,z,6)];
+ Float f_7 = dev_f[grid2index(x,y,z,7)];
+ Float f_8 = dev_f[grid2index(x,y,z,8)];
+ Float f_9 = dev_f[grid2index(x,y,z,9)];
+ Float f_10 = dev_f[grid2index(x,y,z,10)];
+ Float f_11 = dev_f[grid2index(x,y,z,11)];
+ Float f_12 = dev_f[grid2index(x,y,z,12)];
+ Float f_13 = dev_f[grid2index(x,y,z,13)];
+ Float f_14 = dev_f[grid2index(x,y,z,14)];
+ Float f_15 = dev_f[grid2index(x,y,z,15)];
+ Float f_16 = dev_f[grid2index(x,y,z,16)];
+ Float f_17 = dev_f[grid2index(x,y,z,17)];
+ Float f_18 = dev_f[grid2index(x,y,z,18)];
+
+ // Fluid constant (Wei et al. 2004), nu: kinematic viscosity [Pa*s]
+ const Float tau = 0.5*(1.0 + 6.0*devC_params.nu);
+
+ // Directional vectors to each lattice-velocity in D3Q19
+ // Zero velocity: i = 0
+ // Faces: i = 1..6
+ // Edges: i = 7..18
+ const Float3 e_0 = MAKE_FLOAT3( 0.0, 0.0, 0.0); // zero vel.
+ const Float3 e_1 = MAKE_FLOAT3( 1.0, 0.0, 0.0); // face: +x
+ const Float3 e_2 = MAKE_FLOAT3(-1.0, 0.0, 0.0); // face: -x
+ const Float3 e_3 = MAKE_FLOAT3( 0.0, 1.0, 0.0); // face: +y
+ const Float3 e_4 = MAKE_FLOAT3( 0.0,-1.0, 0.0); // face: -y
+ const Float3 e_5 = MAKE_FLOAT3( 0.0, 0.0, 1.0); // face: +z
+ const Float3 e_6 = MAKE_FLOAT3( 0.0, 0.0,-1.0); // face: -z
+ const Float3 e_7 = MAKE_FLOAT3( 1.0, 1.0, 0.0); // edge: +x,+y
+ const Float3 e_8 = MAKE_FLOAT3(-1.0,-1.0, 0.0); // edge: -x,-y
+ const Float3 e_9 = MAKE_FLOAT3( 1.0,-1.0, 0.0); // edge: -x,+y
+ const Float3 e_10 = MAKE_FLOAT3( 1.0,-1.0, 0.0); // edge: +x,-y
+ const Float3 e_11 = MAKE_FLOAT3( 1.0, 0.0, 1.0); // edge: +x,+z
+ const Float3 e_12 = MAKE_FLOAT3(-1.0, 0.0,-1.0); // edge: -x,-z
+ const Float3 e_13 = MAKE_FLOAT3( 0.0, 1.0, 1.0); // edge: +y,+z
+ const Float3 e_14 = MAKE_FLOAT3( 0.0,-1.0,-1.0); // edge: -y,-z
+ const Float3 e_15 = MAKE_FLOAT3(-1.0, 0.0, 1.0); // edge: -x,+z
+ const Float3 e_16 = MAKE_FLOAT3( 1.0, 0.0,-1.0); // edge: +x,-z
+ const Float3 e_17 = MAKE_FLOAT3( 0.0,-1.0, 1.0); // edge: -y,+z
+ const Float3 e_18 = MAKE_FLOAT3( 0.0, 1.0,-1.0); // edge: +y,-z
+
+
+ //// Calculate the cell's macroproperties
+
+ // Fluid density (rho = sum(f_i))
+ const Float rho = f_0 + f_1 + f_2 + f_3 + f_4 + f_5 + f_6 + f_7 + f_8 + f_…
+ + f_10 + f_11 + f_12 + f_13 + f_14 + f_15 + f_16 + f_17 + f_18;
+
+ // Fluid velocity (v = sum(f_i/e_i)/rho)
+ const Float3 v = (f_0/e_0 + f_1/e_1 + f_2/e_2 + f_3/e_3 + f_4/e_4 + f_5/e_5
+ + f_6/e_6 + f_7/e_7 + f_8/e_8 + f_9/e_9 + f_10/e_10 + f_11/e_11
+ + f_12/e_12 + f_13/e_13 + f_14/e_14 + f_15/e_15 + f_16/e_16
+ + f_17/e_17 + f_18/e_18) / rho;
+
+ //// Calculate the force transferred from the particles to the fluid
+ Float3 f_particle;
+ Float3 f_particles = MAKE_FLOAT3(0.0, 0.0, 0.0);
+ Float4 x_particle4; // particle position + radius
+ Float r_particle; // radius
+ Float4 v_particle4; // particle velocity + fixvel
+ Float3 v_particle; // particle velocity
+
+ // Lowest particle index in cell
+ unsigned int startIdx = dev_cellStart[idx];
+ unsigned int orig_idx;
+
+ // Make sure cell is not empty
+ if (startIdx != 0xffffffff) {
+
+ // Highest particle index in cell + 1
+ unsigned int endIdx = dev_cellEnd[idx];
+
+ // Iterate over cell particles
+ for (unsigned int idx = startIdx; idx<endIdx; ++idx) {
+
+ // Read particle radius and velocity
+ __syncthreads();
+ orig_idx = dev_gridParticleIndex[idx];
+ x_particle4 = dev_x_sorted[idx];
+ v_particle4 = dev_vel_sorted[idx];
+
+ r_particle = x_particle4.w;
+ v_particle = MAKE_FLOAT3(
+ v_particle4.x,
+ v_particle4.y,
+ v_particle4.z);
+
+ // Aerodynamic drag
+ f_particle = (v - v_particle) * r_particle*r_particle;
+
+ // Add the drag force to the sum of forces in the cell
+ f_particles += f_particle;
+
+ // The particle experiences the opposite drag force
+ __syncthreads();
+ dev_force[orig_idx] = MAKE_FLOAT4(
+ -f_particle.x,
+ -f_particle.y,
+ -f_particle.z,
+ 0.0);
+ }
+ }
+
+ // Scale the particle force
+ // 100: experimental value, depends on the grid size compared to the
+ // particle size and the time step size
+ f_particles *= 100.0 * rho * 6.0;
+
+ // Gravitational force (F = g * m)
+ const Float3 f_gravity = MAKE_FLOAT3(
+ devC_params.g[0],
+ devC_params.g[1],
+ devC_params.g[2])
+ * (devC_grid.L[0]/devC_grid.num[0])
+ * (devC_grid.L[1]/devC_grid.num[1])
+ * (devC_grid.L[2]/devC_grid.num[2]) * rho;
+
+ // The final external force
+ const Float3 f_ext = f_particles + f_gravity;
+
+ //// Collide fluid
+ // Weights corresponding to each e_i lattice-velocity in D3Q19, sum to 1.0
+ f_0 -= bgk(f_0, tau, v, rho, e_0, 1.0/3.0, f_ext);
+ f_1 -= bgk(f_1, tau, v, rho, e_1, 1.0/18.0, f_ext);
+ f_2 -= bgk(f_2, tau, v, rho, e_2, 1.0/18.0, f_ext);
+ f_3 -= bgk(f_3, tau, v, rho, e_3, 1.0/18.0, f_ext);
+ f_4 -= bgk(f_4, tau, v, rho, e_4, 1.0/18.0, f_ext);
+ f_5 -= bgk(f_5, tau, v, rho, e_5, 1.0/18.0, f_ext);
+ f_6 -= bgk(f_6, tau, v, rho, e_6, 1.0/18.0, f_ext);
+ f_7 -= bgk(f_7, tau, v, rho, e_7, 1.0/36.0, f_ext);
+ f_8 -= bgk(f_8, tau, v, rho, e_8, 1.0/36.0, f_ext);
+ f_9 -= bgk(f_9, tau, v, rho, e_9, 1.0/36.0, f_ext);
+ f_10 -= bgk(f_10, tau, v, rho, e_10, 1.0/36.0, f_ext);
+ f_11 -= bgk(f_11, tau, v, rho, e_11, 1.0/36.0, f_ext);
+ f_12 -= bgk(f_12, tau, v, rho, e_12, 1.0/36.0, f_ext);
+ f_13 -= bgk(f_13, tau, v, rho, e_13, 1.0/36.0, f_ext);
+ f_14 -= bgk(f_14, tau, v, rho, e_14, 1.0/36.0, f_ext);
+ f_15 -= bgk(f_15, tau, v, rho, e_15, 1.0/36.0, f_ext);
+ f_16 -= bgk(f_16, tau, v, rho, e_16, 1.0/36.0, f_ext);
+ f_17 -= bgk(f_17, tau, v, rho, e_17, 1.0/36.0, f_ext);
+ f_18 -= bgk(f_18, tau, v, rho, e_18, 1.0/36.0, f_ext);
+
+
+ //// Stream fluid
+ // Lower and upper boundaries: bounceback, sides: periodic
+ unsigned int nx = devC_grid.num[0];
+ unsigned int ny = devC_grid.num[1];
+ unsigned int nz = devC_grid.num[2];
+
+ // There may be a write conflict due to bounce backs
+ __syncthreads();
+
+ // Face 0
+ dev_f_new[grid2index(x,y,z,0)] = fmax(0.0, f_0);
+
+ // Face 1 (+x): Periodic
+ if (x < nx-1) // not at boundary
+ dev_f_new[grid2index( x+1, y, z, 1)] = fmax(0.0, f_1);
+ else // at boundary
+ dev_f_new[grid2index( 0, y, z, 1)] = fmax(0.0, f_1);
+
+ // Face 2 (-x): Periodic
+ if (x > 0) // not at boundary
+ dev_f_new[grid2index( x-1, y, z, 2)] = fmax(0.0, f_2);
+ else // at boundary
+ dev_f_new[grid2index(nx-1, y, z, 2)] = fmax(0.0, f_2);
+
+ // Face 3 (+y): Periodic
+ if (y < ny-1) // not at boundary
+ dev_f_new[grid2index( x, y+1, z, 3)] = fmax(0.0, f_3);
+ else // at boundary
+ dev_f_new[grid2index( x, 0, z, 3)] = fmax(0.0, f_3);
+
+ // Face 4 (-y): Periodic
+ if (y > 0) // not at boundary
+ dev_f_new[grid2index( x, y-1, z, 4)] = fmax(0.0, f_4);
+ else // at boundary
+ dev_f_new[grid2index( x,ny-1, z, 4)] = fmax(0.0, f_4);
+
+ // Face 5 (+z): Bounce back, free slip
+ if (z < nz-1) // not at boundary
+ dev_f_new[grid2index( x, y, z+1, 5)] = fmax(0.0, f_5);
+ else // at boundary
+ dev_f_new[grid2index( x, y, z, 6)] = fmax(0.0, f_5);
+
+ // Face 6 (-z): Bounce back, free slip
+ if (z > 0) // not at boundary
+ dev_f_new[grid2index( x, y, z-1, 6)] = fmax(0.0, f_6);
+ else // at boundary
+ dev_f_new[grid2index( x, y, z, 5)] = fmax(0.0, f_6);
+
+ // Edge 7 (+x,+y): Periodic
+ if (x < nx-1 && y < ny-1) // not at boundary
+ dev_f_new[grid2index( x+1, y+1, z, 7)] = fmax(0.0, f_7);
+ else if (x < nx-1) // at +y boundary
+ dev_f_new[grid2index( x+1, 0, z, 7)] = fmax(0.0, f_7);
+ else if (y < ny-1) // at +x boundary
+ dev_f_new[grid2index( 0, y+1, z, 7)] = fmax(0.0, f_7);
+ else // at +x+y boundary
+ dev_f_new[grid2index( 0, 0, z, 7)] = fmax(0.0, f_7);
+
+ // Edge 8 (-x,-y): Periodic
+ if (x > 0 && y > 0) // not at boundary
+ dev_f_new[grid2index( x-1, y-1, z, 8)] = fmax(0.0, f_8);
+ else if (x > 0) // at -y boundary
+ dev_f_new[grid2index( x-1,ny-1, z, 8)] = fmax(0.0, f_8);
+ else if (y > 0) // at -x boundary
+ dev_f_new[grid2index(nx-1, y-1, z, 8)] = fmax(0.0, f_8);
+ else // at -x-y boundary
+ dev_f_new[grid2index(nx-1,ny-1, z, 8)] = fmax(0.0, f_8);
+
+ // Edge 9 (-x,+y): Periodic
+ if (x > 0 && y < ny-1) // not at boundary
+ dev_f_new[grid2index( x-1, y+1, z, 9)] = fmax(0.0, f_9);
+ else if (x > 0) // at +y boundary
+ dev_f_new[grid2index( x-1, 0, z, 9)] = fmax(0.0, f_9);
+ else if (y < ny-1) // at -x boundary
+ dev_f_new[grid2index(nx-1, y+1, z, 9)] = fmax(0.0, f_9);
+ else // at -x+y boundary
+ dev_f_new[grid2index(nx-1, 0, z, 9)] = fmax(0.0, f_9);
+
+ // Edge 10 (+x,-y): Periodic
+ if (x < nx-1 && y > 0) // not at boundary
+ dev_f_new[grid2index( x+1, y-1, z, 10)] = fmax(0.0, f_10);
+ else if (x < nx-1) // at -y boundary
+ dev_f_new[grid2index( x+1,ny-1, z, 10)] = fmax(0.0, f_10);
+ else if (y > 0) // at +x boundary
+ dev_f_new[grid2index( 0, y-1, z, 10)] = fmax(0.0, f_10);
+ else // at +x-y boundary
+ dev_f_new[grid2index( 0,ny-1, z, 10)] = fmax(0.0, f_10);
+
+ // Edge 11 (+x,+z): Periodic & bounce-back (free slip)
+ if (x < nx-1 && z < nz-1) // not at boundary
+ dev_f_new[grid2index( x+1, y, z+1, 11)] = fmax(0.0, f_11);
+ else if (x < nx-1) // at +z boundary
+ dev_f_new[grid2index( x+1, y, 0, 12)] = fmax(0.0, f_11);
+ else if (z < nz-1) // at +x boundary
+ dev_f_new[grid2index( 0, y, z+1, 11)] = fmax(0.0, f_11);
+ else // at +x+z boundary
+ dev_f_new[grid2index( 0, y, 0, 12)] = fmax(0.0, f_11);
+
+ // Edge 12 (-x,-z): Periodic & bounce back (free slip)
+ if (x > 0 && z > 0) // not at boundary
+ dev_f_new[grid2index( x-1, y, z-1, 12)] = fmax(0.0, f_12);
+ else if (x > 0) // at -z boundary
+ dev_f_new[grid2index( x-1, y,nz-1, 11)] = fmax(0.0, f_12);
+ else if (z > 0) // at -x boundary
+ dev_f_new[grid2index(nx-1, y, z-1, 12)] = fmax(0.0, f_12);
+ else // at -x-z boundary
+ dev_f_new[grid2index(nx-1, y,nz-1, 11)] = fmax(0.0, f_12);
+
+ // Edge 13 (+y,+z): Periodic & bounce-back (free slip)
+ if (y < ny-1 && z < nz-1) // not at boundary
+ dev_f_new[grid2index( x, y+1, z+1, 13)] = fmax(0.0, f_13);
+ else if (y < ny-1) // at +z boundary
+ dev_f_new[grid2index( x, y+1, 0, 14)] = fmax(0.0, f_13);
+ else if (z < nz-1) // at +y boundary
+ dev_f_new[grid2index( x, 0, z+1, 13)] = fmax(0.0, f_13);
+ else // at +y+z boundary
+ dev_f_new[grid2index( x, 0, 0, 14)] = fmax(0.0, f_13);
+
+ // Edge 14 (-y,-z): Periodic & bounce-back (free slip)
+ if (y > 0 && z > 0) // not at boundary
+ dev_f_new[grid2index( x, y-1, z-1, 14)] = fmax(0.0, f_14);
+ else if (y > 0) // at -z boundary
+ dev_f_new[grid2index( x, y-1,nz-1, 13)] = fmax(0.0, f_14);
+ else if (z > 0) // at -y boundary
+ dev_f_new[grid2index( x,ny-1, z-1, 14)] = fmax(0.0, f_14);
+ else // at -y-z boundary
+ dev_f_new[grid2index( x,ny-1,nz-1, 13)] = fmax(0.0, f_14);
+
+ // Edge 15 (-x,+z): Periodic & bounce-back (free slip)
+ if (x > 0 && z < nz-1) // not at boundary
+ dev_f_new[grid2index( x-1, y, z+1, 15)] = fmax(0.0, f_15);
+ else if (x > 0) // at +z boundary
+ dev_f_new[grid2index( x-1, y, 0, 16)] = fmax(0.0, f_15);
+ else if (z < nz-1) // at -x boundary
+ dev_f_new[grid2index(nx-1, y, z+1, 15)] = fmax(0.0, f_15);
+ else // at -x+z boundary
+ dev_f_new[grid2index(nx-1, y, 0, 16)] = fmax(0.0, f_15);
+
+ // Edge 16 (+x,-z): Periodic & bounce-back (free slip)
+ if (x < nx-1 && z > 0) // not at boundary
+ dev_f_new[grid2index( x+1, y, z-1, 16)] = fmax(0.0, f_16);
+ else if (x < nx-1) // at -z boundary
+ dev_f_new[grid2index( x+1, y,nz-1, 15)] = fmax(0.0, f_16);
+ else if (z > 0) // at +x boundary
+ dev_f_new[grid2index( 0, y, z-1, 16)] = fmax(0.0, f_16);
+ else // at +x-z boundary
+ dev_f_new[grid2index( 0, y,nz-1, 15)] = fmax(0.0, f_16);
+
+ // Edge 17 (-y,+z): Periodic & bounce-back (free slip)
+ if (y > 0 && z < nz-1) // not at boundary
+ dev_f_new[grid2index( x, y-1, z+1, 17)] = fmax(0.0, f_17);
+ else if (y > 0) // at +z boundary
+ dev_f_new[grid2index( x, y-1, 0, 18)] = fmax(0.0, f_17);
+ else if (z < nz-1) // at -y boundary
+ dev_f_new[grid2index( x,ny-1, z+1, 17)] = fmax(0.0, f_17);
+ else // at -y+z boundary
+ dev_f_new[grid2index( x,ny-1, 0, 18)] = fmax(0.0, f_17);
+
+ // Edge 18 (+y,-z): Periodic & bounce-back (free slip)
+ if (y < ny-1 && z > 0) // not at boundary
+ dev_f_new[grid2index( x, y+1, z-1, 18)] = fmax(0.0, f_18);
+ else if (y < ny-1) // at -z boundary
+ dev_f_new[grid2index( x, y+1, 0, 17)] = fmax(0.0, f_18);
+ else if (z > 0) // at +y boundary
+ dev_f_new[grid2index( x, 0, z+1, 18)] = fmax(0.0, f_18);
+ else // at +y-z boundary
+ dev_f_new[grid2index( x, 0, 0, 17)] = fmax(0.0, f_18);
+
+
+ // Write fluid velocity and density to global memory
+ __syncthreads();
+ dev_v_rho[idx] = MAKE_FLOAT4(v.x, v.y, v.z, rho);
+
+}
+
+#endif
+// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.