/*  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.multicanonical;

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.*;

/**
 * Wang-Landau algorithm with single-spin updates for the 2D Potts model
 */
public class PottsWL extends WangLandau {

	private PottsLattice lattice;
	
	/**
	 * Init a new WL algorithm
	 * @param weight initial weight for updating S(E), i.e. S(E)+=weight.
	 * @param dE histogram bin width
	 */
	public PottsWL(PottsLattice lattice, SamplesBag bag, double dE, double weight) {
		super(bag, dE, weight);
		this.lattice = lattice;
	}

	/**
	 * Attempts to update L*L spins.
	 */
	public void sweep(){

		int indexSpin,  newVal;
		double dE, oldSE, newSE;
		final int Q = lattice.pottsQ;
		final int qmax = Q-1;
		final int L2 = lattice.size2;

		for (int step=0; step < L2; step++){

			attemptedMoves++;

			// draw one spin to be updated at random amongst L^2 spins:
			indexSpin = (int)(L2 * createRandomNumber());

			// choose a new value for this spin:
			newVal = lattice.getSpinValue(indexSpin) + 1 + (int)(createRandomNumber() * qmax);
			if (newVal > qmax) newVal -= Q; // make sure the new value belongs to [0,Q-1]

			oldSE = wlDosHistogram.getSE(lattice.getEnergy());
			dE = lattice.getEnergyChange(indexSpin, newVal);
			newSE = wlDosHistogram.getSE(lattice.getEnergy()+dE);

			if (newSE <= oldSE || createRandomNumber() <= Math.exp(oldSE-newSE)){
				acceptedMoves++;
				lattice.setSpinValue(indexSpin, newVal);
				lattice.energy += dE;
			}
		}
		samplesBag.addEnergySample(lattice.getEnergy()/lattice.size2);
		samplesBag.addMagnetizationSample(lattice.getMagnetization());
		wlDosHistogram.fill(lattice.getEnergy());
	}

	
}

