package simulate;

import java.util.Random;
import simulate.units.*;

public class MCMoveVolume extends MCMove {
    
    private final Random rand = new Random();
    protected double pressure;
    protected Unit.Pressure pressureUnit; 

    public MCMoveVolume() {
        super();
        setStepSizeMax(1.0);
        setStepSizeMin(0.0);
        setStepSize(0.10);
        setPressure(Default.PRESSURE, Default.PRESSURE_UNIT);
    }
    
    public void thisTrial(Phase phase) {
        double hOld, hNew, vOld, vNew;
        vOld = phase.volume();
        hOld = phase.energy.potential() + pressure*vOld;
        double vScale = (2.*rand.nextDouble()-1.)*stepSize;
        vNew = vOld * Math.exp(vScale); //Step in ln(V)
        double rScale = Math.exp(vScale/(double)Simulation.D);
        phase.inflate(rScale);
        hNew = phase.energy.potential() + pressure*vNew;
        if(hNew >= Double.MAX_VALUE ||
             Math.exp(-(hNew-hOld)/parentIntegrator.temperature+(phase.moleculeCount+1)*vScale)
                < rand.nextDouble()) 
            {  //reject
              phase.inflate(1.0/rScale);
            }
        nAccept++;   //accept
    }
    
  // Pressure and its units
    public final void setPressure(double p, Unit.Pressure u) {
        pressureUnit = u;
        setPressure(p);
    }
    public void setPressure(double p) {pressure = pressureUnit.toSim(p);}
    public final double getPressure() {return pressureUnit.fromSim(pressure);}
    public final double pressure() {return pressure;}
    public final void setPressureUnit(Unit.Pressure u) {pressureUnit = u;}
    public Unit.Pressure getPressureUnit() {return pressureUnit;}
    public final void setLogPressure(int lp) {setPressure(Math.pow(10.,(double)lp));}
}