#!/bin/env python

#=============================================================================================
# GLOBAL IMPORTS
#=============================================================================================

import os
import os.path
import sys
import copy
import re
import math

import simtk.openmm
from ValidationUtilities import ValidationUtilities

#=============================================================================================
# Results class for force/energy platform comparison tests
#=============================================================================================

class EnergyForceComparisonResult(object):
    """

    EnergyForceComparisonResult generates/computes results for ForceEnergy comparisons

    """
    def __init__(self, test, platforms, state1, state2, verbose=False):
        """
        Generate results summary

        ARGUMENTS

        test      (ForceEnergyComparisonTest)    - ForceEnergyComparisonTest reference
        platforms (string list)                  - list of two string platform names         
        state1    (OpenMM::State)                - state object to retrieve forces/energy for first platform
        state2    (OpenMM::State)                - state object to retrieve forces/energy for second platform
        verbose   (Boolean)                      - if true, print logging info

        """

        self._platforms                            = []
        self._platforms.append( platforms[0] )
        self._platforms.append( platforms[1] )

        self._states                               = []
        self._states.append( state1 )
        self._states.append( state2 )
        self._openMM                               = simtk.openmm
        self._verbose                              = verbose
        self._validationUtilities                  = ValidationUtilities(verbose)
        self._minNormCutoff                        = 1.0e-02
        self._systemName                           = test.getSystemName()
        self._testName                             = test.getTestName()
        self._tolerance                            = test.getTolerance()
        self._minForceNormCutoff                   = test.getMinForceNormCutoff()
        self._minEnergyNormCutoff                  = test.getMinEnergyNormCutoff()
        self._numberOfParticles                    = test.getNumberOfParticles()
        self._passed                               = -1

        # get units from ValidationUtilities 

        lengthUnit                                 = self._validationUtilities.getLengthUnit( )
        energyUnit                                 = self._validationUtilities.getEnergyUnit( )

        # check for differences in potential energies

        potential1                                 = state1.getPotentialEnergy() / energyUnit
        potential2                                 = state2.getPotentialEnergy() / energyUnit
        self._deltaPotentialEnergy                 = abs( potential2 - potential1 )
        self._averagePotentials                    = 0.5*( abs( potential2 ) + abs( potential1 ) )
        self._relativeDeltaPotentialEnergy         = abs( potential2 - potential1 )
        if( self._averagePotentials > 0.0 ):
            self._relativeDeltaPotentialEnergy     = self._relativeDeltaPotentialEnergy/self._averagePotentials

        if self._verbose:
            print "PE %14.7e %14.7e   %14.7e %14.7e " % ( potential1, potential2,  self._deltaPotentialEnergy, self._relativeDeltaPotentialEnergy )

        # check for differences in forces
        # compute delta and relative deltas
        # compute maximum deleta and maximum relative delta and track the indies where max occur
        
        forces1                                    = state1.getForces()
        forces2                                    = state2.getForces()
        forceUnit                                  = energyUnit / lengthUnit

        self._maxDeltaInForce                      = -1.0
        self._maxDeltaInForceIndex                 = -1

        self._avgRelativeDeltaInForce              =  0.0  
        self._avgRelativeDeltaInForce2             =  0.0  

        self._maxRelativeDeltaInForce              = -1.0
        self._maxRelativeDeltaInForceIndex         = -1

        self._cntRelativeDeltaInForce              =  0.0
        self._avgRelativeDeltaInForce              =  0.0
        self._stdRelativeDeltaInForce              =  0.0

        self._forceNormSum                         = -1.0
        self._oppositeSigns                        = 0
        self._threshold                            = 0.1

        for ii in range( len( forces1 ) ):
            force1      = forces1[ii] / forceUnit
            force2      = forces2[ii] / forceUnit
            force1Norm  = math.sqrt( force1[0]*force1[0] + force1[1]*force1[1] + force1[2]*force1[2] )
            force2Norm  = math.sqrt( force2[0]*force2[0] + force2[1]*force2[1] + force2[2]*force2[2] )
            if force1Norm > 0.0 or force2Norm > 0.0:

                deltaNorm                             = abs( force2Norm - force1Norm )
                relativeDeltaNorm                     = 2.0*deltaNorm/(force2Norm + force1Norm )
                logRelativeDeltaInForce               = math.log( relativeDeltaNorm )
                self._avgRelativeDeltaInForce        += logRelativeDeltaInForce
                self._stdRelativeDeltaInForce        += (logRelativeDeltaInForce*logRelativeDeltaInForce)
                self._cntRelativeDeltaInForce        += 1

                change                                = 0
                sign                                  = ''
                for jj in range( len(force1) ):

                   if( ( (force1[jj]*force2[jj]) < 0.0) and ( (abs( force1[jj] ) > self._threshold ) or (abs( force2[jj] ) > self._threshold ) ) ):
                       self._oppositeSigns = 1
                       if sign == '' :
                           sign = "Signs opposite: "
                       sign += "%d " % (jj)
                       change              = 1

                if deltaNorm > self._maxDeltaInForce:
                    self._maxDeltaInForce      = deltaNorm
                    self._maxDeltaInForceIndex = ii
                    change              = 1

                if relativeDeltaNorm > self._maxRelativeDeltaInForce:
                    self._maxRelativeDeltaInForce         = relativeDeltaNorm
                    self._maxRelativeDeltaInForceIndex    = ii
                    self._forceNormSum                    = 0.5*(force2Norm + force1Norm )
                    change                                = 1

                change = 1
                if self._verbose and change:  print "Force: %5d %14.7e %14.7e  [%14.7e %14.7e %14.7e] [%14.7e %14.7e %14.7e] Nrms %14.7e %14.7e %s" % (ii, deltaNorm, relativeDeltaNorm, force1[0], force1[1], force1[2], force2[0], force2[1], force2[2], force1Norm, force2Norm, sign)
 
        if( self._cntRelativeDeltaInForce > 1.0 ):
            self._avgRelativeDeltaInForce   /= self._cntRelativeDeltaInForce
            self._stdRelativeDeltaInForce    = self._stdRelativeDeltaInForce - self._cntRelativeDeltaInForce*self._avgRelativeDeltaInForce*self._avgRelativeDeltaInForce
            self._stdRelativeDeltaInForce    = math.sqrt( self._stdRelativeDeltaInForce/(self._cntRelativeDeltaInForce - 1.0) )
            self._avgRelativeDeltaInForce    = math.exp( self._avgRelativeDeltaInForce )
            self._stdRelativeDeltaInForce    = math.exp( self._stdRelativeDeltaInForce )
  
        if self._verbose:
            print "MaxDeltaForce:         %5d %14.7e %20s %20s %10s %10s" % (self._maxDeltaInForceIndex, self._maxDeltaInForce, self.getTestName(), self.getSystemName(), self._platforms[0], self._platforms[1])
            print "MaxRelativeDeltaForce: %5d %14.7e %20s %20s %10s %10s" % (self._maxRelativeDeltaInForceIndex, self._maxRelativeDeltaInForce, self.getTestName(), self.getSystemName(), self._platforms[0], self._platforms[1] )
            print "LogAvgRelDeltaForce:   %5d %14.7e %14.7e %20s %20s %10s %10s" % (self._cntRelativeDeltaInForce, self._avgRelativeDeltaInForce, self._stdRelativeDeltaInForce, self.getTestName(), self.getSystemName(), self._platforms[0], self._platforms[1])
            print "LogStdRelDeltaForce:   %5d %14.7e %14.7e %20s %20s %10s %10s" % (self._cntRelativeDeltaInForce, self._avgRelativeDeltaInForce, self._stdRelativeDeltaInForce, self.getTestName(), self.getSystemName(), self._platforms[0], self._platforms[1])
            sys.stdout.flush()

    #=============================================================================================
    # Return tolerance
    #=============================================================================================

    def getTolerance(self):
        return self._tolerance

    #=============================================================================================
    # Get platform
    #=============================================================================================

    def getPlatform(self,index):
        return self._platforms[index]

    #=============================================================================================
    # Get delta in potential energies
    #=============================================================================================

    def getDeltaPotentialEnergy(self):
        return self._deltaPotentialEnergy

    #=============================================================================================
    # Get relative delta potential energy
    #=============================================================================================

    def getRelativeDeltaPotentialEnergy(self):
        return self._relativeDeltaPotentialEnergy

    #=============================================================================================
    # Get average relative delta in force
    #=============================================================================================

    def getAvgRelativeDeltaInForce(self):
        return self._avgRelativeDeltaInForce

    #=============================================================================================
    # Get std dev relative delta in force
    #=============================================================================================

    def getStdRelativeDeltaInForce(self):
        return self._stdRelativeDeltaInForce

    #=============================================================================================
    # Get count for relative delta in force
    #=============================================================================================

    def getCntRelativeDeltaInForce(self):
        return self._cntRelativeDeltaInForce

    #=============================================================================================
    # Get MaxDelta
    #=============================================================================================

    def getMaxDeltaInForce(self):
        return self._maxDeltaInForce

    #=============================================================================================
    # Get MaxDeltaIndex
    #=============================================================================================

    def getMaxDeltaInForceIndex(self):
        return self._maxDeltaInForceIndex

    #=============================================================================================
    # Get MaxRelativeDelta
    #=============================================================================================

    def getMaxRelativeDeltaInForce(self):
        return self._maxRelativeDeltaInForce

    #=============================================================================================
    # Get MaxRelativeDeltaIndex
    #=============================================================================================

    def getMaxRelativeDeltaInForceIndex(self):
        return self._maxDeltaInForceIndex

    #=============================================================================================
    # Get MaxRelativeDeltaNormSum
    #=============================================================================================

    def getMaxRelativeDeltaInForceNormSum(self):
        return self._forceNormSum

    #=============================================================================================
    # Get OppositeForceSigns
    #=============================================================================================

    def getOppositeForceSigns(self):
        return self._oppositeSigns;

    #=============================================================================================
    # Get system name
    #=============================================================================================

    def getSystemName(self):
         return self._systemName 

    #=============================================================================================
    # Get system name
    #=============================================================================================

    def getTestName(self):
         return self._testName

    #=============================================================================================
    # Get number of particles
    #=============================================================================================

    def getNumberOfParticles(self):
         return self._numberOfParticles

    #=============================================================================================
    # Return 1 if test passsed, else 0
    #=============================================================================================

    def testPassed(self):

        if( self._passed > -1 ):
            return self._passed

        forceTolerance  = self._tolerance
        energyTolerance = forceTolerance

        self._passed = 1
        if( self.getOppositeForceSigns() ):
            if( self._verbose ):
                print "Test failed: forces have opposite signs."
            self._passed = 0

        if( self._maxRelativeDeltaInForce > forceTolerance and self._forceNormSum > self._minForceNormCutoff ):
            if( self._verbose ):
                print "Test failed on force comparison: maxRelativeDelta %14.7e is greater than tolerance=%10.3e and NormSum=%14.7e is greater than threshold=%10.3e" % (self._maxRelativeDeltaInForce, forceTolerance, self._forceNormSum, self._minForceNormCutoff)
            self._passed = 0

        if(  self._relativeDeltaPotentialEnergy > energyTolerance and self._averagePotentials > self._minEnergyNormCutoff ):
            if( self._verbose ):
                print "Test failed on energy comparison: maxRelativeDelta %14.7e is greater than tolerance=%10.3e and NormSum=%14.7e is greater than threshold=%10.3e" % (self._relativeDeltaPotentialEnergy, energyTolerance, self._averagePotentials, self._minNormCutoff )
            self._passed = 0

        if( self._verbose ):
            sys.stdout.flush()

        return self._passed

