/*  Monte-Carlo simulation code for statistical physics
    Copyright (C) 2001-2004  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 fr.ensea.*;
import fr.ensea.montecarlo.data.*;
import java.io.*;
import java.text.*;
import java.util.Locale;

/**
 * Superclass for multicanonical MC algorithms
 */
public abstract class WangLandau  {

	protected static final boolean DEBUG = false;
	
	protected SamplesBag samplesBag; // data bag to store thermal averages
	protected WLDOSHistogram wlDosHistogram; // energy histogram + stores S(E)

	protected NumberFormat nfPercent;
	protected long attemptedMoves; // nombre de mises-à-jour tentées
	protected long acceptedMoves; // nombre de mises-à-jour acceptées

	/**
	 * Initialize a new Wang-Landau algorithm
	 * @param dE histogram bin width
	 * @param weight initial weight for updating S(E), i.e. S(E)+=weight.
	 */
	public WangLandau(SamplesBag bag, double dE, double weight) {
		this.samplesBag = bag;
		wlDosHistogram = new WLDOSHistogram(dE,weight); // dE , weight
		nfPercent = NumberFormat.getPercentInstance(Locale.US);
		nfPercent.setGroupingUsed(false);
		nfPercent.setMaximumFractionDigits(0);
		reinitCounters();
	}

	/**
	 * Reinit acceptance rate counters
	 */
	public synchronized void reinitCounters(){
		this.acceptedMoves = this.attemptedMoves = 0;
	}
	
	/**
	 * Return the acceptance rate
	 */
	public double getAcceptanceRate(){
		if (attemptedMoves==0) return 0;
		return (double)acceptedMoves/(double)attemptedMoves;
	}
		
	public String getCountersRateLabel(){
		return Localizer.get("AcceptedMoves")+"="+nfPercent.format(getAcceptanceRate());
	}		

	/**
	 * Freshly generates a new random number
	 */
	public double createRandomNumber(){
		return Math.random();
	}

	/**
	 * Réalise un sweep de l'ensemble du réseau, i.e. tente de mettre à jour L*L spins.
	 * Attempts to update L*L spins
	 */
	public abstract void sweep();


	
	/////////////////////////////////////////////////////////////////////////////////
	// Utilities
	/////////////////////////////////////////////////////////////////////////////////

	protected void pause(){
		try {
			System.in.read();
		}
		catch (IOException e){}
	}
}

