12 typedef std::vector<Lattice>::iterator vec_lat_it;
13 typedef std::back_insert_iterator<std::vector<SymOp> > vec_symop_back_inserter;
18 vec_lat_it, vec_lat_it, array_symop_cit, array_symop_cit);
20 template vec_symop_back_inserter Lattice::find_invariant_subgroup<array_symop_cit, vec_symop_back_inserter>(
21 array_symop_cit, array_symop_cit, vec_symop_back_inserter, double)
const;
24 const Lattice &,
const Lattice &, array_symop_cit, array_symop_cit, double);
28 const Eigen::Vector3d &vec2,
29 const Eigen::Vector3d &vec3) {
40 m_inv_lat_mat(lat_mat.
inverse()) {
51 latmat /= pow(latmat.determinant(), 1.0 / 3.0);
63 latmat /= pow(latmat.determinant(), 1.0 / 3.0);
70 return Lattice(Eigen::Matrix3d::Identity());
78 1, -1.0 / sqrt(3.0), 0,
79 0, 2.0 / sqrt(3.0), 0,
82 return Lattice(latmat.transpose());
121 m_lat_mat.transposeInPlace();
130 int tprec = stream.precision();
131 std::ios::fmtflags tflags = stream.flags();
132 stream.precision(_prec);
133 stream.width(_prec + 3);
134 stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
135 stream << 1.0 <<
'\n';
137 stream <<
' ' << std::setw(_prec + 8) <<
m_lat_mat.col(0).transpose() <<
'\n';
138 stream <<
' ' << std::setw(_prec + 8) <<
m_lat_mat.col(1).transpose() <<
'\n';
139 stream <<
' ' << std::setw(_prec + 8) <<
m_lat_mat.col(2).transpose() <<
'\n';
141 stream.precision(tprec);
142 stream.flags(tflags);
165 Lattice recip_lat = (*this).get_reciprocal();
166 double prim_density = (prim_kpoints[0] * prim_kpoints[1] * prim_kpoints[2]) / (prim_recip_lat.
vol());
167 double super_density = 0;
174 for(
int i = 0; i < 3; i++) {
178 double shortest = prim_vec_lengths.
min();
179 int short_ind = prim_vec_lengths.
find(shortest);
185 double scale = (prim_kpoints[short_ind] / shortest);
187 for(
int i = 0; i < 3; i++) {
188 super_kpoints[i] = int(ceil(scale * recip_lat.
length(i)));
191 super_density = (super_kpoints[0] * super_kpoints[1] * super_kpoints[2]) / (recip_lat.
vol());
196 while(super_density < prim_density) {
198 prim_kpoints[short_ind]++;
200 scale = (prim_kpoints[short_ind] / shortest);
203 for(
int i = 0; i < 3; i++) {
204 super_kpoints[i] = int(ceil(scale * recip_lat.
length(i)));
209 super_density = (super_kpoints[0] * super_kpoints[1] * super_kpoints[2]) / (recip_lat.
vol());
215 return super_kpoints;
223 if(sub_group.
size() != 0) {
224 std::cerr <<
"WARNING in Lattice::find_invariant_group" << std::endl;
225 std::cerr <<
"The subgroup isn't empty and it's about to be rewritten!" << std::endl;
255 return SymOp {(this->
lat_column_mat().transpose()).colPivHouseholderQr().solve(canon.lat_column_mat().transpose()).transpose()};
267 return SymOp {(this->
lat_column_mat().transpose()).colPivHouseholderQr().solve(canon.lat_column_mat().transpose()).transpose()};
306 if(point_group.
size() != 0) {
307 std::cerr <<
"WARNING in Lattice::generate_point_group" << std::endl;
308 std::cerr <<
"The point group for your lattice isn't empty and it's about to be rewritten!" << std::endl;
319 Eigen::Matrix3i::Constant(1),
320 Eigen::Matrix3i::Constant(1));
326 if(is_equiv(pg_count())) {
333 std::cerr <<
"*** WARNING *** \n"
334 <<
" Lattice::generate_point_group() has been called on an ill-conditioned lattice \n"
335 <<
" (i.e., a well-defined point group could not be found with the supplied tolerance of " << pg_tol <<
").\n"
336 <<
" CASM will use the group closure of the symmetry operations that were found. Please consider using the \n"
337 <<
" CASM symmetrization tool on your input files.\n";
355 if(!point_group.
is_group(large_tol)) {
356 std::cout <<
"This is not a group. It is being enforced...\n";
359 for(
Index i = 0; i < point_group.
size(); i++) {
360 tarray.
push_back(point_group[i].map_error());
375 for(
double i = small_tol; i <= large_tol; i += increment) {
392 std::cout << tols[i] <<
"\t" << num_ops[i] <<
"\t" << is_group[i] <<
"\t" << old_name[i] <<
"\t" << num_enforced_ops[i] <<
"\t" << is_group_now[i] <<
"\t" << new_name[i] <<
"\n";
416 for(
auto it = enumerator.
begin(); it != enumerator.
end(); ++it) {
447 bool minimized =
false;
456 for(i = 0; i < 3; i++) {
457 for(j = 0; j < 3; j++) {
469 for(i = 0; i < 3; i++) {
499 reduced_mags = reduced_lat_mat.transpose() * reduced_lat_mat;
507 tMat = (reduced_lat_mat * skew[s]);
510 tMat_mags = tMat.transpose() * tMat;
512 for(nv = 0; nv < 3; nv++) {
513 if(tMat_mags(nv, nv) < reduced_mags(nv, nv)) {
514 reduced_lat_mat = tMat;
515 reduced_mags = reduced_lat_mat.transpose() * reduced_lat_mat;
524 Lattice reduced_lat(reduced_lat_mat);
548 for(
Index nv = 0; nv < vtable.size(); nv++) {
549 tproj = vtable.row(nv) * pos;
553 else if(tproj > 1.0) {
569 Eigen::Vector3d tpoint;
577 Eigen::Vector3i(1, 1, 1),
578 Eigen::Vector3i(1, 1, 1));
582 for(; combo_count.
valid(); ++combo_count) {
583 if(combo_count().isZero())
continue;
586 for(i = 0; i < 3; i++) {
587 if(combo_count[(i + 1) % 3] == 0 || combo_count[(i + 2) % 3] == 0)
589 if((180. / M_PI)*
CASM::angle(combo_count[(i + 1) % 3]*tlat_reduced[(i + 1) % 3], combo_count[(i + 2) % 3]*tlat_reduced[(i + 2) % 3]) +
TOL < 90.) {
598 tpoint = tlat_reduced.
lat_column_mat() * combo_count().cast<
double>();
600 double t_rad = tpoint.norm();
631 for(
int i = 0; i < 3; i++) {
632 recip.col(i) *= radius / recip.col(i).norm();
635 auto lambda = [](
double val) {
638 return (
inv_lat_column_mat() * recip).cwiseAbs().unaryExpr(lambda).colwise().maxCoeff().cast<
int>();
647 multimat = result.second.cast<
double>();
648 return result.first != symoplist.
end();
657 multimat = result.second.cast<
double>();
724 if(millers == Eigen::Vector3i(0, 1, 0)) {
725 std::cout <<
"No chopping neccesary" << std::endl;
726 std::cout <<
"Flipping your vectors to bring a and b into plane:" << std::endl;
727 std::cout <<
"b --> c" << std::endl;
728 std::cout <<
"a --> b" << std::endl;
729 std::cout <<
"c --> a" << std::endl;
733 else if(millers == Eigen::Vector3i(1, 0, 0)) {
734 std::cout <<
"No chopping neccesary" << std::endl;
735 std::cout <<
"Flipping your vectors to bring a and b into plane:" << std::endl;
736 std::cout <<
"a --> c" << std::endl;
737 std::cout <<
"b --> a" << std::endl;
738 std::cout <<
"c --> b" << std::endl;
742 else if(millers == Eigen::Vector3i(0, 0, 1)) {
749 else if(millers[0] == 0 || millers[1] == 0 || millers[2] == 0) {
754 if(millers[zero] == 0) {
765 Eigen::Vector3d H_miller_point, K_miller_point;
767 Eigen::Vector3d millers_dubs;
770 millers_dubs = millers.cast<
double>();
774 Eigen::Vector3d inv_miller_dubs;
775 Eigen::Vector3i inv_miller;
780 inv_miller_dubs[zero] = 0;
781 inv_miller_dubs[(zero + 1) % 3] = 1.0 / millers_dubs[(zero + 1) % 3];
782 inv_miller_dubs[(zero + 2) % 3] = 1.0 / millers_dubs[(zero + 2) % 3];
785 H_miller_point = inv_miller[(zero + 1) % 3] *
lat_column_mat().col((zero + 1) % 3);
786 K_miller_point = inv_miller[(zero + 2) % 3] *
lat_column_mat().col((zero + 2) % 3);
788 std::cout <<
"inv millers dubs: " << inv_miller_dubs << std::endl;
789 std::cout <<
"inv millers : " << inv_miller << std::endl;
791 HK = K_miller_point - H_miller_point;
792 surface_cell.col(1) = HK;
801 Eigen::Vector3d H_miller_point, K_miller_point, L_miller_point;
802 Eigen::Vector3d inv_miller_dubs;
803 Eigen::Vector3i inv_miller;
805 Eigen::Vector3d millers_dubs;
806 millers_dubs = millers.cast<
double>();
808 inv_miller_dubs[0] = 1.0 / millers_dubs[0];
809 inv_miller_dubs[1] = 1.0 / millers_dubs[1];
810 inv_miller_dubs[2] = 1.0 / millers_dubs[2];
821 Eigen::Vector3d HK, KL, LH;
822 Eigen::Vector3d tangles;
825 HK = K_miller_point - H_miller_point;
826 KL = L_miller_point - K_miller_point;
827 LH = H_miller_point - L_miller_point;
838 for(
int i = 1; i < 3; i++) {
846 for(
int i = 0; i < 3; i++) {
848 for(
int j = maxval; j > 1; j--) {
852 for(
int k = 0; k < 3; k++) {
872 double HKKL, KLLH, LHHK;
873 HKKL = HK.cross(KL).norm();
874 KLLH = KL.cross(LH).norm();
875 LHHK = LH.cross(HK).norm();
877 if(HKKL <= KLLH && HKKL <= LHHK) {
878 surface_cell.col(0) = HK;
879 surface_cell.col(1) = KL;
882 else if(KLLH <= HKKL && KLLH <= LHHK) {
883 surface_cell.col(0) = KL;
884 surface_cell.col(1) = LH;
888 surface_cell.col(0) = LH;
889 surface_cell.col(1) = HK;
896 Eigen::Vector3d normal;
897 Eigen::Vector3i L_combination;
907 if(fabs(normal[0]) >= fabs(normal[1]) && fabs(normal[0]) >= fabs(normal[2]) && normal[0] != 0) {
908 normal = normal / normal[0];
912 else if(fabs(normal[1]) >= fabs(normal[2]) && fabs(normal[1]) >= fabs(normal[0]) && fabs(normal[1]) != 0) {
913 normal = normal / normal[1];
917 normal = normal / normal[2];
920 std::cout <<
"New cell vectors a and b have been generated:" << std::endl;
921 std::cout <<
"Vector A: <" << surface_cell.col(0) <<
">" << std::endl;
922 std::cout <<
"Vector B: <" << surface_cell.col(1) <<
">" << std::endl;
923 std::cout <<
"Gamma :" << (180 / M_PI)*
CASM::angle(surface_cell.col(0), surface_cell.col(1)) <<
"\u00B0" << std::endl << std::endl;
924 std::cout <<
"Ready to make C..." << std::endl;
926 Eigen::Vector3d tnormal;
928 double orthoscore = 1;
929 double torthoscore = 0;
933 bool one_found =
false;
935 normal = tnormal * factor;
938 L_combination[0] = int(floor(normal[0] + 0.5));
939 L_combination[1] = int(floor(normal[1] + 0.5));
940 L_combination[2] = int(floor(normal[2] + 0.5));
944 surface_cell.col(2) =
lat_column_mat() * L_combination.cast<
double>();
947 if(orthoscore > torthoscore +
TOL) {
948 torthoscore = orthoscore;
949 std::cout <<
"Attempt No." << factor <<
" to get third lattice vector:" << std::endl;
950 std::cout <<
"Combine: " << L_combination[0] <<
"*a+" << L_combination[1] <<
"*b+" << L_combination[2] <<
"*c" << std::endl << std::endl;
951 std::cout <<
"Cell overview:" << std::endl;
952 std::cout <<
"Orthogonality score: " << orthoscore << std::endl;
953 std::cout <<
"Vector A: <" << surface_cell.col(0) <<
" >" << std::endl;
954 std::cout <<
"Vector B: <" << surface_cell.col(1) <<
" >" << std::endl;
955 std::cout <<
"Vector C: <" << surface_cell.col(2) <<
" >" << std::endl << std::endl;
956 std::cout <<
"Alpha :" << (180 / M_PI)*
CASM::angle(surface_cell.col(1), surface_cell.col(2)) <<
"\u00B0" << std::endl << std::endl;
957 std::cout <<
"Beta :" << (180 / M_PI)*
CASM::angle(surface_cell.col(2), surface_cell.col(0)) <<
"\u00B0" << std::endl << std::endl;
958 std::cout <<
"Gamma :" << (180 / M_PI)*
CASM::angle(surface_cell.col(0), surface_cell.col(1)) <<
"\u00B0" << std::endl << std::endl << std::endl;
960 last_surface_cell = surface_cell;
963 new_vol = fabs(surface_cell.col(2).dot(surface_cell.col(0).cross(surface_cell.col(1))));
965 std::cout <<
"Volume: " << new_vol << std::endl;
966 std::cout <<
"Volume equivalent to " << new_vol /
vol() <<
" primitive volumes" << std::endl << std::endl;
973 throw std::runtime_error(
"failed get_lattice_in_plane");
975 std::cerr <<
"Reached an outrageous size. Returning last generated cell" << std::endl;
976 surface_cell = last_surface_cell;
981 while(new_vol /
vol() < max_vol && orthoscore < 1);
985 Lattice surface_lat(surface_cell.col(0), surface_cell.col(1), surface_cell.col(2));
986 surface_lat.make_right_handed();
989 surface_lat.generate_point_group(surf_lat_pg);
992 surface_lat.is_supercell_of(*
this, surf_lat_pg, transmat);
994 std::cout <<
"Your conversion matrix was:" << std::endl << transmat << std::endl;
1016 if(A_is_niggli != B_is_niggli) {
1041 for(
Index ng = 0; ng < relaxed_pg.
size(); ng++) {
1046 tLat2 /= double(relaxed_pg.
size());
1052 Eigen::JacobiSVD<Eigen::Matrix3d> tSVD(tMat);
1053 tMat = Eigen::Matrix3d::Zero();
1054 for(
int i = 0; i < 3; i++) {
1055 tMat(i, i) = tSVD.singularValues()[i];
1058 tMat2 = tSVD.matrixU() * tMat * tSVD.matrixV().transpose();
1062 tSVD.compute(tMat2 * tMat.transpose());
1064 tMat = tSVD.matrixV() * tSVD.matrixU().transpose() * tMat2;
1066 for(
int i = 0; i < 3; i++) {
1067 for(
int j = 0; j < 3; j++) {
1068 tLat2(i, j) = tMat(i, j);
1119 lat = Lattice(json[0].get<Eigen::Vector3d >(), json[1].get<Eigen::Vector3d >(), json[2].get<Eigen::Vector3d >());
1164 long N = 1, num, denom;
1165 for(
Index i = 0; i < 3; i++) {
1166 for(
Index j = 0; j < 3; j++) {
1168 dA *= double(denom);
1184 for(
Index i = 0; i < 3; i++) {
1185 S(i, i) = N /
gcf(S(i, i), N);
1190 return tlat.get_reduced_cell();
1196 std::pair<bool, Eigen::MatrixXi>
is_supercell(
const Lattice &scel,
const Lattice &unit,
double tol) {
1201 return std::make_pair(
true,
iround(T));
1203 return std::make_pair(
false, T.cast<
int>());
1217 Lattice new_lat {lat};
1218 double min_vol = std::abs(
volume(new_lat));
1220 for(
int i = 0; i < 3; i++) {
1222 Lattice tmp_lat = lat;
1223 tmp_lat[i] = new_vector;
1224 double vol = std::abs(
volume(tmp_lat));
1226 if(vol < min_vol && vol > tol) {
const SymOp * const_iterator
void _generate_voronoi_table() const
populate voronoi information.
Eigen::Matrix3d m_inv_lat_mat
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].
virtual void sort()
Sort SymOp in the SymGroup.
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
bool is_canonical(double tol=TOL) const
Check if Lattice is in the canonical form.
SymOp sym_op() const
Return the SymOp, constructed from the map_error and cart_op stored after performing an equivalence c...
Lattice superdupercell(const Lattice &lat1, const Lattice &lat2)
returns Lattice that is smallest possible supercell of both input Lattice
void from_json(ClexDescription &desc, const jsonParser &json)
A Counter allows looping over many incrementing variables in one loop.
void generate_point_group(SymGroup &point_group, double pg_tol=TOL) const
Populate.
Array< double > pg_converge(double large_tol)
int gcf(int i1, int i2)
Find greatest common factor.
double length(Index i) const
Return length of i'th lattice vector.
void push_back(const T &toPush)
static Lattice hexagonal()
Construct cubic primitive cell of unit volume.
bool _eq(const Lattice &RHS) const
Are lattice vectors identical for two lattices, within TOL.
bool is_equivalent(const Lattice &RHS, double tol) const
Are two lattices the same, even if they have different lattice vectors.
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
Data structure for holding supercell enumeration properties.
Object copy_apply(const Transform &f, Object obj, Args &&...args)
const_iterator end() const
A const iterator to the past-the-last volume.
bool standard_orientation_compare(const Eigen::Matrix3d &low_score_lat_mat, const Eigen::Matrix3d &high_score_lat_mat, double compare_tol)
Determine whether high_score has a more standard format than low_score.
Eigen::MatrixXd const & voronoi_table() const
Return voronoi table, which specifies outward-pointing normals of Lattice Voronoi cell...
Lattice get_reduced_cell() const
Find the lattice vectors which give most compact unit cell Compactness is measured by how close lat_c...
A fake container of supercell matrices.
void print(std::ostream &stream, int _prec=8) const
template Lattice superdupercell< vec_lat_it, array_symop_cit >(vec_lat_it, vec_lat_it, array_symop_cit, array_symop_cit)
static Lattice bcc()
Construct BCC primitive cell of unit volume.
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
template std::pair< array_symop_cit, Eigen::MatrixXi > is_supercell< Lattice, array_symop_cit >(const Lattice &, const Lattice &, array_symop_cit, array_symop_cit, double)
Lattice get_lattice_in_plane(Eigen::Vector3i millers, int max_vol=20) const
Generates a lattice with vectors a and b parallel to the plane described by the miller indeces...
Putting all the Lattice comparisons in one place.
double m_inner_voronoi_radius
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Eigen::MatrixXd m_voronoi_table
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
Lattice replace_vector(const Lattice &lat, const Eigen::Vector3d &new_vector, double tol)
Returns a minimum volume Lattice obtainable by replacing one Lattice vector with tau.
const Eigen::Matrix3d & inv_lat_column_mat() const
Inverse of Lattice::lat_column_mat() It is the transformation matrix 'C2F', such that f = C2F * c whe...
Lattice(const Eigen::Vector3d &vec1, const Eigen::Vector3d &vec2, const Eigen::Vector3d &vec3)
const_iterator begin() const
A const iterator to the beginning volume, specify here how the iterator should jump through the enume...
static Lattice cubic()
Construct simple cubic primitive cell of unit volume.
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
bool is_niggli(const Eigen::Matrix3d &test_lat_mat, double compare_tol)
Check whether the given lattice (represented as a matrix) is in niggli TYPE ?? reduced form (does not...
void read(std::istream &stream)
T norm(const Tensor< T > &ttens)
EigenIndex Index
For long integer indexing:
Lattice canonical_equivalent_lattice(const Lattice &in_lat, const SymGroup &point_grp, double compare_tol)
Find the niggli, most standard oriented version of the given orbit (defined by the given SymGroup) of...
const Array< std::complex< double > >::X2 & character_table() const
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.
Eigen::Matrix< int, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime > scale_to_int(const Eigen::MatrixBase< Derived > &val, double _tol=TOL)
Take a vector of doubles, and multiply by some factor that turns it into a vector of integers (within...
Eigen::CwiseUnaryOp< decltype(std::ptr_fun(boost::math::lround< typename Derived::Scalar >)), const Derived > lround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXl.
SymOp to_canonical(double tol=TOL) const
Returns the operation that applied to *this returns the canonical form.
void enforce_group(double tol=TOL, Index max_size=200)
Enforce group property by adding products of operations to the group.
Lattice canonical_form(double tol=TOL) const
Returns the canonical equivalent Lattice, using the point group of the Lattice.
bool is_supercell_of(const Lattice &tile, Eigen::Matrix3d &multimat, double _tol=TOL) const
Matrix that relates two lattices (e.g., strain or slat)
SymOp inverse() const
get the inverse of this SymOp
Eigen::Vector3i get_millers(Eigen::Vector3d plane_normal, double tolerance=TOL) const
Given a normal vector, a Vector3 containing the miller indeces for the lattice is generated...
Index find(const T &test_elem) const
bool is_group(double tol=TOL) const
Check to see if SymGroup satisfies the group property.
double vol() const
Return signed volume of this lattice.
bool is_integer(const Eigen::MatrixBase< Derived > &M, double tol)
Check if Eigen::Matrix is integer.
SymOpOutputIterator find_invariant_subgroup(SymOpIterator begin, SymOpIterator end, SymOpOutputIterator result, double pg_tol=TOL) const
Output the SymOp that leave this lattice invariant.
Lattice scaled_lattice(double scale) const
Return scaled copy of this lattice (Note: Volume will be scaled by scale^3)
bool operator<(const Lattice &RHS) const
Compare two Lattice.
void nearest_rational_number(double val, long &numerator, long &denominator, double tol=TOL)
Lattice get_reciprocal() const
Return reciprocal lattice.
virtual void push_back(const SymOp &new_op)
void reserve(Index new_max)
bool is_right_handed() const
Check if the lattice is right handed.
Eigen::Vector3i enclose_sphere(double radius) const
jsonParser & push_back(const T &value)
Puts new valued element at end of array of any type T for which 'jsonParser& to_json( const T &value...
void smith_normal_form(const Eigen::MatrixBase< DerivedIn > &M, Eigen::MatrixBase< DerivedOut > &U, Eigen::MatrixBase< DerivedOut > &S, Eigen::MatrixBase< DerivedOut > &V)
Return the smith normal form, M == U*S*V.
double max_voronoi_measure(const Eigen::Vector3d &pos, Eigen::Vector3d &lattice_trans) const
void symmetrize(const SymGroup &relaxed_pg)
Force this lattice to have symmetry of group.
Lattice & make_right_handed()
Flip c vector if it's on the wrong side of a-b plane – return (*this)
void set_lattice(const Lattice &new_lat)
std::pair< bool, Eigen::MatrixXi > is_supercell(const Lattice &scel, const Lattice &unit, double tol)
Check if scel is a supercell of unitcell unit and some integer transformation matrix T...
double volume(const Lattice &lat)
Returns the volume of a Lattice.
Array< int > calc_kpoints(Array< int > prim_kpoints, Lattice prim_lat)
Matrix< long int, 3, 3 > Matrix3l
const std::string & get_name() const
Eigen::CwiseUnaryOp< decltype(std::ptr_fun(boost::math::iround< typename Derived::Scalar >)), const Derived > iround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXi.
double angle(Index i) const
Return angle between lattice vectors (*this)[(i+1)%3] and (*this)[(i+2)%3], in degrees.
SymOp from_canonical(double tol=TOL) const
Returns the operation that applied to the canonical form returns *this.
jsonParser & put_array()
Puts new empty JSON array.
static Lattice fcc()
Construct FCC primitive cell of unit volume.
Object & apply(const Transform &f, Object &obj, Args &&...args)
Eigen::Matrix3d m_lat_mat
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
int voronoi_number(const Eigen::Vector3d &pos) const
void generate_supercells(Array< Lattice > &supercell, const SymGroup &effective_pg, const ScelEnumProps &enum_props) const
Populate.