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-2023.
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.utilities.KeywordGroup.PotentialFunctionParameter;
41  import static java.lang.Double.parseDouble;
42  import static java.lang.Integer.parseInt;
43  import static java.lang.String.format;
44  
45  import ffx.potential.parameters.ForceField.ForceFieldType;
46  import ffx.utilities.FFXKeyword;
47  import java.util.Arrays;
48  import java.util.Comparator;
49  import java.util.logging.Level;
50  import java.util.logging.Logger;
51  
52  /**
53   * The VDWPairType class defines a van der Waals Pair type.
54   *
55   * @author Michael J. Schnieders
56   * @since 1.0
57   */
58  @FFXKeyword(name = "vdwpr", clazz = String.class, keywordGroup = PotentialFunctionParameter, description =
59      "[2 integers and 2 reals] "
60          + "Provides the values for the vdw parameters for a single special heteroatomic pair of atoms. "
61          + "The integer modifiers give the pair of atom class numbers for which special vdw parameters are to be defined. "
62          + "The two real number modifiers give the values of the minimum energy contact distance in Angstroms and the well depth at the minimum distance in kcal/mole.")
63  public final class VDWPairType extends BaseType implements Comparator<String> {
64  
65    private static final Logger logger = Logger.getLogger(VDWPairType.class.getName());
66    /** The radius of the minimum well depth energy (angstroms). */
67    public final double radius;
68    /** The minimum energy of the vdw function (kcal/mol). */
69    public final double wellDepth;
70    /** Atom classes that form this bond stretch. */
71    public final int[] atomClasses;
72  
73    /**
74     * van der Waals constructor. If the reduction factor is .LE. 0.0, no reduction is used for this
75     * atom type.
76     *
77     * @param atomClasses The atom class that uses this van der Waals Pair.
78     * @param radius The radius of the minimum well depth energy (angstroms).
79     * @param wellDepth The minimum energy of the vdw function (kcal/mol).
80     */
81    public VDWPairType(int[] atomClasses, double radius, double wellDepth) {
82      super(ForceFieldType.VDWPR, sortKey(atomClasses));
83      this.atomClasses = atomClasses;
84      this.radius = radius;
85      this.wellDepth = wellDepth;
86    }
87  
88    /**
89     * Average.
90     *
91     * @param vdwType1 a {@link VDWPairType} object.
92     * @param vdwType2 a {@link VDWPairType} object.
93     * @param atomClasses The atom classes that uses this van der Waals Pair.
94     * @return a {@link VDWPairType} object.
95     */
96    public static VDWPairType average(VDWPairType vdwType1, VDWPairType vdwType2, int[] atomClasses) {
97      if (vdwType1 == null || vdwType2 == null) {
98        return null;
99      }
100 
101     double radius = (vdwType1.radius + vdwType2.radius) / 2.0;
102     double wellDepth = (vdwType1.wellDepth + vdwType2.wellDepth) / 2.0;
103 
104     return new VDWPairType(atomClasses, radius, wellDepth);
105   }
106 
107   /**
108    * Construct a VDWPairType from multiple input lines.
109    *
110    * @param input The overall input String.
111    * @param tokens The input String tokenized.
112    * @return a VDWType instance.
113    */
114   public static VDWPairType parse(String input, String[] tokens) {
115     if (tokens.length < 5) {
116       logger.log(Level.WARNING, "Invalid VDWPR type:\n{0}", input);
117     } else {
118       try {
119         int atomClass1 = parseInt(tokens[1]);
120         int atomClass2 = parseInt(tokens[2]);
121         double radius = parseDouble(tokens[3]);
122         double wellDepth = parseDouble(tokens[4]);
123         return new VDWPairType(new int[] {atomClass1, atomClass2}, radius, wellDepth);
124       } catch (NumberFormatException e) {
125         String message = "Exception parsing VDWPR type:\n" + input + "\n";
126         logger.log(Level.SEVERE, message, e);
127       }
128     }
129     return null;
130   }
131 
132   /** {@inheritDoc} */
133   @Override
134   public int compare(String key1, String key2) {
135     String[] keys1 = key1.split(" ");
136     String[] keys2 = key2.split(" ");
137     int[] c1 = new int[2];
138     int[] c2 = new int[2];
139     for (int i = 0; i < 2; i++) {
140       c1[i] = Integer.parseInt(keys1[i]);
141       c2[i] = Integer.parseInt(keys2[i]);
142     }
143 
144     if (c1[0] < c2[0]) {
145       return -1;
146     } else if (c1[0] > c2[0]) {
147       return 1;
148     } else if (c1[1] < c2[1]) {
149       return -1;
150     } else if (c1[1] > c2[1]) {
151       return 1;
152     }
153 
154     return 0;
155   }
156 
157   /** {@inheritDoc} */
158   @Override
159   public boolean equals(Object o) {
160     if (this == o) {
161       return true;
162     }
163     if (o == null || getClass() != o.getClass()) {
164       return false;
165     }
166     VDWPairType vdwPairType = (VDWPairType) o;
167     return Arrays.equals(atomClasses, vdwPairType.atomClasses);
168   }
169 
170   /** {@inheritDoc} */
171   @Override
172   public int hashCode() {
173     return Arrays.hashCode(atomClasses);
174   }
175 
176   /**
177    * {@inheritDoc}
178    *
179    * <p>Nicely formatted van der Waals type.
180    */
181   @Override
182   public String toString() {
183     return format("vdwpr  %5d  %5d  %11.9f  %11.9f", atomClasses[0], atomClasses[1], radius,
184         wellDepth);
185   }
186 
187   /**
188    * This method sorts the atom classes as: min, max
189    *
190    * @param c atomClasses
191    * @return lookup key
192    */
193   public static String sortKey(int[] c) {
194     if (c == null || c.length != 2) {
195       return null;
196     }
197 
198     int temp;
199     if (c[1] <= c[0]) {
200       temp = c[1];
201       c[1] = c[0];
202       c[0] = temp;
203     }
204 
205     return c[0] + " " + c[1];
206   }
207 
208   /**
209    * Increment the atom classes by a specified amount.
210    *
211    * @param increment The increment to add to the atom classes.
212    */
213   public void incrementClasses(int increment) {
214     for (int i = 0; i < atomClasses.length; i++) {
215       atomClasses[i] += increment;
216     }
217     setKey(sortKey(atomClasses));
218   }
219 
220 }