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_CustomGBForce_addComputedValue;
50  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addEnergyParameterDerivative;
51  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addEnergyTerm;
52  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addExclusion;
53  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addFunction;
54  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addGlobalParameter;
55  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addParticle;
56  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addPerParticleParameter;
57  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_addTabulatedFunction;
58  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_create;
59  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_destroy;
60  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getComputedValueParameters;
61  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getCutoffDistance;
62  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getEnergyParameterDerivativeName;
63  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getEnergyTermParameters;
64  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getExclusionParticles;
65  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getFunctionParameters;
66  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getGlobalParameterDefaultValue;
67  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getGlobalParameterName;
68  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNonbondedMethod;
69  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumComputedValues;
70  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumEnergyParameterDerivatives;
71  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumEnergyTerms;
72  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumExclusions;
73  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumFunctions;
74  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumGlobalParameters;
75  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumParticles;
76  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumPerParticleParameters;
77  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getNumTabulatedFunctions;
78  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getParticleParameters;
79  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getPerParticleParameterName;
80  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getTabulatedFunction;
81  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_getTabulatedFunctionName;
82  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setComputedValueParameters;
83  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setCutoffDistance;
84  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setEnergyTermParameters;
85  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setExclusionParticles;
86  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setFunctionParameters;
87  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setGlobalParameterDefaultValue;
88  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setGlobalParameterName;
89  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setNonbondedMethod;
90  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setParticleParameters;
91  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_setPerParticleParameterName;
92  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_updateParametersInContext;
93  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomGBForce_usesPeriodicBoundaryConditions;
94  
95  /**
96   * This class implements complex, multiple stage nonbonded interactions between particles.  It is designed primarily
97   * for implementing Generalized Born implicit solvation models, although it is not strictly limited to that purpose.
98   * The interaction is specified as a series of computations, each defined by an arbitrary algebraic expression.
99   * It also allows tabulated functions to be defined and used with the computations.  It optionally supports periodic boundary
100  * conditions and cutoffs for long range interactions.
101  * <p>
102  * The computation consists of calculating some number of per-particle <b>computed values</b>, followed by one or more
103  * <b>energy terms</b>.  A computed value is a scalar value that is computed for each particle in the system.  It may
104  * depend on an arbitrary set of global and per-particle parameters, and well as on other computed values that have
105  * been calculated before it.  Once all computed values have been calculated, the energy terms and their derivatives
106  * are evaluated to determine the system energy and particle forces.  The energy terms may depend on global parameters,
107  * per-particle parameters, and per-particle computed values.
108  * <p>
109  * When specifying a computed value or energy term, you provide an algebraic expression to evaluate and a <b>computation type</b>
110  * describing how the expression is to be evaluated.  There are two main types of computations:
111  * <ul>
112  * <li><b>Single Particle</b>: The expression is evaluated once for each particle in the System.  In the case of a computed
113  * value, this means the value for a particle depends only on other properties of that particle (its position, parameters, and other
114  * computed values).  In the case of an energy term, it means each particle makes an independent contribution to the System
115  * energy.</li>
116  * <li><b>Particle Pairs</b>: The expression is evaluated for every pair of particles in the system.  In the case of a computed
117  * value, the value for a particular particle is calculated by pairing it with every other particle in the system, evaluating
118  * the expression for each pair, and summing them.  For an energy term, each particle pair makes an independent contribution to
119  * the System energy.  (Note that energy terms are assumed to be symmetric with respect to the two interacting particles, and
120  * therefore are evaluated only once per pair.  In contrast, expressions for computed values need not be symmetric and therefore are calculated
121  * twice for each pair: once when calculating the value for the first particle, and again when calculating the value for the
122  * second particle.)</li>
123  * </ul>
124  * <p>
125  * Be aware that, although this class is extremely general in the computations it can define, particular Platforms may only support
126  * more restricted types of computations.  In particular, all currently existing Platforms require that the first computed value
127  * <i>must</i> be a particle pair computation, and all computed values after the first <i>must</i> be single particle computations.
128  * This is sufficient for most Generalized Born models, but might not permit some other types of calculations to be implemented.
129  * <p>
130  * This is a complicated class to use, and an example may help to clarify it.  The following code implements the OBC variant
131  * of the GB/SA solvation model, using the ACE approximation to estimate surface area:
132  * <pre>
133  *   {@code
134  *    CustomGBForce* custom = new CustomGBForce();
135  *    custom->addPerParticleParameter("q");
136  *    custom->addPerParticleParameter("radius");
137  *    custom->addPerParticleParameter("scale");
138  *    custom->addGlobalParameter("solventDielectric", obc->getSolventDielectric());
139  *    custom->addGlobalParameter("soluteDielectric", obc->getSoluteDielectric());
140  *    custom->addComputedValue("I", "step(r+sr2-or1)*0.5*(1/L-1/U+0.25*(1/U^2-1/L^2)*(r-sr2*sr2/r)+0.5*log(L/U)/r+C);"
141  *                                  "U=r+sr2;"
142  *                                  "C=2*(1/or1-1/L)*step(sr2-r-or1);"
143  *                                  "L=max(or1, D);"
144  *                                  "D=abs(r-sr2);"
145  *                                  "sr2 = scale2*or2;"
146  *                                  "or1 = radius1-0.009; or2 = radius2-0.009", CustomGBForce::ParticlePairNoExclusions);
147  *    custom->addComputedValue("B", "1/(1/or-tanh(1*psi-0.8*psi^2+4.85*psi^3)/radius);"
148  *                                  "psi=I*or; or=radius-0.009", CustomGBForce::SingleParticle);
149  *    custom->addEnergyTerm("28.3919551*(radius+0.14)^2*(radius/B)^6-0.5*138.935456*(1/soluteDielectric-1/solventDielectric)*q^2/B",
150  *                          CustomGBForce::SingleParticle);
151  *    custom->addEnergyTerm("-138.935456*(1/soluteDielectric-1/solventDielectric)*q1*q2/f;"
152  *                          "f=sqrt(r^2+B1*B2*exp(-r^2/(4*B1*B2)))", CustomGBForce::ParticlePair);
153  *   }
154  * </pre>
155  * <p>
156  * It begins by defining three per-particle parameters (charge, atomic radius, and scale factor) and two global parameters
157  * (the dielectric constants for the solute and solvent).  It then defines a computed value "I" of type ParticlePair.  The
158  * expression for evaluating it is a complicated function of the distance between each pair of particles (r), their atomic
159  * radii (radius1 and radius2), and their scale factors (scale1 and scale2).  Very roughly speaking, it is a measure of the
160  * distance between each particle and other nearby particles.
161  * <p>
162  * Next a computation is defined for the Born Radius (B).  It is computed independently for each particle, and is a function of
163  * that particle's atomic radius and the intermediate value I defined above.
164  * <p>
165  * Finally, two energy terms are defined.  The first one is computed for each particle and represents the surface area term,
166  * as well as the self interaction part of the polarization energy.  The second term is calculated for each pair of particles,
167  * and represents the screening of electrostatic interactions by the solvent.
168  * <p>
169  * After defining the force as shown above, you should then call addParticle() once for each particle in the System to set the
170  * values of its per-particle parameters (q, radius, and scale).  The number of particles for which you set parameters must be
171  * exactly equal to the number of particles in the System, or else an exception will be thrown when you try to create a Context.
172  * After a particle has been added, you can modify its parameters by calling setParticleParameters().  This will have no effect
173  * on Contexts that already exist unless you call updateParametersInContext().
174  * <p>
175  * CustomGBForce also lets you specify "exclusions", particular pairs of particles whose interactions should be
176  * omitted from calculations.  This is most often used for particles that are bonded to each other.  Even if you specify exclusions,
177  * however, you can use the computation type ParticlePairNoExclusions to indicate that exclusions should not be applied to a
178  * particular piece of the computation.
179  * <p>
180  * This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
181  * Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
182  * computed.  You can then query its value in a Context by calling getState() on it.
183  * <p>
184  * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and &circ; (power), and the following
185  * functions: sqrt, exp, log, sin, cos, sec, csc, tan, cot, asin, acos, atan, atan2, sinh, cosh, tanh, erf, erfc, min, max, abs, floor, ceil, step, delta, select.  All trigonometric functions
186  * are defined in radians, and log is the natural logarithm.  step(x) = 0 if x is less than 0, 1 otherwise.  delta(x) = 1 if x is 0, 0 otherwise.
187  * select(x,y,z) = z if x = 0, y otherwise.  In expressions for particle pair calculations, the names of per-particle parameters and computed values
188  * have the suffix "1" or "2" appended to them to indicate the values for the two interacting particles.  As seen in the above example,
189  * an expression may also involve intermediate quantities that are defined following the main expression, using ";" as a separator.
190  * <p>
191  * In addition, you can call addTabulatedFunction() to define a new function based on tabulated values.  You specify the function by
192  * creating a TabulatedFunction object.  That function can then appear in expressions.
193  */
194 public class CustomGBForce extends Force {
195 
196   /**
197    * Create a CustomGBForce.
198    */
199   public CustomGBForce() {
200     super(OpenMM_CustomGBForce_create());
201   }
202 
203   /**
204    * Add a computed value to the force.
205    *
206    * @param name       The name of the computed value.
207    * @param expression The expression for computing the value.
208    * @param type       The type of computation to perform.
209    * @return The index of the computed value that was added.
210    */
211   public int addComputedValue(String name, String expression, int type) {
212     return OpenMM_CustomGBForce_addComputedValue(pointer, name, expression, type);
213   }
214 
215   /**
216    * Add an energy parameter derivative to the force.
217    *
218    * @param name The name of the parameter to compute the derivative of the energy with respect to.
219    */
220   public void addEnergyParameterDerivative(String name) {
221     OpenMM_CustomGBForce_addEnergyParameterDerivative(pointer, name);
222   }
223 
224   /**
225    * Add an energy term to the force.
226    *
227    * @param expression The expression for computing the energy term.
228    * @param type       The type of computation to perform.
229    * @return The index of the energy term that was added.
230    */
231   public int addEnergyTerm(String expression, int type) {
232     return OpenMM_CustomGBForce_addEnergyTerm(pointer, expression, type);
233   }
234 
235   /**
236    * Add an exclusion to the force.
237    *
238    * @param particle1 The index of the first particle in the exclusion.
239    * @param particle2 The index of the second particle in the exclusion.
240    * @return The index of the exclusion that was added.
241    */
242   public int addExclusion(int particle1, int particle2) {
243     return OpenMM_CustomGBForce_addExclusion(pointer, particle1, particle2);
244   }
245 
246   /**
247    * Add a tabulated function that may appear in the energy expression.
248    *
249    * @param name   The name of the function as it appears in expressions.
250    * @param values The tabulated values of the function.
251    * @param min    The minimum value of the independent variable for which the function is defined.
252    * @param max    The maximum value of the independent variable for which the function is defined.
253    * @return The index of the function that was added.
254    * @deprecated This method exists only for backward compatibility. Use addTabulatedFunction() instead.
255    */
256   @Deprecated
257   public int addFunction(String name, PointerByReference values, double min, double max) {
258     return OpenMM_CustomGBForce_addFunction(pointer, name, values, min, max);
259   }
260 
261   /**
262    * Add a global parameter to the force.
263    *
264    * @param name         The name of the parameter.
265    * @param defaultValue The default value of the parameter.
266    * @return The index of the parameter that was added.
267    */
268   public int addGlobalParameter(String name, double defaultValue) {
269     return OpenMM_CustomGBForce_addGlobalParameter(pointer, name, defaultValue);
270   }
271 
272   /**
273    * Add a particle to the force.
274    *
275    * @param particleParameters The parameters for the particle.
276    * @return The index of the particle that was added.
277    */
278   public int addParticle(DoubleArray particleParameters) {
279     return OpenMM_CustomGBForce_addParticle(pointer, particleParameters.getPointer());
280   }
281 
282   /**
283    * Add a per-particle parameter to the force.
284    *
285    * @param name The name of the parameter.
286    * @return The index of the parameter that was added.
287    */
288   public int addPerParticleParameter(String name) {
289     return OpenMM_CustomGBForce_addPerParticleParameter(pointer, name);
290   }
291 
292   /**
293    * Add a tabulated function that may appear in the energy expression.
294    *
295    * @param name     The name of the function as it appears in expressions.
296    * @param function A TabulatedFunction object defining the function.
297    * @return The index of the function that was added.
298    */
299   public int addTabulatedFunction(String name, PointerByReference function) {
300     return OpenMM_CustomGBForce_addTabulatedFunction(pointer, name, function);
301   }
302 
303   /**
304    * Destroy the force.
305    */
306   @Override
307   public void destroy() {
308     if (pointer != null) {
309       OpenMM_CustomGBForce_destroy(pointer);
310       pointer = null;
311     }
312   }
313 
314   /**
315    * Get the parameters for a computed value.
316    *
317    * @param index      The index of the computed value.
318    * @param name       The name of the computed value (output).
319    * @param expression The expression for computing the value (output).
320    * @param type       The type of computation to perform (output).
321    */
322   public void getComputedValueParameters(int index, PointerByReference name, PointerByReference expression, IntBuffer type) {
323     OpenMM_CustomGBForce_getComputedValueParameters(pointer, index, name, expression, type);
324   }
325 
326   /**
327    * Get the parameters for a computed value.
328    *
329    * @param index      The index of the computed value.
330    * @param name       The name of the computed value (output).
331    * @param expression The expression for computing the value (output).
332    * @param type       The type of computation to perform (output).
333    */
334   public void getComputedValueParameters(int index, PointerByReference name, PointerByReference expression, IntByReference type) {
335     OpenMM_CustomGBForce_getComputedValueParameters(pointer, index, name, expression, type);
336   }
337 
338   /**
339    * Get the cutoff distance.
340    *
341    * @return The cutoff distance.
342    */
343   public double getCutoffDistance() {
344     return OpenMM_CustomGBForce_getCutoffDistance(pointer);
345   }
346 
347   /**
348    * Get the name of a parameter with respect to which the derivative of the energy should be computed.
349    *
350    * @param index The index of the parameter derivative.
351    * @return The name of the parameter.
352    */
353   public String getEnergyParameterDerivativeName(int index) {
354     Pointer p = OpenMM_CustomGBForce_getEnergyParameterDerivativeName(pointer, index);
355     if (p == null) {
356       return null;
357     }
358     return p.getString(0);
359   }
360 
361   /**
362    * Get the parameters for an energy term.
363    *
364    * @param index      The index of the energy term.
365    * @param expression The expression for computing the energy term (output).
366    * @param type       The type of computation to perform (output).
367    */
368   public void getEnergyTermParameters(int index, PointerByReference expression, IntBuffer type) {
369     OpenMM_CustomGBForce_getEnergyTermParameters(pointer, index, expression, type);
370   }
371 
372   /**
373    * Get the parameters for an energy term.
374    *
375    * @param index      The index of the energy term.
376    * @param expression The expression for computing the energy term (output).
377    * @param type       The type of computation to perform (output).
378    */
379   public void getEnergyTermParameters(int index, PointerByReference expression, IntByReference type) {
380     OpenMM_CustomGBForce_getEnergyTermParameters(pointer, index, expression, type);
381   }
382 
383   /**
384    * Get the particles in an exclusion.
385    *
386    * @param index     The index of the exclusion.
387    * @param particle1 The index of the first particle in the exclusion (output).
388    * @param particle2 The index of the second particle in the exclusion (output).
389    */
390   public void getExclusionParticles(int index, IntBuffer particle1, IntBuffer particle2) {
391     OpenMM_CustomGBForce_getExclusionParticles(pointer, index, particle1, particle2);
392   }
393 
394   /**
395    * Get the particles in an exclusion.
396    *
397    * @param index     The index of the exclusion.
398    * @param particle1 The index of the first particle in the exclusion (output).
399    * @param particle2 The index of the second particle in the exclusion (output).
400    */
401   public void getExclusionParticles(int index, IntByReference particle1, IntByReference particle2) {
402     OpenMM_CustomGBForce_getExclusionParticles(pointer, index, particle1, particle2);
403   }
404 
405   /**
406    * Get the parameters for a tabulated function.
407    *
408    * @param index  The index of the function.
409    * @param name   The name of the function (output).
410    * @param values The tabulated values of the function (output).
411    * @param min    The minimum value of the independent variable for which the function is defined (output).
412    * @param max    The maximum value of the independent variable for which the function is defined (output).
413    */
414   public void getFunctionParameters(int index, PointerByReference name, PointerByReference values, DoubleBuffer min, DoubleBuffer max) {
415     OpenMM_CustomGBForce_getFunctionParameters(pointer, index, name, values, min, max);
416   }
417 
418   /**
419    * Get the parameters for a tabulated function.
420    *
421    * @param index  The index of the function.
422    * @param name   The name of the function (output).
423    * @param values The tabulated values of the function (output).
424    * @param min    The minimum value of the independent variable for which the function is defined (output).
425    * @param max    The maximum value of the independent variable for which the function is defined (output).
426    */
427   public void getFunctionParameters(int index, PointerByReference name, PointerByReference values, DoubleByReference min, DoubleByReference max) {
428     OpenMM_CustomGBForce_getFunctionParameters(pointer, index, name, values, min, max);
429   }
430 
431   /**
432    * Get the default value of a global parameter.
433    *
434    * @param index The index of the parameter.
435    * @return The default value of the parameter.
436    */
437   public double getGlobalParameterDefaultValue(int index) {
438     return OpenMM_CustomGBForce_getGlobalParameterDefaultValue(pointer, index);
439   }
440 
441   /**
442    * Get the name of a global parameter.
443    *
444    * @param index The index of the parameter.
445    * @return The name of the parameter.
446    */
447   public String getGlobalParameterName(int index) {
448     Pointer p = OpenMM_CustomGBForce_getGlobalParameterName(pointer, index);
449     if (p == null) {
450       return null;
451     }
452     return p.getString(0);
453   }
454 
455   /**
456    * Get the nonbonded method.
457    *
458    * @return The nonbonded method.
459    */
460   public int getNonbondedMethod() {
461     return OpenMM_CustomGBForce_getNonbondedMethod(pointer);
462   }
463 
464   /**
465    * Get the number of computed values.
466    *
467    * @return The number of computed values.
468    */
469   public int getNumComputedValues() {
470     return OpenMM_CustomGBForce_getNumComputedValues(pointer);
471   }
472 
473   /**
474    * Get the number of parameters with respect to which the derivative of the energy should be computed.
475    *
476    * @return The number of parameters.
477    */
478   public int getNumEnergyParameterDerivatives() {
479     return OpenMM_CustomGBForce_getNumEnergyParameterDerivatives(pointer);
480   }
481 
482   /**
483    * Get the number of energy terms.
484    *
485    * @return The number of energy terms.
486    */
487   public int getNumEnergyTerms() {
488     return OpenMM_CustomGBForce_getNumEnergyTerms(pointer);
489   }
490 
491   /**
492    * Get the number of exclusions.
493    *
494    * @return The number of exclusions.
495    */
496   public int getNumExclusions() {
497     return OpenMM_CustomGBForce_getNumExclusions(pointer);
498   }
499 
500   /**
501    * Get the number of tabulated functions.
502    *
503    * @return The number of tabulated functions.
504    * @deprecated This method exists only for backward compatibility. Use getNumTabulatedFunctions() instead.
505    */
506   @Deprecated
507   public int getNumFunctions() {
508     return OpenMM_CustomGBForce_getNumFunctions(pointer);
509   }
510 
511   /**
512    * Get the number of global parameters.
513    *
514    * @return The number of global parameters.
515    */
516   public int getNumGlobalParameters() {
517     return OpenMM_CustomGBForce_getNumGlobalParameters(pointer);
518   }
519 
520   /**
521    * Get the number of particles.
522    *
523    * @return The number of particles.
524    */
525   public int getNumParticles() {
526     return OpenMM_CustomGBForce_getNumParticles(pointer);
527   }
528 
529   /**
530    * Get the number of per-particle parameters.
531    *
532    * @return The number of per-particle parameters.
533    */
534   public int getNumPerParticleParameters() {
535     return OpenMM_CustomGBForce_getNumPerParticleParameters(pointer);
536   }
537 
538   /**
539    * Get the number of tabulated functions.
540    *
541    * @return The number of tabulated functions.
542    */
543   public int getNumTabulatedFunctions() {
544     return OpenMM_CustomGBForce_getNumTabulatedFunctions(pointer);
545   }
546 
547   /**
548    * Get the parameters for a particle.
549    *
550    * @param index              The index of the particle.
551    * @param particleParameters The parameters for the particle (output).
552    */
553   public void getParticleParameters(int index, DoubleArray particleParameters) {
554     OpenMM_CustomGBForce_getParticleParameters(pointer, index, particleParameters.getPointer());
555   }
556 
557   /**
558    * Get the name of a per-particle parameter.
559    *
560    * @param index The index of the parameter.
561    * @return The name of the parameter.
562    */
563   public String getPerParticleParameterName(int index) {
564     Pointer p = OpenMM_CustomGBForce_getPerParticleParameterName(pointer, index);
565     if (p == null) {
566       return null;
567     }
568     return p.getString(0);
569   }
570 
571   /**
572    * Get a reference to a tabulated function.
573    *
574    * @param index The index of the function.
575    * @return A reference to the function.
576    */
577   public PointerByReference getTabulatedFunction(int index) {
578     return OpenMM_CustomGBForce_getTabulatedFunction(pointer, index);
579   }
580 
581   /**
582    * Get the name of a tabulated function.
583    *
584    * @param index The index of the function.
585    * @return The name of the function.
586    */
587   public String getTabulatedFunctionName(int index) {
588     Pointer p = OpenMM_CustomGBForce_getTabulatedFunctionName(pointer, index);
589     if (p == null) {
590       return null;
591     }
592     return p.getString(0);
593   }
594 
595   /**
596    * Set the parameters for a computed value.
597    *
598    * @param index      The index of the computed value.
599    * @param name       The name of the computed value.
600    * @param expression The expression for computing the value.
601    * @param type       The type of computation to perform.
602    */
603   public void setComputedValueParameters(int index, String name, String expression, int type) {
604     OpenMM_CustomGBForce_setComputedValueParameters(pointer, index, name, expression, type);
605   }
606 
607   /**
608    * Set the cutoff distance.
609    *
610    * @param distance The cutoff distance.
611    */
612   public void setCutoffDistance(double distance) {
613     OpenMM_CustomGBForce_setCutoffDistance(pointer, distance);
614   }
615 
616   /**
617    * Set the parameters for an energy term.
618    *
619    * @param index      The index of the energy term.
620    * @param expression The expression for computing the energy term.
621    * @param type       The type of computation to perform.
622    */
623   public void setEnergyTermParameters(int index, String expression, int type) {
624     OpenMM_CustomGBForce_setEnergyTermParameters(pointer, index, expression, type);
625   }
626 
627   /**
628    * Set the particles in an exclusion.
629    *
630    * @param index     The index of the exclusion.
631    * @param particle1 The index of the first particle in the exclusion.
632    * @param particle2 The index of the second particle in the exclusion.
633    */
634   public void setExclusionParticles(int index, int particle1, int particle2) {
635     OpenMM_CustomGBForce_setExclusionParticles(pointer, index, particle1, particle2);
636   }
637 
638   /**
639    * Set the parameters for a tabulated function.
640    *
641    * @param index  The index of the function.
642    * @param name   The name of the function.
643    * @param values The tabulated values of the function.
644    * @param min    The minimum value of the independent variable for which the function is defined.
645    * @param max    The maximum value of the independent variable for which the function is defined.
646    */
647   public void setFunctionParameters(int index, String name, PointerByReference values, double min, double max) {
648     OpenMM_CustomGBForce_setFunctionParameters(pointer, index, name, values, min, max);
649   }
650 
651   /**
652    * Set the default value of a global parameter.
653    *
654    * @param index        The index of the parameter.
655    * @param defaultValue The default value of the parameter.
656    */
657   public void setGlobalParameterDefaultValue(int index, double defaultValue) {
658     OpenMM_CustomGBForce_setGlobalParameterDefaultValue(pointer, index, defaultValue);
659   }
660 
661   /**
662    * Set the name of a global parameter.
663    *
664    * @param index The index of the parameter.
665    * @param name  The name of the parameter.
666    */
667   public void setGlobalParameterName(int index, String name) {
668     OpenMM_CustomGBForce_setGlobalParameterName(pointer, index, name);
669   }
670 
671   /**
672    * Set the nonbonded method.
673    *
674    * @param method The nonbonded method.
675    */
676   public void setNonbondedMethod(int method) {
677     OpenMM_CustomGBForce_setNonbondedMethod(pointer, method);
678   }
679 
680   /**
681    * Set the parameters for a particle.
682    *
683    * @param index              The index of the particle.
684    * @param particleParameters The parameters for the particle.
685    */
686   public void setParticleParameters(int index, DoubleArray particleParameters) {
687     OpenMM_CustomGBForce_setParticleParameters(pointer, index, particleParameters.getPointer());
688   }
689 
690   /**
691    * Set the name of a per-particle parameter.
692    *
693    * @param index The index of the parameter.
694    * @param name  The name of the parameter.
695    */
696   public void setPerParticleParameterName(int index, String name) {
697     OpenMM_CustomGBForce_setPerParticleParameterName(pointer, index, name);
698   }
699 
700   /**
701    * Update the parameters in the context.
702    *
703    * @param context The context.
704    */
705   public void updateParametersInContext(Context context) {
706     if (context.hasContextPointer()) {
707       OpenMM_CustomGBForce_updateParametersInContext(pointer, context.getPointer());
708     }
709   }
710 
711   /**
712    * Check if the force uses periodic boundary conditions.
713    *
714    * @return True if the force uses periodic boundary conditions.
715    */
716   @Override
717   public boolean usesPeriodicBoundaryConditions() {
718     int pbc = OpenMM_CustomGBForce_usesPeriodicBoundaryConditions(pointer);
719     return pbc == OpenMM_True;
720   }
721 }