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.potential;
39
40 import java.util.Arrays;
41
42 import static ffx.utilities.Constants.KCAL_TO_GRAM_ANG2_PER_PS2;
43 import static java.lang.System.arraycopy;
44
45 /**
46 * The current state of the molecular dynamics simulation.
47 */
48 public class SystemState {
49
50 /**
51 * Number of dynamics variables. The length of x, v, a, aPrevious, gradient, and mass.
52 */
53 protected final int numberOfVariables;
54 /**
55 * Coordinates.
56 */
57 protected final double[] x;
58 /**
59 * Velocities.
60 */
61 protected final double[] v;
62 /**
63 * Accelerations.
64 */
65 protected final double[] a;
66 /**
67 * Previous accelerations.
68 */
69 protected final double[] aPrevious;
70 /**
71 * The gradient.
72 */
73 protected final double[] gradient;
74 /**
75 * Mass for each degree of freedom.
76 */
77 protected final double[] mass;
78 /**
79 * Current temperature.
80 */
81 double temperature;
82 /**
83 * Current kinetic energy.
84 */
85 double kineticEnergy;
86 /**
87 * Current potential energy.
88 */
89 double potentialEnergy;
90
91 /**
92 * Constructor for MDState.
93 *
94 * @param numberOfVariables The number of variables.
95 */
96 public SystemState(int numberOfVariables) {
97 this.numberOfVariables = numberOfVariables;
98 x = new double[numberOfVariables];
99 v = new double[numberOfVariables];
100 a = new double[numberOfVariables];
101 aPrevious = new double[numberOfVariables];
102 gradient = new double[numberOfVariables];
103 mass = new double[numberOfVariables];
104 }
105
106 /**
107 * Get an unmodifiable view of the current state.
108 */
109 public UnmodifiableState getUnmodifiableState() {
110 return new UnmodifiableState(x, v, a, aPrevious, mass, gradient, kineticEnergy,
111 potentialEnergy, temperature);
112 }
113
114 /**
115 * Get the number of variables.
116 *
117 * @return The number of variables.
118 */
119 public int getNumberOfVariables() {
120 return numberOfVariables;
121 }
122
123 /**
124 * Revert the current state to the passed UnmodifiableState.
125 *
126 * @param state The state to revert to.
127 */
128 public void revertState(UnmodifiableState state) {
129 assert (state.x().length == numberOfVariables);
130 arraycopy(state.x(), 0, x, 0, numberOfVariables);
131 arraycopy(state.v(), 0, v, 0, numberOfVariables);
132 arraycopy(state.a(), 0, a, 0, numberOfVariables);
133 arraycopy(state.aPrevious(), 0, aPrevious, 0, numberOfVariables);
134 arraycopy(state.mass(), 0, mass, 0, numberOfVariables);
135 arraycopy(state.gradient(), 0, gradient, 0, numberOfVariables);
136 kineticEnergy = state.kineticEnergy();
137 potentialEnergy = state.potentialEnergy();
138 temperature = state.temperature();
139 }
140
141 /**
142 * Set the mass of each degree of freedom.
143 *
144 * @param mass The mass of each degree of freedom.
145 */
146 public void setMass(double[] mass) {
147 assert (mass.length == numberOfVariables);
148 arraycopy(mass, 0, this.mass, 0, numberOfVariables);
149 }
150
151 /**
152 * Set the coordinates via a copy of the passed array into the internal array.
153 *
154 * @param x The coordinates.
155 */
156 public void setCoordinates(double[] x) {
157 assert (x.length == numberOfVariables);
158 arraycopy(x, 0, this.x, 0, numberOfVariables);
159 }
160
161 /**
162 * Set the velocities via a copy of the passed array into the internal array.
163 *
164 * @param v The velocities.
165 */
166 public void setVelocities(double[] v) {
167 assert (v.length == numberOfVariables);
168 arraycopy(v, 0, this.v, 0, numberOfVariables);
169 }
170
171 /**
172 * Set the accelerations via a copy of the passed array into the internal array.
173 *
174 * @param a The accelerations.
175 */
176 public void setAccelerations(double[] a) {
177 assert (a.length == numberOfVariables);
178 arraycopy(a, 0, this.a, 0, numberOfVariables);
179 }
180
181 /**
182 * Set the previous accelerations via a copy of the passed array into the internal array.
183 *
184 * @param aPrevious The previous accelerations.
185 */
186 public void setPreviousAccelerations(double[] aPrevious) {
187 assert (aPrevious.length == numberOfVariables);
188 arraycopy(aPrevious, 0, this.aPrevious, 0, numberOfVariables);
189 }
190
191 /**
192 * Get a reference to the internal coordinates array.
193 *
194 * @return The coordinates.
195 */
196 public double[] x() {
197 return x;
198 }
199
200 /**
201 * Get a reference to the internal velocities array.
202 *
203 * @return The velocities.
204 */
205 public double[] v() {
206 return v;
207 }
208
209 /**
210 * Get a reference to the internal accelerations array.
211 *
212 * @return The accelerations.
213 */
214 public double[] a() {
215 return a;
216 }
217
218 /**
219 * Get a reference to the internal previous accelerations array.
220 *
221 * @return The previous accelerations.
222 */
223 public double[] aPrevious() {
224 return aPrevious;
225 }
226
227 /**
228 * Get a reference to the internal mass array.
229 *
230 * @return The mass.
231 */
232 public double[] getMass() {
233 return mass;
234 }
235
236 /**
237 * Get a reference to the internal gradient array.
238 *
239 * @return The gradient.
240 */
241 public double[] gradient() {
242 return gradient;
243 }
244
245 /**
246 * Get a copy of the internal coordinate array.
247 *
248 * @return The coordinates.
249 */
250 public double[] getCoordinatesCopy() {
251 return Arrays.copyOf(x, numberOfVariables);
252 }
253
254 /**
255 * Copy the current accelerations to the previous accelerations.
256 */
257 public void copyAccelerationsToPrevious() {
258 arraycopy(a, 0, aPrevious, 0, numberOfVariables);
259 }
260
261 /**
262 * Set the temperature.
263 *
264 * @param temperature The temperature.
265 */
266 public void setTemperature(double temperature) {
267 this.temperature = temperature;
268 }
269
270 /**
271 * Set the kinetic energy.
272 *
273 * @param kineticEnergy The kinetic energy.
274 */
275 public void setKineticEnergy(double kineticEnergy) {
276 this.kineticEnergy = kineticEnergy;
277 }
278
279 /**
280 * Set the potential energy.
281 *
282 * @param potentialEnergy The potential energy.
283 */
284 public void setPotentialEnergy(double potentialEnergy) {
285 this.potentialEnergy = potentialEnergy;
286 }
287
288 /**
289 * Get the temperature.
290 */
291 public double getTemperature() {
292 return temperature;
293 }
294
295 /**
296 * Get the kinetic energy.
297 */
298 public double getKineticEnergy() {
299 return kineticEnergy;
300 }
301
302 /**
303 * Get the potential energy.
304 */
305 public double getPotentialEnergy() {
306 return potentialEnergy;
307 }
308
309 /**
310 * Get the total energy as the sum of the kinetic and potential energies.
311 */
312 public double getTotalEnergy() {
313 return kineticEnergy + potentialEnergy;
314 }
315
316 /**
317 * Compute the kinetic energy from the current velocities and masses.
318 *
319 * @return The kinetic energy.
320 */
321 public double getKineticEnergyFromVelocities() {
322 double e = 0.0;
323 for (int i = 0; i < numberOfVariables; i++) {
324 double m = mass[i];
325 if (m > 0.0) {
326 double velocity = v[i];
327 double v2 = velocity * velocity;
328 e += m * v2;
329 }
330 }
331 e *= 0.5 / KCAL_TO_GRAM_ANG2_PER_PS2;
332 return e;
333 }
334
335 }