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-2024.
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  import edu.uiowa.jopenmm.OpenMM_Vec3;
42  
43  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_applyConstraints;
44  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_create_2;
45  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_destroy;
46  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_getState;
47  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_reinitialize;
48  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_setParameter;
49  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_setPeriodicBoxVectors;
50  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_setPositions;
51  import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Context_setVelocities;
52  import static ffx.openmm.Vec3Array.toVec3Array;
53  
54  /**
55   * A Context stores the complete state of a simulation.  More specifically, it includes:
56   *
57   * <ul>
58   * <li>The current time</li>
59   * <li>The position of each particle</li>
60   * <li>The velocity of each particle</li>
61   * <li>The values of configurable parameters defined by Force objects in the System</li>
62   * </ul>
63   *
64   * You can retrieve a snapshot of the current state at any time by calling getState().  This
65   * allows you to record the state of the simulation at various points, either for analysis
66   * or for checkpointing.  getState() can also be used to retrieve the current forces on each
67   * particle and the current energy of the System.
68   */
69  public class Context {
70  
71    /**
72     * Context pointer.
73     */
74    private PointerByReference pointer;
75  
76    /**
77     * Constructor.
78     */
79    public Context() {
80      pointer = null;
81    }
82  
83    /**
84     * Constructor.
85     *
86     * @param system     The system to simulate.
87     * @param integrator The integrator to use for simulating the system.
88     * @param platform   The platform to use for performing computations.
89     */
90    public Context(System system, Integrator integrator, Platform platform) {
91      pointer = OpenMM_Context_create_2(system.getPointer(), integrator.getPointer(), platform.getPointer());
92    }
93  
94    /**
95     * Update the context.
96     *
97     * @param system     The system to simulate.
98     * @param integrator The integrator to use for simulating the system.
99     * @param platform   The platform to use for performing computations.
100    */
101   public void updateContext(System system, Integrator integrator, Platform platform) {
102     // Destroy the old context.
103     destroy();
104     pointer = OpenMM_Context_create_2(system.getPointer(), integrator.getPointer(), platform.getPointer());
105   }
106 
107   /**
108    * Get the pointer to the context.
109    *
110    * @return The pointer to the context.
111    */
112   public PointerByReference getPointer() {
113     return pointer;
114   }
115 
116   /**
117    * Does the context have a pointer?
118    *
119    * @return True if the context pointer is not null.
120    */
121   public boolean hasContextPointer() {
122     return pointer != null;
123   }
124 
125   /**
126    * Get the state of the context.
127    *
128    * @param types              The bit-flag of properties to include in the state.
129    * @param enforcePeriodicBox If true, the positions will be adjusted so atoms are inside the main periodic box.
130    * @return The state of the context.
131    */
132   public State getState(int types, int enforcePeriodicBox) {
133     return new State(OpenMM_Context_getState(pointer, types, enforcePeriodicBox));
134   }
135 
136   /**
137    * Reinitialize the context.
138    *
139    * <p>When a Context is created, it may cache information about the System being simulated and
140    * the Force objects contained in it. This means that, if the System or Forces are then modified,
141    * the Context might not see all changes. Call reinitialize() to force the Context to rebuild its
142    * internal representation of the System and pick up any changes that have been made.
143    *
144    * <p>This is an expensive operation, so you should try to avoid calling it too frequently.
145    *
146    * @param preserveState If true, the state will be restored to the same state it had before the call.
147    */
148   public void reinitialize(int preserveState) {
149     if (pointer != null) {
150       OpenMM_Context_reinitialize(pointer, preserveState);
151     }
152   }
153 
154   /**
155    * Set a parameter value.
156    *
157    * @param name  The name of the parameter.
158    * @param value The value of the parameter.
159    */
160   public void setParameter(String name, double value) {
161     OpenMM_Context_setParameter(pointer, name, value);
162   }
163 
164   /**
165    * Set the periodic box vectors.
166    *
167    * @param a The first vector.
168    * @param b The second vector.
169    * @param c The third vector.
170    */
171   public void setPeriodicBoxVectors(OpenMM_Vec3 a, OpenMM_Vec3 b, OpenMM_Vec3 c) {
172     OpenMM_Context_setPeriodicBoxVectors(pointer, a, b, c);
173   }
174 
175   /**
176    * Set the atomic positions.
177    *
178    * @param positions The atomic positions.
179    */
180   public void setPositions(double[] positions) {
181     Vec3Array vec3Array = toVec3Array(positions);
182     OpenMM_Context_setPositions(pointer, vec3Array.getPointer());
183     vec3Array.destroy();
184   }
185 
186   /**
187    * Set the atomic velocities.
188    *
189    * @param velocities The atomic velocities.
190    */
191   public void setVelocities(double[] velocities) {
192     Vec3Array velArray = toVec3Array(velocities);
193     OpenMM_Context_setVelocities(pointer, velArray.getPointer());
194     velArray.destroy();
195   }
196 
197   /**
198    * Apply constraints to the current positions.
199    *
200    * @param tol The constraint tolerance.
201    */
202   public void applyConstraints(double tol) {
203     OpenMM_Context_applyConstraints(pointer, tol);
204   }
205 
206   /**
207    * Destroy the context.
208    */
209   public void destroy() {
210     if (pointer != null) {
211       OpenMM_Context_destroy(pointer);
212       pointer = null;
213     }
214   }
215 
216 }