package etomica.data.meter;
import etomica.DataInfo;
import etomica.EtomicaInfo;
import etomica.Meter;
import etomica.Phase;
import etomica.Space;
import etomica.data.DataSourceScalar;
import etomica.space.Tensor;
import etomica.units.Dimension;

/**
 * This is a meter to measure the surface tension for a hard potential.  
 * It uses the meter that measures the pressure tensor to do this
 * and returns the result as PV/N, which has dimensions of energy.
 * Assumes a slab geometry for the liquid, so surface tension is divided by 2 to account for both interfaces.
 *
 * @author Rob Riggleman
 */

public class MeterSurfaceTensionHard extends DataSourceScalar implements Meter {//, EtomicaElement {
    
    public MeterSurfaceTensionHard(Space space) {
        super(new DataInfo("Surface Tension",Dimension.ENERGY));
        velocityTensor = new MeterTensorVelocity(space);
        virialTensor = new MeterTensorVirialHard(space);
        pressureTensor = space.makeTensor();
    }
    
    public static EtomicaInfo getEtomicaInfo() {
        EtomicaInfo info = new EtomicaInfo("Measures surface tension for a collision-based potential");
        return info;
    }

    /**
     * Returns dimensions of this meters measured quanitity, which in this case is energy
     */
    public final Dimension getDimension() {return Dimension.ENERGY;}
    
    /**
     * Gives current value of the surface tension, obtained by summing velocity and virial contributions.
     * Virial contribution includes sum over all collisions since last call to this method, while
     * velocity contribution is based on atom velocities in current configuration.
     * Surface tension is given by difference between normal and tangential stress components.
     * Written for 2-, or 3-dimensional systems; assumes that normal to interface is along x-axis.
     */
    
    public double getDataAsScalar() {
        if (phase == null) throw new IllegalStateException("must call setPhase before using meter");
        pressureTensor.E(velocityTensor.getDataAsTensor(phase));
        pressureTensor.PE(virialTensor.getDataAsTensor(phase));
        switch (phase.space().D) {
            case 1:
                surfaceTension = pressureTensor.component(0, 0);
                break;
            case 2:
                surfaceTension = 0.5*(pressureTensor.component(0, 0) - pressureTensor.component(1, 1));
                break;
            case 3:
                surfaceTension = 0.5*(pressureTensor.component(0, 0) - 0.5*(pressureTensor.component(1, 1) + pressureTensor.component(2, 2)));
                break;
        }
        return surfaceTension;
    }
    
    /**
     * @return Returns the phase.
     */
    public Phase getPhase() {
        return phase;
    }
    /**
     * @param phase The phase to set.
     */
    public void setPhase(Phase phase) {
        if (phase.space().D < 1 || phase.space().D > 3) throw new IllegalArgumentException("phase's space must be 1, 2 or 3 dimensional");
        this.phase = phase;
    }

    private Phase phase;
    private final Tensor pressureTensor;
    private final MeterTensorVelocity velocityTensor;
    private final MeterTensorVirialHard virialTensor;
    private double surfaceTension;
}

@@ -68,20 +68,23 @@
 .Etomica
-Info
+Element
 ;%0Aimport
@@ -92,21 +92,27 @@
 etomica.
-Meter
+EtomicaInfo
 ;%0Aimport
@@ -187,16 +187,144 @@
 Scalar;%0A
+import etomica.data.DataSourceTensorVirialHard;%0Aimport etomica.data.types.DataTensor;%0Aimport etomica.integrator.IntegratorHard;%0A
 import e
@@ -807,19 +807,8 @@
 ents
- Meter %7B//,
  Eto
@@ -872,16 +872,43 @@
 ce space
+, IntegratorHard integrator
 ) %7B%0A    
@@ -1017,32 +1017,91 @@
 elocity(space);%0A
+        velocityTensor.setPhase(integrator.getPhase()%5B0%5D);%0A
         virialTe
@@ -1107,29 +1107,34 @@
 ensor = new 
-Meter
+DataSource
 TensorVirial
@@ -1139,24 +1139,35 @@
 alHard(space
+,integrator
 );%0A        p
@@ -1398,188 +1398,8 @@
  %7D%0A%0A
-    /**%0A     * Returns dimensions of this meters measured quanitity, which in this case is energy%0A     */%0A    public final Dimension getDimension() %7Breturn Dimension.ENERGY;%7D%0A    %0A
     
@@ -1891,21 +1891,16 @@
      */%0A
-    %0A
     publ
@@ -1941,126 +1941,38 @@
     
-if (phase == null) throw new IllegalStateException(%22must call setPhase before using meter%22);%0A        pressure
+pressureTensor.E(((Data
 Tensor
-.E(
+)
 velo
@@ -1985,39 +1985,29 @@
 nsor.getData
-AsTensor(phase)
+()).x
 );%0A        p
@@ -2023,16 +2023,29 @@
 nsor.PE(
+((DataTensor)
 virialTe
@@ -2060,23 +2060,13 @@
 Data
-AsTensor(phase)
+()).x
 );%0A 
@@ -2081,30 +2081,38 @@
 witch (p
-hase.space().D
+ressureTensor.length()
 ) %7B%0A    
@@ -2699,74 +2699,41 @@
 urn 
-phase;%0A    %7D%0A    /**%0A     * @param phase The phase to set.
+velocityTensor.getPhase();
 %0A    
- */
+%7D%0A
 %0A   
@@ -2752,202 +2752,161 @@
  set
-Phase(Phase phase) %7B%0A        if (phase.space().D %3C 1 %7C%7C phase.space().D %3E 3) throw new IllegalArgumentException(%22phase's space must be 1, 2 or 3 dimensional%22);%0A        this.phase = phase
+Integrator(IntegratorHard integrator) %7B%0A        velocityTensor.setPhase(integrator.getPhase()%5B0%5D);%0A        virialTensor.setIntegrator(integrator)
 ;%0A    %7D%0A
 %0A   
@@ -2905,33 +2905,12 @@
   %7D%0A
-%0A
     
-private Phase phase;
 %0A   
@@ -3015,29 +3015,34 @@
 ivate final 
-Meter
+DataSource
 TensorVirial
@@ -3096,9 +3096,8 @@
 nsion;%0A%7D
-%0A

update for Data changes not a meter since it's associated more with an integrator than a phase