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.PointerByReference;
43  
44  import java.nio.DoubleBuffer;
45  
46  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
47  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addBond;
48  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addEnergyParameterDerivative;
49  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addFunction;
50  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addGlobalParameter;
51  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addPerBondParameter;
52  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_addTabulatedFunction;
53  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_create;
54  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_destroy;
55  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getBondParameters;
56  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getEnergyFunction;
57  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getEnergyParameterDerivativeName;
58  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getFunctionParameters;
59  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getGlobalParameterDefaultValue;
60  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getGlobalParameterName;
61  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumBonds;
62  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumEnergyParameterDerivatives;
63  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumFunctions;
64  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumGlobalParameters;
65  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumParticlesPerBond;
66  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumPerBondParameters;
67  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getNumTabulatedFunctions;
68  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getPerBondParameterName;
69  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getTabulatedFunction;
70  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_getTabulatedFunctionName;
71  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setBondParameters;
72  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setEnergyFunction;
73  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setFunctionParameters;
74  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setGlobalParameterDefaultValue;
75  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setGlobalParameterName;
76  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setPerBondParameterName;
77  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_setUsesPeriodicBoundaryConditions;
78  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_updateParametersInContext;
79  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCompoundBondForce_usesPeriodicBoundaryConditions;
80  
81  /**
82   * This class supports a wide variety of bonded interactions.  It defines a "bond" as a single energy term
83   * that depends on the positions of a fixed set of particles.  The number of particles involved in a bond, and how
84   * the energy depends on their positions, is configurable.  It may depend on the positions of individual particles,
85   * the distances between pairs of particles, the angles formed by sets of three particles, and the dihedral
86   * angles formed by sets of four particles.
87   * <p>
88   * We refer to the particles in a bond as p1, p2, p3, etc.  For each bond, CustomCompoundBondForce evaluates a
89   * user supplied algebraic expression to determine the interaction energy.  The expression may depend on the
90   * following variables and functions:
91   * <ul>
92   * <li>x1, y1, z1, x2, y2, z2, etc.: The x, y, and z coordinates of the particle positions.  For example, x1
93   * is the x coordinate of particle p1, and y3 is the y coordinate of particle p3.</li>
94   * <li>distance(p1, p2): the distance between particles p1 and p2 (where "p1" and "p2" may be replaced by the names
95   * of whichever particles you want to calculate the distance between).</li>
96   * <li>angle(p1, p2, p3): the angle formed by the three specified particles.</li>
97   * <li>dihedral(p1, p2, p3, p4): the dihedral angle formed by the four specified particles, guaranteed to be in the range [-pi,+pi].</li>
98   * </ul>
99   * <p>
100  * The expression also may involve tabulated functions, and may depend on arbitrary
101  * global and per-bond parameters.
102  * <p>
103  * To use this class, create a CustomCompoundBondForce object, passing an algebraic expression to the constructor
104  * that defines the interaction energy of each bond.  Then call addPerBondParameter() to define per-bond
105  * parameters and addGlobalParameter() to define global parameters.  The values of per-bond parameters are specified
106  * as part of the system definition, while values of global parameters may be modified during a simulation by calling
107  * Context::setParameter().
108  * <p>
109  * Next, call addBond() to define bonds and specify their parameter values.  After a bond has been added, you can
110  * modify its parameters by calling setBondParameters().  This will have no effect on Contexts that already exist unless
111  * you call updateParametersInContext().
112  * <p>
113  * As an example, the following code creates a CustomCompoundBondForce that implements a Urey-Bradley potential.  This
114  * is an interaction between three particles that depends on the angle formed by p1-p2-p3, and on the distance between
115  * p1 and p3.
116  * <pre>
117  *   {@code
118  *    CustomCompoundBondForce* force = new CustomCompoundBondForce(3, "0.5*(kangle*(angle(p1,p2,p3)-theta0)^2+kbond*(distance(p1,p3)-r0)^2)");
119  *   }
120  * </pre>
121  * <p>
122  * This force depends on four parameters: kangle, kbond, theta0, and r0.  The following code defines these as per-bond parameters:
123  * <pre>
124  *   {@code
125  *    force->addPerBondParameter("kangle");
126  *    force->addPerBondParameter("kbond");
127  *    force->addPerBondParameter("theta0");
128  *    force->addPerBondParameter("r0");
129  *   }
130  * </pre>
131  * <p>
132  * This class also has the ability to compute derivatives of the potential energy with respect to global parameters.
133  * Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be
134  * computed.  You can then query its value in a Context by calling getState() on it.
135  * <p>
136  * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and &circ; (power), and the following
137  * 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
138  * 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.
139  * select(x,y,z) = z if x = 0, y otherwise.
140  * <p>
141  * This class also supports the functions pointdistance(x1, y1, z1, x2, y2, z2),
142  * pointangle(x1, y1, z1, x2, y2, z2, x3, y3, z3), and pointdihedral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4).
143  * These functions are similar to distance(), angle(), and dihedral(), but the arguments are the
144  * coordinates of points to perform the calculation based on rather than the names of particles.
145  * This enables more flexible geometric calculations.  For example, the following computes the distance
146  * from particle p1 to the midpoint between particles p2 and p3.
147  * <pre>
148  *   {@code
149  *    CustomCompoundBondForce* force = new CustomCompoundBondForce(3, "pointdistance(x1, y1, z1, (x2+x3)/2, (y2+y3)/2, (z2+z3)/2)");
150  *   }
151  * </pre>
152  * <p>
153  * In addition, you can call addTabulatedFunction() to define a new function based on tabulated values.  You specify the function by
154  * creating a TabulatedFunction object.  That function can then appear in the expression.
155  */
156 public class CustomCompoundBondForce extends Force {
157 
158   /**
159    * Create a CustomCompoundBondForce.
160    *
161    * @param numParticles The number of particles per bond.
162    * @param energy       The energy expression for the force.
163    */
164   public CustomCompoundBondForce(int numParticles, String energy) {
165     super(OpenMM_CustomCompoundBondForce_create(numParticles, energy));
166   }
167 
168   /**
169    * Add a bond to the force.
170    *
171    * @param particles  The indices of the particles in the bond.
172    * @param parameters The bond parameters.
173    * @return The index of the bond that was added.
174    */
175   public int addBond(IntArray particles, DoubleArray parameters) {
176     return OpenMM_CustomCompoundBondForce_addBond(pointer, particles.getPointer(), parameters.getPointer());
177   }
178 
179   /**
180    * Request that this Force compute the derivative of its energy with respect to a global parameter.
181    *
182    * @param name The name of the parameter to compute the derivative of the energy with respect to.
183    */
184   public void addEnergyParameterDerivative(String name) {
185     OpenMM_CustomCompoundBondForce_addEnergyParameterDerivative(pointer, name);
186   }
187 
188   /**
189    * Add a tabulated function that may appear in the energy expression.
190    *
191    * @param name   The name of the function as it appears in expressions.
192    * @param values The tabulated values of the function.
193    * @param min    The minimum value of the independent variable for which the function is defined.
194    * @param max    The maximum value of the independent variable for which the function is defined.
195    * @return The index of the function that was added.
196    * @deprecated This method exists only for backward compatibility. Use addTabulatedFunction() instead.
197    */
198   @Deprecated
199   public int addFunction(String name, PointerByReference values, double min, double max) {
200     return OpenMM_CustomCompoundBondForce_addFunction(pointer, name, values, min, max);
201   }
202 
203   /**
204    * Add a global parameter that the interaction may depend on.
205    *
206    * @param name         The name of the parameter.
207    * @param defaultValue The default value of the parameter.
208    * @return The index of the parameter that was added.
209    */
210   public int addGlobalParameter(String name, double defaultValue) {
211     return OpenMM_CustomCompoundBondForce_addGlobalParameter(pointer, name, defaultValue);
212   }
213 
214   /**
215    * Add a per-bond parameter that the interaction may depend on.
216    *
217    * @param name The name of the parameter.
218    * @return The index of the parameter that was added.
219    */
220   public int addPerBondParameter(String name) {
221     return OpenMM_CustomCompoundBondForce_addPerBondParameter(pointer, name);
222   }
223 
224   /**
225    * Add a tabulated function that may appear in the energy expression.
226    *
227    * @param name     The name of the function as it appears in expressions.
228    * @param function A TabulatedFunction object defining the function.
229    * @return The index of the function that was added.
230    */
231   public int addTabulatedFunction(String name, PointerByReference function) {
232     return OpenMM_CustomCompoundBondForce_addTabulatedFunction(pointer, name, function);
233   }
234 
235   /**
236    * Destroy the force.
237    */
238   @Override
239   public void destroy() {
240     if (pointer != null) {
241       OpenMM_CustomCompoundBondForce_destroy(pointer);
242       pointer = null;
243     }
244   }
245 
246   /**
247    * Get the parameters for a bond.
248    *
249    * @param index      The index of the bond.
250    * @param particles  The indices of the particles in the bond.
251    * @param parameters The bond parameters.
252    */
253   public void getBondParameters(int index, IntArray particles, DoubleArray parameters) {
254     OpenMM_CustomCompoundBondForce_getBondParameters(pointer, index, particles.getPointer(), parameters.getPointer());
255   }
256 
257   /**
258    * Get the energy expression for the force.
259    *
260    * @return The energy expression for the force.
261    */
262   public String getEnergyFunction() {
263     Pointer p = OpenMM_CustomCompoundBondForce_getEnergyFunction(pointer);
264     if (p == null) {
265       return null;
266     }
267     return p.getString(0);
268   }
269 
270   /**
271    * Get the name of a parameter with respect to which the derivative of the energy should be computed.
272    *
273    * @param index The index of the parameter derivative.
274    * @return The name of the parameter.
275    */
276   public String getEnergyParameterDerivativeName(int index) {
277     Pointer p = OpenMM_CustomCompoundBondForce_getEnergyParameterDerivativeName(pointer, index);
278     if (p == null) {
279       return null;
280     }
281     return p.getString(0);
282   }
283 
284   /**
285    * Get the parameters for a tabulated function.
286    *
287    * @param index  The index of the function.
288    * @param name   The name of the function.
289    * @param values The tabulated values.
290    * @param min    The minimum value of the independent variable.
291    * @param max    The maximum value of the independent variable.
292    */
293   public void getFunctionParameters(int index, PointerByReference name, PointerByReference values, DoubleBuffer min, DoubleBuffer max) {
294     OpenMM_CustomCompoundBondForce_getFunctionParameters(pointer, index, name, values, min, max);
295   }
296 
297   /**
298    * Get the parameters for a tabulated function.
299    *
300    * @param index  The index of the function.
301    * @param name   The name of the function.
302    * @param values The tabulated values.
303    * @param min    The minimum value of the independent variable.
304    * @param max    The maximum value of the independent variable.
305    */
306   public void getFunctionParameters(int index, PointerByReference name, PointerByReference values, DoubleByReference min, DoubleByReference max) {
307     OpenMM_CustomCompoundBondForce_getFunctionParameters(pointer, index, name, values, min, max);
308   }
309 
310   /**
311    * Get the default value of a global parameter.
312    *
313    * @param index The index of the parameter.
314    * @return The default value of the parameter.
315    */
316   public double getGlobalParameterDefaultValue(int index) {
317     return OpenMM_CustomCompoundBondForce_getGlobalParameterDefaultValue(pointer, index);
318   }
319 
320   /**
321    * Get the name of a global parameter.
322    *
323    * @param index The index of the parameter.
324    * @return The name of the parameter.
325    */
326   public String getGlobalParameterName(int index) {
327     Pointer p = OpenMM_CustomCompoundBondForce_getGlobalParameterName(pointer, index);
328     if (p == null) {
329       return null;
330     }
331     return p.getString(0);
332   }
333 
334   /**
335    * Get the number of bonds.
336    *
337    * @return The number of bonds.
338    */
339   public int getNumBonds() {
340     return OpenMM_CustomCompoundBondForce_getNumBonds(pointer);
341   }
342 
343   /**
344    * Get the number of parameters with respect to which the derivative of the energy should be computed.
345    *
346    * @return The number of parameters.
347    */
348   public int getNumEnergyParameterDerivatives() {
349     return OpenMM_CustomCompoundBondForce_getNumEnergyParameterDerivatives(pointer);
350   }
351 
352   /**
353    * Get the number of tabulated functions.
354    *
355    * @return The number of tabulated functions.
356    * @deprecated This method exists only for backward compatibility. Use getNumTabulatedFunctions() instead.
357    */
358   @Deprecated
359   public int getNumFunctions() {
360     return OpenMM_CustomCompoundBondForce_getNumFunctions(pointer);
361   }
362 
363   /**
364    * Get the number of global parameters.
365    *
366    * @return The number of global parameters.
367    */
368   public int getNumGlobalParameters() {
369     return OpenMM_CustomCompoundBondForce_getNumGlobalParameters(pointer);
370   }
371 
372   /**
373    * Get the number of particles per bond.
374    *
375    * @return The number of particles per bond.
376    */
377   public int getNumParticlesPerBond() {
378     return OpenMM_CustomCompoundBondForce_getNumParticlesPerBond(pointer);
379   }
380 
381   /**
382    * Get the number of per-bond parameters.
383    *
384    * @return The number of per-bond parameters.
385    */
386   public int getNumPerBondParameters() {
387     return OpenMM_CustomCompoundBondForce_getNumPerBondParameters(pointer);
388   }
389 
390   /**
391    * Get the number of tabulated functions.
392    *
393    * @return The number of tabulated functions.
394    */
395   public int getNumTabulatedFunctions() {
396     return OpenMM_CustomCompoundBondForce_getNumTabulatedFunctions(pointer);
397   }
398 
399   /**
400    * Get the name of a per-bond parameter.
401    *
402    * @param index The index of the parameter.
403    * @return The name of the parameter.
404    */
405   public String getPerBondParameterName(int index) {
406     Pointer p = OpenMM_CustomCompoundBondForce_getPerBondParameterName(pointer, index);
407     if (p == null) {
408       return null;
409     }
410     return p.getString(0);
411   }
412 
413   /**
414    * Get a reference to a tabulated function.
415    *
416    * @param index The index of the function.
417    * @return A reference to the function.
418    */
419   public PointerByReference getTabulatedFunction(int index) {
420     return OpenMM_CustomCompoundBondForce_getTabulatedFunction(pointer, index);
421   }
422 
423   /**
424    * Get the name of a tabulated function.
425    *
426    * @param index The index of the function.
427    * @return The name of the function.
428    */
429   public String getTabulatedFunctionName(int index) {
430     Pointer p = OpenMM_CustomCompoundBondForce_getTabulatedFunctionName(pointer, index);
431     if (p == null) {
432       return null;
433     }
434     return p.getString(0);
435   }
436 
437   /**
438    * Set the parameters for a bond.
439    *
440    * @param index      The index of the bond.
441    * @param particles  The indices of the particles in the bond.
442    * @param parameters The bond parameters.
443    */
444   public void setBondParameters(int index, IntArray particles, DoubleArray parameters) {
445     OpenMM_CustomCompoundBondForce_setBondParameters(pointer, index, particles.getPointer(), parameters.getPointer());
446   }
447 
448   /**
449    * Set the energy expression for the force.
450    *
451    * @param energy The energy expression for the force.
452    */
453   public void setEnergyFunction(String energy) {
454     OpenMM_CustomCompoundBondForce_setEnergyFunction(pointer, energy);
455   }
456 
457   /**
458    * Set the parameters for a tabulated function.
459    *
460    * @param index  The index of the function.
461    * @param name   The name of the function.
462    * @param values The tabulated values.
463    * @param min    The minimum value of the independent variable.
464    * @param max    The maximum value of the independent variable.
465    */
466   public void setFunctionParameters(int index, String name, PointerByReference values, double min, double max) {
467     OpenMM_CustomCompoundBondForce_setFunctionParameters(pointer, index, name, values, min, max);
468   }
469 
470   /**
471    * Set the default value of a global parameter.
472    *
473    * @param index        The index of the parameter.
474    * @param defaultValue The default value of the parameter.
475    */
476   public void setGlobalParameterDefaultValue(int index, double defaultValue) {
477     OpenMM_CustomCompoundBondForce_setGlobalParameterDefaultValue(pointer, index, defaultValue);
478   }
479 
480   /**
481    * Set the name of a global parameter.
482    *
483    * @param index The index of the parameter.
484    * @param name  The name of the parameter.
485    */
486   public void setGlobalParameterName(int index, String name) {
487     OpenMM_CustomCompoundBondForce_setGlobalParameterName(pointer, index, name);
488   }
489 
490   /**
491    * Set the name of a per-bond parameter.
492    *
493    * @param index The index of the parameter.
494    * @param name  The name of the parameter.
495    */
496   public void setPerBondParameterName(int index, String name) {
497     OpenMM_CustomCompoundBondForce_setPerBondParameterName(pointer, index, name);
498   }
499 
500   /**
501    * Set whether this force should apply periodic boundary conditions when calculating displacements.
502    *
503    * @param periodic If true, periodic boundary conditions will be used.
504    */
505   public void setUsesPeriodicBoundaryConditions(boolean periodic) {
506     OpenMM_CustomCompoundBondForce_setUsesPeriodicBoundaryConditions(pointer, periodic ? 1 : 0);
507   }
508 
509   /**
510    * Update the parameters in the context.
511    *
512    * @param context The context to update.
513    */
514   public void updateParametersInContext(Context context) {
515     if (context.hasContextPointer()) {
516       OpenMM_CustomCompoundBondForce_updateParametersInContext(pointer, context.getPointer());
517     }
518   }
519 
520   /**
521    * Check if the force uses periodic boundary conditions.
522    *
523    * @return True if the force uses periodic boundary conditions.
524    */
525   @Override
526   public boolean usesPeriodicBoundaryConditions() {
527     int pbc = OpenMM_CustomCompoundBondForce_usesPeriodicBoundaryConditions(pointer);
528     return pbc == OpenMM_True;
529   }
530 }