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