Compare commits

..

No commits in common. "7041c6d48531e7b8ba31fa2a84db93395c2c1fc3" and "952e31449fc82ecb2b4ea56e8a6cacd4af87830b" have entirely different histories.

5 changed files with 126 additions and 96 deletions

View File

@ -4,18 +4,13 @@
#include "DLASystem.h" #include "DLASystem.h"
using std::cout;
using std::endl;
// this function gets called every step, // this function gets called every step,
// if there is an active particle then it gets moved, // if there is an active particle then it gets moved,
// if not then add a particle // if not then add a particle
void DLASystem::Update() { void DLASystem::Update() {
this->frame++;
if (lastParticleIsActive == 1) { if (lastParticleIsActive == 1) {
moveLastParticle(); moveLastParticle();
} else if (this->particleList.size() < (size_t) endNum) { } else if (numParticles < endNum) {
addParticleOnAddCircle(); addParticleOnAddCircle();
setParticleActive(); setParticleActive();
} else { } else {
@ -25,17 +20,17 @@ void DLASystem::Update() {
void DLASystem::clearParticles() { void DLASystem::clearParticles() {
// delete particles and the particle list // delete particles and the particle list
for (size_t i = 0; i < this->particleList.size(); i++) { for (int i = 0; i < numParticles; i++) {
delete particleList[i]; delete particleList[i];
} }
particleList.clear(); particleList.clear();
numParticles = 0;
} }
// remove any existing particles and setup initial condition // remove any existing particles and setup initial condition
void DLASystem::Reset() { void DLASystem::Reset() {
// stop running // stop running
running = false; running = 0;
frame = 0;
clearParticles(); clearParticles();
@ -55,6 +50,11 @@ void DLASystem::Reset() {
// add a single particle at the origin // add a single particle at the origin
double pos[] = {0.0, 0.0}; double pos[] = {0.0, 0.0};
addParticle(pos); addParticle(pos);
// set the view
int InitialViewSize = 40;
setViewSize(InitialViewSize);
} }
// set the value of a grid cell for a particular position // set the value of a grid cell for a particular position
@ -71,12 +71,23 @@ int DLASystem::readGrid(double pos[]) {
return grid[(int) (pos[0] + halfGrid)][(int) (pos[1] + halfGrid)]; return grid[(int) (pos[0] + halfGrid)][(int) (pos[1] + halfGrid)];
} }
// check if the cluster is big enough and we should stop:
// to be safe, we need the killCircle to be at least 2 less than the edge of the grid
int DLASystem::checkStop() {
if (killCircle + 2 >= gridSize / 2) {
pauseRunning();
cout << "STOP" << endl;
return 1;
} else return 0;
}
// add a particle to the system at a specific position // add a particle to the system at a specific position
void DLASystem::addParticle(double pos[]) { void DLASystem::addParticle(double pos[]) {
// create a new particle // create a new particle
Particle *p = new Particle(pos); Particle *p = new Particle(pos);
// push_back means "add this to the end of the list" // push_back means "add this to the end of the list"
particleList.push_back(p); particleList.push_back(p);
numParticles++;
// pos coordinates should be -gridSize/2 < x < gridSize/2 // pos coordinates should be -gridSize/2 < x < gridSize/2
setGrid(pos, 1); setGrid(pos, 1);
@ -90,11 +101,10 @@ void DLASystem::addParticleOnAddCircle() {
double theta = rgen.random01() * 2 * M_PI; double theta = rgen.random01() * 2 * M_PI;
pos[0] = ceil(addCircle * cos(theta)); pos[0] = ceil(addCircle * cos(theta));
pos[1] = ceil(addCircle * sin(theta)); pos[1] = ceil(addCircle * sin(theta));
if (readGrid(pos) == 0) { if (readGrid(pos) == 0)
addParticle(pos); addParticle(pos);
} else { else
cout << "FAIL " << pos[0] << " " << pos[1] << endl; cout << "FAIL " << pos[0] << " " << pos[1] << endl;
}
} }
// send back the position of a neighbour of a given grid cell // send back the position of a neighbour of a given grid cell
@ -121,64 +131,88 @@ void DLASystem::setPosNeighbour(double setpos[], double pos[], int val) {
} }
} }
// if the view is smaller than the kill circle then increase the view area (zoom out)
void DLASystem::updateViewSize() {
double mult = 1.2;
if (viewSize < 2.0 * killCircle) {
setViewSize(viewSize * mult);
}
}
// set the view to be the size of the add circle (ie zoom in on the cluster)
void DLASystem::viewAddCircle() {
setViewSize(2.0 * addCircle); // factor of 2 is to go from radius to diameter
}
// when we add a particle to the cluster, we should update the cluster radius // when we add a particle to the cluster, we should update the cluster radius
// and the sizes of the addCircle and the killCircle // and the sizes of the addCircle and the killCircle
void DLASystem::updateClusterRadius(double pos[]) { void DLASystem::updateClusterRadius(double pos[]) {
double newRadius = distanceFromOrigin(pos);
if (newRadius > clusterRadius) { double rr = distanceFromOrigin(pos);
clusterRadius = newRadius; if (rr > clusterRadius) {
clusterRadius = rr;
// this is how big addCircle is supposed to be: // this is how big addCircle is supposed to be:
// either 20% more than cluster radius, or at least 5 bigger. // either 20% more than cluster radius, or at least 5 bigger.
double check = clusterRadius * addRatio; double check = clusterRadius * addRatio;
if (check < clusterRadius + 5) { if (check < clusterRadius + 5)
check = clusterRadius + 5; check = clusterRadius + 5;
}
// if it is smaller then update everything... // if it is smaller then update everything...
if (addCircle < check) { if (addCircle < check) {
addCircle = check; addCircle = check;
killCircle = killRatio * addCircle; killCircle = killRatio * addCircle;
updateViewSize();
} }
checkStop();
if (killCircle + 2 >= gridSize / 2) {
std::cerr << "Early Exit" << endl;
this->running = false;
}
} }
} }
// make a random move of the last particle in the particleList // make a random move of the last particle in the particleList
void DLASystem::moveLastParticle() { void DLASystem::moveLastParticle() {
int direction = rgen.randomInt(4); // pick a random number in the range 0-3, which direction do we hop? int rr = rgen.randomInt(4); // pick a random number in the range 0-3, which direction do we hop?
double newpos[2]; double newpos[2];
Particle *lastP = particleList[this->particleList.size() - 1]; Particle *lastP = particleList[numParticles - 1];
setPosNeighbour(newpos, lastP->pos, direction); setPosNeighbour(newpos, lastP->pos, rr);
if (distanceFromOrigin(newpos) > killCircle) { if (distanceFromOrigin(newpos) > killCircle) {
//cout << "#deleting particle" << endl;
setGrid(lastP->pos, 0); setGrid(lastP->pos, 0);
particleList.pop_back(); // remove particle from particleList particleList.pop_back(); // remove particle from particleList
numParticles--;
setParticleInactive(); setParticleInactive();
} else if (readGrid(newpos) == 0) { }
// check if destination is empty
else if (readGrid(newpos) == 0) {
setGrid(lastP->pos, 0); // set the old grid site to empty setGrid(lastP->pos, 0); // set the old grid site to empty
// update the position // update the position
particleList[this->particleList.size() - 1]->pos[0] = newpos[0]; particleList[numParticles - 1]->pos[0] = newpos[0];
particleList[this->particleList.size() - 1]->pos[1] = newpos[1]; particleList[numParticles - 1]->pos[1] = newpos[1];
setGrid(lastP->pos, 1); // set the new grid site to be occupied setGrid(lastP->pos, 1); // set the new grid site to be occupied
// check if we stick // check if we stick
if (checkStick() && this->rgen.random01() <= this->stickProbability) { if (checkStick()) {
this->csv_out << frame << "," << lastP->pos[0] << "," << lastP->pos[1] << endl; //cout << "stick" << endl;
setParticleInactive(); // make the particle inactive (stuck) setParticleInactive(); // make the particle inactive (stuck)
updateClusterRadius(lastP->pos); // update the cluster radius, addCircle, etc. updateClusterRadius(lastP->pos); // update the cluster radius, addCircle, etc.
if (numParticles % 100 == 0 && logfile.is_open()) {
logfile << numParticles << " " << clusterRadius << endl;
} }
} }
} else {
// if we get to here then we are trying to move to an occupied site
// (this should never happen as long as the sticking probability is 1.0)
cout << "reject " << rr << endl;
cout << lastP->pos[0] << " " << lastP->pos[1] << endl;
//cout << newpos[0] << " " << newpos[1] << " " << (int)newpos[0] << endl;
//printOccupied();
}
} }
// check if the last particle should stick (to a neighbour) // check if the last particle should stick (to a neighbour)
int DLASystem::checkStick() { int DLASystem::checkStick() {
Particle *lastP = particleList[this->particleList.size() - 1]; Particle *lastP = particleList[numParticles - 1];
int result = 0; int result = 0;
// loop over neighbours // loop over neighbours
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -193,28 +227,31 @@ int DLASystem::checkStick() {
// constructor // constructor
DLASystem::DLASystem(Config config) DLASystem::DLASystem() {
: stickProbability(config.stickProbability), csv_out(std::move(config.csv)), endNum(config.maxParticles) {
cout << "creating system, gridSize " << gridSize << endl; cout << "creating system, gridSize " << gridSize << endl;
rgen.setSeed(config.seed); numParticles = 0;
endNum = 1000;
// allocate memory for the grid, remember to free the memory in destructor // allocate memory for the grid, remember to free the memory in destructor
grid = new int *[gridSize]; grid = new int *[gridSize];
for (int i = 0; i < gridSize; i++) { for (int i = 0; i < gridSize; i++) {
grid[i] = new int[gridSize]; grid[i] = new int[gridSize];
} }
slowNotFast = 1;
// reset initial parameters // reset initial parameters
Reset(); Reset();
this->csv_out << 0 << "," << 0 << "," << 0 << std::endl;
addRatio = 1.2; // how much bigger the addCircle should be, compared to cluster radius addRatio = 1.2; // how much bigger the addCircle should be, compared to cluster radius
killRatio = 1.7; // how much bigger is the killCircle, compared to the addCircle killRatio = 1.7; // how much bigger is the killCircle, compared to the addCircle
// this opens a logfile, if we want to...
//logfile.open("opfile.txt");
} }
// destructor // destructor
DLASystem::~DLASystem() { DLASystem::~DLASystem() {
// strictly we should not print inside the destructor but never mind...
cout << "deleting system" << endl;
// delete the particles // delete the particles
clearParticles(); clearParticles();
// delete the grid // delete the grid
@ -222,9 +259,6 @@ DLASystem::~DLASystem() {
delete[] grid[i]; delete[] grid[i];
delete[] grid; delete[] grid;
csv_out.flush(); if (logfile.is_open())
logfile.close();
if (csv_out.is_open()) {
csv_out.close();
}
} }

View File

@ -15,20 +15,15 @@
#include "Particle.h" #include "Particle.h"
#include "rnd.h" #include "rnd.h"
class Config { using namespace std;
public:
int seed;
double stickProbability;
std::ofstream csv;
int maxParticles;
Config(int argc, char **argv);
};
class DLASystem { class DLASystem {
private: private:
// these are private variables and functions that the user will not see // these are private variables and functions that the user will not see
// list of particles // list of particles
std::vector<Particle *> particleList; vector<Particle *> particleList;
int numParticles;
// delete particles and clear the particle list // delete particles and clear the particle list
void clearParticles(); void clearParticles();
@ -39,17 +34,19 @@ private:
double addCircle; double addCircle;
double killCircle; double killCircle;
double stickProbability;
// size of grid // size of grid
static const int gridSize = 1600; static const int gridSize = 1600;
int **grid; // this will be a 2d array that stores whether each site is occupied int **grid; // this will be a 2d array that stores whether each site is occupied
// the window draws only part of the grid, viewSize controls how much...
double viewSize;
double drawScale;
// random number generator, class name is rnd, instance is rgen // random number generator, class name is rnd, instance is rgen
rnd rgen; rnd rgen;
// output file (not used at the moment) // output file (not used at the moment)
std::ofstream csv_out; ofstream logfile;
// number of particles at which the simulation will stop // number of particles at which the simulation will stop
// (the value is set in constructor) // (the value is set in constructor)
@ -59,7 +56,6 @@ private:
double addRatio; // how much bigger the addCircle should be, compared to cluster radius double addRatio; // how much bigger the addCircle should be, compared to cluster radius
double killRatio; // how much bigger is the killCircle, compared to the addCircle double killRatio; // how much bigger is the killCircle, compared to the addCircle
int frame;
public: public:
// these are public variables and functions // these are public variables and functions
@ -69,13 +65,16 @@ public:
void Update(); void Update();
// is the simulation running (1) or paused (0) ? // is the simulation running (1) or paused (0) ?
bool running; int running;
// slowNotFast is +1 for slow running, 0 for fast
int slowNotFast;
// lastParticleIsActive is +1 if there is an active particle in the system, otherwise 0 // lastParticleIsActive is +1 if there is an active particle in the system, otherwise 0
int lastParticleIsActive; int lastParticleIsActive;
// constructor // constructor
DLASystem(Config config); DLASystem();
// destructor // destructor
~DLASystem(); ~DLASystem();
@ -86,9 +85,34 @@ public:
// this sets the seed for the random numbers // this sets the seed for the random numbers
void setSeed(int s) { rgen.setSeed(s); } void setSeed(int s) { rgen.setSeed(s); }
void setRunning() { running = true; } // check whether we should stop (eg the cluster has reached the edge of the grid)
int checkStop();
void pauseRunning() { running = false; } // stop/start the algorithm
void setRunning() { if (checkStop() == true) running = 1; }
void pauseRunning() { running = 0; }
// set whether it runs fast or slow
void setSlow() { slowNotFast = 1; }
void setFast() { slowNotFast = 0; }
void setSuperFast() { slowNotFast = -1; }
// set which part of the grid is visible on the screen
// basically the screen shows co-ordinates -vv < x < vv
// where vv is the input value
void setViewSize(double vv) {
viewSize = vv;
drawScale = 2.0 / viewSize;
}
// if the killcircle is almost as big as the view then increase the view
void updateViewSize();
// set the view to be the approx size of the addCircle
void viewAddCircle();
// if pos is outside the cluster radius then set clusterRadius to be the distance to pos. // if pos is outside the cluster radius then set clusterRadius to be the distance to pos.
void updateClusterRadius(double pos[]); void updateClusterRadius(double pos[]);

View File

@ -10,7 +10,7 @@
CXX = clang++ CXX = clang++
CXXFLAGS = -Wall -Wextra -g -O0 -std=c++20 -stdlib=libc++ CXXFLAGS = -Wall -Wextra -g -O0
IFLAGS = -I/usr/local/include -I/usr/include IFLAGS = -I/usr/local/include -I/usr/include

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
parallel "../run {1} {2} {3}" ::: $(seq 0 10) ::: $(seq 0 0.05 1) ::: 1000

View File

@ -6,41 +6,18 @@
#include "DLASystem.h" #include "DLASystem.h"
using std::cout;
using std::endl;
// this is a global pointer, which is how we access the system itself // this is a global pointer, which is how we access the system itself
DLASystem *sys; DLASystem *sys;
Config::Config(int argc, char **argv) {
if (argc != 4) {
exit(1);
} else {
this->seed = std::stoi(argv[1]);
this->stickProbability = std::stod(argv[2]);
this->maxParticles = std::stoi(argv[3]);
if (stickProbability <= 0 || stickProbability > 1) {
exit(1);
}
std::stringstream str;
// Ensure the output file name contains all information required to replicate data
str << "./out-" << seed << '-' << stickProbability << "-" << maxParticles << ".csv";
std::ofstream csv_out(str.str());
this->csv = std::move(csv_out);
this->csv << "frame" << "," << "x" << "," << "y" << std::endl;
}
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
Config config(argc, argv);
cout << "Seed: " << config.seed << ", Stick P: " << config.stickProbability << endl;
// create the system // create the system
sys = new DLASystem(std::move(config)); sys = new DLASystem();
sys->setRunning();
// this is the seed for the random numbers
int seed = 6;
cout << "setting seed " << seed << endl;
sys->setSeed(seed);
sys->running = true;
/* /*
* NOTE: We run at max speed as rendering is handled by a different engine so we simply want to hjand * NOTE: We run at max speed as rendering is handled by a different engine so we simply want to hjand
@ -49,7 +26,5 @@ int main(int argc, char **argv) {
sys->Update(); sys->Update();
} }
cout << "hey" << endl;
return 0; return 0;
} }