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.parameters;
39
40 import ffx.utilities.FFXProperty;
41 import org.w3c.dom.Document;
42 import org.w3c.dom.Element;
43
44 import java.util.Comparator;
45 import java.util.Map;
46 import java.util.Objects;
47 import java.util.logging.Level;
48 import java.util.logging.Logger;
49
50 import static ffx.potential.parameters.ForceField.ForceFieldType.VDW;
51 import static ffx.potential.parameters.ForceField.ForceFieldType.VDW14;
52 import static ffx.utilities.Constants.ANG_TO_NM;
53 import static ffx.utilities.Constants.KCAL_TO_KJ;
54 import static ffx.utilities.PropertyGroup.PotentialFunctionParameter;
55 import static java.lang.Double.parseDouble;
56 import static java.lang.Integer.parseInt;
57 import static java.lang.StrictMath.abs;
58 import static java.lang.String.format;
59 import static java.lang.String.valueOf;
60
61
62
63
64
65
66
67
68 @FFXProperty(name = "vdw", clazz = String.class, propertyGroup = PotentialFunctionParameter,
69 description = """
70 [1 integer and 3 reals]
71 Provides values for a single van der Waals parameter. The integer modifier, if positive,
72 gives the atom class number for which vdw parameters are to be defined. Note that vdw parameters are given for atom classes, not atom types.
73 The three real number modifiers give the values of the atom size in Angstroms, homoatomic well depth in kcal/mole,
74 and an optional reduction factor for univalent atoms.
75 """)
76 @FFXProperty(name = "vdw14", clazz = String.class, propertyGroup = PotentialFunctionParameter,
77 description = """
78 [1 integer and 2 reals]
79 Provides values for a single van der Waals parameter for use in 1-4 nonbonded interactions.
80 The integer modifier, if positive, gives the atom class number for which vdw parameters are to be defined.
81 Note that vdw parameters are given for atom classes, not atom types.
82 The two real number modifiers give the values of the atom size in Angstroms and the homoatomic well depth in kcal/mole.
83 Reduction factors, if used, are carried over from the vdw keyword for the same atom class.
84 """)
85 public final class VDWType extends BaseType implements Comparator<String> {
86
87 private static final Logger logger = Logger.getLogger(VDWType.class.getName());
88
89
90
91 public static final double DEFAULT_GAMMA = 0.12;
92
93
94
95 public static final double DEFAULT_DELTA = 0.07;
96
97
98
99 public static final EPSILON_RULE DEFAULT_EPSILON_RULE = EPSILON_RULE.GEOMETRIC;
100
101
102
103 public static final RADIUS_RULE DEFAULT_RADIUS_RULE = RADIUS_RULE.ARITHMETIC;
104
105
106
107 public static final RADIUS_SIZE DEFAULT_RADIUS_SIZE = RADIUS_SIZE.RADIUS;
108
109
110
111 public static final RADIUS_TYPE DEFAULT_RADIUS_TYPE = RADIUS_TYPE.R_MIN;
112
113
114
115 public static final VDW_TYPE DEFAULT_VDW_TYPE = VDW_TYPE.LENNARD_JONES;
116
117
118
119 public static final double DEFAULT_VDW_12_SCALE = 0.0;
120
121
122
123 public static final double DEFAULT_VDW_13_SCALE = 0.0;
124
125
126
127 public static final double DEFAULT_VDW_14_SCALE = 1.0;
128
129
130
131
132 public final double radius;
133
134
135
136 public final double wellDepth;
137
138
139
140
141
142 public final double reductionFactor;
143
144
145
146 public int atomClass;
147
148
149
150 private final VDWMode vdwMode;
151
152
153
154
155
156
157
158
159
160
161 public VDWType(int atomClass, double radius, double wellDepth, double reductionFactor) {
162 this(atomClass, radius, wellDepth, reductionFactor, VDWMode.NORMAL);
163 }
164
165
166
167
168
169
170
171
172
173
174
175 public VDWType(int atomClass, double radius, double wellDepth, double reductionFactor,
176 VDWMode vdwMode) {
177 super(VDW, Integer.toString(atomClass));
178 this.atomClass = atomClass;
179 this.radius = radius;
180 this.wellDepth = abs(wellDepth);
181 this.reductionFactor = reductionFactor;
182 this.vdwMode = vdwMode;
183 if (vdwMode == VDWMode.VDW14) {
184 forceFieldType = VDW14;
185 }
186 }
187
188
189
190
191
192
193
194
195
196 public static VDWType average(VDWType vdwType1, VDWType vdwType2, int atomClass) {
197 if (vdwType1 == null || vdwType2 == null) {
198 return null;
199 }
200 double radius = (vdwType1.radius + vdwType2.radius) / 2.0;
201 double wellDepth = (vdwType1.wellDepth + vdwType2.wellDepth) / 2.0;
202 double reductionFactor = (vdwType1.reductionFactor + vdwType2.reductionFactor) / 2.0;
203 return new VDWType(atomClass, radius, wellDepth, reductionFactor);
204 }
205
206
207
208
209
210
211
212
213 public static VDWType parse(String input, String[] tokens) {
214 if (tokens.length < 4) {
215 logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
216 } else {
217 try {
218 int atomType = parseInt(tokens[1]);
219 double radius = parseDouble(tokens[2]);
220 double wellDepth = parseDouble(tokens[3]);
221 double reductionFactor = -1.0;
222 if (tokens.length == 5) {
223 reductionFactor = parseDouble(tokens[4]);
224 }
225 return new VDWType(atomType, radius, wellDepth, reductionFactor);
226 } catch (NumberFormatException e) {
227 String message = "Exception parsing VDW type:\n" + input + "\n";
228 logger.log(Level.SEVERE, message, e);
229 }
230 }
231 return null;
232 }
233
234
235
236
237
238
239
240
241 public static VDWType parseVDW14(String input, String[] tokens) {
242 if (tokens.length < 4) {
243 logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
244 } else {
245 try {
246 int atomType = parseInt(tokens[1]);
247 double radius = parseDouble(tokens[2]);
248 double wellDepth = parseDouble(tokens[3]);
249 double reductionFactor = -1.0;
250 if (tokens.length == 5) {
251 reductionFactor = parseDouble(tokens[4]);
252 }
253 return new VDWType(atomType, radius, wellDepth, reductionFactor, VDWMode.VDW14);
254 } catch (NumberFormatException e) {
255 String message = "Exception parsing VDW14 type:\n" + input + "\n";
256 logger.log(Level.SEVERE, message, e);
257 }
258 }
259 return null;
260 }
261
262
263
264
265 @Override
266 public int compare(String s1, String s2) {
267 int t1 = parseInt(s1);
268 int t2 = parseInt(s2);
269 return Integer.compare(t1, t2);
270 }
271
272
273
274
275 @Override
276 public boolean equals(Object o) {
277 if (this == o) {
278 return true;
279 }
280 if (o == null || getClass() != o.getClass()) {
281 return false;
282 }
283 VDWType vdwType = (VDWType) o;
284 return (vdwType.atomClass == this.atomClass);
285 }
286
287
288
289
290 @Override
291 public int hashCode() {
292 return Objects.hash(atomClass);
293 }
294
295
296
297
298
299
300 @Override
301 public String toString() {
302 StringBuilder vdwString = new StringBuilder("vdw");
303 if (vdwMode == VDWMode.VDW14) {
304 vdwString.append("14");
305 }
306
307
308 if (reductionFactor <= 0e0) {
309 vdwString.append(format(" %5d %11.9f %11.9f", atomClass, radius, wellDepth));
310 } else {
311 vdwString.append(
312 format(" %5d %11.9f %11.9f %5.3f", atomClass, radius, wellDepth, reductionFactor));
313 }
314
315 return vdwString.toString();
316 }
317
318
319
320
321
322
323
324
325 public static Element getXMLForce(Document doc, ForceField forceField) {
326 Map<String, VDWType> vdwTypes = forceField.getVDWTypes();
327 Map<String, VDWPairType> vdwPairTypes = forceField.getVDWPairTypes();
328 if (!vdwTypes.values().isEmpty() || !vdwPairTypes.values().isEmpty()) {
329 Element node = doc.createElement("AmoebaVdwForce");
330 node.setAttribute("type", forceField.getString("vdwtype", DEFAULT_VDW_TYPE.toString()));
331 node.setAttribute("radiusrule", forceField.getString("radiusrule", DEFAULT_RADIUS_RULE.toString()));
332 node.setAttribute("radiustype", forceField.getString("radiustype", DEFAULT_RADIUS_TYPE.toString()));
333 node.setAttribute("radiussize", forceField.getString("radiussize", DEFAULT_RADIUS_SIZE.toString()));
334 node.setAttribute("epsilonrule", forceField.getString("epsilonrule", DEFAULT_EPSILON_RULE.toString()));
335
336 node.setAttribute("vdw-13-scale", valueOf(forceField.getDouble("vdw-13-scale", DEFAULT_VDW_13_SCALE)));
337 node.setAttribute("vdw-14-scale", valueOf(forceField.getDouble("vdw-14-scale", DEFAULT_VDW_14_SCALE)));
338 node.setAttribute("vdw-15-scale", valueOf(forceField.getDouble("vdw-15-scale", 1.0)));
339 for (VDWType vdwType : vdwTypes.values()) {
340 node.appendChild(vdwType.toXML(doc));
341 }
342 for (VDWPairType vdwPairType : vdwPairTypes.values()) {
343 node.appendChild(vdwPairType.toXML(doc));
344 }
345 return node;
346 }
347 return null;
348 }
349
350
351
352
353 public Element toXML(Document doc) {
354 Element node = doc.createElement("Vdw");
355 node.setAttribute("class", format("%d", atomClass));
356
357 node.setAttribute("sigma", format("%f", radius * ANG_TO_NM));
358
359 node.setAttribute("epsilon", format("%f", wellDepth * KCAL_TO_KJ));
360 if (reductionFactor <= 0e0) {
361 node.setAttribute("reduction", "1.0");
362 } else {
363 node.setAttribute("reduction", format("%f", reductionFactor));
364 }
365 return node;
366 }
367
368
369
370
371
372
373 void incrementClass(int increment) {
374 atomClass += increment;
375 setKey(Integer.toString(atomClass));
376 }
377
378
379
380
381 public enum VDWMode {
382 NORMAL, VDW14
383 }
384
385
386
387
388 public enum VDW_TYPE {
389 BUFFERED_14_7,
390 LENNARD_JONES;
391
392 public String toString() {
393 return name().replace("_", "-");
394 }
395 }
396
397
398
399
400 public enum RADIUS_RULE {
401 ARITHMETIC,
402 CUBIC_MEAN,
403 GEOMETRIC;
404
405 public String toString() {
406 return name().replace("_", "-");
407 }
408 }
409
410
411
412
413 public enum RADIUS_SIZE {
414 DIAMETER,
415 RADIUS
416 }
417
418
419
420
421 public enum RADIUS_TYPE {
422 R_MIN,
423 SIGMA;
424
425 public String toString() {
426 return name().replace("_", "-");
427 }
428 }
429
430
431
432
433 public enum EPSILON_RULE {
434 GEOMETRIC,
435 HHG,
436 W_H;
437
438 public String toString() {
439 return name().replace("_", "-");
440 }
441 }
442 }