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.openmm;
39
40 import ffx.openmm.Force;
41 import ffx.openmm.PeriodicTorsionForce;
42 import ffx.potential.ForceFieldEnergy;
43 import ffx.potential.bonded.ImproperTorsion;
44 import ffx.potential.parameters.ImproperTorsionType;
45 import ffx.potential.terms.ImproperTorsionPotentialEnergy;
46
47 import java.util.logging.Logger;
48
49 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_KJPerKcal;
50 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_RadiansPerDegree;
51 import static java.lang.String.format;
52
53
54
55
56 public class ImproperTorsionForce extends PeriodicTorsionForce {
57
58 private static final Logger logger = Logger.getLogger(ImproperTorsionForce.class.getName());
59
60
61
62
63
64
65 public ImproperTorsionForce(ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy) {
66 ImproperTorsion[] improperTorsions = improperTorsionPotentialEnergy.getImproperTorsionArray();
67 for (ImproperTorsion improperTorsion : improperTorsions) {
68 int a1 = improperTorsion.getAtom(0).getArrayIndex();
69 int a2 = improperTorsion.getAtom(1).getArrayIndex();
70 int a3 = improperTorsion.getAtom(2).getArrayIndex();
71 int a4 = improperTorsion.getAtom(3).getArrayIndex();
72 ImproperTorsionType type = improperTorsion.improperType;
73 double forceConstant = OpenMM_KJPerKcal * type.impTorUnit * improperTorsion.scaleFactor * type.k;
74 addTorsion(a1, a2, a3, a4, type.periodicity, type.phase * OpenMM_RadiansPerDegree, forceConstant);
75 }
76 int forceGroup = improperTorsionPotentialEnergy.getForceGroup();
77 setForceGroup(forceGroup);
78 logger.info(format(" Improper Torsions: %10d", improperTorsions.length));
79 logger.fine(format(" Force Group: %10d", forceGroup));
80 }
81
82
83
84
85
86
87
88
89 public ImproperTorsionForce(ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy,
90 int topology, OpenMMDualTopologyEnergy openMMDualTopologyEnergy) {
91 ImproperTorsion[] improperTorsions = improperTorsionPotentialEnergy.getImproperTorsionArray();
92 double scale = openMMDualTopologyEnergy.getTopologyScale(topology);
93
94 for (ImproperTorsion improperTorsion : improperTorsions) {
95 int a1 = improperTorsion.getAtom(0).getArrayIndex();
96 int a2 = improperTorsion.getAtom(1).getArrayIndex();
97 int a3 = improperTorsion.getAtom(2).getArrayIndex();
98 int a4 = improperTorsion.getAtom(3).getArrayIndex();
99 a1 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a1);
100 a2 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a2);
101 a3 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a3);
102 a4 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a4);
103 ImproperTorsionType type = improperTorsion.improperType;
104 double forceConstant = OpenMM_KJPerKcal * type.impTorUnit * improperTorsion.scaleFactor * type.k;
105
106 if (!improperTorsion.applyLambda()) {
107 forceConstant *= scale;
108 }
109 addTorsion(a1, a2, a3, a4, type.periodicity, type.phase * OpenMM_RadiansPerDegree, forceConstant);
110 }
111
112 int forceGroup = improperTorsionPotentialEnergy.getForceGroup();
113 setForceGroup(forceGroup);
114 logger.info(format(" Improper Torsions: %10d", improperTorsions.length));
115 logger.fine(format(" Force Group: %10d", forceGroup));
116 }
117
118
119
120
121
122
123
124 public static Force constructForce(OpenMMEnergy openMMEnergy) {
125 ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy = openMMEnergy.getImproperTorsionPotentialEnergy();
126 if (improperTorsionPotentialEnergy == null) {
127 return null;
128 }
129 return new ImproperTorsionForce(improperTorsionPotentialEnergy);
130 }
131
132
133
134
135
136
137
138
139 public static Force constructForce(int topology, OpenMMDualTopologyEnergy openMMDualTopologyEnergy) {
140 ForceFieldEnergy forceFieldEnergy = openMMDualTopologyEnergy.getForceFieldEnergy(topology);
141 ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy = forceFieldEnergy.getImproperTorsionPotentialEnergy();
142 if (improperTorsionPotentialEnergy == null) {
143 return null;
144 }
145 return new ImproperTorsionForce(improperTorsionPotentialEnergy, topology, openMMDualTopologyEnergy);
146 }
147
148
149
150
151
152
153 public void updateForce(OpenMMEnergy openMMEnergy) {
154 ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy = openMMEnergy.getImproperTorsionPotentialEnergy();
155 if (improperTorsionPotentialEnergy == null) {
156 return;
157 }
158 ImproperTorsion[] improperTorsions = improperTorsionPotentialEnergy.getImproperTorsionArray();
159 int nImproperTorsions = improperTorsions.length;
160 for (int i = 0; i < nImproperTorsions; i++) {
161 ImproperTorsion improperTorsion = improperTorsions[i];
162 int a1 = improperTorsion.getAtom(0).getXyzIndex() - 1;
163 int a2 = improperTorsion.getAtom(1).getXyzIndex() - 1;
164 int a3 = improperTorsion.getAtom(2).getXyzIndex() - 1;
165 int a4 = improperTorsion.getAtom(3).getXyzIndex() - 1;
166 ImproperTorsionType type = improperTorsion.improperType;
167 double forceConstant = OpenMM_KJPerKcal * type.impTorUnit * improperTorsion.scaleFactor * type.k;
168 setTorsionParameters(i, a1, a2, a3, a4, type.periodicity, type.phase * OpenMM_RadiansPerDegree, forceConstant);
169 }
170
171 updateParametersInContext(openMMEnergy.getContext());
172 }
173
174
175
176
177
178
179
180 public void updateForce(int topology, OpenMMDualTopologyEnergy openMMDualTopologyEnergy) {
181 ForceFieldEnergy forceFieldEnergy = openMMDualTopologyEnergy.getForceFieldEnergy(topology);
182 ImproperTorsionPotentialEnergy improperTorsionPotentialEnergy = forceFieldEnergy.getImproperTorsionPotentialEnergy();
183 if (improperTorsionPotentialEnergy == null) {
184 return;
185 }
186 ImproperTorsion[] improperTorsions = improperTorsionPotentialEnergy.getImproperTorsionArray();
187 double scale = openMMDualTopologyEnergy.getTopologyScale(topology);
188
189 int nImproperTorsions = improperTorsions.length;
190 for (int i = 0; i < nImproperTorsions; i++) {
191 ImproperTorsion improperTorsion = improperTorsions[i];
192 int a1 = improperTorsion.getAtom(0).getArrayIndex();
193 int a2 = improperTorsion.getAtom(1).getArrayIndex();
194 int a3 = improperTorsion.getAtom(2).getArrayIndex();
195 int a4 = improperTorsion.getAtom(3).getArrayIndex();
196 a1 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a1);
197 a2 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a2);
198 a3 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a3);
199 a4 = openMMDualTopologyEnergy.mapToDualTopologyIndex(topology, a4);
200 ImproperTorsionType type = improperTorsion.improperType;
201 double forceConstant = OpenMM_KJPerKcal * type.impTorUnit * improperTorsion.scaleFactor * type.k;
202
203 if (!improperTorsion.applyLambda()) {
204 forceConstant *= scale;
205 }
206 setTorsionParameters(i, a1, a2, a3, a4, type.periodicity, type.phase * OpenMM_RadiansPerDegree, forceConstant);
207 }
208
209 updateParametersInContext(openMMDualTopologyEnergy.getContext());
210 }
211
212 }