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.crystal;
39  
40  import static org.apache.commons.math3.util.FastMath.abs;
41  import static org.apache.commons.math3.util.FastMath.random;
42  
43  /**
44   * Enumeration of the 7 lattice systems.
45   * <p>
46   * Currently the SpaceGroup class uses the HEXAGONAL_LATTICE in all cases where its also possible to
47   * use a RHOMBOHEDRAL_LATTICE.
48   * <p>
49   * This includes space groups 146, 148, 155, 160, 161, 166 and 167.
50   *
51   * @author Michael J. Schnieders
52   * @since 1.0
53   */
54  public enum LatticeSystem {
55    TRICLINIC_LATTICE,
56    MONOCLINIC_LATTICE,
57    ORTHORHOMBIC_LATTICE,
58    TETRAGONAL_LATTICE,
59    RHOMBOHEDRAL_LATTICE,
60    HEXAGONAL_LATTICE,
61    CUBIC_LATTICE;
62  
63    /**
64     * Tolerance for checking if the lattice system restrictions are satisfied.
65     * <p>
66     * Set this to 0.0 for strict checking of lattice parameters.
67     * <p>
68     * For an acetamide crystal minimization, 1.0e-15 was too small a tolerance for equivalent lattice
69     * parameters to equate as equal.
70     */
71    private static final double tolerance = 1.0e-15;
72  
73    /**
74     * If the two passed values are the same, within the tolerance, return true.
75     *
76     * @param x1 First value.
77     * @param x2 Second value.
78     * @return Return true if the two values are the same within specified tolerance.
79     */
80    public static boolean check(double x1, double x2) {
81      return abs(x1 - x2) < tolerance;
82    }
83  
84    /**
85     * Reset lattice parameters for the given lattice systems.
86     *
87     * @return New unit cell parameters.
88     */
89    public double[] resetUnitCellParams() {
90      double alpha = 60.0 + random() * 60.0;
91      double beta = 60.0 + random() * 60.0;
92      double gamma = 60.0 + random() * 60.0;
93      double[] params = {0.25 + random(), 0.25 + random(), 0.25 + random(), alpha, beta, gamma};
94      double ab = 0.5 * (params[0] + params[1]);
95      double abc = (params[0] + params[1] + params[2]) / 3.0;
96      switch (this) {
97        case TRICLINIC_LATTICE:
98          break;
99        case MONOCLINIC_LATTICE:
100         // alpha = gamma = 90
101         params[3] = 90.0;
102         params[5] = 90.0;
103         break;
104       case ORTHORHOMBIC_LATTICE:
105         // alpha = beta = gamma = 90
106         params[3] = 90.0;
107         params[4] = 90.0;
108         params[5] = 90.0;
109         break;
110       case TETRAGONAL_LATTICE:
111         // a = b, alpha = beta = gamma = 90
112         params[0] = ab;
113         params[1] = ab;
114         params[3] = 90.0;
115         params[4] = 90.0;
116         params[5] = 90.0;
117         break;
118       case RHOMBOHEDRAL_LATTICE:
119         // a = b = c, alpha = beta = gamma.
120         double angles = (params[3] + params[4] + params[5]) / 3.0;
121         params[0] = abc;
122         params[1] = abc;
123         params[2] = abc;
124         params[3] = angles;
125         params[4] = angles;
126         params[5] = angles;
127         break;
128       case HEXAGONAL_LATTICE:
129         // a = b, alpha = beta = 90, gamma = 120
130         params[0] = ab;
131         params[1] = ab;
132         params[3] = 90.0;
133         params[4] = 90.0;
134         params[5] = 120.0;
135         break;
136       case CUBIC_LATTICE:
137       default:
138         // a = b = c, alpha = beta = gamma = 90
139         params[0] = abc;
140         params[1] = abc;
141         params[2] = abc;
142         params[3] = 90.0;
143         params[4] = 90.0;
144         params[5] = 90.0;
145         break;
146     }
147     return params;
148   }
149 
150   /**
151    * Check that the lattice parameters satisfy the restrictions of the lattice systems.
152    *
153    * @param a the a-axis length.
154    * @param b the b-axis length.
155    * @param c the c-axis length.
156    * @param alpha the alpha angle.
157    * @param beta the beta angle.
158    * @param gamma the gamma angle.
159    * @return True if the restrictions are satisfied, false otherwise.
160    */
161   public boolean validParameters(double a, double b, double c, double alpha, double beta,
162       double gamma) {
163     switch (this) {
164       case TRICLINIC_LATTICE:
165         // No restrictions.
166         return true;
167       case MONOCLINIC_LATTICE:
168         // alpha = gamma = 90
169         return check(alpha, 90.0) && check(gamma, 90.0);
170       case ORTHORHOMBIC_LATTICE:
171         // alpha = beta = gamma = 90
172         return check(alpha, 90.0) && check(beta, 90.0) && check(gamma, 90.0);
173       case TETRAGONAL_LATTICE:
174         // a = b, alpha = beta = gamma = 90
175         return check(a, b) && check(alpha, 90.0) && check(beta, 90.0) && check(gamma, 90.0);
176       case RHOMBOHEDRAL_LATTICE:
177         // a = b = c, alpha = beta = gamma.
178         return check(a, b) && check(b, c) && check(alpha, beta) && check(beta, gamma);
179       case HEXAGONAL_LATTICE:
180         // a = b, alpha = beta = 90, gamma = 120
181         return check(a, b) && check(alpha, 90.0) && check(beta, 90.0) && check(gamma, 120.0);
182       case CUBIC_LATTICE:
183         // a = b = c; alpha = beta = gamma = 90
184         return check(a, b) && check(b, c) && check(alpha, 90.0) && check(beta, 90.0) && check(gamma,
185             90.0);
186       default:
187         assert (2 != 2);
188         return false;
189     }
190   }
191 
192   /**
193    * Change the lattice parameters to satisfy the restrictions of the lattice system.
194    *
195    * @param a the proposed a-axis length.
196    * @param b the proposed b-axis length.
197    * @param c the proposed c-axis length.
198    * @param alpha the proposed alpha angle.
199    * @param beta the proposed beta angle.
200    * @param gamma the proposed gamma angle.
201    * @return Adjusted parameters if the restrictions are satisfied, original parameters otherwise.
202    */
203   public double[] fixParameters(double a, double b, double c, double alpha, double beta,
204                                  double gamma) {
205     double[] parameters = {a,b,c,alpha,beta,gamma};
206     double ab = (parameters[0] + parameters[1])/2;
207     double abc = (parameters[0] + parameters[1] + parameters[2])/3;
208     switch (this) {
209       case TRICLINIC_LATTICE:
210         // No restrictions.
211         return parameters;
212       case MONOCLINIC_LATTICE:
213         // alpha = gamma = 90
214         parameters[3] = 90.0;
215         parameters[5] = 90.0;
216         return parameters;
217       case ORTHORHOMBIC_LATTICE:
218         // alpha = beta = gamma = 90
219         parameters[3] = 90.0;
220         parameters[4] = 90.0;
221         parameters[5] = 90.0;
222         return parameters;
223       case TETRAGONAL_LATTICE:
224         // a = b, alpha = beta = gamma = 90
225         parameters[0] = ab;
226         parameters[1] = ab;
227         parameters[3] = 90.0;
228         parameters[4] = 90.0;
229         parameters[5] = 90.0;
230         return parameters;
231       case RHOMBOHEDRAL_LATTICE:
232         // a = b = c, alpha = beta = gamma.
233         double angles = (parameters[3] + parameters[4] + parameters[5])/3;
234         parameters[0] = abc;
235         parameters[1] = abc;
236         parameters[2] = abc;
237         parameters[3] = angles;
238         parameters[4] = angles;
239         parameters[5] = angles;
240         return parameters;
241         case HEXAGONAL_LATTICE:
242         // a = b, alpha = beta = 90, gamma = 120
243           parameters[0] = ab;
244           parameters[1] = ab;
245           parameters[3] = 90.0;
246           parameters[4] = 90.0;
247           parameters[5] = 120.0;
248           return parameters;
249       case CUBIC_LATTICE:
250         // a = b = c; alpha = beta = gamma = 90
251         parameters[0] = abc;
252         parameters[1] = abc;
253         parameters[2] = abc;
254         parameters[3] = 90.0;
255         parameters[4] = 90.0;
256         parameters[5] = 90.0;
257         return parameters;
258       default:
259         assert (2 != 2);
260         return parameters;
261     }
262   }
263 
264   /**
265    * Returns the default b-axis for the lattice system.
266    *
267    * @param aaxis the a-axis length is the best guess for b-axis.
268    * @return default b-axis value
269    */
270   public double getDefaultBAxis(double aaxis) {
271     return aaxis;
272   }
273 
274   /**
275    * Returns the default c-axis for the lattice system.
276    *
277    * @return default c-axis value
278    */
279   public double getDefaultCAxis(double aaxis, double baxis) {
280     return (aaxis+baxis)/2;
281   }
282 
283   /**
284    * Returns the default alpha for the lattice system.
285    *
286    * @return default alpha value
287    */
288   public double getDefaultAlpha() {
289     return 90.0;
290   }
291 
292   /**
293    * Returns the default beta for the lattice system.
294    *
295    * @return default beta value
296    */
297   public double getDefaultBeta() {
298     return 90.0;
299   }
300 
301   /**
302    * Returns the default gamma for the lattice system.
303    *
304    * @return default gamma value
305    */
306   public double getDefaultGamma() {
307     double gamma = 90.0;
308     if(this==HEXAGONAL_LATTICE){
309       gamma = 120.0;
310     }
311     return gamma;
312   }
313 }