CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
AppIO.cc
Go to the documentation of this file.
1 #include "casm/app/AppIO.hh"
5 
6 namespace CASM {
7 
8 
9  // --------- PrimIO Definitions --------------------------------------------------
10 
12 
13  try {
14  jsonParser json(filename);
15  return read_prim(json);
16  }
17  catch(...) {
18  std::cerr << "Error reading prim from " << filename << std::endl;
20  throw;
21  }
22  }
23 
26 
27  try {
28 
29  // read lattice
30  Eigen::Matrix3d latvec_transpose;
31 
32  from_json(latvec_transpose, json["lattice_vectors"]);
33 
34  Lattice lat(latvec_transpose.transpose());
35 
36  // create prim using lat
37  BasicStructure<Site> prim(lat);
38 
39  // read title
40  from_json(prim.title, json["title"]);
41 
42  Eigen::Vector3d vec;
43 
44  // read basis coordinate mode
45  std::string coordinate_mode;
46  from_json(coordinate_mode, json["coordinate_mode"]);
47  COORD_TYPE mode;
48  if(coordinate_mode == "Fractional") {
49  mode = FRAC;
50  }
51  else if(coordinate_mode == "Direct") {
52  mode = FRAC;
53  }
54  else if(coordinate_mode == "Cartesian") {
55  mode = CART;
56  }
57  else {
58  throw std::runtime_error(
59  std::string(" Invalid: \"coordinate_mode\"\n") +
60  " Expected one of \"Fractional\", \"Direct\", or \"Cartesian\"");
61  }
62 
63  // read basis sites
64  for(int i = 0; i < json["basis"].size(); i++) {
65 
66  // read coordinate
67  Eigen::Vector3d coord(json["basis"][i]["coordinate"][0].get<double>(),
68  json["basis"][i]["coordinate"][1].get<double>(),
69  json["basis"][i]["coordinate"][2].get<double>());
70  Site site(prim.lattice());
71  if(mode == FRAC) {
72  site.frac() = coord;
73  }
74  else if(mode == CART) {
75  site.cart() = coord;
76  }
77 
78  // read atom occupant names
79  Array<std::string> occ_name;
80  from_json(occ_name, json["basis"][i]["occupant_dof"]);
81 
82  // fill site.site_occupant
83  Array<Molecule> tocc;
84  for(int i = 0; i < occ_name.size(); i++) {
85  Molecule tMol(prim.lattice());
86  tMol.name = occ_name[i];
87  tMol.push_back(AtomPosition(0, 0, 0, occ_name[i], prim.lattice(), CART));
88  tocc.push_back(tMol);
89  }
90  site.set_site_occupant(MoleculeOccupant(tocc));
91  site.set_occ_value(0);
92 
93  // add site to prim
94  prim.basis.push_back(site);
95  }
96 
97  return prim;
98  }
99  catch(...) {
101  throw;
102  }
103 
104  }
105 
107  void write_prim(const BasicStructure<Site> &prim, fs::path filename, COORD_TYPE mode) {
108 
109  SafeOfstream outfile;
110  outfile.open(filename);
111 
112  jsonParser json;
113  write_prim(prim, json, mode);
114  json.print(outfile.ofstream());
115 
116  outfile.close();
117  }
118 
120  void write_prim(const BasicStructure<Site> &prim, jsonParser &json, COORD_TYPE mode) {
121 
122  json = jsonParser::object();
123 
124  json["title"] = prim.title;
125 
126  json["lattice_vectors"] = prim.lattice().lat_column_mat().transpose();
127 
128  if(mode == COORD_DEFAULT) {
129  mode = COORD_MODE::CHECK();
130  }
131 
132  if(mode == FRAC) {
133  json["coordinate_mode"] = "Fractional";
134  }
135  else if(mode == CART) {
136  json["coordinate_mode"] = "Cartesian";
137  }
138 
139  json["basis"] = jsonParser::array(prim.basis.size());
140  for(int i = 0; i < prim.basis.size(); i++) {
141  json["basis"][i] = jsonParser::object();
142  json["basis"][i]["coordinate"].put_array();
143  if(mode == FRAC) {
144  json["basis"][i]["coordinate"].push_back(prim.basis[i].frac(0));
145  json["basis"][i]["coordinate"].push_back(prim.basis[i].frac(1));
146  json["basis"][i]["coordinate"].push_back(prim.basis[i].frac(2));
147  }
148  else if(mode == CART) {
149  json["basis"][i]["coordinate"].push_back(prim.basis[i].cart(0));
150  json["basis"][i]["coordinate"].push_back(prim.basis[i].cart(1));
151  json["basis"][i]["coordinate"].push_back(prim.basis[i].cart(2));
152  }
153 
154  json["basis"][i]["occupant_dof"] = jsonParser::array(prim.basis[i].site_occupant().size());
155 
156  for(int j = 0; j < prim.basis[i].site_occupant().size(); j++) {
157  json["basis"][i]["occupant_dof"][j] = prim.basis[i].site_occupant()[j].name;
158  }
159 
160  }
161  }
162 
163 
164  // --------- SymmetryIO Declarations --------------------------------------------------
165 
166  void write_symop(const SymGroup &grp, Index i, jsonParser &j) {
167  j = jsonParser::object();
168 
169  const SymOp &op = grp[i];
170 
171  to_json(op.matrix(), j["matrix"]["CART"]);
172  to_json(grp.lattice().inv_lat_column_mat()*op.matrix()*grp.lattice().lat_column_mat(), j["matrix"]["FRAC"]);
173 
174  to_json_array(op.tau(), j["tau"]["CART"]);
175  to_json_array(grp.lattice().inv_lat_column_mat()*op.tau(), j["tau"]["FRAC"]);
176 
177  to_json(grp.class_of_op(i), j["conjugacy_class"]);
178  to_json(grp.ind_inverse(i), j["inverse"]);
179 
180  add_sym_info(grp.info(i), j);
181  }
182 
183  void write_symgroup(const SymGroup &grp, jsonParser &json) {
184  json = jsonParser::object();
185 
186  json["symop"] = jsonParser::array(grp.size());
187  for(int i = 0; i < grp.size(); i++) {
188  write_symop(grp, i, json["symop"][i]);
189  }
190 
191  json["name"] = grp.get_name();
192  json["latex_name"] = grp.get_latex_name();
193  json["periodicity"] = grp.periodicity();
194  if(grp.periodicity() == PERIODIC) {
195  json["possible_space_groups"] = grp.possible_space_groups();
196  }
197  json["conjugacy_class"] = grp.get_conjugacy_classes();
198  json["inverse"] = jsonParser::array(grp.size());
199  for(int i = 0; i < grp.size(); i++) {
200  json["inverse"][i] = grp.ind_inverse(i);
201  }
202  json["multiplication_table"] = grp.get_multi_table();
203  json["character_table"] = grp.character_table();
204  }
205 
206 
207  // --------- ChemicalReference IO Definitions --------------------------------------------------
208 
213  const Structure &prim,
214  double tol) {
215  try {
216  jsonParser json(filename);
217  return read_chemical_reference(json, prim, tol);
218  }
219  catch(...) {
220  std::cerr << "Error reading chemical reference states from " << filename << std::endl;
222  throw;
223  }
224  }
225 
247  const Structure &prim,
248  double tol) {
249 
250  if(json.find("chemical_reference") == json.end()) {
251  throw std::runtime_error("Error reading chemical reference states: Expected \"chemical_reference\" entry");
252  }
253 
254  return jsonConstructor<ChemicalReference>::from_json(json["chemical_reference"], prim, tol);
255 
256  }
257 
258  void write_chemical_reference(const ChemicalReference &chem_ref, fs::path filename) {
259  SafeOfstream outfile;
260  outfile.open(filename);
261 
262  jsonParser json;
263  write_chemical_reference(chem_ref, json);
264  json.print(outfile.ofstream());
265 
266  outfile.close();
267  }
268 
270  json.put_obj();
271  to_json(chem_ref, json["chemical_reference"]);
272  }
273 
274 
275  // --------- CompositionAxes Definitions --------------------------------------------------
276 
282  read(_filename);
283  }
284 
290  read(json);
291  }
292 
293  void CompositionAxes::read(fs::path _filename) {
294 
295  try {
296 
297  read(jsonParser(_filename), _filename);
298 
299  }
300  catch(...) {
301 
302  std::cerr << "Error reading composition axes from " << _filename << std::endl;
303  throw;
304  }
305  }
306 
307  void CompositionAxes::read(const jsonParser &json, fs::path _filename) {
308 
309  try {
310 
311  *this = CompositionAxes();
312 
313  filename = _filename;
314 
315  filename = _filename;
316 
317  if(json.contains("standard_axes")) {
318  read_composition_axes(std::inserter(standard, standard.begin()), json["standard_axes"]);
319  }
320 
321  if(json.contains("custom_axes")) {
322  read_composition_axes(std::inserter(custom, custom.begin()), json["custom_axes"]);
323  }
324 
325  std::string key;
326  has_current_axes = json.get_if(key, "current_axes");
327 
328  if(has_current_axes) {
329  select(key);
330  }
331 
332  }
333  catch(...) {
334  throw;
335  }
336  }
337 
340 
341  filename = _filename;
342  SafeOfstream outfile;
343  outfile.open(filename);
344  jsonParser json;
345  write(json);
346  json.print(outfile.ofstream());
347  outfile.close();
348  }
349 
351  void CompositionAxes::write(jsonParser &json) const {
352 
353  json = jsonParser::object();
354 
355  json["standard_axes"][standard.cbegin()->first] = true;
356 
357  for(auto it = standard.cbegin(); it != standard.cend(); ++it) {
358  json["standard_axes"][it->first] = it->second;
359  }
360 
361  for(auto it = custom.cbegin(); it != custom.cend(); ++it) {
362  json["custom_axes"][it->first] = it->second;
363  }
364 
365  if(has_current_axes) {
366  json["current_axes"] = curr_key;
367  }
368 
369  }
370 
372  void CompositionAxes::select(std::string key) {
373  if(standard.find(key) != standard.cend() &&
374  custom.find(key) != custom.cend()) {
375 
376  std::stringstream ss;
377  ss << "Error: The composition axes " << key <<
378  " can found in both the standard and custom compostion axes.\n\n" <<
379  "Please edit the custom composition axes to remove this ambiguity.";
380 
381  err_message = ss.str();
382 
383  err_code = 1;
384 
385  }
386  else if(standard.find(key) == standard.cend() &&
387  custom.find(key) == custom.cend()) {
388 
389  std::stringstream ss;
390  ss << "Warning: The composition axes " << key <<
391  " can not be found in the standard or custom compostion axes.\n\n" <<
392  "Please use 'casm composition --select' to re-select your composition axes,\n" <<
393  "Please use 'casm composition --calc' to re-calc your standard axes,\n" <<
394  "or edit the custom composition axes.";
395 
396  err_message = ss.str();
397 
398  err_code = 2;
399  }
400  else if(standard.find(key) != standard.cend()) {
401  curr = standard[key];
402  }
403  else if(custom.find(key) != custom.cend()) {
404  curr = custom[key];
405  }
406  curr_key = key;
407  has_current_axes = true;
408 
409  }
410 
411  // ---------- prim_nlist.json IO -------------------------------------------------------------
412 
413  void write_prim_nlist(const Array<UnitCellCoord> &prim_nlist, const fs::path &nlistpath) {
414 
415  SafeOfstream outfile;
416  outfile.open(nlistpath);
417  jsonParser nlist_json;
418  nlist_json = prim_nlist;
419  nlist_json.print(outfile.ofstream());
420  outfile.close();
421 
422  return;
423  }
424 
426 
427  try {
428  Array<UnitCellCoord> prim_nlist;
429  jsonParser read_json(nlistpath);
430  from_json(prim_nlist, read_json);
431  return prim_nlist;
432  }
433  catch(...) {
434  std::cerr << "Error reading: " << nlistpath;
435  throw;
436  }
437  }
438 
439 
440  // ---------- basis.json IO ------------------------------------------------------------------
441 
474  void write_basis(const SiteOrbitree &tree, const Structure &prim, jsonParser &json, double tol) {
475 
476  json = jsonParser::object();
477 
478  // "site_functions":[
479  // {
480  // "asym_unit": X,
481  // "sublat": [2, 3],
482  // "basis": {
483  // "phi_b_0": {"Va":0.0, "O":1.0},
484  // "phi_b_1": {"Va":0.0, "O":1.0}
485  // }
486  // },
487  // ...
488  // ],
489 
490  jsonParser &sitef = json["site_functions"];
491  sitef = jsonParser::array(prim.basis.size(), jsonParser::object());
492  for(Index no = 0; no < tree.asym_unit().size(); no++) {
493  for(Index ne = 0; ne < tree.asym_unit()[no].size(); ne++) {
494 
495  const SiteCluster &equiv = tree.asym_unit()[no][ne];
496  const Site &site = equiv[0];
497 
498  Index b = site.basis_ind();
499  sitef[b]["sublat"] = b;
500  sitef[b]["asym_unit"] = no;
501 
502  if(equiv.clust_basis.size() == 0) {
503  sitef[b]["basis"].put_null();
504  }
505  else {
506  for(Index f = 0; f < equiv.clust_basis.size(); f++) {
507  std::stringstream fname;
508  fname << "\\phi_" << b << '_' << f;
509  for(Index s = 0; s < site.site_occupant().size(); s++) {
510 
511  // "\phi_b_f": {"Zr":0.0, ...}
512  sitef[b]["basis"][fname.str()][site.site_occupant()[s].name] =
513  equiv.clust_basis[f]->eval(
514  Array<Index>(1, site.site_occupant().ID()),
515  Array<Index>(1, s)
516  );
517  }
518  }
519  }
520  }
521  }
522 
523  // "cluster_functions":[
524  // {
525  // ("eci": X.XXXXX,) <-- is included after fitting
526  // "prototype_function": "\phi_b_i(s_j)...",
527  // "orbit": [branch_index, cluster_orbit_index, bfunc_index],
528  // "linear_orbit_index": I,
529  // "mult": X,
530  // "prototype": {
531  // "max_length": X.X,
532  // "min_length": X.X,
533  // "sites": [
534  // [b, i, j, k],
535  // ...
536  // ]
537  // }
538  // },
539  // ...
540  // ]
541  // }
542 
543  jsonParser &orbitf = json["cluster_functions"];
544  orbitf = jsonParser::array();
545  for(Index i = 0; i < tree.size(); i++) {
546  jsonParser tjson;
547  for(Index j = 0; j < tree.size(i); j++) { //Loops over all i sized Orbits of clusters
548 
549  // cluster specific info
550  tjson["orbit"] = std::vector<Index>({i, j, 0});
551  tjson["mult"] = tree.orbit(i, j).size();
552  to_json(jsonHelper(tree.orbit(i, j)[0], prim), tjson["prototype"]);
553 
554  // basis function info
555  BasisSet tbasis(tree.orbit(i, j)[0].clust_basis);
556  tbasis.accept(OccFuncLabeler("\\phi_%b_%f(s_%n)"));
557 
558  for(Index nf = 0; nf < tbasis.size(); ++nf) {
559  tjson["orbit"][2] = nf;
560  tjson["prototype_function"] = tbasis[nf]->tex_formula();
561  orbitf.push_back(tjson);
562  }
563  }
564  }
565 
566  for(Index i = 0; i < orbitf.size(); ++i) {
567  orbitf[i]["linear_function_index"] = i;
568  }
569  }
570 
571 }
572 
size_type size() const
Returns array size if *this is a JSON array, object size if *this is a JSON object, 1 otherwise.
Definition: jsonParser.cc:430
void close()
Closes stream, and if not a failed write, removes "file" and renames "file.tmp" to "file"...
Definition: SafeOfstream.hh:81
CompositionConverter curr
Definition: AppIO.hh:95
SymInfo info(Index i) const
Definition: SymGroup.cc:927
ClustJsonHelper< ValueType > jsonHelper(ValueType &_value, const Structure &_struc, double tol=TOL)
Definition: jsonClust.hh:62
Index ID() const
Definition: DoF.hh:71
std::map< std::string, CompositionConverter > standard
Definition: AppIO.hh:91
void from_json(ClexDescription &desc, const jsonParser &json)
iterator end()
Returns iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:465
Index size() const
Definition: Array.hh:145
bool get_if(T &t, const std::string &key, Args...args) const
Definition: jsonParser.hh:740
void push_back(const T &toPush)
Definition: Array.hh:513
Structure specifies the lattice and atomic basis of a crystal.
Definition: Structure.hh:29
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
void select(std::string key)
Set this->curr using key.
Definition: AppIO.cc:372
void write_symgroup(const SymGroup &grp, jsonParser &json)
Definition: AppIO.cc:183
const MoleculeOccupant & site_occupant() const
Definition: Site.hh:24
OccupantDoF< Molecule > MoleculeOccupant
Definition: Molecule.hh:22
void write_prim(const BasicStructure< Site > &prim, fs::path filename, COORD_TYPE mode)
Write prim.json to file.
Definition: AppIO.cc:107
void write_chemical_reference(const ChemicalReference &chem_ref, fs::path filename)
Definition: AppIO.cc:258
Main CASM namespace.
Definition: complete.cpp:8
Write to a temporary file to ensure a good write, then rename.
Definition: SafeOfstream.hh:28
const Lattice & lattice() const
fs::ofstream & ofstream()
Access underlying stream.
Definition: SafeOfstream.hh:76
std::string curr_key
Definition: AppIO.hh:94
const Eigen::Matrix3d & lat_column_mat() const
3x3 matrix with lattice vectors as its columne
Definition: Lattice.hh:104
Index ind_inverse(Index i) const
Get index of operation that is inverse of operation at(i)
Definition: SymGroup.cc:3046
const Array< Index >::X2 & get_multi_table() const
Definition: SymGroup.cc:3170
BasicStructure< Site > read_prim(fs::path filename)
Definition: AppIO.cc:11
void print(std::ostream &stream, unsigned int indent=2, unsigned int prec=12) const
Print json to stream.
Definition: jsonParser.cc:185
void open(fs::path name, std::string tmp_ext="tmp")
Opens "file.tmp" for writing, with intended final target "file".
Definition: SafeOfstream.hh:62
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:33
double tol
jsonParser & put_null()
Puts 'null' JSON value.
Definition: jsonParser.hh:305
const matrix_type & matrix() const
Const access of entire cartesian symmetry matrix.
Definition: SymOp.hh:57
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...
Definition: Lattice.hh:113
SymOp is the Coordinate representation of a symmetry operation it keeps fraction (FRAC) and Cartesian...
Definition: SymOp.hh:28
void read(fs::path _filename)
Read CompositionAxes from file.
Definition: AppIO.cc:293
EigenIndex Index
For long integer indexing:
bool accept(const FunctionVisitor &visitor)
Definition: BasisSet.cc:202
const Array< std::complex< double > >::X2 & character_table() const
Definition: SymGroup.cc:3212
void add_sym_info(const SymInfo &info, jsonParser &j)
Add to existing JSON object.
Array< CoordType > basis
Lattice vectors that specifies periodicity of the crystal.
Index size() const override
Definition: DoF.hh:297
std::string title
User-specified name of this Structure.
ChemicalReference read_chemical_reference(fs::path filename, const Structure &prim, double tol)
Read chemical reference states from JSON file.
Definition: AppIO.cc:212
OutputIterator read_composition_axes(OutputIterator result, const jsonParser &json)
Read standard axes from JSON, and output to std::map ...
Definition: AppIO.hh:121
const Array< Index >::X2 & get_conjugacy_classes() const
Definition: SymGroup.cc:3197
static ReturnType from_json(const jsonParser &json)
Default from_json is equivalent to.
Definition: jsonParser.hh:489
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.
Definition: container.hh:191
const Lattice & lattice() const
Definition: SymGroup.cc:940
PERIODICITY_TYPE periodicity() const
Definition: SymGroup.hh:160
iterator find(const std::string &name)
Return iterator to JSON object value with 'name'.
Definition: jsonParser.cc:490
BasisSet clust_basis
Definition: SiteCluster.hh:22
Eigen::Matrix3d Matrix3d
void write_symop(const SymGroup &grp, Index i, jsonParser &j)
Definition: AppIO.cc:166
jsonParser & put_obj()
Puts new empty JSON object.
Definition: jsonParser.hh:276
Index basis_ind() const
Access basis Index.
Definition: Coordinate.hh:190
std::string possible_space_groups() const
Definition: SymGroup.hh:164
void write_basis(const SiteOrbitree &tree, const Structure &prim, jsonParser &json, double tol)
Write summary of basis functions.
Definition: AppIO.cc:474
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...
Definition: jsonParser.hh:696
bool contains(const std::string &name) const
Return true if JSON object contains 'name'.
Definition: jsonParser.cc:500
Coordinate_impl::FracCoordinate frac()
Set the fractional coordinate vector.
Definition: Coordinate.hh:581
const vector_type & tau() const
Const access of the cartesian translation vector, 'tau'.
Definition: SymOp.hh:63
const std::string & get_latex_name() const
Definition: SymGroup.cc:3236
GenericOrbit< ClustType > & orbit(Index np, Index no)
Access orbits using 2-D indexing.
void write(fs::path _filename)
Write CompositionAxes to file.
Definition: AppIO.cc:339
fs::path filename
Definition: AppIO.hh:96
Index class_of_op(Index i) const
Get conjugacy class index of operation at(i)
Definition: SymGroup.cc:3071
Array< UnitCellCoord > read_prim_nlist(const fs::path &nlistpath)
Definition: AppIO.cc:425
const std::string & get_name() const
Definition: SymGroup.cc:3220
std::string name
Definition: Molecule.hh:112
std::map< std::string, CompositionConverter > custom
Definition: AppIO.hh:92
static jsonParser object()
Returns an empty json object.
Definition: jsonParser.hh:329
void write_prim_nlist(const Array< UnitCellCoord > &prim_nlist, const fs::path &nlistpath)
Definition: AppIO.cc:413
std::string err_message
Definition: AppIO.hh:99
jsonParser & put_array()
Puts new empty JSON array.
Definition: jsonParser.hh:285
static jsonParser array()
Returns an empty json array.
Definition: jsonParser.hh:342
const GenericOrbitBranch< ClustType > & asym_unit() const
Definition: Orbitree.hh:227
Index size(Index np) const
Number of orbits in OrbitBranch 'np'.
static COORD_TYPE CHECK()
get the current mode (call using COORD_MODE::CHECK())