| tBig restructuring, moving towards OO form - sphere - GPU-based 3D discrete ele… | |
| git clone git://src.adamsgaard.dk/sphere | |
| Log | |
| Files | |
| Refs | |
| LICENSE | |
| --- | |
| commit 3a0858de8254872921ec35fc73d9b7a2e6e42e14 | |
| parent 42825a06bb016be6ea4ee40eede9c20ebb1649bc | |
| Author: Anders Damsgaard <[email protected]> | |
| Date: Fri, 26 Oct 2012 16:01:28 +0200 | |
| Big restructuring, moving towards OO form | |
| Diffstat: | |
| M src/constants.cuh | 10 +++++++++- | |
| A src/constants.h | 26 ++++++++++++++++++++++++++ | |
| A src/cuPrintf.cuh | 130 +++++++++++++++++++++++++++++… | |
| M src/datatypes.h | 213 +++++++++--------------------… | |
| A src/debug.h | 14 ++++++++++++++ | |
| M src/file_io.cpp | 660 +++++++++++++++--------------… | |
| M src/main.cpp | 505 ++---------------------------… | |
| A src/sphere.cpp | 180 +++++++++++++++++++++++++++++… | |
| A src/sphere.h | 97 ++++++++++++++++++++++++++++++ | |
| A src/typedefs.h | 34 +++++++++++++++++++++++++++++… | |
| A src/utility.cuh | 9 +++++++++ | |
| 11 files changed, 915 insertions(+), 963 deletions(-) | |
| --- | |
| diff --git a/src/constants.cuh b/src/constants.cuh | |
| t@@ -1,10 +1,18 @@ | |
| #ifndef CONSTANTS_CUH_ | |
| #define CONSTANTS_CUH_ | |
| +#include "datatypes.h" | |
| + | |
| // Most constant memory variables are stored in | |
| // structures, see datatypes.cuh | |
| // Constant memory size: 64 kb | |
| -__constant__ int devC_nc; // Max. number of contacts a part… | |
| +__constant__ unsigned int devC_nd; // Number of dimensions | |
| +__constant__ unsigned int devC_np; // Number of particles | |
| +__constant__ int devC_nc; // Max. number of contacts a particle can… | |
| +// Device constant memory structures | |
| +__constant__ Params devC_params; | |
| +__constant__ Grid devC_grid; | |
| + | |
| #endif | |
| diff --git a/src/constants.h b/src/constants.h | |
| t@@ -0,0 +1,26 @@ | |
| +#ifndef CONSTANTS_H_ | |
| +#define CONSTANTS_H_ | |
| + | |
| +#include "typedefs.h" | |
| + | |
| +//////////////////////// | |
| +// SYMBOLIC CONSTANTS // | |
| +//////////////////////// | |
| + | |
| +// Define the max. number of walls | |
| +#define MAXWALLS 6 | |
| + | |
| + | |
| +const Float PI = 3.14159265358979; | |
| + | |
| +// Number of dimensions (1 and 2 NOT functional) | |
| +const unsigned int ND = 3; | |
| + | |
| +// Define source code version | |
| +const Float VERS = 0.35; | |
| + | |
| +// Max. number of contacts per particle | |
| +//const int NC = 16; | |
| +const int NC = 32; | |
| + | |
| +#endif | |
| diff --git a/src/cuPrintf.cuh b/src/cuPrintf.cuh | |
| t@@ -0,0 +1,130 @@ | |
| +/* | |
| + * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. | |
| + * | |
| + * Please refer to the NVIDIA end user license agreement (EULA) associated | |
| + * with this source code for terms and conditions that govern your use of | |
| + * this software. Any use, reproduction, disclosure, or distribution of | |
| + * this software and related documentation outside the terms of the EULA | |
| + * is strictly prohibited. | |
| + * | |
| + */ | |
| + | |
| +#ifndef CUPRINTF_H | |
| +#define CUPRINTF_H | |
| + | |
| +/* | |
| + * This is the header file supporting cuPrintf.cu and defining both | |
| + * the host and device-side interfaces. See that file for some more | |
| + * explanation and sample use code. See also below for details of the | |
| + * host-side interfaces. | |
| + * | |
| + * Quick sample code: | |
| + * | |
| + #include "cuPrintf.cu" | |
| + | |
| + __global__ void testKernel(int val) | |
| + { | |
| + cuPrintf("Value is: %d\n", val); | |
| + } | |
| + | |
| + int main() | |
| + { | |
| + cudaPrintfInit(); | |
| + testKernel<<< 2, 3 >>>(10); | |
| + cudaPrintfDisplay(stdout, true); | |
| + cudaPrintfEnd(); | |
| + return 0; | |
| + } | |
| + */ | |
| + | |
| +/////////////////////////////////////////////////////////////////////////////// | |
| +// DEVICE SIDE | |
| +// External function definitions for device-side code | |
| + | |
| +// Abuse of templates to simulate varargs | |
| +__device__ int cuPrintf(const char *fmt); | |
| +template <typename T1> __device__ int cuPrintf(const char *fmt, T1 arg1); | |
| +template <typename T1, typename T2> __device__ int cuPrintf(const char *fmt, T… | |
| +template <typename T1, typename T2, typename T3> __device__ int cuPrintf(const… | |
| +template <typename T1, typename T2, typename T3, typename T4> __device__ int c… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5> __d… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5, typ… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5, typ… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5, typ… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5, typ… | |
| +template <typename T1, typename T2, typename T3, typename T4, typename T5, typ… | |
| + | |
| + | |
| +// | |
| +// cuPrintfRestrict | |
| +// | |
| +// Called to restrict output to a given thread/block. Pass | |
| +// the constant CUPRINTF_UNRESTRICTED to unrestrict output | |
| +// for thread/block IDs. Note you can therefore allow | |
| +// "all printfs from block 3" or "printfs from thread 2 | |
| +// on all blocks", or "printfs only from block 1, thread 5". | |
| +// | |
| +// Arguments: | |
| +// threadid - Thread ID to allow printfs from | |
| +// blockid - Block ID to allow printfs from | |
| +// | |
| +// NOTE: Restrictions last between invocations of | |
| +// kernels unless cudaPrintfInit() is called again. | |
| +// | |
| +#define CUPRINTF_UNRESTRICTED -1 | |
| +__device__ void cuPrintfRestrict(int threadid, int blockid); | |
| + | |
| + | |
| + | |
| +/////////////////////////////////////////////////////////////////////////////// | |
| +// HOST SIDE | |
| +// External function definitions for host-side code | |
| + | |
| +// | |
| +// cudaPrintfInit | |
| +// | |
| +// Call this once to initialise the printf system. If the output | |
| +// file or buffer size needs to be changed, call cudaPrintfEnd() | |
| +// before re-calling cudaPrintfInit(). | |
| +// | |
| +// The default size for the buffer is 1 megabyte. For CUDA | |
| +// architecture 1.1 and above, the buffer is filled linearly and | |
| +// is completely used; however for architecture 1.0, the buffer | |
| +// is divided into as many segments are there are threads, even | |
| +// if some threads do not call cuPrintf(). | |
| +// | |
| +// Arguments: | |
| +// bufferLen - Length, in bytes, of total space to reserve | |
| +// (in device global memory) for output. | |
| +// | |
| +// Returns: | |
| +// cudaSuccess if all is well. | |
| +// | |
| +extern "C" cudaError_t cudaPrintfInit(size_t bufferLen=1048576); // 1-meg - … | |
| + | |
| +// | |
| +// cudaPrintfEnd | |
| +// | |
| +// Cleans up all memories allocated by cudaPrintfInit(). | |
| +// Call this at exit, or before calling cudaPrintfInit() again. | |
| +// | |
| +extern "C" void cudaPrintfEnd(); | |
| + | |
| +// | |
| +// cudaPrintfDisplay | |
| +// | |
| +// Dumps the contents of the output buffer to the specified | |
| +// file pointer. If the output pointer is not specified, | |
| +// the default "stdout" is used. | |
| +// | |
| +// Arguments: | |
| +// outputFP - A file pointer to an output stream. | |
| +// showThreadID - If "true", output strings are prefixed | |
| +// by "[blockid, threadid] " at output. | |
| +// | |
| +// Returns: | |
| +// cudaSuccess if all is well. | |
| +// | |
| +extern "C" cudaError_t cudaPrintfDisplay(void *outputFP=NULL, bool showThreadI… | |
| + | |
| +#endif // CUPRINTF_H | |
| diff --git a/src/datatypes.h b/src/datatypes.h | |
| t@@ -1,5 +1,3 @@ | |
| -// datatypes.h -- Structure templates and function prototypes | |
| - | |
| // Avoiding multiple inclusions of header file | |
| #ifndef DATATYPES_H_ | |
| #define DATATYPES_H_ | |
| t@@ -7,171 +5,80 @@ | |
| #include <math.h> | |
| #include "vector_functions.h" | |
| //#include "vector_arithmetic.h" | |
| +#include "typedefs.h" | |
| +#include "constants.h" | |
| + | |
| + | |
| +//////////////////////////// | |
| +// STRUCTURE DECLARATIONS // | |
| +//////////////////////////// | |
| + | |
| +// Structure containing kinematic particle values | |
| +struct Kinematics { | |
| + Float4 *x; // Positions + radii (w) | |
| + Float2 *xysum; // Horizontal distance traveled | |
| + Float4 *vel; // Translational velocities + fixvels (w) | |
| + Float4 *force; // Sums of forces | |
| + Float4 *angpos; // Angular positions | |
| + Float4 *angvel; // Angular velocities | |
| + Float4 *torque; // Sums of torques | |
| +}; | |
| - | |
| -// Enable profiling of kernel runtimes? | |
| -// 0: No (default) | |
| -// 1: Yes | |
| -#define PROFILING 1 | |
| - | |
| -// Output information about contacts to stdout? | |
| -// 0: No (default) | |
| -// 1: Yes | |
| -#define CONTACTINFO 0 | |
| - | |
| - | |
| -////////////////////// | |
| -// TYPE DEFINITIONS // | |
| -////////////////////// | |
| - | |
| -// REMEMBER: When changing the precision below, | |
| -// change values in typedefs.h accordingly. | |
| - | |
| -// Uncomment all five lines below for single precision | |
| -/* | |
| -typedef Float Float; | |
| -typedef Float3 Float3; | |
| -typedef Float4 Float4; | |
| -#define MAKE_FLOAT3(x, y, z) make_Float3(x, y, z) | |
| -#define MAKE_FLOAT4(x, y, z, w) make_Float4(x, y, z, w) | |
| -*/ | |
| - | |
| - | |
| -// Uncomment all five lines below for double precision | |
| -///* | |
| -typedef double Float; | |
| -typedef double2 Float2; | |
| -typedef double3 Float3; | |
| -typedef double4 Float4; | |
| -#define MAKE_FLOAT3(x, y, z) make_double3(x, y, z) | |
| -#define MAKE_FLOAT4(x, y, z, w) make_double4(x, y, z, w) | |
| -//*/ | |
| - | |
| - | |
| -//////////////////////// | |
| -// SYMBOLIC CONSTANTS // | |
| -//////////////////////// | |
| - | |
| -// Define the max. number of walls | |
| -#define MAXWALLS 6 | |
| - | |
| - | |
| -const Float PI = 3.14159265358979; | |
| - | |
| -// Number of dimensions (1 and 2 NOT functional) | |
| -const unsigned int ND = 3; | |
| - | |
| -// Define source code version | |
| -const Float VERS = 0.25; | |
| - | |
| -// Max. number of contacts per particle | |
| -//const int NC = 16; | |
| -const int NC = 32; | |
| - | |
| - | |
| -/////////////////////////// | |
| -// STRUCTURE DECLARATION // | |
| -/////////////////////////// | |
| - | |
| -// Structure containing variable particle parameters | |
| -struct Particles { | |
| - Float *radius; | |
| - Float *k_n; | |
| - Float *k_t; | |
| - Float *k_r; | |
| - Float *gamma_n; | |
| - Float *gamma_t; | |
| - Float *gamma_r; | |
| - Float *mu_s; | |
| - Float *mu_d; | |
| - Float *mu_r; | |
| - Float *rho; | |
| - Float *es_dot; | |
| - Float *ev_dot; | |
| - Float *es; | |
| - Float *ev; | |
| - Float *p; | |
| - Float *m; | |
| - Float *I; | |
| - unsigned int np; | |
| +// Structure containing individual physical particle parameters | |
| +struct Energies { | |
| + Float *es_dot; // Frictional dissipation rates | |
| + Float *es; // Frictional dissipations | |
| + Float *ev_dot; // Viscous dissipation rates | |
| + Float *ev; // Viscous dissipations | |
| + Float *p; // Pressures | |
| + //uint4 *bonds; // Cohesive bonds | |
| }; | |
| // Structure containing grid parameters | |
| struct Grid { | |
| - unsigned int nd; | |
| - Float origo[ND]; | |
| - Float L[ND]; | |
| - unsigned int num[ND]; | |
| + Float origo[ND]; // World coordinate system origo | |
| + Float L[ND]; // World dimensions | |
| + unsigned int num[ND]; // Neighbor-search cells along each axis | |
| + int periodic; // Behavior of boundaries at 1st and 2nd world … | |
| }; | |
| // Structure containing time parameters | |
| struct Time { | |
| - Float dt; | |
| - double current; | |
| - double total; | |
| - Float file_dt; | |
| - unsigned int step_count; | |
| + Float dt; // Computational time step length | |
| + double current; // Current time | |
| + double total; // Total time (at the end of experiment) | |
| + Float file_dt; // Time between output files | |
| + unsigned int step_count; // Number of steps taken at current time | |
| }; | |
| // Structure containing constant, global physical parameters | |
| struct Params { | |
| - int global; | |
| - Float g[ND]; | |
| - Float dt; | |
| - unsigned int np; | |
| - unsigned int nw; | |
| - int wmode[MAXWALLS]; | |
| - Float k_n; | |
| - Float k_t; | |
| - Float k_r; | |
| - Float gamma_n; | |
| - Float gamma_t; | |
| - Float gamma_r; | |
| - Float gamma_wn; | |
| - Float gamma_wt; | |
| - Float gamma_wr; | |
| - Float mu_s; | |
| - Float mu_d; | |
| - Float mu_r; | |
| - Float rho; | |
| - Float kappa; | |
| - Float db; | |
| - Float V_b; | |
| - int periodic; | |
| - unsigned int shearmodel; | |
| + Float g[ND]; // Gravitational acceleration | |
| + Float k_n; // Normal stiffness | |
| + Float k_t; // Tangential stiffness | |
| + Float k_r; // Rotational stiffness | |
| + Float gamma_n; // Normal viscosity | |
| + Float gamma_t; // Tangential viscosity | |
| + Float gamma_r; // Rotational viscosity | |
| + Float mu_s; // Static friction coefficient | |
| + Float mu_d; // Dynamic friction coefficient | |
| + Float mu_r; // Rotational friction coefficient | |
| + Float rho; // Material density | |
| + unsigned int contactmodel; // Inter-particle contact model | |
| + Float kappa; // Capillary bond prefactor | |
| + Float db; // Capillary bond debonding distance | |
| + Float V_b; // Volume of fluid in capillary bond | |
| }; | |
| - | |
| -///////////////////////// | |
| -// PROTOTYPE FUNCTIONS // | |
| -///////////////////////// | |
| -int fwritebin(char *target, Particles *p, | |
| - Float4 *host_x, Float4 *host_vel, | |
| - Float4 *host_angvel, Float4 *host_force, | |
| - Float4 *host_torque, Float4 *host_angpos, | |
| - uint4 *host_bonds, | |
| - Grid *grid, Time *time, Params *params, | |
| - Float4 *host_w_nx, Float4 *host_w_mvfd); | |
| - | |
| -// device.cu | |
| -//extern "C" | |
| -void initializeGPU(void); | |
| - | |
| -//extern "C" | |
| -void gpuMain(Float4* host_x, | |
| - Float4* host_vel, | |
| - Float4* host_acc, | |
| - Float4* host_angvel, | |
| - Float4* host_angacc, | |
| - Float4* host_force, | |
| - Float4* host_torque, | |
| - Float4* host_angpos, | |
| - uint4* host_bonds, | |
| - Particles p, Grid grid, | |
| - Time time, Params params, | |
| - Float4* host_w_nx, | |
| - Float4* host_w_mvfd, | |
| - const char* cwd, | |
| - const char* inputbin); | |
| +// Structure containing wall parameters | |
| +struct Walls { | |
| + unsigned int nw; // Number of walls (<= MAXWALLS) | |
| + int wmode[MAXWALLS]; // Wall modes | |
| + Float4* nx; // Wall normal and position | |
| + Float4* mvfd; // Wall mass, velocity, force and dev. stress | |
| + Float gamma_wn; // Wall normal viscosity | |
| + Float gamma_wt; // Wall tangential viscosity | |
| + Float gamma_wr; // Wall rolling viscosity | |
| +}; | |
| #endif | |
| diff --git a/src/debug.h b/src/debug.h | |
| t@@ -0,0 +1,14 @@ | |
| +#ifndef DEBUG_H_ | |
| +#define DEBUG_H_ | |
| + | |
| +// Enable profiling of kernel runtimes? | |
| +// 0: No (default) | |
| +// 1: Yes | |
| +#define PROFILING 1 | |
| + | |
| +// Output information about contacts to stdout? | |
| +// 0: No (default) | |
| +// 1: Yes | |
| +#define CONTACTINFO 0 | |
| + | |
| +#endif | |
| diff --git a/src/file_io.cpp b/src/file_io.cpp | |
| t@@ -1,348 +1,344 @@ | |
| -#include <stdio.h> // Standard library functions for file input and output | |
| -#include <stdlib.h> // Functions involving memory allocation, process control,… | |
| -#include <unistd.h> // UNIX only: For getcwd | |
| -#include <string.h> // For strerror and strcmp | |
| -#include <cuda.h> | |
| -#include "datatypes.h" | |
| +#include <iostream> | |
| +#include <cstdio> | |
| +#include <cstdlib> | |
| +#include "typedefs.h" | |
| +#include "datatypes.h" | |
| +#include "constants.h" | |
| +#include "sphere.h" | |
| -// Write host variables to target binary file | |
| -// The output format should ALWAYS be double precision, | |
| -// so this function will typecast the data before write | |
| -// if it is single precision. | |
| -int fwritebin(char *target, | |
| - Particles *p, | |
| - Float4 *host_x, | |
| - Float4 *host_vel, | |
| - Float4 *host_angvel, | |
| - Float4 *host_force, | |
| - Float4 *host_torque, | |
| - Float4 *host_angpos, | |
| - uint4 *host_bonds, | |
| - Grid *grid, | |
| - Time *time, | |
| - Params *params, | |
| - Float4 *host_w_nx, | |
| - Float4 *host_w_mvfd) | |
| +// Read DEM data from binary file | |
| +void DEM::readbin(const char *target) | |
| { | |
| - FILE *fp; | |
| - unsigned int u; | |
| - unsigned int j; | |
| + if (verbose == 1) | |
| + std::cout << "reading binary: " << target << '\n'; | |
| + | |
| + int err = 0; | |
| - if ((fp = fopen(target,"wb")) == NULL) { | |
| - printf("Could create output binary file. Bye.\n"); | |
| - return 1; // Return unsuccessful exit status | |
| + // Open input file | |
| + FILE *fp; | |
| + if ((fp = fopen(target, "rb")) == NULL) { | |
| + std::cerr << "Could not read input binary file '" | |
| + << target << "'\n"; | |
| + exit(++err); | |
| } | |
| - // If double precision: Values can be written directly | |
| - if (sizeof(Float) == sizeof(double)) { | |
| + // Read data | |
| + if(fread(&nd, sizeof(nd), 1, fp) != 1) | |
| + exit(++err); // Return unsuccessful exit status | |
| - // World dimensions | |
| - fwrite(&grid->nd, sizeof(grid->nd), 1, fp); | |
| - | |
| - // Number of particles | |
| - fwrite(&p->np, sizeof(p->np), 1, fp); | |
| - | |
| - // Temporal parameters | |
| - fwrite(&time->dt, sizeof(time->dt), 1, fp); | |
| - fwrite(&time->current, sizeof(time->current), 1, fp); | |
| - fwrite(&time->total, sizeof(time->total), 1, fp); | |
| - fwrite(&time->file_dt, sizeof(time->file_dt), 1, fp); | |
| - fwrite(&time->step_count, sizeof(time->step_count), 1, fp); | |
| - | |
| - // World coordinate system origo | |
| - for (u=0; u<grid->nd; ++u) { | |
| - fwrite(&grid->origo[u], sizeof(grid->origo[u]), 1, fp); | |
| - } | |
| - | |
| - // World dimensions | |
| - for (u=0; u<grid->nd; ++u) { | |
| - fwrite(&grid->L[u], sizeof(grid->L[u]), 1, fp); | |
| - } | |
| - | |
| - // Grid cells along each dimension | |
| - for (u=0; u<grid->nd; ++u) { | |
| - fwrite(&grid->num[u], sizeof(grid->num[u]), 1, fp); | |
| - } | |
| - | |
| - // Particle vectors | |
| - for (j=0; j<p->np; ++j) { | |
| - // x-axis | |
| - fwrite(&host_x[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_vel[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_angvel[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_force[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_torque[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_angpos[j].x, sizeof(Float), 1, fp); | |
| - | |
| - // y-axis | |
| - fwrite(&host_x[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_vel[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_angvel[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_force[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_torque[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_angpos[j].y, sizeof(Float), 1, fp); | |
| - | |
| - // z-axis | |
| - fwrite(&host_x[j].z, sizeof(Float), 1, fp); | |
| - fwrite(&host_vel[j].z, sizeof(Float), 1, fp); | |
| - fwrite(&host_angvel[j].z, sizeof(Float), 1, fp); | |
| - fwrite(&host_force[j].z, sizeof(Float), 1, fp); | |
| - fwrite(&host_torque[j].z, sizeof(Float), 1, fp); | |
| - fwrite(&host_angpos[j].z, sizeof(Float), 1, fp); | |
| - } | |
| - | |
| - // Individual particle values | |
| - for (j=0; j<p->np; ++j) { | |
| - fwrite(&host_vel[j].w, sizeof(Float), 1, fp); | |
| - fwrite(&host_x[j].w, sizeof(Float), 1, fp); | |
| - fwrite(&p->radius[j], sizeof(p->radius[j]), 1, fp); | |
| - fwrite(&p->rho[j], sizeof(p->rho[j]), 1, fp); | |
| - fwrite(&p->k_n[j], sizeof(p->k_n[j]), 1, fp); | |
| - fwrite(&p->k_t[j], sizeof(p->k_t[j]), 1, fp); | |
| - fwrite(&p->k_r[j], sizeof(p->k_r[j]), 1, fp); | |
| - fwrite(&p->gamma_n[j], sizeof(p->gamma_n[j]), 1, fp); | |
| - fwrite(&p->gamma_t[j], sizeof(p->gamma_t[j]), 1, fp); | |
| - fwrite(&p->gamma_r[j], sizeof(p->gamma_r[j]), 1, fp); | |
| - fwrite(&p->mu_s[j], sizeof(p->mu_s[j]), 1, fp); | |
| - fwrite(&p->mu_d[j], sizeof(p->mu_d[j]), 1, fp); | |
| - fwrite(&p->mu_r[j], sizeof(p->mu_r[j]), 1, fp); | |
| - fwrite(&p->es_dot[j], sizeof(p->es_dot[j]), 1, fp); | |
| - fwrite(&p->ev_dot[j], sizeof(p->ev_dot[j]), 1, fp); | |
| - fwrite(&p->es[j], sizeof(p->es[j]), 1, fp); | |
| - fwrite(&p->ev[j], sizeof(p->ev[j]), 1, fp); | |
| - fwrite(&p->p[j], sizeof(p->p[j]), 1, fp); | |
| - } | |
| - | |
| - // Singular parameters | |
| - fwrite(¶ms->global, sizeof(params->global), 1, fp); | |
| - for (u=0; u<grid->nd; ++u) { | |
| - fwrite(¶ms->g[u], sizeof(params->g[u]), 1, fp); | |
| - } | |
| - fwrite(¶ms->kappa, sizeof(params->kappa), 1, fp); | |
| - fwrite(¶ms->db, sizeof(params->db), 1, fp); | |
| - fwrite(¶ms->V_b, sizeof(params->V_b), 1, fp); | |
| - fwrite(¶ms->shearmodel, sizeof(params->shearmodel), 1, fp); | |
| - | |
| - // Walls | |
| - fwrite(¶ms->nw, sizeof(params->nw), 1, fp); // No. of walls | |
| - for (j=0; j<params->nw; ++j) { | |
| - fwrite(¶ms->wmode[j], sizeof(params->wmode[j]), 1, fp); | |
| - // Wall normal | |
| - fwrite(&host_w_nx[j].x, sizeof(Float), 1, fp); | |
| - fwrite(&host_w_nx[j].y, sizeof(Float), 1, fp); | |
| - fwrite(&host_w_nx[j].z, sizeof(Float), 1, fp); | |
| - | |
| - fwrite(&host_w_nx[j].w, sizeof(Float), 1, fp); // Wall position | |
| - fwrite(&host_w_mvfd[j].x, sizeof(Float), 1, fp); // Wall mass | |
| - fwrite(&host_w_mvfd[j].y, sizeof(Float), 1, fp); // Wall velocity | |
| - fwrite(&host_w_mvfd[j].z, sizeof(Float), 1, fp); // Wall force | |
| - fwrite(&host_w_mvfd[j].w, sizeof(Float), 1, fp); // Wall deviatoric stre… | |
| - } | |
| - fwrite(¶ms->periodic, sizeof(params->periodic), 1, fp); | |
| - fwrite(¶ms->gamma_wn, sizeof(params->gamma_wn), 1, fp); | |
| - fwrite(¶ms->gamma_wt, sizeof(params->gamma_wt), 1, fp); | |
| - fwrite(¶ms->gamma_wr, sizeof(params->gamma_wr), 1, fp); | |
| - | |
| - | |
| - // Write bond pair values | |
| - for (j=0; j<p->np; ++j) { | |
| - fwrite(&host_bonds[j].x, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].y, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].z, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].w, sizeof(unsigned int), 1, fp); | |
| - } | |
| - | |
| - } else if (sizeof(Float) == sizeof(float)) { | |
| - // Single precision: Type conversion required | |
| - | |
| - double d; // Double precision placeholder | |
| - | |
| - // World dimensions | |
| - fwrite(&grid->nd, sizeof(grid->nd), 1, fp); | |
| - | |
| - // Number of particles | |
| - fwrite(&p->np, sizeof(p->np), 1, fp); | |
| - | |
| - // Temporal parameters | |
| - d = (double)time->dt; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - fwrite(&time->current, sizeof(time->current), 1, fp); | |
| - fwrite(&time->total, sizeof(time->total), 1, fp); | |
| - d = (double)time->file_dt; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - fwrite(&time->step_count, sizeof(time->step_count), 1, fp); | |
| - | |
| - // World coordinate system origo | |
| - for (u=0; u<grid->nd; ++u) { | |
| - d = (double)grid->origo[u]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - | |
| - // World dimensions | |
| - for (u=0; u<grid->nd; ++u) { | |
| - d = (double)grid->L[u]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - | |
| - // Grid cells along each dimension | |
| - for (u=0; u<grid->nd; ++u) { | |
| - fwrite(&grid->num[u], sizeof(grid->num[u]), 1, fp); | |
| - } | |
| - | |
| - // Particle vectors | |
| - for (j=0; j<p->np; ++j) { | |
| - // x-axis | |
| - d = (double)host_x[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_vel[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angvel[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_force[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_torque[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angpos[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - | |
| - // y-axis | |
| - d = (double)host_x[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_vel[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angvel[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_force[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_torque[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angpos[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - | |
| - // z-axis | |
| - d = (double)host_x[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_vel[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angvel[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_force[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_torque[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_angpos[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - | |
| - // Individual particle values | |
| - for (j=0; j<p->np; ++j) { | |
| - d = (double)host_vel[j].w; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_x[j].w; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->radius[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->rho[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->k_n[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->k_t[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->k_r[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->gamma_n[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->gamma_t[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->gamma_r[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->mu_s[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->mu_d[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->mu_r[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->es_dot[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->ev_dot[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->es[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->ev[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)p->p[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - | |
| - // Singular parameters | |
| - fwrite(¶ms->global, sizeof(params->global), 1, fp); | |
| - for (u=0; u<grid->nd; ++u) { | |
| - d = (double)params->g[u]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - d = (double)params->kappa; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)params->db; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)params->V_b; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - fwrite(¶ms->shearmodel, sizeof(params->shearmodel), 1, fp); | |
| - | |
| - // Walls | |
| - fwrite(¶ms->nw, sizeof(params->nw), 1, fp); // No. of walls | |
| - for (j=0; j<params->nw; ++j) { | |
| - | |
| - // Wall mode | |
| - d = (double)params->wmode[j]; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - | |
| - // Wall normal | |
| - d = (double)host_w_nx[j].x; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_nx[j].y; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_nx[j].z; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - | |
| - d = (double)host_w_nx[j].w; // Wall position | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_mvfd[j].x; // Wall mass | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_mvfd[j].y; // Wall velocity | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_mvfd[j].z; // Wall force | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)host_w_mvfd[j].w; // Wall deviatoric stress | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - } | |
| - fwrite(¶ms->periodic, sizeof(params->periodic), 1, fp); | |
| - d = (double)params->gamma_wn; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)params->gamma_wt; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - d = (double)params->gamma_wr; | |
| - fwrite(&d, sizeof(d), 1, fp); | |
| - | |
| - // Write bond pair values | |
| - for (j=0; j<p->np; ++j) { | |
| - fwrite(&host_bonds[j].x, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].y, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].z, sizeof(unsigned int), 1, fp); | |
| - fwrite(&host_bonds[j].w, sizeof(unsigned int), 1, fp); | |
| - } | |
| + if (fread(&np, sizeof(np), 1, fp) != 1) | |
| + exit(++err); // Return unsuccessful exit status | |
| + if (verbose == 1) { | |
| + std::cout << " - Number of dimensions: nd = " << nd << "\n" | |
| + << " - Number of particles: np = " << np << "\n"; | |
| + } | |
| + | |
| + if (nd != ND) { | |
| + std::cerr << "Dimensionality mismatch between dataset and this SPHERE prog… | |
| + << "The dataset is " << nd | |
| + << "D, this SPHERE binary is " << ND << "D.\n" | |
| + << "This execution is terminating.\n"; | |
| + exit(++err); // Return unsuccessful exit status | |
| + } | |
| + // Check precision choice | |
| + if (verbose == 1) | |
| + std::cout << " - Compiled for "; | |
| + if (sizeof(Float) == sizeof(float)) { | |
| + if (verbose == 1) | |
| + std::cout << "single"; | |
| + } else if (sizeof(Float) == sizeof(double)) { | |
| + if (verbose == 1) | |
| + std::cout << "double"; | |
| } else { | |
| - fprintf(stderr, "Error: Chosen floating-point precision is incompatible wi… | |
| - exit(1); | |
| + std::cerr << "Error! Chosen precision not available. Check datatypes.h\n"; | |
| + exit(++err); | |
| + } | |
| + if (verbose == 1) | |
| + std::cout << " precision\n"; | |
| + | |
| + // Read time parameters | |
| + if (fread(&time.dt, sizeof(time.dt), 1, fp) != 1) | |
| + exit(++err); // Return unsuccessful exit status | |
| + if (fread(&time.current, sizeof(time.current), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&time.total, sizeof(time.total), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&time.file_dt, sizeof(time.file_dt), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&time.step_count, sizeof(time.step_count), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Output display parameters to screen | |
| + if (verbose == 1) { | |
| + std::cout << " - Timestep length: time.dt = " | |
| + << time.dt << " s\n" | |
| + << " - Start at time: time.current = " | |
| + << time.current << " s\n" | |
| + << " - Total sim. time: time.total = " | |
| + << time.total << " s\n" | |
| + << " - File output interval: time.file_dt = " | |
| + << time.file_dt << " s\n" | |
| + << " - Start at step count: time.step_count = " | |
| + << time.step_count << "\n"; | |
| + } | |
| + | |
| + // For spatial vectors an array of Float4 vectors is chosen for best fit wit… | |
| + // GPU memory handling. Vector variable structure: ( x, y, z, <empty>). | |
| + // Indexing starts from 0. | |
| + | |
| + // Allocate host arrays | |
| + if (verbose == 1) | |
| + std::cout << "\n Allocating host memory: "; | |
| + // Allocate more host arrays | |
| + k.x = new Float4[np]; | |
| + k.xysum = new Float2[np]; | |
| + k.vel = new Float4[np]; | |
| + k.force = new Float4[np]; | |
| + k.angpos = new Float4[np]; | |
| + k.angvel = new Float4[np]; | |
| + k.torque = new Float4[np]; | |
| + | |
| + e.es_dot = new Float[np]; | |
| + e.es = new Float[np]; | |
| + e.ev_dot = new Float[np]; | |
| + e.ev = new Float[np]; | |
| + e.p = new Float[np]; | |
| + | |
| + if (verbose == 1) | |
| + std::cout << "Done\n"; | |
| + | |
| + if (verbose == 1) | |
| + std::cout << " Reading remaining data from input binary: "; | |
| + | |
| + // Read grid parameters | |
| + if (fread(&grid.origo, sizeof(grid.origo[0]), nd, fp) != nd) | |
| + exit(++err); // Return unsuccessful exit status | |
| + if (fread(&grid.L, sizeof(grid.L[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fread(&grid.num, sizeof(grid.num[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fread(&grid.periodic, sizeof(grid.periodic), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Read kinematic values | |
| + if (fread(&k.x, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.xysum, sizeof(Float2), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.vel, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.force, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.angpos, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.angvel, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&k.torque, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + // mass (m) and inertia (I) are calculated on device | |
| + | |
| + // Read energies | |
| + if (fread(&e.es_dot, sizeof(e.es_dot[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&e.es, sizeof(e.es[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&e.ev_dot, sizeof(e.ev_dot[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&e.ev, sizeof(e.ev[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fread(&e.p, sizeof(e.p[0]), np, fp) != np) | |
| + exit(++err); | |
| + | |
| + // Read constant, global physical parameters | |
| + if (fread(¶ms.g, sizeof(params.g[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fread(¶ms.k_n, sizeof(params.k_n), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.k_t, sizeof(params.k_t), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.k_r, sizeof(params.k_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.gamma_n, sizeof(params.gamma_n), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.gamma_t, sizeof(params.gamma_t), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.gamma_r, sizeof(params.gamma_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.mu_s, sizeof(params.mu_s), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.mu_d, sizeof(params.mu_d), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.mu_r, sizeof(params.mu_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.rho, sizeof(params.rho), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.contactmodel, sizeof(params.contactmodel), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.kappa, sizeof(params.kappa), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.db, sizeof(params.db), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(¶ms.V_b, sizeof(params.V_b), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Read wall parameters | |
| + if (fread(&walls.nw, sizeof(walls.nw), 1, fp) != 1) | |
| + exit(++err); | |
| + // Allocate host memory for walls | |
| + // Wall normal (x,y,z), w: wall position on axis parallel to wall normal | |
| + // Wall mass (x), velocity (y), force (z), and deviatoric stress (w) | |
| + walls.nx = new Float4[walls.nw]; | |
| + walls.mvfd = new Float4[walls.nw]; | |
| + | |
| + if (fread(&walls.wmode, sizeof(walls.wmode[0]), walls.nw, fp) != walls.nw) | |
| + exit(++err); | |
| + if (fread(&walls.nx, sizeof(Float4), walls.nw, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&walls.mvfd, sizeof(Float4), walls.nw, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&walls.gamma_wn, sizeof(walls.gamma_wn), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&walls.gamma_wt, sizeof(walls.gamma_wt), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fread(&walls.gamma_wr, sizeof(walls.gamma_wr), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + | |
| + if (walls.nw > MAXWALLS) { | |
| + std::cerr << "Error; MAXWALLS (" << MAXWALLS << ") in datatypes.h " | |
| + << "is smaller than the number of walls specified in the " | |
| + << "input file (" << walls.nw << ").\n"; | |
| } | |
| fclose(fp); | |
| - // This function returns 0 if it ended without problems, | |
| - // and 1 if there were problems opening the target file. | |
| - return 0; | |
| -} // End of fwritebin(...) | |
| + if (verbose == 1) | |
| + std::cout << "Done\n"; | |
| +} | |
| + | |
| +// Write DEM data to binary file | |
| +void DEM::writebin(const char *target) | |
| +{ | |
| + int err = 0; | |
| + | |
| + // Open output file | |
| + FILE *fp; | |
| + if ((fp = fopen(target, "wb")) == NULL) { | |
| + std::cerr << "could create output binary file '" | |
| + << target << "'.\n"; | |
| + exit(++err); // Return unsuccessful exit status | |
| + } | |
| + | |
| + // If double precision: Values can be written directly | |
| + if (sizeof(Float) == sizeof(double)) { | |
| + | |
| + fwrite(&nd, sizeof(nd), 1, fp); | |
| + fwrite(&np, sizeof(np), 1, fp); | |
| + | |
| + // Write temporal parameters | |
| + if (fwrite(&time.dt, sizeof(time.dt), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&time.current, sizeof(time.current), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&time.total, sizeof(time.total), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&time.file_dt, sizeof(time.file_dt), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&time.step_count, sizeof(time.step_count), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Write grid parameters | |
| + if (fwrite(&grid.origo, sizeof(grid.origo[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fwrite(&grid.L, sizeof(grid.L[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fwrite(&grid.num, sizeof(grid.num[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fwrite(&grid.periodic, sizeof(grid.periodic), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Write kinematic values | |
| + if (fwrite(&k.x, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.xysum, sizeof(Float2), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.vel, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.force, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.angpos, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.angvel, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&k.torque, sizeof(Float4), np, fp) != np) | |
| + exit(++err); | |
| + | |
| + // Write energies | |
| + if (fwrite(&e.es_dot, sizeof(e.es_dot[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&e.es, sizeof(e.es[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&e.ev_dot, sizeof(e.ev_dot[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&e.ev, sizeof(e.ev[0]), np, fp) != np) | |
| + exit(++err); | |
| + if (fwrite(&e.p, sizeof(e.p[0]), np, fp) != np) | |
| + exit(++err); | |
| + | |
| + // Write constant, global physical parameters | |
| + if (fwrite(¶ms.g, sizeof(params.g[0]), nd, fp) != nd) | |
| + exit(++err); | |
| + if (fwrite(¶ms.k_n, sizeof(params.k_n), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.k_t, sizeof(params.k_t), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.k_r, sizeof(params.k_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.gamma_n, sizeof(params.gamma_n), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.gamma_t, sizeof(params.gamma_t), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.gamma_r, sizeof(params.gamma_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.mu_s, sizeof(params.mu_s), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.mu_d, sizeof(params.mu_d), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.mu_r, sizeof(params.mu_r), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.rho, sizeof(params.rho), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.contactmodel, sizeof(params.contactmodel), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.kappa, sizeof(params.kappa), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.db, sizeof(params.db), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(¶ms.V_b, sizeof(params.V_b), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + // Write walls parameters | |
| + if (fwrite(&walls.nw, sizeof(walls.nw), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&walls.wmode, sizeof(walls.wmode[0]), walls.nw, fp) != walls.nw) | |
| + exit(++err); | |
| + if (fwrite(&walls.nx, sizeof(Float4), walls.nw, fp) != walls.nw) | |
| + exit(++err); | |
| + if (fwrite(&walls.mvfd, sizeof(Float4), walls.nw, fp) != walls.nw) | |
| + exit(++err); | |
| + if (fwrite(&walls.gamma_wn, sizeof(walls.gamma_wn), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&walls.gamma_wt, sizeof(walls.gamma_wt), 1, fp) != 1) | |
| + exit(++err); | |
| + if (fwrite(&walls.gamma_wr, sizeof(walls.gamma_wr), 1, fp) != 1) | |
| + exit(++err); | |
| + | |
| + } else { | |
| + std::cerr << "Can't write output when in single precision mode.\n"; | |
| + } | |
| +} | |
| diff --git a/src/main.cpp b/src/main.cpp | |
| t@@ -2,7 +2,8 @@ | |
| /* SPHERE source code by Anders Damsgaard Christensen, 2010-12, */ | |
| /* a 3D Discrete Element Method algorithm with CUDA GPU acceleration. */ | |
| /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
| -// Licence: Gnu Public License (GPL) v. 3. See license.txt. | |
| + | |
| +// Licence: GNU Public License (GPL) v. 3. See license.txt. | |
| // See doc/sphere-doc.pdf for full documentation. | |
| // Compile with GNU make by typing 'make' in the src/ directory. | |
| // SPHERE is called from the command line with './sphere_<architecture> projec… | |
| t@@ -10,16 +11,11 @@ | |
| // Including library files | |
| #include <iostream> | |
| -#include <cstdio> // Standard library functions for file input and output | |
| -#include <stdlib.h> // Functions involving memory allocation, process control,… | |
| -#include <unistd.h> // UNIX only: For getcwd | |
| -#include <string.h> // For strerror and strcmp | |
| -#include <errno.h> // For errno | |
| -#include <math.h> // Basic Floating point mathematical operations | |
| -#include <time.h> // Time and date functions for timer | |
| // Including user files | |
| +#include "constants.h" | |
| #include "datatypes.h" | |
| +#include "sphere.h" | |
| ////////////////// | |
| t@@ -29,488 +25,43 @@ | |
| // successfully, and 1 if an error occured which caused the program to crash. | |
| int main(int argc, char *argv[]) | |
| { | |
| - // Namespace declarations | |
| - using std::cout; | |
| - using std::cerr; | |
| // LOCAL VARIABLE DECLARATIONS | |
| if(!argv[1] || argc != 2) { | |
| - cout << "Error: Specify simulation name from the input/ directory (input b… | |
| - return 1; // Return unsuccessful exit status | |
| - } | |
| - | |
| - unsigned int i,j; // Counter variables | |
| - char file[1000]; // Complete path+filename variable | |
| - FILE *fp; // Declare file pointer | |
| - | |
| - // Host particle variable structure | |
| - Particles p; | |
| - | |
| - // Host grid structure | |
| - Grid grid; | |
| - | |
| - // Host time structure | |
| - Time time; | |
| - | |
| - // Host physical global constants structure | |
| - Params params; | |
| - | |
| - // Read path to current working directory | |
| - char *cwd; | |
| - cwd = getcwd(0, 0); | |
| - if (!cwd) { // Terminate program execution if path is not obtained | |
| - cerr << "Error: getcwd failed: " << strerror(errno) << '\n'; | |
| + std::cerr << "Error: Specify input binary file, e.g. " | |
| + << argv[0] << " input/test.bin\n"; | |
| return 1; // Return unsuccessful exit status | |
| } | |
| - | |
| char *inputbin = argv[1]; // Input binary file read from command line argume… | |
| - // Opening cerenomy with fancy ASCII art | |
| - cout << ".-------------------------------------.\n" | |
| - << "| _ Compiled for " << ND << "D |\n" | |
| - << "| | | |\n" | |
| - << "| ___ _ __ | |__ ___ _ __ ___ |\n" | |
| - << "| / __| '_ \\| '_ \\ / _ \\ '__/ _ \\ |\n" | |
| - << "| \\__ \\ |_) | | | | __/ | | __/ |\n" | |
| - << "| |___/ .__/|_| |_|\\___|_| \\___| |\n" | |
| - << "| | | |\n" | |
| - << "| |_| Version: " << VERS << " |\n" | |
| - << "`-------------------------------------´\n" | |
| - << " Simulation ID:\n" | |
| - << " " << inputbin << "\n" | |
| - << " -------------------------------------\n"; | |
| - | |
| - initializeGPU(); | |
| - | |
| - // Import binary data | |
| - printf("Importing initial data from input/%s.bin:\n",inputbin); | |
| - | |
| - sprintf(file,"%s/input/%s.bin", cwd, inputbin); | |
| - if ((fp = fopen(file,"rb")) == NULL) { | |
| - cout << "Could not read input binary file " << cwd << "/input/" | |
| - << inputbin << ".bin. Bye.\n"; | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - // Read the number of dimensions and particles | |
| - if (fread(&grid.nd, sizeof(grid.nd), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&p.np, sizeof(p.np), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - cout << " - Number of dimensions: grid.nd = " << grid.nd << "\n" | |
| - << " - Number of particles: p.np = " << p.np << "\n"; | |
| - | |
| - if (grid.nd != ND) { | |
| - cout << "Dimensionality mismatch between dataset and this SPHERE program.\… | |
| - << "The dataset is " << grid.nd | |
| - << "D, this SPHERE binary is " << ND << "D.\n" | |
| - << "This execution is terminating.\n"; | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - // Report precision choice | |
| - cout << " - Compiled for "; | |
| - if (sizeof(Float) == sizeof(float)) | |
| - cout << "single"; | |
| - else if (sizeof(Float) == sizeof(double)) | |
| - cout << "double"; | |
| - else { | |
| - cerr << "Error! Chosen precision not available. Check datatypes.h\n"; | |
| - exit(1); | |
| - } | |
| - cout << " precision\n"; | |
| - | |
| - // Read time parameters | |
| - if (fread(&time.dt, sizeof(time.dt), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&time.current, sizeof(time.current), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&time.total, sizeof(time.total), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&time.file_dt, sizeof(time.file_dt), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&time.step_count, sizeof(time.step_count), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Copy timestep length to constant memory structure | |
| - params.dt = time.dt; | |
| - | |
| - // Copy number of particles to constant memory structure | |
| - params.np = p.np; | |
| - | |
| - // Output display parameters to screen | |
| - cout << " - Timestep length: time.dt = " | |
| - << time.dt << " s\n" | |
| - << " - Start at time: time.current = " | |
| - << time.current << " s\n" | |
| - << " - Total sim. time: time.total = " | |
| - << time.total << " s\n" | |
| - << " - File output interval: time.file_dt = " | |
| - << time.file_dt << " s\n" | |
| - << " - Start at step count: time.step_count = " | |
| - << time.step_count << "\n"; | |
| - | |
| - | |
| - // For spatial vectors an array of Float4 vectors is chosen for best fit wit… | |
| - // GPU memory handling. Vector variable structure: ( x, y, z, <empty>). | |
| - // Indexing starts from 0. | |
| - | |
| - // Allocate host arrays | |
| - cout << "\n Allocating host memory: "; | |
| - //grid.origo = new Float[ND]; // Coordinate system origo | |
| - //grid.L = new Float[ND]; // Model world dimensions | |
| - //grid.num = new unsigned int[ND]; // Number of cells in each dimension | |
| - //params.g = new Float[ND]; // Gravitational acceleration … | |
| - p.radius = new Float[p.np]; // Particle radii | |
| - p.rho = new Float[p.np]; // Particle densities | |
| - p.m = new Float[p.np]; // Particle masses | |
| - p.I = new Float[p.np]; // Particle moment of inertia | |
| - p.k_n = new Float[p.np]; // Particle normal stiffnesses | |
| - p.k_t = new Float[p.np]; // Particle shear stiffnesses | |
| - p.k_r = new Float[p.np]; // Particle rolling stiffnesses | |
| - p.gamma_n = new Float[p.np]; // Particle normal viscosity | |
| - p.gamma_t = new Float[p.np]; // Particle shear viscosity | |
| - p.gamma_r = new Float[p.np]; // Particle rolling viscosity | |
| - p.mu_s = new Float[p.np]; // Inter-particle static shear contact … | |
| - p.mu_d = new Float[p.np]; // Inter-particle dynamic shear contact… | |
| - p.mu_r = new Float[p.np]; // Inter-particle rolling contact frict… | |
| - p.es_dot = new Float[p.np]; // Rate of shear energy dissipation | |
| - p.ev_dot = new Float[p.np]; // Rate of viscous energy dissipation | |
| - p.es = new Float[p.np]; // Total shear energy dissipation | |
| - p.ev = new Float[p.np]; // Total viscous energy dissipation | |
| - p.p = new Float[p.np]; // Pressure excerted onto particle | |
| - //params.wmode = new int[MAXWALLS]; // Wall BC's, 0: fixed, 1: devs, 2: v… | |
| - | |
| - // Allocate Float4 host arrays | |
| - Float4 *host_x = new Float4[p.np]; // Center coordinates for each part… | |
| - Float4 *host_vel = new Float4[p.np]; // Particle velocities (dotx = v) | |
| - Float4 *host_acc = new Float4[p.np]; // Particle accellerations (dotdotx… | |
| - Float4 *host_angvel = new Float4[p.np]; // Particle angular velocity vector… | |
| - Float4 *host_angacc = new Float4[p.np]; // Particle angular acceleration ve… | |
| - Float4 *host_force = new Float4[p.np]; // Particle summed force | |
| - Float4 *host_torque = new Float4[p.np]; // Particle summed torque | |
| - Float4 *host_angpos = new Float4[p.np]; // Particle angular position | |
| - | |
| - | |
| - uint4 *host_bonds = new uint4[p.np]; // Bonds from particle [i] to two p… | |
| - cout << "Done\n"; | |
| - | |
| - cout << " Reading remaining data from input binary: "; | |
| - // Read remaining data from input binary | |
| - for (i=0; i<ND; ++i) { | |
| - if (fread(&grid.origo[i], sizeof(grid.origo[i]), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - for (i=0; i<ND; ++i) { | |
| - if (fread(&grid.L[i], sizeof(grid.L[i]), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - for (i=0; i<ND; ++i) { | |
| - if (fread(&grid.num[i], sizeof(grid.num[i]), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - for (j=0; j<p.np; ++j) { | |
| - if (fread(&host_x[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&host_vel[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angvel[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_force[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_torque[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angpos[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - | |
| - if (fread(&host_x[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&host_vel[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angvel[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_force[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_torque[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angpos[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - if (fread(&host_x[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&host_vel[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angvel[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_force[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_torque[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_angpos[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - } | |
| - | |
| - for (j=0; j<p.np; ++j) { | |
| - if (fread(&host_vel[j].w, sizeof(Float), 1, fp) != 1) // Fixvel | |
| - exit(1); // Return unsuccessful exit status | |
| - if (fread(&host_x[j].w, sizeof(Float), 1, fp) != 1) // xsum | |
| - exit(1); | |
| - if (fread(&p.radius[j], sizeof(p.radius[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.rho[j], sizeof(p.rho[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.k_n[j], sizeof(p.k_n[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.k_t[j], sizeof(p.k_t[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.k_r[j], sizeof(p.k_r[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.gamma_n[j], sizeof(p.gamma_n[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.gamma_t[j], sizeof(p.gamma_t[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.gamma_r[j], sizeof(p.gamma_r[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.mu_s[j], sizeof(p.mu_s[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.mu_d[j], sizeof(p.mu_d[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.mu_r[j], sizeof(p.mu_r[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.es_dot[j], sizeof(p.es_dot[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.ev_dot[j], sizeof(p.ev_dot[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.es[j], sizeof(p.es[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.ev[j], sizeof(p.ev[j]), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&p.p[j], sizeof(p.p[j]), 1, fp) != 1) | |
| - exit(1); | |
| - } | |
| - | |
| - if (fread(¶ms.global, sizeof(params.global), 1, fp) != 1) | |
| - exit(1); // Return unsuccessful exit status | |
| - for (i=0; i<ND; ++i) { | |
| - if (fread(¶ms.g[i], sizeof(params.g[i]), 1, fp) != 1) | |
| - exit(1); | |
| - } | |
| - | |
| - if (fread(¶ms.kappa, sizeof(params.kappa), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(¶ms.db, sizeof(params.db), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(¶ms.V_b, sizeof(params.V_b), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(¶ms.shearmodel, sizeof(params.shearmodel), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - | |
| - // Number of dynamic walls | |
| - if (fread(¶ms.nw, sizeof(params.nw), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - if (params.nw > MAXWALLS) { | |
| - cerr << "Error; MAXWALLS (" << MAXWALLS << ") in datatypes.h " | |
| - << "is smaller than the number of walls specified in the " | |
| - << "input file (" << params.nw << ").\n"; | |
| - } | |
| + int verbose = 1; | |
| + int checkVals = 1; | |
| - // Allocate host memory for walls | |
| - // Wall normal (x,y,z), w: wall position on axis parallel to wall normal | |
| - // Wall mass (x), velocity (y), force (z), and deviatoric stress (w) | |
| - Float4 *host_w_nx = new Float4[params.nw]; | |
| - Float4 *host_w_mvfd = new Float4[params.nw]; | |
| - | |
| - // Read wall data | |
| - for (j=0; j<params.nw; ++j) { | |
| - // Wall condition mode: 0: fixed, 1: devs, 2: vel | |
| - if (fread(¶ms.wmode[j], sizeof(params.wmode[j]), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall normal, x-dimension | |
| - if (fread(&host_w_nx[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - // Wall normal, y-dimension | |
| - if (fread(&host_w_nx[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - // Wall normal, z-dimension | |
| - if (fread(&host_w_nx[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall position along axis parallel to wall normal | |
| - if (fread(&host_w_nx[j].w, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall mass | |
| - if (fread(&host_w_mvfd[j].x, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall velocity along axis parallel to wall normal | |
| - if (fread(&host_w_mvfd[j].y, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall force along axis parallel to wall normal | |
| - if (fread(&host_w_mvfd[j].z, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - // Wall deviatoric stress | |
| - if (fread(&host_w_mvfd[j].w, sizeof(Float), 1, fp) != 1) | |
| - exit(1); | |
| - } | |
| - // x- and y boundary behavior. | |
| - // 0: walls, 1: periodic boundaries, 2: x boundary periodic, y frictional wa… | |
| - if (fread(¶ms.periodic, sizeof(params.periodic), 1, fp) != 1) { | |
| - cout << " - x- and y boundaries: Behavior not set, assuming frictional wa… | |
| - params.periodic = 0; | |
| + if (verbose == 1) { | |
| + // Opening cerenomy with fancy ASCII art | |
| + std::cout << ".-------------------------------------.\n" | |
| + << "| _ Compiled for " << ND << "D |\n" | |
| + << "| | | |\n" | |
| + << "| ___ _ __ | |__ ___ _ __ ___ |\n" | |
| + << "| / __| '_ \\| '_ \\ / _ \\ '__/ _ \\ |\n" | |
| + << "| \\__ \\ |_) | | | | __/ | | __/ |\n" | |
| + << "| |___/ .__/|_| |_|\\___|_| \\___| |\n" | |
| + << "| | | |\n" | |
| + << "| |_| Version: " << VERS << " |\n" | |
| + << "`-------------------------------------´\n"; | |
| } | |
| - // Wall viscosities | |
| - if (fread(¶ms.gamma_wn, sizeof(params.gamma_wn), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(¶ms.gamma_wt, sizeof(params.gamma_wt), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(¶ms.gamma_wr, sizeof(params.gamma_wr), 1, fp) != 1) | |
| - exit(1); | |
| - | |
| - | |
| - for (i=0; i<p.np; ++i) { | |
| - if (fread(&host_bonds[i].x, sizeof(unsigned int), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_bonds[i].y, sizeof(unsigned int), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_bonds[i].z, sizeof(unsigned int), 1, fp) != 1) | |
| - exit(1); | |
| - if (fread(&host_bonds[i].w, sizeof(unsigned int), 1, fp) != 1) | |
| - exit(1); | |
| - } | |
| - | |
| - fclose(fp); | |
| - | |
| - cout << "Done\n"; | |
| - | |
| - if (params.shearmodel == 1) | |
| - cout << " - Shear force model: Viscous, fricional\n"; | |
| - else if (params.shearmodel == 2) | |
| - cout << " - Shear force model: Linear elastic, viscous, frictional\n"; | |
| - else if (params.shearmodel == 3) | |
| - cout << " - Shear force model: Nonlinear (Hertzian) elastic, viscous, fri… | |
| - else { | |
| - cerr << "Error: Shear model value not understood.\n"; | |
| - exit(1); | |
| - } | |
| - | |
| - cout << " - Number of dynamic walls: " << params.nw << "\n"; | |
| - | |
| - if (params.periodic == 1) | |
| - cout << " - x- and y boundaries: Periodic\n"; | |
| - else if (params.periodic == 2) | |
| - cout << " - x boundaries: Periodic. y boundaries: Frictional walls\n"; | |
| - else | |
| - cout << " - x- and y boundaries: Frictional walls\n"; | |
| - | |
| - cout << " - Top BC: "; | |
| - if (params.wmode[0] == 0) | |
| - cout << "Fixed\n"; | |
| - else if (params.wmode[0] == 1) | |
| - cout << "Deviatoric stress\n"; | |
| - else if (params.wmode[0] == 2) | |
| - cout << "Velocity\n"; | |
| - else { | |
| - cerr << "Top boundary condition not recognized!\n"; | |
| - exit(1); | |
| - } | |
| - | |
| - if (grid.nd == 1) { | |
| - cout << " - Grid: " | |
| - << grid.num[0] << " cells (x)\n"; | |
| - } else if (grid.nd == 2) { | |
| - cout << " - Grid: " | |
| - << grid.num[0] << " (x) * " | |
| - << grid.num[1] << " (y) = " | |
| - << grid.num[0]*grid.num[1] << " cells\n"; | |
| - } else if (grid.nd == 3) { | |
| - cout << " - Grid: " | |
| - << grid.num[0] << " (x) * " | |
| - << grid.num[1] << " (y) * " | |
| - << grid.num[2] << " (z) = " | |
| - << grid.num[0]*grid.num[1]*grid.num[2] << " cells\n"; | |
| - } else { | |
| - cerr << "\nError; the number of dimensions must be 1, 2 or 3, and was\n" | |
| - << "defined as " << grid.nd << ". This SPHERE binary was compiled for… | |
| - << ND << "D. Bye!\n"; | |
| - exit(1); // Return unsuccessful exit status | |
| - } | |
| - | |
| - cout << "\nEntering the CUDA environment...\n"; | |
| - gpuMain(host_x, | |
| - host_vel, | |
| - host_acc, | |
| - host_angvel, | |
| - host_angacc, | |
| - host_force, | |
| - host_torque, | |
| - host_angpos, | |
| - host_bonds, | |
| - p, grid, | |
| - time, params, | |
| - host_w_nx, | |
| - host_w_mvfd, | |
| - cwd, inputbin); | |
| - | |
| - | |
| - // Free host memory. Delete pointers: | |
| - printf("Liberating host memory: "); | |
| - | |
| - // Particle vectors | |
| - delete[] host_x; | |
| - delete[] host_vel; | |
| - delete[] host_angvel; | |
| - delete[] host_acc; | |
| - delete[] host_angacc; | |
| - delete[] host_force; | |
| - delete[] host_torque; | |
| - delete[] host_angpos; | |
| - | |
| - // Particle bonds | |
| - delete[] host_bonds; | |
| - | |
| - // Particle single-value parameters | |
| - //delete[] grid.origo; | |
| - //delete[] grid.L; | |
| - //delete[] grid.num; | |
| - //delete[] params.g; | |
| - delete[] p.radius; | |
| - delete[] p.k_n; | |
| - delete[] p.k_t; | |
| - delete[] p.k_r; | |
| - delete[] p.gamma_n; | |
| - delete[] p.gamma_t; | |
| - delete[] p.gamma_r; | |
| - delete[] p.mu_s; | |
| - delete[] p.mu_d; | |
| - delete[] p.mu_r; | |
| - delete[] p.rho; | |
| - delete[] p.es_dot; | |
| - delete[] p.ev_dot; | |
| - delete[] p.es; | |
| - delete[] p.ev; | |
| - delete[] p.p; | |
| - | |
| - // Wall arrays | |
| - delete[] host_w_nx; | |
| - delete[] host_w_mvfd; | |
| + std::cout << "Input file: " << inputbin << "\n"; | |
| + | |
| + // Create DEM class, read data from input binary, check values | |
| + DEM dem(inputbin, verbose, checkVals); | |
| - // Free other dynamic host memory | |
| - free(cwd); | |
| - printf("Done\n"); | |
| + // Start iterating through time | |
| + std::cout << "\nStarting time loop...\n"; | |
| + dem.startTime(); | |
| // Terminate execution | |
| - printf("\nBye!\n"); | |
| + std::cout << "\nBye!\n"; | |
| return 0; // Return successfull exit status | |
| } | |
| // END OF FILE | |
| diff --git a/src/sphere.cpp b/src/sphere.cpp | |
| t@@ -0,0 +1,180 @@ | |
| +#include <iostream> | |
| +#include <cstdio> | |
| +#include <cstdlib> | |
| + | |
| +#include "typedefs.h" | |
| +#include "datatypes.h" | |
| +#include "constants.h" | |
| +#include "sphere.h" | |
| + | |
| +// Constructor: Reads an input binary, and optionally checks | |
| +// and reports the values | |
| +DEM::DEM(const char *inputbin, | |
| + const int verbosity, | |
| + const int checkVals) | |
| +: verbose(verbosity) | |
| +{ | |
| + using std::cout; | |
| + using std::cerr; | |
| + | |
| + // Initialize CUDA | |
| + initializeGPU(); | |
| + | |
| + // Read target input binary | |
| + readbin(inputbin); | |
| + | |
| + // Check numeric values of chosen parameters | |
| + if (checkVals == 1) | |
| + checkValues(); | |
| + | |
| + // Report data values | |
| + if (verbose == 1) { | |
| + if (params.contactmodel == 1) | |
| + cout << " - Contact model: Linear-elastic-viscous (n), visco-frictional… | |
| + if (params.contactmodel == 2) | |
| + cout << " - Contact model: Linear-elastic-visco-frictional\n"; | |
| + if (params.contactmodel == 3) | |
| + cout << " - Contact model: Nonlinear-elastic-visco-frictional\n"; | |
| + else { | |
| + cerr << "Error: Contact model value not understood.\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + cout << " - Number of dynamic walls: " << walls.nw << '\n'; | |
| + | |
| + if (grid.periodic == 1) | |
| + cout << " - 1st and 2nd dim. boundaries: Periodic\n"; | |
| + else if (grid.periodic == 2) | |
| + cout << " - 1st dim. boundaries: Visco-frictional walls\n"; | |
| + else | |
| + cout << " - 1st and 2nd dim. boundaries: Visco-frictional walls\n"; | |
| + | |
| + cout << " - Top BC: "; | |
| + if (walls.wmode[0] == 0) | |
| + cout << "Fixed\n"; | |
| + else if (walls.wmode[0] == 1) | |
| + cout << "Deviatoric stress\n"; | |
| + else if (walls.wmode[0] == 2) | |
| + cout << "Velocity\n"; | |
| + else { | |
| + cerr << "Top BC not recognized!\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + cout << " - Grid: "; | |
| + if (nd == 1) | |
| + cout << grid.num[0]; | |
| + else if (nd == 2) | |
| + cout << grid.num[0] << " * " << grid.num[1]; | |
| + else | |
| + cout << grid.num[0] << " * " | |
| + << grid.num[1] << " * " | |
| + << grid.num[2]; | |
| + cout << " cells\n"; | |
| + } | |
| +} | |
| + | |
| +// Destructor: Liberates dynamically allocated host memory | |
| +DEM::~DEM(void) | |
| +{ | |
| + delete[] k.x; | |
| + delete[] k.xysum; | |
| + delete[] k.vel; | |
| + delete[] k.force; | |
| + delete[] k.angpos; | |
| + delete[] k.angvel; | |
| + delete[] k.torque; | |
| + delete[] e.es_dot; | |
| + delete[] e.es; | |
| + delete[] e.ev_dot; | |
| + delete[] e.ev; | |
| + delete[] e.p; | |
| + delete[] walls.nx; | |
| + delete[] walls.mvfd; | |
| +} | |
| + | |
| + | |
| +// Check numeric values of selected parameters | |
| +void DEM::checkValues(void) | |
| +{ | |
| + using std::cerr; | |
| + | |
| + unsigned int i; | |
| + | |
| + // Check the number of dimensions | |
| + if (nd != ND) { | |
| + cerr << "Error: nd = " << nd << ", ND = " << ND << '\n'; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check the number of possible contacts | |
| + if (NC < 1) { | |
| + cerr << "Error: NC = " << NC << '\n'; | |
| + exit(1); | |
| + } else if (NC < 8) { | |
| + cerr << "Warning: NC has a low value (" << NC << "). " | |
| + << "Consider increasing it in 'constants.h'\n"; | |
| + } | |
| + | |
| + // Check that we have a positive number of particles | |
| + if (np < 1) { | |
| + cerr << "Error: np = " << np << '\n'; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check that the current time | |
| + if (time.current < time.total || time.current < 0.0) { | |
| + cerr << "Error: time.current = " << time.current | |
| + << " s, time.total = " << time.total << " s\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check world size | |
| + if (grid.L[0] <= 0.0 || grid.L[1] <= 0.0 || grid.L[2] <= 0.0) { | |
| + cerr << "Error: grid.L[0] = " << grid.L[0] << " m, " | |
| + << "grid.L[1] = " << grid.L[1] << " m, " | |
| + << "grid.L[2] = " << grid.L[2] << " m.\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check grid size | |
| + if (grid.num[0] <= 0 || grid.num[1] <= 0 || grid.num[2] <= 0) { | |
| + cerr << "Error: grid.num[0] = " << grid.num[0] << ", " | |
| + << "grid.num[1] = " << grid.num[1] << ", " | |
| + << "grid.num[2] = " << grid.num[2] << ".\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check grid size again | |
| + if (grid.periodic == 2 && grid.num[0] < 3) { | |
| + cerr << "Error: When 1st dimension boundaries are periodic, " | |
| + << "there must be at least 3 cells in that dimension."; | |
| + exit(1); | |
| + } | |
| + | |
| + if (grid.periodic == 1 && (grid.num[0] < 3 || grid.num[1] < 3)) { | |
| + cerr << "Error: When 1st and 2nd dimension boundaries are periodic, " | |
| + << "there must be at least 3 cells in each of those dimensions."; | |
| + exit(1); | |
| + } | |
| + | |
| + // Check that radii are positive values | |
| + for (i = 0; i < np; ++i) { | |
| + if (k.x[i].w <= 0.0) { | |
| + cerr << "Error: Particle " << i << " has a radius of " | |
| + << k.x[i].w << " m."; | |
| + exit(1); | |
| + } | |
| + } | |
| + | |
| + // Check constant, global parameters | |
| + if (params.k_n <= 0.0) { | |
| + cerr << "Error: k_n = " << params.k_n << " N/m\n"; | |
| + exit(1); | |
| + } | |
| + | |
| + if (params.rho <= 0.0) { | |
| + cerr << "Error: rho = " << params.rho << " kg/m3\n"; | |
| + exit(1); | |
| + } | |
| +} | |
| diff --git a/src/sphere.h b/src/sphere.h | |
| t@@ -0,0 +1,97 @@ | |
| +// Make sure the header is only included once | |
| +#ifndef SPHERE_H_ | |
| +#define SPHERE_H_ | |
| + | |
| +#include "datatypes.h" | |
| + | |
| +// DEM class | |
| +class DEM { | |
| + | |
| + // Values and functions only accessible from the class internally | |
| + private: | |
| + | |
| + // Output level | |
| + int verbose; | |
| + | |
| + // Number of dimensions | |
| + unsigned int nd; | |
| + | |
| + // Number of particles | |
| + unsigned int np; | |
| + | |
| + // Structure containing individual particle kinematics | |
| + Kinematics k; | |
| + Kinematics dev_k; | |
| + | |
| + // Structure containing energy values | |
| + Energies e; | |
| + Energies dev_e; | |
| + | |
| + // Structure of global parameters | |
| + Params params; | |
| + Params dev_params; | |
| + | |
| + // Structure containing spatial parameters | |
| + Grid grid; | |
| + Grid dev_grid; | |
| + | |
| + // Structure of temporal parameters | |
| + Time time; | |
| + Time dev_time; | |
| + | |
| + // Structure of wall parameters | |
| + Walls walls; | |
| + Walls dev_walls; | |
| + | |
| + // Wall force arrays | |
| + Float* dev_w_force; | |
| + | |
| + // GPU initialization, must be called before startTime() | |
| + void initializeGPU(void); | |
| + | |
| + // Copy all constant data to constant device memory | |
| + void transferToConstantDeviceMemory(void); | |
| + | |
| + // Check values stored in constant device memory | |
| + void checkConstantMemory(void); | |
| + | |
| + // Allocate global device memory to hold data | |
| + void allocateGlobalDeviceMemory(void); | |
| + | |
| + // Copy non-constant data to global GPU memory | |
| + void transferToGlobalDeviceMemory(void); | |
| + | |
| + // Copy non-constant data from global GPU memory to host RAM | |
| + void transferFromGlobalDeviceMemory(void); | |
| + | |
| + | |
| + // Values and functions accessible from the outside | |
| + public: | |
| + | |
| + // Constructor, some parameters with default values | |
| + DEM(const char *inputbin, | |
| + const int verbosity = 1, | |
| + const int checkVals = 1); | |
| + | |
| + // Read binary input file | |
| + void readbin(const char *target); | |
| + | |
| + // Write binary output file | |
| + void writebin(const char *target); | |
| + | |
| + // Check numeric values of selected parameters | |
| + void checkValues(void); | |
| + | |
| + // Iterate through time, using temporal limits | |
| + // described in "time" struct. | |
| + void startTime(void); | |
| + | |
| + // Render particles using raytracing | |
| + // render(const char *target, | |
| + // Float3 lookat, | |
| + // Float3 eye, | |
| + // Float focalLength); | |
| + | |
| +}; | |
| + | |
| +#endif | |
| diff --git a/src/typedefs.h b/src/typedefs.h | |
| t@@ -0,0 +1,34 @@ | |
| +#ifndef TYPEDEFS_H_ | |
| +#define TYPEDEFS_H_ | |
| + | |
| +#include "vector_functions.h" | |
| + | |
| +////////////////////// | |
| +// TYPE DEFINITIONS // | |
| +////////////////////// | |
| + | |
| + | |
| +// Uncomment all five lines below for single precision | |
| +/* | |
| +typedef Float Float; | |
| +typedef Float3 Float3; | |
| +typedef Float4 Float4; | |
| +#define MAKE_FLOAT3(x, y, z) make_Float3(x, y, z) | |
| +#define MAKE_FLOAT4(x, y, z, w) make_Float4(x, y, z, w) | |
| +*/ | |
| + | |
| + | |
| +/////// BEWARE: single precision is non-functional at the moment, | |
| +// due to the input algorithm. | |
| + | |
| +// Uncomment all five lines below for double precision | |
| +///* | |
| +typedef double Float; | |
| +typedef double2 Float2; | |
| +typedef double3 Float3; | |
| +typedef double4 Float4; | |
| +#define MAKE_FLOAT3(x, y, z) make_double3(x, y, z) | |
| +#define MAKE_FLOAT4(x, y, z, w) make_double4(x, y, z, w) | |
| +//*/ | |
| + | |
| +#endif | |
| diff --git a/src/utility.cuh b/src/utility.cuh | |
| t@@ -0,0 +1,9 @@ | |
| +// Avoiding multiple inclusions of header file | |
| +#ifndef UTILITY_CUH_ | |
| +#define UTILITY_CUH_ | |
| + | |
| +unsigned int iDivUp(unsigned int a, unsigned int b); | |
| +void checkForCudaErrors(const char* checkpoint_description); | |
| +void checkForCudaErrors(const char* checkpoint_description, const unsigned int… | |
| + | |
| +#endif |