#include <cstdio>
#include <iostream>
#include <vector>
#include "gravity_sim_init.h"
using namespace std;
static const bool is3D = true;
const static int total_particles = 4000;
static const int reset = 3000;
static const float min_dist = 3;
static const int width = 768, height = 768, depth = 768;
static const int gravity_constant = 20000;
float mass_range = 0;
float min_mass = 0;
void initial_conditions_rand(
af::array &mass, vector<af::array> &pos,
vector<af::array> &vels,
vector<af::array> &forces) {
for (int i = 0; i < (int)pos.size(); ++i) {
pos[i] =
af::randn(total_particles) * width + width;
vels[i] = 0 *
af::randu(total_particles) - 0.5;
}
}
void initial_conditions_galaxy(
af::array &mass, vector<af::array> &pos,
vector<af::array> &vels,
vector<af::array> &forces) {
initial_cond_consts = initial_cond_consts.T();
for (int i = 0; i < (int)pos.size(); ++i) {
pos[i] =
af::randn(total_particles) * width + width;
vels[i] = 0 * (
af::randu(total_particles) - 0.5);
}
mass = initial_cond_consts(span, 0);
pos[0] = (initial_cond_consts(span, 1) / 32 + 0.6) * width;
pos[1] = (initial_cond_consts(span, 2) / 32 + 0.3) * height;
pos[2] = (initial_cond_consts(span, 3) / 32 + 0.5) * depth;
vels[0] = (initial_cond_consts(span, 4) / 32) * width;
vels[1] = (initial_cond_consts(span, 5) / 32) * height;
vels[2] = (initial_cond_consts(span, 6) / 32) * depth;
pos[0](
seq(0, pos[0].dims(0) - 1, 2)) -= 0.4 * width;
pos[1](
seq(0, pos[0].dims(0) - 1, 2)) += 0.4 * height;
vels[0](
seq(0, pos[0].dims(0) - 1, 2)) += 4;
min_mass = min<float>(mass);
mass_range = max<float>(mass) - min<float>(mass);
}
af::array ids_from_pos(vector<af::array> &pos) {
return (pos[0].as(
u32) * height) + pos[1].
as(
u32);
}
af::array ids_from_3D(vector<af::array> &pos,
float Rx,
float Ry,
float Rz) {
(pos[1] - height / 2) *
cos(Rx) + (pos[2] - depth / 2) *
sin(Rx);
(pos[2] - depth / 2) *
cos(Rx) - (pos[2] - depth / 2) *
sin(Rx);
x2 += width / 2;
y2 += height / 2;
}
af::array ids_from_3D(vector<af::array> &pos,
float Rx,
float Ry,
float Rz,
x2 += width / 2;
y2 += height / 2;
}
void simulate(
af::array &mass, vector<af::array> &pos, vector<af::array> &vels,
vector<af::array> &forces, float dt) {
for (int i = 0; i < (int)pos.size(); ++i) {
pos[i] += vels[i] * dt;
}
vector<af::array> diff(pos.size());
for (int i = 0; i < (int)pos.size(); ++i) {
diff[i] =
tile(pos[i], 1, pos[i].dims(0)) -
dist += (diff[i] * diff[i]);
}
dist *= dist * dist;
for (int i = 0; i < (int)pos.size(); ++i) {
forces[i] = diff[i] / dist;
forces[i] =
matmul(forces[i].T(), mass);
forces[i] *= (gravity_constant);
forces[i].eval();
vels[i] += forces[i] * dt;
vels[i].eval();
}
}
void collisions(vector<af::array> &pos, vector<af::array> &vels, bool is3D) {
af::array invalid_x = -2 * (pos[0] > width - 1 || pos[0] < 0) + 1;
af::array invalid_y = -2 * (pos[1] > height - 1 || pos[1] < 0) + 1;
vels[0] = invalid_x * vels[0];
vels[1] = invalid_y * vels[1];
pos[0] = projected_px;
pos[1] = projected_py;
if (is3D) {
af::array invalid_z = -2 * (pos[2] > depth - 1 || pos[2] < 0) + 1;
vels[2] = invalid_z * vels[2];
pos[2] = projected_pz;
}
}
int main(int, char **) {
try {
"Gravity Simulation using ArrayFire");
int frame_count = 0;
const int dims = (is3D) ? 3 : 2;
vector<af::array> pos(dims);
vector<af::array> vels(dims);
vector<af::array> forces(dims);
initial_conditions_galaxy(mass, pos, vels, forces);
while (!myWindow.close()) {
af::array mid = mass(span) > (min_mass + mass_range / 3);
ids = (is3D) ? ids_from_3D(pos, 0, 0 + frame_count / 150.f, 0, mid)
: ids_from_pos(pos);
image(ids) += 4.f;
mid = mass(span) > (min_mass + 2 * mass_range / 3);
ids = (is3D) ? ids_from_3D(pos, 0, 0 + frame_count / 150.f, 0, mid)
: ids_from_pos(pos);
image(ids) += 4.f;
ids = (is3D) ? ids_from_3D(pos, 0, 0 + frame_count / 150.f, 0)
: ids_from_pos(pos);
image(ids) += 4.f;
myWindow.image(image);
frame_count++;
if (frame_count % reset == 0) {
initial_conditions_galaxy(mass, pos, vels, forces);
}
simulate(mass, pos, vels, forces, dt);
collisions(pos, vels, is3D);
}
fprintf(stderr,
"%s\n", e.
what());
throw;
}
return 0;
}
Window object to render af::arrays.
A multi dimensional data container.
dim4 dims() const
Get dimensions of the array.
const array as(dtype type) const
Casts the array into another data type.
void eval() const
Evaluate any JIT expressions to generate data for the array.
Generic object that represents size and shape.
An ArrayFire exception class.
virtual const char * what() const
Returns an error message for the exception in a string format.
seq is used to create sequences for indexing af::array
@ u32
32-bit unsigned integral values
@ AF_COLORMAP_HEAT
Heat map.
AFAPI array cos(const array &in)
C++ Interface to evaluate the cosine function.
AFAPI array sin(const array &in)
C++ Interface to evaluate the sine function.
AFAPI array sqrt(const array &in)
C++ Interface to evaluate the square root.
AFAPI array matmul(const array &lhs, const array &rhs, const matProp optLhs=AF_MAT_NONE, const matProp optRhs=AF_MAT_NONE)
C++ Interface to multiply two matrices.
AFAPI array transpose(const array &in, const bool conjugate=false)
C++ Interface to transpose a matrix.
array constant(T val, const dim4 &dims, const dtype ty=(af_dtype) dtype_traits< T >::ctype)
C++ Interface to generate an array with elements set to a specified value.
AFAPI array gaussianKernel(const int rows, const int cols, const double sig_r=0, const double sig_c=0)
C++ Interface for generating gausian kernels.
AFAPI array tile(const array &in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1)
C++ Interface to generate a tiled array.
AFAPI array randn(const dim4 &dims, const dtype ty, randomEngine &r)
C++ Interface to create an array of random numbers normally distributed.
AFAPI array randu(const dim4 &dims, const dtype ty, randomEngine &r)
C++ Interface to create an array of random numbers uniformly distributed.
AFAPI array max(const array &in, const int dim=-1)
C++ Interface to return the maximum along a given dimension.
AFAPI array min(const array &in, const int dim=-1)
C++ Interface to return the minimum along a given dimension.
AFAPI array convolve(const array &signal, const array &filter, const convMode mode=AF_CONV_DEFAULT, const convDomain domain=AF_CONV_AUTO)
C++ Interface for convolution any(one through three) dimensional signals.
AFAPI array filter(const array &image, const array &kernel)
Image Filtering.
static AFAPI timer start()
static AFAPI double stop()