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.parsers;
39  
40  import static java.lang.Double.parseDouble;
41  import static java.lang.String.format;
42  
43  import ffx.crystal.Crystal;
44  import java.io.BufferedReader;
45  import java.io.BufferedWriter;
46  import java.io.File;
47  import java.io.FileReader;
48  import java.io.FileWriter;
49  import java.io.IOException;
50  import java.util.logging.Level;
51  import java.util.logging.Logger;
52  
53  /**
54   * The DYNFilter class parses TINKER Restart (*.DYN) files.
55   *
56   * @author Michael J. Schnieders
57   * @since 1.0
58   */
59  public class DYNFilter {
60  
61    private static final Logger logger = Logger.getLogger(DYNFilter.class.getName());
62    private final String label;
63  
64    /**
65     * Constructor for DYNFilter.
66     *
67     * @param label a Label for the restart file.
68     */
69    public DYNFilter(String label) {
70      this.label = label;
71    }
72  
73    /**
74     * readDYN
75     *
76     * @param dynFile a {@link java.io.File} object.
77     * @param crystal a {@link ffx.crystal.Crystal} object.
78     * @param x an array of double.
79     * @param v an array of double.
80     * @param a an array of double.
81     * @param ap an array of double.
82     * @return a boolean.
83     */
84    public boolean readDYN(File dynFile, Crystal crystal, double[] x, double[] v, double[] a,
85        double[] ap) {
86      if (!dynFile.exists() || !dynFile.canRead()) {
87        return false;
88      }
89      try (BufferedReader br = new BufferedReader(new FileReader(dynFile))) {
90  
91        br.readLine();
92        String data = br.readLine().trim();
93        String[] tokens = data.split(" +");
94        if (tokens.length == 0) {
95          return false;
96        }
97        int numAtoms = Integer.parseInt(tokens[0]);
98  
99        // Box size and angles
100       br.readLine();
101       data = br.readLine().trim();
102       tokens = data.split(" +");
103       if (tokens.length != 3) {
104         return false;
105       }
106       double aAxis = parseDouble(tokens[0]);
107       double bAxis = parseDouble(tokens[1]);
108       double cAxis = parseDouble(tokens[2]);
109 
110       data = br.readLine().trim();
111       tokens = data.split(" +");
112       if (tokens.length != 3) {
113         return false;
114       }
115       double alpha = parseDouble(tokens[0]);
116       double beta = parseDouble(tokens[1]);
117       double gamma = parseDouble(tokens[2]);
118 
119       crystal.changeUnitCellParameters(aAxis, bAxis, cAxis, alpha, beta, gamma);
120 
121       // Atomic coordinates
122       br.readLine();
123       for (int i = 0; i < numAtoms; i++) {
124         data = br.readLine().trim();
125         tokens = data.split(" +");
126         if (tokens.length != 3) {
127           return false;
128         }
129         int j = i * 3;
130         x[j] = parseDouble(tokens[0]);
131         x[j + 1] = parseDouble(tokens[1]);
132         x[j + 2] = parseDouble(tokens[2]);
133       }
134 
135       // Velocities
136       br.readLine();
137       for (int i = 0; i < numAtoms; i++) {
138         data = br.readLine().trim();
139         tokens = data.split(" +");
140         if (tokens.length != 3) {
141           return false;
142         }
143         int j = i * 3;
144         v[j] = parseDouble(tokens[0]);
145         v[j + 1] = parseDouble(tokens[1]);
146         v[j + 2] = parseDouble(tokens[2]);
147       }
148 
149       // Accelerations
150       br.readLine();
151       for (int i = 0; i < numAtoms; i++) {
152         data = br.readLine().trim();
153         tokens = data.split(" +");
154         if (tokens.length != 3) {
155           return false;
156         }
157         int j = i * 3;
158         a[j] = parseDouble(tokens[0]);
159         a[j + 1] = parseDouble(tokens[1]);
160         a[j + 2] = parseDouble(tokens[2]);
161       }
162 
163       // Previous Accelerations
164       br.readLine();
165       for (int i = 0; i < numAtoms; i++) {
166         data = br.readLine().trim();
167         tokens = data.split(" +");
168         if (tokens.length != 3) {
169           return false;
170         }
171         int j = i * 3;
172         ap[j] = parseDouble(tokens[0]);
173         ap[j + 1] = parseDouble(tokens[1]);
174         ap[j + 2] = parseDouble(tokens[2]);
175       }
176     } catch (Exception e) {
177       String message = "Exception reading dynamic restart file: " + dynFile;
178       logger.log(Level.WARNING, message, e);
179     }
180     return true;
181   }
182 
183   /**
184    * writeDYN
185    *
186    * @param dynFile The file to write.
187    * @param x The atomic coordinates.
188    * @param v The atomic velocities.
189    * @param a The atomic accelerations.
190    * @param ap The atomic previous accelerations.
191    * @param crystal The crystal unit cell.
192    * @return Returns true if the file was written successfully.
193    */
194   public boolean writeDYN(File dynFile, Crystal crystal, double[] x, double[] v, double[] a,
195       double[] ap) {
196     try (FileWriter fw = new FileWriter(dynFile); BufferedWriter bw = new BufferedWriter(fw)) {
197       bw.write(" Number of Atoms and Title :\n");
198       assert (x.length % 3 == 0);
199       int numberOfAtoms = x.length / 3;
200       String output = format("%7d  %s\n", numberOfAtoms, label);
201       bw.write(output);
202       bw.write(" Periodic Box Dimensions :\n");
203       Crystal unitCell = crystal.getUnitCell();
204       bw.write(format("%26.16E%26.16E%26.16E\n", unitCell.a, unitCell.b, unitCell.c));
205       bw.write(format("%26.16E%26.16E%26.16E\n", unitCell.alpha, unitCell.beta, unitCell.gamma));
206       bw.write(" Current Atomic Positions :\n");
207       for (int i = 0; i < numberOfAtoms; i++) {
208         int k = i * 3;
209         bw.write(format("%26.16E%26.16E%26.16E\n", x[k], x[k + 1], x[k + 2]));
210       }
211       bw.write(" Current Atomic Velocities :\n");
212       for (int i = 0; i < numberOfAtoms; i++) {
213         int k = i * 3;
214         bw.write(format("%26.16E%26.16E%26.16E\n", v[k], v[k + 1], v[k + 2]));
215       }
216       bw.write(" Current Atomic Accelerations :\n");
217       for (int i = 0; i < numberOfAtoms; i++) {
218         int k = i * 3;
219         bw.write(format("%26.16E%26.16E%26.16E\n", a[k], a[k + 1], a[k + 2]));
220       }
221       bw.write(" Previous Atomic Accelerations :\n");
222       for (int i = 0; i < numberOfAtoms; i++) {
223         int k = i * 3;
224         bw.write(format("%26.16E%26.16E%26.16E\n", ap[k], ap[k + 1], ap[k + 2]));
225       }
226     } catch (IOException e) {
227       String message = " Exception writing dynamic restart file " + dynFile;
228       logger.log(Level.SEVERE, message, e);
229       return false;
230     }
231     return true;
232   }
233 }