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 static java.lang.String.format;
41
42 import ffx.crystal.Crystal;
43 import ffx.crystal.CrystalPotential;
44 import ffx.potential.bonded.Atom;
45 import ffx.potential.bonded.LambdaInterface;
46 import ffx.xray.RefinementMinimize.RefinementMode;
47 import ffx.xray.RefinementModel;
48 import java.util.logging.Logger;
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 private final RealSpaceData realSpaceData;
63
64 private final RefinementModel refinementModel;
65
66 protected double lambda = 1.0;
67
68 private int nXYZ;
69
70 private RefinementMode refinementMode;
71
72 private boolean refineXYZ = false;
73
74 private double[] optimizationScaling = null;
75
76 private double totalEnergy;
77
78 private STATE state = STATE.BOTH;
79
80
81
82
83
84
85
86
87
88
89
90 public RealSpaceEnergy(
91 RealSpaceData realSpaceData, int nxyz, int nb, int nocc, RefinementMode refinementMode) {
92 this.realSpaceData = realSpaceData;
93 this.refinementModel = realSpaceData.getRefinementModel();
94 this.refinementMode = refinementMode;
95 this.nXYZ = nxyz;
96 setRefinementBooleans();
97 }
98
99
100 @Override
101 public boolean destroy() {
102 return realSpaceData.destroy();
103 }
104
105
106
107
108
109
110 @Override
111 public double energy(double[] x) {
112
113 double e = 0.0;
114
115
116 unscaleCoordinates(x);
117
118 if (refineXYZ) {
119 int index = 0;
120 double[] xyz = new double[3];
121 for (Atom a : refinementModel.getTotalAtomArray()) {
122 if (a.isActive()) {
123 int i = index * 3;
124 xyz[0] = x[i];
125 xyz[1] = x[i + 1];
126 xyz[2] = x[i + 2];
127 a.setXYZ(xyz);
128 a.setXYZGradient(0.0, 0.0, 0.0);
129 a.setLambdaXYZGradient(0.0, 0.0, 0.0);
130 index++;
131 }
132 }
133 }
134
135
136 if (refineXYZ) {
137 e = realSpaceData.computeRealSpaceTarget();
138 }
139
140
141 scaleCoordinates(x);
142
143 totalEnergy = e;
144 return e;
145 }
146
147
148 @Override
149 public double energyAndGradient(double[] x, double[] g) {
150 double e = 0.0;
151
152 unscaleCoordinates(x);
153
154 if (refineXYZ) {
155 int index = 0;
156 double[] xyz = new double[3];
157 for (Atom a : refinementModel.getTotalAtomArray()) {
158 if (a.isActive()) {
159 int i = index * 3;
160 xyz[0] = x[i];
161 xyz[1] = x[i + 1];
162 xyz[2] = x[i + 2];
163 a.setXYZ(xyz);
164 a.setXYZGradient(0.0, 0.0, 0.0);
165 a.setLambdaXYZGradient(0.0, 0.0, 0.0);
166 index++;
167 }
168 }
169 }
170
171
172 if (refineXYZ) {
173 e = realSpaceData.computeRealSpaceTarget();
174
175 getXYZGradients(g);
176 }
177
178
179 scaleCoordinatesAndGradient(x, g);
180
181 totalEnergy = e;
182 return e;
183 }
184
185
186 @Override
187 public double[] getAcceleration(double[] acceleration) {
188 int n = getNumberOfVariables();
189 if (acceleration == null || acceleration.length < n) {
190 acceleration = new double[n];
191 }
192 int index = 0;
193 double[] acc = new double[3];
194 for (Atom a : refinementModel.getTotalAtomArray()) {
195 if (a.isActive()) {
196 a.getAcceleration(acc);
197 acceleration[index++] = acc[0];
198 acceleration[index++] = acc[1];
199 acceleration[index++] = acc[2];
200 }
201 }
202 return acceleration;
203 }
204
205
206 @Override
207 public double[] getCoordinates(double[] x) {
208 int n = getNumberOfVariables();
209 if (x == null || x.length < n) {
210 x = new double[n];
211 }
212 int index = 0;
213 for (Atom a : refinementModel.getTotalAtomArray()) {
214 if (a.isActive()) {
215 x[index++] = a.getX();
216 x[index++] = a.getY();
217 x[index++] = a.getZ();
218 }
219 }
220 return x;
221 }
222
223
224 @Override
225 public ffx.crystal.Crystal getCrystal() {
226 realSpaceData.getCrystal();
227 return null;
228 }
229
230
231 @Override
232 public void setCrystal(Crystal crystal) {
233 logger.severe(" RealSpaceEnergy does implement setCrystal yet.");
234 }
235
236
237 @Override
238 public STATE getEnergyTermState() {
239 return state;
240 }
241
242
243 @Override
244 public void setEnergyTermState(STATE state) {
245 this.state = state;
246 }
247
248
249 @Override
250 public double getLambda() {
251 return lambda;
252 }
253
254
255 @Override
256 public void setLambda(double lambda) {
257 if (lambda <= 1.0 && lambda >= 0.0) {
258 this.lambda = lambda;
259 realSpaceData.setLambda(lambda);
260 } else {
261 String message = format(" Lambda value %8.3f is not in the range [0..1].", lambda);
262 logger.warning(message);
263 }
264 }
265
266
267 @Override
268 public double[] getMass() {
269 double[] mass = new double[nXYZ];
270 int i = 0;
271 if (refineXYZ) {
272 for (Atom a : refinementModel.getTotalAtomArray()) {
273 if (a.isActive()) {
274 double m = a.getMass();
275 mass[i++] = m;
276 mass[i++] = m;
277 mass[i++] = m;
278 }
279 }
280 }
281 return mass;
282 }
283
284
285 @Override
286 public int getNumberOfVariables() {
287 return nXYZ;
288 }
289
290
291 @Override
292 public double[] getPreviousAcceleration(double[] previousAcceleration) {
293 int n = getNumberOfVariables();
294 if (previousAcceleration == null || previousAcceleration.length < n) {
295 previousAcceleration = new double[n];
296 }
297 int index = 0;
298 double[] prev = new double[3];
299 for (Atom a : refinementModel.getTotalAtomArray()) {
300 if (a.isActive()) {
301 a.getPreviousAcceleration(prev);
302 previousAcceleration[index++] = prev[0];
303 previousAcceleration[index++] = prev[1];
304 previousAcceleration[index++] = prev[2];
305 }
306 }
307 return previousAcceleration;
308 }
309
310
311
312
313
314
315 public RefinementMode getRefinementMode() {
316 return refinementMode;
317 }
318
319
320
321
322
323
324 public void setRefinementMode(RefinementMode refinementMode) {
325 this.refinementMode = refinementMode;
326 setRefinementBooleans();
327 }
328
329
330 @Override
331 public double[] getScaling() {
332 return optimizationScaling;
333 }
334
335
336 @Override
337 public void setScaling(double[] scaling) {
338 optimizationScaling = scaling;
339 }
340
341
342 @Override
343 public double getTotalEnergy() {
344 return totalEnergy;
345 }
346
347
348
349
350
351
352 @Override
353 public VARIABLE_TYPE[] getVariableTypes() {
354
355 int nActive = 0;
356 for (Atom a : refinementModel.getTotalAtomArray()) {
357 if (a.isActive()) {
358 nActive++;
359 }
360 }
361
362 VARIABLE_TYPE[] type = new VARIABLE_TYPE[nActive * 3];
363
364 int index = 0;
365 for (int i = 0; i < nActive; i++) {
366 type[index++] = VARIABLE_TYPE.X;
367 type[index++] = VARIABLE_TYPE.Y;
368 type[index++] = VARIABLE_TYPE.Z;
369 }
370 return type;
371 }
372
373
374 @Override
375 public double[] getVelocity(double[] velocity) {
376 int n = getNumberOfVariables();
377 if (velocity == null || velocity.length < n) {
378 velocity = new double[n];
379 }
380 int index = 0;
381 double[] v = new double[3];
382 for (Atom a : refinementModel.getTotalAtomArray()) {
383 if (a.isActive()) {
384 a.getVelocity(v);
385 velocity[index++] = v[0];
386 velocity[index++] = v[1];
387 velocity[index++] = v[2];
388 }
389 }
390 return velocity;
391 }
392
393
394 @Override
395 public double getd2EdL2() {
396 return 0.0;
397 }
398
399
400 @Override
401 public double getdEdL() {
402 return realSpaceData.getdEdL();
403 }
404
405
406 @Override
407 public void getdEdXdL(double[] gradient) {
408 realSpaceData.getdEdXdL(gradient);
409 }
410
411
412 @Override
413 public void setAcceleration(double[] acceleration) {
414 if (acceleration == null) {
415 return;
416 }
417 int index = 0;
418 double[] accel = new double[3];
419 for (Atom a : refinementModel.getTotalAtomArray()) {
420 if (a.isActive()) {
421 accel[0] = acceleration[index++];
422 accel[1] = acceleration[index++];
423 accel[2] = acceleration[index++];
424 a.setAcceleration(accel);
425 }
426 }
427 }
428
429
430
431
432
433
434 public void setCoordinates(double[] x) {
435 assert (x != null);
436 double[] xyz = new double[3];
437 int index = 0;
438 for (Atom a : refinementModel.getTotalAtomArray()) {
439 if (a.isActive()) {
440 xyz[0] = x[index++];
441 xyz[1] = x[index++];
442 xyz[2] = x[index++];
443 a.moveTo(xyz);
444 }
445 }
446 }
447
448
449 @Override
450 public void setPreviousAcceleration(double[] previousAcceleration) {
451 if (previousAcceleration == null) {
452 return;
453 }
454 int index = 0;
455 double[] prev = new double[3];
456 for (Atom a : refinementModel.getTotalAtomArray()) {
457 if (a.isActive()) {
458 prev[0] = previousAcceleration[index++];
459 prev[1] = previousAcceleration[index++];
460 prev[2] = previousAcceleration[index++];
461 a.setPreviousAcceleration(prev);
462 }
463 }
464 }
465
466
467 @Override
468 public void setVelocity(double[] velocity) {
469 if (velocity == null) {
470 return;
471 }
472 int index = 0;
473 double[] vel = new double[3];
474 for (Atom a : refinementModel.getTotalAtomArray()) {
475 if (a.isActive()) {
476 vel[0] = velocity[index++];
477 vel[1] = velocity[index++];
478 vel[2] = velocity[index++];
479 a.setVelocity(vel);
480 }
481 }
482 }
483
484
485
486
487
488 private void setRefinementBooleans() {
489 refineXYZ =
490 (refinementMode == RefinementMode.COORDINATES
491 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS
492 || refinementMode == RefinementMode.COORDINATES_AND_OCCUPANCIES
493 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS_AND_OCCUPANCIES);
494 }
495
496
497
498
499
500
501 private int getNXYZ() {
502 return nXYZ;
503 }
504
505
506
507
508
509
510 private void setNXYZ(int nxyz) {
511 this.nXYZ = nxyz;
512 }
513
514
515
516
517
518
519 private void getXYZGradients(double[] g) {
520 assert (g != null);
521 double[] grad = new double[3];
522 int index = 0;
523 for (Atom a : refinementModel.getTotalAtomArray()) {
524 if (a.isActive()) {
525 a.getXYZGradient(grad);
526 g[index++] = grad[0];
527 g[index++] = grad[1];
528 g[index++] = grad[2];
529 }
530 }
531 }
532 }