View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2021.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.parameters;
39  
40  import static ffx.potential.parameters.ForceField.ForceFieldType.VDW;
41  import static ffx.potential.parameters.ForceField.ForceFieldType.VDW14;
42  import static ffx.utilities.KeywordGroup.PotentialFunctionParameter;
43  import static java.lang.Double.parseDouble;
44  import static java.lang.Integer.parseInt;
45  import static java.lang.StrictMath.abs;
46  import static java.lang.String.format;
47  
48  import ffx.utilities.FFXKeyword;
49  import java.util.Comparator;
50  import java.util.Objects;
51  import java.util.logging.Level;
52  import java.util.logging.Logger;
53  
54  /**
55   * The VDWType class defines van der Waals type for a normal interaction or a special 1-4
56   * interaction.
57   *
58   * @author Michael J. Schnieders
59   * @since 1.0
60   */
61  @FFXKeyword(name = "vdw", clazz = String.class, keywordGroup = PotentialFunctionParameter,
62      description = "[1 integer and 3 reals] "
63          + "Provides values for a single van der Waals parameter. "
64          + "The integer modifier, if positive, gives the atom class number for which vdw parameters are to be defined. "
65          + "Note that vdw parameters are given for atom classes, not atom types. "
66          + "The three real number modifiers give the values of the atom size in Angstroms, homoatomic well depth in kcal/mole, and an optional reduction factor for univalent atoms.")
67  @FFXKeyword(name = "vdw14", clazz = String.class, keywordGroup = PotentialFunctionParameter,
68      description = "[1 integer and 2 reals] "
69          + "Provides values for a single van der Waals parameter for use in 1-4 nonbonded interactions. "
70          + "The integer modifier, if positive, gives the atom class number for which vdw parameters are to be defined. "
71          + "Note that vdw parameters are given for atom classes, not atom types. "
72          + "The two real number modifiers give the values of the atom size in Angstroms and the homoatomic well depth in kcal/mole. "
73          + "Reduction factors, if used, are carried over from the vdw keyword for the same atom class.")
74  public final class VDWType extends BaseType implements Comparator<String> {
75  
76    private static final Logger logger = Logger.getLogger(VDWType.class.getName());
77    /** The radius of the minimum well depth energy (angstroms). */
78    public final double radius;
79    /** The minimum energy of the vdw function (kcal/mol). */
80    public final double wellDepth;
81    /**
82     * Reduction factor for evaluating van der Waals pairs. Valid range: 0.0 .GT. reduction .LE. 1.0
83     * Usually only hydrogen atoms have a reduction factor. Setting the reduction to .LT. 0.0 indicates
84     * it is not being used.
85     */
86    public final double reductionFactor;
87    /** The atom class that uses this van der Waals parameter. */
88    public int atomClass;
89    /** Is this a normal vdW parameter or is it for 1-4 interactions. */
90    private final VDWMode vdwMode;
91  
92    /**
93     * van der Waals constructor. If the reduction factor is .LE. 0.0, no reduction is used for this
94     * atom type.
95     *
96     * @param atomClass The atom class that uses this van der Waals parameter.
97     * @param radius The radius of the minimum well depth energy (angstroms).
98     * @param wellDepth The minimum energy of the vdw function (kcal/mol).
99     * @param reductionFactor Reduction factor for evaluating van der Waals pairs.
100    */
101   public VDWType(int atomClass, double radius, double wellDepth, double reductionFactor) {
102     this(atomClass, radius, wellDepth, reductionFactor, VDWMode.NORMAL);
103   }
104 
105   /**
106    * van der Waals constructor. If the reduction factor is .LE. 0.0, no reduction is used for this
107    * atom type.
108    *
109    * @param atomClass The atom class that uses this van der Waals parameter.
110    * @param radius The radius of the minimum well depth energy (angstroms).
111    * @param wellDepth The minimum energy of the vdw function (kcal/mol).
112    * @param reductionFactor Reduction factor for evaluating van der Waals pairs.
113    * @param vdwMode The VDWMode to use.
114    */
115   public VDWType(
116       int atomClass, double radius, double wellDepth, double reductionFactor, VDWMode vdwMode) {
117     super(VDW, Integer.toString(atomClass));
118     this.atomClass = atomClass;
119     this.radius = radius;
120     this.wellDepth = abs(wellDepth);
121     this.reductionFactor = reductionFactor;
122     this.vdwMode = vdwMode;
123     if (vdwMode == VDWMode.VDW14) {
124       forceFieldType = VDW14;
125     }
126   }
127 
128   /**
129    * average.
130    *
131    * @param vdwType1 a {@link ffx.potential.parameters.VDWType} object.
132    * @param vdwType2 a {@link ffx.potential.parameters.VDWType} object.
133    * @param atomClass a int.
134    * @return a {@link ffx.potential.parameters.VDWType} object.
135    */
136   public static VDWType average(VDWType vdwType1, VDWType vdwType2, int atomClass) {
137     if (vdwType1 == null || vdwType2 == null) {
138       return null;
139     }
140 
141     double radius = (vdwType1.radius + vdwType2.radius) / 2.0;
142     double wellDepth = (vdwType1.wellDepth + vdwType2.wellDepth) / 2.0;
143     double reductionFactor = (vdwType1.reductionFactor + vdwType2.reductionFactor) / 2.0;
144 
145     return new VDWType(atomClass, radius, wellDepth, reductionFactor);
146   }
147 
148   /**
149    * Construct a VDWType from multiple input lines.
150    *
151    * @param input The overall input String.
152    * @param tokens The input String tokenized.
153    * @return a VDWType instance.
154    */
155   public static VDWType parse(String input, String[] tokens) {
156     if (tokens.length < 4) {
157       logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
158     } else {
159       try {
160         int atomType = parseInt(tokens[1]);
161         double radius = parseDouble(tokens[2]);
162         double wellDepth = parseDouble(tokens[3]);
163         double reductionFactor = -1.0;
164         if (tokens.length == 5) {
165           reductionFactor = parseDouble(tokens[4]);
166         }
167         return new VDWType(atomType, radius, wellDepth, reductionFactor);
168       } catch (NumberFormatException e) {
169         String message = "Exception parsing VDW type:\n" + input + "\n";
170         logger.log(Level.SEVERE, message, e);
171       }
172     }
173     return null;
174   }
175 
176   /**
177    * Construct a 1-4 VDWType from multiple input lines.
178    *
179    * @param input The overall input String.
180    * @param tokens The input String tokenized.
181    * @return a VDWType instance.
182    */
183   public static VDWType parseVDW14(String input, String[] tokens) {
184     if (tokens.length < 4) {
185       logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
186     } else {
187       try {
188         int atomType = parseInt(tokens[1]);
189         double radius = parseDouble(tokens[2]);
190         double wellDepth = parseDouble(tokens[3]);
191         double reductionFactor = -1.0;
192         if (tokens.length == 5) {
193           reductionFactor = parseDouble(tokens[4]);
194         }
195         return new VDWType(atomType, radius, wellDepth, reductionFactor, VDWMode.VDW14);
196       } catch (NumberFormatException e) {
197         String message = "Exception parsing VDW14 type:\n" + input + "\n";
198         logger.log(Level.SEVERE, message, e);
199       }
200     }
201     return null;
202   }
203 
204   /** {@inheritDoc} */
205   @Override
206   public int compare(String s1, String s2) {
207     int t1 = parseInt(s1);
208     int t2 = parseInt(s2);
209     return Integer.compare(t1, t2);
210   }
211 
212   /** {@inheritDoc} */
213   @Override
214   public boolean equals(Object o) {
215     if (this == o) {
216       return true;
217     }
218     if (o == null || getClass() != o.getClass()) {
219       return false;
220     }
221     VDWType vdwType = (VDWType) o;
222     return (vdwType.atomClass == this.atomClass);
223   }
224 
225   /** {@inheritDoc} */
226   @Override
227   public int hashCode() {
228     return Objects.hash(atomClass);
229   }
230 
231   /**
232    * {@inheritDoc}
233    *
234    * <p>Nicely formatted van der Waals type.
235    */
236   @Override
237   public String toString() {
238     StringBuilder vdwString = new StringBuilder("vdw");
239     if (vdwMode == VDWMode.VDW14) {
240       vdwString.append("14");
241     }
242 
243     // No reduction factor.
244     if (reductionFactor <= 0e0) {
245       vdwString.append(format("  %5d  %11.9f  %11.9f", atomClass, radius, wellDepth));
246     } else {
247       vdwString.append(
248           format("  %5d  %11.9f  %11.9f  %5.3f", atomClass, radius, wellDepth, reductionFactor));
249     }
250 
251     return vdwString.toString();
252   }
253 
254   /**
255    * incrementClass
256    *
257    * @param increment a int.
258    */
259   void incrementClass(int increment) {
260     atomClass += increment;
261     setKey(Integer.toString(atomClass));
262   }
263 
264   /** Torsion modes include Normal or In-Plane */
265   public enum VDWMode {
266     NORMAL,
267     VDW14
268   }
269 }