Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

View File

@@ -34,4 +34,3 @@ Download and install the [CUDA Toolkit 12.5](https://developer.nvidia.com/cuda-d
Make sure the dependencies mentioned in [Dependencies]() section above are installed.
## References (for more details)

View File

@@ -30,257 +30,262 @@
#include <algorithm>
enum NBodyConfig {
NBODY_CONFIG_RANDOM,
NBODY_CONFIG_SHELL,
NBODY_CONFIG_EXPAND,
NBODY_NUM_CONFIGS
};
enum NBodyConfig { NBODY_CONFIG_RANDOM, NBODY_CONFIG_SHELL, NBODY_CONFIG_EXPAND, NBODY_NUM_CONFIGS };
enum BodyArray {
BODYSYSTEM_POSITION,
BODYSYSTEM_VELOCITY,
BODYSYSTEM_POSITION,
BODYSYSTEM_VELOCITY,
};
template <typename T>
struct vec3 {
typedef float Type;
}; // dummy
template <>
struct vec3<float> {
typedef float3 Type;
template <typename T> struct vec3
{
typedef float Type;
}; // dummy
template <> struct vec3<float>
{
typedef float3 Type;
};
template <>
struct vec3<double> {
typedef double3 Type;
template <> struct vec3<double>
{
typedef double3 Type;
};
template <typename T>
struct vec4 {
typedef float Type;
}; // dummy
template <>
struct vec4<float> {
typedef float4 Type;
template <typename T> struct vec4
{
typedef float Type;
}; // dummy
template <> struct vec4<float>
{
typedef float4 Type;
};
template <>
struct vec4<double> {
typedef double4 Type;
template <> struct vec4<double>
{
typedef double4 Type;
};
class string;
// BodySystem abstract base class
template <typename T>
class BodySystem {
public: // methods
BodySystem(int numBodies) {}
virtual ~BodySystem() {}
template <typename T> class BodySystem
{
public: // methods
BodySystem(int numBodies) {}
virtual ~BodySystem() {}
virtual void loadTipsyFile(const std::string &filename) = 0;
virtual void loadTipsyFile(const std::string &filename) = 0;
virtual void update(T deltaTime) = 0;
virtual void update(T deltaTime) = 0;
virtual void setSoftening(T softening) = 0;
virtual void setDamping(T damping) = 0;
virtual void setSoftening(T softening) = 0;
virtual void setDamping(T damping) = 0;
virtual T *getArray(BodyArray array) = 0;
virtual void setArray(BodyArray array, const T *data) = 0;
virtual T *getArray(BodyArray array) = 0;
virtual void setArray(BodyArray array, const T *data) = 0;
virtual unsigned int getCurrentReadBuffer() const = 0;
virtual unsigned int getCurrentReadBuffer() const = 0;
virtual unsigned int getNumBodies() const = 0;
virtual unsigned int getNumBodies() const = 0;
virtual void synchronizeThreads() const {};
virtual void synchronizeThreads() const {};
protected: // methods
BodySystem() {} // default constructor
protected: // methods
BodySystem() {} // default constructor
virtual void _initialize(int numBodies) = 0;
virtual void _finalize() = 0;
virtual void _initialize(int numBodies) = 0;
virtual void _finalize() = 0;
};
inline float3 scalevec(float3 &vector, float scalar) {
float3 rt = vector;
rt.x *= scalar;
rt.y *= scalar;
rt.z *= scalar;
return rt;
inline float3 scalevec(float3 &vector, float scalar)
{
float3 rt = vector;
rt.x *= scalar;
rt.y *= scalar;
rt.z *= scalar;
return rt;
}
inline float normalize(float3 &vector) {
float dist =
sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
inline float normalize(float3 &vector)
{
float dist = sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
if (dist > 1e-6) {
vector.x /= dist;
vector.y /= dist;
vector.z /= dist;
}
if (dist > 1e-6) {
vector.x /= dist;
vector.y /= dist;
vector.z /= dist;
}
return dist;
return dist;
}
inline float dot(float3 v0, float3 v1) {
return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z;
}
inline float dot(float3 v0, float3 v1) { return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z; }
inline float3 cross(float3 v0, float3 v1) {
float3 rt;
rt.x = v0.y * v1.z - v0.z * v1.y;
rt.y = v0.z * v1.x - v0.x * v1.z;
rt.z = v0.x * v1.y - v0.y * v1.x;
return rt;
inline float3 cross(float3 v0, float3 v1)
{
float3 rt;
rt.x = v0.y * v1.z - v0.z * v1.y;
rt.y = v0.z * v1.x - v0.x * v1.z;
rt.z = v0.x * v1.y - v0.y * v1.x;
return rt;
}
// utility function
template <typename T>
void randomizeBodies(NBodyConfig config, T *pos, T *vel, float *color,
float clusterScale, float velocityScale, int numBodies,
bool vec4vel) {
switch (config) {
void randomizeBodies(NBodyConfig config,
T *pos,
T *vel,
float *color,
float clusterScale,
float velocityScale,
int numBodies,
bool vec4vel)
{
switch (config) {
default:
case NBODY_CONFIG_RANDOM: {
float scale = clusterScale * std::max<float>(1.0f, numBodies / (1024.0f));
float vscale = velocityScale * scale;
float scale = clusterScale * std::max<float>(1.0f, numBodies / (1024.0f));
float vscale = velocityScale * scale;
int p = 0, v = 0;
int i = 0;
int p = 0, v = 0;
int i = 0;
while (i < numBodies) {
float3 point;
// const int scale = 16;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
while (i < numBodies) {
float3 point;
// const int scale = 16;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
float3 velocity;
velocity.x = rand() / (float)RAND_MAX * 2 - 1;
velocity.y = rand() / (float)RAND_MAX * 2 - 1;
velocity.z = rand() / (float)RAND_MAX * 2 - 1;
lenSqr = dot(velocity, velocity);
float3 velocity;
velocity.x = rand() / (float)RAND_MAX * 2 - 1;
velocity.y = rand() / (float)RAND_MAX * 2 - 1;
velocity.z = rand() / (float)RAND_MAX * 2 - 1;
lenSqr = dot(velocity, velocity);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = velocity.x * vscale; // pos.x
vel[v++] = velocity.y * vscale; // pos.x
vel[v++] = velocity.z * vscale; // pos.x
vel[v++] = velocity.x * vscale; // pos.x
vel[v++] = velocity.y * vscale; // pos.x
vel[v++] = velocity.z * vscale; // pos.x
if (vec4vel) vel[v++] = 1.0f; // inverse mass
if (vec4vel)
vel[v++] = 1.0f; // inverse mass
i++;
}
i++;
}
} break;
case NBODY_CONFIG_SHELL: {
float scale = clusterScale;
float vscale = scale * velocityScale;
float inner = 2.5f * scale;
float outer = 4.0f * scale;
float scale = clusterScale;
float vscale = scale * velocityScale;
float inner = 2.5f * scale;
float outer = 4.0f * scale;
int p = 0, v = 0;
int i = 0;
int p = 0, v = 0;
int i = 0;
while (i < numBodies) // for(int i=0; i < numBodies; i++)
{
float x, y, z;
x = rand() / (float)RAND_MAX * 2 - 1;
y = rand() / (float)RAND_MAX * 2 - 1;
z = rand() / (float)RAND_MAX * 2 - 1;
while (i < numBodies) // for(int i=0; i < numBodies; i++)
{
float x, y, z;
x = rand() / (float)RAND_MAX * 2 - 1;
y = rand() / (float)RAND_MAX * 2 - 1;
z = rand() / (float)RAND_MAX * 2 - 1;
float3 point = {x, y, z};
float len = normalize(point);
float3 point = {x, y, z};
float len = normalize(point);
if (len > 1) continue;
if (len > 1)
continue;
pos[p++] =
point.x * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] =
point.y * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] =
point.z * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = 1.0f;
pos[p++] = point.x * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = point.y * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = point.z * (inner + (outer - inner) * rand() / (float)RAND_MAX);
pos[p++] = 1.0f;
x = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
y = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
z = 1.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
float3 axis = {x, y, z};
normalize(axis);
x = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
y = 0.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
z = 1.0f; // * (rand() / (float) RAND_MAX * 2 - 1);
float3 axis = {x, y, z};
normalize(axis);
if (1 - dot(point, axis) < 1e-6) {
axis.x = point.y;
axis.y = point.x;
normalize(axis);
if (1 - dot(point, axis) < 1e-6) {
axis.x = point.y;
axis.y = point.x;
normalize(axis);
}
// if (point.y < 0) axis = scalevec(axis, -1);
float3 vv = {(float)pos[4 * i], (float)pos[4 * i + 1], (float)pos[4 * i + 2]};
vv = cross(vv, axis);
vel[v++] = vv.x * vscale;
vel[v++] = vv.y * vscale;
vel[v++] = vv.z * vscale;
if (vec4vel)
vel[v++] = 1.0f;
i++;
}
// if (point.y < 0) axis = scalevec(axis, -1);
float3 vv = {(float)pos[4 * i], (float)pos[4 * i + 1],
(float)pos[4 * i + 2]};
vv = cross(vv, axis);
vel[v++] = vv.x * vscale;
vel[v++] = vv.y * vscale;
vel[v++] = vv.z * vscale;
if (vec4vel) vel[v++] = 1.0f;
i++;
}
} break;
case NBODY_CONFIG_EXPAND: {
float scale = clusterScale * numBodies / (1024.f);
float scale = clusterScale * numBodies / (1024.f);
if (scale < 1.0f) scale = clusterScale;
if (scale < 1.0f)
scale = clusterScale;
float vscale = scale * velocityScale;
float vscale = scale * velocityScale;
int p = 0, v = 0;
int p = 0, v = 0;
for (int i = 0; i < numBodies;) {
float3 point;
for (int i = 0; i < numBodies;) {
float3 point;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
point.x = rand() / (float)RAND_MAX * 2 - 1;
point.y = rand() / (float)RAND_MAX * 2 - 1;
point.z = rand() / (float)RAND_MAX * 2 - 1;
float lenSqr = dot(point, point);
float lenSqr = dot(point, point);
if (lenSqr > 1) continue;
if (lenSqr > 1)
continue;
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = point.x * vscale; // pos.x
vel[v++] = point.y * vscale; // pos.x
vel[v++] = point.z * vscale; // pos.x
pos[p++] = point.x * scale; // pos.x
pos[p++] = point.y * scale; // pos.y
pos[p++] = point.z * scale; // pos.z
pos[p++] = 1.0f; // mass
vel[v++] = point.x * vscale; // pos.x
vel[v++] = point.y * vscale; // pos.x
vel[v++] = point.z * vscale; // pos.x
if (vec4vel) vel[v++] = 1.0f; // inverse mass
if (vec4vel)
vel[v++] = 1.0f; // inverse mass
i++;
}
i++;
}
} break;
}
if (color) {
int v = 0;
for (int i = 0; i < numBodies; i++) {
// const int scale = 16;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = 1.0f;
}
}
if (color) {
int v = 0;
for (int i = 0; i < numBodies; i++) {
// const int scale = 16;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = rand() / (float)RAND_MAX;
color[v++] = 1.0f;
}
}
}
#endif // __BODYSYSTEM_H__
#endif // __BODYSYSTEM_H__

View File

@@ -31,49 +31,47 @@
#include "bodysystem.h"
// CPU Body System
template <typename T>
class BodySystemCPU : public BodySystem<T> {
public:
BodySystemCPU(int numBodies);
virtual ~BodySystemCPU();
template <typename T> class BodySystemCPU : public BodySystem<T>
{
public:
BodySystemCPU(int numBodies);
virtual ~BodySystemCPU();
virtual void loadTipsyFile(const std::string &filename);
virtual void loadTipsyFile(const std::string &filename);
virtual void update(T deltaTime);
virtual void update(T deltaTime);
virtual void setSoftening(T softening) {
m_softeningSquared = softening * softening;
}
virtual void setDamping(T damping) { m_damping = damping; }
virtual void setSoftening(T softening) { m_softeningSquared = softening * softening; }
virtual void setDamping(T damping) { m_damping = damping; }
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual unsigned int getCurrentReadBuffer() const { return 0; }
virtual unsigned int getCurrentReadBuffer() const { return 0; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
protected: // methods
BodySystemCPU() {} // default constructor
protected: // methods
BodySystemCPU() {} // default constructor
virtual void _initialize(int numBodies);
virtual void _finalize();
virtual void _initialize(int numBodies);
virtual void _finalize();
void _computeNBodyGravitation();
void _integrateNBodySystem(T deltaTime);
void _computeNBodyGravitation();
void _integrateNBodySystem(T deltaTime);
protected: // data
int m_numBodies;
bool m_bInitialized;
protected: // data
int m_numBodies;
bool m_bInitialized;
T *m_pos;
T *m_vel;
T *m_force;
T *m_pos;
T *m_vel;
T *m_force;
T m_softeningSquared;
T m_damping;
T m_softeningSquared;
T m_damping;
};
#include "bodysystemcpu_impl.h"
#endif // __BODYSYSTEMCPU_H__
#endif // __BODYSYSTEMCPU_H__

View File

@@ -25,15 +25,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bodysystemcpu.h"
#include <assert.h>
#include <memory.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <helper_cuda.h>
#include <algorithm>
#include <assert.h>
#include <helper_cuda.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "bodysystemcpu.h"
#include "tipsy.h"
#ifdef OPENMP
@@ -42,239 +42,229 @@
template <typename T>
BodySystemCPU<T>::BodySystemCPU(int numBodies)
: m_numBodies(numBodies),
m_bInitialized(false),
m_force(0),
m_softeningSquared(.00125f),
m_damping(0.995f) {
m_pos = 0;
m_vel = 0;
: m_numBodies(numBodies)
, m_bInitialized(false)
, m_force(0)
, m_softeningSquared(.00125f)
, m_damping(0.995f)
{
m_pos = 0;
m_vel = 0;
_initialize(numBodies);
_initialize(numBodies);
}
template <typename T>
BodySystemCPU<T>::~BodySystemCPU() {
_finalize();
m_numBodies = 0;
template <typename T> BodySystemCPU<T>::~BodySystemCPU()
{
_finalize();
m_numBodies = 0;
}
template <typename T>
void BodySystemCPU<T>::_initialize(int numBodies) {
assert(!m_bInitialized);
template <typename T> void BodySystemCPU<T>::_initialize(int numBodies)
{
assert(!m_bInitialized);
m_numBodies = numBodies;
m_numBodies = numBodies;
m_pos = new T[m_numBodies * 4];
m_vel = new T[m_numBodies * 4];
m_force = new T[m_numBodies * 3];
m_pos = new T[m_numBodies * 4];
m_vel = new T[m_numBodies * 4];
m_force = new T[m_numBodies * 3];
memset(m_pos, 0, m_numBodies * 4 * sizeof(T));
memset(m_vel, 0, m_numBodies * 4 * sizeof(T));
memset(m_force, 0, m_numBodies * 3 * sizeof(T));
memset(m_pos, 0, m_numBodies * 4 * sizeof(T));
memset(m_vel, 0, m_numBodies * 4 * sizeof(T));
memset(m_force, 0, m_numBodies * 3 * sizeof(T));
m_bInitialized = true;
m_bInitialized = true;
}
template <typename T>
void BodySystemCPU<T>::_finalize() {
assert(m_bInitialized);
template <typename T> void BodySystemCPU<T>::_finalize()
{
assert(m_bInitialized);
delete[] m_pos;
delete[] m_vel;
delete[] m_force;
delete[] m_pos;
delete[] m_vel;
delete[] m_force;
m_bInitialized = false;
m_bInitialized = false;
}
template <typename T>
void BodySystemCPU<T>::loadTipsyFile(const std::string &filename) {
if (m_bInitialized) _finalize();
template <typename T> void BodySystemCPU<T>::loadTipsyFile(const std::string &filename)
{
if (m_bInitialized)
_finalize();
vector<typename vec4<T>::Type> positions;
vector<typename vec4<T>::Type> velocities;
vector<int> ids;
vector<typename vec4<T>::Type> positions;
vector<typename vec4<T>::Type> velocities;
vector<int> ids;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst,
nSecond, nThird);
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst, nSecond, nThird);
_initialize(nBodies);
_initialize(nBodies);
memcpy(m_pos, &positions[0], sizeof(vec4<T>) * nBodies);
memcpy(m_vel, &velocities[0], sizeof(vec4<T>) * nBodies);
memcpy(m_pos, &positions[0], sizeof(vec4<T>) * nBodies);
memcpy(m_vel, &velocities[0], sizeof(vec4<T>) * nBodies);
}
template <typename T>
void BodySystemCPU<T>::update(T deltaTime) {
assert(m_bInitialized);
template <typename T> void BodySystemCPU<T>::update(T deltaTime)
{
assert(m_bInitialized);
_integrateNBodySystem(deltaTime);
_integrateNBodySystem(deltaTime);
// std::swap(m_currentRead, m_currentWrite);
// std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
T *BodySystemCPU<T>::getArray(BodyArray array) {
assert(m_bInitialized);
template <typename T> T *BodySystemCPU<T>::getArray(BodyArray array)
{
assert(m_bInitialized);
T *data = 0;
T *data = 0;
switch (array) {
switch (array) {
default:
case BODYSYSTEM_POSITION:
data = m_pos;
break;
data = m_pos;
break;
case BODYSYSTEM_VELOCITY:
data = m_vel;
break;
}
return data;
}
template <typename T>
void BodySystemCPU<T>::setArray(BodyArray array, const T *data) {
assert(m_bInitialized);
T *target = 0;
switch (array) {
default:
case BODYSYSTEM_POSITION:
target = m_pos;
break;
case BODYSYSTEM_VELOCITY:
target = m_vel;
break;
}
memcpy(target, data, m_numBodies * 4 * sizeof(T));
}
template <typename T>
T sqrt_T(T x) {
return sqrt(x);
}
template <>
float sqrt_T<float>(float x) {
return sqrtf(x);
}
template <typename T>
void bodyBodyInteraction(T accel[3], T posMass0[4], T posMass1[4],
T softeningSquared) {
T r[3];
// r_01 [3 FLOPS]
r[0] = posMass1[0] - posMass0[0];
r[1] = posMass1[1] - posMass0[1];
r[2] = posMass1[2] - posMass0[2];
// d^2 + e^2 [6 FLOPS]
T distSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
distSqr += softeningSquared;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = (T)1.0 / (T)sqrt((double)distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = posMass1[3] * invDistCube;
// (m_1 * r_01) / (d^2 + e^2)^(3/2) [6 FLOPS]
accel[0] += r[0] * s;
accel[1] += r[1] * s;
accel[2] += r[2] * s;
}
template <typename T>
void BodySystemCPU<T>::_computeNBodyGravitation() {
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; i++) {
int indexForce = 3 * i;
T acc[3] = {0, 0, 0};
// We unroll this loop 4X for a small performance boost.
int j = 0;
while (j < m_numBodies) {
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j],
m_softeningSquared);
j++;
data = m_vel;
break;
}
m_force[indexForce] = acc[0];
m_force[indexForce + 1] = acc[1];
m_force[indexForce + 2] = acc[2];
}
return data;
}
template <typename T>
void BodySystemCPU<T>::_integrateNBodySystem(T deltaTime) {
_computeNBodyGravitation();
template <typename T> void BodySystemCPU<T>::setArray(BodyArray array, const T *data)
{
assert(m_bInitialized);
T *target = 0;
switch (array) {
default:
case BODYSYSTEM_POSITION:
target = m_pos;
break;
case BODYSYSTEM_VELOCITY:
target = m_vel;
break;
}
memcpy(target, data, m_numBodies * 4 * sizeof(T));
}
template <typename T> T sqrt_T(T x) { return sqrt(x); }
template <> float sqrt_T<float>(float x) { return sqrtf(x); }
template <typename T> void bodyBodyInteraction(T accel[3], T posMass0[4], T posMass1[4], T softeningSquared)
{
T r[3];
// r_01 [3 FLOPS]
r[0] = posMass1[0] - posMass0[0];
r[1] = posMass1[1] - posMass0[1];
r[2] = posMass1[2] - posMass0[2];
// d^2 + e^2 [6 FLOPS]
T distSqr = r[0] * r[0] + r[1] * r[1] + r[2] * r[2];
distSqr += softeningSquared;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = (T)1.0 / (T)sqrt((double)distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = posMass1[3] * invDistCube;
// (m_1 * r_01) / (d^2 + e^2)^(3/2) [6 FLOPS]
accel[0] += r[0] * s;
accel[1] += r[1] * s;
accel[2] += r[2] * s;
}
template <typename T> void BodySystemCPU<T>::_computeNBodyGravitation()
{
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; i++) {
int indexForce = 3 * i;
T acc[3] = {0, 0, 0};
// We unroll this loop 4X for a small performance boost.
int j = 0;
while (j < m_numBodies) {
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
bodyBodyInteraction<T>(acc, &m_pos[4 * i], &m_pos[4 * j], m_softeningSquared);
j++;
}
m_force[indexForce] = acc[0];
m_force[indexForce + 1] = acc[1];
m_force[indexForce + 2] = acc[2];
}
}
template <typename T> void BodySystemCPU<T>::_integrateNBodySystem(T deltaTime)
{
_computeNBodyGravitation();
#ifdef OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < m_numBodies; ++i) {
int index = 4 * i;
int indexForce = 3 * i;
for (int i = 0; i < m_numBodies; ++i) {
int index = 4 * i;
int indexForce = 3 * i;
T pos[3], vel[3], force[3];
pos[0] = m_pos[index + 0];
pos[1] = m_pos[index + 1];
pos[2] = m_pos[index + 2];
T invMass = m_pos[index + 3];
T pos[3], vel[3], force[3];
pos[0] = m_pos[index + 0];
pos[1] = m_pos[index + 1];
pos[2] = m_pos[index + 2];
T invMass = m_pos[index + 3];
vel[0] = m_vel[index + 0];
vel[1] = m_vel[index + 1];
vel[2] = m_vel[index + 2];
vel[0] = m_vel[index + 0];
vel[1] = m_vel[index + 1];
vel[2] = m_vel[index + 2];
force[0] = m_force[indexForce + 0];
force[1] = m_force[indexForce + 1];
force[2] = m_force[indexForce + 2];
force[0] = m_force[indexForce + 0];
force[1] = m_force[indexForce + 1];
force[2] = m_force[indexForce + 2];
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
vel[0] += (force[0] * invMass) * deltaTime;
vel[1] += (force[1] * invMass) * deltaTime;
vel[2] += (force[2] * invMass) * deltaTime;
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
vel[0] += (force[0] * invMass) * deltaTime;
vel[1] += (force[1] * invMass) * deltaTime;
vel[2] += (force[2] * invMass) * deltaTime;
vel[0] *= m_damping;
vel[1] *= m_damping;
vel[2] *= m_damping;
vel[0] *= m_damping;
vel[1] *= m_damping;
vel[2] *= m_damping;
// new position = old position + velocity * deltaTime
pos[0] += vel[0] * deltaTime;
pos[1] += vel[1] * deltaTime;
pos[2] += vel[2] * deltaTime;
// new position = old position + velocity * deltaTime
pos[0] += vel[0] * deltaTime;
pos[1] += vel[1] * deltaTime;
pos[2] += vel[2] * deltaTime;
m_pos[index + 0] = pos[0];
m_pos[index + 1] = pos[1];
m_pos[index + 2] = pos[2];
m_pos[index + 0] = pos[0];
m_pos[index + 1] = pos[1];
m_pos[index + 2] = pos[2];
m_vel[index + 0] = vel[0];
m_vel[index + 1] = vel[1];
m_vel[index + 2] = vel[2];
}
m_vel[index + 0] = vel[0];
m_vel[index + 1] = vel[1];
m_vel[index + 2] = vel[2];
}
}

View File

@@ -28,249 +28,246 @@
#include <helper_cuda.h>
#include <math.h>
//#include <GL/glew.h>
//#include <GL/freeglut.h>
// #include <GL/glew.h>
// #include <GL/freeglut.h>
// CUDA standard includes
#include <cuda_runtime.h>
//#include <cuda_gl_interop.h>
// #include <cuda_gl_interop.h>
#include "bodysystem.h"
__constant__ float softeningSquared;
__constant__ float softeningSquared;
__constant__ double softeningSquared_fp64;
cudaError_t setSofteningSquared(float softeningSq) {
return cudaMemcpyToSymbol(softeningSquared, &softeningSq, sizeof(float), 0,
cudaMemcpyHostToDevice);
cudaError_t setSofteningSquared(float softeningSq)
{
return cudaMemcpyToSymbol(softeningSquared, &softeningSq, sizeof(float), 0, cudaMemcpyHostToDevice);
}
cudaError_t setSofteningSquared(double softeningSq) {
return cudaMemcpyToSymbol(softeningSquared_fp64, &softeningSq, sizeof(double),
0, cudaMemcpyHostToDevice);
cudaError_t setSofteningSquared(double softeningSq)
{
return cudaMemcpyToSymbol(softeningSquared_fp64, &softeningSq, sizeof(double), 0, cudaMemcpyHostToDevice);
}
template <class T>
struct SharedMemory {
__device__ inline operator T *() {
extern __shared__ int __smem[];
return (T *)__smem;
}
template <class T> struct SharedMemory
{
__device__ inline operator T *()
{
extern __shared__ int __smem[];
return (T *)__smem;
}
__device__ inline operator const T *() const {
extern __shared__ int __smem[];
return (T *)__smem;
}
__device__ inline operator const T *() const
{
extern __shared__ int __smem[];
return (T *)__smem;
}
};
template <typename T>
__device__ T rsqrt_T(T x) {
return rsqrt(x);
}
template <typename T> __device__ T rsqrt_T(T x) { return rsqrt(x); }
template <>
__device__ float rsqrt_T<float>(float x) {
return rsqrtf(x);
}
template <> __device__ float rsqrt_T<float>(float x) { return rsqrtf(x); }
template <>
__device__ double rsqrt_T<double>(double x) {
return rsqrt(x);
}
template <> __device__ double rsqrt_T<double>(double x) { return rsqrt(x); }
// Macros to simplify shared memory addressing
#define SX(i) sharedPos[i + blockDim.x * threadIdx.y]
// This macro is only used when multithreadBodies is true (below)
#define SX_SUM(i, j) sharedPos[i + blockDim.x * j]
template <typename T>
__device__ T getSofteningSquared() {
return softeningSquared;
}
template <>
__device__ double getSofteningSquared<double>() {
return softeningSquared_fp64;
}
template <typename T> __device__ T getSofteningSquared() { return softeningSquared; }
template <> __device__ double getSofteningSquared<double>() { return softeningSquared_fp64; }
template <typename T>
struct DeviceData {
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
template <typename T> struct DeviceData
{
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
};
template <typename T>
__device__ typename vec3<T>::Type bodyBodyInteraction(
typename vec3<T>::Type ai, typename vec4<T>::Type bi,
typename vec4<T>::Type bj) {
typename vec3<T>::Type r;
__device__ typename vec3<T>::Type
bodyBodyInteraction(typename vec3<T>::Type ai, typename vec4<T>::Type bi, typename vec4<T>::Type bj)
{
typename vec3<T>::Type r;
// r_ij [3 FLOPS]
r.x = bj.x - bi.x;
r.y = bj.y - bi.y;
r.z = bj.z - bi.z;
// r_ij [3 FLOPS]
r.x = bj.x - bi.x;
r.y = bj.y - bi.y;
r.z = bj.z - bi.z;
// distSqr = dot(r_ij, r_ij) + EPS^2 [6 FLOPS]
T distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
distSqr += getSofteningSquared<T>();
// distSqr = dot(r_ij, r_ij) + EPS^2 [6 FLOPS]
T distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
distSqr += getSofteningSquared<T>();
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = rsqrt_T(distSqr);
T invDistCube = invDist * invDist * invDist;
// invDistCube =1/distSqr^(3/2) [4 FLOPS (2 mul, 1 sqrt, 1 inv)]
T invDist = rsqrt_T(distSqr);
T invDistCube = invDist * invDist * invDist;
// s = m_j * invDistCube [1 FLOP]
T s = bj.w * invDistCube;
// s = m_j * invDistCube [1 FLOP]
T s = bj.w * invDistCube;
// a_i = a_i + s * r_ij [6 FLOPS]
ai.x += r.x * s;
ai.y += r.y * s;
ai.z += r.z * s;
// a_i = a_i + s * r_ij [6 FLOPS]
ai.x += r.x * s;
ai.y += r.y * s;
ai.z += r.z * s;
return ai;
return ai;
}
template <typename T>
__device__ typename vec3<T>::Type computeBodyAccel(
typename vec4<T>::Type bodyPos, typename vec4<T>::Type *positions,
int numTiles) {
typename vec4<T>::Type *sharedPos = SharedMemory<typename vec4<T>::Type>();
__device__ typename vec3<T>::Type
computeBodyAccel(typename vec4<T>::Type bodyPos, typename vec4<T>::Type *positions, int numTiles)
{
typename vec4<T>::Type *sharedPos = SharedMemory<typename vec4<T>::Type>();
typename vec3<T>::Type acc = {0.0f, 0.0f, 0.0f};
typename vec3<T>::Type acc = {0.0f, 0.0f, 0.0f};
for (int tile = 0; tile < numTiles; tile++) {
sharedPos[threadIdx.x] = positions[tile * blockDim.x + threadIdx.x];
for (int tile = 0; tile < numTiles; tile++) {
sharedPos[threadIdx.x] = positions[tile * blockDim.x + threadIdx.x];
__syncthreads();
__syncthreads();
// This is the "tile_calculation" from the GPUG3 article.
// This is the "tile_calculation" from the GPUG3 article.
#pragma unroll 128
for (unsigned int counter = 0; counter < blockDim.x; counter++) {
acc = bodyBodyInteraction<T>(acc, bodyPos, sharedPos[counter]);
for (unsigned int counter = 0; counter < blockDim.x; counter++) {
acc = bodyBodyInteraction<T>(acc, bodyPos, sharedPos[counter]);
}
__syncthreads();
}
__syncthreads();
}
return acc;
return acc;
}
template <typename T>
__global__ void integrateBodies(typename vec4<T>::Type *__restrict__ newPos,
typename vec4<T>::Type *__restrict__ oldPos,
typename vec4<T>::Type *vel,
unsigned int deviceOffset,
unsigned int deviceNumBodies, float deltaTime,
float damping, int numTiles) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int deviceOffset,
unsigned int deviceNumBodies,
float deltaTime,
float damping,
int numTiles)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
if (index >= deviceNumBodies) {
return;
}
if (index >= deviceNumBodies) {
return;
}
typename vec4<T>::Type position = oldPos[deviceOffset + index];
typename vec4<T>::Type position = oldPos[deviceOffset + index];
typename vec3<T>::Type accel =
computeBodyAccel<T>(position, oldPos, numTiles);
typename vec3<T>::Type accel = computeBodyAccel<T>(position, oldPos, numTiles);
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
// note we factor out the body's mass from the equation, here and in
// bodyBodyInteraction (because they cancel out). Thus here force ==
// acceleration
typename vec4<T>::Type velocity = vel[deviceOffset + index];
// acceleration = force / mass;
// new velocity = old velocity + acceleration * deltaTime
// note we factor out the body's mass from the equation, here and in
// bodyBodyInteraction (because they cancel out). Thus here force ==
// acceleration
typename vec4<T>::Type velocity = vel[deviceOffset + index];
velocity.x += accel.x * deltaTime;
velocity.y += accel.y * deltaTime;
velocity.z += accel.z * deltaTime;
velocity.x += accel.x * deltaTime;
velocity.y += accel.y * deltaTime;
velocity.z += accel.z * deltaTime;
velocity.x *= damping;
velocity.y *= damping;
velocity.z *= damping;
velocity.x *= damping;
velocity.y *= damping;
velocity.z *= damping;
// new position = old position + velocity * deltaTime
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
position.z += velocity.z * deltaTime;
// new position = old position + velocity * deltaTime
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
position.z += velocity.z * deltaTime;
// store new position and velocity
newPos[deviceOffset + index] = position;
vel[deviceOffset + index] = velocity;
// store new position and velocity
newPos[deviceOffset + index] = position;
vel[deviceOffset + index] = velocity;
}
template <typename T>
void integrateNbodySystem(DeviceData<T> *deviceData,
void integrateNbodySystem(DeviceData<T> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead, float deltaTime,
float damping, unsigned int numBodies,
unsigned int numDevices, int blockSize,
bool bUsePBO) {
if (bUsePBO) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(
pgres[currentRead], cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsResourceSetMapFlags(
pgres[1 - currentRead], cudaGraphicsMapFlagsWriteDiscard));
checkCudaErrors(cudaGraphicsMapResources(2, pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[currentRead]), &bytes,
pgres[currentRead]));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[1 - currentRead]), &bytes,
pgres[1 - currentRead]));
}
for (unsigned int dev = 0; dev != numDevices; dev++) {
if (numDevices > 1) {
cudaSetDevice(dev);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO)
{
if (bUsePBO) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres[currentRead], cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres[1 - currentRead], cudaGraphicsMapFlagsWriteDiscard));
checkCudaErrors(cudaGraphicsMapResources(2, pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[currentRead]), &bytes, pgres[currentRead]));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
(void **)&(deviceData[0].dPos[1 - currentRead]), &bytes, pgres[1 - currentRead]));
}
int numBlocks = (deviceData[dev].numBodies + blockSize - 1) / blockSize;
int numTiles = (numBodies + blockSize - 1) / blockSize;
int sharedMemSize = blockSize * 4 * sizeof(T); // 4 floats for pos
for (unsigned int dev = 0; dev != numDevices; dev++) {
if (numDevices > 1) {
cudaSetDevice(dev);
}
integrateBodies<T><<<numBlocks, blockSize, sharedMemSize>>>(
(typename vec4<T>::Type *)deviceData[dev].dPos[1 - currentRead],
(typename vec4<T>::Type *)deviceData[dev].dPos[currentRead],
(typename vec4<T>::Type *)deviceData[dev].dVel, deviceData[dev].offset,
deviceData[dev].numBodies, deltaTime, damping, numTiles);
int numBlocks = (deviceData[dev].numBodies + blockSize - 1) / blockSize;
int numTiles = (numBodies + blockSize - 1) / blockSize;
int sharedMemSize = blockSize * 4 * sizeof(T); // 4 floats for pos
integrateBodies<T>
<<<numBlocks, blockSize, sharedMemSize>>>((typename vec4<T>::Type *)deviceData[dev].dPos[1 - currentRead],
(typename vec4<T>::Type *)deviceData[dev].dPos[currentRead],
(typename vec4<T>::Type *)deviceData[dev].dVel,
deviceData[dev].offset,
deviceData[dev].numBodies,
deltaTime,
damping,
numTiles);
if (numDevices > 1) {
checkCudaErrors(cudaEventRecord(deviceData[dev].event));
// MJH: Hack on older driver versions to force kernel launches to flush!
cudaStreamQuery(0);
}
// check if kernel invocation generated an error
getLastCudaError("Kernel execution failed");
}
if (numDevices > 1) {
checkCudaErrors(cudaEventRecord(deviceData[dev].event));
// MJH: Hack on older driver versions to force kernel launches to flush!
cudaStreamQuery(0);
for (unsigned int dev = 0; dev < numDevices; dev++) {
checkCudaErrors(cudaEventSynchronize(deviceData[dev].event));
}
}
// check if kernel invocation generated an error
getLastCudaError("Kernel execution failed");
}
if (numDevices > 1) {
for (unsigned int dev = 0; dev < numDevices; dev++) {
checkCudaErrors(cudaEventSynchronize(deviceData[dev].event));
if (bUsePBO) {
checkCudaErrors(cudaGraphicsUnmapResources(2, pgres, 0));
}
}
if (bUsePBO) {
checkCudaErrors(cudaGraphicsUnmapResources(2, pgres, 0));
}
}
// Explicit specializations needed to generate code
template void integrateNbodySystem<float>(DeviceData<float> *deviceData,
template void integrateNbodySystem<float>(DeviceData<float> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead,
float deltaTime, float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);
template void integrateNbodySystem<double>(DeviceData<double> *deviceData,
template void integrateNbodySystem<double>(DeviceData<double> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead,
float deltaTime, float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);

View File

@@ -30,70 +30,71 @@
#include "bodysystem.h"
template <typename T>
struct DeviceData {
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
template <typename T> struct DeviceData
{
T *dPos[2]; // mapped host pointers
T *dVel;
cudaEvent_t event;
unsigned int offset;
unsigned int numBodies;
};
// CUDA BodySystem: runs on the GPU
template <typename T>
class BodySystemCUDA : public BodySystem<T> {
public:
BodySystemCUDA(unsigned int numBodies, unsigned int numDevices,
unsigned int blockSize, bool usePBO, bool useSysMem = false);
virtual ~BodySystemCUDA();
template <typename T> class BodySystemCUDA : public BodySystem<T>
{
public:
BodySystemCUDA(unsigned int numBodies,
unsigned int numDevices,
unsigned int blockSize,
bool usePBO,
bool useSysMem = false);
virtual ~BodySystemCUDA();
virtual void loadTipsyFile(const std::string &filename);
virtual void loadTipsyFile(const std::string &filename);
virtual void update(T deltaTime);
virtual void update(T deltaTime);
virtual void setSoftening(T softening);
virtual void setDamping(T damping);
virtual void setSoftening(T softening);
virtual void setDamping(T damping);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual T *getArray(BodyArray array);
virtual void setArray(BodyArray array, const T *data);
virtual unsigned int getCurrentReadBuffer() const {
return m_pbo[m_currentRead];
}
virtual unsigned int getCurrentReadBuffer() const { return m_pbo[m_currentRead]; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
virtual unsigned int getNumBodies() const { return m_numBodies; }
protected: // methods
BodySystemCUDA() {}
protected: // methods
BodySystemCUDA() {}
virtual void _initialize(int numBodies);
virtual void _finalize();
virtual void _initialize(int numBodies);
virtual void _finalize();
protected: // data
unsigned int m_numBodies;
unsigned int m_numDevices;
bool m_bInitialized;
protected: // data
unsigned int m_numBodies;
unsigned int m_numDevices;
bool m_bInitialized;
// Host data
T *m_hPos[2];
T *m_hVel;
// Host data
T *m_hPos[2];
T *m_hVel;
DeviceData<T> *m_deviceData;
DeviceData<T> *m_deviceData;
bool m_bUsePBO;
bool m_bUseSysMem;
unsigned int m_SMVersion;
bool m_bUsePBO;
bool m_bUseSysMem;
unsigned int m_SMVersion;
T m_damping;
T m_damping;
unsigned int m_pbo[2];
cudaGraphicsResource *m_pGRes[2];
unsigned int m_currentRead;
unsigned int m_currentWrite;
unsigned int m_pbo[2];
cudaGraphicsResource *m_pGRes[2];
unsigned int m_currentRead;
unsigned int m_currentWrite;
unsigned int m_blockSize;
unsigned int m_blockSize;
};
#include "bodysystemcuda_impl.h"
#endif // __BODYSYSTEMCUDA_H__
#endif // __BODYSYSTEMCUDA_H__

View File

@@ -25,25 +25,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <helper_cuda.h>
#include <algorithm>
#include <assert.h>
#include <math.h>
#include <memory.h>
#include <cstdio>
#include <cstdlib>
#include <helper_cuda.h>
#include <math.h>
#include <memory.h>
#include <vector>
#include <algorithm>
//#include <GL/glew.h>
// #include <GL/glew.h>
#include <cuda_gl_interop.h>
template <typename T>
void integrateNbodySystem(DeviceData<T> *deviceData,
void integrateNbodySystem(DeviceData<T> *deviceData,
cudaGraphicsResource **pgres,
unsigned int currentRead, float deltaTime,
float damping, unsigned int numBodies,
unsigned int numDevices, int blockSize, bool bUsePBO);
unsigned int currentRead,
float deltaTime,
float damping,
unsigned int numBodies,
unsigned int numDevices,
int blockSize,
bool bUsePBO);
cudaError_t setSofteningSquared(float softeningSq);
cudaError_t setSofteningSquared(double softeningSq);
@@ -51,323 +54,323 @@ cudaError_t setSofteningSquared(double softeningSq);
template <typename T>
BodySystemCUDA<T>::BodySystemCUDA(unsigned int numBodies,
unsigned int numDevices,
unsigned int blockSize, bool usePBO,
bool useSysMem)
: m_numBodies(numBodies),
m_numDevices(numDevices),
m_bInitialized(false),
m_bUsePBO(usePBO),
m_bUseSysMem(useSysMem),
m_currentRead(0),
m_currentWrite(1),
m_blockSize(blockSize) {
m_hPos[0] = m_hPos[1] = 0;
m_hVel = 0;
unsigned int blockSize,
bool usePBO,
bool useSysMem)
: m_numBodies(numBodies)
, m_numDevices(numDevices)
, m_bInitialized(false)
, m_bUsePBO(usePBO)
, m_bUseSysMem(useSysMem)
, m_currentRead(0)
, m_currentWrite(1)
, m_blockSize(blockSize)
{
m_hPos[0] = m_hPos[1] = 0;
m_hVel = 0;
m_deviceData = 0;
m_deviceData = 0;
_initialize(numBodies);
setSoftening(0.00125f);
setDamping(0.995f);
_initialize(numBodies);
setSoftening(0.00125f);
setDamping(0.995f);
}
template <typename T>
BodySystemCUDA<T>::~BodySystemCUDA() {
_finalize();
m_numBodies = 0;
template <typename T> BodySystemCUDA<T>::~BodySystemCUDA()
{
_finalize();
m_numBodies = 0;
}
template <typename T>
void BodySystemCUDA<T>::_initialize(int numBodies) {
assert(!m_bInitialized);
template <typename T> void BodySystemCUDA<T>::_initialize(int numBodies)
{
assert(!m_bInitialized);
m_numBodies = numBodies;
m_numBodies = numBodies;
unsigned int memSize = sizeof(T) * 4 * numBodies;
unsigned int memSize = sizeof(T) * 4 * numBodies;
m_deviceData = new DeviceData<T>[m_numDevices];
m_deviceData = new DeviceData<T>[m_numDevices];
// divide up the workload amongst Devices
float *weights = new float[m_numDevices];
int *numSms = new int[m_numDevices];
float total = 0;
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaDeviceProp props;
checkCudaErrors(cudaGetDeviceProperties(&props, i));
// Choose the weight based on the Compute Capability
// We estimate that a CC2.0 SM is about 4.0x faster than a CC 1.x SM for
// this application (since a 15-SM GF100 is about 2X faster than a 30-SM
// GT200).
numSms[i] = props.multiProcessorCount;
weights[i] = numSms[i] * (props.major >= 2 ? 4.f : 1.f);
total += weights[i];
}
unsigned int offset = 0;
unsigned int remaining = m_numBodies;
for (unsigned int i = 0; i < m_numDevices; i++) {
unsigned int count = (int)((weights[i] / total) * m_numBodies);
unsigned int round = numSms[i] * 256;
count = round * ((count + round - 1) / round);
if (count > remaining) {
count = remaining;
}
remaining -= count;
m_deviceData[i].offset = offset;
m_deviceData[i].numBodies = count;
offset += count;
if ((i == m_numDevices - 1) && (offset < m_numBodies - 1)) {
m_deviceData[i].numBodies += m_numBodies - offset;
}
}
delete[] weights;
delete[] numSms;
if (m_bUseSysMem) {
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[0], memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[1], memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hVel, memSize,
cudaHostAllocMapped | cudaHostAllocPortable));
memset(m_hPos[0], 0, memSize);
memset(m_hPos[1], 0, memSize);
memset(m_hVel, 0, memSize);
// divide up the workload amongst Devices
float *weights = new float[m_numDevices];
int *numSms = new int[m_numDevices];
float total = 0;
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
cudaDeviceProp props;
checkCudaErrors(cudaGetDeviceProperties(&props, i));
checkCudaErrors(cudaEventCreate(&m_deviceData[i].event));
checkCudaErrors(cudaHostGetDevicePointer(
(void **)&m_deviceData[i].dPos[0], (void *)m_hPos[0], 0));
checkCudaErrors(cudaHostGetDevicePointer(
(void **)&m_deviceData[i].dPos[1], (void *)m_hPos[1], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dVel,
(void *)m_hVel, 0));
// Choose the weight based on the Compute Capability
// We estimate that a CC2.0 SM is about 4.0x faster than a CC 1.x SM for
// this application (since a 15-SM GF100 is about 2X faster than a 30-SM
// GT200).
numSms[i] = props.multiProcessorCount;
weights[i] = numSms[i] * (props.major >= 2 ? 4.f : 1.f);
total += weights[i];
}
} else {
m_hPos[0] = new T[m_numBodies * 4];
m_hVel = new T[m_numBodies * 4];
memset(m_hPos[0], 0, memSize);
memset(m_hVel, 0, memSize);
unsigned int offset = 0;
unsigned int remaining = m_numBodies;
checkCudaErrors(cudaEventCreate(&m_deviceData[0].event));
for (unsigned int i = 0; i < m_numDevices; i++) {
unsigned int count = (int)((weights[i] / total) * m_numBodies);
unsigned int round = numSms[i] * 256;
count = round * ((count + round - 1) / round);
if (m_bUsePBO) {
// create the position pixel buffer objects for rendering
// we will actually compute directly from this memory in CUDA too
glGenBuffers(2, (GLuint *)m_pbo);
for (int i = 0; i < 2; ++i) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[i]);
glBufferData(GL_ARRAY_BUFFER, memSize, m_hPos[0], GL_DYNAMIC_DRAW);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != memSize) {
fprintf(stderr, "WARNING: Pixel Buffer Object allocation failed!n");
if (count > remaining) {
count = remaining;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&m_pGRes[i], m_pbo[i],
cudaGraphicsMapFlagsNone));
}
} else {
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[0], memSize));
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[1], memSize));
remaining -= count;
m_deviceData[i].offset = offset;
m_deviceData[i].numBodies = count;
offset += count;
if ((i == m_numDevices - 1) && (offset < m_numBodies - 1)) {
m_deviceData[i].numBodies += m_numBodies - offset;
}
}
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dVel, memSize));
}
delete[] weights;
delete[] numSms;
m_bInitialized = true;
if (m_bUseSysMem) {
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[0], memSize, cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hPos[1], memSize, cudaHostAllocMapped | cudaHostAllocPortable));
checkCudaErrors(cudaHostAlloc((void **)&m_hVel, memSize, cudaHostAllocMapped | cudaHostAllocPortable));
memset(m_hPos[0], 0, memSize);
memset(m_hPos[1], 0, memSize);
memset(m_hVel, 0, memSize);
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
checkCudaErrors(cudaEventCreate(&m_deviceData[i].event));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dPos[0], (void *)m_hPos[0], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dPos[1], (void *)m_hPos[1], 0));
checkCudaErrors(cudaHostGetDevicePointer((void **)&m_deviceData[i].dVel, (void *)m_hVel, 0));
}
}
else {
m_hPos[0] = new T[m_numBodies * 4];
m_hVel = new T[m_numBodies * 4];
memset(m_hPos[0], 0, memSize);
memset(m_hVel, 0, memSize);
checkCudaErrors(cudaEventCreate(&m_deviceData[0].event));
if (m_bUsePBO) {
// create the position pixel buffer objects for rendering
// we will actually compute directly from this memory in CUDA too
glGenBuffers(2, (GLuint *)m_pbo);
for (int i = 0; i < 2; ++i) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[i]);
glBufferData(GL_ARRAY_BUFFER, memSize, m_hPos[0], GL_DYNAMIC_DRAW);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != memSize) {
fprintf(stderr, "WARNING: Pixel Buffer Object allocation failed!n");
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&m_pGRes[i], m_pbo[i], cudaGraphicsMapFlagsNone));
}
}
else {
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[0], memSize));
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dPos[1], memSize));
}
checkCudaErrors(cudaMalloc((void **)&m_deviceData[0].dVel, memSize));
}
m_bInitialized = true;
}
template <typename T>
void BodySystemCUDA<T>::_finalize() {
assert(m_bInitialized);
template <typename T> void BodySystemCUDA<T>::_finalize()
{
assert(m_bInitialized);
if (m_bUseSysMem) {
checkCudaErrors(cudaFreeHost(m_hPos[0]));
checkCudaErrors(cudaFreeHost(m_hPos[1]));
checkCudaErrors(cudaFreeHost(m_hVel));
if (m_bUseSysMem) {
checkCudaErrors(cudaFreeHost(m_hPos[0]));
checkCudaErrors(cudaFreeHost(m_hPos[1]));
checkCudaErrors(cudaFreeHost(m_hVel));
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaEventDestroy(m_deviceData[i].event);
}
}
else {
delete[] m_hPos[0];
delete[] m_hPos[1];
delete[] m_hVel;
checkCudaErrors(cudaFree((void **)m_deviceData[0].dVel));
if (m_bUsePBO) {
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[0]));
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[1]));
glDeleteBuffers(2, (const GLuint *)m_pbo);
}
else {
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[0]));
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[1]));
}
}
delete[] m_deviceData;
m_bInitialized = false;
}
template <typename T> void BodySystemCUDA<T>::loadTipsyFile(const std::string &filename)
{
if (m_bInitialized)
_finalize();
std::vector<typename vec4<T>::Type> positions;
std::vector<typename vec4<T>::Type> velocities;
std::vector<int> ids;
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst, nSecond, nThird);
_initialize(nBodies);
setArray(BODYSYSTEM_POSITION, (T *)&positions[0]);
setArray(BODYSYSTEM_VELOCITY, (T *)&velocities[0]);
}
template <typename T> void BodySystemCUDA<T>::setSoftening(T softening)
{
T softeningSq = softening * softening;
for (unsigned int i = 0; i < m_numDevices; i++) {
cudaEventDestroy(m_deviceData[i].event);
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
checkCudaErrors(setSofteningSquared(softeningSq));
}
} else {
delete[] m_hPos[0];
delete[] m_hPos[1];
delete[] m_hVel;
checkCudaErrors(cudaFree((void **)m_deviceData[0].dVel));
if (m_bUsePBO) {
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[0]));
checkCudaErrors(cudaGraphicsUnregisterResource(m_pGRes[1]));
glDeleteBuffers(2, (const GLuint *)m_pbo);
} else {
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[0]));
checkCudaErrors(cudaFree((void **)m_deviceData[0].dPos[1]));
}
}
delete[] m_deviceData;
m_bInitialized = false;
}
template <typename T>
void BodySystemCUDA<T>::loadTipsyFile(const std::string &filename) {
if (m_bInitialized) _finalize();
template <typename T> void BodySystemCUDA<T>::setDamping(T damping) { m_damping = damping; }
std::vector<typename vec4<T>::Type> positions;
std::vector<typename vec4<T>::Type> velocities;
std::vector<int> ids;
template <typename T> void BodySystemCUDA<T>::update(T deltaTime)
{
assert(m_bInitialized);
int nBodies = 0;
int nFirst = 0, nSecond = 0, nThird = 0;
integrateNbodySystem<T>(m_deviceData,
m_pGRes,
m_currentRead,
(float)deltaTime,
(float)m_damping,
m_numBodies,
m_numDevices,
m_blockSize,
m_bUsePBO);
read_tipsy_file(positions, velocities, ids, filename, nBodies, nFirst,
nSecond, nThird);
_initialize(nBodies);
setArray(BODYSYSTEM_POSITION, (T *)&positions[0]);
setArray(BODYSYSTEM_VELOCITY, (T *)&velocities[0]);
std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
void BodySystemCUDA<T>::setSoftening(T softening) {
T softeningSq = softening * softening;
template <typename T> T *BodySystemCUDA<T>::getArray(BodyArray array)
{
assert(m_bInitialized);
for (unsigned int i = 0; i < m_numDevices; i++) {
if (m_numDevices > 1) {
checkCudaErrors(cudaSetDevice(i));
}
T *hdata = 0;
T *ddata = 0;
checkCudaErrors(setSofteningSquared(softeningSq));
}
}
cudaGraphicsResource *pgres = NULL;
template <typename T>
void BodySystemCUDA<T>::setDamping(T damping) {
m_damping = damping;
}
int currentReadHost = m_bUseSysMem ? m_currentRead : 0;
template <typename T>
void BodySystemCUDA<T>::update(T deltaTime) {
assert(m_bInitialized);
integrateNbodySystem<T>(m_deviceData, m_pGRes, m_currentRead,
(float)deltaTime, (float)m_damping, m_numBodies,
m_numDevices, m_blockSize, m_bUsePBO);
std::swap(m_currentRead, m_currentWrite);
}
template <typename T>
T *BodySystemCUDA<T>::getArray(BodyArray array) {
assert(m_bInitialized);
T *hdata = 0;
T *ddata = 0;
cudaGraphicsResource *pgres = NULL;
int currentReadHost = m_bUseSysMem ? m_currentRead : 0;
switch (array) {
switch (array) {
default:
case BODYSYSTEM_POSITION:
hdata = m_hPos[currentReadHost];
ddata = m_deviceData[0].dPos[m_currentRead];
hdata = m_hPos[currentReadHost];
ddata = m_deviceData[0].dPos[m_currentRead];
if (m_bUsePBO) {
pgres = m_pGRes[m_currentRead];
}
break;
case BODYSYSTEM_VELOCITY:
hdata = m_hVel;
ddata = m_deviceData[0].dVel;
break;
}
if (!m_bUseSysMem) {
if (pgres) {
checkCudaErrors(
cudaGraphicsResourceSetMapFlags(pgres, cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsMapResources(1, &pgres, 0));
size_t bytes;
checkCudaErrors(
cudaGraphicsResourceGetMappedPointer((void **)&ddata, &bytes, pgres));
}
checkCudaErrors(cudaMemcpy(hdata, ddata, m_numBodies * 4 * sizeof(T),
cudaMemcpyDeviceToHost));
if (pgres) {
checkCudaErrors(cudaGraphicsUnmapResources(1, &pgres, 0));
}
}
return hdata;
}
template <typename T>
void BodySystemCUDA<T>::setArray(BodyArray array, const T *data) {
assert(m_bInitialized);
m_currentRead = 0;
m_currentWrite = 1;
switch (array) {
default:
case BODYSYSTEM_POSITION: {
if (m_bUsePBO) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[m_currentRead]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(T) * m_numBodies, data);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != 4 * (sizeof(T) * m_numBodies)) {
fprintf(stderr, "WARNING: Pixel Buffer Object download failed!n");
if (m_bUsePBO) {
pgres = m_pGRes[m_currentRead];
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
} else {
if (m_bUseSysMem) {
memcpy(m_hPos[m_currentRead], data, m_numBodies * 4 * sizeof(T));
} else
checkCudaErrors(cudaMemcpy(m_deviceData[0].dPos[m_currentRead], data,
m_numBodies * 4 * sizeof(T),
cudaMemcpyHostToDevice));
}
break;
case BODYSYSTEM_VELOCITY:
hdata = m_hVel;
ddata = m_deviceData[0].dVel;
break;
}
if (!m_bUseSysMem) {
if (pgres) {
checkCudaErrors(cudaGraphicsResourceSetMapFlags(pgres, cudaGraphicsMapFlagsReadOnly));
checkCudaErrors(cudaGraphicsMapResources(1, &pgres, 0));
size_t bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&ddata, &bytes, pgres));
}
checkCudaErrors(cudaMemcpy(hdata, ddata, m_numBodies * 4 * sizeof(T), cudaMemcpyDeviceToHost));
if (pgres) {
checkCudaErrors(cudaGraphicsUnmapResources(1, &pgres, 0));
}
}
return hdata;
}
template <typename T> void BodySystemCUDA<T>::setArray(BodyArray array, const T *data)
{
assert(m_bInitialized);
m_currentRead = 0;
m_currentWrite = 1;
switch (array) {
default:
case BODYSYSTEM_POSITION: {
if (m_bUsePBO) {
glBindBuffer(GL_ARRAY_BUFFER, m_pbo[m_currentRead]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(T) * m_numBodies, data);
int size = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, (GLint *)&size);
if ((unsigned)size != 4 * (sizeof(T) * m_numBodies)) {
fprintf(stderr, "WARNING: Pixel Buffer Object download failed!n");
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
else {
if (m_bUseSysMem) {
memcpy(m_hPos[m_currentRead], data, m_numBodies * 4 * sizeof(T));
}
else
checkCudaErrors(cudaMemcpy(
m_deviceData[0].dPos[m_currentRead], data, m_numBodies * 4 * sizeof(T), cudaMemcpyHostToDevice));
}
} break;
case BODYSYSTEM_VELOCITY:
if (m_bUseSysMem) {
memcpy(m_hVel, data, m_numBodies * 4 * sizeof(T));
} else
checkCudaErrors(cudaMemcpy(m_deviceData[0].dVel, data,
m_numBodies * 4 * sizeof(T),
cudaMemcpyHostToDevice));
if (m_bUseSysMem) {
memcpy(m_hVel, data, m_numBodies * 4 * sizeof(T));
}
else
checkCudaErrors(
cudaMemcpy(m_deviceData[0].dVel, data, m_numBodies * 4 * sizeof(T), cudaMemcpyHostToDevice));
break;
}
break;
}
}

View File

@@ -27,294 +27,294 @@
#include "render_particles.h"
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include <helper_cuda.h>
#include <math.h>
#include <assert.h>
#include <cuda_gl_interop.h>
#include <cuda_runtime.h>
#include <helper_cuda.h>
#include <math.h>
void mat_identity(matrix4 m) {
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] =
m[2][1] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
void mat_identity(matrix4 m)
{
m[0][1] = m[0][2] = m[0][3] = m[1][0] = m[1][2] = m[1][3] = m[2][0] = m[2][1] = m[2][3] = m[3][0] = m[3][1] =
m[3][2] = 0.0f;
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
}
void mat_multiply(matrix4 m0, matrix4 m1) {
float m[4];
void mat_multiply(matrix4 m0, matrix4 m1)
{
float m[4];
for (int r = 0; r < 4; r++) {
m[0] = m[1] = m[2] = m[3] = 0.0f;
for (int r = 0; r < 4; r++) {
m[0] = m[1] = m[2] = m[3] = 0.0f;
for (int c = 0; c < 4; c++) {
for (int i = 0; i < 4; i++) {
m[c] += m0[i][r] * m1[c][i];
}
for (int c = 0; c < 4; c++) {
for (int i = 0; i < 4; i++) {
m[c] += m0[i][r] * m1[c][i];
}
}
for (int c = 0; c < 4; c++) {
m0[c][r] = m[c];
}
}
for (int c = 0; c < 4; c++) {
m0[c][r] = m[c];
}
}
}
void mat_translate(matrix4 m, vector3 v) {
matrix4 m2;
m2[0][0] = m2[1][1] = m2[2][2] = m2[3][3] = 1.0f;
m2[0][1] = m2[0][2] = m2[0][3] = m2[1][0] = m2[1][2] = m2[1][3] = m2[2][0] =
m2[2][1] = m2[2][3] = 0.0f;
m2[3][0] = v[0];
m2[3][1] = v[1];
m2[3][2] = v[2];
mat_multiply(m, m2);
void mat_translate(matrix4 m, vector3 v)
{
matrix4 m2;
m2[0][0] = m2[1][1] = m2[2][2] = m2[3][3] = 1.0f;
m2[0][1] = m2[0][2] = m2[0][3] = m2[1][0] = m2[1][2] = m2[1][3] = m2[2][0] = m2[2][1] = m2[2][3] = 0.0f;
m2[3][0] = v[0];
m2[3][1] = v[1];
m2[3][2] = v[2];
mat_multiply(m, m2);
}
void mat_perspective(matrix4 m, GLfloat fovy, GLfloat aspect, GLfloat znear,
GLfloat zfar) {
matrix4 m2;
m2[1][0] = m2[2][0] = m2[3][0] = m2[0][1] = m2[2][1] = m2[3][1] = m2[0][2] =
m2[1][2] = m2[0][3] = m2[1][3] = m2[3][3] = 0.0f;
m2[2][3] = -1.0f;
void mat_perspective(matrix4 m, GLfloat fovy, GLfloat aspect, GLfloat znear, GLfloat zfar)
{
matrix4 m2;
m2[1][0] = m2[2][0] = m2[3][0] = m2[0][1] = m2[2][1] = m2[3][1] = m2[0][2] = m2[1][2] = m2[0][3] = m2[1][3] =
m2[3][3] = 0.0f;
m2[2][3] = -1.0f;
float f = 1 / tan((fovy * M_PI / 180) / 2);
m2[0][0] = f / aspect;
m2[1][1] = f;
float f = 1 / tan((fovy * M_PI / 180) / 2);
m2[0][0] = f / aspect;
m2[1][1] = f;
m2[2][2] = ((znear + zfar) / (znear - zfar));
m2[3][2] = ((2 * znear * zfar) / (znear - zfar));
m2[2][2] = ((znear + zfar) / (znear - zfar));
m2[3][2] = ((2 * znear * zfar) / (znear - zfar));
mat_multiply(m, m2);
mat_multiply(m, m2);
}
ParticleRenderer::ParticleRenderer(unsigned int windowWidth,
unsigned int windowHeight)
: m_pos(0),
m_numParticles(0),
m_pointSize(1.0f),
m_spriteSize(2.0f),
m_vertexShader(0),
m_vertexShaderPoints(0),
m_fragmentShader(0),
m_programPoints(0),
m_programSprites(0),
m_texture(0),
m_pbo(0),
m_vboColor(0),
m_windowWidth(windowWidth),
m_windowHeight(windowHeight),
m_bFp64Positions(false) {
m_camera[0] = 0;
m_camera[1] = 0;
m_camera[2] = 0;
_initGL();
ParticleRenderer::ParticleRenderer(unsigned int windowWidth, unsigned int windowHeight)
: m_pos(0)
, m_numParticles(0)
, m_pointSize(1.0f)
, m_spriteSize(2.0f)
, m_vertexShader(0)
, m_vertexShaderPoints(0)
, m_fragmentShader(0)
, m_programPoints(0)
, m_programSprites(0)
, m_texture(0)
, m_pbo(0)
, m_vboColor(0)
, m_windowWidth(windowWidth)
, m_windowHeight(windowHeight)
, m_bFp64Positions(false)
{
m_camera[0] = 0;
m_camera[1] = 0;
m_camera[2] = 0;
_initGL();
}
ParticleRenderer::~ParticleRenderer() { m_pos = 0; }
void ParticleRenderer::resetPBO() { glDeleteBuffers(1, (GLuint *)&m_pbo); }
void ParticleRenderer::setPositions(float *pos, int numParticles) {
m_pos = pos;
m_numParticles = numParticles;
void ParticleRenderer::setPositions(float *pos, int numParticles)
{
m_pos = pos;
m_numParticles = numParticles;
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), pos,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle float position");
}
void ParticleRenderer::setPositions(double *pos, int numParticles) {
m_bFp64Positions = true;
m_pos_fp64 = pos;
m_numParticles = numParticles;
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(double), pos,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle double position");
}
void ParticleRenderer::setColors(float *color, int numParticles) {
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), color,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ParticleRenderer::setBaseColor(float color[4]) {
for (int i = 0; i < 4; i++) m_baseColor[i] = color[i];
}
void ParticleRenderer::setPBO(unsigned int pbo, int numParticles, bool fp64) {
m_pbo = pbo;
m_numParticles = numParticles;
if (fp64) m_bFp64Positions = true;
}
void ParticleRenderer::display() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
glUseProgram(m_programSprites);
// Set modelview and projection matrices
GLint h_ModelViewMatrix = glGetUniformLocation(m_programSprites, "modelview");
GLint h_ProjectionMatrix =
glGetUniformLocation(m_programSprites, "projection");
matrix4 modelview;
matrix4 projection;
mat_identity(modelview);
mat_identity(projection);
mat_translate(modelview, m_camera);
mat_perspective(projection, 60, (float)m_windowWidth / (float)m_windowHeight,
0.1, 1000.0);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat *)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat *)projection);
// Set point size
GLint h_PointSize = glGetUniformLocation(m_programSprites, "size");
glUniform1f(h_PointSize, m_spriteSize);
// Set base and secondary colors
GLint h_BaseColor = glGetUniformLocation(m_programSprites, "baseColor");
GLint h_SecondaryColor =
glGetUniformLocation(m_programSprites, "secondaryColor");
glUniform4f(h_BaseColor, 1.0, 1.0, 1.0, 1.0);
glUniform4f(h_SecondaryColor, m_baseColor[0], m_baseColor[1], m_baseColor[2],
m_baseColor[3]);
// Set position coords
GLint h_position = glGetAttribLocation(m_programSprites, "a_position");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glEnableVertexAttribArray(h_position);
glVertexAttribPointer(h_position, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLuint texLoc = glGetUniformLocation(m_programSprites, "splatTexture");
glUniform1i(texLoc, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_POINTS, 0, m_numParticles);
glDisableVertexAttribArray(h_position);
glUseProgram(0);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
const char vertexShader[] = {
"attribute vec4 a_position;"
"uniform mat4 projection;"
"uniform mat4 modelview;"
"uniform float size;"
"void main()"
"{"
"float pointSize = 500.0 * size;"
"vec4 vert = a_position;"
"vert.w = 1.0;"
"vec3 pos_eye = vec3(modelview * vert);"
"gl_PointSize = max(1.0, pointSize / (1.0 - pos_eye.z));"
"gl_Position = projection * modelview * a_position;"
"}"};
const char fragmentShader[] = {
"uniform sampler2D splatTexture;"
"uniform lowp vec4 baseColor;"
"uniform lowp vec4 secondaryColor;"
"void main()"
"{"
"lowp vec4 textureColor = (0.6 + 0.4 * baseColor) * "
"texture2D(splatTexture, gl_PointCoord);"
"gl_FragColor = textureColor * secondaryColor;"
"}"};
// Checks if the shader is compiled.
static int CheckCompiled(GLuint shader) {
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (!isCompiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling program:\n%s\n", infoLog);
free(infoLog);
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
return 0;
}
return 1;
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), pos, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle float position");
}
void ParticleRenderer::_initGL() {
m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
m_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
void ParticleRenderer::setPositions(double *pos, int numParticles)
{
m_bFp64Positions = true;
m_pos_fp64 = pos;
m_numParticles = numParticles;
const char *v = vertexShader;
const char *f = fragmentShader;
glShaderSource(m_vertexShader, 1, &v, 0);
glShaderSource(m_fragmentShader, 1, &f, 0);
if (!m_pbo) {
glGenBuffers(1, (GLuint *)&m_pbo);
}
checkGLErrors("Shader Source");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(double), pos, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
checkGLErrors("Setting particle double position");
}
glCompileShader(m_vertexShader);
glCompileShader(m_fragmentShader);
void ParticleRenderer::setColors(float *color, int numParticles)
{
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, numParticles * 4 * sizeof(float), color, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (!CheckCompiled(m_vertexShader) || !CheckCompiled(m_fragmentShader)) {
printf("A shader failed to compile.\n");
exit(1);
}
void ParticleRenderer::setBaseColor(float color[4])
{
for (int i = 0; i < 4; i++)
m_baseColor[i] = color[i];
}
m_programSprites = glCreateProgram();
void ParticleRenderer::setPBO(unsigned int pbo, int numParticles, bool fp64)
{
m_pbo = pbo;
m_numParticles = numParticles;
checkGLErrors("create program");
if (fp64)
m_bFp64Positions = true;
}
glAttachShader(m_programSprites, m_vertexShader);
glAttachShader(m_programSprites, m_fragmentShader);
void ParticleRenderer::display()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(GL_FALSE);
checkGLErrors("attaching shaders");
glUseProgram(m_programSprites);
glLinkProgram(m_programSprites);
// Set modelview and projection matrices
GLint h_ModelViewMatrix = glGetUniformLocation(m_programSprites, "modelview");
GLint h_ProjectionMatrix = glGetUniformLocation(m_programSprites, "projection");
matrix4 modelview;
matrix4 projection;
mat_identity(modelview);
mat_identity(projection);
mat_translate(modelview, m_camera);
mat_perspective(projection, 60, (float)m_windowWidth / (float)m_windowHeight, 0.1, 1000.0);
glUniformMatrix4fv(h_ModelViewMatrix, 1, GL_FALSE, (GLfloat *)modelview);
glUniformMatrix4fv(h_ProjectionMatrix, 1, GL_FALSE, (GLfloat *)projection);
checkGLErrors("linking program");
// Set point size
GLint h_PointSize = glGetUniformLocation(m_programSprites, "size");
glUniform1f(h_PointSize, m_spriteSize);
EGLint linked;
glGetProgramiv(m_programSprites, GL_LINK_STATUS, &linked);
if (!linked) {
printf("A shader failed to link.\n");
exit(1);
}
// Set base and secondary colors
GLint h_BaseColor = glGetUniformLocation(m_programSprites, "baseColor");
GLint h_SecondaryColor = glGetUniformLocation(m_programSprites, "secondaryColor");
glUniform4f(h_BaseColor, 1.0, 1.0, 1.0, 1.0);
glUniform4f(h_SecondaryColor, m_baseColor[0], m_baseColor[1], m_baseColor[2], m_baseColor[3]);
_createTexture(32);
// Set position coords
GLint h_position = glGetAttribLocation(m_programSprites, "a_position");
glBindBuffer(GL_ARRAY_BUFFER, m_pbo);
glEnableVertexAttribArray(h_position);
glVertexAttribPointer(h_position, 4, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, (GLuint *)&m_vboColor);
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, m_numParticles * 4 * sizeof(float), 0,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLuint texLoc = glGetUniformLocation(m_programSprites, "splatTexture");
glUniform1i(texLoc, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_POINTS, 0, m_numParticles);
glDisableVertexAttribArray(h_position);
glUseProgram(0);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
const char vertexShader[] = {"attribute vec4 a_position;"
"uniform mat4 projection;"
"uniform mat4 modelview;"
"uniform float size;"
"void main()"
"{"
"float pointSize = 500.0 * size;"
"vec4 vert = a_position;"
"vert.w = 1.0;"
"vec3 pos_eye = vec3(modelview * vert);"
"gl_PointSize = max(1.0, pointSize / (1.0 - pos_eye.z));"
"gl_Position = projection * modelview * a_position;"
"}"};
const char fragmentShader[] = {"uniform sampler2D splatTexture;"
"uniform lowp vec4 baseColor;"
"uniform lowp vec4 secondaryColor;"
"void main()"
"{"
"lowp vec4 textureColor = (0.6 + 0.4 * baseColor) * "
"texture2D(splatTexture, gl_PointCoord);"
"gl_FragColor = textureColor * secondaryColor;"
"}"};
// Checks if the shader is compiled.
static int CheckCompiled(GLuint shader)
{
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (!isCompiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char *infoLog = (char *)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling program:\n%s\n", infoLog);
free(infoLog);
}
return 0;
}
return 1;
}
void ParticleRenderer::_initGL()
{
m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
m_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char *v = vertexShader;
const char *f = fragmentShader;
glShaderSource(m_vertexShader, 1, &v, 0);
glShaderSource(m_fragmentShader, 1, &f, 0);
checkGLErrors("Shader Source");
glCompileShader(m_vertexShader);
glCompileShader(m_fragmentShader);
if (!CheckCompiled(m_vertexShader) || !CheckCompiled(m_fragmentShader)) {
printf("A shader failed to compile.\n");
exit(1);
}
m_programSprites = glCreateProgram();
checkGLErrors("create program");
glAttachShader(m_programSprites, m_vertexShader);
glAttachShader(m_programSprites, m_fragmentShader);
checkGLErrors("attaching shaders");
glLinkProgram(m_programSprites);
checkGLErrors("linking program");
EGLint linked;
glGetProgramiv(m_programSprites, GL_LINK_STATUS, &linked);
if (!linked) {
printf("A shader failed to link.\n");
exit(1);
}
_createTexture(32);
glGenBuffers(1, (GLuint *)&m_vboColor);
glBindBuffer(GL_ARRAY_BUFFER, m_vboColor);
glBufferData(GL_ARRAY_BUFFER, m_numParticles * 4 * sizeof(float), 0, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//------------------------------------------------------------------------------
@@ -325,50 +325,53 @@ void ParticleRenderer::_initGL() {
* EvalHermite(float pA, float pB, float vA, float vB, float u)
* @brief Evaluates Hermite basis functions for the specified coefficients.
*/
inline float evalHermite(float pA, float pB, float vA, float vB, float u) {
float u2 = (u * u), u3 = u2 * u;
float B0 = 2 * u3 - 3 * u2 + 1;
float B1 = -2 * u3 + 3 * u2;
float B2 = u3 - 2 * u2 + u;
float B3 = u3 - u;
return (B0 * pA + B1 * pB + B2 * vA + B3 * vB);
inline float evalHermite(float pA, float pB, float vA, float vB, float u)
{
float u2 = (u * u), u3 = u2 * u;
float B0 = 2 * u3 - 3 * u2 + 1;
float B1 = -2 * u3 + 3 * u2;
float B2 = u3 - 2 * u2 + u;
float B3 = u3 - u;
return (B0 * pA + B1 * pB + B2 * vA + B3 * vB);
}
unsigned char *createGaussianMap(int N) {
float *M = new float[2 * N * N];
unsigned char *B = new unsigned char[4 * N * N];
float X, Y, Y2, Dist;
float Incr = 2.0f / N;
int i = 0;
int j = 0;
Y = -1.0f;
unsigned char *createGaussianMap(int N)
{
float *M = new float[2 * N * N];
unsigned char *B = new unsigned char[4 * N * N];
float X, Y, Y2, Dist;
float Incr = 2.0f / N;
int i = 0;
int j = 0;
Y = -1.0f;
// float mmax = 0;
for (int y = 0; y < N; y++, Y += Incr) {
Y2 = Y * Y;
X = -1.0f;
// float mmax = 0;
for (int y = 0; y < N; y++, Y += Incr) {
Y2 = Y * Y;
X = -1.0f;
for (int x = 0; x < N; x++, X += Incr, i += 2, j += 4) {
Dist = (float)sqrtf(X * X + Y2);
for (int x = 0; x < N; x++, X += Incr, i += 2, j += 4) {
Dist = (float)sqrtf(X * X + Y2);
if (Dist > 1) Dist = 1;
if (Dist > 1)
Dist = 1;
M[i + 1] = M[i] = evalHermite(1.0f, 0, 0, 0, Dist);
B[j + 3] = B[j + 2] = B[j + 1] = B[j] = (unsigned char)(M[i] * 255);
M[i + 1] = M[i] = evalHermite(1.0f, 0, 0, 0, Dist);
B[j + 3] = B[j + 2] = B[j + 1] = B[j] = (unsigned char)(M[i] * 255);
}
}
}
delete[] M;
return (B);
delete[] M;
return (B);
}
void ParticleRenderer::_createTexture(int resolution) {
unsigned char *data = createGaussianMap(resolution);
glGenTextures(1, (GLuint *)&m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR); //_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, resolution, resolution, 0, GL_RGBA,
GL_UNSIGNED_BYTE, data);
void ParticleRenderer::_createTexture(int resolution)
{
unsigned char *data = createGaussianMap(resolution);
glGenTextures(1, (GLuint *)&m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR); //_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, resolution, resolution, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}

View File

@@ -31,80 +31,76 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl31.h>
#include <cstdio>
typedef float matrix4[4][4];
typedef float vector3[3];
// check for OpenGL errors
inline void checkGLErrors(const char *s) {
EGLenum error;
inline void checkGLErrors(const char *s)
{
EGLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "%s: error - %d\n", s, error);
}
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "%s: error - %d\n", s, error);
}
}
class ParticleRenderer {
public:
ParticleRenderer(unsigned int windowWidth = 720,
unsigned int windowHeight = 480);
~ParticleRenderer();
class ParticleRenderer
{
public:
ParticleRenderer(unsigned int windowWidth = 720, unsigned int windowHeight = 480);
~ParticleRenderer();
void setPositions(float *pos, int numParticles);
void setPositions(double *pos, int numParticles);
void setBaseColor(float color[4]);
void setColors(float *color, int numParticles);
void setPBO(unsigned int pbo, int numParticles, bool fp64);
void setPositions(float *pos, int numParticles);
void setPositions(double *pos, int numParticles);
void setBaseColor(float color[4]);
void setColors(float *color, int numParticles);
void setPBO(unsigned int pbo, int numParticles, bool fp64);
enum DisplayMode {
PARTICLE_POINTS,
PARTICLE_SPRITES,
PARTICLE_SPRITES_COLOR,
PARTICLE_NUM_MODES
};
enum DisplayMode { PARTICLE_POINTS, PARTICLE_SPRITES, PARTICLE_SPRITES_COLOR, PARTICLE_NUM_MODES };
void display();
void display();
void setPointSize(float size) { m_pointSize = size; }
void setSpriteSize(float size) { m_spriteSize = size; }
void setPointSize(float size) { m_pointSize = size; }
void setSpriteSize(float size) { m_spriteSize = size; }
void setCameraPos(vector3 camera_pos) {
m_camera[0] = camera_pos[0];
m_camera[1] = camera_pos[1];
m_camera[2] = camera_pos[2];
}
void setCameraPos(vector3 camera_pos)
{
m_camera[0] = camera_pos[0];
m_camera[1] = camera_pos[1];
m_camera[2] = camera_pos[2];
}
void resetPBO();
void resetPBO();
protected: // methods
void _initGL();
void _createTexture(int resolution);
protected: // methods
void _initGL();
void _createTexture(int resolution);
protected: // data
float *m_pos;
double *m_pos_fp64;
int m_numParticles;
protected: // data
float *m_pos;
double *m_pos_fp64;
int m_numParticles;
float m_pointSize;
float m_spriteSize;
vector3 m_camera;
float m_pointSize;
float m_spriteSize;
vector3 m_camera;
unsigned int m_vertexShader;
unsigned int m_vertexShaderPoints;
unsigned int m_fragmentShader;
unsigned int m_programPoints;
unsigned int m_programSprites;
unsigned int m_texture;
unsigned int m_pbo;
unsigned int m_vboColor;
unsigned int m_windowWidth;
unsigned int m_windowHeight;
unsigned int m_vertexShader;
unsigned int m_vertexShaderPoints;
unsigned int m_fragmentShader;
unsigned int m_programPoints;
unsigned int m_programSprites;
unsigned int m_texture;
unsigned int m_pbo;
unsigned int m_vboColor;
unsigned int m_windowWidth;
unsigned int m_windowHeight;
float m_baseColor[4];
float m_baseColor[4];
bool m_bFp64Positions;
bool m_bFp64Positions;
};
#endif //__ RENDER_PARTICLES__
#endif //__ RENDER_PARTICLES__

View File

@@ -17,11 +17,11 @@ struct gas_particle
Real rho;
Real temp;
Real hsmooth;
Real metals ;
Real phi ;
} ;
Real metals;
Real phi;
};
//struct gas_particle *gas_particles;
// struct gas_particle *gas_particles;
struct dark_particle
{
@@ -29,45 +29,45 @@ struct dark_particle
Real pos[MAXDIM];
Real vel[MAXDIM];
Real eps;
int phi ;
} ;
int phi;
};
//struct dark_particle *dark_particles;
// struct dark_particle *dark_particles;
struct star_particle
{
Real mass;
Real pos[MAXDIM];
Real vel[MAXDIM];
Real metals ;
Real tform ;
Real metals;
Real tform;
Real eps;
int phi ;
} ;
int phi;
};
//struct star_particle *star_particles;
// struct star_particle *star_particles;
struct dump
{
double time ;
int nbodies ;
int ndim ;
int nsph ;
int ndark ;
int nstar ;
} ;
double time;
int nbodies;
int ndim;
int nsph;
int ndark;
int nstar;
};
typedef struct dump header ;
typedef struct dump header;
template <typename real4>
void read_tipsy_file(vector<real4> &bodyPositions,
vector<real4> &bodyVelocities,
vector<int> &bodiesIDs,
void read_tipsy_file(vector<real4> &bodyPositions,
vector<real4> &bodyVelocities,
vector<int> &bodiesIDs,
const std::string &fileName,
int &NTotal,
int &NFirst,
int &NSecond,
int &NThird)
int &NTotal,
int &NFirst,
int &NSecond,
int &NThird)
{
/*
Read in our custom version of the tipsy file format written by
@@ -82,59 +82,55 @@ void read_tipsy_file(vector<real4> &bodyPositions,
ifstream inputFile(fullFileName, ios::in | ios::binary);
if (!inputFile.is_open())
{
if (!inputFile.is_open()) {
cout << "Can't open input file \n";
exit(EXIT_SUCCESS);
}
dump h;
dump h;
inputFile.read((char *)&h, sizeof(h));
int idummy;
int idummy;
real4 positions;
real4 velocity;
//Read tipsy header
NTotal = h.nbodies;
NFirst = h.ndark;
NSecond = h.nstar;
NThird = h.nsph;
// Read tipsy header
NTotal = h.nbodies;
NFirst = h.ndark;
NSecond = h.nstar;
NThird = h.nsph;
//Start reading
// Start reading
int particleCount = 0;
dark_particle d;
star_particle s;
for (int i=0; i < NTotal; i++)
{
if (i < NFirst)
{
for (int i = 0; i < NTotal; i++) {
if (i < NFirst) {
inputFile.read((char *)&d, sizeof(d));
velocity.w = d.eps;
positions.w = d.mass;
positions.x = d.pos[0];
positions.y = d.pos[1];
positions.z = d.pos[2];
velocity.x = d.vel[0];
velocity.y = d.vel[1];
velocity.z = d.vel[2];
idummy = d.phi;
velocity.w = d.eps;
positions.w = d.mass;
positions.x = d.pos[0];
positions.y = d.pos[1];
positions.z = d.pos[2];
velocity.x = d.vel[0];
velocity.y = d.vel[1];
velocity.z = d.vel[2];
idummy = d.phi;
}
else
{
else {
inputFile.read((char *)&s, sizeof(s));
velocity.w = s.eps;
positions.w = s.mass;
positions.x = s.pos[0];
positions.y = s.pos[1];
positions.z = s.pos[2];
velocity.x = s.vel[0];
velocity.y = s.vel[1];
velocity.z = s.vel[2];
idummy = s.phi;
velocity.w = s.eps;
positions.w = s.mass;
positions.x = s.pos[0];
positions.y = s.pos[1];
positions.z = s.pos[2];
velocity.x = s.vel[0];
velocity.y = s.vel[1];
velocity.z = s.vel[2];
idummy = s.phi;
}
bodyPositions.push_back(positions);
@@ -142,18 +138,16 @@ void read_tipsy_file(vector<real4> &bodyPositions,
bodiesIDs.push_back(idummy);
particleCount++;
}//end for
} // end for
// round up to a multiple of 256 bodies since our kernel only supports that...
int newTotal = NTotal;
if (NTotal % 256)
{
if (NTotal % 256) {
newTotal = ((NTotal / 256) + 1) * 256;
}
for (int i = NTotal; i < newTotal; i++)
{
for (int i = NTotal; i < newTotal; i++) {
positions.w = positions.x = positions.y = positions.z = 0;
velocity.x = velocity.y = velocity.z = 0;
bodyPositions.push_back(positions);