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.ptr.DoubleByReference;
41 import com.sun.jna.ptr.IntByReference;
42
43 import java.nio.DoubleBuffer;
44 import java.nio.IntBuffer;
45
46 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
47 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_addException;
48 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_addParticle;
49 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_create;
50 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_destroy;
51 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getCutoffDistance;
52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getExceptionParameters;
53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getNonbondedMethod;
54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getNumExceptions;
55 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getNumParticles;
56 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getParticleParameters;
57 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getSwitchingDistance;
58 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_getUseSwitchingFunction;
59 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setCutoffDistance;
60 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setExceptionParameters;
61 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setNonbondedMethod;
62 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setParticleParameters;
63 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setSwitchingDistance;
64 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_setUseSwitchingFunction;
65 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_updateParametersInContext;
66 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_GayBerneForce_usesPeriodicBoundaryConditions;
67
68 /**
69 * This class implements the Gay-Berne anisotropic potential. This is similar to a Lennard-Jones potential,
70 * but it represents the particles as ellipsoids rather than point particles. In addition to the standard
71 * sigma and epsilon parameters, each particle has three widths sx, sy, and sz that give the diameter of the
72 * ellipsoid along each axis. It also has three scale factors ex, ey, and ez that scale the strength
73 * of the interaction along each axis. You can think of this force as a Lennard-Jones interaction computed
74 * based on the distance between the nearest points on two ellipsoids. The scale factors act as multipliers
75 * for epsilon along each axis, so the strength of the interaction along the ellipsoid's x axis is multiplied by
76 * ex, and likewise for the other axes. If two particles each have all their widths set to sigma and all their
77 * scale factors set to 1, the interaction simplifies to a standard Lennard-Jones force between point particles.
78 * <p>
79 * The orientation of a particle's ellipsoid is determined based on the positions of two other particles.
80 * The vector to the first particle sets the direction of the x axis. The vector to the second particle
81 * (after subtracting out any x component) sets the direction of the y axis. If the ellipsoid is axially
82 * symmetric (sy=sz and ey=ez), you can omit the second particle and define only an x axis direction.
83 * If the ellipsoid is a sphere (all three widths and all three scale factors are equal), both particles
84 * can be omitted.
85 * <p>
86 * To determine the values of sigma and epsilon for an interaction, this class uses Lorentz-Berthelot
87 * combining rules: it takes the arithmetic mean of the sigmas and the geometric mean of the epsilons for
88 * the two interacting particles. You also can specify "exceptions", particular pairs of particles for
89 * which different values should be used.
90 * <p>
91 * To use this class, create a GayBerneForce object, then call addParticle() once for each particle in the
92 * System to define its parameters. The number of particles for which you define parameters must be exactly
93 * equal to the number of particles in the System, or else an exception will be thrown when you try to
94 * create a Context. After a particle has been added, you can modify its force field parameters by calling
95 * setParticleParameters(). This will have no effect on Contexts that already exist unless you call
96 * updateParametersInContext().
97 * <p>
98 * When using a cutoff, by default interactions are sharply truncated at the cutoff distance. Optionally
99 * you can instead use a switching function to make the interaction smoothly go to zero over a finite
100 * distance range. To enable this, call setUseSwitchingFunction(). You must also call setSwitchingDistance()
101 * to specify the distance at which the interaction should begin to decrease. The switching distance must be
102 * less than the cutoff distance.
103 */
104 public class GayBerneForce extends Force {
105
106 /**
107 * Create a new GayBerneForce.
108 */
109 public GayBerneForce() {
110 super(OpenMM_GayBerneForce_create());
111 }
112
113 /**
114 * Add an exception to the force.
115 *
116 * @param particle1 The index of the first particle.
117 * @param particle2 The index of the second particle.
118 * @param sigma The sigma parameter for the exception.
119 * @param epsilon The epsilon parameter for the exception.
120 * @param replace Whether to replace an existing exception.
121 * @return The index of the exception that was added.
122 */
123 public int addException(int particle1, int particle2, double sigma, double epsilon, int replace) {
124 return OpenMM_GayBerneForce_addException(pointer, particle1, particle2, sigma, epsilon, replace);
125 }
126
127 /**
128 * Add a particle to the force.
129 *
130 * @param sigma The sigma parameter.
131 * @param epsilon The epsilon parameter.
132 * @param xparticle The x-axis particle type.
133 * @param yparticle The y-axis particle type.
134 * @param ex The x-axis shape parameter.
135 * @param ey The y-axis shape parameter.
136 * @param ez The z-axis shape parameter.
137 * @param sx The x-axis strength parameter.
138 * @param sy The y-axis strength parameter.
139 * @param sz The z-axis strength parameter.
140 * @return The index of the particle that was added.
141 */
142 public int addParticle(double sigma, double epsilon, int xparticle, int yparticle,
143 double ex, double ey, double ez, double sx, double sy, double sz) {
144 return OpenMM_GayBerneForce_addParticle(pointer, sigma, epsilon, xparticle, yparticle,
145 ex, ey, ez, sx, sy, sz);
146 }
147
148 /**
149 * Destroy the force.
150 */
151 @Override
152 public void destroy() {
153 if (pointer != null) {
154 OpenMM_GayBerneForce_destroy(pointer);
155 pointer = null;
156 }
157 }
158
159 /**
160 * Get the cutoff distance.
161 *
162 * @return The cutoff distance, measured in nm.
163 */
164 public double getCutoffDistance() {
165 return OpenMM_GayBerneForce_getCutoffDistance(pointer);
166 }
167
168 /**
169 * Get the parameters for an exception.
170 *
171 * @param index The index of the exception.
172 * @param particle1 The index of the first particle (output).
173 * @param particle2 The index of the second particle (output).
174 * @param sigma The sigma parameter for the exception (output).
175 * @param epsilon The epsilon parameter for the exception (output).
176 */
177 public void getExceptionParameters(int index, IntByReference particle1, IntByReference particle2,
178 DoubleByReference sigma, DoubleByReference epsilon) {
179 OpenMM_GayBerneForce_getExceptionParameters(pointer, index, particle1, particle2, sigma, epsilon);
180 }
181
182 /**
183 * Get the parameters for an exception.
184 *
185 * @param index The index of the exception.
186 * @param particle1 The index of the first particle (output).
187 * @param particle2 The index of the second particle (output).
188 * @param sigma The sigma parameter for the exception (output).
189 * @param epsilon The epsilon parameter for the exception (output).
190 */
191 public void getExceptionParameters(int index, IntBuffer particle1, IntBuffer particle2,
192 DoubleBuffer sigma, DoubleBuffer epsilon) {
193 OpenMM_GayBerneForce_getExceptionParameters(pointer, index, particle1, particle2, sigma, epsilon);
194 }
195
196 /**
197 * Get the nonbonded method.
198 *
199 * @return The nonbonded method.
200 */
201 public int getNonbondedMethod() {
202 return OpenMM_GayBerneForce_getNonbondedMethod(pointer);
203 }
204
205 /**
206 * Get the number of exceptions.
207 *
208 * @return The number of exceptions.
209 */
210 public int getNumExceptions() {
211 return OpenMM_GayBerneForce_getNumExceptions(pointer);
212 }
213
214 /**
215 * Get the number of particles.
216 *
217 * @return The number of particles.
218 */
219 public int getNumParticles() {
220 return OpenMM_GayBerneForce_getNumParticles(pointer);
221 }
222
223 /**
224 * Get the parameters for a particle.
225 *
226 * @param index The index of the particle.
227 * @param sigma The sigma parameter (output).
228 * @param epsilon The epsilon parameter (output).
229 * @param xparticle The x-axis particle type (output).
230 * @param yparticle The y-axis particle type (output).
231 * @param ex The x-axis shape parameter (output).
232 * @param ey The y-axis shape parameter (output).
233 * @param ez The z-axis shape parameter (output).
234 * @param sx The x-axis strength parameter (output).
235 * @param sy The y-axis strength parameter (output).
236 * @param sz The z-axis strength parameter (output).
237 */
238 public void getParticleParameters(int index, DoubleByReference sigma, DoubleByReference epsilon,
239 IntByReference xparticle, IntByReference yparticle,
240 DoubleByReference ex, DoubleByReference ey, DoubleByReference ez,
241 DoubleByReference sx, DoubleByReference sy, DoubleByReference sz) {
242 OpenMM_GayBerneForce_getParticleParameters(pointer, index, sigma, epsilon, xparticle, yparticle,
243 ex, ey, ez, sx, sy, sz);
244 }
245
246 /**
247 * Get the parameters for a particle.
248 *
249 * @param index The index of the particle.
250 * @param sigma The sigma parameter (output).
251 * @param epsilon The epsilon parameter (output).
252 * @param xparticle The x-axis particle type (output).
253 * @param yparticle The y-axis particle type (output).
254 * @param ex The x-axis shape parameter (output).
255 * @param ey The y-axis shape parameter (output).
256 * @param ez The z-axis shape parameter (output).
257 * @param sx The x-axis strength parameter (output).
258 * @param sy The y-axis strength parameter (output).
259 * @param sz The z-axis strength parameter (output).
260 */
261 public void getParticleParameters(int index, DoubleBuffer sigma, DoubleBuffer epsilon,
262 IntBuffer xparticle, IntBuffer yparticle,
263 DoubleBuffer ex, DoubleBuffer ey, DoubleBuffer ez,
264 DoubleBuffer sx, DoubleBuffer sy, DoubleBuffer sz) {
265 OpenMM_GayBerneForce_getParticleParameters(pointer, index, sigma, epsilon, xparticle, yparticle,
266 ex, ey, ez, sx, sy, sz);
267 }
268
269 /**
270 * Get the switching distance.
271 *
272 * @return The switching distance, measured in nm.
273 */
274 public double getSwitchingDistance() {
275 return OpenMM_GayBerneForce_getSwitchingDistance(pointer);
276 }
277
278 /**
279 * Get whether a switching function is used.
280 *
281 * @return 1 if a switching function is used, 0 otherwise.
282 */
283 public int getUseSwitchingFunction() {
284 return OpenMM_GayBerneForce_getUseSwitchingFunction(pointer);
285 }
286
287 /**
288 * Set the cutoff distance.
289 *
290 * @param distance The cutoff distance, measured in nm.
291 */
292 public void setCutoffDistance(double distance) {
293 OpenMM_GayBerneForce_setCutoffDistance(pointer, distance);
294 }
295
296 /**
297 * Set the parameters for an exception.
298 *
299 * @param index The index of the exception.
300 * @param particle1 The index of the first particle.
301 * @param particle2 The index of the second particle.
302 * @param sigma The sigma parameter for the exception.
303 * @param epsilon The epsilon parameter for the exception.
304 */
305 public void setExceptionParameters(int index, int particle1, int particle2, double sigma, double epsilon) {
306 OpenMM_GayBerneForce_setExceptionParameters(pointer, index, particle1, particle2, sigma, epsilon);
307 }
308
309 /**
310 * Set the nonbonded method.
311 *
312 * @param method The nonbonded method.
313 */
314 public void setNonbondedMethod(int method) {
315 OpenMM_GayBerneForce_setNonbondedMethod(pointer, method);
316 }
317
318 /**
319 * Set the parameters for a particle.
320 *
321 * @param index The index of the particle.
322 * @param sigma The sigma parameter.
323 * @param epsilon The epsilon parameter.
324 * @param xparticle The x-axis particle type.
325 * @param yparticle The y-axis particle type.
326 * @param ex The x-axis shape parameter.
327 * @param ey The y-axis shape parameter.
328 * @param ez The z-axis shape parameter.
329 * @param sx The x-axis strength parameter.
330 * @param sy The y-axis strength parameter.
331 * @param sz The z-axis strength parameter.
332 */
333 public void setParticleParameters(int index, double sigma, double epsilon, int xparticle, int yparticle,
334 double ex, double ey, double ez, double sx, double sy, double sz) {
335 OpenMM_GayBerneForce_setParticleParameters(pointer, index, sigma, epsilon, xparticle, yparticle,
336 ex, ey, ez, sx, sy, sz);
337 }
338
339 /**
340 * Set the switching distance.
341 *
342 * @param distance The switching distance, measured in nm.
343 */
344 public void setSwitchingDistance(double distance) {
345 OpenMM_GayBerneForce_setSwitchingDistance(pointer, distance);
346 }
347
348 /**
349 * Set whether to use a switching function.
350 *
351 * @param use 1 to use a switching function, 0 otherwise.
352 */
353 public void setUseSwitchingFunction(int use) {
354 OpenMM_GayBerneForce_setUseSwitchingFunction(pointer, use);
355 }
356
357 /**
358 * Update the parameters in a Context to match those stored in this Force object.
359 *
360 * @param context The Context in which to update the parameters.
361 */
362 public void updateParametersInContext(Context context) {
363 if (context.hasContextPointer()) {
364 OpenMM_GayBerneForce_updateParametersInContext(pointer, context.getPointer());
365 }
366 }
367
368 /**
369 * Check if the force uses periodic boundary conditions.
370 *
371 * @return True if the force uses periodic boundary conditions.
372 */
373 @Override
374 public boolean usesPeriodicBoundaryConditions() {
375 int pbc = OpenMM_GayBerneForce_usesPeriodicBoundaryConditions(pointer);
376 return pbc == OpenMM_True;
377 }
378 }