CASM  1.1.0
A Clusters Approach to Statistical Mechanics
symmetrize.cc
Go to the documentation of this file.
2 
3 #include <boost/filesystem.hpp>
4 
5 #include "casm/app/APICommand.hh"
6 #include "casm/app/io/json_io.hh"
7 #include "casm/casm_io/Log.hh"
9 #include "casm/clex/PrimClex.hh"
17 
18 namespace symmetrize_impl {
19 using namespace CASM;
20 
21 void _print_factor_group_convergence(const Structure &struc, double small_tol,
22  double large_tol, double increment,
23  std::ostream &print_stream) {
24  std::vector<double> tols;
25  std::vector<bool> is_group;
26  std::vector<int> num_ops, num_enforced_ops;
27  std::vector<std::string> name;
28 
29  xtal::Lattice lattice = struc.lattice();
30 
31  double orig_tol = lattice.tol();
32  for (double i = small_tol; i < large_tol; i += increment) {
33  tols.push_back(i);
34  lattice.set_tol(i);
35 
36  xtal::SymOpVector factor_group_operations =
39  adapter::Adapter<SymGroup, xtal::SymOpVector>()(factor_group_operations,
40  lattice);
41 
42  factor_group.get_multi_table();
43  num_ops.push_back(factor_group.size());
44  is_group.push_back(factor_group.is_group(i));
45  factor_group.enforce_group(i);
46  num_enforced_ops.push_back(factor_group.size());
47  name.push_back(factor_group.get_name());
48  }
49  lattice.set_tol(orig_tol);
50 
51  for (Index i = 0; i < tols.size(); i++) {
52  print_stream << tols[i] << "\t" << num_ops[i] << "\t" << is_group[i] << "\t"
53  << num_enforced_ops[i] << "\t name: " << name[i] << "\n";
54  }
55 
56  return;
57 }
58 
61  double enforced_tol) {
62  // symmetrized lattice has tolerance set to "enforced_tol"
63  Lattice symmetrized_lattice{
64  xtal::symmetrize(basic_structure.lattice(), enforced_tol)
65  .lat_column_mat(),
66  enforced_tol};
67  basic_structure.set_lattice(symmetrized_lattice, FRAC);
68 
69  Structure structure{basic_structure};
70  return structure.factor_group();
71 }
72 
94 void symmetrize_v1(fs::path poscar_path, double tol) {
95  Log &log = CASM::log();
96  // fs::path poscar_path = opt().poscar_path();
97  // double tol = opt().tol();
98  log << "\n***************************\n" << std::endl;
99  log << "Symmetrizing: " << poscar_path << std::endl;
100  log << "with tolerance: " << tol << std::endl;
101  Structure struc(poscar_path);
102  struc = Structure(xtal::make_primitive(struc));
103 
104  int biggest = struc.factor_group().size();
105  xtal::BasicStructure basic_tmp = struc;
106  // a) symmetrize the lattice vectors
107  Lattice lat = basic_tmp.lattice();
108  lat = xtal::symmetrize(lat, tol);
109  lat.set_tol(tol);
110  basic_tmp.set_lattice(lat, FRAC);
111 
112  Structure tmp(basic_tmp);
113 
114  tmp.factor_group();
115  // b) find factor group with same tolerance
117  tmp, tmp.structure().lattice().tol(), tol,
118  (tol - tmp.structure().lattice().tol()) / 10.0, log);
119  // c) symmetrize the basis sites
120  SymGroup g = tmp.factor_group();
121  tmp = xtal::symmetrize(tmp, g);
122 
123  // TODO: Why are we doing this twice?
124  g = tmp.factor_group();
125  tmp = xtal::symmetrize(tmp, g);
126  if (tmp.factor_group().is_group(tol) &&
127  (tmp.factor_group().size() > biggest)) {
128  struc = tmp;
129  }
130  struc = Structure(xtal::make_primitive(struc));
131  fs::ofstream file_i;
132  fs::path POSCARpath_i = "POSCAR_sym";
133  file_i.open(POSCARpath_i);
135  struc.structure().title());
136  p_i.print(file_i);
137  file_i.close();
138 }
139 
169 void symmetrize_v2(fs::path input_poscar_location,
170  fs::path output_poscar_location, double enforced_tol,
171  double input_tol) {
172  Log &log = CASM::log();
173 
174  log << "\n***************************\n" << std::endl;
175  log << "Symmetrizing: " << input_poscar_location << std::endl;
176  log << "with tolerance: " << enforced_tol << std::endl;
177 
178  // read input POSCAR
179  fs::ifstream infile{input_poscar_location};
180  Structure input_structure{
181  xtal::BasicStructure::from_poscar_stream(infile, input_tol)};
182 
183  // make primitive if necessary
184  bool input_structure_is_primitive = xtal::is_primitive(input_structure);
185  if (!input_structure_is_primitive) {
186  log << "The input structure is not primitive." << std::endl;
187  log << "The primitive structure will be generated and symmetrized."
188  << std::endl;
189  input_structure = Structure{xtal::make_primitive(input_structure)};
190  }
191 
192  // original method always printed a result, but only prints the resulting
193  // symmetrized structure (called "test_structure" here) if its factor group is
194  // valid and has higher symmetry than the original input structure
195 
196  // make the factor group to be enforced (this also symmetrizes the lattice),
197  // and symmetrize
199  input_structure, enforced_tol);
200  Structure test_structure =
201  xtal::symmetrize(input_structure, enforced_factor_group);
202 
203  // check factor group of the result and compare to original
204  bool test_factor_group_valid =
205  test_structure.factor_group().is_group(enforced_tol);
206  Index test_factor_group_size = test_structure.factor_group().size();
207  Index input_factor_group_size = input_structure.factor_group().size();
208 
209  log << "Factor group size of input structure: " << input_factor_group_size
210  << std::endl;
211  log << "Factor group size with enforced tolerance: " << test_factor_group_size
212  << std::endl;
213 
214  // Set to point to the structure that should be printed
215  Structure const *output_structure = nullptr;
216  if (test_factor_group_valid &&
217  (test_factor_group_size > input_factor_group_size)) {
218  log << "Writing symmetrized structure: " << output_poscar_location
219  << std::endl;
220  output_structure = &test_structure;
221  } else {
222  log << "Higher symmetry not found the specified tolerance." << std::endl;
223  if (input_structure_is_primitive) {
224  log << "Writing input structure, unchanged: " << output_poscar_location
225  << std::endl;
226  } else {
227  log << "Writing primitive of input structure: " << output_poscar_location
228  << std::endl;
229  }
230  output_structure = &input_structure;
231  }
232 
233  // Print result
234  VaspIO::PrintPOSCAR printer{xtal::make_simple_structure(*output_structure),
235  input_structure.structure().title()};
236 
237  fs::ofstream file{output_poscar_location};
238  printer.print(file);
239 }
240 } // namespace symmetrize_impl
241 
242 namespace CASM {
243 
245 std::string symmetrize_desc() {
246  std::string description =
247 
248  "Symmetrize a POSCAR (--symmetrize POSCAR_LOCATION --tol ENFORCED_TOL): "
249  "\n\n"
250 
251  " The --symmetrize option implements a method to adjust a structure's "
252  "lattice \n"
253  " and basis to increase factor group symmetry. "
254  " \n\n"
255 
256  " Method: \n"
257  " - Read a VASP POSCAR file from POSCAR_LOCATION and, if not primitive, "
258  "make \n"
259  " its primitive structure. "
260  " \n"
261  " - Construct a symmetrized lattice such that the point group of the "
262  "lattice \n"
263  " is equal to that of the input structure's lattice when using "
264  "ENFORCED_TOL \n"
265  " to check for lattice equivalence. The symmetrized lattice vectors "
266  "are \n"
267  " obtaining through a process of applying operations in the enforced "
268  "point \n"
269  " group, averaging, and then rotating to match the original lattice "
270  " \n"
271  " orientation. "
272  " \n"
273  " - Construct a symmetrized structure with factor group equal to that "
274  " \n"
275  " generated for the input structure when using ENFORCED_TOL to check "
276  "for \n"
277  " structure equivalence. The symmetrized structure's basis is "
278  "constructed \n"
279  " by setting basis site coordinates equal to the average coordinate "
280  " \n"
281  " positions found after applying each operation in the enforced "
282  "factor group\n"
283  " to the original basis sites. "
284  " \n"
285  " - Write the symmetrized structure to \"POSCAR_sym\". "
286  " \n\n\n";
287 
288  return description;
289 }
290 
292 void symmetrize(PrimClex &primclex, jsonParser const &json_options,
293  jsonParser const &cli_options_as_json) {
294  Log &log = CASM::log();
295 
296  std::map<std::string, std::string> cli_to_combined_keys{
297  {"tol", "tol"}, // --tol
298  {"symmetrize", "symmetrize"} // --symmetrize
299  };
300 
301  jsonParser json_combined{json_options};
302  combine_json_options(cli_to_combined_keys, cli_options_as_json,
303  json_combined);
304  ParentInputParser parser{json_combined};
305 
306  std::string poscar_path;
307  parser.require(poscar_path, "symmetrize");
308 
309  double enforced_tol;
310  parser.require(enforced_tol, "tol");
311 
312  std::runtime_error error_if_invalid{
313  "Error reading `casm sym --symmetrize` input"};
314  report_and_throw_if_invalid(parser, log, error_if_invalid);
315 
316  symmetrize_impl::symmetrize_v1(poscar_path, enforced_tol);
317 
318  // TODO: check equivalence of v1 and v2
319  // symmetrize_impl::symmetrize_v2(poscar_path,
320  // "POSCAR_sym",
321  // enforced tol,
322  // TOL);
323 }
324 
325 } // namespace CASM
std::unique_ptr< RequiredType > require(fs::path option, Args &&... args)
Definition: Log.hh:48
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
Structure specifies the lattice and atomic basis of a crystal.
Definition: Structure.hh:30
const xtal::BasicStructure & structure() const
Definition: Structure.hh:92
const Lattice & lattice() const
Definition: Structure.hh:100
const MasterSymGroup & factor_group() const
Definition: Structure.cc:107
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
bool is_group(double tol=TOL) const
Check to see if SymGroup satisfies the group property.
Definition: SymGroup.cc:1805
Print POSCAR with formating options.
Definition: VaspIO.hh:40
void print(std::ostream &sout) const
Print POSCAR to stream.
Definition: VaspIO.cc:56
BasicStructure specifies the lattice and atomic basis of a crystal.
void set_lattice(const Lattice &lattice, COORD_TYPE mode)
static BasicStructure from_poscar_stream(std::istream &poscar_stream, double tol=TOL)
const std::string & title() const
const Lattice & lattice() const
void set_tol(double _tol)
Definition: Lattice.hh:197
double tol() const
Definition: Lattice.hh:195
GenericDatumFormatter< std::string, ConfigEnumDataType > name()
ConfigIO::GenericConfigFormatter< jsonParser > structure()
Definition: ConfigIO.cc:766
ConfigIO::GenericConfigFormatter< bool > is_primitive()
Definition: ConfigIO.cc:707
GenericVectorXdScelFormatter lattice()
Definition: SupercellIO.cc:266
SharedPrimFormatter< jsonParser > factor_group()
std::vector< SymOp > make_factor_group(const BasicStructure &struc, double tol=TOL)
BasicStructure make_primitive(const BasicStructure &non_primitive_struc, double tol=TOL)
Returns the smallest possible tiling unit of the given structure.
std::vector< SymOp > SymOpVector
Main CASM namespace.
Definition: APICommand.hh:8
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.
std::string description(const SymOp &op, const xtal::Lattice &lat, SymInfoOptions opt=SymInfoOptions())
Print SymInfo to string.
Log & log()
Definition: Log.hh:424
const COORD_TYPE FRAC
Definition: enum.hh:8
jsonParser & combine_json_options(std::map< std::string, std::string > const &source_to_combined_keys, jsonParser const &json_source, jsonParser &json_combined)
Copy from json_source to json_combined
Definition: json_io.cc:8
std::string symmetrize_desc()
Describe the symmetrize method.
Definition: symmetrize.cc:245
void report_and_throw_if_invalid(KwargsParser const &parser, Log &log, ErrorType error)
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
void symmetrize(PrimClex &primclex, jsonParser const &json_options, jsonParser const &cli_options_as_json)
Adjust a structure's lattice and basis to increase factor group symmetry.
Definition: symmetrize.cc:292
void _print_factor_group_convergence(const Structure &struc, double small_tol, double large_tol, double increment, std::ostream &print_stream)
Definition: symmetrize.cc:21
void symmetrize_v1(fs::path poscar_path, double tol)
Definition: symmetrize.cc:94
SymGroup make_enforced_factor_group(xtal::BasicStructure basic_structure, double enforced_tol)
Return SymGroup calculated for basic_structure with specified tolerance.
Definition: symmetrize.cc:60
void symmetrize_v2(fs::path input_poscar_location, fs::path output_poscar_location, double enforced_tol, double input_tol)
Definition: symmetrize.cc:169
PrimClex * primclex
Definition: settings.cc:135
Log & log
Definition: settings.cc:139