diff --git a/src/main/c/compile.sh b/src/main/c/compile.sh index 12cc9cf..377e06d 100644 --- a/src/main/c/compile.sh +++ b/src/main/c/compile.sh @@ -61,12 +61,17 @@ INPUT_FILES="./src/threadpool.c" OUTPUT_FILE="./threadpool.o" gcc $COMPILE_FLAGS -I"$BASE_INCLUDE_DIR" -I"$OS_INCLUDE_DIR" $INPUT_FILES -o $OUTPUT_FILE +COMPILE_FLAGS="-c -fPIC -m64 -mavx -mavx2 -O1" +INPUT_FILES="./src/libfluidsim.c" +OUTPUT_FILE="./libfluidsim.o" +gcc $COMPILE_FLAGS -I"$BASE_INCLUDE_DIR" -I"$OS_INCLUDE_DIR" $INPUT_FILES -o $OUTPUT_FILE + #compile shared object file OUTPUT_FILE="libfluidsim$LIB_ENDING" COMPILE_FLAGS="-shared" -INPUT_FILES="densitystep.o velocitystep.o chunkmask.o threadpool.o" +INPUT_FILES="densitystep.o velocitystep.o chunkmask.o threadpool.o libfluidsim.o" gcc $COMPILE_FLAGS $INPUT_FILES -o $OUTPUT_FILE #move to resources diff --git a/src/main/c/includes/electrosphere_FluidSim.h b/src/main/c/includes/electrosphere_FluidSim.h index ab43af0..261b3e7 100644 --- a/src/main/c/includes/electrosphere_FluidSim.h +++ b/src/main/c/includes/electrosphere_FluidSim.h @@ -16,7 +16,7 @@ extern "C" { #undef electrosphere_FluidSim_LINEARSOLVERTIMES #define electrosphere_FluidSim_LINEARSOLVERTIMES 20L #undef electrosphere_FluidSim_GRAVITY -#define electrosphere_FluidSim_GRAVITY -100.0f +#define electrosphere_FluidSim_GRAVITY 0.0f /* * Class: electrosphere_FluidSim * Method: createThreadpool diff --git a/src/main/c/includes/libfluidsim.h b/src/main/c/includes/libfluidsim.h index 8ffa805..07baad8 100644 --- a/src/main/c/includes/libfluidsim.h +++ b/src/main/c/includes/libfluidsim.h @@ -2,5 +2,15 @@ #ifndef LIB_FLUID_SIM #define LIB_FLUID_SIM +#include "./threadpool.h" + +void simulate(LibraryContext * context, int threadIndex); + +void addDensity(int N, int chunk_mask, float * jrx, float * x0, float dt); + +void diffuseDensity(int N, int chunk_mask, float * jrx, float * jrx0, float DIFFUSION_CONST, float VISCOSITY_CONST, float dt); + +void advectDensity(uint32_t chunk_mask, int N, float * jrd, float * jrd0, float * u, float * v, float * w, float dt); + //close include guard #endif \ No newline at end of file diff --git a/src/main/c/includes/threadpool.h b/src/main/c/includes/threadpool.h index 5691b6d..73ae0a6 100644 --- a/src/main/c/includes/threadpool.h +++ b/src/main/c/includes/threadpool.h @@ -1,6 +1,8 @@ #ifndef THREADPOOL #define THREADPOOL +#include + /** * A threadpool used to distribute work @@ -18,6 +20,7 @@ typedef struct { */ typedef struct { int chunkMask; + float timestep; float * d; float * u; float * v; @@ -26,6 +29,8 @@ typedef struct { float * u0; float * v0; float * w0; + float diffuseConst; + float viscosityConst; } Chunk; diff --git a/src/main/c/src/densitystep.c b/src/main/c/src/densitystep.c index c318aa5..8216786 100644 --- a/src/main/c/src/densitystep.c +++ b/src/main/c/src/densitystep.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,53 +6,35 @@ #include "../includes/utilities.h" #include "../includes/chunkmask.h" -void advectDensity(JNIEnv * env, uint32_t chunk_mask, int N, int b, jobjectArray jrd, jobjectArray d0, float * u, float * v, float * w, float dt); -/* - * Class: electrosphere_FluidSim - * Method: addDensity - * Signature: (II[Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;F)V - */ -JNIEXPORT void JNICALL Java_electrosphere_FluidSim_addDensity - (JNIEnv * env, - jobject this, - jint N, - jint chunk_mask, - jobjectArray jrx, - jobjectArray x0, - jfloat dt){ +void addDensity( + int N, + int chunk_mask, + float * x, + float * s, + float dt){ int i; int size=N*N*N; - float * x = GET_ARR(env,jrx,CENTER_LOC); - float * s = GET_ARR(env,x0,CENTER_LOC); for(i=0; i +#include +#include +#include +#include +#include +#include + +//git libs +#include "../lib/stb/stb_ds.h" + +//all other headers +#include "../includes/libfluidsim.h" +#include "../includes/threadpool.h" +#include "../includes/chunkmask.h" +#include "../includes/utilities.h" + +#define DIM 18 +#define LINEARSOLVERTIMES 20 + + +//call this if the child threads need to wait on one another +void sync(LibraryContext * context){ + pthread_barrier_wait(context->threadpool->barrierMain); +} + +/** + * Main simulation function +*/ +void simulate(LibraryContext * context, int threadIndex){ + int numThreads = context->threadpool->numThreads; + int numChunks = context->numChunks; + + //add densities to chunks + for(int i = threadIndex; i < numChunks; i = i + numThreads){ + Chunk chunk = context->chunks[i]; + addDensity(DIM,chunk.chunkMask,chunk.d,chunk.d0,chunk.timestep); + } + sync(context); + + //diffuse density + for(int l = 0; l < LINEARSOLVERTIMES; l++){ + for(int i = threadIndex; i < numChunks; i = i + numThreads){ + Chunk chunk = context->chunks[i]; + SWAP(chunk.d,chunk.d0); + diffuseDensity( + DIM, + chunk.chunkMask, + chunk.d, + chunk.d0, + chunk.diffuseConst, + chunk.viscosityConst, + chunk.timestep + ); + SWAP(chunk.d,chunk.d0); + } + sync(context); + } + + //advect density + for(int i = threadIndex; i < numChunks; i = i + numThreads){ + Chunk chunk = context->chunks[i]; + advectDensity( + chunk.chunkMask, + DIM, + chunk.d, + chunk.d0, + chunk.u, + chunk.v, + chunk.w, + chunk.timestep + ); + } + + //call this if the child threads need to wait on one another + sync(context); +} \ No newline at end of file diff --git a/src/main/c/src/threadpool.c b/src/main/c/src/threadpool.c index cba4e4b..14ce791 100644 --- a/src/main/c/src/threadpool.c +++ b/src/main/c/src/threadpool.c @@ -17,7 +17,7 @@ #include "../includes/utilities.h" typedef struct { - ThreadPool * threadPool; + LibraryContext * libraryContext; int threadIndex; //the index for this thread in all threadpool objects } ThreadData; @@ -39,6 +39,7 @@ JNIEXPORT jlong JNICALL Java_electrosphere_FluidSim_createThreadpool LibraryContext * libraryContext = (LibraryContext *)malloc(sizeof(LibraryContext)); libraryContext->numChunks = 0; + libraryContext->chunks = NULL; //must be tied to NULL at the start //init threadpool libraryContext->threadpool = (ThreadPool *)malloc(sizeof(ThreadPool)); @@ -71,7 +72,7 @@ JNIEXPORT jlong JNICALL Java_electrosphere_FluidSim_createThreadpool //create data to be sent to thread ThreadData * threadData = (ThreadData *)malloc(sizeof(ThreadData)); - threadData->threadPool = pool; + threadData->libraryContext = libraryContext; threadData->threadIndex = i; //create thread @@ -124,7 +125,6 @@ JNIEXPORT void JNICALL Java_electrosphere_FluidSim_queueChunk( //if the array is full, malloc a new chunk, otherwise overwrite an existing one int arrayCapacity = stbds_arrlen(libraryContext->chunks); if(libraryContext->numChunks >= arrayCapacity){ - printf("%d > %d\n",libraryContext->numChunks,arrayCapacity); Chunk * newChunk = (Chunk *)malloc(sizeof(Chunk)); newChunk->chunkMask = chunkMask; newChunk->u = GET_ARR(env,ur,CENTER_LOC); @@ -134,8 +134,11 @@ JNIEXPORT void JNICALL Java_electrosphere_FluidSim_queueChunk( newChunk->v0 = GET_ARR(env,v0r,CENTER_LOC); newChunk->w0 = GET_ARR(env,w0r,CENTER_LOC); newChunk->d = GET_ARR(env,dr,CENTER_LOC); - stbds_arrput(libraryContext->chunks,newChunk[0]); newChunk->d0 = GET_ARR(env,d0r,CENTER_LOC); + newChunk->timestep = timestep; + newChunk->diffuseConst = DIFFUSION_CONSTANT; + newChunk->viscosityConst = VISCOSITY_CONSTANT; + stbds_arrput(libraryContext->chunks,newChunk[0]); } else { Chunk * currentChunk = &libraryContext->chunks[libraryContext->numChunks]; currentChunk->chunkMask = chunkMask; @@ -147,10 +150,12 @@ JNIEXPORT void JNICALL Java_electrosphere_FluidSim_queueChunk( currentChunk->w0 = GET_ARR(env,w0r,CENTER_LOC); currentChunk->d = GET_ARR(env,dr,CENTER_LOC); currentChunk->d0 = GET_ARR(env,d0r,CENTER_LOC); + currentChunk->timestep = timestep; + currentChunk->diffuseConst = DIFFUSION_CONSTANT; + currentChunk->viscosityConst = VISCOSITY_CONSTANT; } libraryContext->numChunks++; - // arrput(libraryContext->chunks,newChunk); } /* @@ -191,30 +196,26 @@ JNIEXPORT void JNICALL Java_electrosphere_FluidSim_fetchWork( */ void * mainThreadLoop(void * dataRaw){ ThreadData * threadData = (ThreadData *)dataRaw; - ThreadPool * threadPool = threadData->threadPool; + LibraryContext * libraryContext = threadData->libraryContext; int threadIndex = threadData->threadIndex; - printf("thread work\n"); //main thread loop int running = 1; - while(running){ + while(running==1){ //begin work //wait to begin work until parent signals its ready - pthread_barrier_wait(threadPool->barrierWithParentThread); + pthread_barrier_wait(libraryContext->threadpool->barrierWithParentThread); //do main work - - - //call this if the child threads need to wait on one another - pthread_barrier_wait(threadPool->barrierMain); + simulate(libraryContext,threadData->threadIndex); //finalize work //the parent thread needs to call the barrier as well with whatever method it uses to grab data from the sim back to java - pthread_barrier_wait(threadPool->barrierWithParentThread); + pthread_barrier_wait(libraryContext->threadpool->barrierWithParentThread); } diff --git a/src/main/java/electrosphere/FluidSim.java b/src/main/java/electrosphere/FluidSim.java index c4d54f4..44fd007 100644 --- a/src/main/java/electrosphere/FluidSim.java +++ b/src/main/java/electrosphere/FluidSim.java @@ -79,7 +79,8 @@ public class FluidSim { static final int LINEARSOLVERTIMES = 20; - static final float GRAVITY = -100f; + static final float GRAVITY = 0.0f; + // static final float GRAVITY = -100f; //<-- original value public void setup(Vector3i offset){ //allocate buffers for this chunk @@ -713,6 +714,162 @@ public class FluidSim { + + /** + * OLD NATIVE DECLARATIONS + */ + + + + // /** + // * 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 chunkMask, + // ByteBuffer[] x, + // ByteBuffer x0, + // ByteBuffer[] u, + // ByteBuffer[] v, + // ByteBuffer[] w, + // ByteBuffer[] u0, + // ByteBuffer[] v0, + // ByteBuffer[] w0, + // float DIFFUSION_CONSTANT, + // float VISCOSITY_CONSTANT, + // float timestep + // ); + + // private void calculateChunkMaskWrapper(){ + // this.chunkMask = this.calculateChunkMask(density); + // } + // /** + // * Calculates the mask of chunk neighbors + // * @param densityBuffers The neighbor array + // * @return The mask + // */ + // private native int calculateChunkMask(ByteBuffer[] densityBuffers); + + // /** + // * Add vector values to u, v, and w all at once + // */ + // private void addSourceToVectorsWrapper(float timestep){ + // addSourceToVectors(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void addSourceToVectors(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Solves u, v, and w diffusion systems of equations + // */ + // private void solveVectorDiffuseWrapper(float timestep){ + // solveVectorDiffuse(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void solveVectorDiffuse(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Setup projection system + // */ + // private void setupProjectionWrapper(float timestep){ + // setupProjection(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void setupProjection(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Solve projection system + // */ + // private void solveProjectionWrapper(float timestep){ + // solveProjection(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void solveProjection(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Does work like subtracting curl from vector field, setting boundaries, etc + // */ + // private void finalizeProjectionWrapper(float timestep){ + // finalizeProjection(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void finalizeProjection(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Advects vectors + // */ + // private void advectVectorsWrapper(float timestep){ + // advectVectors(DIM, chunkMask, uVector, vVector, wVector, uAdditionVector, vAdditionVector, wAdditionVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void advectVectors(int DIM_X, int chunkMask, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], ByteBuffer u0[], ByteBuffer v0[], ByteBuffer w0[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Adds density to the simulation + // */ + // private void addDensityWrapper(float timestep){ + // addDensity(DIM, chunkMask, density, densityAddition, timestep); + // } + // private native void addDensity(int DIM_X, int chunkMask, ByteBuffer[] x, ByteBuffer[] x0, float timestep); + + // /** + // * Solve density diffusion + // */ + // private void solveDiffuseDensityWrapper(float timestep){ + // solveDiffuseDensity(DIM, chunkMask, density, densityAddition, uVector, vVector, wVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void solveDiffuseDensity(int DIM_X, int chunkMask, ByteBuffer[] x, ByteBuffer[] x0, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + // /** + // * Solve density diffusion + // */ + // private void advectDensityWrapper(float timestep){ + // advectDensity(DIM, chunkMask, density, densityAddition, uVector, vVector, wVector, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep); + // } + // private native void advectDensity(int DIM_X, int chunkMask, ByteBuffer[] x, ByteBuffer[] x0, ByteBuffer[] u, ByteBuffer v[], ByteBuffer w[], float DIFFUSION_CONSTANT, float VISCOSITY_CONSTANT, float timestep); + + + // /** + // * Sets the bounds of the neighbormap to neighbor values if available + // */ + // private void setBoundsToNeighborsWrapper(int vectorDir, ByteBuffer[] neighborMap){ + // setBoundsToNeighbors(DIM, chunkMask, vectorDir, neighborMap); + // } + // private native void setBoundsToNeighbors(int DIM_X, int chunkMask, int vectorDir, ByteBuffer[] neighborMap); + + // /** + // * Sets the bounds of the neighbormap to neighbor values if available, otherwise doesn't mess with them. + // * This is to make sure zeroing out doesn't mess up the sim + // */ + // private void copyNeighborsWrapper(int vectorDir, int x, ByteBuffer[] neighborMap){ + // copyNeighbors(DIM, chunkMask, x, vectorDir, neighborMap); + // } + // private native void copyNeighbors(int DIM_X, int chunkMask, int x, int vectorDir, ByteBuffer[] neighborMap); + + + + + + + + + + + + + + + + + @@ -957,7 +1114,7 @@ public class FluidSim { for(int k = 0; k < DIM; k++){ index = ((i)+(DIM)*(j) + (DIM)*(DIM)*(k)); u0ArrayView[index] = 0; - v0ArrayView[index] = densityArrayView[index] * GRAVITY; + v0ArrayView[index] = 0; w0ArrayView[index] = 0; } } diff --git a/src/main/java/electrosphere/Main.java b/src/main/java/electrosphere/Main.java index e3c064c..c1dd9db 100644 --- a/src/main/java/electrosphere/Main.java +++ b/src/main/java/electrosphere/Main.java @@ -56,7 +56,7 @@ public class Main { //Simulate // FluidSim.unlockThreadsWrapper(); - FluidSim.simChunks(simArray,i,0.01f); + FluidSim.simChunks(simArray,i,0.0001f); FluidSim.unlockThreadsWrapper(); time = time + (System.currentTimeMillis() - lastTime); //