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.drude;
39
40 import com.sun.jna.ptr.DoubleByReference;
41 import com.sun.jna.ptr.IntByReference;
42 import ffx.openmm.Context;
43 import ffx.openmm.Force;
44
45 import java.nio.DoubleBuffer;
46 import java.nio.IntBuffer;
47
48 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_addParticle;
49 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_addScreenedPair;
50 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_create;
51 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_destroy;
52 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_getNumParticles;
53 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_getNumScreenedPairs;
54 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_getParticleParameters;
55 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_getScreenedPairParameters;
56 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_setParticleParameters;
57 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_setScreenedPairParameters;
58 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_setUsesPeriodicBoundaryConditions;
59 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_updateParametersInContext;
60 import static edu.uiowa.jopenmm.OpenMMDrudeLibrary.OpenMM_DrudeForce_usesPeriodicBoundaryConditions;
61 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
62
63 /**
64 * This class implements forces that are specific to Drude oscillators. There are two distinct forces
65 * it applies: an anisotropic harmonic force connecting each Drude particle to its parent particle; and
66 * a screened Coulomb interaction between specific pairs of dipoles. The latter is typically used between
67 * closely bonded particles whose Coulomb interaction would otherwise be fully excluded.
68 * <p>
69 * To use this class, create a DrudeForce object, then call addParticle() once for each Drude particle in the
70 * System to define its parameters. After a particle has been added, you can modify its force field parameters
71 * by calling setParticleParameters(). This will have no effect on Contexts that already exist unless you
72 * call updateParametersInContext(). Likewise, call addScreenedPair() for each pair of dipoles (each dipole
73 * consisting of a Drude particle and its parent) that should be computed.
74 */
75 public class DrudeForce extends Force {
76
77 /**
78 * Create a DrudeForce.
79 */
80 public DrudeForce() {
81 super(OpenMM_DrudeForce_create());
82 }
83
84 /**
85 * Add a Drude particle to which forces should be applied.
86 *
87 * @param particle the index within the System of the Drude particle
88 * @param particle1 the index within the System of the particle to which the Drude particle is attached
89 * @param particle2 the index within the System of the second particle used for defining anisotropic polarizability.
90 * This may be set to -1, in which case aniso12 will be ignored.
91 * @param particle3 the index within the System of the third particle used for defining anisotropic polarizability.
92 * This may be set to -1, in which case aniso34 will be ignored.
93 * @param particle4 the index within the System of the fourth particle used for defining anisotropic polarizability.
94 * This may be set to -1, in which case aniso34 will be ignored.
95 * @param charge The charge on the Drude particle
96 * @param polarizability The isotropic polarizability
97 * @param aniso12 The scale factor for the polarizability along the direction defined by particle1 and particle2
98 * @param aniso34 The scale factor for the polarizability along the direction defined by particle3 and particle4
99 * @return the index of the particle that was added
100 */
101 public int addParticle(int particle, int particle1, int particle2, int particle3, int particle4,
102 double charge, double polarizability, double aniso12, double aniso34) {
103 return OpenMM_DrudeForce_addParticle(pointer, particle, particle1, particle2, particle3, particle4,
104 charge, polarizability, aniso12, aniso34);
105 }
106
107 /**
108 * Add an interaction to the list of screened pairs.
109 *
110 * @param particle1 the index within this Force of the first particle involved in the interaction
111 * @param particle2 the index within this Force of the second particle involved in the interaction
112 * @param thole the Thole screening factor
113 * @return the index of the screenedPair that was added
114 */
115 public int addScreenedPair(int particle1, int particle2, double thole) {
116 return OpenMM_DrudeForce_addScreenedPair(pointer, particle1, particle2, thole);
117 }
118
119 /**
120 * Destroy the force.
121 * <p>
122 * This method releases the memory associated with the DrudeForce object.
123 * After calling this method, the force should not be used.
124 */
125 @Override
126 public void destroy() {
127 if (pointer != null) {
128 OpenMM_DrudeForce_destroy(pointer);
129 pointer = null;
130 }
131 }
132
133 /**
134 * Get the number of particles for which force field parameters have been defined.
135 */
136 public int getNumParticles() {
137 return OpenMM_DrudeForce_getNumParticles(pointer);
138 }
139
140 /**
141 * Get the number of special interactions that should be calculated differently from other interactions.
142 */
143 public int getNumScreenedPairs() {
144 return OpenMM_DrudeForce_getNumScreenedPairs(pointer);
145 }
146
147 /**
148 * Get the parameters for a Drude particle.
149 *
150 * @param index the index of the Drude particle for which to get parameters
151 * @param particle the index within the System of the Drude particle
152 * @param particle1 the index within the System of the particle to which the Drude particle is attached
153 * @param particle2 the index within the System of the second particle used for defining anisotropic polarizability.
154 * This may be set to -1, in which case aniso12 will be ignored.
155 * @param particle3 the index within the System of the third particle used for defining anisotropic polarizability.
156 * This may be set to -1, in which case aniso34 will be ignored.
157 * @param particle4 the index within the System of the fourth particle used for defining anisotropic polarizability.
158 * This may be set to -1, in which case aniso34 will be ignored.
159 * @param charge The charge on the Drude particle
160 * @param polarizability The isotropic polarizability
161 * @param aniso12 The scale factor for the polarizability along the direction defined by particle1 and particle2
162 * @param aniso34 The scale factor for the polarizability along the direction defined by particle3 and particle4
163 */
164 public void getParticleParameters(int index, IntByReference particle, IntByReference particle1,
165 IntByReference particle2, IntByReference particle3, IntByReference particle4,
166 DoubleByReference charge, DoubleByReference polarizability,
167 DoubleByReference aniso12, DoubleByReference aniso34) {
168 OpenMM_DrudeForce_getParticleParameters(pointer, index, particle, particle1, particle2,
169 particle3, particle4, charge, polarizability, aniso12, aniso34);
170 }
171
172 /**
173 * Get the force field parameters for a screened pair.
174 *
175 * @param index the index of the pair for which to get parameters
176 * @param particle1 the index within this Force of the first particle involved in the interaction
177 * @param particle2 the index within this Force of the second particle involved in the interaction
178 * @param thole the Thole screening factor
179 */
180 public void getScreenedPairParameters(int index, IntByReference particle1, IntByReference particle2,
181 DoubleByReference thole) {
182 OpenMM_DrudeForce_getScreenedPairParameters(pointer, index, particle1, particle2, thole);
183 }
184
185 /**
186 * Get the force field parameters for a screened pair.
187 *
188 * @param index the index of the pair for which to get parameters
189 * @param particle1 the index within this Force of the first particle involved in the interaction
190 * @param particle2 the index within this Force of the second particle involved in the interaction
191 * @param thole the Thole screening factor
192 */
193 public void getScreenedPairParameters(int index, IntBuffer particle1, IntBuffer particle2,
194 DoubleBuffer thole) {
195 OpenMM_DrudeForce_getScreenedPairParameters(pointer, index, particle1, particle2, thole);
196 }
197
198 /**
199 * Set the parameters for a Drude particle.
200 *
201 * @param index the index of the Drude particle for which to set parameters
202 * @param particle the index within the System of the Drude particle
203 * @param particle1 the index within the System of the particle to which the Drude particle is attached
204 * @param particle2 the index within the System of the second particle used for defining anisotropic polarizability.
205 * This may be set to -1, in which case aniso12 will be ignored.
206 * @param particle3 the index within the System of the third particle used for defining anisotropic polarizability.
207 * This may be set to -1, in which case aniso34 will be ignored.
208 * @param particle4 the index within the System of the fourth particle used for defining anisotropic polarizability.
209 * This may be set to -1, in which case aniso34 will be ignored.
210 * @param charge The charge on the Drude particle
211 * @param polarizability The isotropic polarizability
212 * @param aniso12 The scale factor for the polarizability along the direction defined by particle1 and particle2
213 * @param aniso34 The scale factor for the polarizability along the direction defined by particle3 and particle4
214 */
215 public void setParticleParameters(int index, int particle, int particle1, int particle2,
216 int particle3, int particle4, double charge, double polarizability,
217 double aniso12, double aniso34) {
218 OpenMM_DrudeForce_setParticleParameters(pointer, index, particle, particle1, particle2,
219 particle3, particle4, charge, polarizability, aniso12, aniso34);
220 }
221
222 /**
223 * Set the force field parameters for a screened pair.
224 *
225 * @param index the index of the pair for which to get parameters
226 * @param particle1 the index within this Force of the first particle involved in the interaction
227 * @param particle2 the index within this Force of the second particle involved in the interaction
228 * @param thole the Thole screening factor
229 */
230 public void setScreenedPairParameters(int index, int particle1, int particle2, double thole) {
231 OpenMM_DrudeForce_setScreenedPairParameters(pointer, index, particle1, particle2, thole);
232 }
233
234 /**
235 * Set whether this force should apply periodic boundary conditions when calculating displacements.
236 * Usually this is not appropriate for bonded forces, but there are situations when it can be useful.
237 * <p>
238 * Periodic boundary conditions are only applied to screened pairs. They are never used for the
239 * force between a Drude particle and its parent particle, regardless of this setting.
240 */
241 public void setUsesPeriodicBoundaryConditions(boolean periodic) {
242 OpenMM_DrudeForce_setUsesPeriodicBoundaryConditions(pointer, periodic ? 1 : 0);
243 }
244
245 /**
246 * Update the particle and screened pair parameters in a Context to match those stored in this Force object. This method
247 * provides an efficient method to update certain parameters in an existing Context without needing to reinitialize it.
248 * Simply call setParticleParameters() and setScreenedPairParameters() to modify this object's parameters, then call
249 * updateParametersInContext() to copy them over to the Context.
250 * <p>
251 * This method has several limitations. It can be used to modify the numeric parameters associated with a particle or
252 * screened pair (polarizability, thole, etc.), but not the identities of the particles they involve. It also cannot
253 * be used to add new particles or screenedPairs, only to change the parameters of existing ones.
254 */
255 public void updateParametersInContext(Context context) {
256 if (context.hasContextPointer()) {
257 OpenMM_DrudeForce_updateParametersInContext(pointer, context.getPointer());
258 }
259 }
260
261 /**
262 * Returns whether or not this force makes use of periodic boundary
263 * conditions.
264 */
265 @Override
266 public boolean usesPeriodicBoundaryConditions() {
267 int pbc = OpenMM_DrudeForce_usesPeriodicBoundaryConditions(pointer);
268 return pbc == OpenMM_True;
269 }
270 }