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