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 static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True; 41 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_addBond; 42 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_addEnergyParameterDerivative; 43 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_addGlobalParameter; 44 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_addGroup; 45 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_addPerBondParameter; 46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_create; 47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_destroy; 48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getBondParameters; 49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getEnergyFunction; 50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getEnergyParameterDerivativeName; 51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getGlobalParameterDefaultValue; 52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getGlobalParameterName; 53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getGroupParameters; 54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumBonds; 55 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumEnergyParameterDerivatives; 56 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumFunctions; 57 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumGlobalParameters; 58 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumGroups; 59 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumGroupsPerBond; 60 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumPerBondParameters; 61 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getNumTabulatedFunctions; 62 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_getPerBondParameterName; 63 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setBondParameters; 64 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setEnergyFunction; 65 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setGlobalParameterDefaultValue; 66 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setGlobalParameterName; 67 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setGroupParameters; 68 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setPerBondParameterName; 69 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_setUsesPeriodicBoundaryConditions; 70 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_updateParametersInContext; 71 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CustomCentroidBondForce_usesPeriodicBoundaryConditions; 72 73 /** 74 * This class is similar to CustomCompoundBondForce, but instead of applying forces between individual particles, 75 * it applies them between the centers of groups of particles. This is useful for a variety of purposes, such as 76 * restraints to keep two molecules from moving too far apart. 77 * <p> 78 * When using this class, you define groups of particles, and the center of each group is calculated as a weighted 79 * average of the particle positions. By default, the particle masses are used as weights, so the center position 80 * is the center of mass. You can optionally specify different weights to use. You then add bonds just as with 81 * CustomCompoundBondForce, but instead of specifying the particles that make up a bond, you specify the groups. 82 * <p> 83 * When creating a CustomCentroidBondForce, you specify the number of groups involved in a bond, and an expression 84 * for the energy of each bond. It may depend on the center positions of individual groups, the distances between 85 * the centers of pairs of groups, the angles formed by sets of three groups, and the dihedral angles formed by 86 * sets of four groups. 87 * <p> 88 * We refer to the groups in a bond as g1, g2, g3, etc. For each bond, CustomCentroidBondForce evaluates a 89 * user supplied algebraic expression to determine the interaction energy. The expression may depend on the 90 * following variables and functions: 91 * 92 * <ul> 93 * <li>x1, y1, z1, x2, y2, z2, etc.: The x, y, and z coordinates of the centers of the groups. For example, x1 94 * is the x coordinate of the center of group g1, and y3 is the y coordinate of the center of group g3.</li> 95 * <li>distance(g1, g2): the distance between the centers of groups g1 and g2 (where "g1" and "g2" may be replaced 96 * by the names of whichever groups you want to calculate the distance between).</li> 97 * <li>angle(g1, g2, g3): the angle formed by the centers of the three specified groups.</li> 98 * <li>dihedral(g1, g2, g3, g4): the dihedral angle formed by the centers of the four specified groups.</li> 99 * </ul> 100 * <p> 101 * The expression also may involve tabulated functions, and may depend on arbitrary global and per-bond parameters. 102 * <p> 103 * To use this class, create a CustomCentroidBondForce 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 addGroup() to define the particle groups. Each group is specified by the particles it contains, and 110 * the weights to use when computing the center position. 111 * <p> 112 * Then call addBond() to define bonds and specify their parameter values. After a bond has been added, you can 113 * modify its parameters by calling setBondParameters(). This will have no effect on Contexts that already exist unless 114 * you call updateParametersInContext(). 115 * <p> 116 * As an example, the following code creates a CustomCentroidBondForce that implements a harmonic force between the 117 * centers of mass of two groups of particles. 118 * 119 * <pre> 120 * {@code 121 * CustomCentroidBondForce* force = new CustomCentroidBondForce(2, "0.5*k*distance(g1,g2)^2"); 122 * force->addPerBondParameter("k"); 123 * force->addGroup(particles1); 124 * force->addGroup(particles2); 125 * vector<int> bondGroups; 126 * bondGroups.push_back(0); 127 * bondGroups.push_back(1); 128 * vector<double> bondParameters; 129 * bondParameters.push_back(k); 130 * force->addBond(bondGroups, bondParameters); 131 * } 132 * </pre> 133 * <p> 134 * This class also has the ability to compute derivatives of the potential energy with respect to global parameters. 135 * Call addEnergyParameterDerivative() to request that the derivative with respect to a particular parameter be 136 * computed. You can then query its value in a Context by calling getState() on it. 137 * <p> 138 * Expressions may involve the operators + (add), - (subtract), * (multiply), / (divide), and ^ (power), and the following 139 * 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 140 * 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. 141 * select(x,y,z) = z if x = 0, y otherwise. 142 * <p> 143 * This class also supports the functions pointdistance(x1, y1, z1, x2, y2, z2), 144 * pointangle(x1, y1, z1, x2, y2, z2, x3, y3, z3), and pointdihedral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4). 145 * These functions are similar to distance(), angle(), and dihedral(), but the arguments are the 146 * coordinates of points to perform the calculation based on rather than the names of groups. 147 * This enables more flexible geometric calculations. For example, the following computes the distance 148 * from group g1 to the midpoint between groups g2 and g3. 149 * 150 * <pre> 151 * {@code 152 * CustomCentroidBondForce* force = new CustomCentroidBondForce(3, "pointdistance(x1, y1, z1, (x2+x3)/2, (y2+y3)/2, (z2+z3)/2)"); 153 * } 154 * </pre> 155 * <p> 156 * In addition, you can call addTabulatedFunction() to define a new function based on tabulated values. You specify the function by 157 * creating a TabulatedFunction object. That function can then appear in the expression. 158 */ 159 public class CustomCentroidBondForce extends Force { 160 161 /** 162 * Create a CustomCentroidBondForce. 163 * 164 * @param numGroups the number of groups used to define each bond 165 * @param energy an algebraic expression giving the interaction energy of each bond as a function 166 * of particle positions, inter-particle distances, angles, and dihedrals, and any global 167 * and per-bond parameters 168 */ 169 public CustomCentroidBondForce(int numGroups, String energy) { 170 pointer = OpenMM_CustomCentroidBondForce_create(numGroups, energy); 171 } 172 173 /** 174 * Get the number of groups used to define each bond. 175 */ 176 public int getNumGroupsPerBond() { 177 return OpenMM_CustomCentroidBondForce_getNumGroupsPerBond(pointer); 178 } 179 180 /** 181 * Get the number of particle groups that have been defined. 182 */ 183 public int getNumGroups() { 184 return OpenMM_CustomCentroidBondForce_getNumGroups(pointer); 185 } 186 187 /** 188 * Get the number of bonds for which force field parameters have been defined. 189 */ 190 public int getNumBonds() { 191 return OpenMM_CustomCentroidBondForce_getNumBonds(pointer); 192 } 193 194 /** 195 * Get the number of per-bond parameters that the interaction depends on. 196 */ 197 public int getNumPerBondParameters() { 198 return OpenMM_CustomCentroidBondForce_getNumPerBondParameters(pointer); 199 } 200 201 /** 202 * Get the number of global parameters that the interaction depends on. 203 */ 204 public int getNumGlobalParameters() { 205 return OpenMM_CustomCentroidBondForce_getNumGlobalParameters(pointer); 206 } 207 208 /** 209 * Get the number of global parameters with respect to which the derivative of the energy 210 * should be computed. 211 */ 212 public int getNumEnergyParameterDerivatives() { 213 return OpenMM_CustomCentroidBondForce_getNumEnergyParameterDerivatives(pointer); 214 } 215 216 /** 217 * Get the number of tabulated functions that have been defined. 218 */ 219 public int getNumTabulatedFunctions() { 220 return OpenMM_CustomCentroidBondForce_getNumTabulatedFunctions(pointer); 221 } 222 223 /** 224 * Get the number of tabulated functions that have been defined. 225 * 226 * @deprecated This method exists only for backward compatibility. Use getNumTabulatedFunctions() instead. 227 */ 228 @Deprecated 229 public int getNumFunctions() { 230 return OpenMM_CustomCentroidBondForce_getNumFunctions(pointer); 231 } 232 233 /** 234 * Get the algebraic expression that gives the interaction energy of each bond 235 */ 236 public String getEnergyFunction() { 237 return OpenMM_CustomCentroidBondForce_getEnergyFunction(pointer).getString(0); 238 } 239 240 /** 241 * Set the algebraic expression that gives the interaction energy of each bond 242 */ 243 public void setEnergyFunction(String energy) { 244 OpenMM_CustomCentroidBondForce_setEnergyFunction(pointer, energy); 245 } 246 247 /** 248 * Add a new per-bond parameter that the interaction may depend on. 249 * 250 * @param name the name of the parameter 251 * @return the index of the parameter that was added 252 */ 253 public int addPerBondParameter(String name) { 254 return OpenMM_CustomCentroidBondForce_addPerBondParameter(pointer, name); 255 } 256 257 /** 258 * Get the name of a per-bond parameter. 259 * 260 * @param index the index of the parameter for which to get the name 261 * @return the parameter name 262 */ 263 public String getPerBondParameterName(int index) { 264 return OpenMM_CustomCentroidBondForce_getPerBondParameterName(pointer, index).getString(0); 265 } 266 267 /** 268 * Set the name of a per-bond parameter. 269 * 270 * @param index the index of the parameter for which to set the name 271 * @param name the name of the parameter 272 */ 273 public void setPerBondParameterName(int index, String name) { 274 OpenMM_CustomCentroidBondForce_setPerBondParameterName(pointer, index, name); 275 } 276 277 /** 278 * Add a new global parameter that the interaction may depend on. The default value provided to 279 * this method is the initial value of the parameter in newly created Contexts. You can change 280 * the value at any time by calling setParameter() on the Context. 281 * 282 * @param name the name of the parameter 283 * @param defaultValue the default value of the parameter 284 * @return the index of the parameter that was added 285 */ 286 public int addGlobalParameter(String name, double defaultValue) { 287 return OpenMM_CustomCentroidBondForce_addGlobalParameter(pointer, name, defaultValue); 288 } 289 290 /** 291 * Get the name of a global parameter. 292 * 293 * @param index the index of the parameter for which to get the name 294 * @return the parameter name 295 */ 296 public String getGlobalParameterName(int index) { 297 return OpenMM_CustomCentroidBondForce_getGlobalParameterName(pointer, index).getString(0); 298 } 299 300 /** 301 * Set the name of a global parameter. 302 * 303 * @param index the index of the parameter for which to set the name 304 * @param name the name of the parameter 305 */ 306 public void setGlobalParameterName(int index, String name) { 307 OpenMM_CustomCentroidBondForce_setGlobalParameterName(pointer, index, name); 308 } 309 310 /** 311 * Get the default value of a global parameter. 312 * 313 * @param index the index of the parameter for which to get the default value 314 * @return the parameter default value 315 */ 316 public double getGlobalParameterDefaultValue(int index) { 317 return OpenMM_CustomCentroidBondForce_getGlobalParameterDefaultValue(pointer, index); 318 } 319 320 /** 321 * Set the default value of a global parameter. 322 * 323 * @param index the index of the parameter for which to set the default value 324 * @param defaultValue the default value of the parameter 325 */ 326 public void setGlobalParameterDefaultValue(int index, double defaultValue) { 327 OpenMM_CustomCentroidBondForce_setGlobalParameterDefaultValue(pointer, index, defaultValue); 328 } 329 330 /** 331 * Request that this Force compute the derivative of its energy with respect to a global parameter. 332 * The parameter must have already been added with addGlobalParameter(). 333 * 334 * @param name the name of the parameter 335 */ 336 public void addEnergyParameterDerivative(String name) { 337 OpenMM_CustomCentroidBondForce_addEnergyParameterDerivative(pointer, name); 338 } 339 340 /** 341 * Get the name of a global parameter with respect to which this Force should compute the 342 * derivative of the energy. 343 * 344 * @param index the index of the parameter derivative, between 0 and getNumEnergyParameterDerivatives() 345 * @return the parameter name 346 */ 347 public String getEnergyParameterDerivativeName(int index) { 348 return OpenMM_CustomCentroidBondForce_getEnergyParameterDerivativeName(pointer, index).getString(0); 349 } 350 351 /** 352 * Add a particle group. 353 * 354 * @param particles the indices of the particles to include in the group 355 * @param weights the weight to use for each particle when computing the center position. 356 * If this is omitted, then particle masses will be used as weights. 357 * @return the index of the group that was added 358 */ 359 public int addGroup(IntArray particles, DoubleArray weights) { 360 return OpenMM_CustomCentroidBondForce_addGroup(pointer, particles.getPointer(), weights.getPointer()); 361 } 362 363 /** 364 * Get the properties of a group. 365 * 366 * @param index the index of the group to get 367 * @param particles the indices of the particles in the group 368 * @param weights the weight used for each particle when computing the center position. 369 * If no weights were specified, this vector will be empty indicating that particle 370 * masses should be used as weights. 371 */ 372 public void getGroupParameters(int index, IntArray particles, DoubleArray weights) { 373 OpenMM_CustomCentroidBondForce_getGroupParameters(pointer, index, particles.getPointer(), weights.getPointer()); 374 } 375 376 /** 377 * Set the properties of a group. 378 * 379 * @param index the index of the group to set 380 * @param particles the indices of the particles in the group 381 * @param weights the weight to use for each particle when computing the center position. 382 * If this is omitted, then particle masses will be used as weights. 383 */ 384 public void setGroupParameters(int index, IntArray particles, DoubleArray weights) { 385 OpenMM_CustomCentroidBondForce_setGroupParameters(pointer, index, particles.getPointer(), weights.getPointer()); 386 } 387 388 /** 389 * Add a bond to the force 390 * 391 * @param groups the indices of the groups the bond depends on 392 * @param parameters the list of per-bond parameter values for the new bond 393 * @return the index of the bond that was added 394 */ 395 public int addBond(IntArray groups, DoubleArray parameters) { 396 return OpenMM_CustomCentroidBondForce_addBond(pointer, groups.getPointer(), parameters.getPointer()); 397 } 398 399 /** 400 * Get the properties of a bond. 401 * 402 * @param index the index of the bond to get 403 * @param groups the indices of the groups in the bond 404 * @param parameters the list of per-bond parameter values for the bond 405 */ 406 public void getBondParameters(int index, IntArray groups, DoubleArray parameters) { 407 OpenMM_CustomCentroidBondForce_getBondParameters(pointer, index, groups.getPointer(), parameters.getPointer()); 408 } 409 410 /** 411 * Set the properties of a bond. 412 * 413 * @param index the index of the bond to set 414 * @param groups the indices of the groups in the bond 415 * @param parameters the list of per-bond parameter values for the bond 416 */ 417 public void setBondParameters(int index, IntArray groups, DoubleArray parameters) { 418 OpenMM_CustomCentroidBondForce_setBondParameters(pointer, index, groups.getPointer(), parameters.getPointer()); 419 } 420 421 422 /** 423 * Update the per-bond parameters and tabulated functions in a Context to match those stored in this Force object. This method provides 424 * an efficient method to update certain parameters in an existing Context without needing to reinitialize it. 425 * Simply call setBondParameters() to modify this object's parameters, then call updateParametersInContext() 426 * to copy them over to the Context. 427 * <p> 428 * This method has several limitations. The only information it updates is the values of per-bond parameters and tabulated 429 * functions. All other aspects of the Force (such as the energy function) are unaffected and can only be changed by reinitializing 430 * the Context. Neither the definitions of groups nor the set of groups involved in a bond can be changed, nor can new 431 * bonds be added. Also, while the tabulated values of a function can change, everything else about it (its dimensions, 432 * the data range) must not be changed. 433 * 434 * @param context the OpenMM context. 435 */ 436 public void updateParametersInContext(Context context) { 437 if (context.hasContextPointer()) { 438 OpenMM_CustomCentroidBondForce_updateParametersInContext(pointer, context.getPointer()); 439 } 440 } 441 442 /** 443 * Set whether this force should apply periodic boundary conditions when calculating displacements. 444 * Usually this is not appropriate for bonded forces, but there are situations when it can be useful. 445 * 446 * @param periodic 1 if periodic boundary conditions should be used, 0 if not. 447 */ 448 public void setUsesPeriodicBoundaryConditions(int periodic) { 449 OpenMM_CustomCentroidBondForce_setUsesPeriodicBoundaryConditions(pointer, periodic); 450 } 451 452 /** 453 * Returns whether this force makes use of periodic boundary 454 * conditions. 455 * 456 * @return true if force uses PBC and false otherwise 457 */ 458 public boolean usesPeriodicBoundaryConditions() { 459 int pbc = OpenMM_CustomCentroidBondForce_usesPeriodicBoundaryConditions(pointer); 460 return pbc == OpenMM_True; 461 } 462 463 /** 464 * Destroy the OpenMM CustomCentroidBondForce. 465 */ 466 public void destroy() { 467 OpenMM_CustomCentroidBondForce_destroy(pointer); 468 } 469 470 }