class IsingSimulation : public alps::scheduler::MCRun { public: IsingSimulation(const alps::ProcessList&,const alps::Parameters&,int); void save(alps::ODump&) const; void load(alps::IDump&); void dostep(); bool is_thermalized() const; double work_done() const; bool change_parameter(const std::string& name, const alps::StringValue& value); private: uint32_t length; // the system size double beta; // the inverse temperatre uint32_t sweeps; // the number of sweeps done uint32_t thermalization_sweeps; // the number of sweeps to be done for equilibration uint32_t total_sweeps; // the total number of sweeps to be done after equilibration std::vector<int> spins; // the vector to store the spins }; typedef alps::scheduler::SimpleMCFactory<IsingSimulation> IsingFactory;
int main(int argc, char** argv) { try { return alps::scheduler::start(argc,argv,IsingFactory()); } catch (std::exception& exc) { return -1; } }
If the object is just created to evaluate the simulation but not to perform actual simulations, the where data member of the simulation, specifying the processes on which a simulation will performed, will be empty. In that case the spins vectoring, storing the spins of the simulation can be resized to zero.IsingSimulation::IsingSimulation(const alps::ProcessList& w,const alps::Parameters& p,int node) : scheduler::MCRun(0,w,p,node), length(static_cast<uint32_t>(parms["L"])), beta(1./static_cast<double>(parms["T"])), thermalization_sweeps(static_cast<uint32_t>(parms["THERMALIZATION"])), total_sweeps(static_cast<uint32_t>(parms["SWEEPS"])), sweeps(0), spins(where.empty() ? 0 : length) { // initialize random spin configuration for(int i=0;i<spins.size();i++) spins[i]=(random_real() < 0.5 ? 1 : -1); // create measurement objects measurements << alea::RealObservable("Energy"); measurements << alea::RealObservable("Magnetization"); }
saves the simulation data into a checkpoint.void IsingSimulation::save(alps::ODump& dump) const { dump << sweeps << spins; }
This loads the simulation data from a checkpoint. If the object is just loaded to evaluate the simulation but not to perform actual simulations, the where data member of the simulation, specifying the processes on which a simulation will performed, will be empty. In that case reading the spin configuration can be omitted to save memory.void IsingSimulation::load(alps::IDump& dump) { dump >> sweeps; if(!where.empty()) // skip reading the spins if we are just evaluating dump >> spins; }
is called when the user tries to change a parameter while the simulation is running. In this example we only allow changes to the total number of sweeps.bool IsingSimulation::change_parameter(const std::string& name, const alps::StringValue& value) { if(name=="SWEEPS") { total_sweeps=static_cast<uint32_t>(value); return true; // can do it. } else return false; // cannot do it. }
Note:The implementation of this function is optional.
determines thermalization. Here the simulation is thermalized when a certain number of sweeps, given by the user has been performed.bool IsingSimulation::is_thermalized() const { return (sweeps >= thermalization_sweeps); }
returns the fraction of total work performed.double IsingSimulation::work_done() const { return (is_thermalized() ? (sweeps-thermalization_sweeps)/double(total_sweeps) :0.); }
performs the actual simulations and measurements.void IsingSimulation::dostep() { // increment sweep count sweeps++; // perform updates for (int j=0;j<length;j++) { // choose a random site and determine the neighbors int i = int(double(length)*random_real()); int right=(i+1 < length ? i+1 : 0); int left=( i-1 < 0 ? length-1 : i-1); // calculate change in the weight of the configuration double p=exp(2.*beta*spins[i]*(spins[right]+spins[left])); // Metropolis updating: accept if random number is smaller than p if (p>=1. || random_real() < p) spins[i]=-spins[i]; } // perform measurements int tmag=0; int ten=0; for (int i=0;i<length;i++) { int right=(i +1 < length ? i+1 : 0); tmag += spins[i]; ten += -spins[i]*spins[right]; } // normalize measurements and add them to the observables measurements.get<alea::RealObservable>("Energy") << double(ten)/length; measurements.get<alea::RealObservable>("Magnetization") << double(tmag)/length; }
can be overridden to perform extra tasks when the simulation is started and halted (e.g. opening and closing of files or (de)allocation of extra resources.void MCRun::start() const; void MCRun::halt() const;
copyright (c) 1994-2010 by Matthias Troyer
Distributed under the Boost Software License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)