View Javadoc
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.Pointer;
41  import com.sun.jna.ptr.DoubleByReference;
42  import com.sun.jna.ptr.IntByReference;
43  import com.sun.jna.ptr.PointerByReference;
44  
45  import java.nio.DoubleBuffer;
46  import java.nio.IntBuffer;
47  
48  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
49  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addComputedValue;
50  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addEnergyParameterDerivative;
51  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addExclusion;
52  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addFunction;
53  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addGlobalParameter;
54  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addInteractionGroup;
55  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addParticle;
56  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addPerParticleParameter;
57  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_addTabulatedFunction;
58  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_create;
59  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_createExclusionsFromBonds;
60  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_destroy;
61  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getComputedValueParameters;
62  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getCutoffDistance;
63  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getEnergyFunction;
64  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getEnergyParameterDerivativeName;
65  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getExclusionParticles;
66  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getFunctionParameters;
67  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getGlobalParameterDefaultValue;
68  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getGlobalParameterName;
69  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getInteractionGroupParameters;
70  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNonbondedMethod;
71  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumComputedValues;
72  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumEnergyParameterDerivatives;
73  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumExclusions;
74  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumFunctions;
75  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumGlobalParameters;
76  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumInteractionGroups;
77  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumParticles;
78  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumPerParticleParameters;
79  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getNumTabulatedFunctions;
80  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getParticleParameters;
81  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getPerParticleParameterName;
82  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getSwitchingDistance;
83  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getTabulatedFunction;
84  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getTabulatedFunctionName;
85  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getUseLongRangeCorrection;
86  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_getUseSwitchingFunction;
87  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setComputedValueParameters;
88  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setCutoffDistance;
89  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setEnergyFunction;
90  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setExclusionParticles;
91  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setFunctionParameters;
92  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setGlobalParameterDefaultValue;
93  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setGlobalParameterName;
94  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setInteractionGroupParameters;
95  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setNonbondedMethod;
96  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setParticleParameters;
97  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setPerParticleParameterName;
98  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setSwitchingDistance;
99  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setUseLongRangeCorrection;
100 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_setUseSwitchingFunction;
101 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_updateParametersInContext;
102 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomNonbondedForce_usesPeriodicBoundaryConditions;
103 
104 /**
105  * This class implements nonbonded interactions between particles.  Unlike NonbondedForce, the functional form
106  * of the interaction is completely customizable, and may involve arbitrary algebraic expressions and tabulated
107  * functions.  It may depend on the distance between particles, as well as on arbitrary global and
108  * per-particle parameters.  It also optionally supports periodic boundary conditions and cutoffs for long range interactions.
109  *
110  * <p>To use this class, create a CustomNonbondedForce object, passing an algebraic expression to the constructor
111  * that defines the interaction energy between each pair of particles.  The expression may depend on r, the distance
112  * between the particles, as well as on any parameters you choose.  Then call addPerParticleParameter() to define per-particle
113  * parameters, and addGlobalParameter() to define global parameters.  The values of per-particle parameters are specified as
114  * part of the system definition, while values of global parameters may be modified during a simulation by calling Context::setParameter().
115  *
116  * <p>Next, call addParticle() once for each particle in the System to set the values of its per-particle parameters.
117  * The number of particles for which you set parameters must be exactly equal to the number of particles in the
118  * System, or else an exception will be thrown when you try to create a Context.  After a particle has been added,
119  * you can modify its parameters by calling setParticleParameters().  This will have no effect on Contexts that already exist
120  * unless you call updateParametersInContext().
121  *
122  * <p>CustomNonbondedForce also lets you specify "exclusions", particular pairs of particles whose interactions should be
123  * omitted from force and energy calculations.  This is most often used for particles that are bonded to each other.
124  *
125  * <p>As an example, the following code creates a CustomNonbondedForce that implements a 12-6 Lennard-Jones potential:
126  *
127  * <pre>{@code
128  * CustomNonbondedForce force = new CustomNonbondedForce("4*epsilon*((sigma/r)^12-(sigma/r)^6); sigma=0.5*(sigma1+sigma2); epsilon=sqrt(epsilon1*epsilon2)");
129  * }</pre>
130  *
131  * <p>This force depends on two parameters: sigma and epsilon.  The following code defines these as per-particle parameters:
132  *
133  * <pre>{@code
134  * force.addPerParticleParameter("sigma");
135  * force.addPerParticleParameter("epsilon");
136  * }</pre>
137  *
138  * <p>The expression <i>must</i> be symmetric with respect to the two particles.  It typically will only be evaluated once
139  * for each pair of particles, and no guarantee is made about which particle will be identified as "particle 1".  In the
140  * above example, the energy only depends on the products sigma1*sigma2 and epsilon1*epsilon2, both of which are unchanged
141  * if the labels 1 and 2 are reversed.  In contrast, if it depended on the difference sigma1-sigma2, the results would
142  * be undefined, because reversing the labels 1 and 2 would change the energy.
143  *
144  * <p>The energy also may depend on "computed values".  These are similar to per-particle parameters, but instead of being
145  * specified in advance, their values are computed based on global and per-particle parameters.  For example, the following
146  * code uses a global parameter (lambda) to interpolate between two different sigma values for each particle (sigmaA and sigmaB).
147  *
148  * <pre>{@code
149  * CustomNonbondedForce force = new CustomNonbondedForce("4*epsilon*((sigma/r)^12-(sigma/r)^6); sigma=0.5*(sigma1+sigma2); epsilon=sqrt(epsilon1*epsilon2)");
150  * force.addComputedValue("sigma", "(1-lambda)*sigmaA + lambda*sigmaB");
151  * force.addGlobalParameter("lambda", 0);
152  * force.addPerParticleParameter("sigmaA");
153  * force.addPerParticleParameter("sigmaB");
154  * force.addPerParticleParameter("epsilon");
155  * }</pre>
156  *
157  * <p>You could, of course, embed the computation of sigma directly into the energy expression, but then it would need to be
158  * repeated for every interaction.  By separating it out as a computed value, it only needs to be computed once for each
159  * particle instead of once for each interaction, thus saving computation time.
160  *
161  * <p>CustomNonbondedForce can operate in two modes.  By default, it computes the interaction of every particle in the System
162  * with every other particle.  Alternatively, you can restrict it to only a subset of particle pairs.  To do this, specify
163  * one or more "interaction groups".  An interaction group consists of two sets of particles that should interact with
164  * each other.  Every particle in the first set interacts with every particle in the second set.  For example, you might use
165  * this feature to compute a solute-solvent interaction energy, while omitting all interactions between two solute atoms
166  * or two solvent atoms.
167  */
168 public class CustomNonbondedForce extends Force {
169 
170   /**
171    * Constructor.
172    *
173    * @param energy The energy expression for the force.
174    */
175   public CustomNonbondedForce(String energy) {
176     super(OpenMM_CustomNonbondedForce_create(energy));
177   }
178 
179   /**
180    * Add a computed value to the force.
181    *
182    * @param name       The name of the computed value.
183    * @param expression The expression for computing the value.
184    * @return The index of the computed value that was added.
185    */
186   public int addComputedValue(String name, String expression) {
187     return OpenMM_CustomNonbondedForce_addComputedValue(pointer, name, expression);
188   }
189 
190   /**
191    * Add an energy parameter derivative to the force.
192    *
193    * @param name The name of the parameter to compute the derivative of the energy with respect to.
194    */
195   public void addEnergyParameterDerivative(String name) {
196     OpenMM_CustomNonbondedForce_addEnergyParameterDerivative(pointer, name);
197   }
198 
199   /**
200    * Add an exclusion to the force.
201    *
202    * @param particle1 The index of the first particle in the exclusion.
203    * @param particle2 The index of the second particle in the exclusion.
204    * @return The index of the exclusion that was added.
205    */
206   public int addExclusion(int particle1, int particle2) {
207     return OpenMM_CustomNonbondedForce_addExclusion(pointer, particle1, particle2);
208   }
209 
210   /**
211    * Add a tabulated function that may appear in the energy expression.
212    *
213    * @param name     The name of the function as it appears in expressions.
214    * @param function A TabulatedFunction object defining the function.
215    * @param min      The minimum value of the independent variable for which the function is defined.
216    * @param max      The maximum value of the independent variable for which the function is defined.
217    * @return The index of the function that was added.
218    */
219   public int addFunction(String name, PointerByReference function, double min, double max) {
220     return OpenMM_CustomNonbondedForce_addFunction(pointer, name, function, min, max);
221   }
222 
223   /**
224    * Add a global parameter to the force.
225    *
226    * @param name  The name of the parameter.
227    * @param value The default value of the parameter.
228    * @return The index of the parameter that was added.
229    */
230   public int addGlobalParameter(String name, double value) {
231     return OpenMM_CustomNonbondedForce_addGlobalParameter(pointer, name, value);
232   }
233 
234   /**
235    * Add an interaction group to the force.
236    *
237    * @param group1 The set of particles in the first group.
238    * @param group2 The set of particles in the second group.
239    * @return The index of the interaction group that was added.
240    */
241   public int addInteractionGroup(IntSet group1, IntSet group2) {
242     return OpenMM_CustomNonbondedForce_addInteractionGroup(pointer, group1.getPointer(), group2.getPointer());
243   }
244 
245   /**
246    * Add a particle to the force.
247    *
248    * @param parameters The parameters for the new particle.
249    * @return The index of the particle that was added.
250    */
251   public int addParticle(DoubleArray parameters) {
252     return OpenMM_CustomNonbondedForce_addParticle(pointer, parameters.getPointer());
253   }
254 
255   /**
256    * Add a per-particle parameter to the force.
257    *
258    * @param name The name of the parameter.
259    * @return The index of the parameter that was added.
260    */
261   public int addPerParticleParameter(String name) {
262     return OpenMM_CustomNonbondedForce_addPerParticleParameter(pointer, name);
263   }
264 
265   /**
266    * Add a tabulated function that may appear in the energy expression.
267    *
268    * @param name     The name of the function as it appears in expressions.
269    * @param function A TabulatedFunction object defining the function.
270    * @return The index of the function that was added.
271    */
272   public int addTabulatedFunction(String name, PointerByReference function) {
273     return OpenMM_CustomNonbondedForce_addTabulatedFunction(pointer, name, function);
274   }
275 
276   /**
277    * Create exclusions based on the molecular topology.
278    *
279    * @param bonds      The bonds to use for determining exclusions.
280    * @param bondCutoff The number of bonds within which particles should be excluded.
281    */
282   public void createExclusionsFromBonds(BondArray bonds, int bondCutoff) {
283     OpenMM_CustomNonbondedForce_createExclusionsFromBonds(pointer, bonds.getPointer(), bondCutoff);
284   }
285 
286   /**
287    * Destroy the force.
288    */
289   @Override
290   public void destroy() {
291     if (pointer != null) {
292       OpenMM_CustomNonbondedForce_destroy(pointer);
293       pointer = null;
294     }
295   }
296 
297   /**
298    * Get the parameters for a computed value.
299    *
300    * @param index      The index of the computed value to get.
301    * @param name       The name of the computed value (output).
302    * @param expression The expression for computing the value (output).
303    */
304   public void getComputedValueParameters(int index, PointerByReference name, PointerByReference expression) {
305     OpenMM_CustomNonbondedForce_getComputedValueParameters(pointer, index, name, expression);
306   }
307 
308   /**
309    * Get the cutoff distance.
310    *
311    * @return The cutoff distance, measured in nm.
312    */
313   public double getCutoffDistance() {
314     return OpenMM_CustomNonbondedForce_getCutoffDistance(pointer);
315   }
316 
317   /**
318    * Get the energy expression for the force.
319    *
320    * @return The energy expression for the force.
321    */
322   public String getEnergyFunction() {
323     Pointer p = OpenMM_CustomNonbondedForce_getEnergyFunction(pointer);
324     if (p == null) {
325       return null;
326     }
327     return p.getString(0);
328   }
329 
330   /**
331    * Get the name of a parameter with respect to which the derivative of the energy should be computed.
332    *
333    * @param index The index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives().
334    * @return The parameter name.
335    */
336   public String getEnergyParameterDerivativeName(int index) {
337     Pointer p = OpenMM_CustomNonbondedForce_getEnergyParameterDerivativeName(pointer, index);
338     if (p == null) {
339       return null;
340     }
341     return p.getString(0);
342   }
343 
344   /**
345    * Get the particles in an exclusion.
346    *
347    * @param index     The index of the exclusion to get.
348    * @param particle1 The index of the first particle in the exclusion (output).
349    * @param particle2 The index of the second particle in the exclusion (output).
350    */
351   public void getExclusionParticles(int index, IntByReference particle1, IntByReference particle2) {
352     OpenMM_CustomNonbondedForce_getExclusionParticles(pointer, index, particle1, particle2);
353   }
354 
355   /**
356    * Get the particles in an exclusion.
357    *
358    * @param index     The index of the exclusion to get.
359    * @param particle1 The index of the first particle in the exclusion (output).
360    * @param particle2 The index of the second particle in the exclusion (output).
361    */
362   public void getExclusionParticles(int index, IntBuffer particle1, IntBuffer particle2) {
363     OpenMM_CustomNonbondedForce_getExclusionParticles(pointer, index, particle1, particle2);
364   }
365 
366   /**
367    * Get the parameters for a tabulated function.
368    *
369    * @param index    The index of the function to get.
370    * @param name     The name of the function as it appears in expressions (output).
371    * @param function A TabulatedFunction object defining the function (output).
372    * @param min      The minimum value of the independent variable for which the function is defined (output).
373    * @param max      The maximum value of the independent variable for which the function is defined (output).
374    */
375   public void getFunctionParameters(int index, PointerByReference name, PointerByReference function, DoubleByReference min, DoubleByReference max) {
376     OpenMM_CustomNonbondedForce_getFunctionParameters(pointer, index, name, function, min, max);
377   }
378 
379   /**
380    * Get the parameters for a tabulated function.
381    *
382    * @param index    The index of the function to get.
383    * @param name     The name of the function as it appears in expressions (output).
384    * @param function A TabulatedFunction object defining the function (output).
385    * @param min      The minimum value of the independent variable for which the function is defined (output).
386    * @param max      The maximum value of the independent variable for which the function is defined (output).
387    */
388   public void getFunctionParameters(int index, PointerByReference name, PointerByReference function, DoubleBuffer min, DoubleBuffer max) {
389     OpenMM_CustomNonbondedForce_getFunctionParameters(pointer, index, name, function, min, max);
390   }
391 
392   /**
393    * Get the default value of a global parameter.
394    *
395    * @param index The index of the parameter to get.
396    * @return The default value of the parameter.
397    */
398   public double getGlobalParameterDefaultValue(int index) {
399     return OpenMM_CustomNonbondedForce_getGlobalParameterDefaultValue(pointer, index);
400   }
401 
402   /**
403    * Get the name of a global parameter.
404    *
405    * @param index The index of the parameter to get.
406    * @return The name of the parameter.
407    */
408   public String getGlobalParameterName(int index) {
409     Pointer p = OpenMM_CustomNonbondedForce_getGlobalParameterName(pointer, index);
410     if (p == null) {
411       return null;
412     }
413     return p.getString(0);
414   }
415 
416   /**
417    * Get the parameters for an interaction group.
418    *
419    * @param index  The index of the interaction group to get.
420    * @param group1 The set of particles in the first group (output).
421    * @param group2 The set of particles in the second group (output).
422    */
423   public void getInteractionGroupParameters(int index, PointerByReference group1, PointerByReference group2) {
424     OpenMM_CustomNonbondedForce_getInteractionGroupParameters(pointer, index, group1, group2);
425   }
426 
427   /**
428    * Get the nonbonded method.
429    *
430    * @return The nonbonded method.
431    */
432   public int getNonbondedMethod() {
433     return OpenMM_CustomNonbondedForce_getNonbondedMethod(pointer);
434   }
435 
436   /**
437    * Get the number of computed values.
438    *
439    * @return The number of computed values.
440    */
441   public int getNumComputedValues() {
442     return OpenMM_CustomNonbondedForce_getNumComputedValues(pointer);
443   }
444 
445   /**
446    * Get the number of parameters with respect to which the derivative of the energy should be computed.
447    *
448    * @return The number of parameters.
449    */
450   public int getNumEnergyParameterDerivatives() {
451     return OpenMM_CustomNonbondedForce_getNumEnergyParameterDerivatives(pointer);
452   }
453 
454   /**
455    * Get the number of exclusions.
456    *
457    * @return The number of exclusions.
458    */
459   public int getNumExclusions() {
460     return OpenMM_CustomNonbondedForce_getNumExclusions(pointer);
461   }
462 
463   /**
464    * Get the number of tabulated functions.
465    *
466    * @return The number of tabulated functions.
467    * @deprecated This method exists only for backward compatibility. Use getNumTabulatedFunctions() instead.
468    */
469   @Deprecated
470   public int getNumFunctions() {
471     return OpenMM_CustomNonbondedForce_getNumFunctions(pointer);
472   }
473 
474   /**
475    * Get the number of global parameters.
476    *
477    * @return The number of global parameters.
478    */
479   public int getNumGlobalParameters() {
480     return OpenMM_CustomNonbondedForce_getNumGlobalParameters(pointer);
481   }
482 
483   /**
484    * Get the number of interaction groups.
485    *
486    * @return The number of interaction groups.
487    */
488   public int getNumInteractionGroups() {
489     return OpenMM_CustomNonbondedForce_getNumInteractionGroups(pointer);
490   }
491 
492   /**
493    * Get the number of particles.
494    *
495    * @return The number of particles.
496    */
497   public int getNumParticles() {
498     return OpenMM_CustomNonbondedForce_getNumParticles(pointer);
499   }
500 
501   /**
502    * Get the number of per-particle parameters.
503    *
504    * @return The number of per-particle parameters.
505    */
506   public int getNumPerParticleParameters() {
507     return OpenMM_CustomNonbondedForce_getNumPerParticleParameters(pointer);
508   }
509 
510   /**
511    * Get the number of tabulated functions.
512    *
513    * @return The number of tabulated functions.
514    */
515   public int getNumTabulatedFunctions() {
516     return OpenMM_CustomNonbondedForce_getNumTabulatedFunctions(pointer);
517   }
518 
519   /**
520    * Get the parameters for a particle.
521    *
522    * @param index      The index of the particle to get.
523    * @param parameters The parameters for the particle (output).
524    */
525   public void getParticleParameters(int index, PointerByReference parameters) {
526     OpenMM_CustomNonbondedForce_getParticleParameters(pointer, index, parameters);
527   }
528 
529   /**
530    * Get the name of a per-particle parameter.
531    *
532    * @param index The index of the parameter to get.
533    * @return The name of the parameter.
534    */
535   public String getPerParticleParameterName(int index) {
536     Pointer p = OpenMM_CustomNonbondedForce_getPerParticleParameterName(pointer, index);
537     if (p == null) {
538       return null;
539     }
540     return p.getString(0);
541   }
542 
543   /**
544    * Get the switching distance.
545    *
546    * @return The switching distance, measured in nm.
547    */
548   public double getSwitchingDistance() {
549     return OpenMM_CustomNonbondedForce_getSwitchingDistance(pointer);
550   }
551 
552   /**
553    * Get a reference to a tabulated function that may appear in the energy expression.
554    *
555    * @param index The index of the function to get.
556    * @return The TabulatedFunction object defining the function.
557    */
558   public PointerByReference getTabulatedFunction(int index) {
559     return OpenMM_CustomNonbondedForce_getTabulatedFunction(pointer, index);
560   }
561 
562   /**
563    * Get the name of a tabulated function that may appear in the energy expression.
564    *
565    * @param index The index of the function to get.
566    * @return The name of the function as it appears in expressions.
567    */
568   public String getTabulatedFunctionName(int index) {
569     Pointer p = OpenMM_CustomNonbondedForce_getTabulatedFunctionName(pointer, index);
570     if (p == null) {
571       return null;
572     }
573     return p.getString(0);
574   }
575 
576   /**
577    * Get whether to use the long range correction.
578    *
579    * @return 1 if the long range correction is used, 0 otherwise.
580    */
581   public int getUseLongRangeCorrection() {
582     return OpenMM_CustomNonbondedForce_getUseLongRangeCorrection(pointer);
583   }
584 
585   /**
586    * Get whether to use a switching function.
587    *
588    * @return 1 if a switching function is used, 0 otherwise.
589    */
590   public int getUseSwitchingFunction() {
591     return OpenMM_CustomNonbondedForce_getUseSwitchingFunction(pointer);
592   }
593 
594   /**
595    * Set the parameters for a computed value.
596    *
597    * @param index      The index of the computed value to set.
598    * @param name       The name of the computed value.
599    * @param expression The expression for computing the value.
600    */
601   public void setComputedValueParameters(int index, String name, String expression) {
602     OpenMM_CustomNonbondedForce_setComputedValueParameters(pointer, index, name, expression);
603   }
604 
605   /**
606    * Set the cutoff distance.
607    *
608    * @param distance The cutoff distance, measured in nm.
609    */
610   public void setCutoffDistance(double distance) {
611     OpenMM_CustomNonbondedForce_setCutoffDistance(pointer, distance);
612   }
613 
614   /**
615    * Set the energy expression for the force.
616    *
617    * @param expression The energy expression for the force.
618    */
619   public void setEnergyFunction(String expression) {
620     OpenMM_CustomNonbondedForce_setEnergyFunction(pointer, expression);
621   }
622 
623   /**
624    * Set the particles in an exclusion.
625    *
626    * @param index     The index of the exclusion to set.
627    * @param particle1 The index of the first particle in the exclusion.
628    * @param particle2 The index of the second particle in the exclusion.
629    */
630   public void setExclusionParticles(int index, int particle1, int particle2) {
631     OpenMM_CustomNonbondedForce_setExclusionParticles(pointer, index, particle1, particle2);
632   }
633 
634   /**
635    * Set the parameters for a tabulated function.
636    *
637    * @param index    The index of the function to set.
638    * @param name     The name of the function as it appears in expressions.
639    * @param function A TabulatedFunction object defining the function.
640    * @param min      The minimum value of the independent variable for which the function is defined.
641    * @param max      The maximum value of the independent variable for which the function is defined.
642    */
643   public void setFunctionParameters(int index, String name, PointerByReference function, double min, double max) {
644     OpenMM_CustomNonbondedForce_setFunctionParameters(pointer, index, name, function, min, max);
645   }
646 
647   /**
648    * Set the default value of a global parameter.
649    *
650    * @param index The index of the parameter to set.
651    * @param value The default value of the parameter.
652    */
653   public void setGlobalParameterDefaultValue(int index, double value) {
654     OpenMM_CustomNonbondedForce_setGlobalParameterDefaultValue(pointer, index, value);
655   }
656 
657   /**
658    * Set the name of a global parameter.
659    *
660    * @param index The index of the parameter to set.
661    * @param name  The name of the parameter.
662    */
663   public void setGlobalParameterName(int index, String name) {
664     OpenMM_CustomNonbondedForce_setGlobalParameterName(pointer, index, name);
665   }
666 
667   /**
668    * Set the parameters for an interaction group.
669    *
670    * @param index  The index of the interaction group to set.
671    * @param group1 The set of particles in the first group.
672    * @param group2 The set of particles in the second group.
673    */
674   public void setInteractionGroupParameters(int index, PointerByReference group1, PointerByReference group2) {
675     OpenMM_CustomNonbondedForce_setInteractionGroupParameters(pointer, index, group1, group2);
676   }
677 
678   /**
679    * Set the nonbonded method.
680    *
681    * @param method The nonbonded method.
682    */
683   public void setNonbondedMethod(int method) {
684     OpenMM_CustomNonbondedForce_setNonbondedMethod(pointer, method);
685   }
686 
687   /**
688    * Set the parameters for a particle.
689    *
690    * @param index      The index of the particle to set.
691    * @param parameters The parameters for the particle.
692    */
693   public void setParticleParameters(int index, PointerByReference parameters) {
694     OpenMM_CustomNonbondedForce_setParticleParameters(pointer, index, parameters);
695   }
696 
697   /**
698    * Set the name of a per-particle parameter.
699    *
700    * @param index The index of the parameter to set.
701    * @param name  The name of the parameter.
702    */
703   public void setPerParticleParameterName(int index, String name) {
704     OpenMM_CustomNonbondedForce_setPerParticleParameterName(pointer, index, name);
705   }
706 
707   /**
708    * Set the switching distance.
709    *
710    * @param distance The switching distance, measured in nm.
711    */
712   public void setSwitchingDistance(double distance) {
713     OpenMM_CustomNonbondedForce_setSwitchingDistance(pointer, distance);
714   }
715 
716   /**
717    * Set whether to use the long range correction.
718    *
719    * @param use 1 to use the long range correction, 0 otherwise.
720    */
721   public void setUseLongRangeCorrection(int use) {
722     OpenMM_CustomNonbondedForce_setUseLongRangeCorrection(pointer, use);
723   }
724 
725   /**
726    * Set whether to use a switching function.
727    *
728    * @param use 1 to use a switching function, 0 otherwise.
729    */
730   public void setUseSwitchingFunction(int use) {
731     OpenMM_CustomNonbondedForce_setUseSwitchingFunction(pointer, use);
732   }
733 
734   /**
735    * Update the per-particle parameters and tabulated functions in a Context to match those stored in this Force object.
736    *
737    * @param context The Context in which to update the parameters.
738    */
739   public void updateParametersInContext(Context context) {
740     if (context.hasContextPointer()) {
741       OpenMM_CustomNonbondedForce_updateParametersInContext(pointer, context.getPointer());
742     }
743   }
744 
745   /**
746    * Check if the force uses periodic boundary conditions.
747    *
748    * @return True if the force uses periodic boundary conditions.
749    */
750   @Override
751   public boolean usesPeriodicBoundaryConditions() {
752     int pbc = OpenMM_CustomNonbondedForce_usesPeriodicBoundaryConditions(pointer);
753     return pbc == OpenMM_True;
754   }
755 }