1 #include <boost/filesystem/fstream.hpp>
26 #include "casm/external/Eigen/Core"
27 #include "casm/external/Eigen/src/Core/Matrix.h"
56 m_desc.add_options()(
"transf-mat",
60 "1 or more files containing a 3x3 transformation matrix "
61 "used to create a supercell.")
63 (
"get-transf-mat",
"If it exists, find the transformation matrix.")
67 "File with structure (POSCAR type) to use.")
72 "Name of supercell to use as unit cell. For ex. "
73 "'SCEL2_2_1_1_0_0_0'.")
76 "Construct the superduperlattice, the minimum supercell of "
77 "all input supercells "
78 "and configurations.")
81 "When constructing the superduperlattice, do not "
82 "consider other symmetrically "
83 "equivalent orientations.")
85 (
"min-volume", po::value<Index>(&
m_min_vol),
86 "Transforms the transformation matrix, T -> T', "
87 "where T' = T*M, such that "
88 "(T').determininant() >= V. This has the effect "
89 "that a supercell has a "
93 "Used with --min-volume to enforce that T' = "
94 "T*m*I, where I is the identity "
95 "matrix, and m is a scalar. This has the effect "
96 "of preserving the shape "
97 "of the resulting supercell, but increasing the "
101 "When used with --duper, show how the input "
102 "lattices are transformed "
103 "to tile the superduperlattice.")
106 "Will add the generated super "
107 "configuration in it's "
108 "canonical form in the equivalent "
112 "Print using VASP5 style (include "
118 "Tolerance used for checking "
135 std::string unitscelname;
137 std::vector<fs::path> tmatfile, abs_tmatfile, config_path;
138 fs::path abs_structfile;
142 po::variables_map vm;
149 po::parse_command_line(args.
argc(), args.
argv(), super_opt.
desc()),
152 if (!vm.count(
"help") && !vm.count(
"desc")) {
153 if (!vm.count(
"duper")) {
154 if (vm.count(
"transf-mat") + vm.count(
"get-transf-mat") != 1) {
155 err_log() <<
"Error in 'casm super'. Only one of --transf-mat or "
156 "--get-transf-mat may be chosen."
161 tmatfile.size() > 1) {
162 err_log() <<
"ERROR: more than one --confignames, --scelnames, or "
163 "--transf-mat argument "
164 "is only allowed for option --duper"
168 if (config_path.size() > 0) {
169 err_log() <<
"ERROR: the --configs option is only allowed with "
179 if (vm.count(
"help")) {
181 log() << super_opt.
desc() << std::endl;
186 if (vm.count(
"desc")) {
188 log() << super_opt.
desc() << std::endl;
189 log() <<
"DESCRIPTION" << std::endl;
192 <<
" casm super --transf-mat T "
194 <<
" - Print super lattice of the PRIM lattice "
198 <<
" casm super --structure POSCAR --transf-mat T "
200 <<
" - Print superstructure of a POSCAR "
204 <<
" casm super --confignames configname --transf-mat T "
206 <<
" - Print superstructure of a configuration "
210 <<
" casm super --structure POSCAR --unitcell scelname "
211 "--get-transf-mat \n"
212 <<
" - Check if POSCAR lattice is a supercell of unit cell "
214 <<
" if so print the transformation matrix "
216 <<
" - Uses primitive cell for unitcell if none given "
220 <<
" casm super --scelnames scelname --unitcell scelname "
222 <<
" - Check if configuration lattice is a supercell of unit cell "
224 <<
" and print the transformation matrix "
226 <<
" - Uses primitive cell for unitcell if none given "
230 " casm super --duper --scelnames scel1 [scel2 ...] --confignames "
232 " --configs [mylist ...] --transf-mat M1 [M2 ...] "
234 <<
" - Makes the superduperlattice of the lattices of all inputs "
236 <<
" - Using '--configs' with no arguments is equivalent to "
237 "'--configs MASTER',\n"
238 <<
" which uses the master config list "
240 <<
" - Default applies prim point group ops to try to find "
242 <<
" superduperlattice, disable with '--fixed-orientation' "
260 }
catch (po::error &e) {
261 err_log() <<
"ERROR: " << e.what() << std::endl << std::endl;
264 }
catch (std::exception &e) {
265 err_log() <<
"Unhandled Exception reached the top of main: " << e.what()
266 <<
", application will now exit" << std::endl;
276 if (vm.count(
"vasp5")) {
288 for (
auto &&file : tmatfile) {
289 abs_tmatfile.push_back(fs::absolute(file));
291 abs_structfile = fs::absolute(structfile);
293 if (vm.count(
"structure") && vm.count(
"transf-mat")) {
294 if (!fs::exists(abs_structfile)) {
295 log() <<
"ERROR: " << abs_tmatfile[0] <<
" not found." << std::endl;
298 std::ifstream abs_structfile_stream(abs_structfile.string());
303 if (!fs::exists(abs_tmatfile[0])) {
304 log() <<
"ERROR: " << abs_tmatfile[0] <<
" not found." << std::endl;
308 fs::ifstream file(abs_tmatfile[0]);
320 const fs::path &root = args.
root;
329 std::unique_ptr<PrimClex> uniq_primclex;
332 if (vm.count(
"duper")) {
334 std::map<std::string, Lattice> lat;
335 std::map<std::string, Lattice> config_lat;
338 if (vm.count(
"transf-mat")) {
339 for (
auto it = abs_tmatfile.begin(); it != abs_tmatfile.end(); ++it) {
340 Eigen::Matrix<int, 3, 3, Eigen::RowMajor> T;
341 fs::ifstream file(*it);
342 for (
int i = 0; i < 9; i++) {
351 if (vm.count(
"scelnames")) {
358 if (vm.count(
"confignames")) {
360 config_lat[*it] = lat[*it] =
366 if (vm.count(
"configs")) {
368 if (config_path.size() == 0) {
369 config_path.push_back(
"MASTER");
372 for (
const auto &p : config_path) {
376 config.supercell().lattice();
381 std::vector<Lattice> lat_only;
382 for (
auto it = lat.begin(); it != lat.end(); ++it) {
383 lat_only.push_back(it->second);
389 if (vm.count(
"fixed-orientation")) {
393 lat_only.begin(), lat_only.end(), begin, end);
396 if (vm.count(
"min-volume")) {
397 log() <<
" Enforcing minimum volume: " << min_vol;
398 if (vm.count(
"fixed-shape")) {
399 log() <<
" (with fixed shape)";
407 log() <<
" superduperlattice lattice: \n"
410 log() <<
" Initial transformation matrix:\n"
412 <<
"\n (volume = " <<
iround(T).cast<
double>().determinant()
416 min_vol, vm.count(
"fixed-shape"));
423 log() <<
" superduperlattice lattice: \n"
426 log() <<
" Transformation matrix, after enforcing mininum volume:\n"
428 <<
"\n (volume = " <<
iround(S).cast<
double>().determinant()
434 superduper = superduper_scel.
lattice();
436 log() <<
"--- Lattices as column vector matrices ---\n\n";
438 log() <<
" superduperlattice: " << superduper_scel.
name() <<
"\n\n";
440 log() <<
" superduperlattice lattice: \n"
443 log() <<
" Transformation matrix, relative the primitive cell:\n";
448 if (vm.count(
"verbose")) {
449 log() <<
"Transformation matrices: \n";
450 for (
auto it = lat.begin(); it != lat.end(); ++it) {
452 log() <<
" Unit: " << it->first <<
":\n"
453 << it->second.lat_column_mat() <<
"\n\n";
457 log() <<
" Superduper = (op*unit) * T\n\nop:\n";
458 log() << res.first->matrix() <<
"\n\n";
465 log() <<
"Write supercell database..." << std::endl;
467 log() <<
" DONE" << std::endl << std::endl;
469 if (vm.count(
"add-canonical")) {
470 log() <<
"Add super configurations:\n";
471 for (
auto it = config_lat.begin(); it != config_lat.end(); ++it) {
475 if (insert_res.insert_canonical) {
476 log() <<
" " << it->first <<
" -> "
477 << insert_res.canonical_it->name() <<
"\n";
481 log() <<
"Writing configuration database..." << std::endl;
483 log() <<
" DONE" << std::endl;
488 }
else if (vm.count(
"transf-mat")) {
490 if (!fs::exists(abs_tmatfile[0])) {
491 log() <<
"ERROR: " << abs_tmatfile[0] <<
" not found." << std::endl;
494 fs::ifstream file(abs_tmatfile[0]);
498 log() <<
"Read transformation matrix, T: \n" << T <<
"\n\n";
501 if (vm.count(
"min-volume")) {
502 if (!vm.count(
"fixed-shape")) {
503 log() <<
" Enforcing minimum volume: \n";
504 log() <<
" Finding T' = T*M, such that (T').determinant() >= "
507 log() <<
" Enforcing minimum volume (with fixed shape): \n";
508 log() <<
" Finding T' = T*m*I, such that (T').determinant() >= "
516 log() <<
" Initial transformation matrix:\n"
517 << T <<
"\n (volume = " << T.cast<
double>().determinant()
522 min_vol, vm.count(
"fixed-shape"));
524 Eigen::Matrix3i super_lat_matrix = T * M;
529 log() <<
" Transformation matrix, after enforcing mininum volume:\n"
530 << T <<
"\n (volume = " <<
iround(T).cast<
double>().determinant()
535 if (vm.count(
"scelnames")) {
540 log() <<
" Unit cell lattice: \n"
547 log() <<
" Add supercell: " << super_scel.
name() <<
"\n\n";
549 log() <<
" Supercell lattice: \n"
552 log() <<
" Transformation matrix: \n"
555 log() <<
"Write supercell database..." << std::endl;
557 log() <<
" DONE" << std::endl << std::endl;
561 else if (vm.count(
"confignames")) {
562 std::stringstream ss;
570 std::istringstream iss(ss.str());
573 log() <<
"Unit structure:";
574 log() <<
"\n------\n";
576 log() <<
"\n------\n";
582 super.
set_title(std::string(
"Supercell of ") + con.name());
584 log() <<
"Super structure:";
585 log() <<
"\n------\n";
587 log() <<
"\n------\n";
589 if (vm.count(
"add-canonical")) {
597 if (map_res.success()) {
598 auto insert_res = (map_res.maps.begin()->second).
config.insert();
601 if (insert_res.insert_canonical) {
602 log() <<
" The configuration was imported successfully as "
603 << imported_config.name() << std::endl
607 log() <<
" The configuration was mapped onto pre-existing "
608 "equivalent structure "
609 << imported_config.name() << std::endl
614 imported_config.push_back_source(json_src);
617 log() <<
" Failure to map configuration." << std::endl << std::endl;
621 log() <<
"Write supercell database..." << std::endl;
623 log() <<
" DONE" << std::endl << std::endl;
625 log() <<
"Writing configuration database..." << std::endl;
627 log() <<
" DONE" << std::endl;
640 Eigen::Matrix3i H_canon;
645 Eigen::Matrix3i T_niggli =
iround(U.inverse() * S_niggli);
648 std::stringstream s_name;
649 s_name <<
"SCEL" << H_niggli(0, 0) * H_niggli(1, 1) * H_niggli(2, 2)
650 <<
"_" << H_niggli(0, 0) <<
"_" << H_niggli(1, 1) <<
"_"
651 << H_niggli(2, 2) <<
"_" << H_niggli(1, 2) <<
"_" << H_niggli(0, 2)
652 <<
"_" << H_niggli(0, 1);
657 log() <<
"--- Lattices as column vector matrices ---\n\n";
659 log() <<
"Prim lattice, U:\n" << U <<
"\n\n";
661 log() <<
"Super lattice, S = U*T:\n" << S <<
"\n\n";
663 log() <<
"This is equivalent to '" << s_name.str()
664 <<
"', the equivalent super lattice \n"
665 <<
"in the standard orientation niggli cell, S_niggli:\n"
666 << S_niggli <<
"\n\n";
668 log() <<
"The transformation matrix (S_niggli = U*T) for '"
669 << s_name.str() <<
"' is:\n"
670 << T_niggli <<
"\n\n";
672 log() <<
"--- Lattices as row vector matrices ---\n\n";
674 log() <<
"Prim lattice:\n" << U.transpose() <<
"\n\n";
676 log() <<
"Super lattice:\n" << S.transpose() <<
"\n\n";
678 log() <<
"This is equivalent to '" << s_name.str()
679 <<
"', the equivalent super lattice \n"
680 <<
"in the standard orientation niggli cell:\n"
681 << S_niggli.transpose() <<
"\n\n";
687 if (vm.count(
"get-transf-mat")) {
690 if (vm.count(
"unitcell")) {
696 if (vm.count(
"structure")) {
697 std::ifstream abs_structfile_stream(abs_structfile.string());
700 }
else if (vm.count(
"scelnames")) {
703 log() <<
"Error in 'casm super --get-transf-mat'. No --structure or "
710 log() <<
"--- Lattices as column vector matrices ---\n\n";
720 std::tie(is_superlat, T) =
723 log() <<
"The super lattice is a supercell of the unit lattice.\n\n";
725 log() <<
"The transformation matrix, T, where S = U*T, is: \n"
728 log() <<
"The super lattice is NOT a supercell of the unit lattice.\n\n";
730 log() <<
"The transformation matrix, T, where S = U*T, is: \n"
static std::string path()
Get value_type string for path completion.
static std::string supercell()
Get value_type string for supercell completion.
void add_confignames_suboption()
Add a –confignames suboption.
const po::options_description & desc()
Get the program options, filled with the initialized values.
void add_help_suboption()
Add a plain –help and –desc suboptions.
po::options_description m_desc
void add_coordtype_suboption()
Add a –coord suboption to specify FRAC or CART.
void add_scelnames_suboption()
Add a –scelnames suboption.
void add_configlists_nodefault_suboption()
Add –configs suboption (no default)
void initialize() override
Fill in the options descriptions accordingly.
COORD_TYPE coordtype_enum() const
Return the coordinate type recasted as the CASM defined enum.
const std::vector< std::string > & config_strs() const
const std::vector< std::string > & supercell_strs() const
Returns the list of the supercells for add_scelnames_suboption()
const std::string & unit_scel_str() const
std::vector< fs::path > m_transf_mat_paths
std::string m_unit_scel_str
const fs::path & struct_path() const
const std::vector< fs::path > & selection_paths() const
Returns the string corresponding to add_config_suboption()
const std::vector< fs::path > & transf_mat_paths() const
ConfigMapperResult import_structure(SimpleStructure const &_struc, Configuration const *hint_ptr=nullptr, std::vector< DoFKey > const &_hint_dofs={ "occ"}) const
imports structure specified by '_struc' into primclex()
boost::iterator_range< iterator > selected()
void error(const std::string &what)
PrimClex is the top-level data structure for a CASM project.
Structure specifies the lattice and atomic basis of a crystal.
const SymGroup & point_group() const
const Lattice & lattice() const
Represents a supercell of the primitive parent crystal structure.
const Lattice & lattice() const
The super lattice.
Eigen::Matrix3l transf_mat() const
std::pair< DB::DatabaseIterator< Supercell >, bool > insert() const
Insert the canonical form of this into the database.
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Print POSCAR with formating options.
void set_coord_mode(COORD_TYPE mode)
Set coordinate mode.
void set_atom_names_off()
Do not print atom names line.
void set_atom_names_on()
Print atom names line.
void sort()
Default sort is by atom name.
void print(std::ostream &sout) const
Print POSCAR to stream.
BasicStructure specifies the lattice and atomic basis of a crystal.
static BasicStructure from_poscar_stream(std::istream &poscar_stream, double tol=TOL)
const std::string & title() const
void set_title(std::string const &_title)
Set the title of the structure.
const Lattice & lattice() const
COORD_MODE specifies the current coordinate mode (Fractional or Cartesian)
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
PrimClex & make_primclex_if_not(const CommandArgs &args, std::unique_ptr< PrimClex > &uniq_primclex)
If !_primclex, construct new PrimClex stored in uniq_primclex, then return reference to existing or c...
Eigen::Matrix3i enforce_min_volume(const Lattice &unit, const Eigen::Matrix3i &T, const SymOpVector &point_grp, Index volume, bool fix_shape=false)
Return a transformation matrix that ensures a supercell of at least some volume.
Lattice make_superlattice(const Lattice &lat, const Eigen::Matrix< IntegralType, 3, 3, Options > &transf_mat)
Returns a super Lattice. Transformation matrix must be integer.
std::pair< bool, Eigen::Matrix3d > is_superlattice(const Lattice &scel, const Lattice &unit, double tol)
Check if scel is a superlattice of unitcell unit and some integer transformation matrix T.
std::pair< Eigen::MatrixXi, Eigen::MatrixXi > hermite_normal_form(const Eigen::MatrixXi &M)
Return the hermite normal form, M == H*V.
Eigen::CwiseUnaryOp< decltype(Local::iround_l< typename Derived::Scalar >), const Derived > iround(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd to Eigen::MatrixXi.
DB::Database< T > & db() const
const PrimType & prim() const
const Access to primitive Structure
void commit(ProjectSettings const &set)
std::string scelname(const Structure &prim, const Lattice &superlat)
Make supercell name name [deprecated].
ConfigIO::GenericConfigFormatter< jsonParser > config()
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Lattice equivalent(Lattice const &in_lat, SymOpVector const &point_grp, double compare_tol)
Lattice make_equivalent_superduperlattice(LatIterator begin, LatIterator end, SymOpIterator op_begin, SymOpIterator op_end)
returns Lattice that is smallest possible superlattice of all input Lattice
BasicStructure make_superstructure(const BasicStructure &tiling_unit, const Eigen::Matrix< IntegralType, 3, 3, Options > &transformation_matrix)
std::pair< OpIterator, Eigen::Matrix3d > is_equivalent_superlattice(const Object &scel, const Object &unit, OpIterator begin, OpIterator end, double tol)
xtal::SimpleStructure make_simple_structure(Supercell const &_scel, ConfigDoF const &_dof, std::vector< DoFKey > const &_which_dofs={})
Construct from ConfigDoF _dof belonging to provided Supercell _scel.
int super_command(const CommandArgs &args)
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
INDEX_TYPE Index
For long integer indexing:
Data structure holding basic CASM command info.
Struct with optional parameters for Config Mapping Specifies default parameters for all values,...