#=============================================================================================
# Base class for ForceEnergy comparison tests
#=============================================================================================

class ForceEnergyComparisonTest(object):
    """Base class for ForceEnergy comparison tests

    Centralizes common functionality across ForceEnergy comparison tests

    """
    def __init__(self, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        defaultOverrides (dictionary of overrides) -         
        verbose          (Boolean)                 - if true, be verbose         

        """

        # tolerance


        if( 'Tolerance' in defaultOverrides ):
            self._tolerance                      = defaultOverrides['Tolerance']
        else:
            self._tolerance                      = 1.0e-02

        # min cutoffs for norms

        if( 'MinForceNormCutoff' in defaultOverrides ):
            self._minForceNormCutoff             = defaultOverrides['MinForceNormCutoff']
        else:
            self._minForceNormCutoff             = 1.0e-01

        if( 'MinEnergyNormCutoff' in defaultOverrides ):
            self._minEnergyNormCutoff            = defaultOverrides['MinEnergyNormCutoff']
        else:
            self._minEnergyNormCutoff            = 1.0e-01

        self._isActive                                   = 1
        self._system                                     = None
        self._systems                                    = None
        self._result                                     = None
        self._openMM                                     = simtk.openmm
        self._verbose                                    = verbose
        self._validationUtilities                        = ValidationUtilities(verbose)
        self._numberOfParticles                          = 0
        self._availablePlatforms                         = {}
        self._availablePlatforms['Reference']            = 1
        self._availablePlatforms['Cuda']                 = 1
        self._availablePlatforms['OpenCL']               = 1

        if( 'DeviceId' in defaultOverrides ):
            self._deviceId                = defaultOverrides['DeviceId']
        else:
            self._deviceId                = -1


    #=============================================================================================
    # Return 1 if test is active
    #=============================================================================================

    def isActive(self):
        return self._isActive

    #=============================================================================================
    # Return tolerance
    #=============================================================================================

    def getTolerance(self):
        return self._tolerance

    #=============================================================================================
    # Return minimum force norm cutoff
    #=============================================================================================

    def getMinForceNormCutoff(self):
        return self._minForceNormCutoff


    #=============================================================================================
    # Return minimum energy norm cutoff
    #=============================================================================================

    def getMinEnergyNormCutoff(self):
        return self._minEnergyNormCutoff

    #=============================================================================================
    # Get test name
    #=============================================================================================

    def getFullTestName(self):
         return self._systemName + '_' + self._testName

    #=============================================================================================
    # Get system name
    #=============================================================================================

    def getSystemName(self):
         return self._systemName 

    #=============================================================================================
    # Get system name
    #=============================================================================================

    def getTestName(self):
         return self._testName

    #=============================================================================================
    # Get number of particles
    #=============================================================================================

    def getNumberOfParticles(self):
         return self._numberOfParticles

    #=============================================================================================
    # Get result
    #=============================================================================================

    def getResult(self):
         return self._result

    def getEnclosingBox(self):
        ii             = 0
        self._range    = [ [ 1.0e+30, 1.0e+30, 1.0e+30 ], [ -1.0e+30 , -1.0e+30, -1.0e+30 ] ]

        while( ii < len( self._positions ) ):
            coordinates = self._positions[ii]
            jj = 0
            while( jj < 3):

                if(  self._range[0][jj] > coordinates[jj] ):
                     self._range[0][jj] = coordinates[jj]

                if(  self._range[1][jj] < coordinates[jj] ):
                     self._range[1][jj] = coordinates[jj]

                jj += 1

            #print "%5d [%14.7f %14.7f %14.7f]" % ( ii, coordinates[0], coordinates[1], coordinates[2] )
            ii += 1
            #if( ii == maxPrint and len( self._positions ) > 2*maxPrint  ):ii = len( self._positions ) - maxPrint

        if self._verbose: 
            jj = 0
            while( jj < 3):
                print "Enclosing Box %2d [%14.7f %14.7f] %14.7f" % ( jj, self._range[0][jj], self._range[1][jj], (self._range[1][jj] - self._range[0][jj]) )
                jj += 1

    def getBoxDimensions(self):
        self.getEnclosingBox()
        self._box    = [ 0, 0, 0 ]

        jj = 0
        while( jj < 3):
            self._box[jj] =  self._range[1][jj] - self._range[0][jj]
            jj           += 1

    def setNonbondedBox( self ):
        self.getBoxDimensions()
        minBoxDimension = 1.0e+30
        for jj in range( 3 ):
            if( self._box[jj] < minBoxDimension ):
                minBoxDimension  =  self._box[jj];
                jj              += 1

        offset     = 0.5
 
        box0       = [ float(self._box[0] + offset),                          0.0,                         0.0   ]
        box1       = [                          0.0, float(self._box[1] + offset),                         0.0   ]
        box2       = [                          0.0,                          0.0,  float(self._box[2] + offset) ]
        if( minBoxDimension > 0.0 ):
            if( minBoxDimension > 2.0 ):
                cutoff = 1.0
            else:
                cutoff = 0.4*minBoxDimension
            self._cutoff  = cutoff
            self._box0    = box0
            self._box1    = box1
            self._box2    = box2
        else:
            self._cutoff  = None
            self._box0    = None

    #=============================================================================================
    # Serialize
    #=============================================================================================

    def serialize(self, serializeDirectory ):

        if self._system is None and  self._systems is None:
            print "serialize: %s no system available" % (self.getFullTestName() )
            return
    
        # serialize system

        serializeFileNames = []
        if( self._systems is not None and len(self._systems) > 0 ):
            serializeFileNames.append(self.getFullTestName() + '_0' ) 
            serializeFileNames.append(self.getFullTestName() + '_1' )
            system = self._systems[0]
        else:
            serializeFileNames.append(self.getFullTestName() )
            system = self._system
  
        self._validationUtilities.serialize(self.getFullTestName(), system, self._positions, serializeDirectory, serializeFileNames[0] )
        if( len( serializeFileNames ) > 1 ):
            self._validationUtilities.serialize(self.getFullTestName(), self._systems[1], None, serializeDirectory, serializeFileNames[1] )

        return

    #=============================================================================================
    # Run test
    #=============================================================================================

    def runTest(self, platformNames):

        if self._system is not None:
           self._numberOfParticles = self._system.getNumParticles()
        elif( self._systems is not None and len(self._systems) > 0 ):
           self._numberOfParticles = self._systems[0].getNumParticles()

        if self._verbose: 
            print "runTest: %s %s %s" % (self.getFullTestName(), platformNames[0], platformNames[1] )
            if self._system is not None:
                print "         Particles=%d NumForces=%d " % (self._system.getNumParticles(), self._system.getNumForces() )

        if( self._availablePlatforms[platformNames[0]] == 0 ): 
            print "runTest: test %s cannot run on platform %s." % (self.getFullTestName(), platformNames[0] )
            return

        if( self._availablePlatforms[platformNames[1]] == 0 ): 
            print "runTest: test %s cannot run on platform %s." % (self.getFullTestName(), platformNames[1] )
            return

        if self._system is None and  self._systems is None:
            print "runTest: %s no system available" % (self.getFullTestName() )
            return
         
        timestep            = 0.01
        integrator          = self._openMM.VerletIntegrator(timestep)
        system              = self._system
        try:
            if( self._systems is not None and len(self._systems) > 0 ):
                system = self._systems[0]
            platform        = self._openMM.Platform.getPlatformByName( platformNames[0] )
            if( self._deviceId > -1 ):
                self._validationUtilities.setDeviceId( platform, self._deviceId )    
            context1        = self._openMM.Context(system, integrator,  platform )
        except:
            print "runTest: %s context not created for platform %s" % (self.getFullTestName(), platformNames[0] )
            sys.stdout.flush()
            raise

        try:
            if( self._systems is not None and len(self._systems) > 1 ):
               system = self._systems[1]

            platform        = self._openMM.Platform.getPlatformByName( platformNames[1] )
            if( self._deviceId > -1 ):
                self._validationUtilities.setDeviceId( platform, self._deviceId )    
            integrator      = self._openMM.VerletIntegrator(timestep)
            context2        = self._openMM.Context(system, integrator,  platform )
        except:
            print "runTest: %s context not created for platform %s" % (self.getFullTestName(), platformNames[1] )
            sys.stdout.flush()
            raise

        try:
            context1.setPositions( self._positions )
        except:
            print "runTest: %s positions not set for context 1." % (self.getFullTestName() )
            sys.stdout.flush()
            raise

        try:
            context2.setPositions( self._positions )
        except:
            print "runTest: %s positions not set." % (self.getFullTestName() )
            sys.stdout.flush()
            raise

        if self._verbose:
            print "Positions %d" % len( self._positions )
            maxPrint = 10
            ii       = 0
            range    = [ [ 1.0e+30, 1.0e+30, 1.0e+30 ], [ -1.0e+30 , -1.0e+30, -1.0e+30 ] ]

            while( ii < len( self._positions ) ):
                coordinates = self._positions[ii]
                jj = 0
                while( jj < 3):

                    if(  range[0][jj] > coordinates[jj] ):
                         range[0][jj] = coordinates[jj]

                    if(  range[1][jj] < coordinates[jj] ):
                         range[1][jj] = coordinates[jj]

                    jj += 1

                #print "%5d [%14.7f %14.7f %14.7f]" % ( ii, coordinates[0], coordinates[1], coordinates[2] )
                ii += 1
                if( ii == maxPrint and len( self._positions ) > 2*maxPrint  ):ii = len( self._positions ) - maxPrint

            jj = 0
            while( jj < 3):
                print "Enclosing Box %2d [%14.7f %14.7f] %14.7f" % ( jj, range[0][jj], range[1][jj], (range[1][jj] - range[0][jj]) )
                jj += 1

            self._validationUtilities.printPlatformProperties( context2 )
                
        state1           = context1.getState(getEnergy=True, getForces=True)
        state2           = context2.getState(getEnergy=True, getForces=True)

        self._result     = EnergyForceComparisonResult( self, platformNames, state1, state2, self._verbose )
        if( self._verbose ):
            if( self._result.testPassed() ):
                print "%s passed."       % self.getFullTestName()
            else:
                print "%s did not pass." % self.getFullTestName()
            sys.stdout.flush()

        return

#=============================================================================================
# Test class for force/energy platform comparison tests for HarmonicBondForce test
#=============================================================================================

class HarmonicBondForceTest(ForceEnergyComparisonTest):
    """
    HarmonicBondForceTest create system for testing HarmonicBondForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'HarmonicBondForceTest'

        if( parameterInput.getNumberOfHarmonicBonds() == 0 ):
            if verbose: print "No harmonic bonds for %s" % parameterInput.getName()
            return
        harmonicBondForce                    = parameterInput.getHarmonicBondForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testHarmonicBondForce = self._validationUtilities.copyHarmonicBondForce( harmonicBondForce )
        self._system.addForce(testHarmonicBondForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d harmonic bonds" % testHarmonicBondForce.getNumBonds()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testHarmonicBondForce.getNumBonds() ):
                args = testHarmonicBondForce.getBondParameters(ii)
                print "HarmonicBond: %5d [%5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2]/lengthUnit, args[3]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testHarmonicBondForce.getNumBonds() > 2*maxPrint  ):ii = testHarmonicBondForce.getNumBonds() - maxPrint
            sys.stdout.flush()


        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for HarmonicAngleForce test
#=============================================================================================

class HarmonicAngleForceTest(ForceEnergyComparisonTest):
    """
    HarmonicAngleForceTest create system for testing HarmonicAngleForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'HarmonicAngleForceTest'

        if( parameterInput.getNumberOfHarmonicAngles() == 0 ):
            if verbose: print "No harmonic angles for %s" % parameterInput.getName()
            return
        harmonicAngleForce                   = parameterInput.getHarmonicAngleForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testHarmonicAngleForce = self._validationUtilities.copyHarmonicAngleForce( harmonicAngleForce )
        self._system.addForce(testHarmonicAngleForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d harmonic angles" % testHarmonicAngleForce.getNumAngles()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testHarmonicAngleForce.getNumAngles() ):
                args = testHarmonicAngleForce.getAngleParameters(ii)
                print "HarmonicAngle: %5d [%5d %5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3]/lengthUnit, args[4]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testHarmonicAngleForce.getNumAngles() > 2*maxPrint  ):ii = testHarmonicAngleForce.getNumAngles() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for PeriodicTorsionForce test
#=============================================================================================

class PeriodicTorsionForceTest(ForceEnergyComparisonTest):
    """
    PeriodicTorsionForceTest create system for testing PeriodicTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'PeriodicTorsionForceTest'

        if( parameterInput.getNumberOfPeriodicTorsions() == 0 ):
            if verbose: print "No periodic torsions for %s" % parameterInput.getName()
            return
        periodicTorsionForce                 = parameterInput.getPeriodicTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testPeriodicTorsionForce = self._validationUtilities.copyPeriodicTorsionForce( periodicTorsionForce )
        self._system.addForce(testPeriodicTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d periodic torsions " % testPeriodicTorsionForce.getNumTorsions()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            energyUnit         = self._validationUtilities.getEnergyUnit( )
            maxPrint = 10
            while( ii < testPeriodicTorsionForce.getNumTorsions() ):
                args = testPeriodicTorsionForce.getTorsionParameters(ii)
                print "PeriodicTorsion: %5d [%5d %5d %5d %5d] %3d [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4], args[5]/lengthUnit, args[6]/energyUnit)
                ii  += 1
                if( ii == maxPrint and testPeriodicTorsionForce.getNumTorsions() > 2*maxPrint  ):ii = testPeriodicTorsionForce.getNumTorsions() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for RBTorsionForce test
#=============================================================================================

class RBTorsionForceTest(ForceEnergyComparisonTest):
    """
    RBTorsionForceTest create system for testing RBTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'RBTorsionForceTest'

        if( parameterInput.getNumberOfRBTorsions() == 0 ):
            if verbose: print "No RB torsions for %s" % parameterInput.getName()
            return
        rbTorsionForce                       = parameterInput.getRBTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testRBTorsionForce = self._validationUtilities.copyRBTorsionForce( rbTorsionForce )
        self._system.addForce(testRBTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d RB torsions " % testRBTorsionForce.getNumTorsions()
            ii                 = 0
            maxPrint = 10
            while( ii < testRBTorsionForce.getNumTorsions() ):
                args = testRBTorsionForce.getTorsionParameters(ii)
                print "RBTorsion: %5d [%5d %5d %5d %5d] [%14.7e %14.7e %14.7e %14.7e %14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])
                ii  += 1
                if( ii == maxPrint and testRBTorsionForce.getNumTorsions() > 2*maxPrint  ):ii = testRBTorsionForce.getNumTorsions() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for CMAPTorsionForceTest test
#=============================================================================================

class CMAPTorsionForceTest(ForceEnergyComparisonTest):
    """
    CMAPTorsionForceTest create system for testing CMAPTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

copyCMAPTorsionForce
        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'CMAPTorsionForceTest'

        if( parameterInput.getNumberOfCMAPTorsions() == 0 ):
            if verbose: print "No CMAP torsions for %s" % parameterInput.getName()
            return

        cmapTorsionForce = parameterInput.getCMAPTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testCMAPTorsionForce = self._validationUtilities.copyCMAPTorsionForce( cmapTorsionForce )
        self._system.addForce(testCMAPTorsionForce)

        if self._verbose: 
            self._validationUtilities.printCMAPTorsionForce( self.getFullTestName(), testCMAPTorsionForce, 10 )

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Base test class for force/energy platform comparison tests for NonbondedForce tests
#=============================================================================================

class NonbondedForceBaseTest(ForceEnergyComparisonTest):
    """
    NonbondedForceTest create system for testing NonbondedForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfNonbondeds() == 0 ):
            if verbose: print "No nonbonded particles %s" % parameterInput.getName()
            return
        nonbondedForce                       = parameterInput.getNonbondedForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        self._testNonbondedForce = self._validationUtilities.copyNonbondedForce( nonbondedForce )
        self._positions          = parameterInput.getPositions()
        self.setNonbondedBox( )
        if( self._cutoff is not None ):
            self._testNonbondedForce.setCutoffDistance( self._cutoff )

        if( self._box0 is not None ):
            self._system.setDefaultPeriodicBoxVectors( self._box0, self._box1, self._box2)

        self._system.addForce(self._testNonbondedForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for NonbondedForce w/ no cutoff
#=============================================================================================

class NonbondedForceNoCutoffTest(NonbondedForceBaseTest):
    """
    NonbondedForceTest create system for testing NonbondedForce w/ no cutoff
    inherits from NonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        NonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )

        self._testName                       = 'NonbondedForceNoCutoffTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.NoCutoff )

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for NonbondeddForce w/ cutoff
# and non-periodic boundary conditions
#=============================================================================================

class NonbondedForceCutoffNonPeriodicTest(NonbondedForceBaseTest):
    """
    NonbondedForceTest create system for testing NonbondedForce w/ cutoff and non-periodic boundary conditions
    inherits from NonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        NonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )

        self._testName                       = 'NonbondedForceCutoffNonPeriodicTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.CutoffNonPeriodic )

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for NonbondeddForce w/ cutoff
# and periodic boundary conditions
#=============================================================================================

class NonbondedForceCutoffPeriodicTest(NonbondedForceBaseTest):
    """
    NonbondedForceTest create system for testing NonbondedForce w/ cutoff and periodic boundary conditions
    inherits from NonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        NonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )

        self._testName                       = 'NonbondedForceCutoffPeriodicTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.CutoffPeriodic )

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for NonbondeddForce using Ewald
#=============================================================================================

class NonbondedForceEwaldTest(NonbondedForceBaseTest):
    """
    NonbondedForceTest create system for testing NonbondedForce using Ewald
    inherits from NonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        NonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )

        self._testName                       = 'NonbondedForceEwaldTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.Ewald )

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for NonbondeddForce using PME
#=============================================================================================

class NonbondedForcePMETest(NonbondedForceBaseTest):
    """
    NonbondedForceTest create system for testing NonbondedForce using PME
    inherits from NonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        NonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )

        self._testName                       = 'NonbondedForcePMETest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.PME )

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Base test class for force/energy platform comparison tests for GbsaObcForce tests
#=============================================================================================

