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.realspace;
39
40 import ffx.crystal.Crystal;
41 import ffx.crystal.CrystalPotential;
42 import ffx.potential.bonded.Atom;
43 import ffx.potential.bonded.LambdaInterface;
44 import ffx.xray.refine.RefinementModel;
45
46 import java.util.logging.Logger;
47
48 import static java.lang.String.format;
49
50
51
52
53
54
55
56
57 public class RealSpaceEnergy implements LambdaInterface, CrystalPotential {
58
59 private static final Logger logger = Logger.getLogger(RealSpaceEnergy.class.getName());
60
61
62
63
64 private final RealSpaceData realSpaceData;
65
66
67
68 private final RefinementModel refinementModel;
69
70
71
72 protected double lambda = 1.0;
73
74
75
76 private final int nXYZ;
77
78
79
80 private double[] optimizationScaling = null;
81
82
83
84 private double totalEnergy;
85
86
87
88 private STATE state = STATE.BOTH;
89
90
91
92
93
94
95 public RealSpaceEnergy(RealSpaceData realSpaceData) {
96 this.realSpaceData = realSpaceData;
97 refinementModel = realSpaceData.getRefinementModel();
98 nXYZ = refinementModel.getNumCoordParameters();
99 }
100
101
102
103
104 @Override
105 public boolean destroy() {
106 return realSpaceData.destroy();
107 }
108
109
110
111
112
113
114 @Override
115 public double energy(double[] x) {
116
117 unscaleCoordinates(x);
118
119
120 refinementModel.setParameters(x);
121
122
123 double e = realSpaceData.computeRealSpaceTarget();
124
125
126 scaleCoordinates(x);
127
128 totalEnergy = e;
129 return e;
130 }
131
132
133
134
135 @Override
136 public double energyAndGradient(double[] x, double[] g) {
137
138 unscaleCoordinates(x);
139
140
141 refinementModel.setParameters(x);
142
143
144 refinementModel.zeroGradient();
145
146
147 double e = realSpaceData.computeRealSpaceTarget();
148
149
150 refinementModel.getGradient(g);
151
152
153 scaleCoordinatesAndGradient(x, g);
154
155 totalEnergy = e;
156 return e;
157 }
158
159
160
161
162 @Override
163 public double[] getAcceleration(double[] acceleration) {
164 int n = getNumberOfVariables();
165 if (acceleration == null || acceleration.length < n) {
166 acceleration = new double[n];
167 }
168 int index = 0;
169 double[] acc = new double[3];
170 for (Atom a : refinementModel.getActiveAtoms()) {
171 a.getAcceleration(acc);
172 acceleration[index++] = acc[0];
173 acceleration[index++] = acc[1];
174 acceleration[index++] = acc[2];
175 }
176 return acceleration;
177 }
178
179
180
181
182 @Override
183 public double[] getCoordinates(double[] x) {
184 int n = getNumberOfVariables();
185 if (x == null || x.length < n) {
186 x = new double[n];
187 }
188 int index = 0;
189 for (Atom a : refinementModel.getActiveAtoms()) {
190 x[index++] = a.getX();
191 x[index++] = a.getY();
192 x[index++] = a.getZ();
193 }
194 return x;
195 }
196
197
198
199
200 @Override
201 public ffx.crystal.Crystal getCrystal() {
202 realSpaceData.getCrystal();
203 return null;
204 }
205
206
207
208
209 @Override
210 public void setCrystal(Crystal crystal) {
211 logger.severe(" RealSpaceEnergy does implement setCrystal yet.");
212 }
213
214
215
216
217 @Override
218 public STATE getEnergyTermState() {
219 return state;
220 }
221
222
223
224
225 @Override
226 public void setEnergyTermState(STATE state) {
227 this.state = state;
228 }
229
230
231
232
233 @Override
234 public double getLambda() {
235 return lambda;
236 }
237
238
239
240
241 @Override
242 public void setLambda(double lambda) {
243 if (lambda <= 1.0 && lambda >= 0.0) {
244 this.lambda = lambda;
245 realSpaceData.setLambda(lambda);
246 } else {
247 String message = format(" Lambda value %8.3f is not in the range [0..1].", lambda);
248 logger.warning(message);
249 }
250 }
251
252
253
254
255 @Override
256 public double[] getMass() {
257 double[] mass = new double[nXYZ];
258 refinementModel.getMass(mass);
259 return mass;
260 }
261
262
263
264
265 @Override
266 public int getNumberOfVariables() {
267 return nXYZ;
268 }
269
270
271
272
273 @Override
274 public double[] getPreviousAcceleration(double[] previousAcceleration) {
275 int n = getNumberOfVariables();
276 if (previousAcceleration == null || previousAcceleration.length < n) {
277 previousAcceleration = new double[n];
278 }
279 int index = 0;
280 double[] prev = new double[3];
281 for (Atom a : refinementModel.getActiveAtoms()) {
282 a.getPreviousAcceleration(prev);
283 previousAcceleration[index++] = prev[0];
284 previousAcceleration[index++] = prev[1];
285 previousAcceleration[index++] = prev[2];
286 }
287 return previousAcceleration;
288 }
289
290
291
292
293 @Override
294 public double[] getScaling() {
295 return optimizationScaling;
296 }
297
298
299
300
301 @Override
302 public void setScaling(double[] scaling) {
303 optimizationScaling = scaling;
304 }
305
306
307
308
309 @Override
310 public double getTotalEnergy() {
311 return totalEnergy;
312 }
313
314
315
316
317
318
319 @Override
320 public VARIABLE_TYPE[] getVariableTypes() {
321 int nActive = refinementModel.getActiveAtoms().length;
322 VARIABLE_TYPE[] type = new VARIABLE_TYPE[nActive * 3];
323 int index = 0;
324 for (int i = 0; i < nActive; i++) {
325 type[index++] = VARIABLE_TYPE.X;
326 type[index++] = VARIABLE_TYPE.Y;
327 type[index++] = VARIABLE_TYPE.Z;
328 }
329 return type;
330 }
331
332
333
334
335 @Override
336 public double[] getVelocity(double[] velocity) {
337 int n = getNumberOfVariables();
338 if (velocity == null || velocity.length < n) {
339 velocity = new double[n];
340 }
341 int index = 0;
342 double[] v = new double[3];
343 for (Atom a : refinementModel.getActiveAtoms()) {
344 a.getVelocity(v);
345 velocity[index++] = v[0];
346 velocity[index++] = v[1];
347 velocity[index++] = v[2];
348 }
349 return velocity;
350 }
351
352
353
354
355 @Override
356 public double getd2EdL2() {
357 return 0.0;
358 }
359
360
361
362
363 @Override
364 public double getdEdL() {
365 return realSpaceData.getdEdL();
366 }
367
368
369
370
371 @Override
372 public void getdEdXdL(double[] gradient) {
373 realSpaceData.getdEdXdL(gradient);
374 }
375
376
377
378
379 @Override
380 public void setAcceleration(double[] acceleration) {
381 if (acceleration == null) {
382 return;
383 }
384 int index = 0;
385 double[] accel = new double[3];
386 for (Atom a : refinementModel.getActiveAtoms()) {
387 accel[0] = acceleration[index++];
388 accel[1] = acceleration[index++];
389 accel[2] = acceleration[index++];
390 a.setAcceleration(accel);
391 }
392 }
393
394
395
396
397
398
399 public void setCoordinates(double[] x) {
400 if (x == null) {
401 return;
402 }
403 refinementModel.setParameters(x);
404 }
405
406
407
408
409 @Override
410 public void setPreviousAcceleration(double[] previousAcceleration) {
411 if (previousAcceleration == null) {
412 return;
413 }
414 int index = 0;
415 double[] prev = new double[3];
416 for (Atom a : refinementModel.getActiveAtoms()) {
417 prev[0] = previousAcceleration[index++];
418 prev[1] = previousAcceleration[index++];
419 prev[2] = previousAcceleration[index++];
420 a.setPreviousAcceleration(prev);
421 }
422 }
423
424
425
426
427 @Override
428 public void setVelocity(double[] velocity) {
429 if (velocity == null) {
430 return;
431 }
432 int index = 0;
433 double[] vel = new double[3];
434 for (Atom a : refinementModel.getActiveAtoms()) {
435 vel[0] = velocity[index++];
436 vel[1] = velocity[index++];
437 vel[2] = velocity[index++];
438 a.setVelocity(vel);
439 }
440 }
441 }