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.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 }