class GbsaObcForceBaseTest(ForceEnergyComparisonTest):
    """
    GbsaObcForceTest create system for testing GbsaObcForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        # include nonbonded and OBC forces

        if( parameterInput.getNumberOfGbsaObcs() == 0 ):
            if verbose: print "No Gbsa Obc particles %s" % parameterInput.getName()
            self._isActive = 0
            return

        if( parameterInput.getNumberOfNonbondeds() == 0 ):
            if verbose: print "No nonbonded particles %s" % parameterInput.getName()
            self._isActive = 0
            return
        nonbondedForce                       = parameterInput.getNonbondedForce()
        gbsaObcForce                         = parameterInput.getGbsaObcForce()

        # build system

        self._system             = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        self._testNonbondedForce = self._validationUtilities.copyNonbondedForce( nonbondedForce )
        self._positions          = parameterInput.getPositions()

        self.getBoxDimensions()
 
        minBoxDimension = 1.0e+30
        for jj in range( 3 ):
            if( self._box[jj] < minBoxDimension ):
                minBoxDimension  =  self._box[jj];
                jj              += 1

        offset     = 0.5
 
        box0       = [ float(self._box[0] + offset),                          0.0,                         0.0   ]
        box1       = [                          0.0, float(self._box[1] + offset),                         0.0   ]
        box2       = [                          0.0,                          0.0,  float(self._box[2] + offset) ]
        if( minBoxDimension > 0.0 ):
            if( minBoxDimension > 2.0 ):
                cutoff = 1.0
            else:
                cutoff = 0.4*minBoxDimension
            self._testNonbondedForce.setCutoffDistance( cutoff )
            self._system.setDefaultPeriodicBoxVectors( box0, box1, box2 )
        self._system.addForce(self._testNonbondedForce)

        self._testGbsaObcForce   = self._validationUtilities.copyGbsaObcForce( gbsaObcForce )
        self._system.addForce(self._testGbsaObcForce)
        self._testGbsaObcForce.setCutoffDistance( self._testNonbondedForce.getCutoffDistance() )

#=============================================================================================
# Test class for force/energy platform comparison tests for GbsaObcForce w/ no cutoff
#=============================================================================================

class GbsaObcForceNoCutoffTest(GbsaObcForceBaseTest):
    """
    GbsaObcForceTest create system for testing GbsaObcForce w/ no cutoff
    inherits from GbsaObcForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        GbsaObcForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'GbsaObcForceNoCutoffTest'
        self._testGbsaObcForce.setNonbondedMethod( self._openMM.NonbondedForce.NoCutoff )
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.NoCutoff )

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for GbsaObcdForce w/ cutoff
# and non-periodic boundary conditions
#=============================================================================================

