package etomica.integrator.mcmove;

import etomica.Atom;
import etomica.AtomIterator;
import etomica.Default;
import etomica.Phase;
import etomica.PotentialMaster;
import etomica.action.AtomActionTranslateBy;
import etomica.action.AtomGroupAction;
import etomica.atom.iterator.AtomIteratorSinglet;
import etomica.data.meter.MeterPotentialEnergy;
import etomica.integrator.MCMove;
import etomica.space.Vector;
import etomica.units.Dimension;

/**
 * Standard Monte Carlo molecule-displacement trial move.
 *
 * @author David Kofke
 */
 
 /* History of changes
  * 7/9/02 Added energyChange() method
  */
public class MCMoveMolecule extends MCMove {
    
    private final MeterPotentialEnergy energyMeter;
    private final AtomIteratorSinglet affectedAtomIterator = new AtomIteratorSinglet();
    private final AtomGroupAction moveMoleculeAction;
    private final Vector translationVector;
    private Atom molecule;
    protected double uOld;
    protected double uNew = Double.NaN;

    public MCMoveMolecule(PotentialMaster potentialMaster) {
        super(potentialMaster, 1);
        energyMeter = new MeterPotentialEnergy(potentialMaster);
        moveMoleculeAction = new AtomGroupAction(new AtomActionTranslateBy(potentialMaster.getSpace()));
        translationVector = ((AtomActionTranslateBy)moveMoleculeAction.getAction()).getTranslationVector();
        setStepSizeMax(Default.BOX_SIZE);
        setStepSizeMin(0.0);
        setStepSize(0.1*Default.ATOM_SIZE);
        perParticleFrequency = true;
        energyMeter.setIncludeLrc(false);
        //set directive to exclude intramolecular contributions to the energy

        //TODO enable meter to do this
        //       iteratorDirective.addCriterion(new IteratorDirective.PotentialCriterion() {
 //           public boolean excludes(Potential p) {return (p instanceof Potential1.Intramolecular);}
 //       });
        setName("MCMoveMolecule");
        
    }
    
    public final Dimension getStepSizeDimension() {return Dimension.LENGTH;}
    public final Dimension getStepSizeMaxDimension() {return Dimension.LENGTH;}
    public final Dimension getStepSizeMinDimension() {return Dimension.LENGTH;}
    

    public boolean doTrial() {
        Phase phase = phases[0];
        if(phase.moleculeCount()==0) return false;
        
        molecule = phase.randomMolecule();

        energyMeter.setTarget(molecule);
        uOld = energyMeter.getDataAsScalar(phase);
        translationVector.setRandomCube();
        translationVector.TE(stepSize);
        moveMoleculeAction.actionPerformed(molecule);
        uNew = Double.NaN;
        return true;
    }//end of doTrial
    
    public double lnTrialRatio() {return 0.0;}
    
    public double lnProbabilityRatio() {
        energyMeter.setTarget(molecule);
        uNew = energyMeter.getDataAsScalar(phases[0]);
        return -(uNew - uOld)/temperature;
    }
    
    public void acceptNotify() {  /* do nothing */}
    
    public void rejectNotify() {
        translationVector.TE(-1);
        moveMoleculeAction.actionPerformed(molecule);
    }
        
    public final AtomIterator affectedAtoms(Phase phase) {
        if(this.phases[0] != phase) return AtomIterator.NULL;
        affectedAtomIterator.setAtom(molecule);
        affectedAtomIterator.reset();
        return affectedAtomIterator;
    }

    public double energyChange(Phase phase) {return (this.phases[0] == phase) ? uNew - uOld : 0.0;}
    
    
/*    public static void main(String[] args) {
        
	    IntegratorMC integrator = new IntegratorMC();
	    MCMoveMolecule mcMove = new MCMoveMolecule(integrator);
	    SpeciesSpheres species = new SpeciesSpheres(20,3);
	    Phase phase = new Phase();
	    P2LennardJones potential = new P2LennardJones();
	    Controller controller = new Controller();
	    DisplayPhase display = new DisplayPhase();

		MeterEnergy energy = new MeterEnergy();
		energy.setPhase(phase);
		energy.setHistorying(true);
		energy.setActive(true);		
		energy.getHistory().setNValues(500);		
		DisplayPlot plot = new DisplayPlot();
		plot.setLabel("Energy");
		plot.setDataSources(energy.getHistory());
		
		integrator.setSleepPeriod(2);
		
		Simulation.instance.elementCoordinator.go();
	    
        potential.setIterator(new AtomPairIterator(phase));
        potential.set(species.getAgent(phase));
        
        Simulation.makeAndDisplayFrame(Simulation.instance);
    }//end of main
  */  
}
@@ -33,82 +33,8 @@
 e;%0A%0A
