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.ptr.PointerByReference;
41  
42  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_addIntegrator;
43  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_create;
44  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_destroy;
45  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getConstraintTolerance;
46  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getCurrentIntegrator;
47  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getIntegrationForceGroups;
48  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getIntegrator;
49  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getNumIntegrators;
50  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_getStepSize;
51  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_setConstraintTolerance;
52  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_setCurrentIntegrator;
53  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_setIntegrationForceGroups;
54  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_setStepSize;
55  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_CompoundIntegrator_step;
56  
57  /**
58   * This class allows you to use multiple integration algorithms within a single simulation,
59   * switching back and forth between them.  To use it, create whatever other Integrators
60   * you need, then add all of them to a CompoundIntegrator:
61   * <pre>
62   *    CompoundIntegrator compoundIntegrator = new CompoundIntegrator();
63   *    compoundIntegrator.addIntegrator(new VerletIntegrator(0.001));
64   *    compoundIntegrator.addIntegrator(new LangevinIntegrator(300.0, 1.0, 0.001));
65   * </pre>
66   * <p>
67   * Next create a Context, specifying the CompoundIntegrator as the Integrator to use for
68   * the Context:
69   * <pre>
70   *     Context context = new Context(system, compoundIntegrator);
71   * </pre>
72   * <p>
73   * Finally, call setCurrentIntegrator() to set which Integrator is active.  That one will
74   * be used for all calls to step() until the next time you change it.
75   * <pre>
76   *     compoundIntegrator.setCurrentIntegrator(0);
77   *     compoundIntegrator.step(1000); // Take 1000 steps of Verlet dynamics
78   *     compoundIntegrator.setCurrentIntegrator(1);
79   *     compoundIntegrator.step(1000); // Take 1000 steps of Langevin dynamics
80   * </pre>
81   * <p>
82   * When switching between integrators, it is important to make sure they are compatible with
83   * each other, and that they will interpret the positions and velocities in the same way.
84   * Remember that leapfrog style integrators assume the positions and velocities are offset
85   * from each other by half a time step.  When switching between a leapfrog and non-leapfrog
86   * integrator, you must first adjust the velocities to avoid introducing error.  This is also
87   * true when switching between two leapfrog integrators that use different step sizes,
88   * since they will interpret the velocities as corresponding to different times.
89   */
90  public class CompoundIntegrator extends Integrator {
91  
92    /**
93     * Create a CompoundIntegrator.
94     */
95    public CompoundIntegrator() {
96      super(OpenMM_CompoundIntegrator_create());
97    }
98  
99    /**
100    * Add an Integrator to this CompoundIntegrator.  The Integrator object should have
101    * been created on the heap with the "new" operator.  The CompoundIntegrator takes over
102    * ownership of it, and deletes it when the CompoundIntegrator itself is deleted.
103    * All Integrators must be added before the Context is created.
104    *
105    * @param integrator the Integrator to add
106    * @return the index of the Integrator that was added
107    */
108   public int addIntegrator(Integrator integrator) {
109     return OpenMM_CompoundIntegrator_addIntegrator(pointer, integrator.getPointer());
110   }
111 
112   /**
113    * Destroy the integrator.
114    */
115   @Override
116   public void destroy() {
117     if (pointer != null) {
118       OpenMM_CompoundIntegrator_destroy(pointer);
119       pointer = null;
120     }
121   }
122 
123   /**
124    * Get the distance tolerance within which constraints are maintained, as a fraction of the constrained distance.
125    * This method calls getConstraintTolerance() on whichever Integrator has been set as current.
126    */
127   @Override
128   public double getConstraintTolerance() {
129     return OpenMM_CompoundIntegrator_getConstraintTolerance(pointer);
130   }
131 
132   /**
133    * Get the index of the current Integrator.
134    */
135   public int getCurrentIntegrator() {
136     return OpenMM_CompoundIntegrator_getCurrentIntegrator(pointer);
137   }
138 
139   /**
140    * Get which force groups to use for integration.  By default, all force groups
141    * are included.  This is interpreted as a set of bit flags: the forces from group i
142    * will be included if (groups&amp;(1&lt;&lt;i)) != 0.
143    * <p>
144    * This method returns the integration force groups for the current Integrator.
145    */
146   @Override
147   public int getIntegrationForceGroups() {
148     return OpenMM_CompoundIntegrator_getIntegrationForceGroups(pointer);
149   }
150 
151   /**
152    * Get a reference to one of the Integrators that have been added to this CompoundIntegrator.
153    *
154    * @param index the index of the Integrator to get
155    */
156   public PointerByReference getIntegrator(int index) {
157     return OpenMM_CompoundIntegrator_getIntegrator(pointer, index);
158   }
159 
160   /**
161    * Get the number of Integrators that have been added to this CompoundIntegrator.
162    */
163   public int getNumIntegrators() {
164     return OpenMM_CompoundIntegrator_getNumIntegrators(pointer);
165   }
166 
167   /**
168    * Get the size of each time step, in picoseconds.  This method calls getStepSize() on
169    * whichever Integrator has been set as current.
170    *
171    * @return the step size, measured in ps
172    */
173   @Override
174   public double getStepSize() {
175     return OpenMM_CompoundIntegrator_getStepSize(pointer);
176   }
177 
178   /**
179    * Set the distance tolerance within which constraints are maintained, as a fraction of the constrained distance.
180    * This method calls setConstraintTolerance() on whichever Integrator has been set as current.
181    */
182   @Override
183   public void setConstraintTolerance(double tol) {
184     OpenMM_CompoundIntegrator_setConstraintTolerance(pointer, tol);
185   }
186 
187   /**
188    * Set the current Integrator.
189    *
190    * @param index the index of the Integrator to use
191    */
192   public void setCurrentIntegrator(int index) {
193     OpenMM_CompoundIntegrator_setCurrentIntegrator(pointer, index);
194   }
195 
196   /**
197    * Set which force groups to use for integration.  By default, all force groups
198    * are included.  This is interpreted as a set of bit flags: the forces from group i
199    * will be included if (groups&amp;(1&lt;&lt;i)) != 0.
200    * <p>
201    * Calling this method sets the integration force groups for all Integrators
202    * contained in this CompoundIntegrator.
203    */
204   @Override
205   public void setIntegrationForceGroups(int groups) {
206     OpenMM_CompoundIntegrator_setIntegrationForceGroups(pointer, groups);
207   }
208 
209   /**
210    * Set the size of each time step, in picoseconds.  This method calls setStepSize() on
211    * whichever Integrator has been set as current.
212    *
213    * @param size the step size, measured in ps
214    */
215   @Override
216   public void setStepSize(double size) {
217     OpenMM_CompoundIntegrator_setStepSize(pointer, size);
218   }
219 
220   /**
221    * Advance a simulation through time by taking a series of time steps.  This method
222    * calls step() on whichever Integrator has been set as current.
223    *
224    * @param steps the number of time steps to take
225    */
226   @Override
227   public void step(int steps) {
228     OpenMM_CompoundIntegrator_step(pointer, steps);
229   }
230 }