class GbsaObcForceCutoffNonPeriodicTest(GbsaObcForceBaseTest):
    """
    GbsaObcForceTest create system for testing GbsaObcForce w/ cutoff and non-periodic boundary conditions
    inherits from GbsaObcForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        GbsaObcForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'GbsaObcForceCutoffNonPeriodicTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.CutoffNonPeriodic )
        self._testNonbondedForce.setCutoffDistance( 2.0 )
        self._testGbsaObcForce.setCutoffDistance( 2.0 )
        self._testGbsaObcForce.setNonbondedMethod(   self._openMM.NonbondedForce.CutoffNonPeriodic )

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for GbsaObcdForce w/ cutoff
# and periodic boundary conditions
#=============================================================================================

class GbsaObcForceCutoffPeriodicTest(GbsaObcForceBaseTest):
    """
    GbsaObcForceTest create system for testing GbsaObcForce w/ cutoff and periodic boundary conditions
    inherits from GbsaObcForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        GbsaObcForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'GbsaObcForceCutoffPeriodicTest'
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.CutoffPeriodic )
#        self.getBoxDimensions()
# 
#        minBoxDimension = 1.0e+30
#        for jj in range( 3 ):
#            if( self._box[jj] < minBoxDimension ):
#                minBoxDimension  =  self._box[jj];
#                jj              += 1
#
#        offset     = 0.5
# 
#        box0       = [ float(self._box[0] + offset),                          0.0,                         0.0   ]
#        box1       = [                          0.0, float(self._box[1] + offset),                         0.0   ]
#        box2       = [                          0.0,                          0.0,  float(self._box[2] + offset) ]
#        if( minBoxDimension > 0.0 ):
#            self._testNonbondedForce.setCutoffDistance( 0.4*minBoxDimension )
#            self._system.setDefaultPeriodicBoxVectors( box0, box1, box2 )
#
        self._testGbsaObcForce.setNonbondedMethod( self._openMM.NonbondedForce.CutoffPeriodic )

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)

#=============================================================================================
# Base test class for force/energy platform comparison tests for GbviForce tests
#=============================================================================================

class GbviForceBaseTest(ForceEnergyComparisonTest):
    """
    GbviForceTest create system for testing GbviForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._availablePlatforms['OpenCL']   = 0

        # include nonbonded and OBC forces

        if( parameterInput.getNumberOfGbvis() == 0 ):
            if verbose: print "No Gbvi particles %s" % parameterInput.getName()
            self._isActive = 0
            return

        if( parameterInput.getNumberOfNonbondeds() == 0 ):
            if verbose: print "No nonbonded particles %s" % parameterInput.getName()
            self._isActive = 0
            return

        nonbondedForce                    = parameterInput.getNonbondedForce()
        gbviForce                         = parameterInput.getGbviForce()

        # build system

        self._system             = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        self._testNonbondedForce = self._validationUtilities.copyNonbondedForce( nonbondedForce )
        self._positions          = parameterInput.getPositions()

        self.getBoxDimensions()
 
        minBoxDimension = 1.0e+30
        for jj in range( 3 ):
            if( self._box[jj] < minBoxDimension ):
                minBoxDimension  =  self._box[jj];
                jj              += 1

        offset     = 0.5
 
        box0       = [ float(self._box[0] + offset),                          0.0,                         0.0   ]
        box1       = [                          0.0, float(self._box[1] + offset),                         0.0   ]
        box2       = [                          0.0,                          0.0,  float(self._box[2] + offset) ]
        if( minBoxDimension > 0.0 ):
            if( minBoxDimension > 2.0 ):
                cutoff = 1.0
            else:
                cutoff = 0.4*minBoxDimension
            self._testNonbondedForce.setCutoffDistance( cutoff )
            self._system.setDefaultPeriodicBoxVectors( box0, box1, box2 )
        self._system.addForce(self._testNonbondedForce)

        self._testGbviForce   = self._validationUtilities.copyGbviForce( gbviForce )
        self._system.addForce(self._testGbviForce)
        self._testGbviForce.setCutoffDistance( self._testNonbondedForce.getCutoffDistance() )

#=============================================================================================
# Test class for force/energy platform comparison tests for GbviForce w/ no cutoff
#=============================================================================================

class GbviForceNoCutoffTest(GbviForceBaseTest):
    """
    GbviForceTest create system for testing GbviForce w/ no cutoff
    inherits from GbviForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        GbviForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'GbviForceNoCutoffTest'
        self._testGbviForce.setNonbondedMethod( self._openMM.NonbondedForce.NoCutoff )
        self._testNonbondedForce.setNonbondedMethod( self._openMM.NonbondedForce.NoCutoff )

        if self._verbose: 
            self._validationUtilities.printGbvi( self._testName, self._testGbviForce)

#=============================================================================================
# Base test class for force/energy platform comparison tests for GbsaObcForce tests
#=============================================================================================

