CASM  1.1.0
A Clusters Approach to Statistical Mechanics
SymInfo.cc
Go to the documentation of this file.
2 
4 #include "casm/symmetry/SymOp.hh"
5 
6 namespace CASM {
7 
8 SymInfo::SymInfo(const SymOp &op, const xtal::Lattice &lat)
9  : axis(lat),
10  screw_glide_shift(lat),
11  location(lat),
12  time_reversal(op.time_reversal()) {
13  auto matrix = op.matrix();
14  auto tau = op.tau();
15 
16  vector_type _axis;
17  vector_type _screw_glide_shift;
18  vector_type _location;
19 
20  // Simplest case is identity: has no axis and no location
21  if (almost_equal(matrix.trace(), 3.)) {
22  angle = 0;
24  _axis = vector_type::Zero();
25  _location = vector_type::Zero();
26  _set(_axis, _screw_glide_shift, _location, lat);
27  return;
28  }
29 
30  // second simplest case is inversion: has no axis and location is tau()/2
31  if (almost_equal(matrix.trace(), -3.)) {
32  angle = 0;
34  _axis = vector_type::Zero();
35  _location = tau / 2.;
36  _set(_axis, _screw_glide_shift, _location, lat);
37  return;
38  }
39 
40  // det is -1 if improper and +1 if proper
41  int det = round(matrix.determinant());
42 
43  // Find eigen decomposition of proper operation (by multiplying by
44  // determinant)
45  Eigen::EigenSolver<matrix_type> t_eig(det * matrix);
46 
47  // 'axis' is eigenvector whose eigenvalue is +1
48  for (Index i = 0; i < 3; i++) {
49  if (almost_equal(t_eig.eigenvalues()(i), std::complex<double>(1, 0))) {
50  _axis = t_eig.eigenvectors().col(i).real();
51  break;
52  }
53  }
54 
55  // Sign convention for 'axis': first non-zero element is positive
56  for (Index i = 0; i < 3; i++) {
57  if (!almost_zero(_axis[i])) {
58  _axis *= float_sgn(_axis[i]);
59  break;
60  }
61  }
62 
63  // get vector orthogonal to axis: ortho,
64  // apply matrix: rot
65  // and check angle between ortho and det*rot,
66  // using determinant to get the correct angle for improper
67  // (i.e. want angle before inversion for rotoinversion)
68  vector_type ortho = _axis.unitOrthogonal();
69  vector_type rot = det * (matrix * ortho);
70  angle = fmod(
71  (180. / M_PI) * atan2(_axis.dot(ortho.cross(rot)), ortho.dot(rot)) + 360.,
72  360.);
73 
74  /*
75  std::cout << "det: " << det << "\n";
76  std::cout << "y: " << _axis.dot(ortho.cross(rot)) << "\n";
77  std::cout << "x: " << ortho.dot(rot) << "\n";
78  std::cout << "angle: " << angle << std::endl;
79  */
80 
81  if (det < 0) {
82  if (almost_equal(angle, 180.)) {
83  // shift is component of tau perpendicular to axis
84  xtal::Coordinate coord(tau - tau.dot(_axis) * _axis, lat, CART);
85  _screw_glide_shift = coord.cart();
86 
87  // location is 1/2 of component of tau parallel to axis:
88  // matrix*location+tau = -location+tau = location
89  _location = tau.dot(_axis) * _axis / 2.;
90 
93  } else {
94  // shift is component of tau parallel to axis
95  _screw_glide_shift = tau.dot(_axis) * _axis;
96 
97  // rotoinversion is point symmetry, so we can solve matrix*p+tau=p for
98  // invariant point p
99  _location = (matrix_type::Identity() - matrix).inverse() * tau;
100 
102  }
103  } else {
104  // shift is component of tau parallel to axis
105  xtal::Coordinate coord(tau.dot(_axis) * _axis, lat, CART);
106  _screw_glide_shift = coord.cart();
107 
108  // Can only solve 2d location problem
109  Eigen::MatrixXd tmat(3, 2);
110  tmat << ortho, ortho.cross(_axis);
111 
112  // if A = tmat.transpose()*matrix()*tmat and s=tmat.transpose()*tau()
113  // then 2d invariant point 'v' is solution to A*v+s=v
114  // implies 3d invariant point 'p' is p=tmat*(eye(2)-A).inverse()*s
115  _location =
116  tmat *
117  (Eigen::MatrixXd::Identity(2, 2) - tmat.transpose() * matrix * tmat)
118  .inverse() *
119  tmat.transpose() * tau;
120 
123  }
124  _set(_axis, _screw_glide_shift, _location, lat);
125  return;
126 }
127 
128 void SymInfo::_set(const vector_type &_axis,
129  const vector_type &_screw_glide_shift,
130  const vector_type &_location, const xtal::Lattice &lat) {
131  axis = xtal::Coordinate(_axis, lat, CART);
132  screw_glide_shift = xtal::Coordinate(_screw_glide_shift, lat, CART);
133  location = xtal::Coordinate(_location, lat, CART);
134 }
135 
136 } // namespace CASM
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
Definition: SymOp.hh:28
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
Definition: SymOp.hh:60
const vector_type & tau() const
Const access of the cartesian translation vector, 'tau'.
Definition: SymOp.hh:63
Represents cartesian and fractional coordinates.
Definition: Coordinate.hh:34
Coordinate_impl::CartCoordinate cart()
Set Cartesian coordinate vector and update fractional coordinate vector.
Definition: Coordinate.hh:562
bool is_lattice_shift(double tol=TOL) const
Definition: Coordinate.cc:311
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
Eigen::Matrix< typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime > inverse(const Eigen::MatrixBase< Derived > &M)
Return the integer inverse matrix of an invertible integer matrix.
IdentitySymRepBuilder Identity()
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
Eigen::MatrixXd MatrixXd
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:104
int float_sgn(T val, double compare_tol=TOL)
Definition: CASM_math.hh:188
const COORD_TYPE CART
Definition: enum.hh:9
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
double angle
Definition: SymInfo.hh:42
xtal::Coordinate axis
Definition: SymInfo.hh:38
symmetry_type op_type
Definition: SymInfo.hh:31
xtal::Coordinate screw_glide_shift
Definition: SymInfo.hh:46
xtal::Coordinate location
A Cartesian coordinate that is invariant to the operation (if one exists)
Definition: SymInfo.hh:49
SymOp::vector_type vector_type
Definition: SymInfo.hh:55
SymInfo(const SymOp &op, const xtal::Lattice &lat)
Definition: SymInfo.cc:8
void _set(const vector_type &_axis, const vector_type &_screw_glide_shift, const vector_type &_location, const xtal::Lattice &lat)
Definition: SymInfo.cc:128