6 const std::string traits<symmetry_type>::name =
"symmetry_type";
8 const std::multimap<symmetry_type, std::vector<std::string> > traits<symmetry_type>::strval = {
22 screw_glide_shift(lat),
25 auto matrix = op.matrix();
29 vector_type _screw_glide_shift;
30 vector_type _location;
36 _axis = vector_type::Zero();
37 _location = vector_type::Zero();
38 _set(_axis, _screw_glide_shift, _location, lat);
46 _axis = vector_type::Zero();
48 _set(_axis, _screw_glide_shift, _location, lat);
53 int det =
round(matrix.determinant());
56 Eigen::EigenSolver<matrix_type> t_eig(det * matrix);
59 for(
Index i = 0; i < 3; i++) {
60 if(
almost_equal(t_eig.eigenvalues()(i), std::complex<double>(1, 0))) {
61 _axis = t_eig.eigenvectors().col(i).real();
67 for(
Index i = 0; i < 3; i++) {
79 vector_type ortho = _axis.unitOrthogonal();
80 vector_type rot = det * (matrix * ortho);
81 angle = fmod((180. / M_PI) * atan2(_axis.dot(ortho.cross(rot)), ortho.dot(rot)) + 360., 360.);
94 Coordinate coord(tau - tau.dot(_axis) * _axis, lat,
CART);
95 _screw_glide_shift = coord.cart();
99 _location = tau.dot(_axis) * _axis / 2.;
105 _screw_glide_shift = tau.dot(_axis) * _axis;
108 _location = (matrix_type::Identity() - matrix).
inverse() * tau;
116 Coordinate coord(tau.dot(_axis) * _axis, lat,
CART);
117 _screw_glide_shift = coord.cart();
121 tmat << ortho, ortho.cross(_axis);
126 _location = tmat * (Eigen::MatrixXd::Identity(2, 2) - tmat.transpose() * matrix * tmat).
inverse() * tmat.transpose() * tau;
131 _set(_axis, _screw_glide_shift, _location, lat);
135 void SymInfo::_set(
const vector_type &_axis,
136 const vector_type &_screw_glide_shift,
137 const vector_type &_location,
138 const Lattice &lat) {
139 axis = Coordinate(_axis, lat,
CART);
140 screw_glide_shift = Coordinate(_screw_glide_shift, lat,
CART);
141 location = Coordinate(_location, lat,
CART);
152 std::stringstream stream;
157 auto print_coord = [&](
const Coordinate & coord) {
158 coord.print(stream, mode, term, prec,
pad);
161 auto print_axis = [&](
const Coordinate & coord) {
162 coord.print_axis(stream, mode, term, prec,
pad);
165 switch(info.op_type) {
166 case symmetry_type::identity_op:
167 stream <<
"Identity Operation";
170 case symmetry_type::mirror_op:
171 stream.setf(std::ios::showpoint);
172 stream <<
"Mirror Operation with plane normal" << std::setw(7);
173 print_axis(info.axis);
176 case symmetry_type::glide_op:
177 stream.setf(std::ios::showpoint);
178 stream <<
"Glide Operation with plane normal" << std::setw(7);
179 print_axis(info.axis);
181 stream <<
"Glide Vector:" << std::setw(7);
182 print_coord(info.screw_glide_shift);
185 case symmetry_type::rotation_op:
186 stream.unsetf(std::ios::showpoint);
187 stream << std::setprecision(3) << info.angle <<
"-degree Rotation Operation about axis";
188 stream.setf(std::ios::showpoint);
189 stream << std::setw(7);
190 print_axis(info.axis);
193 case symmetry_type::screw_op:
194 stream.unsetf(std::ios::showpoint);
195 stream << std::setprecision(3) << info.angle <<
"-degree Screw Operation along axis";
196 stream.setf(std::ios::showpoint);
197 stream << std::setw(7);
198 print_axis(info.axis);
199 stream <<
"\n Screw Vector:" << std::setw(7);
200 print_coord(info.screw_glide_shift);
203 case symmetry_type::inversion_op:
204 stream <<
"Inversion Operation";
207 case symmetry_type::rotoinversion_op:
208 stream.unsetf(std::ios::showpoint);
209 stream << std::setprecision(3) << info.angle <<
"-degree Rotoinversion Operation about axis";
210 stream.setf(std::ios::showpoint);
211 stream << std::setw(7);
212 print_axis(info.axis);
215 case symmetry_type::invalid_op:
216 stream <<
"Invalid Operation !!!";
226 return to_string(SymInfo(op, lat), mode);
232 j[
"type"] = info.op_type;
234 if(info.op_type == symmetry_type::rotation_op ||
235 info.op_type == symmetry_type::screw_op ||
236 info.op_type == symmetry_type::rotoinversion_op) {
237 to_json_array(info.axis.const_cart().normalized(), j[
"rotation_axis"][
"CART"]);
238 to_json_array(info.axis.const_frac().normalized(), j[
"rotation_axis"][
"FRAC"]);
239 j[
"rotation_angle"] = info.angle;
241 else if(info.op_type == symmetry_type::mirror_op ||
242 info.op_type == symmetry_type::glide_op) {
243 to_json_array(info.axis.const_cart().normalized(), j[
"mirror_normal"][
"CART"]);
244 to_json_array(info.axis.const_frac().normalized(), j[
"mirror_normal"][
"FRAC"]);
247 if(info.op_type == symmetry_type::screw_op ||
248 info.op_type == symmetry_type::glide_op) {
249 to_json_array(info.screw_glide_shift.const_cart(), j[
"shift"][
"CART"]);
250 to_json_array(info.screw_glide_shift.const_frac(), j[
"shift"][
"FRAC"]);
253 if(info.op_type != symmetry_type::identity_op) {
254 to_json_array(info.location.const_cart(), j[
"invariant_point"][
"CART"]);
255 to_json_array(info.location.const_frac(), j[
"invariant_point"][
"FRAC"]);
double angle(const Eigen::Ref< const Eigen::Vector3d > &a, const Eigen::Ref< const Eigen::Vector3d > &b)
Get angle, in radians, between two vectors on range [0,pi].
Eigen::MatrixXd pad(const Eigen::MatrixXd &M, int n)
Construct a matrix consisting of blocks M and Identity(n,n)
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
std::string to_string(ENUM val)
Return string representation of enum class.
SymInfo(const SymOp &op, const Lattice &lat)
EigenIndex Index
For long integer indexing:
int float_sgn(T val, double compare_tol=TOL)
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.
void add_sym_info(const SymInfo &info, jsonParser &j)
Add to existing JSON object.
std::string description(const SymOp &op, const Lattice &lat, COORD_TYPE mode)
Print SymInfo to string.
CASM::jsonParser & to_json_array(const Eigen::MatrixBase< Derived > &value, CASM::jsonParser &json)
Write Eigen Matrix with 1 row or 1 column to JSON array.
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)