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.optimize;
39
40 import ffx.algorithms.AlgorithmListener;
41 import ffx.numerics.Potential;
42 import ffx.numerics.optimization.LineSearch;
43 import ffx.potential.ForceFieldEnergy;
44 import ffx.potential.MolecularAssembly;
45 import ffx.potential.bonded.Atom;
46 import ffx.potential.openmm.OpenMMContext;
47 import ffx.potential.openmm.OpenMMEnergy;
48 import ffx.potential.openmm.OpenMMState;
49
50 import java.util.logging.Logger;
51
52 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_State_DataType.OpenMM_State_Energy;
53 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_State_DataType.OpenMM_State_Forces;
54 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_State_DataType.OpenMM_State_Positions;
55 import static java.lang.Double.isInfinite;
56 import static java.lang.Double.isNaN;
57 import static java.lang.String.format;
58 import static org.apache.commons.math3.util.FastMath.sqrt;
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class MinimizeOpenMM extends Minimize {
76
77 private static final Logger logger = Logger.getLogger(MinimizeOpenMM.class.getName());
78
79
80
81
82
83
84 public MinimizeOpenMM(MolecularAssembly molecularAssembly) {
85 super(molecularAssembly, molecularAssembly.getPotentialEnergy(), null);
86 }
87
88
89
90
91
92
93
94 public MinimizeOpenMM(MolecularAssembly molecularAssembly, OpenMMEnergy openMMEnergy) {
95 super(molecularAssembly, openMMEnergy, null);
96 }
97
98
99
100
101
102
103
104
105 public MinimizeOpenMM(MolecularAssembly molecularAssembly, OpenMMEnergy openMMEnergy, AlgorithmListener algorithmListener) {
106 super(molecularAssembly, openMMEnergy, algorithmListener);
107 }
108
109
110
111
112
113
114
115
116
117
118 @Override
119 public Potential minimize(int m, double eps, int maxIterations) {
120 return minimize(eps, maxIterations);
121 }
122
123
124
125
126
127
128
129
130 @Override
131 public Potential minimize(double eps, int maxIterations) {
132
133 ForceFieldEnergy forceFieldEnergy = molecularAssembly.getPotentialEnergy();
134
135 if (forceFieldEnergy instanceof OpenMMEnergy openMMEnergy) {
136 time = -System.nanoTime();
137
138
139 Atom[] atoms = molecularAssembly.getAtomArray();
140 openMMEnergy.updateParameters(atoms);
141
142
143 openMMEnergy.setActiveAtoms();
144
145
146 openMMEnergy.getCoordinates(x);
147
148
149 double e = openMMEnergy.energy(x);
150 logger.info(format("\n Initial energy: %12.6f (kcal/mol)", e));
151
152
153 OpenMMContext openMMContext = openMMEnergy.getContext();
154 openMMContext.optimize(eps, maxIterations);
155
156
157 int mask = OpenMM_State_Energy | OpenMM_State_Positions | OpenMM_State_Forces;
158 OpenMMState openMMState = openMMContext.getOpenMMState(mask);
159 energy = openMMState.potentialEnergy;
160 openMMState.getActivePositions(x, atoms);
161 openMMState.getActiveGradient(grad, atoms);
162 openMMState.destroy();
163
164
165 double grad2 = 0;
166 for (int i = 0; i < n; i++) {
167 double gi = grad[i];
168 if (isNaN(gi) || isInfinite(gi)) {
169 String message = format(" The gradient of variable %d is %8.3f.", i, gi);
170 logger.warning(message);
171 }
172 grad2 += gi * gi;
173 }
174 rmsGradient = sqrt(grad2 / n);
175
176 double[] ffxGrad = new double[n];
177 double ffxEnergy = openMMEnergy.energyAndGradientFFX(x, ffxGrad);
178 double grmsFFX = 0.0;
179 for (int i = 0; i < n; i++) {
180 double gi = ffxGrad[i];
181 if (isNaN(gi) || isInfinite(gi)) {
182 String message = format(" The gradient of variable %d is %8.3f.", i, gi);
183 logger.warning(message);
184 }
185 grmsFFX += gi * gi;
186 }
187 grmsFFX = sqrt(grmsFFX / n);
188
189 time += System.nanoTime();
190 logger.info(format(" Final energy for OpenMM %12.6f vs. FFX %12.6f in %8.3f (sec).", energy, ffxEnergy, time * 1.0e-9));
191 logger.info(format(" Convergence criteria for OpenMM %12.6f vs. FFX %12.6f (kcal/mol/A).", rmsGradient, grmsFFX));
192 }
193
194 if (algorithmListener != null) {
195 algorithmListener.algorithmUpdate(molecularAssembly);
196 }
197
198 return forceFieldEnergy;
199 }
200
201
202
203
204
205
206 @Override
207 public boolean optimizationUpdate(int iteration, int nBFGS, int functionEvaluations,
208 double rmsGradient, double rmsCoordinateChange, double energy, double energyChange,
209 double angle, LineSearch.LineSearchResult lineSearchResult) {
210 logger.warning(" MinimizeOpenMM does not support updates at each optimization step.");
211 return false;
212 }
213 }