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.crystal;
39  
40  import static java.lang.String.format;
41  import static org.apache.commons.math3.util.FastMath.PI;
42  import static org.apache.commons.math3.util.FastMath.acos;
43  import static org.apache.commons.math3.util.FastMath.cos;
44  import static org.apache.commons.math3.util.FastMath.pow;
45  import static org.apache.commons.math3.util.FastMath.sqrt;
46  
47  import java.util.logging.Logger;
48  
49  /**
50   * This class holds the functionality to convert between equivalent space groups.
51   */
52  public class SpaceGroupConversions {
53  
54    /**
55     * The logger.
56     */
57    private static final Logger logger = Logger.getLogger(SpaceGroupConversions.class.getName());
58  
59    /**
60     * Convert between hexagonal and rhombohedral space groups.
61     *
62     * @param crystal Crystal parameters to be converted.
63     * @return Converted crystal.
64     */
65    public static Crystal hrConversion(Crystal crystal) {
66      return hrConversion(crystal.a, crystal.b, crystal.c, crystal.alpha, crystal.beta, crystal.gamma,
67          crystal.spaceGroup);
68    }
69  
70    /**
71     * Convert between hexagonal and rhombohedral space groups.
72     *
73     * @param a proposed axis length
74     * @param b proposed axis length
75     * @param c proposed axis length
76     * @param alpha proposed angle
77     * @param beta proposed angle
78     * @param gamma proposed angle
79     * @param currentSG Space group to be converted
80     * @return Converted crystal satisfying other lattice system.
81     */
82    public static Crystal hrConversion(double a, double b, double c, double alpha, double beta,
83        double gamma, SpaceGroup currentSG) {
84      //Name for converted space group.
85      String xtalName;
86      // Going from hexagonal to rhombohedral (true), or visa versa (false).
87      boolean hexStart = false;
88      // Determine starting space group.
89      switch (currentSG.shortName) {
90        case ("H3") -> {
91          logger.info(" Converting from H3 to R3:");
92          xtalName = "R3";
93          hexStart = true;
94        }
95        case ("H-3") -> {
96          logger.info(" Converting from H-3 to R-3:");
97          xtalName = "R-3";
98          hexStart = true;
99        }
100       case ("H32") -> {
101         logger.info(" Converting from H32 to R32:");
102         xtalName = "R32";
103         hexStart = true;
104       }
105       case ("H3m") -> {
106         logger.info(" Converting from H3m to R3m:");
107         xtalName = "R3m";
108         hexStart = true;
109       }
110       case ("H3c") -> {
111         logger.info(" Converting from H3c to R3c:");
112         xtalName = "R3c";
113         hexStart = true;
114       }
115       case ("H-3m") -> {
116         logger.info(" Converting from H-3m to R-3m:");
117         xtalName = "R-3m";
118         hexStart = true;
119       }
120       case ("H-3c") -> {
121         logger.info(" Converting from H-3c to R-3c:");
122         xtalName = "R-3c";
123         hexStart = true;
124       }
125       case ("R3") -> {
126         logger.info(" Converting from R3 to H3:");
127         xtalName = "H3";
128       }
129       case ("R-3") -> {
130         logger.info(" Converting from R-3 to H-3:");
131         xtalName = "H-3";
132       }
133       case ("R32") -> {
134         logger.info(" Converting from R32 to H32:");
135         xtalName = "H32";
136       }
137       case ("R3m") -> {
138         logger.info(" Converting from R3m to H3m:");
139         xtalName = "H3m";
140       }
141       case ("R3c") -> {
142         logger.info(" Converting from R3c to H3c:");
143         xtalName = "H3c";
144       }
145       case ("R-3m") -> {
146         logger.info(" Converting from R-3m to H-3m:");
147         xtalName = "H-3m";
148       }
149       case ("R-3c") -> {
150         logger.info(" Converting from R-3c to H-3c:");
151         xtalName = "H-3c";
152       }
153       default -> {
154         logger.severe(
155             format(" Unable to determine converted version for space group: %s", currentSG));
156         return new Crystal(a, b, c, alpha, beta, gamma, currentSG.shortName);
157       }
158     }
159 
160     // Hexagonal and Rhombohedral space groups are frequently treated synonymously, therefore check if mislabeled.
161     if (hexStart) {
162       //Hexagonal aH = bH, alpha = beta = 90 gamma = 120
163       if (LatticeSystem.RHOMBOHEDRAL_LATTICE.validParameters(a, b, c, alpha, beta, gamma)) {
164         logger.info(" Crystal already has valid lattice parameters for new space group " + xtalName);
165         return new Crystal(a, b, c, alpha, beta, gamma, xtalName);
166       }
167 
168       double aR = sqrt(1.0 / 9.0 * (pow(c, 2) + 3 * pow(a, 2)));
169       double aRAlpha = acos((2 * pow(c, 2) - 3 * pow(a, 2)) /
170           (2 * pow(c, 2) + 6 * pow(a, 2))) / PI * 180;
171 
172       return new Crystal(aR, aR, aR, aRAlpha, aRAlpha, aRAlpha, xtalName);
173     } else {
174       if (LatticeSystem.HEXAGONAL_LATTICE.validParameters(a, b, c, alpha, beta, gamma)) {
175         logger.info(" Crystal already has valid lattice parameters for new space group " + xtalName);
176         return new Crystal(a, b, c, alpha, beta, gamma, xtalName);
177       }
178 
179       double aH = 2 * pow(a, 2) * (1 - cos(alpha / 180 * PI));
180       double cH = sqrt(3 * pow(a, 2) * (1 + 2 * cos(alpha / 180 * PI)));
181 
182       return new Crystal(aH, aH, cH, 90.00, 90.00, 120.00, xtalName);
183     }
184   }
185 }