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.crystal.Crystal;
41 import ffx.potential.bonded.Atom;
42 import ffx.potential.extended.ExtendedSystem;
43 import ffx.potential.nonbonded.NonbondedCutoff;
44 import ffx.potential.nonbonded.VanDerWaals;
45 import ffx.potential.nonbonded.VanDerWaalsForm;
46 import ffx.potential.parameters.ForceField;
47 import ffx.potential.parameters.VDWPairType;
48 import ffx.potential.parameters.VDWType;
49
50 import java.util.HashMap;
51 import java.util.Map;
52 import java.util.logging.Level;
53 import java.util.logging.Logger;
54
55 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_AlchemicalMethod.OpenMM_AmoebaVdwForce_Decouple;
56 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_NonbondedMethod.OpenMM_AmoebaVdwForce_CutoffPeriodic;
57 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_NonbondedMethod.OpenMM_AmoebaVdwForce_NoCutoff;
58 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_addParticleType;
59 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_addParticle_1;
60 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_addTypePair;
61 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_create;
62 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setAlchemicalMethod;
63 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setCutoffDistance;
64 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setNonbondedMethod;
65 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setParticleExclusions;
66 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setParticleParameters;
67 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setSoftcoreAlpha;
68 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setSoftcorePower;
69 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_setUseDispersionCorrection;
70 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_AmoebaVdwForce_updateParametersInContext;
71 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_KJPerKcal;
72 import static edu.uiowa.jopenmm.OpenMMAmoebaLibrary.OpenMM_NmPerAngstrom;
73 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_False;
74 import static edu.uiowa.jopenmm.OpenMMLibrary.OpenMM_Boolean.OpenMM_True;
75 import static java.lang.String.format;
76
77
78
79
80 public class AmoebaVDWForce extends OpenMMForce {
81
82 private static final Logger logger = Logger.getLogger(AmoebaVDWForce.class.getName());
83
84
85
86
87
88
89
90
91 private int vdWClassForNoInteraction = 0;
92
93
94
95
96 private final Map<Integer, Integer> vdwClassToOpenMMType = new HashMap<>();
97
98
99
100
101
102
103 public AmoebaVDWForce(OpenMMEnergy openMMEnergy) {
104 VanDerWaals vdW = openMMEnergy.getVdwNode();
105 if (vdW == null) {
106 return;
107 }
108
109 forcePointer = OpenMM_AmoebaVdwForce_create();
110
111 VanDerWaalsForm vdwForm = vdW.getVDWForm();
112 NonbondedCutoff nonbondedCutoff = vdW.getNonbondedCutoff();
113 Crystal crystal = openMMEnergy.getCrystal();
114
115 double radScale = 1.0;
116 if (vdwForm.radiusSize == VanDerWaalsForm.RADIUS_SIZE.DIAMETER) {
117 radScale = 0.5;
118 }
119
120 ForceField forceField = openMMEnergy.getMolecularAssembly().getForceField();
121
122 Map<String, VDWType> vdwTypes = forceField.getVDWTypes();
123
124 for (VDWType vdwType : vdwTypes.values()) {
125 int atomClass = vdwType.atomClass;
126 if (!vdwClassToOpenMMType.containsKey(atomClass)) {
127 double eps = OpenMM_KJPerKcal * vdwType.wellDepth;
128 double rad = OpenMM_NmPerAngstrom * vdwType.radius * radScale;
129 int type = addParticleType(rad, eps);
130 vdwClassToOpenMMType.put(atomClass, type);
131 if (atomClass <= vdWClassForNoInteraction) {
132 vdWClassForNoInteraction = atomClass - 1;
133 }
134 }
135 }
136
137
138 int type = addParticleType(OpenMM_NmPerAngstrom, 0.0);
139 vdwClassToOpenMMType.put(vdWClassForNoInteraction, type);
140
141 Map<String, VDWPairType> vdwPairTypeMap = forceField.getVDWPairTypes();
142 for (VDWPairType vdwPairType : vdwPairTypeMap.values()) {
143 int c1 = vdwPairType.atomClasses[0];
144 int c2 = vdwPairType.atomClasses[1];
145 int type1 = vdwClassToOpenMMType.get(c1);
146 int type2 = vdwClassToOpenMMType.get(c2);
147 double rMin = vdwPairType.radius * OpenMM_NmPerAngstrom;
148 double eps = vdwPairType.wellDepth * OpenMM_KJPerKcal;
149 addTypePair(type1, type2, rMin, eps);
150 addTypePair(type2, type1, rMin, eps);
151 }
152
153 ExtendedSystem extendedSystem = vdW.getExtendedSystem();
154 double[] vdwPrefactorAndDerivs = new double[3];
155
156 int[] ired = vdW.getReductionIndex();
157 Atom[] atoms = openMMEnergy.getMolecularAssembly().getAtomArray();
158 int nAtoms = atoms.length;
159 for (int i = 0; i < nAtoms; i++) {
160 Atom atom = atoms[i];
161 VDWType vdwType = atom.getVDWType();
162 int atomClass = vdwType.atomClass;
163 type = vdwClassToOpenMMType.get(atomClass);
164 int isAlchemical = atom.applyLambda() ? 1 : 0;
165 double scaleFactor = 1.0;
166 if (extendedSystem != null) {
167 extendedSystem.getVdwPrefactor(i, vdwPrefactorAndDerivs);
168 scaleFactor = vdwPrefactorAndDerivs[0];
169 }
170 addParticle_1(ired[i], type, vdwType.reductionFactor, isAlchemical, scaleFactor);
171 }
172
173 setCutoffDistance(nonbondedCutoff.off * OpenMM_NmPerAngstrom);
174 if (vdW.getDoLongRangeCorrection()) {
175 setUseDispersionCorrection(OpenMM_True);
176 } else {
177 setUseDispersionCorrection(OpenMM_False);
178 }
179
180 if (crystal.aperiodic()) {
181 setNonbondedMethod(OpenMM_AmoebaVdwForce_NoCutoff);
182 } else {
183 setNonbondedMethod(OpenMM_AmoebaVdwForce_CutoffPeriodic);
184 }
185
186 if (openMMEnergy.getSystem().getVdwLambdaTerm()) {
187 setAlchemicalMethod(OpenMM_AmoebaVdwForce_Decouple);
188 setSoftcoreAlpha(vdW.getAlpha());
189 setSoftcorePower((int) vdW.getBeta());
190 }
191
192 int[][] bondMask = vdW.getMask12();
193 int[][] angleMask = vdW.getMask13();
194
195
196 OpenMMIntArray exclusions = new OpenMMIntArray(0);
197 for (int i = 0; i < nAtoms; i++) {
198 exclusions.append(i);
199 final int[] bondMaski = bondMask[i];
200 for (int value : bondMaski) {
201 exclusions.append(value);
202 }
203 final int[] angleMaski = angleMask[i];
204 for (int value : angleMaski) {
205 exclusions.append(value);
206 }
207 setParticleExclusions(i, exclusions);
208 exclusions.resize(0);
209 }
210 exclusions.destroy();
211
212 int forceGroup = forceField.getInteger("VDW_FORCE_GROUP", 1);
213 setForceGroup(forceGroup);
214 logger.log(Level.INFO, format(" AMOEBA van der Waals force \t\t%d", forceGroup));
215 }
216
217
218
219
220
221
222
223 public static OpenMMForce constructForce(OpenMMEnergy openMMEnergy) {
224 VanDerWaals vdW = openMMEnergy.getVdwNode();
225 if (vdW == null) {
226 return null;
227 }
228 return new AmoebaVDWForce(openMMEnergy);
229 }
230
231
232
233
234
235
236
237 public void updateForce(Atom[] atoms, OpenMMEnergy openMMEnergy) {
238 VanDerWaals vdW = openMMEnergy.getVdwNode();
239 VanDerWaalsForm vdwForm = vdW.getVDWForm();
240 double radScale = 1.0;
241 if (vdwForm.radiusSize == VanDerWaalsForm.RADIUS_SIZE.DIAMETER) {
242 radScale = 0.5;
243 }
244
245 ExtendedSystem extendedSystem = vdW.getExtendedSystem();
246 double[] vdwPrefactorAndDerivs = new double[3];
247
248 int[] ired = vdW.getReductionIndex();
249 for (Atom atom : atoms) {
250 int index = atom.getXyzIndex() - 1;
251 VDWType vdwType = atom.getVDWType();
252
253
254 int type = vdwClassToOpenMMType.get(vdwType.atomClass);
255 if (!atom.getUse()) {
256
257 type = vdwClassToOpenMMType.get(vdWClassForNoInteraction);
258 }
259 int isAlchemical = atom.applyLambda() ? 1 : 0;
260 double eps = OpenMM_KJPerKcal * vdwType.wellDepth;
261 double rad = OpenMM_NmPerAngstrom * vdwType.radius * radScale;
262
263 double scaleFactor = 1.0;
264 if (extendedSystem != null) {
265 extendedSystem.getVdwPrefactor(index, vdwPrefactorAndDerivs);
266 scaleFactor = vdwPrefactorAndDerivs[0];
267 }
268
269 setParticleParameters(index, ired[index], rad, eps, vdwType.reductionFactor, isAlchemical, type, scaleFactor);
270 }
271 updateParametersInContext(openMMEnergy.getContext());
272 }
273
274
275
276
277
278
279
280
281 public int addParticleType(double rad, double eps) {
282 return OpenMM_AmoebaVdwForce_addParticleType(forcePointer, rad, eps);
283 }
284
285
286
287
288
289
290
291
292
293 public void addTypePair(int type1, int type2, double rad, double eps) {
294 OpenMM_AmoebaVdwForce_addTypePair(forcePointer, type1, type2, rad, eps);
295 }
296
297
298
299
300
301
302
303
304
305
306 public void addParticle_1(int ired, int type, double reductionFactor, int isAlchemical, double scaleFactor) {
307 OpenMM_AmoebaVdwForce_addParticle_1(forcePointer, ired, type, reductionFactor, isAlchemical, scaleFactor);
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322 public void setParticleParameters(int index, int ired, double rad, double eps, double reductionFactor,
323 int isAlchemical, int type, double scaleFactor) {
324 OpenMM_AmoebaVdwForce_setParticleParameters(forcePointer, index, ired, rad, eps, reductionFactor, isAlchemical, type, scaleFactor);
325 }
326
327
328
329
330
331
332 public void setCutoffDistance(double cutoff) {
333 OpenMM_AmoebaVdwForce_setCutoffDistance(forcePointer, cutoff);
334 }
335
336
337
338
339
340
341 public void setUseDispersionCorrection(int value) {
342 OpenMM_AmoebaVdwForce_setUseDispersionCorrection(forcePointer, value);
343 }
344
345
346
347
348
349
350 public void setNonbondedMethod(int method) {
351 OpenMM_AmoebaVdwForce_setNonbondedMethod(forcePointer, method);
352 }
353
354
355
356
357
358
359 public void setAlchemicalMethod(int method) {
360 OpenMM_AmoebaVdwForce_setAlchemicalMethod(forcePointer, method);
361 }
362
363
364
365
366
367
368 public void setSoftcoreAlpha(double vdWSoftcoreAlpha) {
369 OpenMM_AmoebaVdwForce_setSoftcoreAlpha(forcePointer, vdWSoftcoreAlpha);
370 }
371
372
373
374
375
376
377 public void setSoftcorePower(int vdwSoftcorePower) {
378 OpenMM_AmoebaVdwForce_setSoftcorePower(forcePointer, vdwSoftcorePower);
379 }
380
381
382
383
384
385
386
387 public void setParticleExclusions(int i, OpenMMIntArray exclusions) {
388 OpenMM_AmoebaVdwForce_setParticleExclusions(forcePointer, i, exclusions.getPointer());
389 }
390
391
392
393
394
395
396 public void updateParametersInContext(OpenMMContext openMMContext) {
397 if (openMMContext.hasContextPointer()) {
398 OpenMM_AmoebaVdwForce_updateParametersInContext(forcePointer, openMMContext.getContextPointer());
399 }
400 }
401
402 }