Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

mcljsimulation.cpp

Go to the documentation of this file.
00001 /***************************************************************************************************
00002 *****           Copyright (C) 2005 John Schneiderman <JohnMS@member.fsf.org>                   *****
00003 *****                                                                                          *****
00004 *****           This program is free software; you can redistribute it and/or modify           *****
00005 *****           it under the terms of the GNU General Public License as published by           *****
00006 *****           the Free Software Foundation; either version 2 of the License, or              *****
00007 *****           (at your option) any later version.                                            *****
00008 *****                                                                                          *****
00009 *****           This program is distributed in the hope that it will be useful,                *****
00010 *****           but WITHOUT ANY WARRANTY; without even the implied warranty of                 *****
00011 *****           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                  *****
00012 *****           GNU General Public License for more details.                                   *****
00013 *****                                                                                          *****
00014 *****           You should have received a copy of the GNU General Public License              *****
00015 *****           along with this program; if not, write to the Free Software                    *****
00016 *****           Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA     *****
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     // Open files.
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     // Pre-run operations and manipulations follow.
00064     m_stepStart = findLastStep(previousRun);
00065     cluster.calculateCentreMass();
00066     cluster.calculatePotentialEnergy();
00067     m_potentialEnergy = cluster.potentialEnergyTotal();
00068 
00069     /* The big outer loop is the "step" loop.  For each step
00070       we make n attempted moves (n = # atoms).  Hence the double loop.
00071       We choose the particles sequentially, going through each
00072       one in turn and trying to move it.
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         //timeStep = step * changeInTime + m_stepStart;
00082         //Try to move an atom.
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     //Write out histograms
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;//Temperary values of time.
00145     ifstream inputFile;//The input run file.
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             //Calculate the potential energy of the Cluster in the old position.
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             //Calculate the potential energy of the Cluster in the new position.
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 }

Generated on Tue Mar 28 23:28:03 2006 for ClusterSim by  doxygen 1.4.4