class CustomForceBaseTest(ForceEnergyComparisonTest):
    """
    CustomForceBaseTest intermediate class for Custom force tests
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        # build systems

        self._systems = []
        for ii in range( 2 ):
            self._systems.append( self._openMM.System() )
            self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._systems[ii] )
            self._validationUtilities.copyDefaultBoxVectors( parameterInput.getDefaultBoxVectors(), self._systems[ii] )
       
        self._positions          = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomBondForce
#=============================================================================================

class CustomBondForceTest(CustomForceBaseTest):
    """
    CustomBondForceTest create system for testing CustomBondForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomBondForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfHarmonicBonds() == 0 ):
            if verbose: print "No harmonic bonds for %s" % parameterInput.getName()
            return
        harmonicBondForce                    = parameterInput.getHarmonicBondForce()

        # build system

        testHarmonicBondForce = self._validationUtilities.copyHarmonicBondForce( harmonicBondForce )
        self._systems[0].addForce(testHarmonicBondForce)

        testCustomBondForce = self._validationUtilities.copyHarmonicBondForceToCustomBondForce( harmonicBondForce )
        self._systems[1].addForce(testCustomBondForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d harmonic bonds" % testHarmonicBondForce.getNumBonds()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testHarmonicBondForce.getNumBonds() ):
                args = testHarmonicBondForce.getBondParameters(ii)
                print "HarmonicBond: %5d [%5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2]/lengthUnit, args[3]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testHarmonicBondForce.getNumBonds() > 2*maxPrint  ):ii = testHarmonicBondForce.getNumBonds() - maxPrint
            sys.stdout.flush()

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomAngleForce
#=============================================================================================

class CustomAngleForceTest(CustomForceBaseTest):
    """
    CustomAngleForceTest create system for testing CustomAngleForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomAngleForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfHarmonicAngles() == 0 ):
            if verbose: print "No angle bonds for %s" % parameterInput.getName()
            return
        harmonicAngleForce                    = parameterInput.getHarmonicAngleForce()

        # build system

        testHarmonicAngleForce = self._validationUtilities.copyHarmonicAngleForce( harmonicAngleForce )
        self._systems[0].addForce(testHarmonicAngleForce)

        testCustomAngleForce = self._validationUtilities.copyHarmonicAngleForceToCustomAngleForce( harmonicAngleForce )
        self._systems[1].addForce(testCustomAngleForce)


        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d harmonic bonds" % testHarmonicAngleForce.getNumAngles()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testHarmonicAngleForce.getNumAngles() ):
                args = testHarmonicAngleForce.getAngleParameters(ii)
                print "HarmonicAngle: %5d [%5d %5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3]/lengthUnit, args[4]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testHarmonicAngleForce.getNumAngles() > 2*maxPrint  ):ii = testHarmonicAngleForce.getNumAngles() - maxPrint
            sys.stdout.flush()

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomTorsionForce
#=============================================================================================

class CustomTorsionForceTest(CustomForceBaseTest):
    """
    CustomTorsionForceTest create system for testing CustomTorsionForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomTorsionForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfPeriodicTorsions() == 0 ):
            if verbose: print "No periodic torsions for %s" % parameterInput.getName()
            return
        periodicTorsionForce                 = parameterInput.getPeriodicTorsionForce()

        # build system

        testPeriodicTorsionForce = self._validationUtilities.copyPeriodicTorsionForce( periodicTorsionForce )
        self._systems[0].addForce(testPeriodicTorsionForce)

        testCustomTorsionForce = self._validationUtilities.copyPeriodicTorsionForceToCustomTorsionForce( periodicTorsionForce )
        self._systems[1].addForce(testCustomTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d periodic torsions " % testPeriodicTorsionForce.getNumTorsions()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            energyUnit         = self._validationUtilities.getEnergyUnit( )
            maxPrint = 10
            while( ii < testPeriodicTorsionForce.getNumTorsions() ):
                args = testPeriodicTorsionForce.getTorsionParameters(ii)
                print "PeriodicTorsion: %5d [%5d %5d %5d %5d] %3d [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4], args[5]/lengthUnit, args[6]/energyUnit)
                ii  += 1
                if( ii == maxPrint and testPeriodicTorsionForce.getNumTorsions() > 2*maxPrint  ):ii = testPeriodicTorsionForce.getNumTorsions() - maxPrint
            sys.stdout.flush()

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomExternalForce
#=============================================================================================

class CustomExternalForceTest(CustomForceBaseTest):
    """
    CustomExternalForceTest create system for testing CustomExternalForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomExternalForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfExternals() == 0 ):
            if verbose: print "No  externals for %s" % parameterInput.getName()
            return

        # build system

        testExternalForce = self._validationUtilities.createCustomExternalForce( self._systems[0].getNumParticles() )
        self._systems[0].addForce(testExternalForce)
        self._systems[1].addForce(testExternalForce)

#        if self._verbose: 
#            print "\n\n" + self.getFullTestName()
#            print "Added %d  externals " % testExternalForce.getNumExternals()
#            ii                 = 0
#            lengthUnit         = self._validationUtilities.getRadianUnit( )
#            energyUnit         = self._validationUtilities.getEnergyUnit( )
#            maxPrint = 10
#            while( ii < testExternalForce.getNumExternals() ):
#                args = testExternalForce.getExternalParameters(ii)
#                print "External: %5d [%5d %5d %5d %5d] %3d [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4], args[5]/lengthUnit, args[6]/energyUnit)
#                ii  += 1
#                if( ii == maxPrint and testExternalForce.getNumExternals() > 2*maxPrint  ):ii = testExternalForce.getNumExternals() - maxPrint
#            sys.stdout.flush()

#=============================================================================================
# Test base class for force/energy platform comparison tests for CustomNonbondedForce
#=============================================================================================

class CustomNonbondedForceBaseTest(CustomForceBaseTest):
    """
    CustomNonbondedForceTest create system for testing CustomNonbondedForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, nonbondedMethod, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomNonbondedForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfNonbondeds() == 0 ):
            if verbose: print "No interactions for %s" % parameterInput.getName()
            return
        nonbondedForce                       = parameterInput.getNonbondedForce()

#        for ii in range( nonbondedForce.getNumParticles() ):
#            args   = nonbondedForce.getParticleParameters(ii)
#            #charge = (args[1]/(chargeUnit*chargeUnit))
#            #eps    = (args[3]/energyUnit)
#            eps     = args[2]
#            eps     = 0.0
#            #args[0] = 0.0
#            nonbondedForce.setParticleParameters( ii, args[0], args[1], eps )
#
#        for ii in range( nonbondedForce.getNumExceptions() ):
#            args     = nonbondedForce.getExceptionParameters(ii)
#            #charge = (args[2]/(chargeUnit*chargeUnit))
#            #eps    = (args[4]/energyUnit)
#            #args[2]  = 0.0
#            eps      = args[4]
#            #eps      = 0.0
#            nonbondedForce.setExceptionParameters( ii, args[0], args[1], args[2], args[3], eps )


#       self.setNonbondedBox( )
#       if( self._box0 is not None ):
#           self._systems[0].setDefaultPeriodicBoxVectors( self._box0, self._box1, self._box2)
#           self._systems[1].setDefaultPeriodicBoxVectors( self._box0, self._box1, self._box2)

        # build system

        self._testNonbondedForce = self._validationUtilities.copyNonbondedForce( nonbondedForce )
        #self._testNonbondedForce.setCutoffDistance(  self._cutoff )
        if( nonbondedMethod > -1 ):
            self._testNonbondedForce.setNonbondedMethod( nonbondedMethod )
        self._systems[0].addForce(self._testNonbondedForce)

        if( self._verbose ):
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )
            box = self._systems[0].getDefaultPeriodicBoxVectors( )
            print "Box0: %s" % (str(box))

        if( nonbondedMethod == self._openMM.NonbondedForce.NoCutoff ):
            methodType = 1
        else:

            # include rxn field term

            methodType = 2

        self._testCustomNonbondedForce = self._validationUtilities.copyNonbondedForceToCustomNonbondedForce( self._testNonbondedForce, methodType)
        if( nonbondedMethod > -1 ):
            self._testCustomNonbondedForce.setNonbondedMethod( nonbondedMethod )
        self._systems[1].addForce(self._testCustomNonbondedForce)

        # add exceptions

        methodType = 1
        #methodType = 2
        self._testCustomBondForce = self._validationUtilities.copyExceptionsFromNonbondedForceToCustomBondForce( self._testNonbondedForce, methodType )
        self._systems[1].addForce(self._testCustomBondForce )
        if( self._verbose ):
            box = self._systems[1].getDefaultPeriodicBoxVectors( )
            print "Box1: %s" % (str(box))
            self._validationUtilities.printCustomNonbonded(  self._testName, self._testCustomNonbondedForce )
            self._validationUtilities.printCustomBonded(  self._testName, self._testCustomBondForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomNonbondedForce w/o cutoffs
#=============================================================================================

class CustomNonbondedForceNoCutoffTest(CustomNonbondedForceBaseTest):
    """
    CustomNonbondedForceTest create system for testing CustomNonbondedForce
    inherits from CustomNonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomNonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.NonbondedForce.NoCutoff, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomNonbondedForceNoCutoffTest'

        # build system

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomNonbondedForce w/ cutoffs, non-periodic
#=============================================================================================

class CustomNonbondedForceNonPeriodicCutoffTest(CustomNonbondedForceBaseTest):
    """
    CustomNonbondedForceTest create system for testing CustomNonbondedForce
    inherits from CustomNonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomNonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.NonbondedForce.CutoffNonPeriodic, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomNonbondedForceNonPeriodicCutoffTest'

        # build system

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )


#=============================================================================================
# Test class for force/energy platform comparison tests for CustomNonbondedForce w/ cutoffs, periodic
#=============================================================================================

