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.xray;
39
40 import static ffx.numerics.math.MatrixMath.determinant3;
41 import static ffx.numerics.math.ScalarMath.b2u;
42 import static ffx.numerics.math.ScalarMath.u2b;
43 import static ffx.utilities.Constants.KCAL_TO_GRAM_ANG2_PER_PS2;
44 import static ffx.utilities.Constants.kB;
45 import static java.lang.String.format;
46 import static java.lang.System.arraycopy;
47 import static java.util.Arrays.fill;
48 import static org.apache.commons.math3.util.FastMath.PI;
49
50 import ffx.crystal.Crystal;
51 import ffx.crystal.CrystalPotential;
52 import ffx.potential.bonded.Atom;
53 import ffx.potential.bonded.Bond;
54 import ffx.potential.bonded.LambdaInterface;
55 import ffx.potential.bonded.Molecule;
56 import ffx.potential.bonded.Residue;
57 import ffx.potential.parameters.ForceField;
58 import ffx.xray.RefinementMinimize.RefinementMode;
59 import java.util.List;
60 import java.util.logging.Logger;
61
62
63
64
65
66
67
68
69 public class XRayEnergy implements LambdaInterface, CrystalPotential {
70
71 private static final Logger logger = Logger.getLogger(XRayEnergy.class.getName());
72 private static final double kBkcal = kB / KCAL_TO_GRAM_ANG2_PER_PS2;
73 private static final double eightPI2 = 8.0 * PI * PI;
74 private static final double eightPI23 = eightPI2 * eightPI2 * eightPI2;
75
76 private final DiffractionData diffractionData;
77 private final RefinementModel refinementModel;
78 private final Atom[] activeAtomArray;
79 private final int nAtoms;
80 private final double bMass;
81 private final double kTbNonzero;
82 private final double kTbSimWeight;
83 private final double occMass;
84 private final boolean lambdaTerm;
85 private final double[] g2;
86 private final double[] dUdXdL;
87 protected double lambda = 1.0;
88 private int nXYZ;
89 private int nB;
90 private int nOCC;
91 private RefinementMode refinementMode;
92 private boolean refineXYZ = false;
93 private boolean refineOCC = false;
94 private boolean refineB = false;
95 private boolean xrayTerms = true;
96 private boolean restraintTerms = true;
97 private double[] optimizationScaling = null;
98 private double totalEnergy;
99 private double dEdL;
100 private STATE state = STATE.BOTH;
101
102
103
104
105
106
107
108
109
110
111
112 public XRayEnergy(
113 DiffractionData diffractionData, int nXYZ, int nB, int nOCC, RefinementMode refinementMode) {
114 this.diffractionData = diffractionData;
115 this.refinementModel = diffractionData.getRefinementModel();
116 this.refinementMode = refinementMode;
117 this.nXYZ = nXYZ;
118 this.nB = nB;
119 this.nOCC = nOCC;
120
121 Atom[] atomArray = refinementModel.getTotalAtomArray();
122 this.nAtoms = atomArray.length;
123
124 bMass = diffractionData.getbMass();
125 double temperature = 50.0;
126 kTbNonzero = 0.5 * kBkcal * temperature * diffractionData.getbNonZeroWeight();
127 kTbSimWeight = kBkcal * temperature * diffractionData.getbSimWeight();
128 occMass = diffractionData.getOccMass();
129
130 ForceField forceField = diffractionData.getAssembly()[0].getForceField();
131 lambdaTerm = forceField.getBoolean("LAMBDATERM", false);
132
133
134 int count = 0;
135 for (Atom a : atomArray) {
136 if (a.isActive()) {
137 count++;
138 }
139 }
140 activeAtomArray = new Atom[count];
141 count = 0;
142 for (Atom a : atomArray) {
143 if (a.isActive()) {
144 activeAtomArray[count++] = a;
145 }
146 }
147
148 dUdXdL = new double[count * 3];
149 g2 = new double[count * 3];
150
151 setRefinementBooleans();
152
153 if (refineB) {
154 logger.info(" B-Factor Refinement Parameters");
155 logger.info(" Temperature: " + temperature);
156 logger.info(" Non-zero restraint weight: " + diffractionData.getbNonZeroWeight());
157 logger.info(" Similarity restraint weight: " + diffractionData.getbSimWeight());
158 }
159 }
160
161
162 @Override
163 public boolean destroy() {
164 return diffractionData.destroy();
165 }
166
167
168 @Override
169 public double energy(double[] x) {
170 double e = 0.0;
171
172
173 unscaleCoordinates(x);
174
175 if (refineXYZ) {
176
177 diffractionData.setFFTCoordinates(x);
178 }
179 if (refineB) {
180
181 setBFactors(x);
182 }
183 if (refineOCC) {
184
185 setOccupancies(x);
186 }
187
188 if (xrayTerms) {
189
190 if (lambdaTerm) {
191 diffractionData.setLambdaTerm(false);
192 }
193
194
195 diffractionData.computeAtomicDensity();
196
197 e = diffractionData.computeLikelihood();
198
199 if (lambdaTerm) {
200
201
202 diffractionData.setLambdaTerm(true);
203
204
205 diffractionData.computeAtomicDensity();
206
207
208 double e2 = diffractionData.computeLikelihood();
209
210 dEdL = e - e2;
211
212 e = lambda * e + (1.0 - lambda) * e2;
213
214 diffractionData.setLambdaTerm(false);
215 }
216 }
217
218 if (restraintTerms) {
219 if (refineB) {
220
221 e += getBFactorRestraints();
222 }
223 }
224
225
226 scaleCoordinates(x);
227
228 totalEnergy = e;
229 return e;
230 }
231
232
233 @Override
234 public double energyAndGradient(double[] x, double[] g) {
235 double e = 0.0;
236
237
238 unscaleCoordinates(x);
239
240 if (refineXYZ) {
241 for (Atom a : activeAtomArray) {
242 a.setXYZGradient(0.0, 0.0, 0.0);
243 a.setLambdaXYZGradient(0.0, 0.0, 0.0);
244 }
245
246
247 diffractionData.setFFTCoordinates(x);
248 }
249
250 if (refineB) {
251 for (Atom a : activeAtomArray) {
252 a.setTempFactorGradient(0.0);
253 if (a.getAnisou(null) != null) {
254 if (a.getAnisouGradient(null) == null) {
255 double[] ganisou = new double[6];
256 a.setAnisouGradient(ganisou);
257 } else {
258 double[] ganisou = a.getAnisouGradient(null);
259 ganisou[0] = ganisou[1] = ganisou[2] = 0.0;
260 ganisou[3] = ganisou[4] = ganisou[5] = 0.0;
261 a.setAnisouGradient(ganisou);
262 }
263 }
264 }
265
266
267 setBFactors(x);
268 }
269
270 if (refineOCC) {
271 for (Atom a : activeAtomArray) {
272 a.setOccupancyGradient(0.0);
273 }
274
275
276 setOccupancies(x);
277 }
278
279 if (xrayTerms) {
280
281 if (lambdaTerm) {
282 diffractionData.setLambdaTerm(false);
283 }
284
285
286 diffractionData.computeAtomicDensity();
287
288
289 e = diffractionData.computeLikelihood();
290
291
292 diffractionData.computeAtomicGradients(refinementMode);
293
294 if (refineXYZ) {
295
296 getXYZGradients(g);
297 }
298
299 if (lambdaTerm) {
300
301 int n = dUdXdL.length;
302 arraycopy(g, 0, dUdXdL, 0, n);
303
304 for (Atom a : activeAtomArray) {
305 a.setXYZGradient(0.0, 0.0, 0.0);
306 a.setLambdaXYZGradient(0.0, 0.0, 0.0);
307 }
308
309
310 diffractionData.setLambdaTerm(true);
311
312
313 diffractionData.computeAtomicDensity();
314
315
316 double e2 = diffractionData.computeLikelihood();
317
318
319 diffractionData.computeAtomicGradients(refinementMode);
320
321 dEdL = e - e2;
322 e = lambda * e + (1.0 - lambda) * e2;
323 getXYZGradients(g2);
324 for (int i = 0; i < g.length; i++) {
325 dUdXdL[i] -= g2[i];
326 g[i] = lambda * g[i] + (1.0 - lambda) * g2[i];
327 }
328
329 diffractionData.setLambdaTerm(false);
330 }
331 }
332
333 if (restraintTerms) {
334 if (refineB) {
335
336 e += getBFactorRestraints();
337
338
339 getBFactorGradients(g);
340 }
341
342 if (refineOCC) {
343
344 getOccupancyGradients(g);
345 }
346 }
347
348
349 scaleCoordinatesAndGradient(x, g);
350
351 totalEnergy = e;
352 return e;
353 }
354
355
356 @Override
357 public double[] getAcceleration(double[] acceleration) {
358 throw new UnsupportedOperationException("Not supported yet.");
359 }
360
361
362 @Override
363 public double[] getCoordinates(double[] x) {
364 assert (x != null);
365 double[] xyz = new double[3];
366 int index = 0;
367 fill(x, 0.0);
368
369 if (refineXYZ) {
370 for (Atom a : activeAtomArray) {
371 a.getXYZ(xyz);
372 x[index++] = xyz[0];
373 x[index++] = xyz[1];
374 x[index++] = xyz[2];
375 }
376 }
377
378 if (refineB) {
379 double[] anisou = null;
380 int resnum = -1;
381 int nat = 0;
382 int nres = diffractionData.getnResidueBFactor() + 1;
383 for (Atom a : activeAtomArray) {
384
385 if (a.getAtomicNumber() == 1) {
386 continue;
387 }
388 if (a.getAnisou(null) != null) {
389 anisou = a.getAnisou(anisou);
390 x[index++] = anisou[0];
391 x[index++] = anisou[1];
392 x[index++] = anisou[2];
393 x[index++] = anisou[3];
394 x[index++] = anisou[4];
395 x[index++] = anisou[5];
396 } else if (diffractionData.isResidueBFactor()) {
397 if (resnum != a.getResidueNumber()) {
398 if (nres >= diffractionData.getnResidueBFactor()) {
399 if (resnum > -1 && index < nXYZ + nB - 1) {
400 x[index] /= nat;
401 index++;
402 }
403 nat = 1;
404 nres = 1;
405 } else {
406 nres++;
407 nat++;
408 }
409 x[index] += a.getTempFactor();
410 resnum = a.getResidueNumber();
411 } else {
412 x[index] += a.getTempFactor();
413 nat++;
414 }
415 } else {
416 x[index++] = a.getTempFactor();
417 }
418 }
419
420 if (diffractionData.isResidueBFactor()) {
421 if (nat > 1) {
422 x[index] /= nat;
423 }
424 }
425 }
426
427 if (refineOCC) {
428 for (List<Residue> list : refinementModel.getAltResidues()) {
429 for (Residue r : list) {
430 for (Atom a : r.getAtomList()) {
431 if (a.getOccupancy() < 1.0) {
432 x[index++] = a.getOccupancy();
433 break;
434 }
435 }
436 }
437 }
438 for (List<Molecule> list : refinementModel.getAltMolecules()) {
439 for (Molecule m : list) {
440 for (Atom a : m.getAtomList()) {
441 if (a.getOccupancy() < 1.0) {
442 x[index++] = a.getOccupancy();
443 break;
444 }
445 }
446 }
447 }
448 }
449
450 return x;
451 }
452
453
454 @Override
455 public Crystal getCrystal() {
456 return diffractionData.getCrystal()[0];
457 }
458
459
460 @Override
461 public void setCrystal(Crystal crystal) {
462 logger.severe(" XRayEnergy does implement setCrystal yet.");
463 }
464
465
466 @Override
467 public STATE getEnergyTermState() {
468 return state;
469 }
470
471
472 @Override
473 public void setEnergyTermState(STATE state) {
474 this.state = state;
475 switch (state) {
476 case FAST:
477 xrayTerms = false;
478 restraintTerms = true;
479 break;
480 case SLOW:
481 xrayTerms = true;
482 restraintTerms = false;
483 break;
484 default:
485 xrayTerms = true;
486 restraintTerms = true;
487 }
488 }
489
490
491 @Override
492 public double getLambda() {
493 return lambda;
494 }
495
496
497 @Override
498 public void setLambda(double lambda) {
499 if (lambda <= 1.0 && lambda >= 0.0) {
500 this.lambda = lambda;
501 } else {
502 String message = format("Lambda value %8.3f is not in the range [0..1].", lambda);
503 logger.warning(message);
504 }
505 }
506
507
508 @Override
509 public double[] getMass() {
510 double[] mass = new double[nXYZ + nB + nOCC];
511 int i = 0;
512 if (refineXYZ) {
513 for (Atom a : activeAtomArray) {
514 double m = a.getMass();
515 mass[i++] = m;
516 mass[i++] = m;
517 mass[i++] = m;
518 }
519 }
520
521 if (refineB) {
522 for (int j = i; j < nXYZ + nB; i++, j++) {
523 mass[j] = bMass;
524 }
525 }
526
527 if (refineOCC) {
528 for (int j = i; j < nXYZ + nB + nOCC; i++, j++) {
529 mass[j] = occMass;
530 }
531 }
532 return mass;
533 }
534
535
536
537
538
539
540 public int getNB() {
541 return nB;
542 }
543
544
545
546
547
548
549 public void setNB(int nB) {
550 this.nB = nB;
551 }
552
553
554
555
556
557
558 public int getNOcc() {
559 return nOCC;
560 }
561
562
563
564
565
566
567 public void setNOcc(int nOCC) {
568 this.nOCC = nOCC;
569 }
570
571
572
573
574
575
576 public int getNXYZ() {
577 return nXYZ;
578 }
579
580
581
582
583
584
585 public void setNXYZ(int nXYZ) {
586 this.nXYZ = nXYZ;
587 }
588
589
590 @Override
591 public int getNumberOfVariables() {
592 return nXYZ + nB + nOCC;
593 }
594
595
596 @Override
597 public double[] getPreviousAcceleration(double[] previousAcceleration) {
598 throw new UnsupportedOperationException("Not supported yet.");
599 }
600
601
602
603
604
605
606 public RefinementMode getRefinementMode() {
607 return refinementMode;
608 }
609
610
611
612
613
614
615 public void setRefinementMode(RefinementMode refinementmode) {
616 this.refinementMode = refinementmode;
617 setRefinementBooleans();
618 }
619
620
621 @Override
622 public double[] getScaling() {
623 return optimizationScaling;
624 }
625
626
627 @Override
628 public void setScaling(double[] scaling) {
629 optimizationScaling = scaling;
630 }
631
632
633 @Override
634 public double getTotalEnergy() {
635 return totalEnergy;
636 }
637
638
639
640
641
642
643 @Override
644 public VARIABLE_TYPE[] getVariableTypes() {
645 VARIABLE_TYPE[] vtypes = new VARIABLE_TYPE[nXYZ + nB + nOCC];
646 int i = 0;
647 if (refineXYZ) {
648 for (Atom a : activeAtomArray) {
649 vtypes[i++] = VARIABLE_TYPE.X;
650 vtypes[i++] = VARIABLE_TYPE.Y;
651 vtypes[i++] = VARIABLE_TYPE.Z;
652 }
653 }
654
655 if (refineB) {
656 for (int j = i; j < nXYZ + nB; i++, j++) {
657 vtypes[j] = VARIABLE_TYPE.OTHER;
658 }
659 }
660
661 if (refineOCC) {
662 for (int j = i; j < nXYZ + nB + nOCC; i++, j++) {
663 vtypes[j] = VARIABLE_TYPE.OTHER;
664 }
665 }
666 return vtypes;
667 }
668
669
670 @Override
671 public double[] getVelocity(double[] velocity) {
672 throw new UnsupportedOperationException("Not supported yet.");
673 }
674
675
676 @Override
677 public double getd2EdL2() {
678 return 0.0;
679 }
680
681
682 @Override
683 public double getdEdL() {
684 return dEdL;
685 }
686
687
688 @Override
689 public void getdEdXdL(double[] gradient) {
690 int n = dUdXdL.length;
691 arraycopy(dUdXdL, 0, gradient, 0, n);
692 }
693
694
695 @Override
696 public void setAcceleration(double[] acceleration) {
697 throw new UnsupportedOperationException("Not supported yet.");
698 }
699
700
701
702
703
704
705 public void setCoordinates(double[] x) {
706 assert (x != null);
707 double[] xyz = new double[3];
708 int index = 0;
709 for (Atom a : activeAtomArray) {
710 xyz[0] = x[index++];
711 xyz[1] = x[index++];
712 xyz[2] = x[index++];
713 a.moveTo(xyz);
714 }
715 }
716
717
718
719
720
721
722 public void setOccupancies(double[] x) {
723 double occ;
724 int index = nXYZ + nB;
725 for (List<Residue> list : refinementModel.getAltResidues()) {
726 for (Residue r : list) {
727 occ = x[index++];
728 for (Atom a : r.getAtomList()) {
729 if (a.getOccupancy() < 1.0) {
730 a.setOccupancy(occ);
731 }
732 }
733 }
734 }
735 for (List<Molecule> list : refinementModel.getAltMolecules()) {
736 for (Molecule m : list) {
737 occ = x[index++];
738 for (Atom a : m.getAtomList()) {
739 if (a.getOccupancy() < 1.0) {
740 a.setOccupancy(occ);
741 }
742 }
743 }
744 }
745 }
746
747
748 @Override
749 public void setPreviousAcceleration(double[] previousAcceleration) {
750 throw new UnsupportedOperationException("Not supported yet.");
751 }
752
753
754 @Override
755 public void setVelocity(double[] velocity) {
756 throw new UnsupportedOperationException("Not supported yet.");
757 }
758
759
760
761
762
763 private void setRefinementBooleans() {
764
765 refineXYZ = false;
766 refineB = false;
767 refineOCC = false;
768
769 if (refinementMode == RefinementMode.COORDINATES
770 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS
771 || refinementMode == RefinementMode.COORDINATES_AND_OCCUPANCIES
772 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS_AND_OCCUPANCIES) {
773 refineXYZ = true;
774 }
775
776 if (refinementMode == RefinementMode.BFACTORS
777 || refinementMode == RefinementMode.BFACTORS_AND_OCCUPANCIES
778 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS
779 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS_AND_OCCUPANCIES) {
780 refineB = true;
781 }
782
783 if (refinementMode == RefinementMode.OCCUPANCIES
784 || refinementMode == RefinementMode.BFACTORS_AND_OCCUPANCIES
785 || refinementMode == RefinementMode.COORDINATES_AND_OCCUPANCIES
786 || refinementMode == RefinementMode.COORDINATES_AND_BFACTORS_AND_OCCUPANCIES) {
787 refineOCC = true;
788 }
789 }
790
791
792
793
794
795
796 private void getBFactorGradients(double[] g) {
797 assert (g != null);
798 double[] grad = null;
799 int index = nXYZ;
800 int resnum = -1;
801 int nres = diffractionData.getnResidueBFactor() + 1;
802 for (Atom a : activeAtomArray) {
803
804 if (a.getAtomicNumber() == 1) {
805 continue;
806 }
807 if (a.getAnisou(null) != null) {
808 grad = a.getAnisouGradient(grad);
809 g[index++] = grad[0];
810 g[index++] = grad[1];
811 g[index++] = grad[2];
812 g[index++] = grad[3];
813 g[index++] = grad[4];
814 g[index++] = grad[5];
815 } else if (diffractionData.isResidueBFactor()) {
816 if (resnum != a.getResidueNumber()) {
817 if (nres >= diffractionData.getnResidueBFactor()) {
818 if (resnum > -1 && index < nXYZ + nB - 1) {
819 index++;
820 }
821 nres = 1;
822 } else {
823 nres++;
824 }
825 g[index] += a.getTempFactorGradient();
826 resnum = a.getResidueNumber();
827 } else {
828 g[index] += a.getTempFactorGradient();
829 }
830 } else {
831 g[index++] = a.getTempFactorGradient();
832 }
833 }
834 }
835
836
837
838
839
840
841
842 private void getOccupancyGradients(double[] g) {
843 double ave;
844 int index = nXYZ + nB;
845
846
847 for (List<Residue> list : refinementModel.getAltResidues()) {
848 ave = 0.0;
849 for (Residue r : list) {
850 for (Atom a : r.getAtomList()) {
851 if (a.getOccupancy() < 1.0) {
852 ave += a.getOccupancyGradient();
853 }
854 }
855 }
856
857
858
859
860 ave /= list.size();
861 for (Residue r : list) {
862 for (Atom a : r.getAtomList()) {
863 if (a.getOccupancy() < 1.0) {
864 g[index] += a.getOccupancyGradient();
865 }
866 }
867 if (list.size() > 1) {
868
869 g[index] -= ave;
870 }
871 index++;
872 }
873 }
874
875
876 for (List<Molecule> list : refinementModel.getAltMolecules()) {
877 ave = 0.0;
878 for (Molecule m : list) {
879 for (Atom a : m.getAtomList()) {
880 if (a.getOccupancy() < 1.0) {
881 ave += a.getOccupancyGradient();
882 }
883 }
884 }
885 ave /= list.size();
886 for (Molecule m : list) {
887 for (Atom a : m.getAtomList()) {
888 if (a.getOccupancy() < 1.0) {
889 g[index] += a.getOccupancyGradient();
890 }
891 }
892 if (list.size() > 1) {
893 g[index] -= ave;
894 }
895 index++;
896 }
897 }
898 }
899
900
901
902
903
904
905 private void getXYZGradients(double[] g) {
906 assert (g != null);
907 double[] grad = new double[3];
908 int index = 0;
909 for (Atom a : activeAtomArray) {
910 a.getXYZGradient(grad);
911 g[index++] = grad[0];
912 g[index++] = grad[1];
913 g[index++] = grad[2];
914 }
915 }
916
917
918
919
920
921
922 private void setBFactors(double[] x) {
923 double[] tmpanisou = new double[6];
924 int index = nXYZ;
925 int nneg = 0;
926 int resnum = -1;
927 int nres = diffractionData.getnResidueBFactor() + 1;
928 for (Atom a : activeAtomArray) {
929
930 if (a.getAtomicNumber() == 1) {
931 continue;
932 }
933 if (a.getAnisou(null) == null) {
934 double biso = x[index];
935 if (diffractionData.isResidueBFactor()) {
936 if (resnum != a.getResidueNumber()) {
937 if (nres >= diffractionData.getnResidueBFactor()) {
938 if (resnum > -1 && index < nXYZ + nB - 1) {
939 index++;
940 biso = x[index];
941 }
942 nres = 1;
943 } else {
944 nres++;
945 }
946 resnum = a.getResidueNumber();
947 }
948 } else {
949 index++;
950 }
951
952 if (biso > 0.0) {
953 a.setTempFactor(biso);
954 } else {
955 nneg++;
956 a.setTempFactor(0.01);
957 if (nneg < 5) {
958 logger.info(" Isotropic atom: " + a + " negative B factor");
959 }
960 }
961 } else {
962 double[] anisou = a.getAnisou(null);
963 tmpanisou[0] = x[index++];
964 tmpanisou[1] = x[index++];
965 tmpanisou[2] = x[index++];
966 tmpanisou[3] = x[index++];
967 tmpanisou[4] = x[index++];
968 tmpanisou[5] = x[index++];
969 double det = determinant3(tmpanisou);
970 if (det > 0.0) {
971 arraycopy(tmpanisou, 0, anisou, 0, 6);
972 a.setAnisou(anisou);
973 det = Math.pow(det, 0.3333);
974 a.setTempFactor(u2b(det));
975 } else {
976 nneg++;
977 a.setTempFactor(0.01);
978 anisou[0] = anisou[1] = anisou[2] = b2u(0.01);
979 anisou[3] = anisou[4] = anisou[5] = 0.0;
980 a.setAnisou(anisou);
981 if (nneg < 5) {
982 logger.info(" Anisotropic atom: " + a + " negative ANISOU");
983 }
984 }
985 }
986 }
987
988 if (nneg > 0) {
989 logger.info(
990 " "
991 + nneg
992 + " of "
993 + nAtoms
994 + " atoms with negative B factors! Attempting to correct.\n (If this problem persists, increase bsimweight)");
995 }
996
997
998 for (Atom a : activeAtomArray) {
999 if (a.getAtomicNumber() == 1) {
1000 Atom b = a.getBonds().get(0).get1_2(a);
1001 a.setTempFactor(b.getTempFactor());
1002 }
1003 }
1004 }
1005
1006
1007
1008
1009
1010
1011
1012 private double getBFactorRestraints() {
1013 Atom a1, a2;
1014 double b1, b2, bdiff;
1015 double[] anisou1 = null;
1016 double[] anisou2 = null;
1017 double gradb;
1018 double det1, det2;
1019 double[] gradu = new double[6];
1020 double e = 0.0;
1021
1022 for (Atom a : activeAtomArray) {
1023 double biso = a.getTempFactor();
1024
1025 if (a.getAtomicNumber() == 1) {
1026 continue;
1027 }
1028
1029 if (a.getAnisou(null) == null) {
1030
1031
1032 e += -3.0 * kTbNonzero * Math.log(biso / (4.0 * Math.PI));
1033 gradb = -3.0 * kTbNonzero / biso;
1034 a.addToTempFactorGradient(gradb);
1035
1036
1037 List<Bond> bonds = a.getBonds();
1038 for (Bond b : bonds) {
1039 if (a.compareTo(b.getAtom(0)) == 0) {
1040 a1 = b.getAtom(0);
1041 a2 = b.getAtom(1);
1042 } else {
1043 a1 = b.getAtom(1);
1044 a2 = b.getAtom(0);
1045 }
1046 if (a2.getAtomicNumber() == 1) {
1047 continue;
1048 }
1049 if (a2.getIndex() < a1.getIndex()) {
1050 continue;
1051 }
1052 if (!a1.getAltLoc().equals(' ')
1053 && !a1.getAltLoc().equals('A')
1054 && a2.getAltLoc().equals(' ')) {
1055 continue;
1056 }
1057
1058 b1 = a1.getTempFactor();
1059 b2 = a2.getTempFactor();
1060
1061 bdiff = b2u(b1 - b2);
1062 e += kTbSimWeight * Math.pow(bdiff, 2.0);
1063 gradb = 2.0 * kTbSimWeight * bdiff;
1064 a1.addToTempFactorGradient(gradb);
1065 a2.addToTempFactorGradient(-gradb);
1066 }
1067 } else {
1068
1069 anisou1 = a.getAnisou(anisou1);
1070 det1 = determinant3(anisou1);
1071
1072
1073 e += u2b(-kTbNonzero * Math.log(det1 * eightPI2 * Math.PI));
1074 gradu[0] = u2b(-kTbNonzero * ((anisou1[1] * anisou1[2] - anisou1[5] * anisou1[5]) / det1));
1075 gradu[1] = u2b(-kTbNonzero * ((anisou1[0] * anisou1[2] - anisou1[4] * anisou1[4]) / det1));
1076 gradu[2] = u2b(-kTbNonzero * ((anisou1[0] * anisou1[1] - anisou1[3] * anisou1[3]) / det1));
1077 gradu[3] =
1078 u2b(-kTbNonzero * ((2.0 * (anisou1[4] * anisou1[5] - anisou1[3] * anisou1[2])) / det1));
1079 gradu[4] =
1080 u2b(-kTbNonzero * ((2.0 * (anisou1[3] * anisou1[5] - anisou1[4] * anisou1[1])) / det1));
1081 gradu[5] =
1082 u2b(-kTbNonzero * ((2.0 * (anisou1[3] * anisou1[4] - anisou1[5] * anisou1[0])) / det1));
1083 a.addToAnisouGradient(gradu);
1084
1085
1086 List<Bond> bonds = a.getBonds();
1087 for (Bond b : bonds) {
1088 if (a.compareTo(b.getAtom(0)) == 0) {
1089 a1 = b.getAtom(0);
1090 a2 = b.getAtom(1);
1091 } else {
1092 a1 = b.getAtom(1);
1093 a2 = b.getAtom(0);
1094 }
1095 if (a2.getAtomicNumber() == 1) {
1096 continue;
1097 }
1098 if (a2.getIndex() < a1.getIndex()) {
1099 continue;
1100 }
1101 if (a2.getAnisou(null) == null) {
1102 continue;
1103 }
1104 if (!a1.getAltLoc().equals(' ')
1105 && !a1.getAltLoc().equals('A')
1106 && a2.getAltLoc().equals(' ')) {
1107 continue;
1108 }
1109
1110 anisou2 = a2.getAnisou(anisou2);
1111 det2 = determinant3(anisou2);
1112 bdiff = det1 - det2;
1113 e += eightPI23 * kTbSimWeight * Math.pow(bdiff, 2.0);
1114 gradb = eightPI23 * 2.0 * kTbSimWeight * bdiff;
1115
1116
1117 gradu[0] = gradb * (anisou1[1] * anisou1[2] - anisou1[5] * anisou1[5]);
1118 gradu[1] = gradb * (anisou1[0] * anisou1[2] - anisou1[4] * anisou1[4]);
1119 gradu[2] = gradb * (anisou1[0] * anisou1[1] - anisou1[3] * anisou1[3]);
1120 gradu[3] = gradb * (2.0 * (anisou1[4] * anisou1[5] - anisou1[3] * anisou1[2]));
1121 gradu[4] = gradb * (2.0 * (anisou1[3] * anisou1[5] - anisou1[4] * anisou1[1]));
1122 gradu[5] = gradb * (2.0 * (anisou1[3] * anisou1[4] - anisou1[5] * anisou1[0]));
1123 a1.addToAnisouGradient(gradu);
1124
1125
1126 gradu[0] = gradb * (anisou2[5] * anisou2[5] - anisou2[1] * anisou2[2]);
1127 gradu[1] = gradb * (anisou2[4] * anisou2[4] - anisou2[0] * anisou2[2]);
1128 gradu[2] = gradb * (anisou2[3] * anisou2[3] - anisou2[0] * anisou2[1]);
1129 gradu[3] = gradb * (2.0 * (anisou2[3] * anisou2[2] - anisou2[4] * anisou2[5]));
1130 gradu[4] = gradb * (2.0 * (anisou2[4] * anisou2[1] - anisou2[3] * anisou2[5]));
1131 gradu[5] = gradb * (2.0 * (anisou2[5] * anisou2[0] - anisou2[3] * anisou2[4]));
1132 a2.addToAnisouGradient(gradu);
1133 }
1134 }
1135 }
1136 return e;
1137 }
1138 }