NonbondedForce.h 23.4 KB
Newer Older
1
2
#ifndef OPENMM_NONBONDEDFORCE_H_
#define OPENMM_NONBONDEDFORCE_H_
3
4
5
6
7
8
9
10
11

/* -------------------------------------------------------------------------- *
 *                                   OpenMM                                   *
 * -------------------------------------------------------------------------- *
 * 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.               *
 *                                                                            *
12
 * Portions copyright (c) 2008-2014 Stanford University and the Authors.      *
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * Authors: Peter Eastman                                                     *
 * 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.                                     *
 * -------------------------------------------------------------------------- */

35
#include "Context.h"
36
37
#include "Force.h"
#include <map>
38
#include <set>
39
#include <utility>
40
#include <vector>
41
#include "internal/windowsExport.h"
42
43
44
45

namespace OpenMM {

/**
46
47
 * This class implements nonbonded interactions between particles, including a Coulomb force to represent
 * electrostatics and a Lennard-Jones force to represent van der Waals interactions.  It optionally supports
48
 * periodic boundary conditions and cutoffs for long range interactions.  Lennard-Jones interactions are
peastman's avatar
peastman committed
49
 * calculated with the Lorentz-Berthelot combining rule: it uses the arithmetic mean of the sigmas and the
50
 * geometric mean of the epsilons for the two interacting particles.
51
52
53
54
 *
 * To use this class, create a NonbondedForce object, then call addParticle() once for each particle in the
 * System to define its parameters.  The number of particles for which you define nonbonded parameters must
 * be exactly equal to the number of particles in the System, or else an exception will be thrown when you
55
 * try to create a Context.  After a particle has been added, you can modify its force field parameters
56
57
 * by calling setParticleParameters().  This will have no effect on Contexts that already exist unless you
 * call updateParametersInContext().
58
59
60
61
62
63
64
65
66
67
 *
 * NonbondedForce also lets you specify "exceptions", particular pairs of particles whose interactions should be
 * computed based on different parameters than those defined for the individual particles.  This can be used to
 * completely exclude certain interactions from the force calculation, or to alter how they interact with each other.
 *
 * Many molecular force fields omit Coulomb and Lennard-Jones interactions between particles separated by one
 * or two bonds, while using modified parameters for those separated by three bonds (known as "1-4 interactions").
 * This class provides a convenience method for this case called createExceptionsFromBonds().  You pass to it
 * a list of bonds and the scale factors to use for 1-4 interactions.  It identifies all pairs of particles which
 * are separated by 1, 2, or 3 bonds, then automatically creates exceptions for them.
68
69
70
71
72
73
 * 
 * When using a cutoff, by default Lennard-Jones interactions are sharply truncated at the cutoff distance.
 * Optionally you can instead use a switching function to make the interaction smoothly go to zero over a finite
 * distance range.  To enable this, call setUseSwitchingFunction().  You must also call setSwitchingDistance()
 * to specify the distance at which the interaction should begin to decrease.  The switching distance must be
 * less than the cutoff distance.
74
75
76
77
78
 * 
 * Another optional feature of this class (enabled by default) is to add a contribution to the energy which approximates
 * the effect of all Lennard-Jones interactions beyond the cutoff in a periodic system.  When running a simulation
 * at constant pressure, this can improve the quality of the result.  Call setUseDispersionCorrection() to set whether
 * this should be used.
79
80
 */

81
class OPENMM_EXPORT NonbondedForce : public Force {
82
public:
83
84
85
86
87
88
    /**
     * This is an enumeration of the different methods that may be used for handling long range nonbonded forces.
     */
    enum NonbondedMethod {
        /**
         * No cutoff is applied to nonbonded interactions.  The full set of N^2 interactions is computed exactly.
89
         * This necessarily means that periodic boundary conditions cannot be used.  This is the default.
90
91
92
93
         */
        NoCutoff = 0,
        /**
         * Interactions beyond the cutoff distance are ignored.  Coulomb interactions closer than the cutoff distance
94
         * are modified using the reaction field method.
95
96
97
         */
        CutoffNonPeriodic = 1,
        /**
Peter Eastman's avatar
Peter Eastman committed
98
99
         * Periodic boundary conditions are used, so that each particle interacts only with the nearest periodic copy of
         * each other particle.  Interactions beyond the cutoff distance are ignored.  Coulomb interactions closer than the
100
         * cutoff distance are modified using the reaction field method.
101
         */
102
103
        CutoffPeriodic = 2,
        /**
104
105
         * Periodic boundary conditions are used, and Ewald summation is used to compute the interaction of each particle
         * with all periodic copies of every other particle.
106
         */
107
108
109
110
111
112
        Ewald = 3,
        /**
         * Periodic boundary conditions are used, and Particle-Mesh Ewald (PME) summation is used to compute the interaction of each particle
         * with all periodic copies of every other particle.
         */
        PME = 4
113
    };
114
    /**
115
     * Create a NonbondedForce.
116
     */
117
    NonbondedForce();
118
    /**
119
     * Get the number of particles for which force field parameters have been defined.
120
     */
Peter Eastman's avatar
Peter Eastman committed
121
122
    int getNumParticles() const {
        return particles.size();
123
    }
124
    /**
125
     * Get the number of special interactions that should be calculated differently from other interactions.
126
     */
127
128
    int getNumExceptions() const {
        return exceptions.size();
129
    }
130
131
132
    /**
     * Get the method used for handling long range nonbonded interactions.
     */
133
    NonbondedMethod getNonbondedMethod() const;
134
135
136
137
138
139
    /**
     * Set the method used for handling long range nonbonded interactions.
     */
    void setNonbondedMethod(NonbondedMethod method);
    /**
     * Get the cutoff distance (in nm) being used for nonbonded interactions.  If the NonbondedMethod in use
140
     * is NoCutoff, this value will have no effect.
141
142
     *
     * @return the cutoff distance, measured in nm
143
     */
144
    double getCutoffDistance() const;
145
146
    /**
     * Set the cutoff distance (in nm) being used for nonbonded interactions.  If the NonbondedMethod in use
147
     * is NoCutoff, this value will have no effect.
148
149
     *
     * @param distance    the cutoff distance, measured in nm
150
151
     */
    void setCutoffDistance(double distance);
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    /**
     * Get whether a switching function is applied to the Lennard-Jones interaction.  If the nonbonded method is set
     * to NoCutoff, this option is ignored.
     */
    bool getUseSwitchingFunction() const;
    /**
     * Set whether a switching function is applied to the Lennard-Jones interaction.  If the nonbonded method is set
     * to NoCutoff, this option is ignored.
     */
    void setUseSwitchingFunction(bool use);
    /**
     * Get the distance at which the switching function begins to reduce the Lennard-Jones interaction.  This must be
     * less than the cutoff distance.
     */
    double getSwitchingDistance() const;
    /**
     * Set the distance at which the switching function begins to reduce the Lennard-Jones interaction.  This must be
     * less than the cutoff distance.
     */
    void setSwitchingDistance(double distance);
172
173
174
175
176
177
178
179
    /**
     * Get the dielectric constant to use for the solvent in the reaction field approximation.
     */
    double getReactionFieldDielectric() const;
    /**
     * Set the dielectric constant to use for the solvent in the reaction field approximation.
     */
    void setReactionFieldDielectric(double dielectric);
180
181
182
183
184
    /**
     * Get the error tolerance for Ewald summation.  This corresponds to the fractional error in the forces
     * which is acceptable.  This value is used to select the reciprocal space cutoff and separation
     * parameter so that the average error level will be less than the tolerance.  There is not a
     * rigorous guarantee that all forces on all atoms will be less than the tolerance, however.
185
186
187
     * 
     * For PME calculations, if setPMEParameters() is used to set alpha to something other than 0,
     * this value is ignored.
188
189
190
     */
    double getEwaldErrorTolerance() const;
    /**
191
     * Set the error tolerance for Ewald summation.  This corresponds to the fractional error in the forces
192
193
194
     * which is acceptable.  This value is used to select the reciprocal space cutoff and separation
     * parameter so that the average error level will be less than the tolerance.  There is not a
     * rigorous guarantee that all forces on all atoms will be less than the tolerance, however.
195
196
197
     * 
     * For PME calculations, if setPMEParameters() is used to set alpha to something other than 0,
     * this value is ignored.
198
199
     */
    void setEwaldErrorTolerance(double tol);
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    /**
     * Get the parameters to use for PME calculations.  If alpha is 0 (the default), these parameters are
     * ignored and instead their values are chosen based on the Ewald error tolerance.
     * 
     * @param alpha   the separation parameter
     * @param nx      the number of grid points along the X axis
     * @param ny      the number of grid points along the Y axis
     * @param nz      the number of grid points along the Z axis
     */
    void getPMEParameters(double& alpha, int& nx, int& ny, int& nz) const;
    /**
     * Set the parameters to use for PME calculations.  If alpha is 0 (the default), these parameters are
     * ignored and instead their values are chosen based on the Ewald error tolerance.
     * 
     * @param alpha   the separation parameter
     * @param nx      the number of grid points along the X axis
     * @param ny      the number of grid points along the Y axis
     * @param nz      the number of grid points along the Z axis
     */
    void setPMEParameters(double alpha, int nx, int ny, int nz);
220
221
222
223
    /**
     * Add the nonbonded force parameters for a particle.  This should be called once for each particle
     * in the System.  When it is called for the i'th time, it specifies the parameters for the i'th particle.
     * For calculating the Lennard-Jones interaction between two particles, the arithmetic mean of the sigmas
peastman's avatar
peastman committed
224
     * and the geometric mean of the epsilons for the two interacting particles is used (the Lorentz-Berthelot
225
226
227
228
229
     * combining rule).
     *
     * @param charge    the charge of the particle, measured in units of the proton charge
     * @param sigma     the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon   the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
230
     * @return the index of the particle that was added
231
     */
232
    int addParticle(double charge, double sigma, double epsilon);
233
    /**
Peter Eastman's avatar
Peter Eastman committed
234
     * Get the nonbonded force parameters for a particle.
235
     *
Peter Eastman's avatar
Peter Eastman committed
236
237
     * @param index     the index of the particle for which to get parameters
     * @param charge    the charge of the particle, measured in units of the proton charge
238
239
     * @param sigma     the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon   the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
240
     */
241
    void getParticleParameters(int index, double& charge, double& sigma, double& epsilon) const;
242
    /**
243
244
     * Set the nonbonded force parameters for a particle.  When calculating the Lennard-Jones interaction between two particles,
     * it uses the arithmetic mean of the sigmas and the geometric mean of the epsilons for the two interacting particles
peastman's avatar
peastman committed
245
     * (the Lorentz-Berthelot combining rule).
246
     *
Peter Eastman's avatar
Peter Eastman committed
247
248
     * @param index     the index of the particle for which to set parameters
     * @param charge    the charge of the particle, measured in units of the proton charge
249
250
     * @param sigma     the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon   the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
251
     */
252
    void setParticleParameters(int index, double charge, double sigma, double epsilon);
253
    /**
254
255
256
257
258
259
260
261
262
263
264
     * Add an interaction to the list of exceptions that should be calculated differently from other interactions.
     * If chargeProd and epsilon are both equal to 0, this will cause the interaction to be completely omitted from
     * force and energy calculations.
     *
     * In many cases, you can use createExceptionsFromBonds() rather than adding each exception explicitly.
     *
     * @param particle1  the index of the first particle involved in the interaction
     * @param particle2  the index of the second particle involved in the interaction
     * @param chargeProd the scaled product of the atomic charges (i.e. the strength of the Coulomb interaction), measured in units of the proton charge squared
     * @param sigma      the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon    the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
265
266
     * @param replace    determines the behavior if there is already an exception for the same two particles.  If true, the existing one is replaced.  If false,
     *                   an exception is thrown.
267
     * @return the index of the exception that was added
268
     */
269
    int addException(int particle1, int particle2, double chargeProd, double sigma, double epsilon, bool replace = false);
270
271
    /**
     * Get the force field parameters for an interaction that should be calculated differently from others.
272
     * 
273
274
275
276
     * @param index      the index of the interaction for which to get parameters
     * @param particle1  the index of the first particle involved in the interaction
     * @param particle2  the index of the second particle involved in the interaction
     * @param chargeProd the scaled product of the atomic charges (i.e. the strength of the Coulomb interaction), measured in units of the proton charge squared
277
278
     * @param sigma      the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon    the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
279
     */
280
    void getExceptionParameters(int index, int& particle1, int& particle2, double& chargeProd, double& sigma, double& epsilon) const;
281
    /**
282
283
284
     * Set the force field parameters for an interaction that should be calculated differently from others.
     * If chargeProd and epsilon are both equal to 0, this will cause the interaction to be completely omitted from
     * force and energy calculations.
285
     * 
286
287
288
289
     * @param index      the index of the interaction for which to get parameters
     * @param particle1  the index of the first particle involved in the interaction
     * @param particle2  the index of the second particle involved in the interaction
     * @param chargeProd the scaled product of the atomic charges (i.e. the strength of the Coulomb interaction), measured in units of the proton charge squared
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
     * @param sigma      the sigma parameter of the Lennard-Jones potential (corresponding to the van der Waals radius of the particle), measured in nm
     * @param epsilon    the epsilon parameter of the Lennard-Jones potential (corresponding to the well depth of the van der Waals interaction), measured in kJ/mol
     */
    void setExceptionParameters(int index, int particle1, int particle2, double chargeProd, double sigma, double epsilon);
    /**
     * Identify exceptions based on the molecular topology.  Particles which are separated by one or two bonds are set
     * to not interact at all, while pairs of particles separated by three bonds (known as "1-4 interactions") have
     * their Coulomb and Lennard-Jones interactions reduced by a fixed factor.
     *
     * @param bonds           the set of bonds based on which to construct exceptions.  Each element specifies the indices of
     *                        two particles that are bonded to each other.
     * @param coulomb14Scale  pairs of particles separated by three bonds will have the strength of their Coulomb interaction
     *                        multiplied by this factor
     * @param lj14Scale       pairs of particles separated by three bonds will have the strength of their Lennard-Jones interaction
     *                        multiplied by this factor
305
     */
306
    void createExceptionsFromBonds(const std::vector<std::pair<int, int> >& bonds, double coulomb14Scale, double lj14Scale);
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
    /**
     * Get whether to add a contribution to the energy that approximately represents the effect of Lennard-Jones
     * 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 Lennard-Jones
     * 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;
    }
325
326
327
328
    /**
     * Get the force group that reciprocal space interactions for Ewald or PME are included in.  This allows multiple
     * time step integrators to evaluate direct and reciprocal space interactions at different intervals: getForceGroup()
     * specifies the group for direct space, and getReciprocalSpaceForceGroup() specifies the group for reciprocal space.
329
     * If this is -1 (the default value), the same force group is used for reciprocal space as for direct space.
330
331
332
333
334
335
     */
    int getReciprocalSpaceForceGroup() const;
    /**
     * Set the force group that reciprocal space interactions for Ewald or PME are included in.  This allows multiple
     * time step integrators to evaluate direct and reciprocal space interactions at different intervals: setForceGroup()
     * specifies the group for direct space, and setReciprocalSpaceForceGroup() specifies the group for reciprocal space.
336
     * If this is -1 (the default value), the same force group is used for reciprocal space as for direct space.
337
     * 
338
339
     * @param group    the group index.  Legal values are between 0 and 31 (inclusive), or -1 to use the same force group
     *                 that is specified for direct space.
340
341
     */
    void setReciprocalSpaceForceGroup(int group);
342
343
344
345
346
347
348
349
350
351
352
353
354
    /**
     * Update the particle and exception parameters in a Context to match those stored in this Force object.  This method
     * provides an efficient method to update certain parameters in an existing Context without needing to reinitialize it.
     * Simply call setParticleParameters() and setExceptionParameters() to modify this object's parameters, then call
     * updateParametersInState() to copy them over to the Context.
     * 
     * This method has several limitations.  The only information it updates is the parameters of particles and exceptions.
     * All other aspects of the Force (the nonbonded method, the cutoff distance, etc.) are unaffected and can only be
     * changed by reinitializing the Context.  Furthermore, only the chargeProd, sigma, and epsilon values of an exception
     * can be changed; the pair of particles involved in the exception cannot change.  Finally, this method cannot be used
     * to add new particles or exceptions, only to change the parameters of existing ones.
     */
    void updateParametersInContext(Context& context);
355
protected:
356
    ForceImpl* createImpl() const;
357
private:
Peter Eastman's avatar
Peter Eastman committed
358
    class ParticleInfo;
359
    class ExceptionInfo;
360
    NonbondedMethod nonbondedMethod;
361
    double cutoffDistance, switchingDistance, rfDielectric, ewaldErrorTol, alpha;
362
    bool useSwitchingFunction, useDispersionCorrection;
363
    int recipForceGroup, nx, ny, nz;
364
    void addExclusionsToSet(const std::vector<std::set<int> >& bonded12, std::set<int>& exclusions, int baseParticle, int fromParticle, int currentLevel) const;
Peter Eastman's avatar
Peter Eastman committed
365
    std::vector<ParticleInfo> particles;
366
    std::vector<ExceptionInfo> exceptions;
367
    std::map<std::pair<int, int>, int> exceptionMap;
368
369
};

370
371
372
373
/**
 * This is an internal class used to record information about a particle.
 * @private
 */
Peter Eastman's avatar
Peter Eastman committed
374
class NonbondedForce::ParticleInfo {
375
public:
376
    double charge, sigma, epsilon;
Peter Eastman's avatar
Peter Eastman committed
377
    ParticleInfo() {
378
        charge = sigma = epsilon = 0.0;
379
    }
380
381
382
    ParticleInfo(double charge, double sigma, double epsilon) :
        charge(charge), sigma(sigma), epsilon(epsilon) {
    }
383
384
};

385
386
387
388
/**
 * This is an internal class used to record information about an exception.
 * @private
 */
389
class NonbondedForce::ExceptionInfo {
390
public:
Peter Eastman's avatar
Peter Eastman committed
391
    int particle1, particle2;
392
    double chargeProd, sigma, epsilon;
393
    ExceptionInfo() {
Peter Eastman's avatar
Peter Eastman committed
394
        particle1 = particle2 = -1;
395
        chargeProd = sigma = epsilon = 0.0;
396
    }
397
398
399
    ExceptionInfo(int particle1, int particle2, double chargeProd, double sigma, double epsilon) :
        particle1(particle1), particle2(particle2), chargeProd(chargeProd), sigma(sigma), epsilon(epsilon) {
    }
400
401
};

402
403
} // namespace OpenMM

404
#endif /*OPENMM_NONBONDEDFORCE_H_*/