Commit 5209c1cd authored by Mark Friedrichs's avatar Mark Friedrichs
Browse files

Lee-Ping's vdw dispersion correction

added tests to TestCudaAmoebaVdwForce for dispersion correction using box of 216 water molecules
AmoebaVdwForce and AmoebaMultipoleForce now throw execptions if cutoff > 0.5*(box size)
parent 887d4e18
#ifndef OPENMM_AMOEBA_VDW_FORCE_H_
#define OPENMM_AMOEBA_VDW_FORCE_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/internal/windowsExport.h"
#include <vector>
namespace OpenMM {
/**
* This class implements an interaction between pairs of particles that varies harmonically with the distance
* between them. To use it, create a VdwForce object then call addAngle() once for each angle. After
* a angle has been added, you can modify its force field parameters by calling setAngleParameters().
*/
class OPENMM_EXPORT AmoebaVdwForce : public Force {
public:
/**
* Create a Amoeba VdwForce.
*/
AmoebaVdwForce();
/**
* Get the number of particles
*/
int getNumParticles() const {
return parameters.size();
}
/**
* Set the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
*/
void setParticleParameters(int particleIndex, int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor );
/**
* Get the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
*/
void getParticleParameters(int particleIndex, int& ivIndex, int& classIndex,
double& sigma, double& epsilon, double& reductionFactor ) const;
/**
* Set the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
* @return index of added particle
*/
int addParticle(int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor );
/**
* Set sigma combining rule
*
* @param sigmaCombiningRule sigma combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'CUBIC-MEAN'
*/
void setSigmaCombiningRule( const std::string& sigmaCombiningRule );
/**
* Get sigma combining rule
*
* @return sigmaCombiningRule sigma combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'CUBIC-MEAN'
*/
const std::string& getSigmaCombiningRule( void ) const;
/**
* Set epsilon combining rule
*
* @param epsilonCombiningRule epsilon combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'HARMONIC', 'HHG'
*/
void setEpsilonCombiningRule( const std::string& epsilonCombiningRule );
/**
* Get epsilon combining rule
*
* @return epsilonCombiningRule epsilon combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'HARMONIC', 'HHG'
*/
const std::string& getEpsilonCombiningRule( void ) const;
/**
* Set exclusions for specified particle
*
* @param particleIndex particle index
* @param exclusions output vector of exclusions
*/
void setParticleExclusions( int particleIndex, const std::vector< int >& exclusions );
/**
* Get exclusions for specified particle
*
* @param particleIndex particle index
* @param exclusions output vector of exclusions
*/
void getParticleExclusions( int particleIndex, std::vector< int >& exclusions ) const;
/**
* Set cutoff
*
* @param cutoff cutoff
*/
void setCutoff( double cutoff );
/**
* Get cutoff
*
* @return cutoff
*/
double getCutoff( void ) const;
/**
* Set flag for using neighbor list for vdw ixn
*
* @param neighboristFlag neighbor list flag
*/
void setUseNeighborList( int neighborListFlag );
/**
* Get neighbor list flag for vdw ixn
*
* @return neighbor list flag
*/
int getUseNeighborList( void ) const;
/**
* Set flag for employing periodic boundary conditions
*
* @param pbcFlag if nonozero, use periodic boundary conditions
*/
void setPBC( int pbcFlag );
/**
* Get periodic boundary conditions flag
*
* @return periodic boundary conditions flag (nonzero -> use PBC)
*/
int getPBC( void ) const;
protected:
ForceImpl* createImpl();
private:
class VdwInfo;
int usePBC;
int useNeighborList;
double cutoff;
std::string sigmaCombiningRule;
std::string epsilonCombiningRule;
std::vector< std::vector<int> > exclusions;
// Retarded visual studio compiler complains about being unable to
// export private stl class members.
// This stanza explains that it should temporarily shut up.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4251)
#endif
std::vector<VdwInfo> parameters;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
std::vector< std::vector< std::vector<double> > > sigEpsTable;
};
class AmoebaVdwForce::VdwInfo {
public:
int ivIndex, classIndex;
double reductionFactor, sigma, epsilon, cutoff;
VdwInfo() {
ivIndex = classIndex = -1;
reductionFactor = 0.0;
sigma = 1.0;
epsilon = 0.0;
}
VdwInfo(int ivIndex, int classIndex, double sigma, double epsilon, double reductionFactor ) :
ivIndex(ivIndex), classIndex(classIndex), sigma(sigma), epsilon(epsilon), reductionFactor(reductionFactor) {
}
};
} // namespace OpenMM
#endif /*OPENMM_AMOEBA_VDW_FORCE_H_*/
#ifndef OPENMM_AMOEBA_VDW_FORCE_H_
#define OPENMM_AMOEBA_VDW_FORCE_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/internal/windowsExport.h"
#include <vector>
namespace OpenMM {
/**
* This class implements an interaction between pairs of particles that varies harmonically with the distance
* between them. To use it, create a VdwForce object then call addAngle() once for each angle. After
* a angle has been added, you can modify its force field parameters by calling setAngleParameters().
*/
class OPENMM_EXPORT AmoebaVdwForce : public Force {
public:
/**
* Create a Amoeba VdwForce.
*/
AmoebaVdwForce();
/**
* Get the number of particles
*/
int getNumParticles() const {
return parameters.size();
}
/**
* Set the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
*/
void setParticleParameters(int particleIndex, int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor );
/**
* Get the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
*/
void getParticleParameters(int particleIndex, int& ivIndex, int& classIndex,
double& sigma, double& epsilon, double& reductionFactor ) const;
/**
* Set the force field parameters for a vdw particle.
*
* @param particleIndex the particle index
* @param ivIndex the iv index
* @param classIndex the class index into the sig-eps table
* @param sigma vdw sigma
* @param epsilon vdw epsilon
* @param reductionFactor the reduction factor
* @return index of added particle
*/
int addParticle(int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor );
/**
* Set sigma combining rule
*
* @param sigmaCombiningRule sigma combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'CUBIC-MEAN'
*/
void setSigmaCombiningRule( const std::string& sigmaCombiningRule );
/**
* Get sigma combining rule
*
* @return sigmaCombiningRule sigma combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'CUBIC-MEAN'
*/
const std::string& getSigmaCombiningRule( void ) const;
/**
* Set epsilon combining rule
*
* @param epsilonCombiningRule epsilon combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'HARMONIC', 'HHG'
*/
void setEpsilonCombiningRule( const std::string& epsilonCombiningRule );
/**
* Get epsilon combining rule
*
* @return epsilonCombiningRule epsilon combining rule: 'ARITHMETIC', 'GEOMETRIC'. 'HARMONIC', 'HHG'
*/
const std::string& getEpsilonCombiningRule( void ) const;
/**
* LPW: Get whether to add a contribution to the energy that approximately represents the effect of VdW
* interactions beyond the cutoff distance. The energy depends on the volume of the periodic box, and is only
* applicable when periodic boundary conditions are used. When running simulations at constant pressure, adding
* this contribution can improve the quality of results.
*/
bool getUseDispersionCorrection() const {
return useDispersionCorrection;
}
/**
* Set whether to add a contribution to the energy that approximately represents the effect of VdW
* interactions beyond the cutoff distance. The energy depends on the volume of the periodic box, and is only
* applicable when periodic boundary conditions are used. When running simulations at constant pressure, adding
* this contribution can improve the quality of results.
*/
void setUseDispersionCorrection(bool useCorrection) {
useDispersionCorrection = useCorrection;
}
/**
* Set exclusions for specified particle
*
* @param particleIndex particle index
* @param exclusions output vector of exclusions
*/
void setParticleExclusions( int particleIndex, const std::vector< int >& exclusions );
/**
* Get exclusions for specified particle
*
* @param particleIndex particle index
* @param exclusions output vector of exclusions
*/
void getParticleExclusions( int particleIndex, std::vector< int >& exclusions ) const;
/**
* Set cutoff
*
* @param cutoff cutoff
*/
void setCutoff( double cutoff );
/**
* Get cutoff
*
* @return cutoff
*/
double getCutoff( void ) const;
/**
* Set flag for using neighbor list for vdw ixn
*
* @param neighboristFlag neighbor list flag
*/
void setUseNeighborList( int neighborListFlag );
/**
* Get neighbor list flag for vdw ixn
*
* @return neighbor list flag
*/
int getUseNeighborList( void ) const;
/**
* Set flag for employing periodic boundary conditions
*
* @param pbcFlag if nonozero, use periodic boundary conditions
*/
void setPBC( int pbcFlag );
/**
* Get periodic boundary conditions flag
*
* @return periodic boundary conditions flag (nonzero -> use PBC)
*/
int getPBC( void ) const;
protected:
ForceImpl* createImpl();
private:
class VdwInfo;
int usePBC;
int useNeighborList;
double cutoff;
bool useDispersionCorrection;
std::string sigmaCombiningRule;
std::string epsilonCombiningRule;
std::vector< std::vector<int> > exclusions;
// Retarded visual studio compiler complains about being unable to
// export private stl class members.
// This stanza explains that it should temporarily shut up.
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4251)
#endif
std::vector<VdwInfo> parameters;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
std::vector< std::vector< std::vector<double> > > sigEpsTable;
};
class AmoebaVdwForce::VdwInfo {
public:
int ivIndex, classIndex;
double reductionFactor, sigma, epsilon, cutoff;
VdwInfo() {
ivIndex = classIndex = -1;
reductionFactor = 0.0;
sigma = 1.0;
epsilon = 0.0;
}
VdwInfo(int ivIndex, int classIndex, double sigma, double epsilon, double reductionFactor ) :
ivIndex(ivIndex), classIndex(classIndex), sigma(sigma), epsilon(epsilon), reductionFactor(reductionFactor) {
}
};
} // namespace OpenMM
#endif /*OPENMM_AMOEBA_VDW_FORCE_H_*/
#ifndef OPENMM_AMOEBA_VDW_FORCE_IMPL_H_
#define OPENMM_AMOEBA_VDW_FORCE_IMPL_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/ForceImpl.h"
#include "openmm/AmoebaVdwForce.h"
#include "openmm/Kernel.h"
#include <utility>
#include <set>
#include <string>
namespace OpenMM {
/**
* This is the internal implementation of AmoebaVdwForce.
*/
class AmoebaVdwForceImpl : public ForceImpl {
public:
AmoebaVdwForceImpl(AmoebaVdwForce& owner);
~AmoebaVdwForceImpl();
void initialize(ContextImpl& context);
AmoebaVdwForce& getOwner() {
return owner;
}
void updateContextState(ContextImpl& context) {
// This force field doesn't update the state directly.
}
double calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups);
std::map<std::string, double> getDefaultParameters() {
return std::map<std::string, double>(); // This force field doesn't define any parameters.
}
std::vector<std::string> getKernelNames();
private:
AmoebaVdwForce& owner;
Kernel kernel;
};
} // namespace OpenMM
#endif /*OPENMM_AMOEBA_VDW_FORCE_IMPL_H_*/
#ifndef OPENMM_AMOEBA_VDW_FORCE_IMPL_H_
#define OPENMM_AMOEBA_VDW_FORCE_IMPL_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/ForceImpl.h"
#include "openmm/AmoebaVdwForce.h"
#include "openmm/Kernel.h"
#include <utility>
#include <set>
#include <string>
namespace OpenMM {
class System;
/**
* This is the internal implementation of AmoebaVdwForce.
*/
class AmoebaVdwForceImpl : public ForceImpl {
public:
AmoebaVdwForceImpl(AmoebaVdwForce& owner);
~AmoebaVdwForceImpl();
void initialize(ContextImpl& context);
AmoebaVdwForce& getOwner() {
return owner;
}
void updateContextState(ContextImpl& context) {
// This force field doesn't update the state directly.
}
double calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups);
std::map<std::string, double> getDefaultParameters() {
return std::map<std::string, double>(); // This force field doesn't define any parameters.
}
std::vector<std::string> getKernelNames();
/**
* Compute the coefficient which, when divided by the periodic box volume, gives the
* long range dispersion correction to the energy.
*/
static double calcDispersionCorrection(const System& system, const AmoebaVdwForce& force);
private:
AmoebaVdwForce& owner;
Kernel kernel;
};
} // namespace OpenMM
#endif /*OPENMM_AMOEBA_VDW_FORCE_IMPL_H_*/
......@@ -53,6 +53,16 @@ void AmoebaMultipoleForceImpl::initialize(ContextImpl& context) {
if (owner.getNumMultipoles() != system.getNumParticles())
throw OpenMMException("AmoebaMultipoleForce must have exactly as many particles as the System it belongs to.");
// check cutoff < 0.5*boxSize
if (owner.getNonbondedMethod() == AmoebaMultipoleForce::PME) {
Vec3 boxVectors[3];
system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
double cutoff = owner.getCutoffDistance();
if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2])
throw OpenMMException("AmoebaMultipoleForce: The cutoff distance cannot be greater than half the periodic box size.");
}
double quadrupoleValidationTolerance = 1.0e-05;
for( int ii = 0; ii < system.getNumParticles(); ii++ ){
......
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/OpenMMException.h"
#include "openmm/AmoebaVdwForce.h"
#include "openmm/internal/AmoebaVdwForceImpl.h"
using namespace OpenMM;
using std::string;
using std::vector;
AmoebaVdwForce::AmoebaVdwForce() : sigmaCombiningRule("CUBIC-MEAN"), epsilonCombiningRule("HHG"), usePBC(0), cutoff(1.0e+10), useNeighborList(0) {
}
int AmoebaVdwForce::addParticle(int ivIndex, int classIndex, double sigma, double epsilon, double reductionFactor ) {
parameters.push_back(VdwInfo(ivIndex, classIndex, sigma, epsilon, reductionFactor));
return parameters.size()-1;
}
void AmoebaVdwForce::getParticleParameters(int particleIndex, int& ivIndex, int& classIndex,
double& sigma, double& epsilon, double& reductionFactor ) const {
ivIndex = parameters[particleIndex].ivIndex;
classIndex = parameters[particleIndex].classIndex;
sigma = parameters[particleIndex].sigma;
epsilon = parameters[particleIndex].epsilon;
reductionFactor = parameters[particleIndex].reductionFactor;
}
void AmoebaVdwForce::setParticleParameters(int particleIndex, int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor ) {
parameters[particleIndex].ivIndex = ivIndex;
parameters[particleIndex].classIndex = classIndex;
parameters[particleIndex].sigma = sigma;
parameters[particleIndex].epsilon = epsilon;
parameters[particleIndex].reductionFactor = reductionFactor;
}
void AmoebaVdwForce::setSigmaCombiningRule( const std::string& inputSigmaCombiningRule ) {
sigmaCombiningRule = inputSigmaCombiningRule;
}
const std::string& AmoebaVdwForce::getSigmaCombiningRule( void ) const {
return sigmaCombiningRule;
}
void AmoebaVdwForce::setEpsilonCombiningRule( const std::string& inputEpsilonCombiningRule ) {
epsilonCombiningRule = inputEpsilonCombiningRule;
}
const std::string& AmoebaVdwForce::getEpsilonCombiningRule( void ) const {
return epsilonCombiningRule;
}
void AmoebaVdwForce::setParticleExclusions( int particleIndex, const std::vector< int >& inputExclusions ) {
if( exclusions.size() < parameters.size() ){
exclusions.resize( parameters.size() );
}
if( static_cast<int>(exclusions.size()) < particleIndex ){
exclusions.resize( particleIndex + 10 );
}
for( unsigned int ii = 0; ii < inputExclusions.size(); ii++ ){
exclusions[particleIndex].push_back( inputExclusions[ii] );
}
}
void AmoebaVdwForce::getParticleExclusions( int particleIndex, std::vector< int >& outputExclusions ) const {
if( particleIndex < static_cast<int>(exclusions.size()) ){
outputExclusions.resize( exclusions[particleIndex].size() );
for( unsigned int ii = 0; ii < exclusions[particleIndex].size(); ii++ ){
outputExclusions[ii] = exclusions[particleIndex][ii];
}
}
}
void AmoebaVdwForce::setCutoff( double inputCutoff ){
cutoff = inputCutoff;
}
double AmoebaVdwForce::getCutoff( void ) const {
return cutoff;
}
void AmoebaVdwForce::setUseNeighborList( int useNeighborListFlag ){
useNeighborList = useNeighborListFlag;
}
int AmoebaVdwForce::getUseNeighborList( void ) const {
return useNeighborList;
}
void AmoebaVdwForce::setPBC( int pbcFlag ){
usePBC = pbcFlag;
}
int AmoebaVdwForce::getPBC( void ) const {
return usePBC;
}
ForceImpl* AmoebaVdwForce::createImpl() {
return new AmoebaVdwForceImpl(*this);
}
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008-2009 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/Force.h"
#include "openmm/OpenMMException.h"
#include "openmm/AmoebaVdwForce.h"
#include "openmm/internal/AmoebaVdwForceImpl.h"
using namespace OpenMM;
using std::string;
using std::vector;
AmoebaVdwForce::AmoebaVdwForce() : sigmaCombiningRule("CUBIC-MEAN"), epsilonCombiningRule("HHG"), usePBC(0), cutoff(1.0e+10), useNeighborList(0), useDispersionCorrection(true) {
}
int AmoebaVdwForce::addParticle(int ivIndex, int classIndex, double sigma, double epsilon, double reductionFactor ) {
parameters.push_back(VdwInfo(ivIndex, classIndex, sigma, epsilon, reductionFactor));
return parameters.size()-1;
}
void AmoebaVdwForce::getParticleParameters(int particleIndex, int& ivIndex, int& classIndex,
double& sigma, double& epsilon, double& reductionFactor ) const {
ivIndex = parameters[particleIndex].ivIndex;
classIndex = parameters[particleIndex].classIndex;
sigma = parameters[particleIndex].sigma;
epsilon = parameters[particleIndex].epsilon;
reductionFactor = parameters[particleIndex].reductionFactor;
}
void AmoebaVdwForce::setParticleParameters(int particleIndex, int ivIndex, int classIndex,
double sigma, double epsilon, double reductionFactor ) {
parameters[particleIndex].ivIndex = ivIndex;
parameters[particleIndex].classIndex = classIndex;
parameters[particleIndex].sigma = sigma;
parameters[particleIndex].epsilon = epsilon;
parameters[particleIndex].reductionFactor = reductionFactor;
}
void AmoebaVdwForce::setSigmaCombiningRule( const std::string& inputSigmaCombiningRule ) {
sigmaCombiningRule = inputSigmaCombiningRule;
}
const std::string& AmoebaVdwForce::getSigmaCombiningRule( void ) const {
return sigmaCombiningRule;
}
void AmoebaVdwForce::setEpsilonCombiningRule( const std::string& inputEpsilonCombiningRule ) {
epsilonCombiningRule = inputEpsilonCombiningRule;
}
const std::string& AmoebaVdwForce::getEpsilonCombiningRule( void ) const {
return epsilonCombiningRule;
}
void AmoebaVdwForce::setParticleExclusions( int particleIndex, const std::vector< int >& inputExclusions ) {
if( exclusions.size() < parameters.size() ){
exclusions.resize( parameters.size() );
}
if( static_cast<int>(exclusions.size()) < particleIndex ){
exclusions.resize( particleIndex + 10 );
}
for( unsigned int ii = 0; ii < inputExclusions.size(); ii++ ){
exclusions[particleIndex].push_back( inputExclusions[ii] );
}
}
void AmoebaVdwForce::getParticleExclusions( int particleIndex, std::vector< int >& outputExclusions ) const {
if( particleIndex < static_cast<int>(exclusions.size()) ){
outputExclusions.resize( exclusions[particleIndex].size() );
for( unsigned int ii = 0; ii < exclusions[particleIndex].size(); ii++ ){
outputExclusions[ii] = exclusions[particleIndex][ii];
}
}
}
void AmoebaVdwForce::setCutoff( double inputCutoff ){
cutoff = inputCutoff;
}
double AmoebaVdwForce::getCutoff( void ) const {
return cutoff;
}
void AmoebaVdwForce::setUseNeighborList( int useNeighborListFlag ){
useNeighborList = useNeighborListFlag;
}
int AmoebaVdwForce::getUseNeighborList( void ) const {
return useNeighborList;
}
void AmoebaVdwForce::setPBC( int pbcFlag ){
usePBC = pbcFlag;
}
int AmoebaVdwForce::getPBC( void ) const {
return usePBC;
}
ForceImpl* AmoebaVdwForce::createImpl() {
return new AmoebaVdwForceImpl(*this);
}
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/AmoebaVdwForceImpl.h"
#include "openmm/amoebaKernels.h"
using namespace OpenMM;
using std::pair;
using std::vector;
using std::set;
AmoebaVdwForceImpl::AmoebaVdwForceImpl(AmoebaVdwForce& owner) : owner(owner) {
}
AmoebaVdwForceImpl::~AmoebaVdwForceImpl() {
}
void AmoebaVdwForceImpl::initialize(ContextImpl& context) {
System& system = context.getSystem();
if (owner.getNumParticles() != system.getNumParticles())
throw OpenMMException("AmoebaVdwForce must have exactly as many particles as the System it belongs to.");
kernel = context.getPlatform().createKernel(CalcAmoebaVdwForceKernel::Name(), context);
kernel.getAs<CalcAmoebaVdwForceKernel>().initialize(context.getSystem(), owner);
}
double AmoebaVdwForceImpl::calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) {
if ((groups&(1<<owner.getForceGroup())) != 0)
return kernel.getAs<CalcAmoebaVdwForceKernel>().execute(context, includeForces, includeEnergy);
return 0.0;
}
std::vector<std::string> AmoebaVdwForceImpl::getKernelNames() {
std::vector<std::string> names;
names.push_back(CalcAmoebaVdwForceKernel::Name());
return names;
}
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "openmm/internal/ContextImpl.h"
#include "openmm/internal/AmoebaVdwForceImpl.h"
#include "openmm/amoebaKernels.h"
#include <map>
#include <stdio.h>
using namespace OpenMM;
using namespace std;
using std::pair;
using std::vector;
using std::set;
AmoebaVdwForceImpl::AmoebaVdwForceImpl(AmoebaVdwForce& owner) : owner(owner) {
}
AmoebaVdwForceImpl::~AmoebaVdwForceImpl() {
}
void AmoebaVdwForceImpl::initialize(ContextImpl& context) {
System& system = context.getSystem();
if (owner.getNumParticles() != system.getNumParticles())
throw OpenMMException("AmoebaVdwForce must have exactly as many particles as the System it belongs to.");
// check that cutoff < 0.5*boxSize
if (owner.getPBC()) {
Vec3 boxVectors[3];
system.getDefaultPeriodicBoxVectors(boxVectors[0], boxVectors[1], boxVectors[2]);
double cutoff = owner.getCutoff();
if (cutoff > 0.5*boxVectors[0][0] || cutoff > 0.5*boxVectors[1][1] || cutoff > 0.5*boxVectors[2][2])
throw OpenMMException("AmoebaVdwForce: The cutoff distance cannot be greater than half the periodic box size.");
}
kernel = context.getPlatform().createKernel(CalcAmoebaVdwForceKernel::Name(), context);
kernel.getAs<CalcAmoebaVdwForceKernel>().initialize(context.getSystem(), owner);
}
double AmoebaVdwForceImpl::calcForcesAndEnergy(ContextImpl& context, bool includeForces, bool includeEnergy, int groups) {
if ((groups&(1<<owner.getForceGroup())) != 0)
return kernel.getAs<CalcAmoebaVdwForceKernel>().execute(context, includeForces, includeEnergy);
return 0.0;
}
double AmoebaVdwForceImpl::calcDispersionCorrection(const System& system, const AmoebaVdwForce& force) {
// Amoeba VdW dispersion correction implemented by LPW
// There is no dispersion correction if PBC is off or the cutoff is set to the default value of ten billion (AmoebaVdwForce.cpp)
if (force.getPBC() == 0 || force.getUseNeighborList() == 0)
return 0.0;
// Identify all particle classes (defined by sigma and epsilon and reduction), and count the number of
// particles in each class.
map<pair<double, double>, int> classCounts;
for (int i = 0; i < force.getNumParticles(); i++) {
double sigma, epsilon, reduction;
// The variables reduction, ivindex, classindex are not used.
int ivindex, classindex;
// Get the sigma and epsilon parameters, ignoring everything else.
force.getParticleParameters(i, ivindex, classindex, sigma, epsilon, reduction);
pair<double, double> key = make_pair(sigma, epsilon);
map<pair<double, double>, int>::iterator entry = classCounts.find(key);
if (entry == classCounts.end())
classCounts[key] = 1;
else
entry->second++;
}
// Compute the VdW tapering coefficients. Mostly copied from amoebaCudaGpu.cpp.
double cutoff = force.getCutoff();
double vdwTaper = 0.90; // vdwTaper is a scaling factor, it is not a distance.
double c0 = 0.0;
double c1 = 0.0;
double c2 = 0.0;
double c3 = 0.0;
double c4 = 0.0;
double c5 = 0.0;
double vdwCut = cutoff;
double vdwTaperCut = vdwTaper*cutoff;
double vdwCut2 = vdwCut*vdwCut;
double vdwCut3 = vdwCut2*vdwCut;
double vdwCut4 = vdwCut2*vdwCut2;
double vdwCut5 = vdwCut2*vdwCut3;
double vdwCut6 = vdwCut3*vdwCut3;
double vdwCut7 = vdwCut3*vdwCut4;
double vdwTaperCut2 = vdwTaperCut*vdwTaperCut;
double vdwTaperCut3 = vdwTaperCut2*vdwTaperCut;
double vdwTaperCut4 = vdwTaperCut2*vdwTaperCut2;
double vdwTaperCut5 = vdwTaperCut2*vdwTaperCut3;
double vdwTaperCut6 = vdwTaperCut3*vdwTaperCut3;
double vdwTaperCut7 = vdwTaperCut3*vdwTaperCut4;
// get 5th degree multiplicative switching function coefficients;
double denom = 1.0 / (vdwCut - vdwTaperCut);
double denom2 = denom*denom;
denom = denom * denom2*denom2;
c0 = vdwCut * vdwCut2 * (vdwCut2 - 5.0 * vdwCut * vdwTaperCut + 10.0 * vdwTaperCut2) * denom;
c1 = -30.0 * vdwCut2 * vdwTaperCut2*denom;
c2 = 30.0 * (vdwCut2 * vdwTaperCut + vdwCut * vdwTaperCut2) * denom;
c3 = -10.0 * (vdwCut2 + 4.0 * vdwCut * vdwTaperCut + vdwTaperCut2) * denom;
c4 = 15.0 * (vdwCut + vdwTaperCut) * denom;
c5 = -6.0 * denom;
// Loop over all pairs of classes to compute the coefficient.
// Copied over from TINKER - numerical integration.
double range = 20.0;
double cut = vdwTaperCut; // This is where tapering BEGINS
double off = vdwCut; // This is where tapering ENDS
int nstep = 200;
int ndelta = int(double(nstep) * (range - cut));
double rdelta = (range - cut) / double(ndelta);
double offset = cut - 0.5 * rdelta;
double dhal = 0.07; // This magic number also appears in kCalculateAmoebaCudaVdw14_7.cu
double ghal = 0.12; // This magic number also appears in kCalculateAmoebaCudaVdw14_7.cu
double elrc = 0.0; // This number is incremented and passed out at the end
double e = 0.0;
double sigma, epsilon; // The pairwise sigma and epsilon parameters.
int i = 0, k = 0; // Loop counters.
// Double loop over different atom types.
std::string sigmaCombiningRule = force.getSigmaCombiningRule();
std::string epsilonCombiningRule = force.getEpsilonCombiningRule();
for (map<pair<double, double>, int>::const_iterator class1 = classCounts.begin(); class1 != classCounts.end(); ++class1) {
k = 0;
for (map<pair<double, double>, int>::const_iterator class2 = classCounts.begin(); class2 != classCounts.end(); ++class2) {
// AMOEBA combining rules, copied over from the CUDA code.
double iSigma = class1->first.first;
double jSigma = class2->first.first;
double iEpsilon = class1->first.second;
double jEpsilon = class2->first.second;
// ARITHMETIC = 1
// GEOMETRIC = 2
// CUBIC-MEAN = 3
if (sigmaCombiningRule == "ARITHMETIC") {
sigma = iSigma + jSigma;
} else if (sigmaCombiningRule == "GEOMETRIC") {
sigma = 2.0f * std::sqrt(iSigma * jSigma);
} else {
double iSigma2 = iSigma*iSigma;
double jSigma2 = jSigma*jSigma;
sigma = 2.0f * (iSigma2 * iSigma + jSigma2 * jSigma) / (iSigma2 + jSigma2);
}
// ARITHMETIC = 1
// GEOMETRIC = 2
// HARMONIC = 3
// HHG = 4
if (epsilonCombiningRule == "ARITHMETIC") {
epsilon = 0.5f * (iEpsilon + jEpsilon);
} else if (epsilonCombiningRule == "GEOMETRIC") {
epsilon = std::sqrt(iEpsilon * jEpsilon);
} else if (epsilonCombiningRule == "HARMONIC") {
epsilon = 2.0f * (iEpsilon * jEpsilon) / (iEpsilon + jEpsilon);
} else {
double epsilonS = std::sqrt(iEpsilon) + std::sqrt(jEpsilon);
epsilon = 4.0f * (iEpsilon * jEpsilon) / (epsilonS * epsilonS);
}
int count = class1->second * class2->second;
// Below is an exact copy of stuff from the previous block.
double rv = sigma;
double termik = 2.0 * M_PI * count; // termik is equivalent to 2 * pi * count.
double rv2 = rv * rv;
double rv6 = rv2 * rv2 * rv2;
double rv7 = rv6 * rv;
double etot = 0.0;
double r2 = 0.0;
for (int j = 1; j <= ndelta; j++) {
double r = offset + double(j) * rdelta;
r2 = r*r;
double r3 = r2 * r;
double r6 = r3 * r3;
double r7 = r6 * r;
// The following is for buffered 14-7 only.
/*
double rho = r/rv;
double term1 = pow(((dhal + 1.0) / (dhal + rho)),7);
double term2 = ((ghal + 1.0) / (ghal + pow(rho,7))) - 2.0;
e = epsilon * term1 * term2;
*/
double rho = r7 + ghal*rv7;
double tau = (dhal + 1.0) / (r + dhal * rv);
double tau7 = pow(tau, 7);
e = epsilon * rv7 * tau7 * ((ghal + 1.0) * rv7 / rho - 2.0);
double taper = 0.0;
if (r < off) {
double r4 = r2 * r2;
double r5 = r2 * r3;
taper = c5 * r5 + c4 * r4 + c3 * r3 + c2 * r2 + c1 * r + c0;
e = e * (1.0 - taper);
}
etot = etot + e * rdelta * r2;
}
elrc = elrc + termik * etot;
k++;
}
i++;
}
return elrc;
}
std::vector<std::string> AmoebaVdwForceImpl::getKernelNames() {
std::vector<std::string> names;
names.push_back(CalcAmoebaVdwForceKernel::Name());
return names;
}
#ifndef AMOEBA_CUDA_DATA_H_
#define AMOEBA_CUDA_DATA_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "CudaPlatform.h"
#include "kernels/amoebaGpuTypes.h"
#include "kernels/cudaKernels.h"
#include "openmm/KernelImpl.h"
namespace OpenMM {
/**
* This kernel is invoked by AmoebaHarmonicBondForce to calculate the forces acting on the system and the energy of the system.
*/
class AmoebaCudaData {
public:
AmoebaCudaData( CudaPlatform::PlatformData& data );
~AmoebaCudaData();
/**
* Increment kernel count
*
*/
void incrementKernelCount( void );
/**
* Decrement kernel count
*
*/
void decrementKernelCount( void );
/**
* Set value of hasAmoebaBonds
*
* @param value of hasAmoebaBonds
*/
void setHasAmoebaBonds( bool inputHasAmoebaBonds );
/**
* Set value of hasAmoebaMultipole
*
* @param value of hasAmoebaMultipole
*/
void setHasAmoebaMultipole( bool inputHasAmoebaMultipole );
/**
* Get value of hasAmoebaMultipole
*
* @return value of hasAmoebaMultipole
*/
bool getHasAmoebaMultipole( void ) const;
/**
* Get use Grycuk flag
*
* @return value of useGrycuk
*/
int getUseGrycuk( void ) const;
/**
* Set value of hasAmoebaGeneralizedKirkwood
*
* @param value of hasAmoebaGeneralizedKirkwood
*/
void setHasAmoebaGeneralizedKirkwood( bool inputHasAmoebaGeneralizedKirkwood );
/**
* Get value of hasAmoebaGeneralizedKirkwood
*
* @return value of hasAmoebaGeneralizedKirkwood
*/
bool getHasAmoebaGeneralizedKirkwood( void ) const;
/**
* Return amoebaGpuContext context
*
* @return amoebaGpuContext
*/
amoebaGpuContext OPENMMCUDA_EXPORT getAmoebaGpu( void ) const;
/**
* Set accessor for LocalForcesKernel
*
* @param inputLocalForceKernel
*/
void setAmoebaLocalForcesKernel( KernelImpl* inputLocalForceKernel );
/**
* Get accessor for LocalForcesKernel
*
* @return localForceKernel
*/
KernelImpl* getAmoebaLocalForcesKernel( void ) const;
/**
* Set log file reference
*
* @param log file reference; if not set, then no logging
*/
void setLog( FILE* inputLog );
/**
* Get log file reference
*
* @return log file reference
*/
FILE* getLog( void ) const;
/**
* if gpuInitialized is false, write data to board
*
* @param log file reference; if not set, then no logging
*/
void initializeGpu( void );
/**
* Set contextImpl
*
* @param contextImpl reference
*/
void setContextImpl( void* contextImpl );
/**
* Get multipole force count
*
* @return multipole force count
*/
int getMultipoleForceCount( void ) const;
/**
* Get multipole force count
*
* @return multipole force count
*/
void incrementMultipoleForceCount( void );
/**
* Get multipole cutoff
*
* @return multipole cutoff
*/
int getApplyMultipoleCutoff( ) const;
/**
* Set multipole cutoff
*
* @return multipole cutoff
*/
void setApplyMultipoleCutoff( int applyMultipoleCutoff );
/**
* Get vdw cutoff
*
* @return vdw cutoff
*/
int getUseVdwNeighborList( ) const;
/**
* Set vdw cutoff
*
* @return vdw cutoff
*/
void setUseVdwNeighborList( int useVdwNeighborList );
/**
* Set flag indicating whether gpu is initialized
*
* @param flag indicating gpu is initialized
*/
void setGpuInitialized( bool gpuInitialized );
CudaPlatform::PlatformData& cudaPlatformData;
private:
amoebaGpuContext amoebaGpu;
bool hasAmoebaBonds, hasAmoebaGeneralizedKirkwood, hasAmoebaMultipole;
int multipoleForceCount;
int applyMultipoleCutoff;
int useVdwNeighborList;
int useGrycuk;
KernelImpl* localForceKernel;
unsigned int kernelCount;
void* contextImpl;
FILE* log;
bool gpuInitialized;
double boxDimensions[3];
};
} // namespace OpenMM
#endif /*AMOEBA_CUDA_DATA_H_*/
#ifndef AMOEBA_CUDA_DATA_H_
#define AMOEBA_CUDA_DATA_H_
/* -------------------------------------------------------------------------- *
* OpenMMAmoeba *
* -------------------------------------------------------------------------- *
* This is part of the OpenMM molecular simulation toolkit originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2008 Stanford University and the Authors. *
* Authors: *
* Contributors: *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* -------------------------------------------------------------------------- */
#include "CudaPlatform.h"
#include "kernels/amoebaGpuTypes.h"
#include "kernels/cudaKernels.h"
#include "openmm/KernelImpl.h"
namespace OpenMM {
/**
* This kernel is invoked by AmoebaHarmonicBondForce to calculate the forces acting on the system and the energy of the system.
*/
class AmoebaCudaData {
public:
AmoebaCudaData( CudaPlatform::PlatformData& data );
~AmoebaCudaData();
/**
* Increment kernel count
*
*/
void incrementKernelCount( void );
/**
* Decrement kernel count
*
*/
void decrementKernelCount( void );
/**
* Set value of hasAmoebaBonds
*
* @param value of hasAmoebaBonds
*/
void setHasAmoebaBonds( bool inputHasAmoebaBonds );
/**
* Set value of hasAmoebaMultipole
*
* @param value of hasAmoebaMultipole
*/
void setHasAmoebaMultipole( bool inputHasAmoebaMultipole );
/**
* Get value of hasAmoebaMultipole
*
* @return value of hasAmoebaMultipole
*/
bool getHasAmoebaMultipole( void ) const;
/**
* Get use Grycuk flag
*
* @return value of useGrycuk
*/
int getUseGrycuk( void ) const;
/**
* Set value of hasAmoebaGeneralizedKirkwood
*
* @param value of hasAmoebaGeneralizedKirkwood
*/
void setHasAmoebaGeneralizedKirkwood( bool inputHasAmoebaGeneralizedKirkwood );
/**
* Get value of hasAmoebaGeneralizedKirkwood
*
* @return value of hasAmoebaGeneralizedKirkwood
*/
bool getHasAmoebaGeneralizedKirkwood( void ) const;
/**
* Return amoebaGpuContext context
*
* @return amoebaGpuContext
*/
amoebaGpuContext OPENMMCUDA_EXPORT getAmoebaGpu( void ) const;
/**
* Set accessor for LocalForcesKernel
*
* @param inputLocalForceKernel
*/
void setAmoebaLocalForcesKernel( KernelImpl* inputLocalForceKernel );
/**
* Get accessor for LocalForcesKernel
*
* @return localForceKernel
*/
KernelImpl* getAmoebaLocalForcesKernel( void ) const;
/**
* Set log file reference
*
* @param log file reference; if not set, then no logging
*/
void setLog( FILE* inputLog );
/**
* Get log file reference
*
* @return log file reference
*/
FILE* getLog( void ) const;
/**
* if gpuInitialized is false, write data to board
*
* @param log file reference; if not set, then no logging
*/
void initializeGpu( void );
/**
* Set contextImpl
*
* @param contextImpl reference
*/
void setContextImpl( void* contextImpl );
/**
* Get multipole force count
*
* @return multipole force count
*/
int getMultipoleForceCount( void ) const;
/**
* Get multipole force count
*
* @return multipole force count
*/
void incrementMultipoleForceCount( void );
/**
* Get multipole cutoff
*
* @return multipole cutoff
*/
int getApplyMultipoleCutoff( ) const;
/**
* Set multipole cutoff
*
* @return multipole cutoff
*/
void setApplyMultipoleCutoff( int applyMultipoleCutoff );
/**
* Get vdw cutoff
*
* @return vdw cutoff
*/
int getUseVdwNeighborList( ) const;
/**
* Set vdw cutoff
*
* @return vdw cutoff
*/
void setUseVdwNeighborList( int useVdwNeighborList );
/**
* Set flag indicating whether gpu is initialized
*
* @param flag indicating gpu is initialized
*/
void setGpuInitialized( bool gpuInitialized );
CudaPlatform::PlatformData& cudaPlatformData;
double dispersionCoefficient;
private:
amoebaGpuContext amoebaGpu;
bool hasAmoebaBonds, hasAmoebaGeneralizedKirkwood, hasAmoebaMultipole;
int multipoleForceCount;
int applyMultipoleCutoff;
int useVdwNeighborList;
int useGrycuk;
KernelImpl* localForceKernel;
unsigned int kernelCount;
void* contextImpl;
FILE* log;
bool gpuInitialized;
double boxDimensions[3];
};
} // namespace OpenMM
#endif /*AMOEBA_CUDA_DATA_H_*/
......@@ -618,6 +618,10 @@ void ReferenceCalcAmoebaMultipoleForceKernel::getSystemMultipoleMoments(ContextI
ReferenceCalcAmoebaVdwForceKernel::ReferenceCalcAmoebaVdwForceKernel(std::string name, const Platform& platform, System& system) :
CalcAmoebaVdwForceKernel(name, platform), system(system) {
useNeighborList = 0;
usePBC = 0;
cutoff = 1.0e+10;
}
ReferenceCalcAmoebaVdwForceKernel::~ReferenceCalcAmoebaVdwForceKernel() {
......@@ -656,14 +660,27 @@ void ReferenceCalcAmoebaVdwForceKernel::initialize(const System& system, const A
}
sigmaCombiningRule = force.getSigmaCombiningRule();
epsilonCombiningRule = force.getEpsilonCombiningRule();
useNeighborList = force.getUseNeighborList();
usePBC = force.getPBC();
cutoff = force.getCutoff();
}
double ReferenceCalcAmoebaVdwForceKernel::execute(ContextImpl& context, bool includeForces, bool includeEnergy) {
vector<RealVec>& posData = extractPositions(context);
vector<RealVec>& forceData = extractForces(context);
AmoebaReferenceVdwForce vdwForce( sigmaCombiningRule, epsilonCombiningRule, AmoebaReferenceVdwForce::NoCutoff );
RealOpenMM energy = vdwForce.calculateForceAndEnergy( numParticles, posData, indexIVs, indexClasses, sigmas, epsilons, reductions, allExclusions, forceData);
AmoebaReferenceVdwForce vdwForce( sigmaCombiningRule, epsilonCombiningRule );
if( useNeighborList ){
vdwForce.setCutoff( cutoff );
if( usePBC ){
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffPeriodic);
} else {
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::CutoffNonPeriodic);
}
} else {
vdwForce.setNonbondedMethod( AmoebaReferenceVdwForce::NoCutoff );
}
RealOpenMM energy = vdwForce.calculateForceAndEnergy( numParticles, posData, indexIVs, indexClasses, sigmas, epsilons, reductions, allExclusions, forceData);
return static_cast<double>(energy);
}
......
......@@ -29,6 +29,7 @@
#include "openmm/System.h"
#include "openmm/amoebaKernels.h"
#include "SimTKReference/ReferenceNeighborList.h"
#include "SimTKUtilities/SimTKOpenMMRealType.h"
namespace OpenMM {
......@@ -430,33 +431,6 @@ private:
System& system;
};
// /**
// * This kernel is invoked by AmoebaMultipoleForce to calculate the forces acting on the system and the energy of the system.
// */
// class ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel : public CalcAmoebaGeneralizedKirkwoodForceKernel {
// public:
// ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel(std::string name, const Platform& platform, System& system);
// ~ReferenceCalcAmoebaGeneralizedKirkwoodForceKernel();
// /**
// * Initialize the kernel.
// *
// * @param system the System this kernel will be applied to
// * @param force the AmoebaMultipoleForce this kernel will be used for
// */
// void initialize(const System& system, const AmoebaGeneralizedKirkwoodForce& force);
// /**
// * Execute the kernel to calculate the forces and/or energy.
// *
// * @param context the context in which to execute this kernel
// * @param includeForces true if forces should be calculated
// * @param includeEnergy true if the energy should be calculated
// * @return the potential energy due to the force
// */
// double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
// private:
// System& system;
// };
/**
* This kernel is invoked to calculate the vdw forces acting on the system and the energy of the system.
*/
......@@ -482,6 +456,9 @@ public:
double execute(ContextImpl& context, bool includeForces, bool includeEnergy);
private:
int numParticles;
int useNeighborList;
int usePBC;
double cutoff;
std::vector<int> indexIVs;
std::vector<int> indexClasses;
std::vector< std::vector<int> > allExclusions;
......@@ -491,6 +468,7 @@ private:
std::string sigmaCombiningRule;
std::string epsilonCombiningRule;
System& system;
NeighborList* neighborList;
};
/**
......
......@@ -32,12 +32,12 @@ using OpenMM::RealVec;
AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( ) : _nonbondedMethod(NoCutoff) {
_cutoff = 1.0e+10;
setSigmaCombiningRule( "ARITHMETIC" );
setEpsilonCombiningRule( "GEOMETRIC" );
}
AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( const std::string& sigmaCombiningRule, const std::string& epsilonCombiningRule, NonbondedMethod nonbondedMethod ) :
_nonbondedMethod(nonbondedMethod) {
AmoebaReferenceVdwForce::AmoebaReferenceVdwForce( const std::string& sigmaCombiningRule, const std::string& epsilonCombiningRule ) : _nonbondedMethod(NoCutoff) {
setSigmaCombiningRule( sigmaCombiningRule );
setEpsilonCombiningRule( epsilonCombiningRule );
......@@ -51,6 +51,14 @@ void AmoebaReferenceVdwForce::setNonbondedMethod( AmoebaReferenceVdwForce::Nonbo
_nonbondedMethod = nonbondedMethod;
}
void AmoebaReferenceVdwForce::setCutoff( double cutoff ){
_cutoff = cutoff;
}
double AmoebaReferenceVdwForce::getCutoff( void ) const {
return _cutoff;
}
void AmoebaReferenceVdwForce::setSigmaCombiningRule( const std::string& sigmaCombiningRule ){
_sigmaCombiningRule = sigmaCombiningRule;
......@@ -116,7 +124,7 @@ RealOpenMM AmoebaReferenceVdwForce::arithmeticEpsilonCombiningRule( RealOpenMM e
}
RealOpenMM AmoebaReferenceVdwForce::geometricEpsilonCombiningRule( RealOpenMM epsilonI, RealOpenMM epsilonJ ) const {
return 2.0*SQRT(epsilonI*epsilonJ);
return SQRT(epsilonI*epsilonJ);
}
RealOpenMM AmoebaReferenceVdwForce::harmonicEpsilonCombiningRule( RealOpenMM epsilonI, RealOpenMM epsilonJ ) const {
......@@ -199,7 +207,7 @@ RealOpenMM AmoebaReferenceVdwForce::calculatePairIxn( RealOpenMM combindedSigma,
}
RealOpenMM AmoebaReferenceVdwForce::calculateNoCutoffForceAndEnergy( int numParticles,
RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergyNoCutoff( int numParticles,
const vector<RealVec>& particlePositions,
const std::vector<int>& indexIVs,
const std::vector<int>& indexClasses,
......@@ -211,7 +219,88 @@ RealOpenMM AmoebaReferenceVdwForce::calculateNoCutoffForceAndEnergy( int numPart
// ---------------------------------------------------------------------------------------
//static const std::string methodName = "AmoebaReferenceVdwForce::calculateNoCutoffForceAndEnergy";
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
static const RealOpenMM two = 2.0;
// ---------------------------------------------------------------------------------------
// set reduced coordinates
std::vector<Vec3> reducedPositions;
reducedPositions.resize(numParticles);
for( unsigned int ii = 0; ii < static_cast<unsigned int>(numParticles); ii++ ){
if( reductions[ii] != zero ){
int reductionIndex = indexIVs[ii];
reducedPositions[ii] = Vec3( reductions[ii]*( particlePositions[ii][0] - particlePositions[reductionIndex][0] ) + particlePositions[reductionIndex][0],
reductions[ii]*( particlePositions[ii][1] - particlePositions[reductionIndex][1] ) + particlePositions[reductionIndex][1],
reductions[ii]*( particlePositions[ii][2] - particlePositions[reductionIndex][2] ) + particlePositions[reductionIndex][2] );
} else {
reducedPositions[ii] = Vec3( particlePositions[ii][0], particlePositions[ii][1], particlePositions[ii][2] );
}
}
// loop over all ixns
// (1) initialize exclusion vector
RealOpenMM energy = zero;
std::vector<unsigned int> exclusions(numParticles, 0);
for( unsigned int ii = 0; ii < static_cast<unsigned int>(numParticles); ii++ ){
RealOpenMM sigmaI = sigmas[ii];
RealOpenMM epsilonI = epsilons[ii];
for( unsigned int jj = 0; jj < allExclusions[ii].size(); jj++ ){
exclusions[allExclusions[ii][jj]] = 1;
}
for( unsigned int jj = ii+1; jj < static_cast<unsigned int>(numParticles); jj++ ){
if( exclusions[jj] == 0 ){
RealOpenMM combindedSigma = (this->*_combineSigmas)(sigmaI, sigmas[jj] );
RealOpenMM combindedEpsilon = (this->*_combineEpsilons)(epsilonI, epsilons[jj] );
Vec3 force;
energy += calculatePairIxn( combindedSigma, combindedEpsilon,
reducedPositions[ii], reducedPositions[jj],
force );
if( indexIVs[ii] == ii ){
forces[ii][0] -= force[0];
forces[ii][1] -= force[1];
forces[ii][2] -= force[2];
} else {
addReducedForce( ii, indexIVs[ii], reductions[ii], -one, force, forces );
}
if( indexIVs[jj] == jj ){
forces[jj][0] += force[0];
forces[jj][1] += force[1];
forces[jj][2] += force[2];
} else {
addReducedForce( jj, indexIVs[jj], reductions[jj], one, force, forces );
}
}
}
for( unsigned int jj = 0; jj < allExclusions[ii].size(); jj++ ){
exclusions[allExclusions[ii][jj]] = 0;
}
}
return energy;
}
RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergyApplyCutoff( int numParticles,
const vector<RealVec>& particlePositions,
const std::vector<int>& indexIVs,
const std::vector<int>& indexClasses,
const std::vector<RealOpenMM>& sigmas,
const std::vector<RealOpenMM>& epsilons,
const std::vector<RealOpenMM>& reductions,
const std::vector< std::vector<int> >& allExclusions,
vector<RealVec>& forces ) const {
// ---------------------------------------------------------------------------------------
static const RealOpenMM zero = 0.0;
static const RealOpenMM one = 1.0;
......@@ -295,11 +384,24 @@ RealOpenMM AmoebaReferenceVdwForce::calculateForceAndEnergy( int numParticles,
vector<RealVec>& forces ) const {
if( getNonbondedMethod() == NoCutoff || 1 ){
return calculateNoCutoffForceAndEnergy( numParticles, particlePositions,
if( getNonbondedMethod() == NoCutoff ){
return calculateForceAndEnergyNoCutoff( numParticles, particlePositions,
indexIVs, indexClasses, sigmas, epsilons,
reductions, allExclusions, forces );
} else {
return calculateForceAndEnergyApplyCutoff( numParticles, particlePositions,
indexIVs, indexClasses, sigmas, epsilons,
reductions, allExclusions, forces );
}
}
/*
double cutoff = force.getCutoff();
double taperCutoff = cutoff*0.9;
replacements["CUTOFF_DISTANCE"] = cu.doubleToString(force.getCutoff());
replacements["TAPER_CUTOFF"] = cu.doubleToString(taperCutoff);
replacements["TAPER_C3"] = cu.doubleToString(10/pow(taperCutoff-cutoff, 3.0));
replacements["TAPER_C4"] = cu.doubleToString(15/pow(taperCutoff-cutoff, 4.0));
replacements["TAPER_C5"] = cu.doubleToString(6/pow(taperCutoff-cutoff, 5.0));
*/
......@@ -79,8 +79,7 @@ public:
--------------------------------------------------------------------------------------- */
AmoebaReferenceVdwForce( const std::string& sigmaCombiningRule,
const std::string& epsilonCombiningRule,
NonbondedMethod nonbondedMethod );
const std::string& epsilonCombiningRule );
/**---------------------------------------------------------------------------------------
......@@ -110,6 +109,26 @@ public:
void setNonbondedMethod( NonbondedMethod nonbondedMethod );
/**---------------------------------------------------------------------------------------
Get cutoff
@return cutoff
--------------------------------------------------------------------------------------- */
double getCutoff( void ) const;
/**---------------------------------------------------------------------------------------
Set cutof
@param cutoff
--------------------------------------------------------------------------------------- */
void setCutoff( double cutoff );
/**---------------------------------------------------------------------------------------
Set sigma combining rule
......@@ -181,6 +200,7 @@ private:
std::string _sigmaCombiningRule;
std::string _epsilonCombiningRule;
NonbondedMethod _nonbondedMethod;
double _cutoff;
CombiningFunction _combineSigmas;
RealOpenMM arithmeticSigmaCombiningRule( RealOpenMM sigmaI, RealOpenMM sigmaJ ) const;
......@@ -246,7 +266,7 @@ private:
--------------------------------------------------------------------------------------- */
RealOpenMM calculateNoCutoffForceAndEnergy( int numParticles, const std::vector<OpenMM::RealVec>& particlePositions,
RealOpenMM calculateForceAndEnergyNoCutoff( int numParticles, const std::vector<OpenMM::RealVec>& particlePositions,
const std::vector<int>& indexIVs,
const std::vector<int>& indexClasses,
const std::vector<RealOpenMM>& sigmas, const std::vector<RealOpenMM>& epsilons,
......@@ -254,6 +274,32 @@ private:
const std::vector< std::vector<int> >& vdwExclusions,
std::vector<OpenMM::RealVec>& forces ) const;
/**---------------------------------------------------------------------------------------
Calculate Vdw ixns w/ cutoff
@param numParticles number of particles
@param particlePositions Cartesian coordinates of particles
@param indexIVs position index for associated reducing particle
@param indexClasses class index for combining sigmas/epsilons (not currently used)
@param sigmas particle sigmas
@param epsilons particle epsilons
@param reductions particle reduction factors
@param vdwExclusions particle exclusions
@param forces add forces to this vector
@return energy
--------------------------------------------------------------------------------------- */
RealOpenMM calculateForceAndEnergyApplyCutoff( int numParticles, const std::vector<OpenMM::RealVec>& particlePositions,
const std::vector<int>& indexIVs,
const std::vector<int>& indexClasses,
const std::vector<RealOpenMM>& sigmas, const std::vector<RealOpenMM>& epsilons,
const std::vector<RealOpenMM>& reductions,
const std::vector< std::vector<int> >& vdwExclusions,
std::vector<OpenMM::RealVec>& forces ) const;
};
// ---------------------------------------------------------------------------------------
......
......@@ -2793,6 +2793,11 @@ class AmoebaVdwGenerator:
else:
force.setCutoff(nonbondedCutoff)
# dispersion correction
if ('useDispersionCorrection' in args):
force.setUseDispersionCorrection(int(args['useDispersionCorrection']))
if (nonbondedMethod == PME):
force.setPBC(1)
force.setUseNeighborList(1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment