1 // ****************************************************************************** 2 // 3 // Title: Force Field X. 4 // Description: Force Field X - Software for Molecular Biophysics. 5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025. 6 // 7 // This file is part of Force Field X. 8 // 9 // Force Field X is free software; you can redistribute it and/or modify it 10 // under the terms of the GNU General Public License version 3 as published by 11 // the Free Software Foundation. 12 // 13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT 14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 // details. 17 // 18 // You should have received a copy of the GNU General Public License along with 19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple 20 // Place, Suite 330, Boston, MA 02111-1307 USA 21 // 22 // Linking this library statically or dynamically with other modules is making a 23 // combined work based on this library. Thus, the terms and conditions of the 24 // GNU General Public License cover the whole combination. 25 // 26 // As a special exception, the copyright holders of this library give you 27 // permission to link this library with independent modules to produce an 28 // executable, regardless of the license terms of these independent modules, and 29 // to copy and distribute the resulting executable under terms of your choice, 30 // provided that you also meet, for each linked independent module, the terms 31 // and conditions of the license of that module. An independent module is a 32 // module which is not derived from or based on this library. If you modify this 33 // library, you may extend this exception to your version of the library, but 34 // you are not obligated to do so. If you do not wish to do so, delete this 35 // exception statement from your version. 36 // 37 // ****************************************************************************** 38 package ffx.openmm; 39 40 import com.sun.jna.ptr.DoubleByReference; 41 import com.sun.jna.ptr.IntByReference; 42 43 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True; 44 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_addException; 45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_addParticle; 46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_create; 47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_createExceptionsFromBonds; 48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_destroy; 49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_getCutoffDistance; 50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_getExceptionParameters; 51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_getNumExceptions; 52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_getNumParticles; 53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_getParticleParameters; 54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setCutoffDistance; 55 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setExceptionParameters; 56 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setNonbondedMethod; 57 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setPMEParameters; 58 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setParticleParameters; 59 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setSwitchingDistance; 60 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setUseDispersionCorrection; 61 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_setUseSwitchingFunction; 62 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_updateParametersInContext; 63 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_NonbondedForce_usesPeriodicBoundaryConditions; 64 65 /** 66 * This class implements nonbonded interactions between particles, including a Coulomb force to represent 67 * electrostatics and a Lennard-Jones force to represent van der Waals interactions. It optionally supports 68 * periodic boundary conditions and cutoffs for long range interactions. Lennard-Jones interactions are 69 * calculated with the Lorentz-Berthelot combining rule: it uses the arithmetic mean of the sigmas and the 70 * geometric mean of the epsilons for the two interacting particles. 71 * <p> 72 * To use this class, create a NonbondedForce object, then call addParticle() once for each particle in the 73 * System to define its parameters. The number of particles for which you define nonbonded parameters must 74 * be exactly equal to the number of particles in the System, or else an exception will be thrown when you 75 * try to create a Context. After a particle has been added, you can modify its force field parameters 76 * by calling setParticleParameters(). This will have no effect on Contexts that already exist unless you 77 * call updateParametersInContext(). 78 * <p> 79 * NonbondedForce also lets you specify "exceptions", particular pairs of particles whose interactions should be 80 * computed based on different parameters than those defined for the individual particles. This can be used to 81 * completely exclude certain interactions from the force calculation, or to alter how they interact with each other. 82 * <p> 83 * Many molecular force fields omit Coulomb and Lennard-Jones interactions between particles separated by one 84 * or two bonds, while using modified parameters for those separated by three bonds (known as "1-4 interactions"). 85 * This class provides a convenience method for this case called createExceptionsFromBonds(). You pass to it 86 * a list of bonds and the scale factors to use for 1-4 interactions. It identifies all pairs of particles which 87 * are separated by 1, 2, or 3 bonds, then automatically creates exceptions for them. 88 * <p> 89 * When using a cutoff, by default Lennard-Jones interactions are sharply truncated at the cutoff distance. 90 * Optionally you can instead use a switching function to make the interaction smoothly go to zero over a finite 91 * distance range. To enable this, call setUseSwitchingFunction(). You must also call setSwitchingDistance() 92 * to specify the distance at which the interaction should begin to decrease. The switching distance must be 93 * less than the cutoff distance. 94 * <p> 95 * Another optional feature of this class (enabled by default) is to add a contribution to the energy which approximates 96 * the effect of all Lennard-Jones interactions beyond the cutoff in a periodic system. When running a simulation 97 * at constant pressure, this can improve the quality of the result. Call setUseDispersionCorrection() to set whether 98 * this should be used. 99 * <p> 100 * In some applications, it is useful to be able to inexpensively change the parameters of small groups of particles. 101 * Usually this is done to interpolate between two sets of parameters. For example, a titratable group might have 102 * two states it can exist in, each described by a different set of parameters for the atoms that make up the 103 * group. You might then want to smoothly interpolate between the two states. This is done by first calling 104 * addGlobalParameter() to define a Context parameter, then addParticleParameterOffset() to create a "parameter offset" 105 * that depends on the Context parameter. Each offset defines the following: 106 * <ul> 107 * <li>A Context parameter used to interpolate between the states.</li> 108 * <li>A single particle whose parameters are influenced by the Context parameter.</li> 109 * <li>Three scale factors (chargeScale, sigmaScale, and epsilonScale) that specify how the Context parameter 110 * affects the particle.</li> 111 * </ul> 112 * <p> 113 * The "effective" parameters for a particle (those used to compute forces) are given by 114 * <pre>{@code 115 * charge = baseCharge + param*chargeScale 116 * sigma = baseSigma + param*sigmaScale 117 * epsilon = baseEpsilon + param*epsilonScale 118 * }</pre> 119 * where the "base" values are the ones specified by addParticle() and "param" is the current value 120 * of the Context parameter. A single Context parameter can apply offsets to multiple particles, 121 * and multiple parameters can be used to apply offsets to the same particle. Parameters can also be used 122 * to modify exceptions in exactly the same way by calling addExceptionParameterOffset(). 123 */ 124 public class NonbondedForce extends Force { 125 126 /** 127 * Create a new NonbondedForce. 128 */ 129 public NonbondedForce() { 130 super(OpenMM_NonbondedForce_create()); 131 } 132 133 /** 134 * Add an exception to the force. 135 * 136 * @param particle1 The index of the first particle. 137 * @param particle2 The index of the second particle. 138 * @param chargeProd The charge product. 139 * @param sigma The sigma vdW parameter. 140 * @param epsilon The epsilon vdW parameter. 141 * @param replace If true, replace any existing exception. 142 * @return The index of the exception that was added. 143 */ 144 public int addException(int particle1, int particle2, double chargeProd, double sigma, double epsilon, boolean replace) { 145 return OpenMM_NonbondedForce_addException(pointer, particle1, particle2, chargeProd, sigma, epsilon, replace ? 1 : 0); 146 } 147 148 /** 149 * Add a particle. 150 * 151 * @param charge The atomic charge. 152 * @param sigma The vdW sigma. 153 * @param eps The vdW eps. 154 * @return The index of the particle that was added. 155 */ 156 public int addParticle(double charge, double sigma, double eps) { 157 return OpenMM_NonbondedForce_addParticle(pointer, charge, sigma, eps); 158 } 159 160 /** 161 * Create exceptions from bonds. 162 * 163 * @param bondArray The bond array. 164 * @param coulomb14Scale The coulomb 1-4 scale. 165 * @param lj14Scale The LJ 1-4 scale. 166 */ 167 public void createExceptionsFromBonds(BondArray bondArray, double coulomb14Scale, double lj14Scale) { 168 OpenMM_NonbondedForce_createExceptionsFromBonds(pointer, bondArray.getPointer(), coulomb14Scale, lj14Scale); 169 } 170 171 /** 172 * Destroy the force. 173 */ 174 @Override 175 public void destroy() { 176 if (pointer != null) { 177 OpenMM_NonbondedForce_destroy(pointer); 178 pointer = null; 179 } 180 } 181 182 /** 183 * Get the cutoff distance. 184 * 185 * @return The cutoff distance. 186 */ 187 public double getCutoffDistance() { 188 return OpenMM_NonbondedForce_getCutoffDistance(pointer); 189 } 190 191 /** 192 * Get the exception parameters. 193 * 194 * @param index The exception index. 195 * @param particle1 The first particle. 196 * @param particle2 The second particle. 197 * @param chargeProd The charge product. 198 * @param sigma The sigma vdW parameter. 199 * @param eps The eps vdW parameter. 200 */ 201 public void getExceptionParameters(int index, IntByReference particle1, IntByReference particle2, 202 DoubleByReference chargeProd, DoubleByReference sigma, DoubleByReference eps) { 203 OpenMM_NonbondedForce_getExceptionParameters(pointer, index, particle1, particle2, chargeProd, sigma, eps); 204 } 205 206 /** 207 * Get the number of exceptions. 208 * 209 * @return The number of exceptions. 210 */ 211 public int getNumExceptions() { 212 return OpenMM_NonbondedForce_getNumExceptions(pointer); 213 } 214 215 /** 216 * Get the number of particles. 217 * 218 * @return The number of particles. 219 */ 220 public int getNumParticles() { 221 return OpenMM_NonbondedForce_getNumParticles(pointer); 222 } 223 224 /** 225 * Get the particle parameters. 226 * 227 * @param index The particle index. 228 * @param charge The atomic charge. 229 * @param sigma The vdW sigma. 230 * @param eps The vdW eps. 231 */ 232 public void getParticleParameters(int index, DoubleByReference charge, DoubleByReference sigma, DoubleByReference eps) { 233 OpenMM_NonbondedForce_getParticleParameters(pointer, index, charge, sigma, eps); 234 } 235 236 /** 237 * Set the cutoff distance. 238 * 239 * @param cutoffDistance The cutoff distance. 240 */ 241 public void setCutoffDistance(double cutoffDistance) { 242 OpenMM_NonbondedForce_setCutoffDistance(pointer, cutoffDistance); 243 } 244 245 /** 246 * Set the exception parameters. 247 * 248 * @param index The exception index. 249 * @param particle1 The first particle. 250 * @param particle2 The second particle. 251 * @param chargeProd The charge product. 252 * @param sigma The sigma vdW parameter. 253 * @param eps The eps vdW parameter. 254 */ 255 public void setExceptionParameters(int index, int particle1, int particle2, double chargeProd, double sigma, double eps) { 256 OpenMM_NonbondedForce_setExceptionParameters(pointer, index, particle1, particle2, chargeProd, sigma, eps); 257 } 258 259 /** 260 * Set the nonbonded method. 261 * 262 * @param method The nonbonded method. 263 */ 264 public void setNonbondedMethod(int method) { 265 OpenMM_NonbondedForce_setNonbondedMethod(pointer, method); 266 } 267 268 /** 269 * Set the PME parameters. 270 * 271 * @param aEwald The Ewald alpha. 272 * @param nx The PME grid size in x. 273 * @param ny The PME grid size in y. 274 * @param nz The PME grid size in z. 275 */ 276 public void setPMEParameters(double aEwald, int nx, int ny, int nz) { 277 OpenMM_NonbondedForce_setPMEParameters(pointer, aEwald, nx, ny, nz); 278 } 279 280 /** 281 * Set the particle parameters. 282 * 283 * @param index The particle index. 284 * @param charge The atomic charge. 285 * @param sigma The vdW sigma. 286 * @param eps The vdW eps. 287 */ 288 public void setParticleParameters(int index, double charge, double sigma, double eps) { 289 OpenMM_NonbondedForce_setParticleParameters(pointer, index, charge, sigma, eps); 290 } 291 292 /** 293 * Set the switching distance. 294 * 295 * @param switchingDistance The switching distance. 296 */ 297 public void setSwitchingDistance(double switchingDistance) { 298 OpenMM_NonbondedForce_setSwitchingDistance(pointer, switchingDistance); 299 } 300 301 /** 302 * Set if a dispersion correction will be used. 303 * 304 * @param useDispersionCorrection The dispersion correction flag. 305 */ 306 public void setUseDispersionCorrection(int useDispersionCorrection) { 307 OpenMM_NonbondedForce_setUseDispersionCorrection(pointer, useDispersionCorrection); 308 } 309 310 /** 311 * Set if a switching function will be used. 312 * 313 * @param useSwitchingFunction The switching distance flag. 314 */ 315 public void setUseSwitchingFunction(int useSwitchingFunction) { 316 OpenMM_NonbondedForce_setUseSwitchingFunction(pointer, useSwitchingFunction); 317 } 318 319 /** 320 * Update the parameters in the context. 321 * 322 * @param context The context. 323 */ 324 public void updateParametersInContext(Context context) { 325 if (context.hasContextPointer()) { 326 OpenMM_NonbondedForce_updateParametersInContext(pointer, context.getPointer()); 327 } 328 } 329 330 /** 331 * Check if the force uses periodic boundary conditions. 332 * 333 * @return True if the force uses periodic boundary conditions. 334 */ 335 @Override 336 public boolean usesPeriodicBoundaryConditions() { 337 int pbc = OpenMM_NonbondedForce_usesPeriodicBoundaryConditions(pointer); 338 return pbc == OpenMM_True; 339 } 340 }