/* Monte-Carlo simulation code for statistical physics Copyright (C) 2001-2005 Sylvain Reynal Département de Physique Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA) 6, avenue du Ponceau, F-95014 CERGY CEDEX et Laboratoire de Physique Théorique et Modélisation (LPTM) Université de Cergy-Pontoise - Site de Neuville F-95031 CERGY CEDEX Tel : 00 +33 130 736 245 Fax : 00 +33 130 736 667 e-mail : reynal@ensea.fr web page : http://www.ensea.fr/staff/reynal/ */ package fr.ensea.montecarlo.canonical; import java.io.*; import java.awt.Color; import java.text.*; import fr.ensea.Localizer; import fr.ensea.montecarlo.model.*; import fr.ensea.montecarlo.data.*; import fr.ensea.montecarlo.canonical.*; import fr.ensea.montecarlo.misc.*; /** * Monte-carlo algorithm with Metropolis updates (=single-spin updates) for the 2D Potts model */ public class PottsMetropolis extends AbstractMetropolis { private PottsLattice lattice; // --- RG specific --- private PottsLattice[] latticeRG; private int factorRG; private double[] probas; // contains acceptance probabilities whenever dE > 0 (only valid if external field is null) // (negative dE yield a unit proba anyway) // example : // 3 3 // 1 2 2 => 1 3 2 yields dE = -1 // 3 3 // /** * Init a new MC algorithm * @param energySamples list for energy measurements * @param magnetizationSamples list for magnetization measurements * @param lattice lattice to be simulated * @param kT default temperature */ public PottsMetropolis(PottsLattice lattice, SamplesBag bag, double kT) { super(bag, kT); this.lattice = lattice; } /** * Alters the current temperature and reset counters */ public synchronized void setTemperature(double kT){ super.setTemperature(kT); this.probas=new double[5]; if (kT>0) for (int dE=1; dE<5; dE++) probas[dE] = Math.exp(-(double)dE/kT); // otherwise, when kT==0, probabilities are null for an update with positive dE } public void activateRG(){ setFactorRG(1); } public void setFactorRG(int f){ if (f<1) f=1; this.factorRG=f; latticeRG = new PottsLattice[factorRG]; latticeRG[factorRG-1] = lattice.renormalize(latticeRG[factorRG-1]); for (int s=factorRG-2; s >= 0; s--){ latticeRG[s] = latticeRG[s+1].renormalize(latticeRG[s]); } } public PottsLattice getRGLattice(){ return latticeRG[0]; } /** * Réalise un sweep de l'ensemble du réseau, i.e. tente de mettre à jour L*L spins. */ public void sweep(){ int indexSpin, nouvelleValeur; double dE; final int Q = lattice.pottsQ; final int qmax = Q-1; final int L2 = lattice.size2; for (int pas=0; pas < L2; pas++){ attemptedMoves++; // draw one spin to be updated at random amongst L^2 spins: indexSpin = (int)(L2 * createRandomNumber()); // choose a new value for this spin: nouvelleValeur = lattice.getSpinValue(indexSpin) + 1 + (int)(createRandomNumber() * qmax); if (nouvelleValeur > qmax) nouvelleValeur -= Q; // make sure the new value belongs to [0,Q-1] dE = lattice.getEnergyChange(indexSpin, nouvelleValeur); if (DEBUG) { System.out.println(lattice.toString()); System.out.println("indexSpin=" + indexSpin); System.out.println("nouvelleValeur=" + nouvelleValeur); System.out.println("dE=" + dE); //System.out.println("proba=" + (dE > 0 ? probas[dE] : 1.0)); } if (lattice.getMagneticField()==0){ // attempt move: if (dE <= 0.0 || createRandomNumber() <= probas[(int)dE]){ acceptedMoves++; lattice.setSpinValue(indexSpin, nouvelleValeur); lattice.energy += dE; if (DEBUG) System.out.println("Acceptée !\n"+lattice.toString()); } } else { if (dE <= 0.0 || createRandomNumber() <= Math.exp(-dE/kT)){ acceptedMoves++; lattice.setSpinValue(indexSpin, nouvelleValeur); lattice.energy += dE; if (DEBUG) System.out.println("Acceptée !\n"+lattice.toString()); } } if (DEBUG) { System.out.println("======================================================="); pause(); } } samplesBag.addEnergySample(lattice.getEnergy()/lattice.size2); samplesBag.addMagnetizationSample(lattice.getMagnetization()); if (latticeRG != null){ // means RG has been activated latticeRG[factorRG-1] = lattice.renormalize(latticeRG[factorRG-1]); for (int s=factorRG-2; s >= 0; s--){ latticeRG[s] = latticeRG[s+1].renormalize(latticeRG[s]); } samplesBag.addEnergyRGSample(latticeRG[0].getEnergy()/latticeRG[0].size2); } } }