CASM  1.1.0
A Clusters Approach to Statistical Mechanics
DoFSpace.cc
Go to the documentation of this file.
2 
7 #include "casm/clex/Supercell.hh"
18 
19 namespace CASM {
20 
21 namespace { // implementation for to_json(DoFSpace const &dofspace, ...)
22 
25 void _add_homogeneous_mode_info(jsonParser &json, DoFSpace const &dofspace) {
26  jsonParser &irreps_json = json["irreducible_representations"];
27 
28  Eigen::MatrixXd homogeneous_mode_space =
30 
31  auto print_string = [&](std::vector<Index> const &indices) {
32  std::vector<std::string> string_of_indices;
33  for (auto &i : indices) {
34  std::string s = "q" + to_sequential_string(i + 1, dofspace.dim());
35  string_of_indices.push_back(s);
36  }
37  return string_of_indices;
38  };
39 
40  VectorSpaceMixingInfo mixing_info(dofspace.basis(), homogeneous_mode_space,
41  CASM::TOL);
42  irreps_json["adapted_axes_which_are_not_homogeneous_modes"] =
43  print_string(mixing_info.axes_not_in_subspace);
44  irreps_json["adapted_axes_mixed_with_homogeneous_modes"] =
45  print_string(mixing_info.axes_mixed_with_subspace);
46  irreps_json["adapted_axes_which_are_homogeneous_modes"] =
47  print_string(mixing_info.axes_in_subspace);
48 }
49 } // namespace
50 
51 void from_json(DoFSpace &dofspace, jsonParser const &json,
52  std::shared_ptr<Structure const> const &shared_prim) {
54 }
55 
56 jsonParser &to_json(DoFSpace const &dofspace, jsonParser &json,
57  std::optional<std::string> const &identifier,
58  std::optional<ConfigEnumInput> const &input_state,
59  std::optional<VectorSpaceSymReport> const &sym_report) {
60  json["dof"] = dofspace.dof_key();
61  json["transformation_matrix_to_supercell"] =
63  json["sites"] = dofspace.sites();
64  json["basis"] = dofspace.basis().transpose();
65  json["glossary"] = dofspace.axis_glossary();
66  json["axis_site_index"] = dofspace.axis_site_index();
67  json["axis_dof_component"] = dofspace.axis_dof_component();
68 
69  if (identifier.has_value()) {
70  json["identifier"] = identifier;
71  }
72  if (input_state.has_value()) {
73  json["state"] = input_state;
74  }
75  if (sym_report.has_value()) {
76  to_json(sym_report, json);
77  if (dofspace.includes_all_sites() && dofspace.dof_key() == "disp") {
78  _add_homogeneous_mode_info(json, dofspace);
79  }
80  }
81  return json;
82 }
83 
85  DoFSpace const &dofspace, jsonParser &json,
86  std::optional<std::string> const &identifier,
87  std::optional<ConfigEnumInput> const &input_state,
88  std::optional<SymRepTools_v2::VectorSpaceSymReport> const &sym_report) {
89  json["dof"] = dofspace.dof_key();
90  json["transformation_matrix_to_supercell"] =
92  json["sites"] = dofspace.sites();
93  json["basis"] = dofspace.basis().transpose();
94  json["glossary"] = dofspace.axis_glossary();
95  json["axis_site_index"] = dofspace.axis_site_index();
96  json["axis_dof_component"] = dofspace.axis_dof_component();
97 
98  if (identifier.has_value()) {
99  json["identifier"] = identifier;
100  }
101  if (input_state.has_value()) {
102  json["state"] = input_state;
103  }
104  if (sym_report.has_value()) {
105  to_json(sym_report, json);
106  if (dofspace.includes_all_sites() && dofspace.dof_key() == "disp") {
107  _add_homogeneous_mode_info(json, dofspace);
108  }
109  }
110  return json;
111 }
112 
114  jsonParser const &json,
115  std::shared_ptr<Structure const> const &shared_prim) {
116  InputParser<DoFSpace> parser{json, shared_prim};
117 
118  std::runtime_error error_if_invalid{"Error reading DoFSpace from JSON"};
119  report_and_throw_if_invalid(parser, CASM::log(), error_if_invalid);
120 
121  return std::move(*parser.value);
122 }
123 
124 std::unique_ptr<DoFSpace> jsonMake<DoFSpace>::make_from_json(
125  jsonParser const &json,
126  std::shared_ptr<Structure const> const &shared_prim) {
127  InputParser<DoFSpace> parser{json, shared_prim};
128 
129  std::runtime_error error_if_invalid{"Error reading DoFSpace from JSON"};
130  report_and_throw_if_invalid(parser, CASM::log(), error_if_invalid);
131 
132  return std::move(parser.value);
133 }
134 
136  std::shared_ptr<Structure const> const &shared_prim) {
137  DoFKey dof_key;
138  parser.require(dof_key, "dof");
139 
140  std::optional<Eigen::Matrix3l> transformation_matrix_to_super;
142  "transformation_matrix_to_supercell");
143 
144  std::optional<std::set<Index>> sites;
145  parser.optional(sites, "sites");
146 
147  Eigen::MatrixXd tmp;
148  parser.optional(tmp, "basis");
149  std::optional<Eigen::MatrixXd> basis = tmp.transpose();
150 
151  if (parser.valid()) {
152  parser.value = notstd::make_unique<DoFSpace>(
153  shared_prim, dof_key, transformation_matrix_to_super, sites, basis);
154  }
155 }
156 
157 namespace { // implementation for parse_axes_counter_range
158 
164 void _enforce_num(InputParser<AxesCounterParams> &parser, double &inc,
165  double &max, double min, int num) {
166  if (num < 1) {
167  parser.insert_error("num", "Error: 'num' must be >= 1.");
168  } else if (num == 1) {
169  inc = (max - min);
170  max -= inc / 10.;
171  } else {
172  inc = (max - min) / (num - 1);
173  max += inc / 10.;
174  }
175 }
176 
178 void _parse_scalar_input(InputParser<AxesCounterParams> &parser) {
179  AxesCounterParams &params = *parser.value;
180  params.scalar_input = true;
181 
182  parser.optional_else(params.min_scalar, "min", 0.);
183  parser.require(params.max_scalar, "max");
184 
185  if (parser.self.contains("increment") == parser.self.contains("num")) {
186  parser.error.insert("Error: require one of 'increment' or 'num'.");
187  return;
188  }
189  if (parser.self.contains("increment")) {
190  parser.optional(params.inc_scalar, "increment");
191  } else {
194  int num_scalar;
195  parser.optional(num_scalar, "num");
196  _enforce_num(parser, params.inc_scalar, params.max_scalar,
197  params.min_scalar, num_scalar);
198  }
199 }
200 
202 void _parse_vector_input(InputParser<AxesCounterParams> &parser) {
203  AxesCounterParams &params = *parser.value;
204  int dim = params.axes.cols();
205  params.scalar_input = false;
206 
207  // "min"
208  Eigen::VectorXd default_min = Eigen::VectorXd::Constant(dim, 0.);
209  parser.optional_else(params.min_vector, "min", default_min);
210  if (params.min_vector.size() != dim) {
211  parser.insert_error("min", "Error: 'min' size != axes dimension");
212  }
213 
214  // "max"
215  parser.require(params.max_vector, "max");
216  if (params.max_vector.size() != dim) {
217  parser.insert_error("max", "Error: 'max' size != axes dimension");
218  }
219 
220  // "increment" or "num"
221  if (parser.self.contains("increment") == parser.self.contains("num")) {
222  parser.error.insert("Error: require one of 'increment' or 'num'.");
223  return;
224  }
225  if (parser.self.contains("increment")) {
226  parser.optional(params.inc_vector, "increment");
227  if (params.inc_vector.size() != dim) {
228  parser.insert_error("increment",
229  "Error: 'increment' size != axes dimension");
230  }
231  } else {
234  Eigen::VectorXi num_vector;
235  parser.optional(num_vector, "num");
236  if (num_vector.size() != dim) {
237  parser.insert_error("num", "Error: 'num' size != axes dimension");
238  }
239  for (int i = 0; i < num_vector.size(); ++i) {
240  _enforce_num(parser, params.inc_vector[i], params.max_vector[i],
241  params.min_vector[i], num_vector[i]);
242  }
243  }
244 }
245 
246 } // namespace
247 
268  if (parser.value == nullptr) {
269  throw std::runtime_error("Unknown AxesCounterParams parsing error");
270  return;
271  }
272 
273  // Use "max" to check for scalar or array input
274  if (!parser.self.contains("max")) {
275  parser.insert_error("max", "Error: missing required parameter 'max'.");
276  return;
277  } else if (parser.self["max"].is_number()) {
278  _parse_scalar_input(parser);
279  } else if (parser.self["max"].is_array()) {
280  _parse_vector_input(parser);
281  } else {
282  std::stringstream msg;
283  msg << "Error: Parameter 'max' must be a number, or an "
284  "array of numbers matching the 'axes' dimension.";
285  parser.insert_error("max", msg.str());
286  return;
287  }
288 }
289 
333  Index dof_space_dimension) {
334  if (parser.value == nullptr) {
335  throw std::runtime_error("Unknown AxesCounterParams parsing error");
336  return;
337  }
338  Eigen::MatrixXd inaxes =
339  Eigen::MatrixXd::Zero(dof_space_dimension, dof_space_dimension);
340 
341  std::set<Index> found;
342  for (Index i = 0; i < dof_space_dimension; ++i) {
343  std::string axis_name =
344  "q" + to_sequential_string(i + 1, dof_space_dimension);
345  auto subparser =
346  parser.subparse_if<Eigen::VectorXd>(fs::path{"axes"} / axis_name);
347  if (subparser->value != nullptr) {
348  if (subparser->value->size() != dof_space_dimension) {
349  std::stringstream msg;
350  msg << "Error reading axis vector '" << axis_name
351  << "': expected size=" << dof_space_dimension
352  << " found size=" << subparser->value->size();
353  subparser->error.insert(msg.str());
354  } else {
355  inaxes.col(found.size()) = *subparser->value;
356  }
357  found.insert(i);
358  }
359  }
360 
361  Index subspace_dimension = found.size();
362  parser.value->axes = inaxes.leftCols(subspace_dimension);
363 }
364 
368  Index dof_space_dimension) {
369  if (parser.value == nullptr) {
370  throw std::runtime_error("Unknown AxesCounterParams parsing error");
371  return;
372  }
373 
374  auto subparser = parser.subparse_if<Eigen::MatrixXd>("axes");
375  if (!subparser->valid()) {
376  return;
377  }
378  Eigen::MatrixXd &axes = parser.value->axes;
379  axes = subparser->value->transpose();
380 
381  // check axes dimensions:
382  if (axes.rows() != dof_space_dimension) {
383  // Note: message "columns" refers to JSON input axes, transpose of
384  // params.axes
385  std::stringstream msg;
386  msg << "Number of columns of 'axes' must be equal to site DoF space "
387  "dimension ("
388  << dof_space_dimension << "). Size as parsed: " << axes.rows();
389  subparser->error.insert(msg.str());
390  }
391  if (axes.cols() > dof_space_dimension) {
392  // Note: message "rows" refers to JSON input axes, transpose of params.axes
393  std::stringstream msg;
394  msg << "Number of coordinate axes (number of rows of 'axes') must be less "
395  "than or equal to "
396  "site DoF space dimension ("
397  << dof_space_dimension << "). Number of axes parsed: " << axes.cols();
398  subparser->error.insert(msg.str());
399  }
400 }
401 
417  Index dof_space_dimension) {
418  if (parser.value == nullptr) {
419  return;
420  }
421  Eigen::MatrixXd &axes = parser.value->axes;
422  // "axes" -> axes
423  if (!parser.self.contains("axes")) {
424  axes = Eigen::MatrixXd::Identity(dof_space_dimension, dof_space_dimension);
425  } else if (parser.self.contains("axes") && parser.self["axes"].is_obj()) {
426  parse_axes_from_object(parser, dof_space_dimension);
427  } else if (parser.self.contains("axes") && parser.self["axes"].is_array()) {
428  parse_axes_from_array(parser, dof_space_dimension);
429  } else {
430  std::stringstream msg;
431  msg << "The 'axes' must be a JSON object of axis vectors (named 'q1', "
432  "'q2', etc.), or a row-vector matrix";
433  parser.error.insert(msg.str());
434  }
435 }
436 
439 void parse(InputParser<AxesCounterParams> &parser, Index dof_space_dimension) {
440  parser.value = notstd::make_unique<AxesCounterParams>();
441  parse_dof_space_axes(parser, dof_space_dimension);
442  parse_axes_counter_range(parser);
443  if (!parser.valid()) {
444  parser.value.reset();
445  }
446 }
447 
448 } // namespace CASM
std::set< std::string > & s
std::shared_ptr< Structure const > shared_prim
Eigen::MatrixXd const & basis() const
Definition: DoFSpace.cc:227
std::optional< std::vector< Index > > const & axis_site_index() const
Definition: DoFSpace.cc:242
bool includes_all_sites() const
True, if local DoF space with all sites in the supercell included.
Definition: DoFSpace.cc:219
std::optional< Eigen::Matrix3l > const & transformation_matrix_to_super() const
Specifies the supercell for a local DoF space. Has value for local DoF.
Definition: DoFSpace.cc:208
std::optional< std::vector< Index > > const & axis_dof_component() const
Definition: DoFSpace.cc:248
std::optional< std::set< Index > > const & sites() const
The sites included in a local DoF space. Has value for local DoF.
Definition: DoFSpace.cc:214
std::vector< std::string > const & axis_glossary() const
Names the DoF corresponding to each dimension (row) of the basis.
Definition: DoFSpace.cc:236
DoFKey const & dof_key() const
Definition: DoFSpace.cc:205
std::unique_ptr< RequiredType > optional(fs::path option, Args &&... args)
std::unique_ptr< RequiredType > require(fs::path option, Args &&... args)
std::unique_ptr< T > value
Definition: InputParser.hh:234
std::shared_ptr< InputParser< RequiredType > > subparse_if(fs::path option, Args &&... args)
bool contains(const std::string &name) const
Return true if JSON object contains 'name'.
Definition: jsonParser.cc:601
bool is_array() const
Check if array type.
Definition: jsonParser.cc:275
bool is_number() const
Check if number type (including int)
Definition: jsonParser.cc:266
bool is_obj() const
Check if object type.
Definition: jsonParser.cc:272
MatrixXiSupercellSymInfoFormatter transformation_matrix_to_super()
IdentitySymRepBuilder Identity()
Main CASM namespace.
Definition: APICommand.hh:8
Eigen::MatrixXd MatrixXd
void parse_dof_space_axes(InputParser< AxesCounterParams > &parser, Index dof_space_dimension)
Definition: DoFSpace.cc:416
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
Log & log()
Definition: Log.hh:424
void parse_axes_from_object(InputParser< AxesCounterParams > &parser, Index dof_space_dimension)
Definition: DoFSpace.cc:332
std::string to_sequential_string(Index i, Index max_i, char prepend_char='0')
Definition: CASM_math.cc:248
const double TOL
Definition: definitions.hh:30
std::string DoFKey
Definition: DoFDecl.hh:7
void parse_axes_counter_range(InputParser< AxesCounterParams > &parser)
Definition: DoFSpace.cc:267
Eigen::MatrixXd make_homogeneous_mode_space(DoFSpace const &dof_space)
Make the homogeneous mode space of a local DoFSpace.
Definition: DoFSpace.cc:740
void from_json(ClexDescription &desc, const jsonParser &json)
T min(const T &A, const T &B)
Definition: CASM_math.hh:88
void parse_axes_from_array(InputParser< AxesCounterParams > &parser, Index dof_space_dimension)
Definition: DoFSpace.cc:367
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 parse(InputParser< ConfigEnumOptions > &parser, std::string method_name, PrimClex const &primclex, DataFormatterDictionary< Configuration > const &dict)
Eigen::VectorXd VectorXd
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
bool valid() const
Return true if this and and all subparsers are valid.
Definition: InputParser.cc:56
jsonParser const & self
Definition: InputParser.hh:81
void insert_error(fs::path option, std::string message)
Insert a subparser at location option with a single error message
Definition: InputParser.cc:97
std::set< std::string > error
Definition: Validator.hh:11
static ReturnType from_json(const jsonParser &json)
Default from_json is equivalent to.
Definition: jsonParser.hh:551
static std::unique_ptr< ValueType > make_from_json(const jsonParser &json)
Default make_from_json is equivalent to.
Definition: jsonParser.hh:567