From 8e6b6e4095d32270f82ec10eb346e778c416808a Mon Sep 17 00:00:00 2001 From: unknown <> Date: Sun, 16 Jul 2023 10:14:31 -0400 Subject: [PATCH] C code works! --- .gitignore | 3 +- shared-folder/libfluidsim.dll | Bin 72666 -> 46924 bytes src/main/c/fluidsim.c | 177 ++++---- src/main/c/includes/electrosphere_FluidSim.h | 10 +- src/main/java/electrosphere/FluidSim.java | 433 ++++++++----------- 5 files changed, 270 insertions(+), 353 deletions(-) diff --git a/.gitignore b/.gitignore index 77c9be0..8d0637a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ /.settings /.classpath /.project -/.vscode \ No newline at end of file +/.vscode +/shared-folder \ No newline at end of file diff --git a/shared-folder/libfluidsim.dll b/shared-folder/libfluidsim.dll index 2fbdd2c431177fe768937fbeccd894c50452d0b5..ae966ffa5d04f5551322516203147a0b21c899db 100644 GIT binary patch delta 11445 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 literal 72666 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%0A>o z5b0q}ro#)WOPhzNA4y!=SQx$tbviSqks?Dfk@}0JaeS-vFJVH`xWC8=W*8;8h?z`P zV`~0I)|L9&lDNkCMP(|Fs?ngGUDefOJtHd1z-YG*jjOdsnYb=?(xOtVhvGOIev(Vo z4{8ZHC0ftMS33M0dyc}z7aYF!xHevDt&ye<&+_m!rzS6s_8@IGnD3!$ZIK5jfjDI| zJ~oeb!`KbP6x?6)8odCRLLZ|*W(T{239Jb`jIZb$BlU#aJ)?7a{def-8sVJ%9PZJ1 zz7qYjIz;OSZc})i=>5VJ`WkoX{zbWgmwET{;PyjU`^>%d2UzHMQaX*(5urs-=-|% z�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,jx,&isCopy); - float * x0 = (*env)->GetFloatArrayElements(env,jx0,&isCopy); - float * u = (*env)->GetFloatArrayElements(env,ju,&isCopy); - float * v = (*env)->GetFloatArrayElements(env,jv,&isCopy); - float * w = (*env)->GetFloatArrayElements(env,jw,&isCopy); - float * u0 = (*env)->GetFloatArrayElements(env,ju0,&isCopy); - float * v0 = (*env)->GetFloatArrayElements(env,jv0,&isCopy); - float * w0 = (*env)->GetFloatArrayElements(env,jw0,&isCopy); + float * x = (*env)->GetDirectBufferAddress(env,jx); + float * x0 = (*env)->GetDirectBufferAddress(env,jx0); + float * u = (*env)->GetDirectBufferAddress(env,ju); + float * v = (*env)->GetDirectBufferAddress(env,jv); + float * w = (*env)->GetDirectBufferAddress(env,jw); + float * u0 = (*env)->GetDirectBufferAddress(env,ju0); + float * v0 = (*env)->GetDirectBufferAddress(env,jv0); + float * w0 = (*env)->GetDirectBufferAddress(env,jw0); + int N = DIM_X; + int i,j,k; + // for ( i=1 ; iSetFloatArrayRegion(env,jx,0,DIM_X*DIM_X*DIM_X,x); - (*env)->SetFloatArrayRegion(env,jx0,0,DIM_X*DIM_X*DIM_X,x0); - (*env)->SetFloatArrayRegion(env,ju,0,DIM_X*DIM_X*DIM_X,u); - (*env)->SetFloatArrayRegion(env,jv,0,DIM_X*DIM_X*DIM_X,v); - (*env)->SetFloatArrayRegion(env,jw,0,DIM_X*DIM_X*DIM_X,w); - (*env)->SetFloatArrayRegion(env,ju0,0,DIM_X*DIM_X*DIM_X,u0); - (*env)->SetFloatArrayRegion(env,jv0,0,DIM_X*DIM_X*DIM_X,v0); - (*env)->SetFloatArrayRegion(env,jw0,0,DIM_X*DIM_X*DIM_X,w0); - // for(int i=0; iSetFloatArrayRegion(env,jx,0,DIM_X*DIM_X*DIM_X,x); - // // jx[IX(i,j,k)] = x[IX(i,j,k)]; - // }}} } - - -int main() { - printf("Hello World from Project Panama Baeldung Article"); - return 0; +void add_source(int N, float * x, float * s, float dt){ + int i; + int size=N*N*N; + for(i=0; iN+0.5f) x=N+0.5f; i0=(int)x; i1=i0+1; - if (y<0.5f) y=0.5f; if (y>N+0.5f) y=N+0.5f; j0=(int)y; j1=j0+1; - if (z<0.5f) z=0.5f; if (z>N+0.5f) z=N+0.5f; k0=(int)z; k1=k0+1; + for ( i=1 ; iN+0.5f) x=N+0.5f; i0=(int)x; i1=i0+1; + if (y<0.5f) y=0.5f; if (y>N+0.5f) y=N+0.5f; j0=(int)y; j1=j0+1; + if (z<0.5f) z=0.5f; if (z>N+0.5f) z=N+0.5f; k0=(int)z; k1=k0+1; - s1 = x-i0; s0 = 1-s1; t1 = y-j0; t0 = 1-t1; u1 = z-k0; u0 = 1-u1; - if(i0 >= N){ - i0 = N - 1; - } - if(j0 >= N){ - j0 = N - 1; - } - if(k0 >= N){ - k0 = N - 1; - } - if(i1 >= N){ - i1 = N - 1; - } - if(j1 >= N){ - j1 = N - 1; - } - if(k1 >= N){ - k1 = N - 1; - } - d[IX(i,j,k)] = s0*(t0*u0*d0[IX(i0,j0,k0)]+t1*u0*d0[IX(i0,j1,k0)]+t0*u1*d0[IX(i0,j0,k1)]+t1*u1*d0[IX(i0,j1,k1)])+ - s1*(t0*u0*d0[IX(i1,j0,k0)]+t1*u0*d0[IX(i1,j1,k0)]+t0*u1*d0[IX(i1,j0,k1)]+t1*u1*d0[IX(i1,j1,k1)]); - }}} + s1 = x-i0; s0 = 1-s1; t1 = y-j0; t0 = 1-t1; u1 = z-k0; u0 = 1-u1; + if(i0 >= N){ + i0 = N - 1; + } + // if(i0 < 0){ + // i0 = 0; + // } + if(j0 >= N){ + j0 = N - 1; + } + // if(j0 < 0){ + // j0 = 0; + // } + if(k0 >= N){ + k0 = N - 1; + } + // if(k0 < 0){ + // k0 = 0; + // } + if(i1 >= N){ + i1 = N - 1; + } + // if(i1 < 0){ + // i1 = 0; + // } + if(j1 >= N){ + j1 = N - 1; + } + // if(j1 < 0){ + // j1 = 0; + // } + if(k1 >= N){ + k1 = N - 1; + } + // if(k1 < 0){ + // k1 = 0; + // } + d[IX(i,j,k)] = s0*(t0*u0*d0[IX(i0,j0,k0)]+t1*u0*d0[IX(i0,j1,k0)]+t0*u1*d0[IX(i0,j0,k1)]+t1*u1*d0[IX(i0,j1,k1)])+ + s1*(t0*u0*d0[IX(i1,j0,k0)]+t1*u0*d0[IX(i1,j1,k0)]+t0*u1*d0[IX(i1,j0,k1)]+t1*u1*d0[IX(i1,j1,k1)]); + }}} set_bnd(N, b, d); } + void dens_step(int N, float * x, float * x0, float * u, float * v, float * w, float diff, float dt){ // add_source ( N, x, x0, dt ); - SWAP ( x0, x ); diffuse ( N, 0, x, x0, diff, dt ); - SWAP ( x0, x ); advect ( N, 0, x, x0, u, v, w, dt ); + SWAP(x0, x); + diffuse(N, 0, x, x0, diff, dt); + SWAP(x0, x); + advect(N, 0, x, x0, u, v, w, dt); } void vel_step(int N, float * u, float * v, float * w, float * u0, float * v0, float * w0, float visc, float dt){ - // add_source ( N, u, u0, dt ); add_source ( N, v, v0, dt ); - // SWAP ( u0, u ); diffuse ( N, 1, u, u0, visc, dt ); - // SWAP ( v0, v ); diffuse ( N, 2, v, v0, visc, dt ); - // project ( N, u, v, w, u0, v0 ); - // SWAP ( u0, u ); SWAP ( v0, v ); - // advect ( N, 1, u, u0, u0, v0, dt ); advect ( N, 2, v, v0, u0, v0, dt ); - // project ( N, u, v, w, u0, v0 ); - - // add_source(N, v, x, dt); + add_source(N, u, u0, dt); + add_source(N, v, v0, dt); + add_source(N, w, w0, dt); SWAP(u0, u); diffuse(N, 1, u, u0, visc, dt); SWAP(v0, v); @@ -168,6 +179,7 @@ void project(int N, float * u, float * v, float * w, float * p, float * div){ set_bnd(N, 3, w); } + void lin_solve(int N, int b, float* x, float* x0, float a, float c){ int i, j, k, l; @@ -181,19 +193,6 @@ void lin_solve(int N, int b, float* x, float* x0, float a, float c){ } } -// void set_bnd ( int N, int b, float * x ){ -// int i; -// // for ( i=1 ; i<=N ; i++ ) { -// // x[IX(0 ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)]; -// // x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)]; -// // x[IX(i,0 )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)]; -// // x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)]; -// // } -// // x[IX(0 ,0 )] = 0.5*(x[IX(1,0 )]+x[IX(0 ,1)]); -// // x[IX(0 ,N+1)] = 0.5*(x[IX(1,N+1)]+x[IX(0 ,N )]); -// // x[IX(N+1,0 )] = 0.5*(x[IX(N,0 )]+x[IX(N+1,1)]); -// // x[IX(N+1,N+1)] = 0.5*(x[IX(N,N+1)]+x[IX(N+1,N )]); -// } void set_bnd(int N, int b, float * target){ int DIM = N; diff --git a/src/main/c/includes/electrosphere_FluidSim.h b/src/main/c/includes/electrosphere_FluidSim.h index 146de66..5d87a94 100644 --- a/src/main/c/includes/electrosphere_FluidSim.h +++ b/src/main/c/includes/electrosphere_FluidSim.h @@ -10,20 +10,20 @@ extern "C" { #undef electrosphere_FluidSim_DIM #define electrosphere_FluidSim_DIM 18L #undef electrosphere_FluidSim_DIFFUSION_CONSTANT -#define electrosphere_FluidSim_DIFFUSION_CONSTANT 1.0E-4f +#define electrosphere_FluidSim_DIFFUSION_CONSTANT 0.0f #undef electrosphere_FluidSim_VISCOSITY_CONSTANT -#define electrosphere_FluidSim_VISCOSITY_CONSTANT 1.0E-4f +#define electrosphere_FluidSim_VISCOSITY_CONSTANT 0.0f #undef electrosphere_FluidSim_LINEARSOLVERTIMES #define electrosphere_FluidSim_LINEARSOLVERTIMES 20L #undef electrosphere_FluidSim_GRAVITY -#define electrosphere_FluidSim_GRAVITY -10000.0f +#define electrosphere_FluidSim_GRAVITY -1000.0f /* * Class: electrosphere_FluidSim * Method: simulate - * Signature: (III[F[F[F[F[F[F[F[FFFF)V + * Signature: (IIILjava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;FFF)V */ JNIEXPORT void JNICALL Java_electrosphere_FluidSim_simulate - (JNIEnv *, jobject, jint, jint, jint, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloatArray, jfloat, jfloat, jfloat); + (JNIEnv *, jobject, jint, jint, jint, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jobject, jfloat, jfloat, jfloat); #ifdef __cplusplus } diff --git a/src/main/java/electrosphere/FluidSim.java b/src/main/java/electrosphere/FluidSim.java index 969721b..893634c 100644 --- a/src/main/java/electrosphere/FluidSim.java +++ b/src/main/java/electrosphere/FluidSim.java @@ -3,6 +3,8 @@ package electrosphere; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; import java.nio.file.Files; import java.util.LinkedList; import java.util.List; @@ -26,24 +28,50 @@ public class FluidSim { public static final int DIM = 18; - float[] x = new float[DIM * DIM * DIM]; - float[] x0 = new float[DIM * DIM * DIM]; - float[] u = new float[DIM * DIM * DIM]; - float[] v = new float[DIM * DIM * DIM]; - float[] w = new float[DIM * DIM * DIM]; - float[] u0 = new float[DIM * DIM * DIM]; - float[] v0 = new float[DIM * DIM * DIM]; - float[] w0 = new float[DIM * DIM * DIM]; - float[] jacobiAltArray = new float[DIM * DIM * DIM]; + ByteBuffer x = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer x0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer u = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer v = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer w = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer u0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer v0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); + ByteBuffer w0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4); - static final float DIFFUSION_CONSTANT = 0.0001f; - static final float VISCOSITY_CONSTANT = 0.0001f; + //The densities for every voxel for the current frame + float[] densityArrayView = new float[DIM * DIM * DIM]; + //Should be set to add water to the current frame + float[] density0ArrayView = new float[DIM * DIM * DIM]; + //The force vector for each voxel for the current frame + float[] uArrayView = new float[DIM * DIM * DIM]; + float[] vArrayView = new float[DIM * DIM * DIM]; + float[] wArrayView = new float[DIM * DIM * DIM]; + //these should be set to the + float[] u0ArrayView = new float[DIM * DIM * DIM]; + float[] v0ArrayView = new float[DIM * DIM * DIM]; + float[] w0ArrayView = new float[DIM * DIM * DIM]; + + + static final float DIFFUSION_CONSTANT = 0.0f; + static final float VISCOSITY_CONSTANT = 0.0f; static final int LINEARSOLVERTIMES = 20; - static final float GRAVITY = -10000f; + static final float GRAVITY = -1000f; public void setup(){ + x.order(ByteOrder.LITTLE_ENDIAN); + x0.order(ByteOrder.LITTLE_ENDIAN); + u.order(ByteOrder.LITTLE_ENDIAN); + v.order(ByteOrder.LITTLE_ENDIAN); + w.order(ByteOrder.LITTLE_ENDIAN); + u0.order(ByteOrder.LITTLE_ENDIAN); + v0.order(ByteOrder.LITTLE_ENDIAN); + w0.order(ByteOrder.LITTLE_ENDIAN); + FloatBuffer xf = x.asFloatBuffer(); + FloatBuffer uf = u.asFloatBuffer(); + FloatBuffer vf = v.asFloatBuffer(); + FloatBuffer wf = w.asFloatBuffer(); + Random rand = new Random(1); //make a cube of water in the center for(int i = 0; i < DIM; i++){ @@ -54,10 +82,15 @@ public class FluidSim { Math.abs(8 - j) < 4 && Math.abs(10 - k) < 4 ){ - x[IX(i,j,k)] = 1; - u[IX(i,j,k)] = rand.nextFloat() * 0.1f; - v[IX(i,j,k)] = -1f; - w[IX(i,j,k)] = rand.nextFloat() * 0.1f; + xf.put(1); + uf.put(rand.nextFloat() * 0.1f); + vf.put(-1f); + wf.put(rand.nextFloat() * 0.1f); + } else { + xf.put(0); + uf.put(0); + vf.put(0); + wf.put(0); } } } @@ -68,283 +101,167 @@ public class FluidSim { * Runs a frame of the fluid simulation */ public void simulate(int step, float timestep){ - //diffuse vectors - // moveData(oldData[1], data[1]); - // diffuse(timestep, data[1], oldData[1], 1); - // moveData(oldData[2], data[2]); - // diffuse(timestep, data[2], oldData[2], 2); - // moveData(oldData[3], data[3]); - // diffuse(timestep, data[3], oldData[3], 3); - // //project - // project(data[1],data[2],data[3],oldData[1],oldData[2]); - // moveData(oldData[1], data[1]); - // moveData(oldData[2], data[2]); - // moveData(oldData[3], data[3]); - // //advect vectors - // advect(timestep, 1, 1); - // advect(timestep, 2, 2); - // advect(timestep, 3, 3); - // project(data[1],data[2],data[3],oldData[1],oldData[2]); + // + // Add forces and density here + // + addGravity(); - // //diffuse density - // moveData(oldData[0], data[0]); - // diffuse(timestep, data[0], oldData[0], 0); - // //advect density - // moveData(oldData[0], data[0]); - // advect(timestep, 0, 0); + // + //Performs main fluid simulation logic + // + writeNewStateIntoBuffers(); - if(step % 1500 == 0){ - for(int i = 0; i < 4; i++){ - for(int j = 0; j < 4; j++){ - x[IX(15 - i,15,15 - j)] = 1; - v[IX(15 - i,15,15 - j)] = -1; - } - } + if(x.position() > 0){ + x.position(0); + } + if(x0.position() > 0){ + x0.position(0); + } + if(u.position() > 0){ + u.position(0); + } + if(v.position() > 0){ + v.position(0); + } + if(w.position() > 0){ + w.position(0); + } + if(u0.position() > 0){ + u0.position(0); + } + if(v0.position() > 0){ + v0.position(0); + } + if(w0.position() > 0){ + w0.position(0); } - simulate(DIM, DIM, DIM, x, x0, u, v, w, u0, v0, w0, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); - // vel_step(DIM, DIM, DIM, u, v, w, u0, v0, w0, VISCOSITY_CONSTANT, timestep); + // + //Reads out the results of the fluid sim + // + readDataIntoArrays(); - // dens_step(DIM, DIM, DIM, x, x0, u, v, w, DIFFUSION_CONSTANT, timestep); - - sum(); } - - void lin_solve(int M, int N, int O, int b, float[] x, float[] x0, float a, float c){ - int i, j, k, l; - - // iterate the solver - for ( l=0 ; l 0){ + x.position(0); } - } - - - void diffuse(int M, int N, int O, int b, float[] x, float[] x0, float diff, float dt){ - int max = Math.max(Math.max(M, N), Math.max(N, O)); - float a=dt*diff*max*max*max; - lin_solve(M, N, O, b, x, x0, a, 1+6*a); - } - - void setBounds(float[] target, int b){ - for(int x=1; x < DIM-1; x++){ - for(int y = 1; y < DIM-1; y++){ - //((x)+(DIM)*(y) + (DIM)*(DIM)*(z)) - target[0 + DIM * x + DIM * DIM * y] = b==1 ? -target[1 + DIM * x + DIM * DIM * y] : target[1 + DIM * x + DIM * DIM * y]; - target[IX(DIM-1,x,y)] = b==1 ? -target[IX(DIM-2,x,y)] : target[IX(DIM-2,x,y)]; - target[IX(x,0,y)] = b==2 ? -target[IX(x,1,y)] : target[IX(x,1,y)]; - target[IX(x,DIM-1,y)] = b==2 ? -target[IX(x,DIM-2,y)] : target[IX(x,DIM-2,y)]; - target[IX(x,y,0)] = b==3 ? -target[IX(x,y,1)] : target[IX(x,y,1)]; - target[IX(x,y,DIM-1)] = b==3 ? -target[IX(x,y,DIM-2)] : target[IX(x,y,DIM-2)]; - } + if(u.position() > 0){ + u.position(0); } - for(int x = 1; x < DIM-1; x++){ - target[IX(x,0,0)] = (float)(0.5f * (target[IX(x,1,0)] + target[IX(x,0,1)])); - target[IX(x,DIM-1,0)] = (float)(0.5f * (target[IX(x,DIM-2,0)] + target[IX(x,DIM-1,1)])); - target[IX(x,0,DIM-1)] = (float)(0.5f * (target[IX(x,1,DIM-1)] + target[IX(x,0,DIM-2)])); - target[IX(x,DIM-1,DIM-1)] = (float)(0.5f * (target[IX(x,DIM-2,DIM-1)] + target[IX(x,DIM-1,DIM-2)])); - - target[IX(0,x,0)] = (float)(0.5f * (target[IX(1,x,0)] + target[IX(0,x,1)])); - target[IX(DIM-1,x,0)] = (float)(0.5f * (target[IX(DIM-2,x,0)] + target[IX(DIM-1,x,1)])); - target[IX(0,x,DIM-1)] = (float)(0.5f * (target[IX(1,x,DIM-1)] + target[IX(0,x,DIM-2)])); - target[IX(DIM-1,x,DIM-1)] = (float)(0.5f * (target[IX(DIM-2,x,DIM-1)] + target[IX(DIM-1,x,DIM-2)])); - - - target[IX(0,0,x)] = (float)(0.5f * (target[IX(1,0,x)] + target[IX(0,1,x)])); - target[IX(DIM-1,0,x)] = (float)(0.5f * (target[IX(DIM-2,0,x)] + target[IX(DIM-1,1,x)])); - target[IX(0,DIM-1,x)] = (float)(0.5f * (target[IX(1,DIM-1,x)] + target[IX(0,DIM-2,x)])); - target[IX(DIM-1,DIM-1,x)] = (float)(0.5f * (target[IX(DIM-2,DIM-1,x)] + target[IX(DIM-1,DIM-2,x)])); - + if(v.position() > 0){ + v.position(0); } - target[IX(0,0,0)] = (float)((target[IX(1,0,0)]+target[IX(0,1,0)]+target[IX(0,0,1)])/3.0); - target[IX(DIM-1,0,0)] = (float)((target[IX(DIM-2,0,0)]+target[IX(DIM-1,1,0)]+target[IX(DIM-1,0,1)])/3.0); - target[IX(0,DIM-1,0)] = (float)((target[IX(1,DIM-1,0)]+target[IX(0,DIM-2,0)]+target[IX(0,DIM-1,1)])/3.0); - target[IX(0,0,DIM-1)] = (float)((target[IX(0,0,DIM-2)]+target[IX(1,0,DIM-1)]+target[IX(0,1,DIM-1)])/3.0); - target[IX(DIM-1,DIM-1,0)] = (float)((target[IX(DIM-2,DIM-1,0)]+target[IX(DIM-1,DIM-2,0)]+target[IX(DIM-1,DIM-1,1)])/3.0); - target[IX(0,DIM-1,DIM-1)] = (float)((target[IX(1,DIM-1,DIM-1)]+target[IX(0,DIM-2,DIM-1)]+target[IX(0,DIM-1,DIM-2)])/3.0); - target[IX(DIM-1,0,DIM-1)] = (float)((target[IX(DIM-1,0,DIM-2)]+target[IX(DIM-2,0,DIM-1)]+target[IX(DIM-1,1,DIM-1)])/3.0); - target[IX(DIM-1,DIM-1,DIM-1)] = (float)((target[IX(DIM-1,DIM-1,DIM-2)]+target[IX(DIM-1,DIM-2,DIM-1)]+target[IX(DIM-1,DIM-1,DIM-2)])/3.0); - } - - void advect(int M, int N, int O, int b, float[] d, float[] d0, float[] u, float[] v, float[] w, float dt){ - int i, j, k, i0, j0, k0, i1, j1, k1; - float x, y, z, s0, t0, s1, t1, u1, u0, dtx,dty,dtz; - - dtx=dty=dtz=dt*Math.max(Math.max(M, N), Math.max(N, O)); - - for ( i=1 ; iM+0.5f) x=M+0.5f; i0=(int)x; i1=i0+1; - if (y<0.5f) y=0.5f; if (y>N+0.5f) y=N+0.5f; j0=(int)y; j1=j0+1; - if (z<0.5f) z=0.5f; if (z>O+0.5f) z=O+0.5f; k0=(int)z; k1=k0+1; - - s1 = x-i0; s0 = 1-s1; t1 = y-j0; t0 = 1-t1; u1 = z-k0; u0 = 1-u1; - if(i0 >= DIM){ - i0 = DIM - 1; - } - if(j0 >= DIM){ - j0 = DIM - 1; - } - if(k0 >= DIM){ - k0 = DIM - 1; - } - if(i1 >= DIM){ - i1 = DIM - 1; - } - if(j1 >= DIM){ - j1 = DIM - 1; - } - if(k1 >= DIM){ - k1 = DIM - 1; - } - d[IX(i,j,k)] = s0*(t0*u0*d0[IX(i0,j0,k0)]+t1*u0*d0[IX(i0,j1,k0)]+t0*u1*d0[IX(i0,j0,k1)]+t1*u1*d0[IX(i0,j1,k1)])+ - s1*(t0*u0*d0[IX(i1,j0,k0)]+t1*u0*d0[IX(i1,j1,k0)]+t0*u1*d0[IX(i1,j0,k1)]+t1*u1*d0[IX(i1,j1,k1)]); - }}} - - setBounds(d, b); - } - - void moveData(float[] set1, float[] set2){ - float tmp = 0; - for(int i = 0; i < set1.length; i++){ - tmp = set1[i]; - set1[i] = set2[i]; - set2[i] = tmp; + if(w.position() > 0){ + w.position(0); } - } - - void project(int M, int N, int O, float[] u, float[] v, float[] w, float[] p, float[] div){ - int i, j, k; - - for ( i=1 ; i 0.0f){ - x[IX(i,j,k)] += dt * GRAVITY * density[IX(i,j,k)]; - } - }}} - } - - void vel_step(int M, int N, int O, float[] u, float[] v, float[] w, float[] u0, float[] v0, float[] w0, float visc, float dt ){ - // add_source ( M, N, O, u, u0, dt ); add_source ( M, N, O, v, v0, dt );add_source ( M, N, O, w, w0, dt ); - add_source(M, N, O, v, x, dt); - moveData(u0, u); - diffuse(M, N, O, 1, u, u0, visc, dt); - moveData(v0, v); - diffuse(M, N, O, 2, v, v0, visc, dt); - moveData(w0, w); - diffuse(M, N, O, 3, w, w0, visc, dt); - project(M, N, O, u, v, w, u0, v0); - moveData(u0, u); - moveData(v0, v); - moveData(w0, w); - advect(M, N, O, 1, u, u0, u0, v0, w0, dt); - advect(M, N, O, 2, v, v0, u0, v0, w0, dt); - advect(M, N, O, 3, w, w0, u0, v0, w0, dt); - project(M, N, O, u, v, w, u0, v0); - } - - void sum(){ - double[] sum = new double[8]; for(int i = 0; i < DIM; i++){ for(int j = 0; j < DIM; j++){ for(int k = 0; k < DIM; k++){ - sum[0] = sum[0] + x[IX(i,j,k)]; - sum[1] = sum[1] + u[IX(i,j,k)]; - sum[2] = sum[2] + v[IX(i,j,k)]; - sum[3] = sum[3] + w[IX(i,j,k)]; + densityArrayView[IX(i,j,k)] = x.getFloat(); + uArrayView[IX(i,j,k)] = u.getFloat(); + vArrayView[IX(i,j,k)] = v.getFloat(); + wArrayView[IX(i,j,k)] = w.getFloat(); } } } - // System.out.println(sum[0] + " " + sum[1] + " " + sum[2] + " " + sum[3]); } + /** + * Writes data from the java-side arrays into buffers that get passed into c-side + */ + private void writeNewStateIntoBuffers(){ + if(x0.position() > 0){ + x0.position(0); + } + if(u0.position() > 0){ + u0.position(0); + } + if(v0.position() > 0){ + v0.position(0); + } + if(w0.position() > 0){ + w0.position(0); + } + FloatBuffer x0FloatView = x0.asFloatBuffer(); + FloatBuffer u0FloatView = u0.asFloatBuffer(); + FloatBuffer v0FloatView = v0.asFloatBuffer(); + FloatBuffer w0FloatView = w0.asFloatBuffer(); + for(int i = 0; i < DIM; i++){ + for(int j = 0; j < DIM; j++){ + for(int k = 0; k < DIM; k++){ + x0FloatView.put(density0ArrayView[IX(i,j,k)]); + u0FloatView.put(u0ArrayView[IX(i,j,k)]); + v0FloatView.put(v0ArrayView[IX(i,j,k)]); + w0FloatView.put(w0ArrayView[IX(i,j,k)]); + } + } + } + } + + /** + * Adds gravity to the simulation + */ + private void addGravity(){ + for(int i = 0; i < DIM; i++){ + for(int j = 0; j < DIM; j++){ + for(int k = 0; k < DIM; k++){ + v0ArrayView[IX(i,j,k)] = densityArrayView[IX(i,j,k)] * GRAVITY; + } + } + } + } + + /** + * The native function call to simulate a frame of fluid + * @param DIM_X + * @param DIM_Y + * @param DIM_Z + * @param x + * @param x0 + * @param u + * @param v + * @param w + * @param u0 + * @param v0 + * @param w0 + * @param DIFFUSION_CONSTANT + * @param VISCOSITY_CONSTANT + * @param timestep + */ private native void simulate( int DIM_X, int DIM_Y, int DIM_Z, - float[] x, - float[] x0, - float[] u, - float[] v, - float[] w, - float[] u0, - float[] v0, - float[] w0, + ByteBuffer x, + ByteBuffer x0, + ByteBuffer u, + ByteBuffer v, + ByteBuffer w, + ByteBuffer u0, + ByteBuffer v0, + ByteBuffer w0, float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep ); public float[] getData(){ - return x; + return densityArrayView; } public static final int IX(int x, int y, int z){ return ((x)+(DIM)*(y) + (DIM)*(DIM)*(z)); } - static final int[] vectorOffsetMap = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapXN = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapXP = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapYN = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapYP = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapZN = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static final int[] vectorOffsetMapZP = new int[(DIM - 2) * (DIM - 2) * (DIM - 2)]; - static { - int i = 0; - for(int x = 1; x < DIM - 1; x++){ - for(int y = 1; y < DIM - 1; y++){ - for(int z = 1; z < DIM - 1; z++){ - // if(x != y || y != z){ - vectorOffsetMap[i] = IX(x,y,z); - vectorOffsetMapXN[i] = IX(x-1, y, z); - vectorOffsetMapXP[i] = IX(x+1, y, z); - vectorOffsetMapYN[i] = IX( x,y-1, z); - vectorOffsetMapYP[i] = IX( x,y+1, z); - vectorOffsetMapZN[i] = IX( x, y,z-1); - vectorOffsetMapZP[i] = IX( x, y,z+1); - i++; - // } - } - } - } - } - }