1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.algorithms.mc;
39
40 import ffx.algorithms.AlgorithmListener;
41 import ffx.algorithms.cli.DynamicsOptions;
42 import ffx.algorithms.dynamics.MDVerbosity;
43 import ffx.algorithms.dynamics.MDWriteAction;
44 import ffx.algorithms.dynamics.MolecularDynamics;
45 import ffx.algorithms.dynamics.MolecularDynamicsOpenMM;
46 import ffx.algorithms.dynamics.thermostats.Thermostat;
47 import ffx.crystal.Crystal;
48 import ffx.numerics.Potential;
49 import ffx.potential.MolecularAssembly;
50 import ffx.potential.SystemState;
51 import ffx.potential.parsers.DYNFilter;
52 import ffx.utilities.Constants;
53
54 import javax.annotation.Nullable;
55 import java.io.File;
56 import java.util.EnumSet;
57 import java.util.logging.Level;
58 import java.util.logging.Logger;
59
60 import static java.lang.Math.abs;
61 import static java.lang.Math.min;
62 import static java.lang.String.format;
63
64
65
66
67
68
69 public class MDMove implements MCMove {
70
71 private static final Logger logger = Logger.getLogger(MDMove.class.getName());
72
73
74
75
76 private final MolecularDynamics molecularDynamics;
77
78
79
80 private final long mdSteps;
81
82
83
84 private final double timeStep;
85
86
87
88 private final double printInterval;
89
90
91
92 private final double temperature;
93
94
95
96 private final double saveInterval;
97
98
99
100 private final Potential potential;
101
102
103
104 private int mdMoveCounter = 0;
105
106
107
108 private double energyChange;
109
110
111
112 private double energyDriftAbs;
113
114
115
116 private double energyDriftNet;
117
118
119
120 private double initialKinetic;
121
122
123
124 private double initialPotential;
125
126
127
128 private double initialTotal;
129
130 private File dynRestartFile;
131
132
133
134
135
136
137
138
139
140
141
142 public MDMove(MolecularAssembly assembly, Potential potentialEnergy, AlgorithmListener listener,
143 DynamicsOptions dynamics, long stepsPerCycle, @Nullable File dynRestartFile) {
144 this.potential = potentialEnergy;
145 molecularDynamics = MolecularDynamics.dynamicsFactory(assembly, potentialEnergy, listener,
146 dynamics.thermostat, dynamics.integrator);
147 molecularDynamics.setAutomaticWriteouts(false);
148
149 timeStep = dynamics.getDt();
150 double dtPs = timeStep * Constants.FSEC_TO_PSEC;
151 mdSteps = stepsPerCycle;
152
153 molecularDynamics.setVerbosityLevel(MDVerbosity.QUIET);
154 molecularDynamics.setObtainVelAcc(false);
155 molecularDynamics.setRestartFrequency(dynamics.getCheckpoint());
156 this.saveInterval = dynamics.getSnapshotInterval();
157
158 double requestedPrint = dynamics.getReport();
159 double maxPrintInterval = dtPs * mdSteps;
160
161 printInterval = min(requestedPrint, maxPrintInterval);
162 this.temperature = dynamics.getTemperature();
163
164 this.dynRestartFile = dynRestartFile;
165
166 if (this.dynRestartFile != null && this.dynRestartFile.exists()) {
167 molecularDynamics.setVerbosityLevel(MDVerbosity.SILENT);
168 molecularDynamics.dynamic(1, timeStep, printInterval, saveInterval, temperature, false, dynRestartFile);
169 collectEnergies();
170 revertMove();
171 molecularDynamics.setVerbosityLevel(MDVerbosity.QUIET);
172 }
173 }
174
175
176
177
178
179
180 public double getEnergyChange() {
181 return energyChange;
182 }
183
184 public double getInitialKinetic() {
185 return initialKinetic;
186 }
187
188 public double getInitialPotential() {
189 return initialPotential;
190 }
191
192 public double getInitialTotal() {
193 return initialTotal;
194 }
195
196
197
198
199
200
201 public double getKineticEnergy() {
202 return molecularDynamics.getKineticEnergy();
203 }
204
205 public MolecularDynamics getMD() {
206 return molecularDynamics;
207 }
208
209
210
211
212
213
214 public double getPotentialEnergy() {
215 return molecularDynamics.getPotentialEnergy();
216 }
217
218
219
220
221 @Override
222 public void move() {
223 move(MDVerbosity.QUIET);
224 }
225
226
227
228
229
230
231 public void move(MDVerbosity verbosityLevel) {
232 MDVerbosity origLevel = molecularDynamics.getVerbosityLevel();
233 molecularDynamics.setVerbosityLevel(verbosityLevel);
234 if (mdMoveCounter == 0 && dynRestartFile != null && dynRestartFile.exists()) {
235 molecularDynamics.dynamic(mdSteps, timeStep, printInterval, saveInterval, temperature, false, dynRestartFile);
236 } else {
237 molecularDynamics.dynamic(mdSteps, timeStep, printInterval, saveInterval, temperature, true, null);
238 }
239 mdMoveCounter++;
240 collectEnergies();
241 energyChange = molecularDynamics.getTotalEnergy() - initialTotal;
242
243 if (molecularDynamics instanceof MolecularDynamicsOpenMM && logger.isLoggable(Level.FINE)) {
244 energyDriftNet += energyChange;
245 energyDriftAbs += abs(energyChange);
246 double energyDriftAverageNet = energyDriftNet / mdMoveCounter;
247 double energyDriftAverageAbs = energyDriftAbs / mdMoveCounter;
248 logger.fine(format(" Mean signed/unsigned energy drift: %8.4f/%8.4f",
249 energyDriftAverageNet, energyDriftAverageAbs));
250
251 double dt = molecularDynamics.getTimeStep();
252 int intervalSteps = molecularDynamics.getIntervalSteps();
253 int nAtoms = potential.getNumberOfVariables() / 3;
254
255
256 double normalizedEnergyDriftNet = (energyDriftAverageNet / (dt * intervalSteps * nAtoms)) * 1000;
257 double normalizedEnergyDriftAbs = (energyDriftAverageAbs / (dt * intervalSteps * nAtoms)) * 1000;
258 logger.fine(format(" Mean singed/unsigned energy drift per psec per atom: %8.4f/%8.4f\n",
259 normalizedEnergyDriftNet, normalizedEnergyDriftAbs));
260 }
261 molecularDynamics.setVerbosityLevel(origLevel);
262 }
263
264
265
266
267 @Override
268 public void revertMove() {
269 try {
270 molecularDynamics.revertState();
271 } catch (Exception ex) {
272 logger.severe(" The MD state could not be reverted.");
273 }
274 }
275
276 public void setMDIntervalSteps(int intervalSteps) {
277 molecularDynamics.setIntervalSteps(intervalSteps);
278 }
279
280
281
282
283
284
285
286
287
288 public EnumSet<MDWriteAction> writeFilesForStep(long mdStep, boolean trySnapshot, boolean tryRestart) {
289 return molecularDynamics.writeFilesForStep(mdStep, trySnapshot, tryRestart);
290 }
291
292 private void collectEnergies() {
293 initialTotal = molecularDynamics.getInitialTotalEnergy();
294 initialKinetic = molecularDynamics.getInitialKineticEnergy();
295 initialPotential = molecularDynamics.getInitialPotentialEnergy();
296
297 assert abs(initialTotal) < 1.0E-3
298 || abs((initialKinetic + initialPotential - initialTotal) / initialTotal) < 1.0E-7;
299 }
300 }