00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mcljsimulation.h"
00019 #include "atom.h"
00020 #include "cluster.h"
00021 #include "configurationdatabase.h"
00022 #include "coordinate.h"
00023
00024 #include <fstream>
00025 using std::ifstream;
00026 using std::ofstream;
00027 using std::cout;
00028
00029 #include <iomanip>
00030 using std::ios;
00031 using std::showpos;
00032 using std::setw;
00033
00034 #include <cmath>
00035
00036 MCLJ_Simulation::MCLJ_Simulation(const ConfigurationDatabase &conf):MC_Simulation(conf)
00037 {
00038 time_t seconds;
00039
00040 m_potentialEnergy = 0.0;
00041 time(&seconds);
00042 srand((unsigned int) seconds);
00043 }
00044
00045 void MCLJ_Simulation::run(Cluster& cluster, string currentRun, string previousRun)
00046 {
00047 int numTried = 0, numAccepted = 0;
00048 double potEngDiff, potentialPart, eDV, ranc, acceptRatio;
00049 Coordinate distanceToMove, testPosition;
00050 ofstream runFile, mscFile;
00051 string currentRunFile = currentRun + ".run", mscFilename = currentRun + ".mis";
00052
00053
00054 runFile.open(currentRunFile.c_str());
00055 runFile.precision(Cluster::PRECISION);
00056 runFile.setf(ios::scientific);
00057 runFile.setf(ios::showpos);
00058 mscFile.open(mscFilename.c_str());
00059 mscFile.precision(Cluster::PRECISION);
00060 mscFile.setf(ios::scientific);
00061 mscFile.setf(ios::showpos);
00062
00063
00064 m_stepStart = findLastStep(previousRun);
00065 cluster.calculateCentreMass();
00066 cluster.calculatePotentialEnergy();
00067 m_potentialEnergy = cluster.potentialEnergyTotal();
00068
00069
00070
00071
00072
00073
00074 mscFile << "Number of steps = " << m_runSteps << " at T* = " << m_temperature << endl;
00075 mscFile << "Current run name = " << currentRun << endl;
00076 mscFile << "Previous run name = " << previousRun << endl;
00077 mscFile <<"For the input Cluster-energy (over epsilon, per particle): " << m_potentialEnergy/cluster.size() << endl;
00078 cout << "Step" << setw(Cluster::WIDTH) << "Potential Energy" << setw(Cluster::WIDTH) << "Accept Ratio" << endl;
00079 for(int step = 0; step < m_runSteps; ++step)
00080 {
00081
00082
00083 for(int i = 0; i < cluster.size(); ++i)
00084 {
00085 numTried++;
00086 distanceToMove=generateDistanceToMove();
00087 testPosition = distanceToMove + cluster[i].properties.position;
00088 potEngDiff=potentialEnergyDifference(cluster, cluster[i], testPosition);
00089 if (isAcceptableMove(potEngDiff))
00090 {
00091 cluster[i].properties.position = testPosition;
00092 ++numAccepted;
00093 m_potentialEnergy+=potEngDiff;
00094 potentialPart = m_potentialEnergy/cluster.size();
00095 }
00096 else
00097 {
00098 eDV = exp(-potEngDiff/m_temperature);
00099 ranc = double(rand())/RAND_MAX;
00100 if (eDV > ranc)
00101 {
00102 cluster[i].properties.position = testPosition;
00103 ++numAccepted;
00104 m_potentialEnergy+=potEngDiff;
00105 potentialPart = m_potentialEnergy/cluster.size();
00106 }
00107 }
00108 }
00109 potentialPart = m_potentialEnergy/cluster.size();
00110 cluster.calculatePotentialEnergy();
00111 acceptRatio = double(numAccepted)/double(numTried);
00112 m_accumPotentialTotal += potentialPart;
00113 m_accumPotentialSQ += (potentialPart * potentialPart);
00114 if ((step % m_radialDensityHistogram.pullingInterval()) == 0)
00115 m_radialDensityHistogram.acquire(cluster);
00116 if ((step % m_radialDistributionFunction.pullingInterval()) == 0)
00117 m_radialDistributionFunction.acquire(cluster);
00118 if ((step % m_potentialEnergyHistogram.pullingInterval()) == 0)
00119 {
00120 cluster.calculatePotentialEnergy();
00121 m_potentialEnergyHistogram.acquire(cluster);
00122 }
00123 if( (step % m_printInterval) == 0)
00124 {
00125 runFile << step << setw(Cluster::WIDTH) << potentialPart << setw(Cluster::WIDTH) << acceptRatio << endl;
00126 cout << step << setw(Cluster::WIDTH) << potentialPart << setw(Cluster::WIDTH) << acceptRatio << endl;
00127 }
00128 }
00129 runFile << m_runSteps << setw(Cluster::WIDTH) << potentialPart << setw(Cluster::WIDTH) << acceptRatio << endl;
00130 cout << m_runSteps << setw(Cluster::WIDTH) << potentialPart << setw(Cluster::WIDTH) << acceptRatio << endl;
00131 writeAverages(mscFile, cluster);
00132 mscFile.close();
00133 runFile.close();
00134
00135
00136 m_radialDensityHistogram.write(cluster.size(), currentRun);
00137 m_radialDistributionFunction.write(cluster.size(), currentRun);
00138 m_kineticEnergyHistogram.write(cluster.size(), currentRun);
00139 m_potentialEnergyHistogram.write(cluster.size(), currentRun);
00140 }
00141
00142 double MCLJ_Simulation::findLastStep(string previousRun) const
00143 {
00144 double timeTemp=0.0, temp=0.0, temp0=0.0;
00145 ifstream inputFile;
00146 string filename = previousRun + ".run";
00147
00148 inputFile.open(filename.c_str());
00149 while(!inputFile.fail())
00150 inputFile >> timeTemp >> temp >> temp0;
00151 inputFile.close();
00152 return timeTemp;
00153 }
00154
00155 Coordinate MCLJ_Simulation::generateDistanceToMove() const
00156 {
00157 Coordinate distance;
00158
00159 distance.x = m_changeInStep * ((double(rand()) / RAND_MAX) - 0.5);
00160 distance.y = m_changeInStep * ((double(rand()) / RAND_MAX) - 0.5);
00161 distance.z = m_changeInStep * ((double(rand()) / RAND_MAX) - 0.5);
00162 return distance;
00163 }
00164
00165 bool MCLJ_Simulation::isAcceptableMove(double potentialEnergyDifference) const
00166 {
00167 if( potentialEnergyDifference <= 0.0)
00168 return true;
00169 else
00170 return false;
00171 }
00172
00173 double MCLJ_Simulation::potentialEnergyDifference(const Cluster &cluster, const Atom &examinedAtom, const Coordinate &testPosition) const
00174 {
00175 double potEngOld=0.0, potEngNew=0.0, rsqold, sr2, sr6, sr12, rsqnew;
00176 Coordinate rijOld, rijNew;
00177
00178 for(int i=0; i < cluster.size(); ++i)
00179 {
00180 if(cluster[i] != examinedAtom)
00181 {
00182
00183 rijOld = cluster[i].properties.position - examinedAtom.properties.position;
00184 rsqold = (rijOld.x * rijOld.x) + (rijOld.y * rijOld.y) + (rijOld.z * rijOld.z);
00185 sr2 = 1.0 / rsqold;
00186 sr6 = sr2 * sr2 * sr2;
00187 sr12 = sr6 * sr6;
00188 potEngOld += (4.0) * (sr12 - sr6);
00189
00190
00191 rijNew = cluster[i].properties.position - testPosition;
00192 rsqnew = (rijNew.x * rijNew.x) + (rijNew.y * rijNew.y) + (rijNew.z * rijNew.z);
00193 sr2 = 1.0 / rsqnew;
00194 sr6 = sr2 * sr2 * sr2;
00195 sr12= sr6 * sr6;
00196 potEngNew += (4.0)*(sr12 - sr6);
00197 }
00198 }
00199 return potEngNew - potEngOld;
00200 }