Loading [MathJax]/extensions/TeX/AMSsymbols.js
SIRIUS 7.5.0
Electronic structure library and applications
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
crystal_symmetry.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2017 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file crystal_symmetry.hpp
21 *
22 * \brief Contains definition and partial implementation of sirius::Crystal_symmetry class.
23 */
24
25#ifndef __CRYSTAL_SYMMETRY_HPP__
26#define __CRYSTAL_SYMMETRY_HPP__
27
28#include <cstddef>
29
30extern "C" {
31#include <spglib.h>
32}
33
34#include "SDDK/memory.hpp"
35#include "core/r3/r3.hpp"
36#include "core/profiler.hpp"
37
38namespace sirius {
39
40/// Descriptor of the space group symmetry operation.
42{
43 /// Rotational part of symmetry operation (fractional coordinates).
45
46 /// Inverse of R.
48
49 /// Inverse transposed of R.
51
52 /// Proper rotation matrix in Cartesian coordinates.
54
55 /// (Im)proper Rotation matrix in Cartesian coordinates.
57
58 /// Fractional translation.
60
61 /// Proper (+1) or improper (-1) rotation.
62 int proper;
63
64 /// Three Euler angles that generate the proper rotation matrix.
66
67 /// Symmetry table.
68 std::vector<int> sym_atom;
69
70 /// Invere symmetry table.
71 std::vector<int> inv_sym_atom;
72
73 /// Translation vector that prings symmetry-transformed atom back to the unit cell.
74 std::vector<r3::vector<int>> inv_sym_atom_T;
75};
76
77/// Descriptor of the magnetic group symmetry operation.
79{
80 /// Element of space group symmetry.
82
83 /// Proper rotation matrix in Cartesian coordinates.
85
86 /// Inverse of proper spin rotation matrix in Cartesian coordinates.
88
89 sddk::mdarray<std::complex<double>, 2> spin_rotation_su2;
90};
91
92/// Representation of the crystal symmetry.
94{
95 private:
96
97 /// Matrix of lattice vectors.
98 /** Spglib requires this matrix to have a positively defined determinant. */
100
101 /// Inverse of the lattice vectors matrix.
103
104 /// Number of atoms in the unit cell.
106
107 /// Number of atom types.
109
110 /// Atom types.
111 std::vector<int> types_;
112
113 /// Atomic positions.
115
116 /// Magnetic moments of atoms.
118
119 double tolerance_;
120
121 /// Crystal structure descriptor returned by spglib.
122 SpglibDataset* spg_dataset_{nullptr};
123
124 /// List of all space group symmetry operations.
125 std::vector<space_group_symmetry_descriptor> space_group_symmetry_;
126
127 /// List of all magnetic group symmetry operations.
128 std::vector<magnetic_group_symmetry_descriptor> magnetic_group_symmetry_;
129
130 /// Number of crystal symmetries without magnetic configuration.
131 inline int num_spg_sym() const
132 {
133 return static_cast<int>(space_group_symmetry_.size());
134 }
135
136 inline auto const& space_group_symmetry(int isym__) const
137 {
138 assert(isym__ >= 0 && isym__ < num_spg_sym());
139 return space_group_symmetry_[isym__];
140 }
141
142 public:
143
144 Crystal_symmetry(r3::matrix<double> const& lattice_vectors__, int num_atoms__, int num_atom_types__,
145 std::vector<int> const& types__, sddk::mdarray<double, 2> const& positions__,
146 sddk::mdarray<double, 2> const& spins__, bool spin_orbit__, double tolerance__, bool use_sym__);
147
148 ~Crystal_symmetry()
149 {
150 if (spg_dataset_) {
151 spg_free_dataset(spg_dataset_);
152 }
153 }
154
155 inline int atom_symmetry_class(int ia__) const
156 {
157 if (spg_dataset_) {
158 return spg_dataset_->equivalent_atoms[ia__];
159 } else {
160 return ia__;
161 }
162 }
163
164 inline int spacegroup_number() const
165 {
166 if (spg_dataset_) {
167 return spg_dataset_->spacegroup_number;
168 } else {
169 return 0;
170 }
171 }
172
173 inline auto international_symbol() const
174 {
175 if (spg_dataset_) {
176 return std::string(spg_dataset_->international_symbol);
177 } else {
178 return std::string("n/a");
179 }
180 }
181
182 inline auto hall_symbol() const
183 {
184 if (spg_dataset_) {
185 return std::string(spg_dataset_->hall_symbol);
186 } else {
187 return std::string("n/a");
188 }
189 }
190
191 inline auto transformation_matrix() const
192 {
193 if (spg_dataset_) {
194 return r3::matrix<double>(spg_dataset_->transformation_matrix);
195 } else {
196 return r3::matrix<double>({{1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}});
197 }
198 }
199
200 inline auto origin_shift() const
201 {
202 if (spg_dataset_) {
203 return r3::vector<double>(spg_dataset_->origin_shift[0],
204 spg_dataset_->origin_shift[1],
205 spg_dataset_->origin_shift[2]);
206 } else {
207 return r3::vector<double>(0, 0, 0);
208 }
209 }
210
211 /// Number of symmetries including the magnetic configuration.
212 /** This is less or equal to the number of crystal symmetries. */
213 inline int size() const
214 {
215 return static_cast<int>(magnetic_group_symmetry_.size());
216 }
217
218 inline auto const& operator[](int isym__) const
219 {
220 assert(isym__ >= 0 && isym__ < this->size());
221 return magnetic_group_symmetry_[isym__];
222 }
223
224 auto const& lattice_vectors() const
225 {
226 return lattice_vectors_;
227 }
228
229 auto const& inverse_lattice_vectors() const
230 {
232 }
233
234 inline auto num_atoms() const
235 {
236 return num_atoms_;
237 }
238
239 inline auto num_atom_types() const
240 {
241 return num_atom_types_;
242 }
243
244 inline auto atom_type(int ia__) const
245 {
246 return types_[ia__];
247 }
248
249 /// Get an error in metric tensor.
250 /** Metric tensor in transformed under lattice symmetry operations and compareed with
251 * the initial value. It should stay invariant under transformation. This, however,
252 * is not always guaranteed numerically, especially when spglib uses large tolerance
253 * and find more symmeetry operations.
254 *
255 * The error is the maximum value of \f$ |M_{ij} - \tilde M_{ij}| \f$ where \f$ M_{ij} \f$
256 * is the initial metric tensor and \f$ \tilde M_{ij} \f$ is the transformed tensor. */
257 double metric_tensor_error() const;
258
259 /// Get error in rotation matrix of the symmetry operation.
260 /** Comparte rotation matrix in Cartesian coordinates with its inverse transpose. They should match.
261 *
262 * The error is the maximum value of \f$ |R_{ij} - R_{ij}^{-T}| \f$, where \f$ R_{ij} \f$ is the rotation
263 * matrix and \f$ R_{ij}^{-T} \f$ inverse transpose of the rotation matrix. */
264 double sym_op_R_error() const;
265
266 /// Print information about the unit cell symmetry.
267 void print_info(std::ostream& out__, int verbosity__) const;
268};
269
270} // namespace
271
272/** \page sym Symmetry
273 * \section section1 Definition of symmetry operation
274 *
275 * SIRIUS uses Spglib to find the spacial symmetry operations. Spglib defines symmetry operation in fractional
276 * coordinates:
277 * \f[
278 * {\bf x'} = \{ {\bf R} | {\bf t} \} {\bf x} \equiv {\bf R}{\bf x} + {\bf t}
279 * \f]
280 * where \b R is the proper or improper rotation matrix with elements equal to -1,0,1 and determinant of 1
281 * (pure rotation) or -1 (rotoreflection) and \b t is the fractional translation, associated with the symmetry
282 * operation. The inverse of the symmetry operation is:
283 * \f[
284 * {\bf x} = \{ {\bf R} | {\bf t} \}^{-1} {\bf x'} = {\bf R}^{-1} ({\bf x'} - {\bf t}) =
285 * {\bf R}^{-1} {\bf x'} - {\bf R}^{-1} {\bf t}
286 * \f]
287 *
288 * We will always use an \a active transformation (transformation of vectors or functions) and never a passive
289 * transformation (transformation of coordinate system). However one should remember definition of the function
290 * transformation:
291 * \f[
292 * \hat {\bf P} f({\bf r}) \equiv f(\hat {\bf P}^{-1} {\bf r})
293 * \f]
294 *
295 * It is straightforward to get the rotation matrix in Cartesian coordinates. We know how the vector in Cartesian
296 * coordinates is obtained from the vector in fractional coordinates:
297 * \f[
298 * {\bf v} = {\bf L} {\bf x}
299 * \f]
300 * where \b L is the 3x3 matrix which clomuns are three lattice vectors. The backward transformation is simply
301 * \f[
302 * {\bf x} = {\bf L}^{-1} {\bf v}
303 * \f]
304 * Now we write rotation operation in fractional coordinates and apply the backward transformation to Cartesian
305 * coordinates:
306 * \f[
307 * {\bf x'} = {\bf R}{\bf x} \rightarrow {\bf L}^{-1} {\bf v'} = {\bf R} {\bf L}^{-1} {\bf v}
308 * \f]
309 * from which we derive the rotation operation in Cartesian coordinates:
310 * \f[
311 * {\bf v'} = {\bf L} {\bf R} {\bf L}^{-1} {\bf v}
312 * \f]
313 */
314
315#endif // __UNIT_CELL_SYMMETRY_H__
Representation of the crystal symmetry.
int num_atom_types_
Number of atom types.
void print_info(std::ostream &out__, int verbosity__) const
Print information about the unit cell symmetry.
std::vector< space_group_symmetry_descriptor > space_group_symmetry_
List of all space group symmetry operations.
r3::matrix< double > inverse_lattice_vectors_
Inverse of the lattice vectors matrix.
int num_atoms_
Number of atoms in the unit cell.
double metric_tensor_error() const
Get an error in metric tensor.
std::vector< int > types_
Atom types.
sddk::mdarray< double, 2 > positions_
Atomic positions.
int num_spg_sym() const
Number of crystal symmetries without magnetic configuration.
std::vector< magnetic_group_symmetry_descriptor > magnetic_group_symmetry_
List of all magnetic group symmetry operations.
int size() const
Number of symmetries including the magnetic configuration.
sddk::mdarray< double, 2 > magnetization_
Magnetic moments of atoms.
double sym_op_R_error() const
Get error in rotation matrix of the symmetry operation.
r3::matrix< double > lattice_vectors_
Matrix of lattice vectors.
SpglibDataset * spg_dataset_
Crystal structure descriptor returned by spglib.
Multidimensional array with the column-major (Fortran) order.
Definition: memory.hpp:660
Memory management functions and classes.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
A time-based profiler.
Simple classes and functions to work with vectors and matrices of the R^3 space.
Descriptor of the magnetic group symmetry operation.
space_group_symmetry_descriptor spg_op
Element of space group symmetry.
r3::matrix< double > spin_rotation_inv
Inverse of proper spin rotation matrix in Cartesian coordinates.
r3::matrix< double > spin_rotation
Proper rotation matrix in Cartesian coordinates.
Descriptor of the space group symmetry operation.
std::vector< int > sym_atom
Symmetry table.
r3::matrix< double > Rc
(Im)proper Rotation matrix in Cartesian coordinates.
r3::vector< double > t
Fractional translation.
std::vector< int > inv_sym_atom
Invere symmetry table.
int proper
Proper (+1) or improper (-1) rotation.
r3::matrix< int > invR
Inverse of R.
r3::matrix< int > R
Rotational part of symmetry operation (fractional coordinates).
r3::matrix< double > Rcp
Proper rotation matrix in Cartesian coordinates.
r3::vector< double > euler_angles
Three Euler angles that generate the proper rotation matrix.
std::vector< r3::vector< int > > inv_sym_atom_T
Translation vector that prings symmetry-transformed atom back to the unit cell.
r3::matrix< int > invRT
Inverse transposed of R.