class CustomNonbondedForcePeriodicCutoffTest(CustomNonbondedForceBaseTest):
    """
    CustomNonbondedForceTest create system for testing CustomNonbondedForce
    inherits from CustomNonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomNonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.NonbondedForce.CutoffPeriodic, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomNonbondedForcePeriodicCutoffTest'

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )


#=============================================================================================
# Test class for force/energy platform comparison tests for CustomNonbondedForce w/ cutoffs, periodic
#=============================================================================================

class CustomNonbondedForceNoModificationTest(CustomNonbondedForceBaseTest):
    """
    CustomNonbondedForceTest create system for testing CustomNonbondedForce
    inherits from CustomNonbondedForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomNonbondedForceBaseTest.__init__(self, parameterInput, defaultOverrides, -1, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomNonbondedForceNoModificationTest'

        if self._verbose: 
            self._validationUtilities.printNonbonded( self._testName, self._testNonbondedForce )

#=============================================================================================
# Test base class for force/energy platform comparison tests for CustomGbsaForce
#=============================================================================================

class CustomGbsaForceBaseTest(CustomForceBaseTest):
    """
    CustomGbsaForceTest create system for testing CustomGbsaForce
    inherits from CustomForceBaseTest 
    """
    def __init__(self, parameterInput, defaultOverrides, nonbondedMethod, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomForceBaseTest.__init__(self, parameterInput, defaultOverrides, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomGbsaForceTest'
        self._systemName                     = parameterInput.getName().replace( '.txt', '' )

        if( parameterInput.getNumberOfGbsaObcs() == 0 ):
            if verbose: print "No interactions for %s" % parameterInput.getName()
            return
        gbsaForce                       = parameterInput.getGbsaObcForce()

#        for ii in range( gbsaForce.getNumParticles() ):
#            args   = gbsaForce.getParticleParameters(ii)
#            #charge = (args[1]/(chargeUnit*chargeUnit))
#            #eps    = (args[3]/energyUnit)
#            eps     = args[2]
#            #eps     = 0.0
#            #args[0] = 0.0
#            gbsaForce.setParticleParameters( ii, args[0], args[1], eps )
#
#        for ii in range( gbsaForce.getNumExceptions() ):
#            args     = gbsaForce.getExceptionParameters(ii)
#            #charge = (args[2]/(chargeUnit*chargeUnit))
#            #eps    = (args[4]/energyUnit)
#            #args[2]  = 0.0
#            eps      = args[4]
#            #eps      = 0.0
#            gbsaForce.setExceptionParameters( ii, args[0], args[1], args[2], args[3], eps )


        self.setNonbondedBox( )
        if( self._box0 is not None ):
            self._systems[0].setDefaultPeriodicBoxVectors( self._box0, self._box1, self._box2)
            self._systems[1].setDefaultPeriodicBoxVectors( self._box0, self._box1, self._box2)

        # build system

        self._testGbsaObcForce = self._validationUtilities.copyGbsaObcForce( gbsaForce )
        self._testGbsaObcForce.setCutoffDistance( self._cutoff )
        self._testGbsaObcForce.setNonbondedMethod( nonbondedMethod )
        self._systems[0].addForce(self._testGbsaObcForce)

#       if( nonbondedMethod == self._openMM.GBForce.NoCutoff ):
#           methodType = 1
#       else:

#           # include rxn field term

#           methodType = 2

        self._testCustomGbsaForce = self._validationUtilities.copyGBSAOBCForceToCustomGBSAOBCForce( self._testGbsaObcForce )
        self._systems[1].addForce(self._testCustomGbsaForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomGbsaForce w/o cutoffs
#=============================================================================================

class CustomGbsaForceNoCutoffTest(CustomGbsaForceBaseTest):
    """
    CustomGbsaForceTest create system for testing CustomGbsaForce
    inherits from CustomGbsaForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomGbsaForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.GBSAOBCForce.NoCutoff, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomGbsaForceNoCutoffTest'

        # build system

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for CustomGbsaForce w/ cutoffs, non-periodic
#=============================================================================================

class CustomGbsaForceNonPeriodicCutoffTest(CustomGbsaForceBaseTest):
    """
    CustomGbsaForceTest create system for testing CustomGbsaForce
    inherits from CustomGbsaForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomGbsaForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.GBSAOBCForce.CutoffNonPeriodic, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomGbsaForceNonPeriodicCutoffTest'

        # build system

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)


#=============================================================================================
# Test class for force/energy platform comparison tests for CustomGbsaForce w/ cutoffs, periodic
#=============================================================================================

class CustomGbsaForcePeriodicCutoffTest(CustomGbsaForceBaseTest):
    """
    CustomGbsaForceTest create system for testing CustomGbsaForce
    inherits from CustomGbsaForceBaseTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        CustomGbsaForceBaseTest.__init__(self, parameterInput, defaultOverrides, simtk.openmm.GBSAOBCForce.CutoffPeriodic, verbose )
        if( self.isActive() == 0 ): return

        self._testName                       = 'CustomGbsaForcePeriodicCutoffTest'

        if self._verbose: 
            self._validationUtilities.printGbsaObc( self._testName, self._testGbsaObcForce)

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaHarmonicBondForce test
#=============================================================================================

class AmoebaHarmonicBondForceTest(ForceEnergyComparisonTest):
    """
    AmoebaHarmonicBondForceTest create system for testing AmoebaHarmonicBondForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaHarmonicBondForceTest'

        if( parameterInput.getNumberOfAmoebaHarmonicBonds() == 0 ):
            if verbose: print "No harmonic bonds for %s" % parameterInput.getName()
            return
        harmonicBondForce                    = parameterInput.getAmoebaHarmonicBondForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaHarmonicBondForce = self._validationUtilities.copyAmoebaHarmonicBondForce( harmonicBondForce )
        self._system.addForce(testAmoebaHarmonicBondForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba harmonic bonds" % testAmoebaHarmonicBondForce.getNumBonds()
            print "Cubic=%14.7e quartic=%14.7e " % (testAmoebaHarmonicBondForce.getAmoebaGlobalHarmonicBondCubic(), testAmoebaHarmonicBondForce.getAmoebaGlobalHarmonicBondQuartic() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testAmoebaHarmonicBondForce.getNumBonds() ):
                args = testAmoebaHarmonicBondForce.getBondParameters(ii)
                #print "AmoebaHarmonicBond: %5d [%s %s] [%s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]) )
                print "AmoebaHarmonicBond: %5d [%5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2]/lengthUnit, args[3]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaHarmonicBondForce.getNumBonds() > 2*maxPrint  ):ii = testAmoebaHarmonicBondForce.getNumBonds() - maxPrint
            sys.stdout.flush()


        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaHarmonicAngleForce test
#=============================================================================================

class AmoebaHarmonicAngleForceTest(ForceEnergyComparisonTest):
    """
    AmoebaHarmonicAngleForceTest create system for testing AmoebaHarmonicAngleForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaHarmonicAngleForceTest'

        if( parameterInput.getNumberOfAmoebaHarmonicAngles() == 0 ):
            if verbose: print "No angles for %s" % parameterInput.getName()
            return
        harmonicAngleForce                   = parameterInput.getAmoebaHarmonicAngleForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaHarmonicAngleForce = self._validationUtilities.copyAmoebaHarmonicAngleForce( harmonicAngleForce )
        self._system.addForce(testAmoebaHarmonicAngleForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba harmonic angles " % testAmoebaHarmonicAngleForce.getNumAngles()
            print "Cubic=%14.7e quartic=%14.7e pentic=%14.7e  sextic=%14.7e " % (testAmoebaHarmonicAngleForce.getAmoebaGlobalHarmonicAngleCubic(), testAmoebaHarmonicAngleForce.getAmoebaGlobalHarmonicAngleQuartic(), testAmoebaHarmonicAngleForce.getAmoebaGlobalHarmonicAnglePentic(), testAmoebaHarmonicAngleForce.getAmoebaGlobalHarmonicAngleSextic() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint = 10
            while( ii < testAmoebaHarmonicAngleForce.getNumAngles() ):
                args = testAmoebaHarmonicAngleForce.getAngleParameters(ii)
                #print "AmoebaHarmonicAngle: %5d [%s %s] %s %s %s %s %s" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]), type( lengthUnit ), type( forceConstantUnit ) )
                print "AmoebaHarmonicAngle: %5d [%5d %5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3]/lengthUnit, args[4]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaHarmonicAngleForce.getNumAngles() > 2*maxPrint  ):ii = testAmoebaHarmonicAngleForce.getNumAngles() - maxPrint
            sys.stdout.flush()


        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaHarmonicInPlaneAngleForce test
#=============================================================================================

class AmoebaHarmonicInPlaneAngleForceTest(ForceEnergyComparisonTest):
    """
    AmoebaHarmonicInPlaneAngleForceTest create system for testing AmoebaHarmonicInPlaneAngleForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaHarmonicInPlaneAngleForceTest'

        if( parameterInput.getNumberOfAmoebaHarmonicInPlaneAngles() == 0 ):
            if verbose: print "No angles for %s" % parameterInput.getName()
            return

        harmonicInPlaneAngleForce            = parameterInput.getAmoebaHarmonicInPlaneAngleForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaHarmonicInPlaneAngleForce = self._validationUtilities.copyAmoebaHarmonicInPlaneAngleForce( harmonicInPlaneAngleForce )
        self._system.addForce(testAmoebaHarmonicInPlaneAngleForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba in-plane angles " % testAmoebaHarmonicInPlaneAngleForce.getNumAngles()
            print "Cubic=%14.7e quartic=%14.7e pentic=%14.7e  sextic=%14.7e " % (testAmoebaHarmonicInPlaneAngleForce.getAmoebaGlobalHarmonicInPlaneAngleCubic(), testAmoebaHarmonicInPlaneAngleForce.getAmoebaGlobalHarmonicInPlaneAngleQuartic(), testAmoebaHarmonicInPlaneAngleForce.getAmoebaGlobalHarmonicInPlaneAnglePentic(), testAmoebaHarmonicInPlaneAngleForce.getAmoebaGlobalHarmonicInPlaneAngleSextic() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getRadianUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( ) / lengthUnit**2
            maxPrint           = 10
            while( ii < testAmoebaHarmonicInPlaneAngleForce.getNumAngles() ):
                args = testAmoebaHarmonicInPlaneAngleForce.getAngleParameters(ii)
                #print "AmoebaHarmonicInPlaneAngle: %5d [%s %s] [%s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]) )
                print "AmoebaHarmonicInPlaneAngle: %5d [%5d %5d %5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4]/lengthUnit, args[5]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaHarmonicInPlaneAngleForce.getNumAngles() > 2*maxPrint  ):
                    ii = testAmoebaHarmonicInPlaneAngleForce.getNumAngles() - maxPrint
            sys.stdout.flush()


        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaOutOfPlaneBendForce test
#=============================================================================================

class AmoebaOutOfPlaneBendForceTest(ForceEnergyComparisonTest):
    """
    AmoebaOutOfPlaneBendForceTest create system for testing AmoebaOutOfPlaneBendForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaOutOfPlaneBendForceTest'
        self._tolerance                      = 1.0e-01

        if( parameterInput.getNumberOfAmoebaOutOfPlaneBends() == 0 ):
            if verbose: print "No out-of-plane-bends for %s" % parameterInput.getName()
            return
        outOfPlaneBendForce                  = parameterInput.getAmoebaOutOfPlaneBendForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaOutOfPlaneBendForce = self._validationUtilities.copyAmoebaOutOfPlaneBendForce( outOfPlaneBendForce )
        self._system.addForce(testAmoebaOutOfPlaneBendForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "***************** Note: tolerance is %12.3e ***********" % self._tolerance
            print "Added %d Amoeba OutOfPlaneBends " % testAmoebaOutOfPlaneBendForce.getNumOutOfPlaneBends()
            print "Cubic=%14.7e quartic=%14.7e pentic=%14.7e  sextic=%14.7e " % (testAmoebaOutOfPlaneBendForce.getAmoebaGlobalOutOfPlaneBendCubic(), testAmoebaOutOfPlaneBendForce.getAmoebaGlobalOutOfPlaneBendQuartic(), testAmoebaOutOfPlaneBendForce.getAmoebaGlobalOutOfPlaneBendPentic(), testAmoebaOutOfPlaneBendForce.getAmoebaGlobalOutOfPlaneBendSextic() )
            ii                 = 0
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaOutOfPlaneBendForce.getNumOutOfPlaneBends() ):
                args = testAmoebaOutOfPlaneBendForce.getOutOfPlaneBendParameters(ii)
                #print "AmoebaOutOfPlaneBend: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaOutOfPlaneBend: %5d [%5d %5d %5d %5d] [%14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaOutOfPlaneBendForce.getNumOutOfPlaneBends() > 2*maxPrint  ):ii = testAmoebaOutOfPlaneBendForce.getNumOutOfPlaneBends() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaPiTorsionForce test
#=============================================================================================

class AmoebaPiTorsionForceTest(ForceEnergyComparisonTest):
    """
    AmoebaPiTorsionForceTest create system for testing AmoebaPiTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaPiTorsionForceTest'

        if( parameterInput.getNumberOfAmoebaPiTorsions() == 0 ):
            if verbose: print "No pi torsions for %s" % parameterInput.getName()
            return
        piTorsionForce                       = parameterInput.getAmoebaPiTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaPiTorsionForce = self._validationUtilities.copyAmoebaPiTorsionForce( piTorsionForce )
        self._system.addForce(testAmoebaPiTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba PiTorsions " % testAmoebaPiTorsionForce.getNumPiTorsions()
            ii                 = 0
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaPiTorsionForce.getNumPiTorsions() ):
                args = testAmoebaPiTorsionForce.getPiTorsionParameters(ii)
                #print "AmoebaPiTorsion: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaPiTorsion: %5d [%5d %5d %5d %5d %5d %5d] [%14.7e]" % (ii, args[0], args[1], args[2], args[3], args[4],  args[5],  args[6]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaPiTorsionForce.getNumPiTorsions() > 2*maxPrint  ):ii = testAmoebaPiTorsionForce.getNumPiTorsions() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaTorsionForce test
#=============================================================================================

class AmoebaTorsionForceTest(ForceEnergyComparisonTest):
    """
    AmoebaTorsionForceTest create system for testing AmoebaTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaTorsionForceTest'

        if( parameterInput.getNumberOfAmoebaTorsions() == 0 ):
            if verbose: print "No torsions for %s" % parameterInput.getName()
            return
        torsionForce                         = parameterInput.getAmoebaTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaTorsionForce = self._validationUtilities.copyAmoebaTorsionForce( torsionForce )
        self._system.addForce(testAmoebaTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba Torsions " % testAmoebaTorsionForce.getNumTorsions()
            ii                 = 0
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaTorsionForce.getNumTorsions() ):
                args = testAmoebaTorsionForce.getTorsionParameters(ii)
                #print "AmoebaTorsion: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                # getTorsionParameters(int index, int& particle1, int& particle2, int& particle3, int& particle4, 
                #              std::vector<double>& torsion1, std::vector<double>& torsion2, std::vector<double>& torsion3 ) const;

                print "AmoebaTorsion: %5d [%5d %5d %5d %5d] [%8.3f %5.3f] [%8.3f %5.3f] [%8.3f %5.3f] " % (ii, args[0], args[1], args[2], args[3], args[4][0], args[4][1], args[5][0], args[5][1], args[6][0], args[6][1] )
                ii += 1
                if( ii == maxPrint and testAmoebaTorsionForce.getNumTorsions() > 2*maxPrint  ):ii = testAmoebaTorsionForce.getNumTorsions() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaTorsionTorsionForce test
#=============================================================================================

class AmoebaTorsionTorsionForceTest(ForceEnergyComparisonTest):
    """
    AmoebaTorsionTorsionForceTest create system for testing AmoebaTorsionTorsionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaTorsionTorsionForceTest'

        if( parameterInput.getNumberOfAmoebaTorsionTorsions() == 0 ):
            if verbose: print "No torsion-torsion for %s" % parameterInput.getName()
            return
        torsionTorsionForce                  = parameterInput.getAmoebaTorsionTorsionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaTorsionTorsionForce = self._validationUtilities.copyAmoebaTorsionTorsionForce( torsionTorsionForce )
        self._system.addForce(testAmoebaTorsionTorsionForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba TorsionTorsions " % testAmoebaTorsionTorsionForce.getNumTorsionTorsions()
            ii                 = 0
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaTorsionTorsionForce.getNumTorsionTorsions() ):
                args = testAmoebaTorsionTorsionForce.getTorsionTorsionParameters(ii)
                #print "AmoebaTorsionTorsion: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaTorsionTorsion: %5d [%5d %5d %5d %5d %5d %5d %5d] " % (ii, args[0], args[1], args[2], args[3], args[4],  args[5],  args[6] )
                ii += 1
                if( ii == maxPrint and testAmoebaTorsionTorsionForce.getNumTorsionTorsions() > 2*maxPrint  ):ii = testAmoebaTorsionTorsionForce.getNumTorsionTorsions() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaStretchBendForce test
#=============================================================================================

class AmoebaStretchBendForceTest(ForceEnergyComparisonTest):
    """
    AmoebaStretchBendForceTest create system for testing AmoebaStretchBendForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaStretchBendForceTest'

        if verbose: print "parameterInput %s" % parameterInput.getName()
        sys.stdout.flush()
        if( parameterInput.getNumberOfAmoebaStretchBendForces() == 0 ):
            if verbose: print "No stretch-bends for %s" % parameterInput.getName()
            return
        stretchBend                          = parameterInput.getAmoebaStretchBendForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaStretchBendForce = self._validationUtilities.copyAmoebaStretchBendForce( stretchBend )
        self._system.addForce(testAmoebaStretchBendForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba StretchBends " % testAmoebaStretchBendForce.getNumStretchBends()
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )/lengthUnit
            maxPrint           = 10
            while( ii < testAmoebaStretchBendForce.getNumStretchBends() ):
                args = testAmoebaStretchBendForce.getStretchBendParameters(ii)
                #print "AmoebaStretchBend: %5d [%s %s %s] [%s %s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]), type(args[5]), type(args[6]), type( forceConstantUnit ) )
                #print "AmoebaStretchBend: %5d %s %s %s %s]" % (ii, args[3], args[4], args[5], args[6] )
                #sys.stdout.flush()
                print "AmoebaStretchBend: %5d [%5d %5d %5d] [%14.7e %14.7e %14.7e %14.7e]" % (ii, args[0], args[1], args[2], args[3]/lengthUnit, args[4]/lengthUnit, args[5]/self._validationUtilities.getRadianUnit(), args[6]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaStretchBendForce.getNumStretchBends() > 2*maxPrint  ):ii = testAmoebaStretchBendForce.getNumStretchBends() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaUreyBradleyForce test
#=============================================================================================

class AmoebaUreyBradleyForceTest(ForceEnergyComparisonTest):
    """
    AmoebaUreyBradleyForceTest create system for testing AmoebaUreyBradleyForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaUreyBradleyForceTest'

        if( parameterInput.getNumberOfAmoebaUreyBradleys() == 0 ):
            if verbose: print "No Urey-Bradley ixns for %s" % parameterInput.getName()
            return
        ureyBradley                          = parameterInput.getAmoebaUreyBradleyForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaUreyBradleyForce = self._validationUtilities.copyAmoebaUreyBradleyForce( ureyBradley )
        self._system.addForce(testAmoebaUreyBradleyForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba UreyBradleys " % testAmoebaUreyBradleyForce.getNumUreyBradleys()
            print "Cubic=%14.7e quartic=%14.7e " % (testAmoebaUreyBradleyForce.getAmoebaGlobalUreyBradleyCubic(), testAmoebaUreyBradleyForce.getAmoebaGlobalUreyBradleyQuartic() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            forceConstantUnit  = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaUreyBradleyForce.getNumUreyBradleys() ):
                args = testAmoebaUreyBradleyForce.getUreyBradleyParameters(ii)
                #print "AmoebaUreyBradley: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaUreyBradley: %5d [%5d %5d] [%14.7e %14.7e]" % (ii, args[0], args[1], args[2]/lengthUnit, args[3]/forceConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaUreyBradleyForce.getNumUreyBradleys() > 2*maxPrint  ):ii = testAmoebaUreyBradleyForce.getNumUreyBradleys() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaGeneralizedKirkwoodForce test
#=============================================================================================

class AmoebaGeneralizedKirkwoodForceTest(ForceEnergyComparisonTest):
    """
    AmoebaGeneralizedKirkwoodForceTest create system for testing AmoebaGeneralizedKirkwoodForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaGeneralizedKirkwoodForceTest'

        if( parameterInput.getNumberOfAmoebaGeneralizedKirkwoods() == 0 ):
            if verbose: print "No particles for %s" % parameterInput.getName()
            return
        generalizedKirkwood                  = parameterInput.getAmoebaGeneralizedKirkwoodForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaGeneralizedKirkwoodForce = self._validationUtilities.copyAmoebaGeneralizedKirkwoodForce( generalizedKirkwood )
        self._system.addForce(testAmoebaGeneralizedKirkwoodForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba GeneralizedKirkwoods " %   testAmoebaGeneralizedKirkwoodForce.getNumGeneralizedKirkwoods()
            print "Dielectrics        [%12.3f %12.3f] "   % ( testAmoebaGeneralizedKirkwoodForce.getSolventDielectric(), testAmoebaGeneralizedKirkwoodForce.getSoluteDielectric() )
            print "Dielectric offset   %12.3f "           % ( testAmoebaGeneralizedKirkwoodForce.getDielectricOffset() )
            print "IncludeCavityTerm   %d "               % ( testAmoebaGeneralizedKirkwoodForce.getIncludeCavityTerm() )
            print "Probe radius        %12.3f "           % ( testAmoebaGeneralizedKirkwoodForce.getProbeRadius() )
            print "Surface area factor %12.3f "           % ( testAmoebaGeneralizedKirkwoodForce.getSurfaceAreaFactor() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            maxPrint           = 10
            while( ii < testAmoebaGeneralizedKirkwoodForce.getNumGeneralizedKirkwoods() ):
                args = testAmoebaGeneralizedKirkwoodForce.getParticleParameters(ii)
                #print "AmoebaGeneralizedKirkwood: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaGeneralizedKirkwood: %5d [%14.7e %14.7e %14.7e]" % (ii, args[0], args[1]/lengthUnit, args[2] )
                ii += 1
                if( ii == maxPrint and testAmoebaGeneralizedKirkwoodForce.getNumGeneralizedKirkwoods() > 2*maxPrint  ):ii = testAmoebaGeneralizedKirkwoodForce.getNumGeneralizedKirkwoods() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()


#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaWcaDispersionForce test
#=============================================================================================

class AmoebaWcaDispersionForceTest(ForceEnergyComparisonTest):
    """
    AmoebaWcaDispersionForceTest create system for testing AmoebaWcaDispersionForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaWcaDispersionForceTest'

        if( parameterInput.getNumberOfAmoebaWcaDispersionParticles() == 0 ):
            if verbose: print "No particles for %s" % parameterInput.getName()
            return
        wcaDispersion                  = parameterInput.getAmoebaWcaDispersionForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaWcaDispersionForce = self._validationUtilities.copyAmoebaWcaDispersionForce( wcaDispersion )
        self._system.addForce(testAmoebaWcaDispersionForce)

        if self._verbose: 

            lengthUnit         = self._validationUtilities.getLengthUnit( )
            energyConstantUnit = self._validationUtilities.getEnergyUnit( )
            forceConstantUnit  = energyConstantUnit/lengthUnit

            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba WcaDispersions "       %   testAmoebaWcaDispersionForce.getNumParticles()
            print "Eps[O,H]       [%s %s] "       % ( testAmoebaWcaDispersionForce.getEpso(), testAmoebaWcaDispersionForce.getEpsh() )
            #print "Eps[O,H]       [%12.3f %12.3f] "       % ( testAmoebaWcaDispersionForce.getEpso()/energyConstantUnit, testAmoebaWcaDispersionForce.getEpsh()/energyConstantUnit )
            print "Eps[O,H]       [%12.3f %12.3f] "       % ( testAmoebaWcaDispersionForce.getEpso(), testAmoebaWcaDispersionForce.getEpsh())
            #print "Rmin[O,H]      [%12.3f %12.3f] "       % ( testAmoebaWcaDispersionForce.getRmino()/lengthUnit,        testAmoebaWcaDispersionForce.getRminh()/lengthUnit )
            print "Rmin[O,H]      [%12.3f %12.3f] "       % ( testAmoebaWcaDispersionForce.getRmino(),        testAmoebaWcaDispersionForce.getRminh())
            #print "Awater                 %12.3f  "       % ( testAmoebaWcaDispersionForce.getAwater() /(lengthUnit*lengthUnit*lengthUnit) )
            print "Awater                 %12.3f  "       % ( testAmoebaWcaDispersionForce.getAwater() )
            print "Shctd                   %9.5f  "       % ( testAmoebaWcaDispersionForce.getShctd() )
            #print "Dispoff                %12.3f  "       % ( testAmoebaWcaDispersionForce.getDispoff()/lengthUnit )
            print "Dispoff                %12.3f  "       % ( testAmoebaWcaDispersionForce.getDispoff())
            print "Slevy                  %12.3f  "       % ( testAmoebaWcaDispersionForce.getSlevy() )
            ii                 = 0
            maxPrint           = 10
            while( ii < testAmoebaWcaDispersionForce.getNumParticles() ):
                args = testAmoebaWcaDispersionForce.getParticleParameters(ii)
                #print "AmoebaWcaDispersion: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaWcaDispersion: %5d [%14.7e %14.7e]" % (ii, args[0]/lengthUnit, args[1]/energyConstantUnit )
                ii += 1
                if( ii == maxPrint and testAmoebaWcaDispersionForce.getNumParticles() > 2*maxPrint  ):ii = testAmoebaWcaDispersionForce.getNumParticles() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaVdwForce test
#=============================================================================================

class AmoebaVdwForceTest(ForceEnergyComparisonTest):
    """
    AmoebaVdwForceTest create system for testing AmoebaVdwForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaVdwForceTest'

        if( parameterInput.getNumberOfAmoebaVdwParticles() == 0 ):
            if verbose: print "No particles for %s" % parameterInput.getName()
            return
        vdw                                  = parameterInput.getAmoebaVdwForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaVdwForce = self._validationUtilities.copyAmoebaVdwForce( vdw )
        self._system.addForce(testAmoebaVdwForce)

        if self._verbose: 
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba Vdws "                 %   testAmoebaVdwForce.getNumParticles()
            print "Combining rules    [%s %s] "           % ( testAmoebaVdwForce.getSigmaCombiningRule(), testAmoebaVdwForce.getEpsilonCombiningRule() )
            print "Cutoff              %12.3f "           % ( testAmoebaVdwForce.getCutoff() )
            print "Use neighbor list   %d "               % ( testAmoebaVdwForce.getUseNeighborList() )
            print "PBC                 %d "               % ( testAmoebaVdwForce.getPBC() )
            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            energyUnit         = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaVdwForce.getNumParticles() ):
                args = testAmoebaVdwForce.getParticleParameters(ii)
                #print "AmoebaVdw: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaVdw: %5d [%5d %5d %14.7e %14.7e %14.7e]" % (ii, args[0], args[1], args[2]/lengthUnit, args[3]/energyUnit, args[4] )
                ii += 1
                if( ii == maxPrint and testAmoebaVdwForce.getNumParticles() > 2*maxPrint  ):ii = testAmoebaVdwForce.getNumParticles() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

#=============================================================================================
# Test class for force/energy platform comparison tests for AmoebaMultipoleForce test
#=============================================================================================

class AmoebaMultipoleForceTest(ForceEnergyComparisonTest):
    """
    AmoebaMultipoleForceTest create system for testing AmoebaMultipoleForce
    inherits from ForceEnergyComparisonTest
    """
    def __init__(self, parameterInput, defaultOverrides, verbose=False):
        """

        ARGUMENTS

        parameterInput   (ParameterFileParser class)      - ParameterFileParser class containing parameters and 
                                                            coordinates         
        defaultOverrides (dictionary of overrides)        -         
        verbose          (Boolean)                        - if true, be verbose         

        """
        ForceEnergyComparisonTest.__init__(self, defaultOverrides, verbose )

        self._systemName                     = parameterInput.getName().replace( '.txt', '' )
        self._testName                       = 'AmoebaMultipoleForceTest'

        if( parameterInput.getNumberOfAmoebaMultipoleParticles() == 0 ):
            if verbose: print "No particles for %s" % parameterInput.getName()
            return
        multipole                                  = parameterInput.getAmoebaMultipoleForce()

        # build system

        self._system  = self._openMM.System()
        self._validationUtilities.loadSystemMasses( parameterInput.getMasses(), self._system )

        testAmoebaMultipoleForce = self._validationUtilities.copyAmoebaMultipoleForce( multipole )
        self._system.addForce(testAmoebaMultipoleForce)

        if self._verbose: 
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            print "\n\n" + self.getFullTestName()
            print "Added %d Amoeba Multipoles "           %   testAmoebaMultipoleForce.getNumMultipoles()
            print "Nonbond method      %12d   "           % ( testAmoebaMultipoleForce.getNonbondedMethod() )
            print "Cutoff              %12.3f "           % ( testAmoebaMultipoleForce.getCutoffDistance() )
            print "AEwald              %12.3f "           % ( testAmoebaMultipoleForce.getAEwald()*lengthUnit )
            print "Spline order        %12d   "           % ( testAmoebaMultipoleForce.getPmeBSplineOrder() )

            #getPmeGridDimensions = testAmoebaMultipoleForce.getPmeGridDimensions() 
            #print "Grid dimensions         %d "           % ( testAmoebaMultipoleForce.getPmeBSplineOrder() )

            ii                 = 0
            lengthUnit         = self._validationUtilities.getLengthUnit( )
            energyUnit         = self._validationUtilities.getEnergyUnit( )
            maxPrint           = 10
            while( ii < testAmoebaMultipoleForce.getNumMultipoles() ):
                args = testAmoebaMultipoleForce.getMultipoleParameters(ii)
                #print "AmoebaMultipole: %5d [%s %s] [%s %s %s %s]" % (ii, type(args[0]), type(args[1]), type(args[2]), type(args[3]), type(args[4]),type( forceConstantUnit ) )
                print "AmoebaMultipole: %5d q=%14.7e [%14.7e %14.7e %14.7e] ax=%d [%5d %5d %5d] thole=%12.3f dmp=%12.3f polarity=%12.3e " % (ii, args[0], args[1][0], args[1][1], args[1][2],
args[3] , args[4], args[5], args[6], args[7], args[8], args[9] )
                ii += 1
                if( ii == maxPrint and testAmoebaMultipoleForce.getNumMultipoles() > 2*maxPrint  ):ii = testAmoebaMultipoleForce.getNumMultipoles() - maxPrint
            sys.stdout.flush()

        self._positions               = parameterInput.getPositions()