-import etomica.Atom;%0Aimport etomica.AtomIterator;%0Aimport etomica.Default;%0A
 impo
@@ -170,201 +170,8 @@
 ion;
-%0Aimport etomica.atom.iterator.AtomIteratorSinglet;%0Aimport etomica.data.meter.MeterPotentialEnergy;%0Aimport etomica.integrator.MCMove;%0Aimport etomica.space.Vector;%0Aimport etomica.units.Dimension;
 %0A%0A/*
@@ -371,16 +371,20 @@
 s MCMove
+Atom
  %7B%0A    %0A
@@ -393,332 +393,56 @@
   pr
-ivate final MeterPotentialEnergy energyMeter;%0A    private final AtomIteratorSinglet affectedAtomIterator = new AtomIteratorSinglet();%0A    private final AtomGroupAction moveMoleculeAction;%0A    private final Vector translationVector;%0A    private Atom molecule;%0A    protected double uOld;%0A    protected double uNew = Double.NaN
+otected final AtomGroupAction moveMoleculeAction
 ;%0A%0A 
@@ -534,76 +534,8 @@
 ster
-, 1);%0A        energyMeter = new MeterPotentialEnergy(potentialMaster
 );%0A 
@@ -642,310 +642,8 @@
 ));%0A
-        translationVector = ((AtomActionTranslateBy)moveMoleculeAction.getAction()).getTranslationVector();%0A        setStepSizeMax(Default.BOX_SIZE);%0A        setStepSizeMin(0.0);%0A        setStepSize(0.1*Default.ATOM_SIZE);%0A        perParticleFrequency = true;%0A        energyMeter.setIncludeLrc(false);%0A
     
@@ -1023,250 +1023,8 @@
     
-%0A    public final Dimension getStepSizeDimension() %7Breturn Dimension.LENGTH;%7D%0A    public final Dimension getStepSizeMaxDimension() %7Breturn Dimension.LENGTH;%7D%0A    public final Dimension getStepSizeMinDimension() %7Breturn Dimension.LENGTH;%7D%0A    
 %0A%0A  
@@ -1153,24 +1153,20 @@
         
-molecule
+atom
  = phase
@@ -1211,32 +1211,28 @@
 r.setTarget(
-molecule
+atom
 );%0A        u
@@ -1395,32 +1395,28 @@
 onPerformed(
-molecule
+atom
 );%0A        u
@@ -1496,789 +1496,124 @@
 lic 
-double lnTrialRatio() %7Breturn 0.0;%7D%0A    %0A    public double lnProbabilityRatio() %7B%0A        energyMeter.setTarget(molecule);%0A        uNew = energyMeter.getDataAsScalar(phases%5B0%5D);%0A        return -(uNew - uOld)/temperature;%0A    %7D%0A    %0A    public void acceptNotify() %7B  /* do nothing */%7D%0A    %0A    public void rejectNotify() %7B%0A        translationVector.TE(-1);%0A        moveMoleculeAction.actionPerformed(molecule);%0A    %7D%0A        %0A    public final AtomIterator affectedAtoms(Phase phase) %7B%0A        if(this.phases%5B0%5D != phase) return AtomIterator.NULL;%0A        affectedAtomIterator.setAtom(molecule);%0A        affectedAtomIterator.reset();%0A        return affectedAtomIterator;%0A    %7D%0A%0A    public double energyChange(Phase phase) %7Breturn (this.phases%5B0%5D == phase) ? uNew - uOld : 0.0;
+void rejectNotify() %7B%0A        translationVector.TE(-1);%0A        moveMoleculeAction.actionPerformed(atom);%0A    
 %7D%0A    
-%0A
     

make MCMoveMolecule extend MCMoveAtom instead duplicating most of its functionality