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-2024.
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 ffx.utilities.FFXProperty;
41  
42  import java.util.Comparator;
43  import java.util.Objects;
44  import java.util.logging.Level;
45  import java.util.logging.Logger;
46  
47  import static ffx.potential.parameters.ForceField.ForceFieldType.VDW;
48  import static ffx.potential.parameters.ForceField.ForceFieldType.VDW14;
49  import static ffx.utilities.PropertyGroup.PotentialFunctionParameter;
50  import static java.lang.Double.parseDouble;
51  import static java.lang.Integer.parseInt;
52  import static java.lang.StrictMath.abs;
53  import static java.lang.String.format;
54  
55  /**
56   * The VDWType class defines van der Waals type for a normal interaction or a special 1-4
57   * interaction.
58   *
59   * @author Michael J. Schnieders
60   * @since 1.0
61   */
62  @FFXProperty(name = "vdw", clazz = String.class, propertyGroup = PotentialFunctionParameter,
63      description = """
64          [1 integer and 3 reals]
65          Provides values for a single van der Waals parameter. The integer modifier, if positive,
66          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.
67          The three real number modifiers give the values of the atom size in Angstroms, homoatomic well depth in kcal/mole,
68          and an optional reduction factor for univalent atoms.
69          """)
70  @FFXProperty(name = "vdw14", clazz = String.class, propertyGroup = PotentialFunctionParameter,
71      description = """
72          [1 integer and 2 reals]
73          Provides values for a single van der Waals parameter for use in 1-4 nonbonded interactions.
74          The integer modifier, if positive, gives the atom class number for which vdw parameters are to be defined.
75          Note that vdw parameters are given for atom classes, not atom types.
76          The two real number modifiers give the values of the atom size in Angstroms and the homoatomic well depth in kcal/mole.
77          Reduction factors, if used, are carried over from the vdw keyword for the same atom class.
78          """)
79  public final class VDWType extends BaseType implements Comparator<String> {
80  
81    private static final Logger logger = Logger.getLogger(VDWType.class.getName());
82    /**
83     * The radius of the minimum well depth energy (angstroms).
84     */
85    public final double radius;
86    /**
87     * The minimum energy of the vdw function (kcal/mol).
88     */
89    public final double wellDepth;
90    /**
91     * Reduction factor for evaluating van der Waals pairs. Valid range: 0.0 .GT. reduction .LE. 1.0
92     * Usually only hydrogen atoms have a reduction factor. Setting the reduction to .LT. 0.0 indicates
93     * it is not being used.
94     */
95    public final double reductionFactor;
96    /**
97     * The atom class that uses this van der Waals parameter.
98     */
99    public int atomClass;
100   /**
101    * Is this a normal vdW parameter or is it for 1-4 interactions.
102    */
103   private final VDWMode vdwMode;
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    */
114   public VDWType(int atomClass, double radius, double wellDepth, double reductionFactor) {
115     this(atomClass, radius, wellDepth, reductionFactor, VDWMode.NORMAL);
116   }
117 
118   /**
119    * van der Waals constructor. If the reduction factor is .LE. 0.0, no reduction is used for this
120    * atom type.
121    *
122    * @param atomClass       The atom class that uses this van der Waals parameter.
123    * @param radius          The radius of the minimum well depth energy (angstroms).
124    * @param wellDepth       The minimum energy of the vdw function (kcal/mol).
125    * @param reductionFactor Reduction factor for evaluating van der Waals pairs.
126    * @param vdwMode         The VDWMode to use.
127    */
128   public VDWType(int atomClass, double radius, double wellDepth, double reductionFactor,
129                  VDWMode vdwMode) {
130     super(VDW, Integer.toString(atomClass));
131     this.atomClass = atomClass;
132     this.radius = radius;
133     this.wellDepth = abs(wellDepth);
134     this.reductionFactor = reductionFactor;
135     this.vdwMode = vdwMode;
136     if (vdwMode == VDWMode.VDW14) {
137       forceFieldType = VDW14;
138     }
139   }
140 
141   /**
142    * Average two VDWType objects.
143    *
144    * @param vdwType1  The first VDWType.
145    * @param vdwType2  The second VDWType.
146    * @param atomClass The new atom class.
147    * @return The new averaged VDWType.
148    */
149   public static VDWType average(VDWType vdwType1, VDWType vdwType2, int atomClass) {
150     if (vdwType1 == null || vdwType2 == null) {
151       return null;
152     }
153     double radius = (vdwType1.radius + vdwType2.radius) / 2.0;
154     double wellDepth = (vdwType1.wellDepth + vdwType2.wellDepth) / 2.0;
155     double reductionFactor = (vdwType1.reductionFactor + vdwType2.reductionFactor) / 2.0;
156     return new VDWType(atomClass, radius, wellDepth, reductionFactor);
157   }
158 
159   /**
160    * Construct a VDWType from multiple input lines.
161    *
162    * @param input  The overall input String.
163    * @param tokens The input String tokenized.
164    * @return a VDWType instance.
165    */
166   public static VDWType parse(String input, String[] tokens) {
167     if (tokens.length < 4) {
168       logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
169     } else {
170       try {
171         int atomType = parseInt(tokens[1]);
172         double radius = parseDouble(tokens[2]);
173         double wellDepth = parseDouble(tokens[3]);
174         double reductionFactor = -1.0;
175         if (tokens.length == 5) {
176           reductionFactor = parseDouble(tokens[4]);
177         }
178         return new VDWType(atomType, radius, wellDepth, reductionFactor);
179       } catch (NumberFormatException e) {
180         String message = "Exception parsing VDW type:\n" + input + "\n";
181         logger.log(Level.SEVERE, message, e);
182       }
183     }
184     return null;
185   }
186 
187   /**
188    * Construct a 1-4 VDWType from multiple input lines.
189    *
190    * @param input  The overall input String.
191    * @param tokens The input String tokenized.
192    * @return a VDWType instance.
193    */
194   public static VDWType parseVDW14(String input, String[] tokens) {
195     if (tokens.length < 4) {
196       logger.log(Level.WARNING, "Invalid VDW type:\n{0}", input);
197     } else {
198       try {
199         int atomType = parseInt(tokens[1]);
200         double radius = parseDouble(tokens[2]);
201         double wellDepth = parseDouble(tokens[3]);
202         double reductionFactor = -1.0;
203         if (tokens.length == 5) {
204           reductionFactor = parseDouble(tokens[4]);
205         }
206         return new VDWType(atomType, radius, wellDepth, reductionFactor, VDWMode.VDW14);
207       } catch (NumberFormatException e) {
208         String message = "Exception parsing VDW14 type:\n" + input + "\n";
209         logger.log(Level.SEVERE, message, e);
210       }
211     }
212     return null;
213   }
214 
215   /**
216    * {@inheritDoc}
217    */
218   @Override
219   public int compare(String s1, String s2) {
220     int t1 = parseInt(s1);
221     int t2 = parseInt(s2);
222     return Integer.compare(t1, t2);
223   }
224 
225   /**
226    * {@inheritDoc}
227    */
228   @Override
229   public boolean equals(Object o) {
230     if (this == o) {
231       return true;
232     }
233     if (o == null || getClass() != o.getClass()) {
234       return false;
235     }
236     VDWType vdwType = (VDWType) o;
237     return (vdwType.atomClass == this.atomClass);
238   }
239 
240   /**
241    * {@inheritDoc}
242    */
243   @Override
244   public int hashCode() {
245     return Objects.hash(atomClass);
246   }
247 
248   /**
249    * {@inheritDoc}
250    *
251    * <p>Nicely formatted van der Waals type.
252    */
253   @Override
254   public String toString() {
255     StringBuilder vdwString = new StringBuilder("vdw");
256     if (vdwMode == VDWMode.VDW14) {
257       vdwString.append("14");
258     }
259 
260     // No reduction factor.
261     if (reductionFactor <= 0e0) {
262       vdwString.append(format("  %5d  %11.9f  %11.9f", atomClass, radius, wellDepth));
263     } else {
264       vdwString.append(
265           format("  %5d  %11.9f  %11.9f  %5.3f", atomClass, radius, wellDepth, reductionFactor));
266     }
267 
268     return vdwString.toString();
269   }
270 
271   /**
272    * Increment the atom class by a specified amount.
273    *
274    * @param increment The increment to add to the atom class.
275    */
276   void incrementClass(int increment) {
277     atomClass += increment;
278     setKey(Integer.toString(atomClass));
279   }
280 
281   /**
282    * Torsion modes include Normal or In-Plane
283    */
284   public enum VDWMode {
285     NORMAL, VDW14
286   }
287 }