I’m writing a small program to calculate a physics problem but I’m having problems erasing elements from a 2D array. I’m compiling with XCode (so GDB).
The problem always comes in the walker.erase(walker.begin()+loacationInArray) part (in the void diffuseWalkers function), and always after a different number of function calls. So sometimes, the ‘thermalisation’ loop runs maybe 50 times, other times it runs all the way through. I usually get an EXC_BAD_ACCESS error, and very occasionally a malloc error.
Any help would be much appreciated as I’ve tried everything and really can’t see what I’m doing wrong. I’ve posted the code below. A header file called ‘heliumHeader.h’ contains some mathematical functions that aren’t really important for my problem.
#include "heliumHeader.h"
void copyVectorInformation(vector<double>& walker, vector<double>& walkerTemp);
void diffuseWalker(double beta, double a, double alpha, int locationInArray, vector<double>& walker, double dt,
double& trialEnergy, int& numberOfWalkers, int targetNumberOfWalkers);
using namespace std;
int main(){
srand(time(NULL));
double s=0.; //inter-molecular distance
double beta = 0.15;
double alpha = 2.;
double dt=0.1;
int numberOfWalkers = 1; //number of particles
int targetNumberOfWalkers = numberOfWalkers;
//2D-vectors to hold information
vector<vector<double> > walker(numberOfWalkers,6);
//solve for a
double a = 1.;
for(int i=0; i<20;i++)
a = 1./(1.+exp(-s/a));
//set up sums
double localEnergy, trialEnergy, localEnergy2, trialEnergy2;
localEnergy = trialEnergy = localEnergy2 = trialEnergy2 = 0.;
//put the walkers randomly in space & get the energy of that configuration
for(int i=0; i<walker.size(); i++){
for(int j=0; j<6; j++)
walker[i][j]=randomPositiveNegative();
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
}
localEnergy /= numberOfWalkers;
double beforeEnergy = localEnergy;
cout << "local energy of random " << localEnergy << endl;
trialEnergy = -2.903;
//move the walkers
for(int thermalisationCounter = 1; thermalisationCounter<1000; thermalisationCounter++){
for(int i=0; i<walker.size(); i++)
diffuseWalker(beta, a, alpha, i, walker[i], dt, trialEnergy, numberOfWalkers, targetNumberOfWalkers);
cout << thermalisationCounter << endl;
}
//recalculate the local energy
for(int i=0; i<walker.size(); i++){
for(int j=0; j<6; j++)
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
}
localEnergy /= numberOfWalkers;
for(int numberOfSteps = 1; numberOfSteps<1000; numberOfSteps++){
for(int i=0; i<walker.size(); i++)
diffuseWalker(beta, a, alpha, i, walker[i], dt, trialEnergy, numberOfWalkers, targetNumberOfWalkers);
cout << numberOfSteps << endl;
}
//get initial energy of random positiions
for(int i=0; i<walker.size(); i++)
localEnergy += calculateEnergy(beta, alpha, a, walker[i]);
localEnergy /= numberOfWalkers;
cout << "before energy " << beforeEnergy << " local energy " << localEnergy <<
" trial energy " << trialEnergy << " number " << numberOfWalkers << endl;
return 0;
}
void copyVectorInformation(vector<double>& walker, vector<double>& walkerTemp){
for(int i=0; i<6; i++)
walkerTemp[i] = walker[i];
}//end of copyVectorInformation
void diffuseWalker(double beta, double a, double alpha, int locationInArray, vector<double>& walker, double dt,
double& trialEnergy, int& numberOfWalkers, int targetNumberOfWalkers){
vector<double> driftFunction(6);
vector<double> walkerTemp(6); //temporary store of information
//copy the walker information over
copyVectorInformation(walker, walkerTemp);
//get the drift functions
calculateDriftFunctions(beta, alpha, a, walker, driftFunction);
//get the old local energy
double preMoveLocalEnergy = calculateEnergy(beta, alpha, a, walker);
//move the walker
for(int j=0; j<6;j++)
walker[j] += 0.5*dt*driftFunction[j] + randomGauss()*sqrt(dt);
//caclulate the local energy of the new position
double postMoveLocalEnergy = calculateEnergy(beta, alpha, a, walker);
//calculate the weight, q and branching ration s
double q = exp(-dt*(0.5*(postMoveLocalEnergy + preMoveLocalEnergy) - trialEnergy));
double s = q+randomPositive();
if(int(s)<1){
//kill the walker
walker.erase(walker.begin()+locationInArray);
numberOfWalkers--;
}
else{
//reproduce walker int(s) number of times
for(int k=0; k<int(s); k++){
walker.push_back(walker[locationInArray]);
numberOfWalkers++;
}
}
//update the trial energy
trialEnergy += 0.2*log((double)targetNumberOfWalkers/(double)numberOfWalkers);
}//end of diffuse walkers
I think you are erasing from the wrong vector. In the
mainfunctionwalkeris a 2D vector. IndiffuseWalkeryou are erasing from thewalkerthat has been passed into the function which is a 1D vector of doubles. You uselocationInArrayand decrementnumberOfWalkershere which doesn’t make sense for the 1D walker – it looks like you want to actually erase from the 2D vector. I’d suggest using a different name for the 2D and 1D vectors to avoid confusion like this.