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.potential;
39
40 import edu.rit.pj.IntegerForLoop;
41 import edu.rit.pj.IntegerSchedule;
42 import edu.rit.pj.ParallelRegion;
43 import edu.rit.pj.ParallelTeam;
44 import edu.rit.pj.reduction.SharedDouble;
45 import ffx.crystal.Crystal;
46 import ffx.crystal.CrystalPotential;
47 import ffx.crystal.LatticeSystem;
48 import ffx.crystal.NCSCrystal;
49 import ffx.crystal.ReplicatesCrystal;
50 import ffx.crystal.SpaceGroup;
51 import ffx.crystal.SpaceGroupDefinitions;
52 import ffx.crystal.SymOp;
53 import ffx.numerics.Constraint;
54 import ffx.numerics.atomic.AtomicDoubleArray.AtomicDoubleArrayImpl;
55 import ffx.numerics.atomic.AtomicDoubleArray3D;
56 import ffx.numerics.math.Double3;
57 import ffx.numerics.switching.ConstantSwitch;
58 import ffx.numerics.switching.UnivariateFunctionFactory;
59 import ffx.numerics.switching.UnivariateSwitchingFunction;
60 import ffx.potential.bonded.Angle;
61 import ffx.potential.bonded.AngleTorsion;
62 import ffx.potential.bonded.Atom;
63 import ffx.potential.bonded.Bond;
64 import ffx.potential.bonded.BondedTerm;
65 import ffx.potential.bonded.ImproperTorsion;
66 import ffx.potential.bonded.LambdaInterface;
67 import ffx.potential.bonded.MSNode;
68 import ffx.potential.bonded.MultiResidue;
69 import ffx.potential.bonded.OutOfPlaneBend;
70 import ffx.potential.bonded.PiOrbitalTorsion;
71 import ffx.potential.bonded.RelativeSolvation;
72 import ffx.potential.bonded.RelativeSolvation.SolvationLibrary;
73 import ffx.potential.bonded.Residue;
74 import ffx.potential.bonded.RestrainDistance;
75 import ffx.potential.bonded.RestraintTorsion;
76 import ffx.potential.bonded.StretchBend;
77 import ffx.potential.bonded.StretchTorsion;
78 import ffx.potential.bonded.Torsion;
79 import ffx.potential.bonded.TorsionTorsion;
80 import ffx.potential.bonded.UreyBradley;
81 import ffx.potential.constraint.CcmaConstraint;
82 import ffx.potential.constraint.SettleConstraint;
83 import ffx.potential.extended.ExtendedSystem;
84 import ffx.potential.nonbonded.COMRestraint;
85 import ffx.potential.nonbonded.GeneralizedKirkwood;
86 import ffx.potential.nonbonded.NCSRestraint;
87 import ffx.potential.nonbonded.ParticleMeshEwald;
88 import ffx.potential.nonbonded.RestrainGroups;
89 import ffx.potential.nonbonded.RestrainPosition;
90 import ffx.potential.nonbonded.VanDerWaals;
91 import ffx.potential.nonbonded.VanDerWaalsTornado;
92 import ffx.potential.openmm.OpenMMEnergy;
93 import ffx.potential.parameters.AngleType;
94 import ffx.potential.parameters.AngleType.AngleMode;
95 import ffx.potential.parameters.BondType;
96 import ffx.potential.parameters.ForceField;
97 import ffx.potential.parameters.ForceField.ELEC_FORM;
98 import ffx.potential.parameters.OutOfPlaneBendType;
99 import ffx.potential.parameters.TorsionType;
100 import ffx.potential.utils.ConvexHullOps;
101 import ffx.potential.utils.EnergyException;
102 import ffx.potential.utils.PotentialsFunctions;
103 import ffx.potential.utils.PotentialsUtils;
104 import ffx.utilities.FFXProperty;
105 import org.apache.commons.configuration2.CompositeConfiguration;
106
107 import javax.annotation.Nullable;
108 import java.io.File;
109 import java.time.LocalDateTime;
110 import java.time.format.DateTimeFormatter;
111 import java.util.ArrayList;
112 import java.util.Arrays;
113 import java.util.Collections;
114 import java.util.HashSet;
115 import java.util.List;
116 import java.util.Set;
117 import java.util.logging.Level;
118 import java.util.logging.Logger;
119 import java.util.stream.Collectors;
120 import java.util.stream.Stream;
121
122 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_NmPerAngstrom;
123 import static ffx.potential.bonded.BondedTerm.removeNeuralNetworkTerms;
124 import static ffx.potential.nonbonded.RestrainPosition.parseRestrainPositions;
125 import static ffx.potential.nonbonded.VanDerWaalsForm.DEFAULT_VDW_CUTOFF;
126 import static ffx.potential.nonbonded.pme.EwaldParameters.DEFAULT_EWALD_CUTOFF;
127 import static ffx.potential.parameters.ForceField.toEnumForm;
128 import static ffx.potential.parsers.XYZFileFilter.isXYZ;
129 import static ffx.utilities.PropertyGroup.NonBondedCutoff;
130 import static ffx.utilities.PropertyGroup.PotentialFunctionSelection;
131 import static java.lang.Double.isInfinite;
132 import static java.lang.Double.isNaN;
133 import static java.lang.String.format;
134 import static java.lang.System.arraycopy;
135 import static java.util.Arrays.sort;
136 import static org.apache.commons.io.FilenameUtils.removeExtension;
137 import static org.apache.commons.math3.util.FastMath.PI;
138 import static org.apache.commons.math3.util.FastMath.max;
139 import static org.apache.commons.math3.util.FastMath.min;
140 import static org.apache.commons.math3.util.FastMath.sqrt;
141
142
143
144
145
146
147
148 public class ForceFieldEnergy implements CrystalPotential, LambdaInterface {
149
150
151
152
153 public static final double DEFAULT_CONSTRAINT_TOLERANCE = 1E-4;
154
155
156
157 private static final Logger logger = Logger.getLogger(ForceFieldEnergy.class.getName());
158
159
160
161 private static final double toSeconds = 1.0e-9;
162
163
164
165 protected final MolecularAssembly molecularAssembly;
166
167
168
169
170 public final double maxDebugGradient;
171
172
173
174 private final ParallelTeam parallelTeam;
175
176
177
178 private final NCSRestraint ncsRestraint;
179
180
181
182 private final COMRestraint comRestraint;
183
184
185
186 private final VanDerWaals vanderWaals;
187
188
189
190 private final ANIEnergy aniEnergy;
191
192 private final List<Constraint> constraints;
193
194 @FFXProperty(name = "vdw-cutoff", propertyGroup = NonBondedCutoff, defaultValue = "12.0", description = """
195 Sets the cutoff distance value in Angstroms for van der Waals potential energy interactions.
196 The energy for any pair of van der Waals sites beyond the cutoff distance will be set to zero.
197 Other properties can be used to define the smoothing scheme near the cutoff distance.
198 The default cutoff distance in the absence of the vdw-cutoff keyword is infinite for nonperiodic
199 systems and 12.0 for periodic systems.
200 """)
201 private double vdwCutoff;
202
203 @FFXProperty(name = "ewald-cutoff", propertyGroup = NonBondedCutoff, defaultValue = "7.0", description = """
204 Sets the value in Angstroms of the real-space distance cutoff for use during Ewald summation.
205 By default, in the absence of the ewald-cutoff property, a value of 7.0 is used.
206 """)
207 private double ewaldCutoff;
208
209 @FFXProperty(name = "gk-cutoff", propertyGroup = NonBondedCutoff, defaultValue = "12.0", description = """
210 Sets the value in Angstroms of the generalized Kirkwood distance cutoff for use
211 during implicit solvent simulations. By default, in the absence of the gk-cutoff property,
212 no cutoff is used under aperiodic boundary conditions and the vdw-cutoff is used under PBC.
213 """)
214 private double gkCutoff;
215
216 private static final double DEFAULT_LIST_BUFFER = 2.0;
217
218 @FFXProperty(name = "list-buffer", propertyGroup = NonBondedCutoff, defaultValue = "2.0", description = """
219 Sets the size of the neighbor list buffer in Angstroms for potential energy functions.
220 This value is added to the actual cutoff distance to determine which pairs will be kept on the neighbor list.
221 This buffer value is used for all potential function neighbor lists.
222 The default value in the absence of the list-buffer keyword is 2.0 Angstroms.
223 """)
224 private double listBuffer;
225
226
227
228
229 private final double cutOff2;
230
231
232
233 private final double cutoffPlusBuffer;
234
235
236
237 private final ParticleMeshEwald particleMeshEwald;
238
239
240
241 private final ELEC_FORM elecForm;
242
243
244
245 private final boolean nnTermOrig;
246
247
248
249 private final boolean bondTermOrig;
250
251
252
253 private final boolean angleTermOrig;
254
255
256
257 private final boolean stretchBendTermOrig;
258
259
260
261 private final boolean ureyBradleyTermOrig;
262
263
264
265 private final boolean outOfPlaneBendTermOrig;
266
267
268
269 private final boolean torsionTermOrig;
270
271
272
273 private final boolean stretchTorsionTermOrig;
274
275
276
277 private final boolean angleTorsionTermOrig;
278
279
280
281 private final boolean improperTorsionTermOrig;
282
283
284
285 private final boolean piOrbitalTorsionTermOrig;
286
287
288
289 private final boolean torsionTorsionTermOrig;
290
291
292
293 private final boolean restrainPositionTermOrig;
294
295
296
297 private final boolean restrainGroupTermOrig;
298
299
300
301 private final boolean restrainDistanceTermOrig;
302
303
304
305 private final boolean restrainTorsionTermOrig;
306
307
308
309
310 private final boolean vanderWaalsTermOrig;
311
312
313
314 private final boolean multipoleTermOrig;
315
316
317
318 private final boolean polarizationTermOrig;
319
320
321
322 private final boolean generalizedKirkwoodTermOrig;
323
324 private boolean esvTermOrig;
325
326
327
328 private final boolean rigidHydrogens;
329
330
331
332 private final boolean lambdaTorsions;
333
334
335
336 private final RelativeSolvation relativeSolvation;
337 private final boolean relativeSolvationTerm;
338 private final Platform platform = Platform.FFX;
339
340
341
342
343 @FFXProperty(name = "lambdaterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
344 defaultValue = "false", description = "Specifies use of the Lambda state variable.")
345 protected boolean lambdaTerm;
346
347
348
349 private double lambda = 1.0;
350
351
352
353 protected double[] optimizationScaling = null;
354
355
356
357 public boolean lambdaBondedTerms = false;
358
359
360
361 boolean lambdaAllBondedTerms = false;
362
363
364
365
366 boolean destroyed = false;
367
368
369
370
371 private STATE state = STATE.BOTH;
372
373
374
375 private Atom[] atoms;
376
377
378
379 private Bond[] bonds;
380
381
382
383 private Angle[] angles;
384
385
386
387 private StretchBend[] stretchBends;
388
389
390
391 private UreyBradley[] ureyBradleys;
392
393
394
395 private OutOfPlaneBend[] outOfPlaneBends;
396
397
398
399 private Torsion[] torsions;
400
401
402
403 private ImproperTorsion[] improperTorsions;
404
405
406
407 private PiOrbitalTorsion[] piOrbitalTorsions;
408
409
410
411 private TorsionTorsion[] torsionTorsions;
412
413
414
415 private StretchTorsion[] stretchTorsions;
416
417
418
419 private AngleTorsion[] angleTorsions;
420
421
422
423 private RestrainDistance[] restrainDistances;
424
425
426
427 private RestraintTorsion[] restrainTorsions;
428
429
430
431 private RestrainPosition[] restrainPositions;
432
433
434
435 private final RestrainGroups restrainGroups;
436
437
438
439
440 private int nAtoms;
441
442
443
444 private int nBonds;
445
446
447
448 private int nAngles;
449
450
451
452 private int nStretchBends;
453
454
455
456 private int nUreyBradleys;
457
458
459
460 private int nOutOfPlaneBends;
461
462
463
464 private int nTorsions;
465
466
467
468 private int nImproperTorsions;
469
470
471
472 private int nPiOrbitalTorsions;
473
474
475
476 private int nTorsionTorsions;
477
478
479
480 private int nAngleTorsions;
481
482
483
484 private int nStretchTorsions;
485
486
487
488 private int nRestrainDistances;
489
490
491
492 private int nRestrainTorsions;
493
494
495
496 private int nRestrainPositions;
497
498
499
500 private int nRestrainGroups;
501
502
503
504
505 private int nVanDerWaalInteractions;
506
507
508
509 private int nPermanentInteractions;
510
511
512
513 private int nGKInteractions;
514
515
516
517
518 private Crystal crystal;
519
520
521
522 private BondedRegion bondedRegion;
523
524
525
526
527 private boolean nnTerm;
528
529
530
531
532 @FFXProperty(name = "bondterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
533 defaultValue = "true", description = "Specifies use of the bond stretch potential.")
534 private boolean bondTerm;
535
536
537
538
539 @FFXProperty(name = "angleterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
540 defaultValue = "true", description = "Specifies use of the angle bend potential.")
541 private boolean angleTerm;
542
543
544
545
546 @FFXProperty(name = "strbndterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
547 defaultValue = "true", description = "Specifies use of the stretch-bend potential.")
548 private boolean stretchBendTerm;
549
550
551
552
553 @FFXProperty(name = "ureyterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
554 defaultValue = "true", description = "Specifies use of the Urey-Bradley potential.")
555 private boolean ureyBradleyTerm;
556
557
558
559
560 @FFXProperty(name = "opbendterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
561 defaultValue = "true", description = "Specifies use of the out-of-plane potential.")
562 private boolean outOfPlaneBendTerm;
563
564
565
566
567 @FFXProperty(name = "torsionterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
568 defaultValue = "true", description = "Specifies use of the torsional potential.")
569 private boolean torsionTerm;
570
571
572
573
574 @FFXProperty(name = "strtorterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
575 defaultValue = "true", description = "Specifies use of the stretch-torsion potential.")
576 private boolean stretchTorsionTerm;
577
578
579
580
581 @FFXProperty(name = "angtorterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
582 defaultValue = "true", description = "Specifies use of the angle-torsion potential.")
583 private boolean angleTorsionTerm;
584
585
586
587
588 @FFXProperty(name = "imptorterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
589 defaultValue = "true", description = "Specifies use of the improper torsion potential.")
590 private boolean improperTorsionTerm;
591
592
593
594
595 @FFXProperty(name = "pitorsterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
596 defaultValue = "true", description = "Specifies use of the pi-system torsion potential.")
597 private boolean piOrbitalTorsionTerm;
598
599
600
601
602 @FFXProperty(name = "tortorterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
603 defaultValue = "true", description = "Specifies use of the pi-system torsion potential.")
604 private boolean torsionTorsionTerm;
605
606
607
608
609 @FFXProperty(name = "vdwterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
610 defaultValue = "true", description = """
611 Specifies use of the vdw der Waals potential.
612 If set to false, all non-bonded terms are turned off.
613 """)
614 private boolean vanderWaalsTerm;
615
616
617
618
619 @FFXProperty(name = "mpoleterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
620 defaultValue = "true", description = """
621 Specifies use of the fixed charge electrostatic potential.
622 Setting mpoleterm to false also turns off polarization and generalized Kirkwood,
623 overriding the polarizeterm and gkterm properties.
624 """)
625 private boolean multipoleTerm;
626
627
628
629
630 @FFXProperty(name = "polarizeterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
631 defaultValue = "true", description = """
632 Specifies use of the polarizable electrostatic potential.
633 Setting polarizeterm to false overrides the polarization property.
634 """)
635 private boolean polarizationTerm;
636
637
638
639
640 @FFXProperty(name = "gkterm", clazz = Boolean.class, propertyGroup = PotentialFunctionSelection,
641 defaultValue = "false", description = "Specifies use of generalized Kirkwood electrostatics.")
642 private boolean generalizedKirkwoodTerm;
643
644
645
646
647 private boolean comTerm;
648
649
650
651 private boolean comTermOrig;
652
653
654
655 private boolean ncsTerm;
656
657
658
659 private boolean ncsTermOrig;
660
661
662
663 private boolean restrainDistanceTerm;
664
665
666
667 private boolean restrainTorsionTerm;
668
669
670
671 private boolean restrainPositionTerm;
672
673
674
675 private boolean restrainGroupTerm;
676
677
678
679
680 private double rigidScale;
681
682
683
684
685 private double nnEnergy;
686
687
688
689 private double bondEnergy;
690
691
692
693 private double bondRMSD;
694
695
696
697 private double angleEnergy;
698
699
700
701 private double angleRMSD;
702
703
704
705 private double stretchBendEnergy;
706
707
708
709 private double ureyBradleyEnergy;
710
711
712
713 private double outOfPlaneBendEnergy;
714
715
716
717 private double torsionEnergy;
718
719
720
721 private double stretchTorsionEnergy;
722
723
724
725 private double angleTorsionEnergy;
726
727
728
729 private double improperTorsionEnergy;
730
731
732
733 private double piOrbitalTorsionEnergy;
734
735
736
737 private double torsionTorsionEnergy;
738
739
740
741
742 private double restrainDistanceEnergy;
743
744
745
746 private double restrainPositionEnergy;
747
748
749
750 private double restrainGroupEnergy;
751
752
753
754 private double restrainTorsionEnergy;
755
756
757
758
759 private double totalBondedEnergy;
760
761
762
763 private double vanDerWaalsEnergy;
764
765
766
767 private double permanentMultipoleEnergy;
768
769
770
771 private double permanentRealSpaceEnergy;
772
773
774
775 private double polarizationEnergy;
776
777
778
779 private double totalMultipoleEnergy;
780
781
782
783 private double totalNonBondedEnergy;
784
785
786
787 private double solvationEnergy;
788
789
790
791 private double ncsEnergy;
792
793
794
795
796 private double comRestraintEnergy;
797
798
799
800 private double totalEnergy;
801
802
803
804
805 private long nnTime;
806
807
808
809 private long bondTime;
810
811
812
813 private long angleTime;
814
815
816
817 private long stretchBendTime;
818
819
820
821 private long ureyBradleyTime;
822
823
824
825 private long outOfPlaneBendTime;
826
827
828
829 private long torsionTime;
830
831
832
833 private long angleTorsionTime;
834
835
836
837 private long stretchTorsionTime;
838
839
840
841 private long piOrbitalTorsionTime;
842
843
844
845 private long improperTorsionTime;
846
847
848
849 private long torsionTorsionTime;
850
851
852
853 private long vanDerWaalsTime;
854
855
856
857 private long electrostaticTime;
858
859
860
861 private long restrainDistanceTime;
862
863
864
865 private long restrainTorsionTime;
866
867
868
869
870 private long comRestraintTime;
871
872
873
874 private long restrainGroupTime;
875
876
877
878 private long totalTime;
879
880
881
882 private double[] xyz;
883
884
885
886 private ExtendedSystem esvSystem = null;
887
888 private boolean esvTerm;
889 private double esvBias;
890
891
892
893 private long ncsTime;
894 private int nRelativeSolvations;
895
896
897
898 private long restrainPositionTime;
899
900 private double relativeSolvationEnergy;
901
902
903
904 private boolean printOnFailure;
905
906
907
908
909
910
911 protected ForceFieldEnergy(MolecularAssembly molecularAssembly) {
912 this(molecularAssembly, ParallelTeam.getDefaultThreadCount());
913 }
914
915
916
917
918
919
920
921 protected ForceFieldEnergy(MolecularAssembly molecularAssembly, int numThreads) {
922
923 this.molecularAssembly = molecularAssembly;
924 atoms = molecularAssembly.getAtomArray();
925 nAtoms = atoms.length;
926 xyz = new double[nAtoms * 3];
927
928
929 for (int i = 0; i < nAtoms; i++) {
930 int index = atoms[i].getXyzIndex() - 1;
931 assert (i == index);
932 }
933
934
935 int nThreads = min(nAtoms, numThreads);
936 parallelTeam = new ParallelTeam(nThreads);
937
938 ForceField forceField = molecularAssembly.getForceField();
939 CompositeConfiguration properties = forceField.getProperties();
940 String name = forceField.toString().toUpperCase();
941
942 logger.info(format(" Constructing Force Field %s", name));
943 logger.info(format("\n SMP threads: %10d", nThreads));
944
945
946 boolean standardizeAtomNames = properties.getBoolean("standardizeAtomNames", true);
947 if (standardizeAtomNames) {
948 molecularAssembly.renameWaterProtons();
949 }
950
951 nnTerm = forceField.getBoolean("NNTERM", false);
952
953 if (nnTerm) {
954 for (Atom atom : atoms) {
955 atom.setNeuralNetwork(true);
956 }
957 }
958 bondTerm = forceField.getBoolean("BONDTERM", true);
959 angleTerm = forceField.getBoolean("ANGLETERM", true);
960 stretchBendTerm = forceField.getBoolean("STRBNDTERM", true);
961 ureyBradleyTerm = forceField.getBoolean("UREYTERM", true);
962 outOfPlaneBendTerm = forceField.getBoolean("OPBENDTERM", true);
963 torsionTerm = forceField.getBoolean("TORSIONTERM", true);
964 stretchTorsionTerm = forceField.getBoolean("STRTORTERM", true);
965 angleTorsionTerm = forceField.getBoolean("ANGTORTERM", true);
966 piOrbitalTorsionTerm = forceField.getBoolean("PITORSTERM", true);
967 torsionTorsionTerm = forceField.getBoolean("TORTORTERM", true);
968 improperTorsionTerm = forceField.getBoolean("IMPROPERTERM", true);
969 vanderWaalsTerm = forceField.getBoolean("VDWTERM", true);
970
971 boolean tornadoVM = forceField.getBoolean("tornado", false);
972 if (vanderWaalsTerm && !tornadoVM) {
973 multipoleTerm = forceField.getBoolean("MPOLETERM", true);
974 if (multipoleTerm) {
975 String polarizeString = forceField.getString("POLARIZATION", "NONE");
976 boolean defaultPolarizeTerm = !polarizeString.equalsIgnoreCase("NONE");
977 polarizationTerm = forceField.getBoolean("POLARIZETERM", defaultPolarizeTerm);
978 generalizedKirkwoodTerm = forceField.getBoolean("GKTERM", false);
979 } else {
980
981 polarizationTerm = false;
982 generalizedKirkwoodTerm = false;
983 }
984 } else {
985
986 multipoleTerm = false;
987 polarizationTerm = false;
988 generalizedKirkwoodTerm = false;
989 }
990
991
992 lambdaTerm = forceField.getBoolean("LAMBDATERM", false);
993 comTerm = forceField.getBoolean("COMRESTRAINTERM", false);
994 lambdaTorsions = forceField.getBoolean("TORSION_LAMBDATERM", false);
995 printOnFailure = forceField.getBoolean("PRINT_ON_FAILURE", false);
996
997
998 if (properties.containsKey("restrain-distance")) {
999 restrainDistanceTerm = true;
1000 } else {
1001 restrainDistanceTerm = false;
1002 }
1003
1004
1005 if (properties.containsKey("restrain-torsion-cos")) {
1006 restrainTorsionTerm = true;
1007 } else {
1008 restrainTorsionTerm = false;
1009 }
1010
1011
1012 if (properties.containsKey("restrain-groups")) {
1013 restrainGroupTerm = true;
1014 } else {
1015 restrainGroupTerm = false;
1016 }
1017
1018
1019 if (properties.containsKey("restrain-position") || properties.containsKey("restrain-position-lambda")) {
1020 restrainPositionTerm = true;
1021 } else {
1022 restrainPositionTerm = false;
1023 }
1024
1025
1026
1027 nnTermOrig = nnTerm;
1028 bondTermOrig = bondTerm;
1029 angleTermOrig = angleTerm;
1030 stretchBendTermOrig = stretchBendTerm;
1031 ureyBradleyTermOrig = ureyBradleyTerm;
1032 outOfPlaneBendTermOrig = outOfPlaneBendTerm;
1033 torsionTermOrig = torsionTerm;
1034 angleTorsionTermOrig = angleTorsionTerm;
1035 stretchTorsionTermOrig = stretchTorsionTerm;
1036 improperTorsionTermOrig = improperTorsionTerm;
1037 piOrbitalTorsionTermOrig = piOrbitalTorsionTerm;
1038 torsionTorsionTermOrig = torsionTorsionTerm;
1039 vanderWaalsTermOrig = vanderWaalsTerm;
1040 multipoleTermOrig = multipoleTerm;
1041 polarizationTermOrig = polarizationTerm;
1042 generalizedKirkwoodTermOrig = generalizedKirkwoodTerm;
1043 ncsTermOrig = ncsTerm;
1044 comTermOrig = comTerm;
1045 restrainDistanceTermOrig = restrainDistanceTerm;
1046 restrainTorsionTermOrig = restrainTorsionTerm;
1047 restrainPositionTermOrig = restrainPositionTerm;
1048 restrainGroupTermOrig = restrainGroupTerm;
1049
1050
1051 String spacegroup;
1052 double a, b, c, alpha, beta, gamma;
1053 boolean aperiodic;
1054 try {
1055 spacegroup = forceField.getString("SPACEGROUP", "P 1");
1056 SpaceGroup sg = SpaceGroupDefinitions.spaceGroupFactory(spacegroup);
1057 LatticeSystem latticeSystem = sg.latticeSystem;
1058 a = forceField.getDouble("A_AXIS");
1059 aperiodic = false;
1060 b = forceField.getDouble("B_AXIS", latticeSystem.getDefaultBAxis(a));
1061 c = forceField.getDouble("C_AXIS", latticeSystem.getDefaultCAxis(a, b));
1062 alpha = forceField.getDouble("ALPHA", latticeSystem.getDefaultAlpha());
1063 beta = forceField.getDouble("BETA", latticeSystem.getDefaultBeta());
1064 gamma = forceField.getDouble("GAMMA", latticeSystem.getDefaultGamma());
1065 if (!sg.latticeSystem.validParameters(a, b, c, alpha, beta, gamma)) {
1066 logger.severe(" Check lattice parameters.");
1067 }
1068 if (a == 1.0 && b == 1.0 && c == 1.0) {
1069 String message = " A-, B-, and C-axis values equal to 1.0.";
1070 logger.info(message);
1071 throw new Exception(message);
1072 }
1073 if (a <= 0.0 || b <= 0.0 || c <= 0.0 || alpha <= 0.0 || beta <= 0.0 || gamma <= 0.0) {
1074
1075 String message = " Crystal parameters are not valid due to negative or zero value.";
1076 logger.warning(message);
1077 throw new Exception(message);
1078 }
1079 } catch (Exception e) {
1080 aperiodic = true;
1081
1082
1083 double maxR = 0.0;
1084 if (nAtoms < 10) {
1085 for (int i = 0; i < nAtoms - 1; i++) {
1086 Double3 xi = atoms[i].getXYZ();
1087 for (int j = 1; j < nAtoms; j++) {
1088 double r = atoms[j].getXYZ().dist(xi);
1089 maxR = max(r, maxR);
1090 }
1091 }
1092 } else {
1093 try {
1094 maxR = ConvexHullOps.maxDist(ConvexHullOps.constructHull(atoms));
1095 } catch (Exception ex) {
1096
1097 logger.info(" Convex Hull operation failed with message " + ex + "\n Trying brute force approach...");
1098 if(logger.isLoggable(Level.FINE)){
1099 logger.fine(Utilities.stackTraceToString(ex));
1100 }
1101 for (int i = 0; i < nAtoms - 1; i++) {
1102 Double3 xi = atoms[i].getXYZ();
1103 for (int j = 1; j < nAtoms; j++) {
1104 double r = atoms[j].getXYZ().dist(xi);
1105 maxR = max(r, maxR);
1106 }
1107 }
1108 }
1109 }
1110 maxR = max(10.0, maxR);
1111
1112 logger.info(format(" The system will be treated as aperiodic (max separation = %6.1f A).", maxR));
1113
1114
1115 forceField.addProperty("EWALD_ALPHA", "0.0");
1116
1117
1118 spacegroup = "P1";
1119 a = 2.0 * maxR;
1120 b = 2.0 * maxR;
1121 c = 2.0 * maxR;
1122 alpha = 90.0;
1123 beta = 90.0;
1124 gamma = 90.0;
1125 }
1126 Crystal unitCell = new Crystal(a, b, c, alpha, beta, gamma, spacegroup);
1127 unitCell.setAperiodic(aperiodic);
1128
1129
1130 vdwCutoff = DEFAULT_VDW_CUTOFF;
1131 ewaldCutoff = DEFAULT_EWALD_CUTOFF;
1132 gkCutoff = vdwCutoff;
1133 if (unitCell.aperiodic()) {
1134
1135 vdwCutoff = Double.POSITIVE_INFINITY;
1136 ewaldCutoff = Double.POSITIVE_INFINITY;
1137 gkCutoff = Double.POSITIVE_INFINITY;
1138 }
1139
1140 vdwCutoff = forceField.getDouble("VDW_CUTOFF", vdwCutoff);
1141 ewaldCutoff = forceField.getDouble("EWALD_CUTOFF", ewaldCutoff);
1142 gkCutoff = forceField.getDouble("GK_CUTOFF", gkCutoff);
1143
1144
1145 double nlistCutoff = vdwCutoff;
1146 if (multipoleTerm) {
1147 nlistCutoff = max(vdwCutoff, ewaldCutoff);
1148 }
1149 if (generalizedKirkwoodTerm) {
1150 nlistCutoff = max(nlistCutoff, gkCutoff);
1151 }
1152
1153
1154 boolean disabledNeighborUpdates = forceField.getBoolean("DISABLE_NEIGHBOR_UPDATES", false);
1155 if (disabledNeighborUpdates) {
1156 logger.info(format(" Neighbor list updates disabled; interactions will "
1157 + "only be calculated between atoms that started the simulation "
1158 + "within a radius of %9.3g Angstroms of each other.", nlistCutoff));
1159
1160 vdwCutoff = Double.POSITIVE_INFINITY;
1161 ewaldCutoff = Double.POSITIVE_INFINITY;
1162 gkCutoff = Double.POSITIVE_INFINITY;
1163 }
1164
1165 listBuffer = forceField.getDouble("LIST_BUFFER", DEFAULT_LIST_BUFFER);
1166 cutoffPlusBuffer = nlistCutoff + listBuffer;
1167 cutOff2 = 2.0 * cutoffPlusBuffer;
1168 unitCell = configureNCS(forceField, unitCell);
1169
1170
1171 if (!aperiodic) {
1172 this.crystal = ReplicatesCrystal.replicatesCrystalFactory(unitCell, cutOff2);
1173 logger.info(format("\n Density: %6.3f (g/cc)",
1174 crystal.getDensity(molecularAssembly.getMass())));
1175 logger.info(crystal.toString());
1176 } else {
1177 this.crystal = unitCell;
1178 }
1179
1180 if (!unitCell.aperiodic() && unitCell.spaceGroup.number == 1) {
1181 ncsTerm = forceField.getBoolean("NCSTERM", false);
1182 ncsTermOrig = ncsTerm;
1183 } else {
1184 ncsTerm = false;
1185 ncsTermOrig = false;
1186 }
1187
1188
1189 int nSpecial = checkForSpecialPositions(forceField);
1190
1191 rigidHydrogens = forceField.getBoolean("RIGID_HYDROGENS", false);
1192 rigidScale = forceField.getDouble("RIGID_SCALE", 10.0);
1193
1194 nRelativeSolvations = 0;
1195 String relSolvLibrary = forceField.getString("RELATIVE_SOLVATION", "NONE").toUpperCase();
1196 SolvationLibrary library = SolvationLibrary.valueOf(relSolvLibrary);
1197 if (library == SolvationLibrary.AUTO) {
1198 if (generalizedKirkwoodTerm && name.toUpperCase().contains("OPLS")) {
1199 library = SolvationLibrary.MACCALLUM_TIP4P;
1200
1201 } else if (generalizedKirkwoodTerm) {
1202 library = SolvationLibrary.GK;
1203 } else {
1204 library = SolvationLibrary.NONE;
1205 }
1206 }
1207 if (library != SolvationLibrary.NONE) {
1208 relativeSolvationTerm = true;
1209 relativeSolvation = new RelativeSolvation(library, forceField);
1210 } else {
1211 relativeSolvationTerm = false;
1212 relativeSolvation = null;
1213 }
1214
1215 boolean checkAllNodeCharges = forceField.getBoolean("CHECK_ALL_NODE_CHARGES", false);
1216
1217 if (rigidScale <= 1.0) {
1218 rigidScale = 1.0;
1219 }
1220
1221 logger.info("\n Bonded Terms");
1222 if (rigidHydrogens && rigidScale > 1.0) {
1223 logger.info(format(" Rigid hydrogens: %10.2f", rigidScale));
1224 }
1225
1226
1227 if (bondTerm) {
1228 List<Bond> bondList = molecularAssembly.getBondList();
1229 if (nnTerm) {
1230 removeNeuralNetworkTerms(bondList);
1231 }
1232 nBonds = bondList.size();
1233 bonds = bondList.toArray(new Bond[0]);
1234 sort(bonds);
1235 if (nBonds > 0) {
1236 logger.info(format(" Bonds: %10d", nBonds));
1237 }
1238 } else {
1239 nBonds = 0;
1240 bonds = null;
1241 }
1242
1243
1244 if (angleTerm) {
1245 List<Angle> angleList = molecularAssembly.getAngleList();
1246 if (nnTerm) {
1247 removeNeuralNetworkTerms(angleList);
1248 }
1249 nAngles = angleList.size();
1250 angles = angleList.toArray(new Angle[0]);
1251 sort(angles);
1252 if (nAngles > 0) {
1253 logger.info(format(" Angles: %10d", nAngles));
1254 }
1255 } else {
1256 nAngles = 0;
1257 angles = null;
1258 }
1259
1260
1261 if (stretchBendTerm) {
1262 List<StretchBend> stretchBendList = molecularAssembly.getStretchBendList();
1263 if (nnTerm) {
1264 removeNeuralNetworkTerms(stretchBendList);
1265 }
1266 nStretchBends = stretchBendList.size();
1267 stretchBends = stretchBendList.toArray(new StretchBend[0]);
1268 sort(stretchBends);
1269 if (nStretchBends > 0) {
1270 logger.info(format(" Stretch-Bends: %10d", nStretchBends));
1271 }
1272 } else {
1273 nStretchBends = 0;
1274 stretchBends = null;
1275 }
1276
1277
1278 if (ureyBradleyTerm) {
1279 List<UreyBradley> ureyBradleyList = molecularAssembly.getUreyBradleyList();
1280 if (nnTerm) {
1281 removeNeuralNetworkTerms(ureyBradleyList);
1282 }
1283 nUreyBradleys = ureyBradleyList.size();
1284 ureyBradleys = ureyBradleyList.toArray(new UreyBradley[0]);
1285 sort(ureyBradleys);
1286 if (nUreyBradleys > 0) {
1287 logger.info(format(" Urey-Bradleys: %10d", nUreyBradleys));
1288 }
1289 } else {
1290 nUreyBradleys = 0;
1291 ureyBradleys = null;
1292 }
1293
1294
1295 if (rigidHydrogens) {
1296 if (bonds != null) {
1297 for (Bond bond : bonds) {
1298 if (bond.containsHydrogen()) {
1299 bond.setRigidScale(rigidScale);
1300 }
1301 }
1302 }
1303 if (angles != null) {
1304 for (Angle angle : angles) {
1305 if (angle.containsHydrogen()) {
1306 angle.setRigidScale(rigidScale);
1307 }
1308 }
1309 }
1310 if (stretchBends != null) {
1311 for (StretchBend stretchBend : stretchBends) {
1312 if (stretchBend.containsHydrogen()) {
1313 stretchBend.setRigidScale(rigidScale);
1314 }
1315 }
1316 }
1317 if (ureyBradleys != null) {
1318 for (UreyBradley ureyBradley : ureyBradleys) {
1319 if (ureyBradley.containsHydrogen()) {
1320 ureyBradley.setRigidScale(rigidScale);
1321 }
1322 }
1323 }
1324 }
1325
1326
1327 if (outOfPlaneBendTerm) {
1328 List<OutOfPlaneBend> outOfPlaneBendList = molecularAssembly.getOutOfPlaneBendList();
1329 if (nnTerm) {
1330 removeNeuralNetworkTerms(outOfPlaneBendList);
1331 }
1332 nOutOfPlaneBends = outOfPlaneBendList.size();
1333 outOfPlaneBends = outOfPlaneBendList.toArray(new OutOfPlaneBend[0]);
1334 sort(outOfPlaneBends);
1335 if (nOutOfPlaneBends > 0) {
1336 logger.info(format(" Out-of-Plane Bends: %10d", nOutOfPlaneBends));
1337 }
1338 } else {
1339 nOutOfPlaneBends = 0;
1340 outOfPlaneBends = null;
1341 }
1342
1343
1344 if (torsionTerm) {
1345 List<Torsion> torsionList = molecularAssembly.getTorsionList();
1346 if (nnTerm) {
1347 removeNeuralNetworkTerms(torsionList);
1348 }
1349 nTorsions = torsionList.size();
1350 torsions = torsionList.toArray(new Torsion[0]);
1351 if (nTorsions > 0) {
1352 logger.info(format(" Torsions: %10d", nTorsions));
1353 }
1354 } else {
1355 nTorsions = 0;
1356 torsions = null;
1357 }
1358
1359
1360 if (stretchTorsionTerm) {
1361 List<StretchTorsion> stretchTorsionList = molecularAssembly.getStretchTorsionList();
1362 if (nnTerm) {
1363 removeNeuralNetworkTerms(stretchTorsionList);
1364 }
1365 nStretchTorsions = stretchTorsionList.size();
1366 stretchTorsions = stretchTorsionList.toArray(new StretchTorsion[0]);
1367 if (nStretchTorsions > 0) {
1368 logger.info(format(" Stretch-Torsions: %10d", nStretchTorsions));
1369 }
1370 } else {
1371 nStretchTorsions = 0;
1372 stretchTorsions = null;
1373 }
1374
1375
1376 if (angleTorsionTerm) {
1377 List<AngleTorsion> angleTorsionList = molecularAssembly.getAngleTorsionList();
1378 if (nnTerm) {
1379 removeNeuralNetworkTerms(angleTorsionList);
1380 }
1381 nAngleTorsions = angleTorsionList.size();
1382 angleTorsions = angleTorsionList.toArray(new AngleTorsion[0]);
1383 if (nAngleTorsions > 0) {
1384 logger.info(format(" Angle-Torsions: %10d", nAngleTorsions));
1385 }
1386 } else {
1387 nAngleTorsions = 0;
1388 angleTorsions = null;
1389 }
1390
1391
1392 if (piOrbitalTorsionTerm) {
1393 List<PiOrbitalTorsion> piOrbitalTorsionList = molecularAssembly.getPiOrbitalTorsionList();
1394 if (nnTerm) {
1395 removeNeuralNetworkTerms(piOrbitalTorsionList);
1396 }
1397 nPiOrbitalTorsions = piOrbitalTorsionList.size();
1398 piOrbitalTorsions = piOrbitalTorsionList.toArray(new PiOrbitalTorsion[0]);
1399 if (nPiOrbitalTorsions > 0) {
1400 logger.info(format(" Pi-Orbital Torsions: %10d", nPiOrbitalTorsions));
1401 }
1402 } else {
1403 nPiOrbitalTorsions = 0;
1404 piOrbitalTorsions = null;
1405 }
1406
1407
1408 if (torsionTorsionTerm) {
1409 List<TorsionTorsion> torsionTorsionList = molecularAssembly.getTorsionTorsionList();
1410 if (nnTerm) {
1411 removeNeuralNetworkTerms(torsionTorsionList);
1412 }
1413 nTorsionTorsions = torsionTorsionList.size();
1414 torsionTorsions = torsionTorsionList.toArray(new TorsionTorsion[0]);
1415 if (nTorsionTorsions > 0) {
1416 logger.info(format(" Torsion-Torsions: %10d", nTorsionTorsions));
1417 }
1418 } else {
1419 nTorsionTorsions = 0;
1420 torsionTorsions = null;
1421 }
1422
1423
1424 if (improperTorsionTerm) {
1425 List<ImproperTorsion> improperTorsionList = molecularAssembly.getImproperTorsionList();
1426 if (nnTerm) {
1427 removeNeuralNetworkTerms(improperTorsionList);
1428 }
1429 nImproperTorsions = improperTorsionList.size();
1430 improperTorsions = improperTorsionList.toArray(new ImproperTorsion[0]);
1431 if (nImproperTorsions > 0) {
1432 logger.info(format(" Improper Torsions: %10d", nImproperTorsions));
1433 }
1434 } else {
1435 nImproperTorsions = 0;
1436 improperTorsions = null;
1437 }
1438
1439 int[] molecule = molecularAssembly.getMoleculeNumbers();
1440 if (vanderWaalsTerm) {
1441 logger.info("\n Non-Bonded Terms");
1442 boolean[] nn = null;
1443 if (nnTerm) {
1444 nn = molecularAssembly.getNeuralNetworkIdentity();
1445 } else {
1446 nn = new boolean[nAtoms];
1447 Arrays.fill(nn, false);
1448 }
1449
1450 if (!tornadoVM) {
1451 vanderWaals = new VanDerWaals(atoms, molecule, nn, crystal, forceField, parallelTeam,
1452 vdwCutoff, nlistCutoff);
1453 } else {
1454 vanderWaals = new VanDerWaalsTornado(atoms, crystal, forceField, vdwCutoff);
1455 }
1456 } else {
1457 vanderWaals = null;
1458 }
1459
1460 if (nnTerm) {
1461 aniEnergy = new ANIEnergy(molecularAssembly);
1462 } else {
1463 aniEnergy = null;
1464 }
1465
1466 if (multipoleTerm) {
1467 if (name.contains("OPLS") || name.contains("AMBER") || name.contains("CHARMM")) {
1468 elecForm = ELEC_FORM.FIXED_CHARGE;
1469 } else {
1470 elecForm = ELEC_FORM.PAM;
1471 }
1472 particleMeshEwald = new ParticleMeshEwald(atoms, molecule, forceField, crystal,
1473 vanderWaals.getNeighborList(), elecForm, ewaldCutoff, gkCutoff, parallelTeam);
1474 double charge = molecularAssembly.getCharge(checkAllNodeCharges);
1475 logger.info(format("\n Overall system charge: %10.3f", charge));
1476 } else {
1477 elecForm = null;
1478 particleMeshEwald = null;
1479 }
1480
1481 if (ncsTerm) {
1482 String sg = forceField.getString("NCSGROUP", "P 1");
1483 Crystal ncsCrystal = new Crystal(a, b, c, alpha, beta, gamma, sg);
1484 ncsRestraint = new NCSRestraint(atoms, forceField, ncsCrystal);
1485 } else {
1486 ncsRestraint = null;
1487 }
1488
1489 if (restrainPositionTerm) {
1490 restrainPositions = parseRestrainPositions(molecularAssembly);
1491 if (restrainPositions != null) {
1492 nRestrainPositions = restrainPositions.length;
1493 } else {
1494 nRestrainPositions = 0;
1495 }
1496 } else {
1497 restrainPositions = null;
1498 }
1499
1500 if (restrainGroupTerm) {
1501 restrainGroups = new RestrainGroups(molecularAssembly);
1502 nRestrainGroups = restrainGroups.getNumberOfRestraints();
1503 } else {
1504 restrainGroups = null;
1505 }
1506
1507 if (comTerm) {
1508 comRestraint = new COMRestraint(molecularAssembly);
1509 } else {
1510 comRestraint = null;
1511 }
1512
1513 if (restrainDistanceTerm) {
1514
1515 configureRestraintBonds(properties);
1516 }
1517
1518 if (restrainTorsionTerm) {
1519 nRestrainTorsions = configureRestraintTorsions(properties, forceField);
1520 }
1521
1522
1523 bondedRegion = new BondedRegion();
1524
1525 maxDebugGradient = forceField.getDouble("MAX_DEBUG_GRADIENT", Double.POSITIVE_INFINITY);
1526
1527 molecularAssembly.setPotential(this);
1528
1529
1530 constraints = configureConstraints(forceField);
1531
1532 if (lambdaTerm) {
1533 this.setLambda(1.0);
1534 if (nSpecial == 0) {
1535
1536
1537 crystal.setSpecialPositionCutoff(0.0);
1538 } else {
1539
1540 logger.info(" Special positions checking will be performed during a lambda simulation.");
1541 }
1542 }
1543 }
1544
1545 private int checkForSpecialPositions(ForceField forceField) {
1546
1547 boolean specialPositionsInactive = forceField.getBoolean("SPECIAL_POSITIONS_INACTIVE", true);
1548 int nSpecial = 0;
1549 if (specialPositionsInactive) {
1550 int nSymm = crystal.getNumSymOps();
1551 if (nSymm > 1) {
1552 SpaceGroup spaceGroup = crystal.spaceGroup;
1553 double sp2 = crystal.getSpecialPositionCutoff2();
1554 double[] mate = new double[3];
1555 StringBuilder sb = new StringBuilder("\n Atoms at Special Positions set to Inactive:\n");
1556 for (int i = 0; i < nAtoms; i++) {
1557 Atom atom = atoms[i];
1558 double[] xyz = atom.getXYZ(null);
1559 for (int iSymm = 1; iSymm < nSymm; iSymm++) {
1560 SymOp symOp = spaceGroup.getSymOp(iSymm);
1561 crystal.applySymOp(xyz, mate, symOp);
1562 double dr2 = crystal.image(xyz, mate);
1563 if (dr2 < sp2) {
1564 sb.append(
1565 format(" %s separation with SymOp %d at %8.6f A.\n", atoms[i], iSymm, sqrt(dr2)));
1566 atom.setActive(false);
1567 nSpecial++;
1568 break;
1569 }
1570 }
1571 }
1572 if (nSpecial > 0) {
1573 logger.info(sb.toString());
1574 }
1575 }
1576 }
1577 return nSpecial;
1578 }
1579
1580
1581
1582
1583
1584
1585
1586
1587 private int configureRestraintTorsions(CompositeConfiguration properties, ForceField forceField) {
1588 String[] restrainTorsionCos = properties.getStringArray("restrain-torsion-cos");
1589 double torsUnits = forceField.getDouble("TORSIONUNIT", TorsionType.DEFAULT_TORSION_UNIT);
1590 List<RestraintTorsion> rTorsList = new ArrayList<>(restrainTorsionCos.length);
1591 for (String rtc : restrainTorsionCos) {
1592 String[] toks = rtc.split("\\s+");
1593 int nTok = toks.length;
1594 if (nTok < 7) {
1595 throw new IllegalArgumentException(format(
1596 "restrain-torsion-cos record %s must have 4 atom indices, amplitude, phase shift and periodicity!",
1597 rtc));
1598 }
1599 int ai1 = Integer.parseInt(toks[0]) - 1;
1600 int ai2 = Integer.parseInt(toks[1]) - 1;
1601 int ai3 = Integer.parseInt(toks[2]) - 1;
1602 int ai4 = Integer.parseInt(toks[3]) - 1;
1603 Atom a1 = atoms[ai1];
1604 Atom a2 = atoms[ai2];
1605 Atom a3 = atoms[ai3];
1606 Atom a4 = atoms[ai4];
1607 int[] atomClasses = new int[]{-1, -1, -1, -1};
1608
1609 int startTerms = 4;
1610 boolean lamEnabled = false;
1611 boolean revLam = false;
1612 if (toks[4].equalsIgnoreCase("lambda")) {
1613 ++startTerms;
1614 lamEnabled = true;
1615 if (toks[5].toLowerCase().startsWith("reverse")) {
1616 ++startTerms;
1617 revLam = true;
1618 }
1619 }
1620 if (!lambdaTerm) {
1621 lamEnabled = false;
1622 }
1623
1624 int nTerms = (nTok - startTerms) / 3;
1625 assert (nTok - startTerms) % 3 == 0;
1626 double[] amp = new double[nTerms];
1627 double[] phase = new double[nTerms];
1628 int[] period = new int[nTerms];
1629
1630 for (int i = 0; i < nTerms; i++) {
1631 int i0 = startTerms + (3 * i);
1632 amp[i] = Double.parseDouble(toks[i0]);
1633 phase[i] = Double.parseDouble(toks[i0 + 1]);
1634 period[i] = Integer.parseInt(toks[i0 + 2]);
1635 }
1636
1637
1638 assert !lamEnabled || lambdaTerm;
1639 TorsionType tType = new TorsionType(atomClasses, amp, phase, period);
1640 rTorsList.add(new RestraintTorsion(a1, a2, a3, a4, tType, lamEnabled, revLam, torsUnits));
1641 }
1642
1643 if (!rTorsList.isEmpty()) {
1644 logger.info(format(" Adding %4d cosine-based torsion restraints.", nRestrainTorsions));
1645 restrainTorsionTerm = true;
1646 restrainTorsions = rTorsList.toArray(new RestraintTorsion[0]);
1647 restrainTorsionEnergy = 0;
1648 restrainTorsionTime = 0;
1649 return rTorsList.size();
1650 }
1651 return 0;
1652 }
1653
1654
1655
1656
1657
1658
1659 private void configureRestraintBonds(CompositeConfiguration properties) {
1660
1661 String[] bondRestraints = properties.getStringArray("restrain-distance");
1662 for (String bondRest : bondRestraints) {
1663 try {
1664 String[] toks = bondRest.split("\\s+");
1665 if (toks.length < 2) {
1666 throw new IllegalArgumentException(
1667 format(" restrain-distance value %s could not be parsed!", bondRest));
1668 }
1669
1670
1671 int at1 = Integer.parseInt(toks[0]) - 1;
1672 int at2 = Integer.parseInt(toks[1]) - 1;
1673
1674 double forceConst = 100.0;
1675 double flatBottomRadius = 0;
1676 Atom a1 = atoms[at1];
1677 Atom a2 = atoms[at2];
1678
1679 if (toks.length > 2) {
1680 forceConst = Double.parseDouble(toks[2]);
1681 }
1682 double dist;
1683 switch (toks.length) {
1684 case 2:
1685 case 3:
1686 double[] xyz1 = new double[3];
1687 xyz1 = a1.getXYZ(xyz1);
1688 double[] xyz2 = new double[3];
1689 xyz2 = a2.getXYZ(xyz2);
1690
1691 dist = crystal.minDistOverSymOps(xyz1, xyz2);
1692 break;
1693 case 4:
1694 dist = Double.parseDouble(toks[3]);
1695 break;
1696 case 5:
1697 default:
1698 double minDist = Double.parseDouble(toks[3]);
1699 double maxDist = Double.parseDouble(toks[4]);
1700 dist = 0.5 * (minDist + maxDist);
1701 flatBottomRadius = 0.5 * Math.abs(maxDist - minDist);
1702 break;
1703 }
1704
1705 UnivariateSwitchingFunction switchF;
1706 double lamStart = RestrainDistance.DEFAULT_RB_LAM_START;
1707 double lamEnd = RestrainDistance.DEFAULT_RB_LAM_END;
1708 if (toks.length > 5) {
1709 int offset = 5;
1710 if (toks[5].matches("^[01](?:\\.[0-9]*)?")) {
1711 offset = 6;
1712 lamStart = Double.parseDouble(toks[5]);
1713 if (toks[6].matches("^[01](?:\\.[0-9]*)?")) {
1714 offset = 7;
1715 lamEnd = Double.parseDouble(toks[6]);
1716 }
1717 }
1718 switchF = UnivariateFunctionFactory.parseUSF(toks, offset);
1719 } else {
1720 switchF = new ConstantSwitch();
1721 }
1722
1723 setRestrainDistance(a1, a2, dist, forceConst, flatBottomRadius, lamStart, lamEnd, switchF);
1724 } catch (Exception ex) {
1725 logger.info(format(" Exception in parsing restrain-distance: %s", ex));
1726 }
1727 }
1728 }
1729
1730
1731
1732
1733
1734
1735
1736 private List<Constraint> configureConstraints(ForceField forceField) {
1737 String constraintStrings = forceField.getString("CONSTRAIN", forceField.getString("RATTLE", null));
1738 if (constraintStrings == null) {
1739 return Collections.emptyList();
1740 }
1741
1742 ArrayList<Constraint> constraints = new ArrayList<>();
1743 logger.info(format(" Experimental: parsing constraints option %s", constraintStrings));
1744
1745 Set<Bond> numericBonds = new HashSet<>(1);
1746 Set<Angle> numericAngles = new HashSet<>(1);
1747
1748
1749 if (constraintStrings.isEmpty() || constraintStrings.matches("^\\s*$")) {
1750
1751 logger.info(" Constraining X-H bonds.");
1752 numericBonds = Arrays.stream(bonds).filter(
1753 (Bond bond) -> bond.getAtom(0).getAtomicNumber() == 1
1754 || bond.getAtom(1).getAtomicNumber() == 1).collect(Collectors.toSet());
1755 } else {
1756 String[] constraintToks = constraintStrings.split("\\s+");
1757
1758
1759 for (String tok : constraintToks) {
1760 if (tok.equalsIgnoreCase("WATER")) {
1761 logger.info(" Constraining waters to be rigid based on angle & bonds.");
1762
1763
1764 Stream<MSNode> settleStream = molecularAssembly.getMolecules().stream()
1765 .filter((MSNode m) -> m.getAtomList().size() == 3).filter((MSNode m) -> {
1766 List<Atom> atoms = m.getAtomList();
1767 Atom O = null;
1768 List<Atom> H = new ArrayList<>(2);
1769 for (Atom at : atoms) {
1770 int atN = at.getAtomicNumber();
1771 if (atN == 8) {
1772 O = at;
1773 } else if (atN == 1) {
1774 H.add(at);
1775 }
1776 }
1777 return O != null && H.size() == 2;
1778 });
1779
1780 settleStream = Stream.concat(settleStream, molecularAssembly.getWater().stream());
1781
1782 List<SettleConstraint> settleConstraints = settleStream.map(
1783 (MSNode m) -> m.getAngleList().getFirst()).map(SettleConstraint::settleFactory).toList();
1784 constraints.addAll(settleConstraints);
1785
1786 } else if (tok.equalsIgnoreCase("DIATOMIC")) {
1787 logger.severe(" Diatomic distance constraints not yet implemented properly.");
1788 } else if (tok.equalsIgnoreCase("TRIATOMIC")) {
1789 logger.severe(
1790 " Triatomic SETTLE constraints for non-water molecules not yet implemented properly.");
1791 }
1792 }
1793
1794
1795 for (String tok : constraintToks) {
1796 if (tok.equalsIgnoreCase("BONDS")) {
1797 numericBonds = new HashSet<>(Arrays.asList(bonds));
1798 } else if (tok.equalsIgnoreCase("ANGLES")) {
1799 numericAngles = new HashSet<>(Arrays.asList(angles));
1800 }
1801 }
1802 }
1803
1804
1805 for (Angle angle : numericAngles) {
1806 angle.getBondList().forEach(numericBonds::remove);
1807 }
1808
1809
1810 List<Angle> ccmaAngles = numericAngles.stream().filter((Angle ang) -> !ang.isConstrained())
1811 .collect(Collectors.toList());
1812 List<Bond> ccmaBonds = numericBonds.stream().filter((Bond bond) -> !bond.isConstrained())
1813 .collect(Collectors.toList());
1814
1815 CcmaConstraint ccmaConstraint = CcmaConstraint.ccmaFactory(ccmaBonds, ccmaAngles, atoms,
1816 getMass(), CcmaConstraint.DEFAULT_CCMA_NONZERO_CUTOFF);
1817 constraints.add(ccmaConstraint);
1818 logger.info(format(" Added %d constraints.", constraints.size()));
1819
1820 return constraints;
1821 }
1822
1823
1824
1825
1826
1827
1828
1829 public static ForceFieldEnergy energyFactory(MolecularAssembly assembly) {
1830 return energyFactory(assembly, ParallelTeam.getDefaultThreadCount());
1831 }
1832
1833
1834
1835
1836
1837
1838
1839
1840 @SuppressWarnings("fallthrough")
1841 public static ForceFieldEnergy energyFactory(MolecularAssembly assembly, int numThreads) {
1842 ForceField forceField = assembly.getForceField();
1843 String platformString = toEnumForm(forceField.getString("PLATFORM", "FFX"));
1844 try {
1845 Platform platform = Platform.valueOf(platformString);
1846 switch (platform) {
1847 case OMM, OMM_REF, OMM_CUDA, OMM_OPENCL:
1848 try {
1849 return new OpenMMEnergy(assembly, platform, numThreads);
1850 } catch (Exception ex) {
1851 logger.warning(format(" Exception creating OpenMMEnergy: %s", ex));
1852 ForceFieldEnergy ffxEnergy = assembly.getPotentialEnergy();
1853 if (ffxEnergy == null) {
1854 ffxEnergy = new ForceFieldEnergy(assembly, numThreads);
1855 assembly.setPotential(ffxEnergy);
1856 }
1857 return ffxEnergy;
1858 }
1859 case OMM_CPU:
1860 logger.warning(format(" Platform %s not supported; defaulting to FFX", platform));
1861 default:
1862 ForceFieldEnergy ffxEnergy = assembly.getPotentialEnergy();
1863 if (ffxEnergy == null) {
1864 ffxEnergy = new ForceFieldEnergy(assembly, numThreads);
1865 assembly.setPotential(ffxEnergy);
1866 }
1867 return ffxEnergy;
1868 }
1869 } catch (IllegalArgumentException | NullPointerException ex) {
1870 logger.warning(
1871 format(" String %s did not match a known energy implementation", platformString));
1872 ForceFieldEnergy ffxEnergy = assembly.getPotentialEnergy();
1873 if (ffxEnergy == null) {
1874 ffxEnergy = new ForceFieldEnergy(assembly, numThreads);
1875 assembly.setPotential(ffxEnergy);
1876 }
1877 return ffxEnergy;
1878 }
1879 }
1880
1881
1882
1883
1884
1885
1886
1887 public void applyAllConstraintPositions(double[] xPrior, double[] xNew) {
1888 applyAllConstraintPositions(xPrior, xNew, DEFAULT_CONSTRAINT_TOLERANCE);
1889 }
1890
1891
1892
1893
1894
1895
1896
1897
1898 public void applyAllConstraintPositions(double[] xPrior, double[] xNew, double tol) {
1899 if (xPrior == null) {
1900 xPrior = Arrays.copyOf(xNew, xNew.length);
1901 }
1902 for (Constraint constraint : constraints) {
1903 constraint.applyConstraintToStep(xPrior, xNew, getMass(), tol);
1904 }
1905 }
1906
1907
1908
1909
1910
1911
1912
1913 public void attachExtendedSystem(ExtendedSystem system) {
1914 if (system == null) {
1915 throw new IllegalArgumentException();
1916 }
1917 esvTerm = true;
1918 esvTermOrig = esvTerm;
1919 esvSystem = system;
1920 if (vanderWaalsTerm) {
1921 if (vanderWaals == null) {
1922 logger.warning("Null VdW during ESV setup.");
1923 } else {
1924 vanderWaals.attachExtendedSystem(system);
1925 }
1926 }
1927 if (multipoleTerm) {
1928 if (particleMeshEwald == null) {
1929 logger.warning("Null PME during ESV setup.");
1930 } else {
1931 particleMeshEwald.attachExtendedSystem(system);
1932 }
1933 }
1934 }
1935
1936
1937
1938
1939
1940
1941 @Override
1942 public boolean dEdLZeroAtEnds() {
1943
1944
1945 return !lambdaTerm;
1946 }
1947
1948
1949
1950
1951
1952
1953 public boolean destroy() {
1954 if (destroyed) {
1955
1956
1957 logger.fine(format(" This ForceFieldEnergy is already destroyed: %s", this));
1958 return true;
1959 } else {
1960 try {
1961 if (parallelTeam != null) {
1962 parallelTeam.shutdown();
1963 }
1964 if (vanderWaals != null) {
1965 vanderWaals.destroy();
1966 }
1967 if (particleMeshEwald != null) {
1968 particleMeshEwald.destroy();
1969 }
1970 molecularAssembly.finishDestruction();
1971 destroyed = true;
1972 return true;
1973 } catch (Exception ex) {
1974 logger.warning(format(" Exception in shutting down a ForceFieldEnergy: %s", ex));
1975 logger.info(Utilities.stackTraceToString(ex));
1976 return false;
1977 }
1978 }
1979 }
1980
1981
1982
1983
1984
1985
1986 public double energy() {
1987 return energy(false, false);
1988 }
1989
1990
1991
1992
1993
1994
1995 public double energy(boolean gradient, boolean print) {
1996 try {
1997 totalTime = System.nanoTime();
1998 nnTime = 0;
1999 bondTime = 0;
2000 angleTime = 0;
2001 stretchBendTime = 0;
2002 ureyBradleyTime = 0;
2003 outOfPlaneBendTime = 0;
2004 torsionTime = 0;
2005 stretchTorsionTime = 0;
2006 angleTorsionTime = 0;
2007 piOrbitalTorsionTime = 0;
2008 torsionTorsionTime = 0;
2009 improperTorsionTime = 0;
2010 vanDerWaalsTime = 0;
2011 electrostaticTime = 0;
2012 restrainDistanceTime = 0;
2013 restrainTorsionTime = 0;
2014 restrainPositionTime = 0;
2015 restrainGroupTime = 0;
2016 ncsTime = 0;
2017
2018
2019 nnEnergy = 0.0;
2020 bondEnergy = 0.0;
2021 angleEnergy = 0.0;
2022 stretchBendEnergy = 0.0;
2023 ureyBradleyEnergy = 0.0;
2024 outOfPlaneBendEnergy = 0.0;
2025 torsionEnergy = 0.0;
2026 angleTorsionEnergy = 0.0;
2027 stretchTorsionEnergy = 0.0;
2028 piOrbitalTorsionEnergy = 0.0;
2029 torsionTorsionEnergy = 0.0;
2030 improperTorsionEnergy = 0.0;
2031 totalBondedEnergy = 0.0;
2032
2033
2034 restrainDistanceEnergy = 0.0;
2035 restrainTorsionEnergy = 0.0;
2036 restrainPositionEnergy = 0.0;
2037 restrainGroupEnergy = 0.0;
2038 ncsEnergy = 0.0;
2039
2040
2041 bondRMSD = 0.0;
2042 angleRMSD = 0.0;
2043
2044
2045 vanDerWaalsEnergy = 0.0;
2046 permanentMultipoleEnergy = 0.0;
2047 permanentRealSpaceEnergy = 0.0;
2048 polarizationEnergy = 0.0;
2049 totalMultipoleEnergy = 0.0;
2050 totalNonBondedEnergy = 0.0;
2051
2052
2053 solvationEnergy = 0.0;
2054
2055
2056 relativeSolvationEnergy = 0.0;
2057 nRelativeSolvations = 0;
2058
2059 esvBias = 0.0;
2060
2061
2062 totalEnergy = 0.0;
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073 try {
2074 bondedRegion.setGradient(gradient);
2075 parallelTeam.execute(bondedRegion);
2076 } catch (RuntimeException ex) {
2077 logger.warning("Runtime exception during bonded term calculation.");
2078 throw ex;
2079 } catch (Exception ex) {
2080 logger.info(Utilities.stackTraceToString(ex));
2081 logger.severe(ex.toString());
2082 }
2083
2084 if (!lambdaBondedTerms) {
2085
2086 if (ncsTerm) {
2087 ncsTime = -System.nanoTime();
2088 ncsEnergy = ncsRestraint.residual(gradient, print);
2089 ncsTime += System.nanoTime();
2090 }
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102 if (restrainGroupTerm) {
2103 restrainGroupTime = -System.nanoTime();
2104 restrainGroupEnergy = restrainGroups.energy(gradient);
2105 restrainGroupTime += System.nanoTime();
2106 }
2107
2108 if (comTerm) {
2109 comRestraintTime = -System.nanoTime();
2110 comRestraintEnergy = comRestraint.residual(gradient, print);
2111 comRestraintTime += System.nanoTime();
2112 }
2113
2114
2115
2116 if (nnTerm) {
2117 nnTime = -System.nanoTime();
2118 nnEnergy = aniEnergy.energy(gradient, print);
2119 nnTime += System.nanoTime();
2120 }
2121
2122
2123 if (vanderWaalsTerm) {
2124 vanDerWaalsTime = -System.nanoTime();
2125 vanDerWaalsEnergy = vanderWaals.energy(gradient, print);
2126 nVanDerWaalInteractions = this.vanderWaals.getInteractions();
2127 vanDerWaalsTime += System.nanoTime();
2128 }
2129
2130 if (multipoleTerm) {
2131 electrostaticTime = -System.nanoTime();
2132 totalMultipoleEnergy = particleMeshEwald.energy(gradient, print);
2133 permanentMultipoleEnergy = particleMeshEwald.getPermanentEnergy();
2134 permanentRealSpaceEnergy = particleMeshEwald.getPermRealEnergy();
2135 polarizationEnergy = particleMeshEwald.getPolarizationEnergy();
2136 nPermanentInteractions = particleMeshEwald.getInteractions();
2137 solvationEnergy = particleMeshEwald.getSolvationEnergy();
2138 nGKInteractions = particleMeshEwald.getGKInteractions();
2139 electrostaticTime += System.nanoTime();
2140 }
2141 }
2142
2143 if (relativeSolvationTerm) {
2144 List<Residue> residuesList = molecularAssembly.getResidueList();
2145 for (Residue residue : residuesList) {
2146 if (residue instanceof MultiResidue) {
2147 Atom refAtom = residue.getSideChainAtoms().get(0);
2148 if (refAtom != null && refAtom.getUse()) {
2149
2150
2151 double thisSolvation = relativeSolvation.getSolvationEnergy(residue, false);
2152 relativeSolvationEnergy -= thisSolvation;
2153 if (thisSolvation != 0) {
2154 nRelativeSolvations++;
2155 }
2156 }
2157 }
2158 }
2159 }
2160
2161 totalTime = System.nanoTime() - totalTime;
2162
2163 totalBondedEnergy = nnEnergy + bondEnergy + angleEnergy + stretchBendEnergy + ureyBradleyEnergy
2164 + outOfPlaneBendEnergy + torsionEnergy + angleTorsionEnergy + stretchTorsionEnergy
2165 + piOrbitalTorsionEnergy + improperTorsionEnergy + torsionTorsionEnergy
2166 + ncsEnergy + comRestraintEnergy
2167 + restrainDistanceEnergy + restrainPositionEnergy + restrainGroupEnergy + restrainTorsionEnergy ;
2168
2169 totalNonBondedEnergy = vanDerWaalsEnergy + totalMultipoleEnergy + relativeSolvationEnergy;
2170 totalEnergy = totalBondedEnergy + totalNonBondedEnergy + solvationEnergy;
2171 if (esvTerm) {
2172 esvBias = esvSystem.getBiasEnergy();
2173 totalEnergy += esvBias;
2174 }
2175
2176 if (print) {
2177 StringBuilder sb = new StringBuilder();
2178 if (gradient) {
2179 sb.append("\n Computed Potential Energy and Atomic Coordinate Gradients\n");
2180 } else {
2181 sb.append("\n Computed Potential Energy\n");
2182 }
2183 sb.append(this);
2184 logger.info(sb.toString());
2185 }
2186 return totalEnergy;
2187 } catch (EnergyException ex) {
2188 if (printOnFailure) {
2189 printFailure();
2190 }
2191 if (ex.doCauseSevere()) {
2192 logger.info(Utilities.stackTraceToString(ex));
2193 logger.log(Level.SEVERE, " Error in calculating energies or gradients", ex);
2194 } else {
2195 logger.log(Level.INFO, format(" Exception in energy calculation:\n %s", ex));
2196 }
2197 throw ex;
2198 }
2199 }
2200
2201
2202
2203
2204 @Override
2205 public double energy(double[] x) {
2206 return energy(x, false);
2207 }
2208
2209
2210
2211
2212 @Override
2213 public double energy(double[] x, boolean verbose) {
2214 assert Arrays.stream(x).allMatch(Double::isFinite);
2215
2216
2217 unscaleCoordinates(x);
2218
2219
2220 setCoordinates(x);
2221
2222 double e = this.energy(false, verbose);
2223
2224
2225 scaleCoordinates(x);
2226
2227 return e;
2228 }
2229
2230
2231
2232
2233 @Override
2234 public double energyAndGradient(double[] x, double[] g) {
2235 return energyAndGradient(x, g, false);
2236 }
2237
2238
2239
2240
2241 @Override
2242 public double energyAndGradient(double[] x, double[] g, boolean verbose) {
2243 assert Arrays.stream(x).allMatch(Double::isFinite);
2244
2245 unscaleCoordinates(x);
2246
2247 setCoordinates(x);
2248 double e = energy(true, verbose);
2249
2250
2251
2252 try {
2253 fillGradient(g);
2254
2255
2256 scaleCoordinatesAndGradient(x, g);
2257
2258 if (maxDebugGradient < Double.MAX_VALUE) {
2259 boolean extremeGrad = Arrays.stream(g)
2260 .anyMatch((double gi) -> (gi > maxDebugGradient || gi < -maxDebugGradient));
2261 if (extremeGrad) {
2262 File origFile = molecularAssembly.getFile();
2263 String timeString = LocalDateTime.now()
2264 .format(DateTimeFormatter.ofPattern("yyyy_MM_dd-HH_mm_ss"));
2265
2266 String filename = format("%s-LARGEGRAD-%s.pdb",
2267 removeExtension(molecularAssembly.getFile().getName()), timeString);
2268 PotentialsFunctions ef = new PotentialsUtils();
2269 filename = ef.versionFile(filename);
2270
2271 logger.warning(format(" Excessively large gradient detected; printing snapshot to file %s",
2272 filename));
2273 ef.saveAsPDB(molecularAssembly, new File(filename));
2274 molecularAssembly.setFile(origFile);
2275 }
2276 }
2277 return e;
2278 } catch (EnergyException ex) {
2279 if (printOnFailure) {
2280 printFailure();
2281 }
2282 if (ex.doCauseSevere()) {
2283 logger.info(Utilities.stackTraceToString(ex));
2284 logger.log(Level.SEVERE, " Error in calculating energies or gradients", ex);
2285 } else {
2286 logger.log(Level.INFO, format(" Exception in energy calculation:\n %s", ex));
2287 }
2288 throw ex;
2289 }
2290 }
2291
2292
2293
2294
2295 private void printFailure() {
2296 String timeString = LocalDateTime.now()
2297 .format(DateTimeFormatter.ofPattern("yyyy_MM_dd-HH_mm_ss"));
2298 File file = molecularAssembly.getFile();
2299 String ext = "pdb";
2300 if (isXYZ(file)) {
2301 ext = "xyz";
2302 }
2303 String filename = format("%s-ERROR-%s.%s", removeExtension(file.getName()), timeString, ext);
2304 PotentialsFunctions ef = new PotentialsUtils();
2305 filename = ef.versionFile(filename);
2306 logger.info(format(" Writing on-error snapshot to file %s", filename));
2307 ef.save(molecularAssembly, new File(filename));
2308 }
2309
2310
2311
2312
2313
2314
2315 @Override
2316 public double[] getAcceleration(double[] acceleration) {
2317 int n = getNumberOfVariables();
2318 if (acceleration == null || acceleration.length < n) {
2319 acceleration = new double[n];
2320 }
2321 int index = 0;
2322 double[] a = new double[3];
2323 for (int i = 0; i < nAtoms; i++) {
2324 if (atoms[i].isActive()) {
2325 atoms[i].getAcceleration(a);
2326 acceleration[index++] = a[0];
2327 acceleration[index++] = a[1];
2328 acceleration[index++] = a[2];
2329 }
2330 }
2331 return acceleration;
2332 }
2333
2334
2335
2336
2337
2338
2339 public double getAngleEnergy() {
2340 return angleEnergy;
2341 }
2342
2343
2344
2345
2346
2347
2348 public double getAngleTorsionEnergy() {
2349 return angleTorsionEnergy;
2350 }
2351
2352
2353
2354
2355
2356
2357 public AngleTorsion[] getAngleTorsions() {
2358 return angleTorsions;
2359 }
2360
2361
2362
2363
2364
2365
2366 public Angle[] getAngles() {
2367 return angles;
2368 }
2369
2370 public String getAngleEnergyString() {
2371 AngleType angleType = angles[0].angleType;
2372 String energy;
2373 if (angleType.angleFunction == AngleType.AngleFunction.SEXTIC) {
2374 energy = format("""
2375 k*(d^2 + %.15g*d^3 + %.15g*d^4 + %.15g*d^5 + %.15g*d^6);
2376 d=%.15g*theta-theta0;
2377 """,
2378 angleType.cubic, angleType.quartic, angleType.pentic, angleType.sextic, 180.0 / PI);
2379 } else {
2380 energy = format("""
2381 k*(d^2);
2382 d=%.15g*theta-theta0;
2383 """,
2384 180.0 / PI);
2385 }
2386 return energy;
2387 }
2388
2389 public String getInPlaneAngleEnergyString() {
2390 AngleType angleType = angles[0].angleType;
2391 String energy = format("""
2392 k*(d^2 + %.15g*d^3 + %.15g*d^4 + %.15g*d^5 + %.15g*d^6);
2393 d=theta-theta0;
2394 theta = %.15g*pointangle(x1, y1, z1, projx, projy, projz, x3, y3, z3);
2395 projx = x2-nx*dot;
2396 projy = y2-ny*dot;
2397 projz = z2-nz*dot;
2398 dot = nx*(x2-x3) + ny*(y2-y3) + nz*(z2-z3);
2399 nx = px/norm;
2400 ny = py/norm;
2401 nz = pz/norm;
2402 norm = sqrt(px*px + py*py + pz*pz);
2403 px = (d1y*d2z-d1z*d2y);
2404 py = (d1z*d2x-d1x*d2z);
2405 pz = (d1x*d2y-d1y*d2x);
2406 d1x = x1-x4;
2407 d1y = y1-y4;
2408 d1z = z1-z4;
2409 d2x = x3-x4;
2410 d2y = y3-y4;
2411 d2z = z3-z4;
2412 """,
2413 angleType.cubic, angleType.quartic, angleType.pentic, angleType.sextic, 180.0 / PI);
2414 return energy;
2415 }
2416
2417
2418
2419
2420
2421
2422
2423 public Angle[] getAngles(AngleMode angleMode) {
2424 if (angles == null || angles.length < 1) {
2425 return null;
2426 }
2427 int nAngles = angles.length;
2428 List<Angle> angleList = new ArrayList<>();
2429
2430 for (int i = 0; i < nAngles; i++) {
2431 if (angles[i].getAngleMode() == angleMode) {
2432 angleList.add(angles[i]);
2433 }
2434 }
2435 nAngles = angleList.size();
2436 if (nAngles < 1) {
2437 return null;
2438 }
2439 return angleList.toArray(new Angle[0]);
2440 }
2441
2442
2443
2444
2445
2446
2447
2448 public double getNeutralNetworkEnergy() {
2449 return nnEnergy;
2450 }
2451
2452
2453
2454
2455
2456
2457 public double getBondEnergy() {
2458 return bondEnergy;
2459 }
2460
2461
2462
2463
2464
2465
2466 public Bond[] getBonds() {
2467 return bonds;
2468 }
2469
2470 public String getBondEnergyString() {
2471 BondType bondType = bonds[0].getBondType();
2472 String energy;
2473 if (bondType.bondFunction == BondType.BondFunction.QUARTIC) {
2474 energy = format("""
2475 k*(d^2 + %.15g*d^3 + %.15g*d^4);
2476 d=r-r0;
2477 """,
2478 bondType.cubic / OpenMM_NmPerAngstrom,
2479 bondType.quartic / (OpenMM_NmPerAngstrom * OpenMM_NmPerAngstrom));
2480 } else {
2481 energy = """
2482 k*(d^2);
2483 d=r-r0;
2484 """;
2485 }
2486 return energy;
2487 }
2488
2489
2490
2491
2492
2493
2494 public double getCavitationEnergy() {
2495 return particleMeshEwald.getCavitationEnergy();
2496 }
2497
2498
2499
2500
2501
2502
2503 @Override
2504 public List<Constraint> getConstraints() {
2505 return constraints.isEmpty() ? Collections.emptyList() : new ArrayList<>(constraints);
2506 }
2507
2508
2509
2510
2511
2512
2513 public List<RestrainPosition> getRestrainPositions() {
2514 if (restrainPositions == null) {
2515 return Collections.emptyList();
2516 }
2517 return List.of(restrainPositions);
2518 }
2519
2520
2521
2522
2523 @Override
2524 public double[] getCoordinates(double[] x) {
2525 int n = getNumberOfVariables();
2526 if (x == null || x.length < n) {
2527 x = new double[n];
2528 }
2529 int index = 0;
2530 for (int i = 0; i < nAtoms; i++) {
2531 Atom a = atoms[i];
2532 if (a.isActive()) {
2533 x[index++] = a.getX();
2534 x[index++] = a.getY();
2535 x[index++] = a.getZ();
2536 }
2537 }
2538 return x;
2539 }
2540
2541
2542
2543
2544
2545
2546 @Override
2547 public Crystal getCrystal() {
2548 return crystal;
2549 }
2550
2551
2552
2553
2554
2555
2556 @Override
2557 public void setCrystal(Crystal crystal) {
2558 setCrystal(crystal, false);
2559 }
2560
2561
2562
2563
2564
2565
2566 public double getCutoffPlusBuffer() {
2567 return cutoffPlusBuffer;
2568 }
2569
2570
2571
2572
2573
2574
2575 public double getDispersionEnergy() {
2576 return particleMeshEwald.getDispersionEnergy();
2577 }
2578
2579
2580
2581
2582
2583
2584 public double getElectrostaticEnergy() {
2585 return totalMultipoleEnergy;
2586 }
2587
2588
2589
2590
2591 @Override
2592 public STATE getEnergyTermState() {
2593 return state;
2594 }
2595
2596
2597
2598
2599
2600
2601 @Override
2602 public void setEnergyTermState(STATE state) {
2603 this.state = state;
2604 switch (state) {
2605 case FAST:
2606 nnTerm = nnTermOrig;
2607 bondTerm = bondTermOrig;
2608 angleTerm = angleTermOrig;
2609 stretchBendTerm = stretchBendTermOrig;
2610 ureyBradleyTerm = ureyBradleyTermOrig;
2611 outOfPlaneBendTerm = outOfPlaneBendTermOrig;
2612 torsionTerm = torsionTermOrig;
2613 stretchTorsionTerm = stretchTorsionTermOrig;
2614 angleTorsionTerm = angleTorsionTermOrig;
2615 piOrbitalTorsionTerm = piOrbitalTorsionTermOrig;
2616 torsionTorsionTerm = torsionTorsionTermOrig;
2617 improperTorsionTerm = improperTorsionTermOrig;
2618 restrainDistanceTerm = restrainDistanceTermOrig;
2619 restrainTorsionTerm = restrainTorsionTermOrig;
2620 restrainPositionTerm = restrainPositionTermOrig;
2621 restrainGroupTerm = restrainGroupTermOrig;
2622 ncsTerm = ncsTermOrig;
2623 comTerm = comTermOrig;
2624 vanderWaalsTerm = false;
2625 multipoleTerm = false;
2626 polarizationTerm = false;
2627 generalizedKirkwoodTerm = false;
2628 esvTerm = false;
2629 break;
2630 case SLOW:
2631 vanderWaalsTerm = vanderWaalsTermOrig;
2632 multipoleTerm = multipoleTermOrig;
2633 polarizationTerm = polarizationTermOrig;
2634 generalizedKirkwoodTerm = generalizedKirkwoodTermOrig;
2635 esvTerm = esvTermOrig;
2636 nnTerm = false;
2637 bondTerm = false;
2638 angleTerm = false;
2639 stretchBendTerm = false;
2640 ureyBradleyTerm = false;
2641 outOfPlaneBendTerm = false;
2642 torsionTerm = false;
2643 stretchTorsionTerm = false;
2644 angleTorsionTerm = false;
2645 piOrbitalTorsionTerm = false;
2646 torsionTorsionTerm = false;
2647 improperTorsionTerm = false;
2648 restrainDistanceTerm = false;
2649 restrainPositionTerm = false;
2650 restrainGroupTerm = false;
2651 ncsTerm = false;
2652 comTerm = false;
2653 break;
2654 default:
2655 nnTerm = nnTermOrig;
2656 bondTerm = bondTermOrig;
2657 angleTerm = angleTermOrig;
2658 stretchBendTerm = stretchBendTermOrig;
2659 ureyBradleyTerm = ureyBradleyTermOrig;
2660 outOfPlaneBendTerm = outOfPlaneBendTermOrig;
2661 torsionTerm = torsionTermOrig;
2662 stretchTorsionTerm = stretchTorsionTermOrig;
2663 angleTorsionTerm = angleTorsionTermOrig;
2664 piOrbitalTorsionTerm = piOrbitalTorsionTermOrig;
2665 torsionTorsionTerm = torsionTorsionTermOrig;
2666 improperTorsionTerm = improperTorsionTermOrig;
2667 restrainDistanceTerm = restrainDistanceTermOrig;
2668 restrainTorsionTerm = restrainTorsionTermOrig;
2669 restrainPositionTerm = restrainPositionTermOrig;
2670 restrainGroupTerm = restrainGroupTermOrig;
2671 ncsTerm = ncsTermOrig;
2672 comTermOrig = comTerm;
2673 vanderWaalsTerm = vanderWaalsTermOrig;
2674 multipoleTerm = multipoleTermOrig;
2675 polarizationTerm = polarizationTermOrig;
2676 generalizedKirkwoodTerm = generalizedKirkwoodTermOrig;
2677 }
2678 }
2679
2680
2681
2682
2683
2684
2685 public double getEsvBiasEnergy() {
2686 return esvBias;
2687 }
2688
2689
2690
2691
2692
2693
2694 public ExtendedSystem getExtendedSystem() {
2695 return esvSystem;
2696 }
2697
2698
2699
2700
2701
2702
2703 public GeneralizedKirkwood getGK() {
2704 if (particleMeshEwald != null) {
2705 return particleMeshEwald.getGK();
2706 } else {
2707 return null;
2708 }
2709 }
2710
2711
2712
2713
2714
2715
2716 public double getGKEnergy() {
2717 return particleMeshEwald.getGKEnergy();
2718 }
2719
2720
2721
2722
2723
2724
2725
2726 public double[] getGradient(double[] g) {
2727 return fillGradient(g);
2728 }
2729
2730
2731
2732
2733
2734
2735 public double getImproperTorsionEnergy() {
2736 return improperTorsionEnergy;
2737 }
2738
2739
2740
2741
2742
2743
2744 public ImproperTorsion[] getImproperTorsions() {
2745 return improperTorsions;
2746 }
2747
2748
2749
2750
2751 @Override
2752 public double getLambda() {
2753 return lambda;
2754 }
2755
2756
2757
2758
2759 @Override
2760 public void setLambda(double lambda) {
2761 if (lambdaTerm) {
2762 if (lambda <= 1.0 && lambda >= 0.0) {
2763 this.lambda = lambda;
2764 if (vanderWaalsTerm) {
2765 vanderWaals.setLambda(lambda);
2766 }
2767 if (multipoleTerm) {
2768 particleMeshEwald.setLambda(lambda);
2769 }
2770
2771
2772
2773
2774
2775
2776
2777
2778 if (restrainDistanceTerm && nRestrainDistances > 0) {
2779 for (RestrainDistance restrainDistance : restrainDistances) {
2780 restrainDistance.setLambda(lambda);
2781 }
2782 }
2783 if (restrainTorsionTerm && nRestrainTorsions > 0) {
2784 for (RestraintTorsion restraintTorsion : restrainTorsions) {
2785 restraintTorsion.setLambda(lambda);
2786 }
2787 }
2788
2789 if (ncsTerm && ncsRestraint != null) {
2790 ncsRestraint.setLambda(lambda);
2791 }
2792 if (comTerm && comRestraint != null) {
2793 comRestraint.setLambda(lambda);
2794 }
2795 if (lambdaTorsions) {
2796 for (int i = 0; i < nTorsions; i++) {
2797 torsions[i].setLambda(lambda);
2798 }
2799 for (int i = 0; i < nPiOrbitalTorsions; i++) {
2800 piOrbitalTorsions[i].setLambda(lambda);
2801 }
2802 for (int i = 0; i < nTorsionTorsions; i++) {
2803 torsionTorsions[i].setLambda(lambda);
2804 }
2805 }
2806 } else {
2807 String message = format("Lambda value %8.3f is not in the range [0..1].", lambda);
2808 logger.warning(message);
2809 }
2810 } else {
2811 logger.fine(" Attempting to set a lambda value on a ForceFieldEnergy with lambdaterm false.");
2812 }
2813 }
2814
2815
2816
2817
2818 @Override
2819 public double[] getMass() {
2820 int n = getNumberOfVariables();
2821 double[] mass = new double[n];
2822 int index = 0;
2823 for (int i = 0; i < nAtoms; i++) {
2824 Atom a = atoms[i];
2825 if (a.isActive()) {
2826 double m = a.getMass();
2827 mass[index++] = m;
2828 mass[index++] = m;
2829 mass[index++] = m;
2830 }
2831 }
2832 return mass;
2833 }
2834
2835
2836
2837
2838 @Override
2839 public int getNumberOfVariables() {
2840 int nActive = 0;
2841 for (int i = 0; i < nAtoms; i++) {
2842 if (atoms[i].isActive()) {
2843 nActive++;
2844 }
2845 }
2846 return nActive * 3;
2847 }
2848
2849
2850
2851
2852
2853
2854 public int getNumberofAngleTorsions() {
2855 return nAngleTorsions;
2856 }
2857
2858
2859
2860
2861
2862
2863 public int getNumberofAngles() {
2864 return nAngles;
2865 }
2866
2867
2868
2869
2870
2871
2872 public int getNumberofBonds() {
2873 return nBonds;
2874 }
2875
2876
2877
2878
2879
2880
2881 public int getNumberofImproperTorsions() {
2882 return nImproperTorsions;
2883 }
2884
2885
2886
2887
2888
2889
2890 public int getNumberofOutOfPlaneBends() {
2891 return nOutOfPlaneBends;
2892 }
2893
2894
2895
2896
2897
2898
2899 public int getNumberofPiOrbitalTorsions() {
2900 return nPiOrbitalTorsions;
2901 }
2902
2903
2904
2905
2906
2907
2908 public int getNumberofStretchBends() {
2909 return nStretchBends;
2910 }
2911
2912
2913
2914
2915
2916
2917 public int getNumberofStretchTorsions() {
2918 return nStretchTorsions;
2919 }
2920
2921
2922
2923
2924
2925
2926 public int getNumberofTorsionTorsions() {
2927 return nTorsionTorsions;
2928 }
2929
2930
2931
2932
2933
2934
2935 public int getNumberofTorsions() {
2936 return nTorsions;
2937 }
2938
2939
2940
2941
2942
2943
2944 public int getNumberofUreyBradleys() {
2945 return nUreyBradleys;
2946 }
2947
2948
2949
2950
2951
2952
2953 public double getOutOfPlaneBendEnergy() {
2954 return outOfPlaneBendEnergy;
2955 }
2956
2957
2958
2959
2960
2961
2962 public OutOfPlaneBend[] getOutOfPlaneBends() {
2963 return outOfPlaneBends;
2964 }
2965
2966 public String getOutOfPlaneEnergyString() {
2967 OutOfPlaneBendType outOfPlaneBendType = outOfPlaneBends[0].outOfPlaneBendType;
2968 String energy = format("""
2969 k*(theta^2 + %.15g*theta^3 + %.15g*theta^4 + %.15g*theta^5 + %.15g*theta^6);
2970 theta = %.15g*pointangle(x2, y2, z2, x4, y4, z4, projx, projy, projz);
2971 projx = x2-nx*dot;
2972 projy = y2-ny*dot;
2973 projz = z2-nz*dot;
2974 dot = nx*(x2-x3) + ny*(y2-y3) + nz*(z2-z3);
2975 nx = px/norm;
2976 ny = py/norm;
2977 nz = pz/norm;
2978 norm = sqrt(px*px + py*py + pz*pz);
2979 px = (d1y*d2z-d1z*d2y);
2980 py = (d1z*d2x-d1x*d2z);
2981 pz = (d1x*d2y-d1y*d2x);
2982 d1x = x1-x4;
2983 d1y = y1-y4;
2984 d1z = z1-z4;
2985 d2x = x3-x4;
2986 d2y = y3-y4;
2987 d2z = z3-z4
2988 """,
2989 outOfPlaneBendType.cubic, outOfPlaneBendType.quartic,
2990 outOfPlaneBendType.pentic, outOfPlaneBendType.sextic, 180.0 / PI);
2991 return energy;
2992 }
2993
2994
2995
2996
2997
2998
2999 public String getPDBHeaderString() {
3000 energy(false, false);
3001 StringBuilder sb = new StringBuilder();
3002 sb.append("REMARK 3 CALCULATED POTENTIAL ENERGY\n");
3003 if (nnTerm) {
3004 sb.append(
3005 format("REMARK 3 %s %g (%d)\n", "NEUTRAL NETWORK : ", nnEnergy, nAtoms));
3006 }
3007 if (bondTerm) {
3008 sb.append(
3009 format("REMARK 3 %s %g (%d)\n", "BOND STRETCHING : ", bondEnergy, nBonds));
3010 sb.append(format("REMARK 3 %s %g\n", "BOND RMSD : ", bondRMSD));
3011 }
3012 if (angleTerm) {
3013 sb.append(format("REMARK 3 %s %g (%d)\n", "ANGLE BENDING : ", angleEnergy,
3014 nAngles));
3015 sb.append(format("REMARK 3 %s %g\n", "ANGLE RMSD : ", angleRMSD));
3016 }
3017 if (stretchBendTerm) {
3018 sb.append(
3019 format("REMARK 3 %s %g (%d)\n", "STRETCH-BEND : ", stretchBendEnergy,
3020 nStretchBends));
3021 }
3022 if (ureyBradleyTerm) {
3023 sb.append(
3024 format("REMARK 3 %s %g (%d)\n", "UREY-BRADLEY : ", ureyBradleyEnergy,
3025 nUreyBradleys));
3026 }
3027 if (outOfPlaneBendTerm) {
3028 sb.append(
3029 format("REMARK 3 %s %g (%d)\n", "OUT-OF-PLANE BEND : ", outOfPlaneBendEnergy,
3030 nOutOfPlaneBends));
3031 }
3032 if (torsionTerm) {
3033 sb.append(format("REMARK 3 %s %g (%d)\n", "TORSIONAL ANGLE : ", torsionEnergy,
3034 nTorsions));
3035 }
3036 if (piOrbitalTorsionTerm) {
3037 sb.append(format("REMARK 3 %s %g (%d)\n", "PI-ORBITAL TORSION : ",
3038 piOrbitalTorsionEnergy, nPiOrbitalTorsions));
3039 }
3040 if (torsionTorsionTerm) {
3041 sb.append(
3042 format("REMARK 3 %s %g (%d)\n", "TORSION-TORSION : ", torsionTorsionEnergy,
3043 nTorsionTorsions));
3044 }
3045 if (improperTorsionTerm) {
3046 sb.append(
3047 format("REMARK 3 %s %g (%d)\n", "IMPROPER TORSION : ", improperTorsionEnergy,
3048 nImproperTorsions));
3049 }
3050 if (restrainDistanceTerm) {
3051 sb.append(format("REMARK 3 %s %g (%d)\n", "RESTRAINT BOND STRETCHING : ",
3052 restrainDistanceEnergy, nRestrainDistances));
3053 }
3054
3055 if (ncsTerm) {
3056 sb.append(
3057 format("REMARK 3 %s %g (%d)\n", "NCS RESTRAINT : ", ncsEnergy, nAtoms));
3058 }
3059
3060 if (restrainPositionTerm && nRestrainPositions > 0) {
3061 int nRests = 0;
3062 for (RestrainPosition restrainPosition : restrainPositions) {
3063 nRests += restrainPosition.getNumAtoms();
3064 }
3065 sb.append(format("REMARK 3 %s %g (%d)\n", "COORDINATE RESTRAINTS : ", restrainPositionEnergy,
3066 nRests));
3067 }
3068
3069 if (comTerm) {
3070 sb.append(
3071 format("REMARK 3 %s %g (%d)\n", "COM RESTRAINT : ", comRestraintEnergy,
3072 nAtoms));
3073 }
3074
3075 if (vanderWaalsTerm) {
3076 sb.append(
3077 format("REMARK 3 %s %g (%d)\n", "VAN DER WAALS : ", vanDerWaalsEnergy,
3078 nVanDerWaalInteractions));
3079 }
3080 if (multipoleTerm) {
3081 sb.append(format("REMARK 3 %s %g (%d)\n", "ATOMIC MULTIPOLES : ",
3082 permanentMultipoleEnergy, nPermanentInteractions));
3083 }
3084 if (polarizationTerm) {
3085 sb.append(format("REMARK 3 %s %g (%d)\n", "POLARIZATION : ",
3086 polarizationEnergy, nPermanentInteractions));
3087 }
3088 sb.append(format("REMARK 3 %s %g\n", "TOTAL POTENTIAL (KCAL/MOL) : ", totalEnergy));
3089 int nsymm = crystal.getUnitCell().spaceGroup.getNumberOfSymOps();
3090 if (nsymm > 1) {
3091 sb.append(format("REMARK 3 %s %g\n", "UNIT CELL POTENTIAL : ", totalEnergy * nsymm));
3092 }
3093 if (crystal.getUnitCell() != crystal) {
3094 nsymm = crystal.spaceGroup.getNumberOfSymOps();
3095 if (nsymm > 1) {
3096 sb.append(format("REMARK 3 %s %g\n", "REPLICATES CELL POTENTIAL : ", totalEnergy * nsymm));
3097 }
3098 }
3099 sb.append("REMARK 3\n");
3100
3101 return sb.toString();
3102 }
3103
3104
3105
3106
3107
3108
3109 public ParallelTeam getParallelTeam() {
3110 return parallelTeam;
3111 }
3112
3113
3114
3115
3116
3117
3118 public int getPermanentInteractions() {
3119 return nPermanentInteractions;
3120 }
3121
3122
3123
3124
3125
3126
3127 public double getPermanentMultipoleEnergy() {
3128 return permanentMultipoleEnergy;
3129 }
3130
3131
3132
3133
3134
3135
3136 public double getPermanentRealSpaceEnergy() {
3137 return permanentRealSpaceEnergy;
3138 }
3139
3140
3141
3142
3143
3144
3145 public double getPermanentReciprocalMpoleEnergy() {
3146 return particleMeshEwald.getPermRecipEnergy();
3147 }
3148
3149
3150
3151
3152
3153
3154 public double getPermanentReciprocalSelfEnergy() {
3155 return particleMeshEwald.getPermSelfEnergy();
3156 }
3157
3158
3159
3160
3161
3162
3163 public double getPiOrbitalTorsionEnergy() {
3164 return piOrbitalTorsionEnergy;
3165 }
3166
3167
3168
3169
3170
3171
3172 public PiOrbitalTorsion[] getPiOrbitalTorsions() {
3173 return piOrbitalTorsions;
3174 }
3175
3176 public String getPiOrbitalTorsionEnergyString() {
3177 String energy = """
3178 2*k*sin(phi)^2;
3179 phi = pointdihedral(x3+c1x, y3+c1y, z3+c1z, x3, y3, z3, x4, y4, z4, x4+c2x, y4+c2y, z4+c2z);
3180 c1x = (d14y*d24z-d14z*d24y);
3181 c1y = (d14z*d24x-d14x*d24z);
3182 c1z = (d14x*d24y-d14y*d24x);
3183 c2x = (d53y*d63z-d53z*d63y);
3184 c2y = (d53z*d63x-d53x*d63z);
3185 c2z = (d53x*d63y-d53y*d63x);
3186 d14x = x1-x4;
3187 d14y = y1-y4;
3188 d14z = z1-z4;
3189 d24x = x2-x4;
3190 d24y = y2-y4;
3191 d24z = z2-z4;
3192 d53x = x5-x3;
3193 d53y = y5-y3;
3194 d53z = z5-z3;
3195 d63x = x6-x3;
3196 d63y = y6-y3;
3197 d63z = z6-z3;
3198 """;
3199 return energy;
3200 }
3201
3202
3203
3204
3205
3206
3207
3208 public Platform getPlatform() {
3209 return platform;
3210 }
3211
3212
3213
3214
3215
3216
3217 public ParticleMeshEwald getPmeNode() {
3218 return particleMeshEwald;
3219 }
3220
3221
3222
3223
3224
3225
3226 public double getPolarizationEnergy() {
3227 return polarizationEnergy;
3228 }
3229
3230
3231
3232
3233
3234
3235
3236 @Override
3237 public double[] getPreviousAcceleration(double[] previousAcceleration) {
3238 int n = getNumberOfVariables();
3239 if (previousAcceleration == null || previousAcceleration.length < n) {
3240 previousAcceleration = new double[n];
3241 }
3242 int index = 0;
3243 double[] a = new double[3];
3244 for (int i = 0; i < nAtoms; i++) {
3245 if (atoms[i].isActive()) {
3246 atoms[i].getPreviousAcceleration(a);
3247 previousAcceleration[index++] = a[0];
3248 previousAcceleration[index++] = a[1];
3249 previousAcceleration[index++] = a[2];
3250 }
3251 }
3252 return previousAcceleration;
3253 }
3254
3255
3256
3257
3258
3259
3260 public double getRelativeSolvationEnergy() {
3261 return relativeSolvationEnergy;
3262 }
3263
3264
3265
3266
3267 @Override
3268 public double[] getScaling() {
3269 return optimizationScaling;
3270 }
3271
3272
3273
3274
3275 @Override
3276 public void setScaling(double[] scaling) {
3277 optimizationScaling = scaling;
3278 }
3279
3280
3281
3282
3283
3284
3285 public double getSolvationEnergy() {
3286 return solvationEnergy;
3287 }
3288
3289
3290
3291
3292
3293
3294 public int getSolvationInteractions() {
3295 return nGKInteractions;
3296 }
3297
3298
3299
3300
3301
3302
3303 public double getStrenchBendEnergy() {
3304 return stretchBendEnergy;
3305 }
3306
3307
3308
3309
3310
3311
3312 public StretchBend[] getStretchBends() {
3313 return stretchBends;
3314 }
3315
3316 public String getStretchBendEnergyString() {
3317 String energy = format("(k1*(distance(p1,p2)-r12) + k2*(distance(p2,p3)-r23))*(%.15g*(angle(p1,p2,p3)-theta0))", 180.0 / PI);
3318 return energy;
3319 }
3320
3321
3322
3323
3324
3325
3326 public double getStretchTorsionEnergy() {
3327 return stretchTorsionEnergy;
3328 }
3329
3330
3331
3332
3333
3334
3335 public StretchTorsion[] getStretchTorsions() {
3336 return stretchTorsions;
3337 }
3338
3339
3340
3341
3342
3343
3344 public double getTorsionEnergy() {
3345 return torsionEnergy;
3346 }
3347
3348
3349
3350
3351
3352
3353 public double getTorsionTorsionEnergy() {
3354 return torsionTorsionEnergy;
3355 }
3356
3357
3358
3359
3360
3361
3362 public TorsionTorsion[] getTorsionTorsions() {
3363 return torsionTorsions;
3364 }
3365
3366
3367
3368
3369
3370
3371 public Torsion[] getTorsions() {
3372 return torsions;
3373 }
3374
3375
3376
3377
3378
3379
3380 public double getTotalElectrostaticEnergy() {
3381 return totalMultipoleEnergy + solvationEnergy;
3382 }
3383
3384
3385
3386
3387 @Override
3388 public double getTotalEnergy() {
3389 return totalEnergy;
3390 }
3391
3392
3393
3394
3395
3396
3397 public double getUreyBradleyEnergy() {
3398 return ureyBradleyEnergy;
3399 }
3400
3401
3402
3403
3404
3405
3406 public UreyBradley[] getUreyBradleys() {
3407 return ureyBradleys;
3408 }
3409
3410
3411
3412
3413
3414
3415 public double getVanDerWaalsEnergy() {
3416 return vanDerWaalsEnergy;
3417 }
3418
3419
3420
3421
3422
3423
3424 public int getVanDerWaalsInteractions() {
3425 return nVanDerWaalInteractions;
3426 }
3427
3428
3429
3430
3431
3432
3433 @Override
3434 public VARIABLE_TYPE[] getVariableTypes() {
3435 int n = getNumberOfVariables();
3436 VARIABLE_TYPE[] type = new VARIABLE_TYPE[n];
3437 int i = 0;
3438 for (int j = 0; j < nAtoms; j++) {
3439 if (atoms[j].isActive()) {
3440 type[i++] = VARIABLE_TYPE.X;
3441 type[i++] = VARIABLE_TYPE.Y;
3442 type[i++] = VARIABLE_TYPE.Z;
3443 }
3444 }
3445 return type;
3446 }
3447
3448
3449
3450
3451
3452
3453 public VanDerWaals getVdwNode() {
3454 return vanderWaals;
3455 }
3456
3457
3458
3459
3460
3461
3462 @Override
3463 public double[] getVelocity(double[] velocity) {
3464 int n = getNumberOfVariables();
3465 if (velocity == null || velocity.length < n) {
3466 velocity = new double[n];
3467 }
3468 int index = 0;
3469 double[] v = new double[3];
3470 for (int i = 0; i < nAtoms; i++) {
3471 Atom a = atoms[i];
3472 if (a.isActive()) {
3473 a.getVelocity(v);
3474 velocity[index++] = v[0];
3475 velocity[index++] = v[1];
3476 velocity[index++] = v[2];
3477 }
3478 }
3479 return velocity;
3480 }
3481
3482
3483
3484
3485 @Override
3486 public double getd2EdL2() {
3487 double d2EdLambda2 = 0.0;
3488 if (!lambdaBondedTerms) {
3489 if (vanderWaalsTerm) {
3490 d2EdLambda2 = vanderWaals.getd2EdL2();
3491 }
3492 if (multipoleTerm) {
3493 d2EdLambda2 += particleMeshEwald.getd2EdL2();
3494 }
3495
3496
3497
3498
3499
3500
3501
3502 if (restrainDistanceTerm && nRestrainDistances > 0) {
3503 for (int i = 0; i < nRestrainDistances; i++) {
3504 d2EdLambda2 += restrainDistances[i].getd2EdL2();
3505 }
3506 }
3507 if (ncsTerm && ncsRestraint != null) {
3508 d2EdLambda2 += ncsRestraint.getd2EdL2();
3509 }
3510 if (comTerm && comRestraint != null) {
3511 d2EdLambda2 += comRestraint.getd2EdL2();
3512 }
3513 if (lambdaTorsions) {
3514 for (int i = 0; i < nTorsions; i++) {
3515 d2EdLambda2 += torsions[i].getd2EdL2();
3516 }
3517 for (int i = 0; i < nPiOrbitalTorsions; i++) {
3518 d2EdLambda2 += piOrbitalTorsions[i].getd2EdL2();
3519 }
3520 for (int i = 0; i < nTorsionTorsions; i++) {
3521 d2EdLambda2 += torsionTorsions[i].getd2EdL2();
3522 }
3523 }
3524 }
3525 return d2EdLambda2;
3526 }
3527
3528
3529
3530
3531 @Override
3532 public double getdEdL() {
3533 double dEdLambda = 0.0;
3534 if (!lambdaBondedTerms) {
3535 if (vanderWaalsTerm) {
3536 dEdLambda = vanderWaals.getdEdL();
3537 }
3538 if (multipoleTerm) {
3539 dEdLambda += particleMeshEwald.getdEdL();
3540 }
3541 if (restrainDistanceTerm && nRestrainDistances > 0) {
3542 for (int i = 0; i < nRestrainDistances; i++) {
3543 dEdLambda += restrainDistances[i].getdEdL();
3544 }
3545 }
3546
3547
3548
3549
3550
3551
3552
3553 if (ncsTerm && ncsRestraint != null) {
3554 dEdLambda += ncsRestraint.getdEdL();
3555 }
3556 if (comTerm && comRestraint != null) {
3557 dEdLambda += comRestraint.getdEdL();
3558 }
3559 if (lambdaTorsions) {
3560 for (int i = 0; i < nTorsions; i++) {
3561 dEdLambda += torsions[i].getdEdL();
3562 }
3563 for (int i = 0; i < nPiOrbitalTorsions; i++) {
3564 dEdLambda += piOrbitalTorsions[i].getdEdL();
3565 }
3566 for (int i = 0; i < nTorsionTorsions; i++) {
3567 dEdLambda += torsionTorsions[i].getdEdL();
3568 }
3569 }
3570 }
3571 return dEdLambda;
3572 }
3573
3574
3575
3576
3577 @Override
3578 public void getdEdXdL(double[] gradients) {
3579 if (!lambdaBondedTerms) {
3580 if (vanderWaalsTerm) {
3581 vanderWaals.getdEdXdL(gradients);
3582 }
3583 if (multipoleTerm) {
3584 particleMeshEwald.getdEdXdL(gradients);
3585 }
3586 if (restrainDistanceTerm && nRestrainDistances > 0) {
3587 for (int i = 0; i < nRestrainDistances; i++) {
3588 restrainDistances[i].getdEdXdL(gradients);
3589 }
3590 }
3591
3592
3593
3594
3595
3596
3597
3598 if (ncsTerm && ncsRestraint != null) {
3599 ncsRestraint.getdEdXdL(gradients);
3600 }
3601 if (comTerm && comRestraint != null) {
3602 comRestraint.getdEdXdL(gradients);
3603 }
3604 if (lambdaTorsions) {
3605 double[] grad = new double[3];
3606 int index = 0;
3607 for (int i = 0; i < nAtoms; i++) {
3608 Atom a = atoms[i];
3609 if (a.isActive()) {
3610 a.getLambdaXYZGradient(grad);
3611 gradients[index++] += grad[0];
3612 gradients[index++] += grad[1];
3613 gradients[index++] += grad[2];
3614 }
3615 }
3616 }
3617 }
3618 }
3619
3620
3621
3622
3623
3624
3625 @Override
3626 public void setAcceleration(double[] acceleration) {
3627 if (acceleration == null) {
3628 return;
3629 }
3630 int index = 0;
3631 double[] accel = new double[3];
3632 for (int i = 0; i < nAtoms; i++) {
3633 if (atoms[i].isActive()) {
3634 accel[0] = acceleration[index++];
3635 accel[1] = acceleration[index++];
3636 accel[2] = acceleration[index++];
3637 atoms[i].setAcceleration(accel);
3638 }
3639 }
3640 }
3641
3642
3643
3644
3645
3646
3647 public void setCoordinates(double[] coords) {
3648 if (coords == null) {
3649 return;
3650 }
3651 int index = 0;
3652 for (int i = 0; i < nAtoms; i++) {
3653 Atom a = atoms[i];
3654 if (a.isActive()) {
3655 double x = coords[index++];
3656 double y = coords[index++];
3657 double z = coords[index++];
3658 a.moveTo(x, y, z);
3659 }
3660 }
3661 }
3662
3663
3664
3665
3666
3667
3668
3669 public void setCrystal(Crystal crystal, boolean checkReplicatesCell) {
3670 if (checkReplicatesCell) {
3671 this.crystal = ReplicatesCrystal.replicatesCrystalFactory(crystal.getUnitCell(), cutOff2);
3672 } else {
3673 this.crystal = crystal;
3674 }
3675
3676
3677
3678
3679 if (vanderWaalsTerm) {
3680 vanderWaals.setCrystal(this.crystal);
3681 }
3682 if (multipoleTerm) {
3683 particleMeshEwald.setCrystal(this.crystal);
3684 }
3685 }
3686
3687
3688
3689
3690
3691
3692
3693 @Override
3694 public void setPreviousAcceleration(double[] previousAcceleration) {
3695 if (previousAcceleration == null) {
3696 return;
3697 }
3698 int index = 0;
3699 double[] prev = new double[3];
3700 for (int i = 0; i < nAtoms; i++) {
3701 if (atoms[i].isActive()) {
3702 prev[0] = previousAcceleration[index++];
3703 prev[1] = previousAcceleration[index++];
3704 prev[2] = previousAcceleration[index++];
3705 atoms[i].setPreviousAcceleration(prev);
3706 }
3707 }
3708 }
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720 public void setPrintOnFailure(boolean onFail, boolean override) {
3721 if (override) {
3722
3723 printOnFailure = onFail;
3724 } else {
3725 try {
3726 molecularAssembly.getForceField().getBoolean("PRINT_ON_FAILURE");
3727
3728
3729
3730
3731
3732 } catch (Exception ex) {
3733 printOnFailure = onFail;
3734 }
3735 }
3736 }
3737
3738
3739
3740
3741
3742
3743 @Override
3744 public void setVelocity(double[] velocity) {
3745 if (velocity == null) {
3746 return;
3747 }
3748 int index = 0;
3749 double[] vel = new double[3];
3750 for (int i = 0; i < nAtoms; i++) {
3751 if (atoms[i].isActive()) {
3752 vel[0] = velocity[index++];
3753 vel[1] = velocity[index++];
3754 vel[2] = velocity[index++];
3755 atoms[i].setVelocity(vel);
3756 }
3757 }
3758 }
3759
3760
3761
3762
3763 @Override
3764 public String toString() {
3765 StringBuilder sb = new StringBuilder();
3766 if (bondTerm && nBonds > 0) {
3767 sb.append(format(" %s %20.8f %12d %12.3f (%8.5f)\n", "Bond Stretching ", bondEnergy, nBonds,
3768 bondTime * toSeconds, bondRMSD));
3769 }
3770 if (angleTerm && nAngles > 0) {
3771 sb.append(
3772 format(" %s %20.8f %12d %12.3f (%8.5f)\n", "Angle Bending ", angleEnergy, nAngles,
3773 angleTime * toSeconds, angleRMSD));
3774 }
3775 if (stretchBendTerm && nStretchBends > 0) {
3776 sb.append(
3777 format(" %s %20.8f %12d %12.3f\n", "Stretch-Bend ", stretchBendEnergy, nStretchBends,
3778 stretchBendTime * toSeconds));
3779 }
3780 if (ureyBradleyTerm && nUreyBradleys > 0) {
3781 sb.append(
3782 format(" %s %20.8f %12d %12.3f\n", "Urey-Bradley ", ureyBradleyEnergy, nUreyBradleys,
3783 ureyBradleyTime * toSeconds));
3784 }
3785 if (outOfPlaneBendTerm && nOutOfPlaneBends > 0) {
3786 sb.append(format(" %s %20.8f %12d %12.3f\n", "Out-of-Plane Bend ", outOfPlaneBendEnergy,
3787 nOutOfPlaneBends, outOfPlaneBendTime * toSeconds));
3788 }
3789 if (torsionTerm && nTorsions > 0) {
3790 sb.append(format(" %s %20.8f %12d %12.3f\n", "Torsional Angle ", torsionEnergy, nTorsions,
3791 torsionTime * toSeconds));
3792 }
3793 if (piOrbitalTorsionTerm && nPiOrbitalTorsions > 0) {
3794 sb.append(format(" %s %20.8f %12d %12.3f\n", "Pi-Orbital Torsion", piOrbitalTorsionEnergy,
3795 nPiOrbitalTorsions, piOrbitalTorsionTime * toSeconds));
3796 }
3797 if (stretchTorsionTerm && nStretchTorsions > 0) {
3798 sb.append(format(" %s %20.8f %12d %12.3f\n", "Stretch-Torsion ", stretchTorsionEnergy,
3799 nStretchTorsions, stretchTorsionTime * toSeconds));
3800 }
3801 if (angleTorsionTerm && nAngleTorsions > 0) {
3802 sb.append(format(" %s %20.8f %12d %12.3f\n", "Angle-Torsion ", angleTorsionEnergy,
3803 nAngleTorsions, angleTorsionTime * toSeconds));
3804 }
3805 if (torsionTorsionTerm && nTorsionTorsions > 0) {
3806 sb.append(format(" %s %20.8f %12d %12.3f\n", "Torsion-Torsion ", torsionTorsionEnergy,
3807 nTorsionTorsions, torsionTorsionTime * toSeconds));
3808 }
3809 if (improperTorsionTerm && nImproperTorsions > 0) {
3810 sb.append(format(" %s %20.8f %12d %12.3f\n", "Improper Torsion ", improperTorsionEnergy,
3811 nImproperTorsions, improperTorsionTime * toSeconds));
3812 }
3813 if (restrainDistanceTerm && nRestrainDistances > 0) {
3814 sb.append(format(" %s %20.8f %12d %12.3f\n", "Restrain Distance ", restrainDistanceEnergy,
3815 nRestrainDistances, restrainDistanceTime * toSeconds));
3816 }
3817 if (restrainTorsionTerm && nRestrainTorsions > 0) {
3818 sb.append(format(" %s %20.8f %12d %12.3f\n", "Restrain Torsion ", restrainTorsionEnergy, nRestrainTorsions,
3819 restrainTorsionTime * toSeconds));
3820 }
3821 if (restrainPositionTerm && nRestrainPositions > 0) {
3822 int nRestrainPositionAtoms = 0;
3823 for (RestrainPosition restrainPosition : restrainPositions) {
3824 nRestrainPositionAtoms += restrainPosition.getNumAtoms();
3825 }
3826 sb.append(format(" %s %20.8f %12d %12.3f\n", "Restrain Position ", restrainPositionEnergy, nRestrainPositionAtoms,
3827 restrainPositionTime * toSeconds));
3828 }
3829 if (restrainGroupTerm && nRestrainGroups > 0) {
3830 sb.append(format(" %s %20.8f %12d %12.3f\n", "Restrain Groups ", restrainGroupEnergy,
3831 nRestrainGroups, restrainGroupTime * toSeconds));
3832 }
3833 if (ncsTerm) {
3834 sb.append(format(" %s %20.8f %12d %12.3f\n", "NCS Restraint ", ncsEnergy, nAtoms,
3835 ncsTime * toSeconds));
3836 }
3837 if (comTerm) {
3838 sb.append(format(" %s %20.8f %12d %12.3f\n", "COM Restraint ", comRestraintEnergy, nAtoms,
3839 comRestraintTime * toSeconds));
3840 }
3841 if (vanderWaalsTerm && nVanDerWaalInteractions > 0) {
3842 sb.append(format(" %s %20.8f %12d %12.3f\n", "Van der Waals ", vanDerWaalsEnergy,
3843 nVanDerWaalInteractions, vanDerWaalsTime * toSeconds));
3844 }
3845 if (multipoleTerm && nPermanentInteractions > 0) {
3846 if (polarizationTerm) {
3847 sb.append(format(" %s %20.8f %12d\n", "Atomic Multipoles ", permanentMultipoleEnergy,
3848 nPermanentInteractions));
3849 } else {
3850 if (elecForm == ELEC_FORM.FIXED_CHARGE) {
3851 sb.append(format(" %s %20.8f %12d %12.3f\n", "Atomic Charges ", permanentMultipoleEnergy,
3852 nPermanentInteractions, electrostaticTime * toSeconds));
3853 } else
3854 sb.append(format(" %s %20.8f %12d %12.3f\n", "Atomic Multipoles ", permanentMultipoleEnergy,
3855 nPermanentInteractions, electrostaticTime * toSeconds));
3856 }
3857 }
3858 if (polarizationTerm && nPermanentInteractions > 0) {
3859 sb.append(format(" %s %20.8f %12d %12.3f\n", "Polarization ", polarizationEnergy,
3860 nPermanentInteractions, electrostaticTime * toSeconds));
3861 }
3862 if (generalizedKirkwoodTerm && nGKInteractions > 0) {
3863 sb.append(
3864 format(" %s %20.8f %12d\n", "Solvation ", solvationEnergy, nGKInteractions));
3865 }
3866 if (relativeSolvationTerm) {
3867 sb.append(format(" %s %20.8f %12d\n", "Relative Solvation", relativeSolvationEnergy,
3868 nRelativeSolvations));
3869 }
3870 if (esvTerm) {
3871 sb.append(
3872 format(" %s %20.8f %s\n", "ExtendedSystemBias", esvBias, esvSystem.getLambdaList()));
3873 sb.append(esvSystem.getBiasDecomposition());
3874 }
3875 if (nnTerm) {
3876 sb.append(format(" %s %20.8f %12d %12.3f\n", "Neural Network ", nnEnergy, nAtoms,
3877 nnTime * toSeconds));
3878 }
3879 sb.append(
3880 format(" %s %20.8f %s %12.3f (sec)", "Total Potential ", totalEnergy, "(Kcal/mole)",
3881 totalTime * toSeconds));
3882 int nsymm = crystal.getUnitCell().spaceGroup.getNumberOfSymOps();
3883 if (nsymm > 1) {
3884 sb.append(format("\n %s %20.8f", "Unit Cell ", totalEnergy * nsymm));
3885 }
3886 if (crystal.getUnitCell() != crystal) {
3887 nsymm = crystal.spaceGroup.getNumberOfSymOps();
3888 sb.append(format("\n %s %20.8f", "Replicates Cell ", totalEnergy * nsymm));
3889 }
3890
3891 return sb.toString();
3892 }
3893
3894
3895
3896
3897
3898 public void logBondedTerms() {
3899 if (bondTerm && nBonds > 0) {
3900 logger.info("\n Bond Stretching Interactions:");
3901 Bond[] bonds = getBonds();
3902 for (Bond bond : bonds) {
3903 logger.info(" Bond \t" + bond.toString());
3904 }
3905 }
3906 if (angleTerm && nAngles > 0) {
3907 logger.info("\n Angle Bending Interactions:");
3908 Angle[] angles = getAngles();
3909 for (Angle angle : angles) {
3910 logger.info(" Angle \t" + angle.toString());
3911 }
3912 }
3913 if (stretchBendTerm && nStretchBends > 0) {
3914 logger.info("\n Stretch-Bend Interactions:");
3915 StretchBend[] stretchBends = getStretchBends();
3916 for (StretchBend stretchBend : stretchBends) {
3917 logger.info(" Stretch-Bend \t" + stretchBend.toString());
3918 }
3919 }
3920 if (ureyBradleyTerm && nUreyBradleys > 0) {
3921 logger.info("\n Urey-Bradley Interactions:");
3922 UreyBradley[] ureyBradleys = getUreyBradleys();
3923 for (UreyBradley ureyBradley : ureyBradleys) {
3924 logger.info("Urey-Bradley \t" + ureyBradley.toString());
3925 }
3926 }
3927 if (outOfPlaneBendTerm && nOutOfPlaneBends > 0) {
3928 logger.info("\n Out-of-Plane Bend Interactions:");
3929 OutOfPlaneBend[] outOfPlaneBends = getOutOfPlaneBends();
3930 for (OutOfPlaneBend outOfPlaneBend : outOfPlaneBends) {
3931 logger.info(" Out-of-Plane Bend \t" + outOfPlaneBend.toString());
3932 }
3933 }
3934 if (torsionTerm && nTorsions > 0) {
3935 logger.info("\n Torsion Angle Interactions:");
3936 Torsion[] torsions = getTorsions();
3937 for (Torsion torsion : torsions) {
3938 logger.info(" Torsion \t" + torsion.toString());
3939 }
3940 }
3941 if (piOrbitalTorsionTerm && nPiOrbitalTorsions > 0) {
3942 logger.info("\n Pi-Orbital Torsion Interactions:");
3943 PiOrbitalTorsion[] piOrbitalTorsions = getPiOrbitalTorsions();
3944 for (PiOrbitalTorsion piOrbitalTorsion : piOrbitalTorsions) {
3945 logger.info(" Pi-Torsion \t" + piOrbitalTorsion.toString());
3946 }
3947 }
3948 if (stretchTorsionTerm && nStretchTorsions > 0) {
3949 logger.info("\n Stretch-Torsion Interactions:");
3950 StretchTorsion[] stretchTorsions = getStretchTorsions();
3951 for (StretchTorsion stretchTorsion : stretchTorsions) {
3952 logger.info(" Stretch-Torsion \t" + stretchTorsion.toString());
3953 }
3954 }
3955 if (angleTorsionTerm && nAngleTorsions > 0) {
3956 logger.info("\n Angle-Torsion Interactions:");
3957 AngleTorsion[] angleTorsions = getAngleTorsions();
3958 for (AngleTorsion angleTorsion : angleTorsions) {
3959 logger.info(" Angle-Torsion \t" + angleTorsion.toString());
3960 }
3961 }
3962 if (torsionTorsionTerm && nTorsionTorsions > 0) {
3963 logger.info("\n Torsion-Torsion Interactions:");
3964 TorsionTorsion[] torsionTorsions = getTorsionTorsions();
3965 for (TorsionTorsion torsionTorsion : torsionTorsions) {
3966 logger.info(" Torsion-Torsion \t" + torsionTorsion.toString());
3967 }
3968 }
3969 if (improperTorsionTerm && nImproperTorsions > 0) {
3970 logger.info("\n Improper Interactions:");
3971 ImproperTorsion[] improperTorsions = getImproperTorsions();
3972 for (ImproperTorsion improperTorsion : improperTorsions) {
3973 logger.info(" Improper \t" + improperTorsion.toString());
3974 }
3975 }
3976 if (restrainDistanceTerm && nRestrainDistances > 0) {
3977 logger.info("\n Restrain Distance Interactions:");
3978 List<RestrainDistance> restrainDistances = getRestrainDistances(null);
3979 for (RestrainDistance restrainDistance : restrainDistances) {
3980 logger.info(" Restrain Distance \t" + restrainDistance.toString());
3981 }
3982 }
3983 if (restrainTorsionTerm && nRestrainTorsions > 0) {
3984 logger.info("\n Restrain Torsion Interactions:");
3985 for (RestraintTorsion restraintTorsion : restrainTorsions) {
3986 logger.info(" Restrain Torsion \t" + restraintTorsion.toString());
3987 }
3988 }
3989 if (restrainPositionTerm && nRestrainPositions > 0) {
3990 logger.info("\n Restrain Position Interactions:");
3991 for (RestrainPosition restrainPosition : restrainPositions) {
3992 logger.info(" Restrain Position \t" + restrainPosition.toString());
3993 }
3994 }
3995 if (restrainGroupTerm && nRestrainGroups > 0) {
3996 logger.info("\n Restrain Group Interactions:");
3997 logger.info(restrainGroups.toString());
3998 }
3999 }
4000
4001
4002
4003
4004
4005
4006
4007 void setLambdaBondedTerms(boolean lambdaBondedTerms, boolean lambdaAllBondedTerms) {
4008 this.lambdaBondedTerms = lambdaBondedTerms;
4009 this.lambdaAllBondedTerms = lambdaAllBondedTerms;
4010 }
4011
4012
4013
4014
4015
4016
4017
4018 private double getNonbondedEnergy(boolean includeSolv) {
4019 return (includeSolv ? (totalNonBondedEnergy + solvationEnergy) : totalNonBondedEnergy);
4020 }
4021
4022
4023
4024
4025
4026
4027
4028
4029 private double[] fillGradient(double[] g) {
4030 assert (g != null);
4031 double[] grad = new double[3];
4032 int n = getNumberOfVariables();
4033 if (g == null || g.length < n) {
4034 g = new double[n];
4035 }
4036 int index = 0;
4037 for (int i = 0; i < nAtoms; i++) {
4038 Atom a = atoms[i];
4039 if (a.isActive()) {
4040 a.getXYZGradient(grad);
4041 double gx = grad[0];
4042 double gy = grad[1];
4043 double gz = grad[2];
4044 if (isNaN(gx) || isInfinite(gx) || isNaN(gy) || isInfinite(gy) || isNaN(gz) || isInfinite(
4045 gz)) {
4046 StringBuilder sb = new StringBuilder(
4047 format("The gradient of atom %s is (%8.3f,%8.3f,%8.3f).", a, gx, gy, gz));
4048 double[] vals = new double[3];
4049 a.getVelocity(vals);
4050 sb.append(format("\n Velocities: %8.3g %8.3g %8.3g", vals[0], vals[1], vals[2]));
4051 a.getAcceleration(vals);
4052 sb.append(format("\n Accelerations: %8.3g %8.3g %8.3g", vals[0], vals[1], vals[2]));
4053 a.getPreviousAcceleration(vals);
4054 sb.append(
4055 format("\n Previous accelerations: %8.3g %8.3g %8.3g", vals[0], vals[1], vals[2]));
4056
4057 throw new EnergyException(sb.toString());
4058 }
4059 g[index++] = gx;
4060 g[index++] = gy;
4061 g[index++] = gz;
4062 }
4063 }
4064 return g;
4065 }
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079 private void setRestrainDistance(Atom a1, Atom a2, double distance, double forceConstant,
4080 double flatBottom, double lamStart, double lamEnd,
4081 UnivariateSwitchingFunction switchingFunction) {
4082 restrainDistanceTerm = true;
4083 boolean rbLambda = !(switchingFunction instanceof ConstantSwitch) && lambdaTerm;
4084 RestrainDistance restrainDistance = new RestrainDistance(a1, a2, crystal, rbLambda, lamStart, lamEnd, switchingFunction);
4085 int[] classes = {a1.getAtomType().atomClass, a2.getAtomType().atomClass};
4086 if (flatBottom != 0) {
4087 BondType bondType = new BondType(classes, forceConstant, distance,
4088 BondType.BondFunction.FLAT_BOTTOM_HARMONIC, flatBottom);
4089 restrainDistance.setBondType(bondType);
4090 } else {
4091 BondType bondType = new BondType(classes, forceConstant, distance,
4092 BondType.BondFunction.HARMONIC);
4093 restrainDistance.setBondType(bondType);
4094 }
4095
4096 if (restrainDistances == null) {
4097 nRestrainDistances = 0;
4098 }
4099
4100 RestrainDistance[] restrainDistances1 = new RestrainDistance[++nRestrainDistances];
4101 if (restrainDistances != null && restrainDistances.length != 0) {
4102 arraycopy(restrainDistances, 0, restrainDistances1, 0, (nRestrainDistances - 1));
4103 }
4104 restrainDistances1[nRestrainDistances - 1] = restrainDistance;
4105 restrainDistances = restrainDistances1;
4106 restrainDistance.energy(false);
4107 restrainDistance.log();
4108 }
4109
4110 private Crystal configureNCS(ForceField forceField, Crystal unitCell) {
4111
4112
4113 if (forceField.getProperties().containsKey("MTRIX1")
4114 && forceField.getProperties().containsKey("MTRIX2") && forceField.getProperties()
4115 .containsKey("MTRIX3")) {
4116 Crystal unitCell2 = new Crystal(unitCell.a, unitCell.b, unitCell.c, unitCell.alpha,
4117 unitCell.beta, unitCell.gamma, unitCell.spaceGroup.pdbName);
4118 SpaceGroup spaceGroup = unitCell2.spaceGroup;
4119
4120 CompositeConfiguration properties = forceField.getProperties();
4121 String[] MTRX1List = properties.getStringArray("MTRIX1");
4122 String[] MTRX2List = properties.getStringArray("MTRIX2");
4123 String[] MTRX3List = properties.getStringArray("MTRIX3");
4124 spaceGroup.symOps.clear();
4125 double number1;
4126 double number2;
4127 double number3;
4128 for (int i = 0; i < MTRX1List.length; i++) {
4129 double[][] Rot_MTRX = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
4130 double[] Tr_MTRX = {0, 0, 0};
4131 String[] tokens1 = MTRX1List[i].trim().split(" +");
4132 String[] tokens2 = MTRX2List[i].trim().split(" +");
4133 String[] tokens3 = MTRX3List[i].trim().split(" +");
4134 for (int k = 0; k < 4; k++) {
4135 number1 = Double.parseDouble(tokens1[k]);
4136 number2 = Double.parseDouble(tokens2[k]);
4137 number3 = Double.parseDouble(tokens3[k]);
4138 if (k != 3) {
4139 Rot_MTRX[0][k] = number1;
4140 Rot_MTRX[1][k] = number2;
4141 Rot_MTRX[2][k] = number3;
4142 } else {
4143 Tr_MTRX[0] = number1;
4144 Tr_MTRX[1] = number2;
4145 Tr_MTRX[2] = number3;
4146 }
4147 }
4148 SymOp symOp = new SymOp(Rot_MTRX, Tr_MTRX);
4149 if (logger.isLoggable(Level.FINEST)) {
4150 logger.info(
4151 format(" MTRIXn SymOp: %d of %d\n" + symOp, i + 1, MTRX1List.length));
4152 }
4153 spaceGroup.symOps.add(symOp);
4154 }
4155 unitCell = NCSCrystal.NCSCrystalFactory(unitCell, spaceGroup.symOps);
4156 unitCell.updateCrystal();
4157 }
4158 return unitCell;
4159 }
4160
4161
4162
4163
4164
4165
4166
4167 public List<RestrainDistance> getRestrainDistances(@Nullable BondType.BondFunction bondFunction) {
4168 List<RestrainDistance> list = new ArrayList<>();
4169 if (restrainDistances != null && restrainDistances.length > 0) {
4170
4171 if (bondFunction == null) {
4172 return Arrays.asList(restrainDistances);
4173 }
4174
4175 for (RestrainDistance restrainDistance : restrainDistances) {
4176 if (restrainDistance.getBondType().bondFunction == bondFunction) {
4177 list.add(restrainDistance);
4178 }
4179 }
4180 if (!list.isEmpty()) {
4181 return list;
4182 }
4183 }
4184 return null;
4185 }
4186
4187
4188
4189
4190
4191
4192 public List<RestraintTorsion> getRestrainTorsions() {
4193 if (restrainTorsions != null && restrainTorsions.length > 0) {
4194 return Arrays.asList(restrainTorsions);
4195 } else {
4196 return null;
4197 }
4198 }
4199
4200
4201
4202
4203
4204
4205 public RestrainGroups getRestrainGroups() {
4206 return restrainGroups;
4207 }
4208
4209 private class BondedRegion extends ParallelRegion {
4210
4211
4212 private final SharedDouble sharedBondRMSD;
4213 private final SharedDouble sharedAngleRMSD;
4214
4215 private final SharedDouble sharedBondEnergy;
4216 private final SharedDouble sharedAngleEnergy;
4217 private final SharedDouble sharedOutOfPlaneBendEnergy;
4218 private final SharedDouble sharedPiOrbitalTorsionEnergy;
4219 private final SharedDouble sharedStretchBendEnergy;
4220 private final SharedDouble sharedUreyBradleyEnergy;
4221 private final SharedDouble sharedImproperTorsionEnergy;
4222 private final SharedDouble sharedTorsionEnergy;
4223 private final SharedDouble sharedStretchTorsionEnergy;
4224 private final SharedDouble sharedAngleTorsionEnergy;
4225 private final SharedDouble sharedTorsionTorsionEnergy;
4226 private final SharedDouble sharedRestrainPositionEnergy;
4227 private final SharedDouble sharedRestrainDistanceEnergy;
4228 private final SharedDouble sharedRestrainTorsionEnergy;
4229
4230 private final int nThreads;
4231
4232 private final GradInitLoop[] gradInitLoops;
4233 private final GradReduceLoop[] gradReduceLoops;
4234
4235 private final BondedTermLoop[] bondLoops;
4236 private final BondedTermLoop[] angleLoops;
4237 private final BondedTermLoop[] outOfPlaneBendLoops;
4238 private final BondedTermLoop[] improperTorsionLoops;
4239 private final BondedTermLoop[] piOrbitalTorsionLoops;
4240 private final BondedTermLoop[] stretchBendLoops;
4241 private final BondedTermLoop[] torsionLoops;
4242 private final BondedTermLoop[] stretchTorsionLoops;
4243 private final BondedTermLoop[] angleTorsionLoops;
4244 private final BondedTermLoop[] torsionTorsionLoops;
4245 private final BondedTermLoop[] ureyBradleyLoops;
4246
4247 private final BondedTermLoop[] restrainPositionLoops;
4248 private final BondedTermLoop[] restrainDistanceLoops;
4249 private final BondedTermLoop[] restrainTorsionLoops;
4250 private final AtomicDoubleArray3D grad;
4251
4252 private boolean gradient = false;
4253 private AtomicDoubleArrayImpl atomicDoubleArrayImpl;
4254 private AtomicDoubleArray3D lambdaGrad;
4255
4256 BondedRegion() {
4257
4258
4259 sharedAngleRMSD = new SharedDouble();
4260 sharedBondRMSD = new SharedDouble();
4261
4262
4263 sharedBondEnergy = new SharedDouble();
4264 sharedAngleEnergy = new SharedDouble();
4265 sharedImproperTorsionEnergy = new SharedDouble();
4266 sharedOutOfPlaneBendEnergy = new SharedDouble();
4267 sharedPiOrbitalTorsionEnergy = new SharedDouble();
4268 sharedStretchBendEnergy = new SharedDouble();
4269 sharedTorsionEnergy = new SharedDouble();
4270 sharedStretchTorsionEnergy = new SharedDouble();
4271 sharedAngleTorsionEnergy = new SharedDouble();
4272 sharedTorsionTorsionEnergy = new SharedDouble();
4273 sharedUreyBradleyEnergy = new SharedDouble();
4274
4275
4276 sharedRestrainPositionEnergy = new SharedDouble();
4277 sharedRestrainDistanceEnergy = new SharedDouble();
4278 sharedRestrainTorsionEnergy = new SharedDouble();
4279
4280 nThreads = parallelTeam.getThreadCount();
4281
4282
4283 gradInitLoops = new GradInitLoop[nThreads];
4284 gradReduceLoops = new GradReduceLoop[nThreads];
4285
4286
4287 angleLoops = new BondedTermLoop[nThreads];
4288 bondLoops = new BondedTermLoop[nThreads];
4289 improperTorsionLoops = new BondedTermLoop[nThreads];
4290 outOfPlaneBendLoops = new BondedTermLoop[nThreads];
4291 piOrbitalTorsionLoops = new BondedTermLoop[nThreads];
4292 stretchBendLoops = new BondedTermLoop[nThreads];
4293 torsionLoops = new BondedTermLoop[nThreads];
4294 stretchTorsionLoops = new BondedTermLoop[nThreads];
4295 angleTorsionLoops = new BondedTermLoop[nThreads];
4296 torsionTorsionLoops = new BondedTermLoop[nThreads];
4297 ureyBradleyLoops = new BondedTermLoop[nThreads];
4298 restrainPositionLoops = new BondedTermLoop[nThreads];
4299 restrainTorsionLoops = new BondedTermLoop[nThreads];
4300 restrainDistanceLoops = new BondedTermLoop[nThreads];
4301
4302
4303 atomicDoubleArrayImpl = AtomicDoubleArrayImpl.MULTI;
4304 ForceField forceField = molecularAssembly.getForceField();
4305
4306 String value = forceField.getString("ARRAY_REDUCTION", "MULTI");
4307 try {
4308 atomicDoubleArrayImpl = AtomicDoubleArrayImpl.valueOf(toEnumForm(value));
4309 } catch (Exception e) {
4310 logger.info(format(" Unrecognized ARRAY-REDUCTION %s; defaulting to %s", value,
4311 atomicDoubleArrayImpl));
4312 }
4313 logger.fine(format(" Bonded using %s arrays.", atomicDoubleArrayImpl.toString()));
4314
4315 grad = new AtomicDoubleArray3D(atomicDoubleArrayImpl, nAtoms, nThreads);
4316 if (lambdaTerm) {
4317 lambdaGrad = new AtomicDoubleArray3D(atomicDoubleArrayImpl, nAtoms, nThreads);
4318 }
4319 }
4320
4321 @Override
4322 public void finish() {
4323
4324 if (bondTerm) {
4325 bondRMSD = sqrt(sharedBondRMSD.get() / bonds.length);
4326 }
4327 if (angleTerm) {
4328 angleRMSD = sqrt(sharedAngleRMSD.get() / angles.length);
4329 }
4330
4331
4332 angleEnergy = sharedAngleEnergy.get();
4333 bondEnergy = sharedBondEnergy.get();
4334 improperTorsionEnergy = sharedImproperTorsionEnergy.get();
4335 outOfPlaneBendEnergy = sharedOutOfPlaneBendEnergy.get();
4336 piOrbitalTorsionEnergy = sharedPiOrbitalTorsionEnergy.get();
4337 stretchBendEnergy = sharedStretchBendEnergy.get();
4338 ureyBradleyEnergy = sharedUreyBradleyEnergy.get();
4339 torsionEnergy = sharedTorsionEnergy.get();
4340 stretchTorsionEnergy = sharedStretchTorsionEnergy.get();
4341 angleTorsionEnergy = sharedAngleTorsionEnergy.get();
4342 torsionTorsionEnergy = sharedTorsionTorsionEnergy.get();
4343 ureyBradleyEnergy = sharedUreyBradleyEnergy.get();
4344
4345
4346 restrainPositionEnergy = sharedRestrainPositionEnergy.get();
4347 restrainDistanceEnergy = sharedRestrainDistanceEnergy.get();
4348 restrainTorsionEnergy = sharedRestrainTorsionEnergy.get();
4349 }
4350
4351 @Override
4352 public void run() throws Exception {
4353 int threadID = getThreadIndex();
4354
4355
4356 if (gradient) {
4357 if (gradInitLoops[threadID] == null) {
4358 gradInitLoops[threadID] = new GradInitLoop();
4359 }
4360 execute(0, nAtoms - 1, gradInitLoops[threadID]);
4361 }
4362
4363
4364 if (angleTerm) {
4365 if (angleLoops[threadID] == null) {
4366 angleLoops[threadID] = new BondedTermLoop(angles, sharedAngleEnergy, sharedAngleRMSD);
4367 }
4368 if (threadID == 0) {
4369 angleTime = -System.nanoTime();
4370 }
4371 execute(0, nAngles - 1, angleLoops[threadID]);
4372 if (threadID == 0) {
4373 angleTime += System.nanoTime();
4374 }
4375 }
4376
4377 if (bondTerm) {
4378 if (bondLoops[threadID] == null) {
4379 bondLoops[threadID] = new BondedTermLoop(bonds, sharedBondEnergy, sharedBondRMSD);
4380 }
4381 if (threadID == 0) {
4382 bondTime = -System.nanoTime();
4383 }
4384 execute(0, nBonds - 1, bondLoops[threadID]);
4385 if (threadID == 0) {
4386 bondTime += System.nanoTime();
4387 }
4388 }
4389
4390 if (improperTorsionTerm) {
4391 if (improperTorsionLoops[threadID] == null) {
4392 improperTorsionLoops[threadID] = new BondedTermLoop(improperTorsions,
4393 sharedImproperTorsionEnergy);
4394 }
4395 if (threadID == 0) {
4396 improperTorsionTime = -System.nanoTime();
4397 }
4398 execute(0, nImproperTorsions - 1, improperTorsionLoops[threadID]);
4399 if (threadID == 0) {
4400 improperTorsionTime += System.nanoTime();
4401 }
4402 }
4403
4404 if (outOfPlaneBendTerm) {
4405 if (outOfPlaneBendLoops[threadID] == null) {
4406 outOfPlaneBendLoops[threadID] = new BondedTermLoop(outOfPlaneBends,
4407 sharedOutOfPlaneBendEnergy);
4408 }
4409 if (threadID == 0) {
4410 outOfPlaneBendTime = -System.nanoTime();
4411 }
4412 execute(0, nOutOfPlaneBends - 1, outOfPlaneBendLoops[threadID]);
4413 if (threadID == 0) {
4414 outOfPlaneBendTime += System.nanoTime();
4415 }
4416 }
4417
4418 if (piOrbitalTorsionTerm) {
4419 if (piOrbitalTorsionLoops[threadID] == null) {
4420 piOrbitalTorsionLoops[threadID] = new BondedTermLoop(piOrbitalTorsions,
4421 sharedPiOrbitalTorsionEnergy);
4422 }
4423 if (threadID == 0) {
4424 piOrbitalTorsionTime = -System.nanoTime();
4425 }
4426 execute(0, nPiOrbitalTorsions - 1, piOrbitalTorsionLoops[threadID]);
4427 if (threadID == 0) {
4428 piOrbitalTorsionTime += System.nanoTime();
4429 }
4430 }
4431
4432 if (stretchBendTerm) {
4433 if (stretchBendLoops[threadID] == null) {
4434 stretchBendLoops[threadID] = new BondedTermLoop(stretchBends, sharedStretchBendEnergy);
4435 }
4436 if (threadID == 0) {
4437 stretchBendTime = -System.nanoTime();
4438 }
4439 execute(0, nStretchBends - 1, stretchBendLoops[threadID]);
4440 if (threadID == 0) {
4441 stretchBendTime += System.nanoTime();
4442 }
4443 }
4444
4445 if (torsionTerm) {
4446 if (torsionLoops[threadID] == null) {
4447 torsionLoops[threadID] = new BondedTermLoop(torsions, sharedTorsionEnergy);
4448 }
4449 if (threadID == 0) {
4450 torsionTime = -System.nanoTime();
4451 }
4452 execute(0, nTorsions - 1, torsionLoops[threadID]);
4453 if (threadID == 0) {
4454 torsionTime += System.nanoTime();
4455 }
4456 }
4457
4458 if (stretchTorsionTerm) {
4459 if (stretchTorsionLoops[threadID] == null) {
4460 stretchTorsionLoops[threadID] = new BondedTermLoop(stretchTorsions,
4461 sharedStretchTorsionEnergy);
4462 }
4463 if (threadID == 0) {
4464 stretchTorsionTime = -System.nanoTime();
4465 }
4466 execute(0, nStretchTorsions - 1, stretchTorsionLoops[threadID]);
4467 if (threadID == 0) {
4468 stretchTorsionTime += System.nanoTime();
4469 }
4470 }
4471
4472 if (angleTorsionTerm) {
4473 if (angleTorsionLoops[threadID] == null) {
4474 angleTorsionLoops[threadID] = new BondedTermLoop(angleTorsions, sharedAngleTorsionEnergy);
4475 }
4476 if (threadID == 0) {
4477 angleTorsionTime = -System.nanoTime();
4478 }
4479 execute(0, nAngleTorsions - 1, angleTorsionLoops[threadID]);
4480 if (threadID == 0) {
4481 angleTorsionTime += System.nanoTime();
4482 }
4483 }
4484
4485 if (torsionTorsionTerm) {
4486 if (torsionTorsionLoops[threadID] == null) {
4487 torsionTorsionLoops[threadID] = new BondedTermLoop(torsionTorsions,
4488 sharedTorsionTorsionEnergy);
4489 }
4490 if (threadID == 0) {
4491 torsionTorsionTime = -System.nanoTime();
4492 }
4493 execute(0, nTorsionTorsions - 1, torsionTorsionLoops[threadID]);
4494 if (threadID == 0) {
4495 torsionTorsionTime += System.nanoTime();
4496 }
4497 }
4498
4499 if (ureyBradleyTerm) {
4500 if (ureyBradleyLoops[threadID] == null) {
4501 ureyBradleyLoops[threadID] = new BondedTermLoop(ureyBradleys, sharedUreyBradleyEnergy);
4502 }
4503 if (threadID == 0) {
4504 ureyBradleyTime = -System.nanoTime();
4505 }
4506 execute(0, nUreyBradleys - 1, ureyBradleyLoops[threadID]);
4507 if (threadID == 0) {
4508 ureyBradleyTime += System.nanoTime();
4509 }
4510 }
4511
4512
4513 if (restrainPositionTerm && nRestrainPositions > 0) {
4514 if (restrainPositionLoops[threadID] == null) {
4515 restrainPositionLoops[threadID] = new BondedTermLoop(restrainPositions, sharedRestrainPositionEnergy);
4516 }
4517 if (threadID == 0) {
4518 restrainPositionTime = -System.nanoTime();
4519 }
4520 execute(0, nRestrainPositions - 1, restrainPositionLoops[threadID]);
4521 if (threadID == 0) {
4522 restrainPositionTime += System.nanoTime();
4523 }
4524 }
4525
4526
4527 if (restrainDistanceTerm && nRestrainDistances > 0) {
4528 if (restrainDistanceLoops[threadID] == null) {
4529 restrainDistanceLoops[threadID] = new BondedTermLoop(restrainDistances, sharedRestrainDistanceEnergy);
4530 }
4531 if (threadID == 0) {
4532 restrainDistanceTime = -System.nanoTime();
4533 }
4534 execute(0, nRestrainDistances - 1, restrainDistanceLoops[threadID]);
4535 if (threadID == 0) {
4536 restrainDistanceTime += System.nanoTime();
4537 }
4538 }
4539
4540
4541 if (restrainTorsionTerm && nRestrainTorsions > 0) {
4542 if (restrainTorsionLoops[threadID] == null) {
4543 restrainTorsionLoops[threadID] = new BondedTermLoop(restrainTorsions, sharedRestrainTorsionEnergy);
4544 }
4545 if (threadID == 0) {
4546 restrainTorsionTime = -System.nanoTime();
4547 }
4548 execute(0, nRestrainTorsions - 1, restrainTorsionLoops[threadID]);
4549 if (threadID == 0) {
4550 restrainTorsionTime += System.nanoTime();
4551 }
4552 }
4553
4554
4555 if (gradient) {
4556 if (gradReduceLoops[threadID] == null) {
4557 gradReduceLoops[threadID] = new GradReduceLoop();
4558 }
4559 execute(0, nAtoms - 1, gradReduceLoops[threadID]);
4560 }
4561 }
4562
4563 public void setGradient(boolean gradient) {
4564 this.gradient = gradient;
4565 }
4566
4567 @Override
4568 public void start() {
4569
4570 sharedAngleRMSD.set(0.0);
4571 sharedBondRMSD.set(0.0);
4572
4573
4574 sharedAngleEnergy.set(0.0);
4575 sharedBondEnergy.set(0.0);
4576 sharedImproperTorsionEnergy.set(0.0);
4577 sharedOutOfPlaneBendEnergy.set(0.0);
4578 sharedPiOrbitalTorsionEnergy.set(0.0);
4579 sharedStretchBendEnergy.set(0.0);
4580 sharedTorsionEnergy.set(0.0);
4581 sharedStretchTorsionEnergy.set(0.0);
4582 sharedAngleTorsionEnergy.set(0.0);
4583 sharedTorsionTorsionEnergy.set(0.0);
4584 sharedUreyBradleyEnergy.set(0.0);
4585
4586
4587 sharedRestrainPositionEnergy.set(0.0);
4588 sharedRestrainDistanceEnergy.set(0.0);
4589 sharedRestrainTorsionEnergy.set(0.0);
4590
4591
4592 if (gradient) {
4593 grad.alloc(nAtoms);
4594 }
4595 if (lambdaTerm) {
4596 lambdaGrad.alloc(nAtoms);
4597 }
4598 }
4599
4600 private class GradInitLoop extends IntegerForLoop {
4601
4602 @Override
4603 public void run(int first, int last) {
4604 int threadID = getThreadIndex();
4605 if (gradient) {
4606 grad.reset(threadID, first, last);
4607 for (int i = first; i <= last; i++) {
4608 atoms[i].setXYZGradient(0.0, 0.0, 0.0);
4609 }
4610 }
4611 if (lambdaTerm) {
4612 lambdaGrad.reset(threadID, first, last);
4613 for (int i = first; i <= last; i++) {
4614 atoms[i].setLambdaXYZGradient(0.0, 0.0, 0.0);
4615 }
4616 }
4617 }
4618
4619 @Override
4620 public IntegerSchedule schedule() {
4621 return IntegerSchedule.fixed();
4622 }
4623 }
4624
4625 private class GradReduceLoop extends IntegerForLoop {
4626
4627 @Override
4628 public void run(int first, int last) {
4629 if (gradient) {
4630 grad.reduce(first, last);
4631 for (int i = first; i <= last; i++) {
4632 Atom a = atoms[i];
4633 a.setXYZGradient(grad.getX(i), grad.getY(i), grad.getZ(i));
4634 }
4635 }
4636 if (lambdaTerm) {
4637 lambdaGrad.reduce(first, last);
4638 for (int i = first; i <= last; i++) {
4639 Atom a = atoms[i];
4640 a.setLambdaXYZGradient(lambdaGrad.getX(i), lambdaGrad.getY(i), lambdaGrad.getZ(i));
4641 }
4642 }
4643 }
4644
4645 @Override
4646 public IntegerSchedule schedule() {
4647 return IntegerSchedule.fixed();
4648 }
4649 }
4650
4651 private class BondedTermLoop extends IntegerForLoop {
4652
4653 private final BondedTerm[] terms;
4654 private final SharedDouble sharedEnergy;
4655 private final SharedDouble sharedRMSD;
4656 private final boolean computeRMSD;
4657 private double localEnergy;
4658 private double localRMSD;
4659 private int threadID;
4660
4661 BondedTermLoop(BondedTerm[] terms, SharedDouble sharedEnergy) {
4662 this(terms, sharedEnergy, null);
4663 }
4664
4665 BondedTermLoop(BondedTerm[] terms, SharedDouble sharedEnergy, SharedDouble sharedRMSD) {
4666 this.terms = terms;
4667 this.sharedEnergy = sharedEnergy;
4668 this.sharedRMSD = sharedRMSD;
4669 computeRMSD = (sharedRMSD != null);
4670 }
4671
4672 @Override
4673 public void finish() {
4674 sharedEnergy.addAndGet(localEnergy);
4675 if (computeRMSD) {
4676 sharedRMSD.addAndGet(localRMSD);
4677 }
4678 }
4679
4680 @Override
4681 public void run(int first, int last) {
4682 for (int i = first; i <= last; i++) {
4683 BondedTerm term = terms[i];
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700 boolean used = !lambdaBondedTerms || lambdaAllBondedTerms || (term.applyLambda() && !term.isLambdaScaled());
4701 if (used) {
4702 localEnergy += term.energy(gradient, threadID, grad, lambdaGrad);
4703 if (computeRMSD) {
4704 double value = term.getValue();
4705 localRMSD += value * value;
4706 }
4707 }
4708 }
4709 }
4710
4711 @Override
4712 public void start() {
4713 localEnergy = 0.0;
4714 localRMSD = 0.0;
4715 threadID = getThreadIndex();
4716 }
4717 }
4718 }
4719 }