CASM  1.1.0
A Clusters Approach to Statistical Mechanics
DoFSpace.cc
Go to the documentation of this file.
2 
4 #include "casm/clex/Supercell.hh"
10 
11 // for make_symmetry_adapted_dof_space error_report:
12 #include "casm/casm_io/Log.hh"
16 
17 namespace CASM {
18 
19 namespace DoFSpace_impl {
20 
22  DoFKey const &dof_key,
23  std::optional<Eigen::Matrix3l> const &transformation_matrix_to_super,
24  std::optional<std::set<Index>> const &sites) {
25  if (!transformation_matrix_to_super.has_value() || !sites.has_value()) {
26  std::stringstream msg;
27  msg << "Error: local DoF '" << dof_key
28  << "' require transformation_matrix_to_super and sites" << std::endl;
29  throw std::runtime_error(msg.str());
30  }
31 }
32 
34 void error_report(DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
35  std::vector<PermuteIterator> const &group, bool calc_wedges,
36  std::optional<VectorSpaceSymReport> &symmetry_report) {
37  CASM::err_log() << "prim:" << std::endl;
38  COORD_TYPE mode = FRAC;
39  bool include_va = false;
40  jsonParser prim_json;
41  write_prim(*dof_space.shared_prim(), prim_json, mode, include_va);
42  CASM::err_log() << prim_json << std::endl;
43 
44  CASM::err_log() << "transformation_matrix_to_super:" << std::endl;
45  CASM::err_log() << sym_info.transformation_matrix_to_super() << std::endl;
46 
47  CASM::err_log() << "supercell factor group: " << std::endl;
48  SymInfoOptions opt{CART};
49  brief_description(log(), sym_info.factor_group(),
50  sym_info.supercell_lattice(), opt);
51 
52  jsonParser dof_space_json;
53  std::optional<std::string> identifier;
54  std::optional<ConfigEnumInput> input_state;
55  to_json(dof_space, dof_space_json, identifier, input_state, symmetry_report);
56  CASM::err_log() << dof_space_json << std::endl;
57 
58  CASM::err_log() << "dof_space.basis().cols(): " << dof_space.basis().cols()
59  << std::endl;
60  CASM::err_log() << "dof_space basis: " << std::endl
61  << dof_space.basis() << std::endl;
62  if (symmetry_report.has_value()) {
63  CASM::err_log() << "symmetry_adapted_dof_subspace.cols(): "
64  << symmetry_report->symmetry_adapted_dof_subspace.cols()
65  << std::endl;
66  CASM::err_log() << "symmetry_adapted_dof_subspace: " << std::endl
67  << symmetry_report->symmetry_adapted_dof_subspace
68  << std::endl;
69  Index i = 0;
70  for (auto const &irrep : symmetry_report->irreps) {
71  CASM::err_log() << "irrep[" << i << "].trans_mat: " << std::endl;
72  CASM::err_log() << irrep.trans_mat << std::endl;
73  i++;
74  }
75  }
76 };
77 
80  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
81  std::vector<PermuteIterator> const &group, bool calc_wedges,
82  std::optional<SymRepTools_v2::VectorSpaceSymReport> &symmetry_report) {
83  CASM::err_log() << "prim:" << std::endl;
84  COORD_TYPE mode = FRAC;
85  bool include_va = false;
86  jsonParser prim_json;
87  write_prim(*dof_space.shared_prim(), prim_json, mode, include_va);
88  CASM::err_log() << prim_json << std::endl;
89 
90  CASM::err_log() << "transformation_matrix_to_super:" << std::endl;
91  CASM::err_log() << sym_info.transformation_matrix_to_super() << std::endl;
92 
93  CASM::err_log() << "supercell factor group: " << std::endl;
94  SymInfoOptions opt{CART};
95  brief_description(log(), sym_info.factor_group(),
96  sym_info.supercell_lattice(), opt);
97 
98  jsonParser dof_space_json;
99  std::optional<std::string> identifier;
100  std::optional<ConfigEnumInput> input_state;
101  to_json(dof_space, dof_space_json, identifier, input_state, symmetry_report);
102  CASM::err_log() << dof_space_json << std::endl;
103 
104  CASM::err_log() << "dof_space.basis().cols(): " << dof_space.basis().cols()
105  << std::endl;
106  CASM::err_log() << "dof_space basis: " << std::endl
107  << dof_space.basis() << std::endl;
108  if (symmetry_report.has_value()) {
109  CASM::err_log() << "symmetry_adapted_dof_subspace.cols(): "
110  << symmetry_report->symmetry_adapted_subspace.cols()
111  << std::endl;
112  CASM::err_log() << "symmetry_adapted_dof_subspace: " << std::endl
113  << symmetry_report->symmetry_adapted_subspace << std::endl;
114  Index i = 0;
115  for (auto const &irrep : symmetry_report->irreps) {
116  CASM::err_log() << "irrep[" << i << "].trans_mat: " << std::endl;
117  CASM::err_log() << irrep.trans_mat << std::endl;
118  i++;
119  }
120  }
121 };
122 
123 } // namespace DoFSpace_impl
124 
142  std::shared_ptr<Structure const> const &_shared_prim,
143  DoFKey const &_dof_key,
144  std::optional<Eigen::Matrix3l> const &_transformation_matrix_to_super,
145  std::optional<std::set<Index>> const &_sites,
146  std::optional<Eigen::MatrixXd> const &_basis)
147  : m_shared_prim(_shared_prim),
148  m_dof_key(_dof_key),
149  m_transformation_matrix_to_super(_transformation_matrix_to_super),
150  m_sites(_sites) {
151  if (AnisoValTraits(m_dof_key).global()) {
153  m_sites.reset();
154  } else {
155  if (!m_transformation_matrix_to_super.has_value()) {
156  std::stringstream msg;
157  msg << "Error constructing DoFSpace: Local DoF '" << m_dof_key
158  << "' requires transformation_matrix_to_super." << std::endl;
159  throw std::runtime_error(msg.str());
160  }
161  if (!m_sites.has_value()) {
162  xtal::UnitCellCoordIndexConverter unitcellcoord_index_converter(
164  m_sites = std::set<Index>();
165  for (Index i = 0; i < unitcellcoord_index_converter.total_sites(); ++i) {
166  m_sites->insert(i);
167  }
168  }
169  }
170 
171  Index dof_space_dimension = get_dof_space_dimension(
173 
174  if (!_basis.has_value()) {
175  m_basis =
176  Eigen::MatrixXd::Identity(dof_space_dimension, dof_space_dimension);
177  } else {
178  m_basis = _basis.value();
179  }
180  if (m_basis.rows() != dof_space_dimension) {
181  std::stringstream msg;
182  msg << "Error constructing DoFSpace: # basis rows (" << m_basis.rows()
183  << ") != expected dimension (" << dof_space_dimension << ").";
184  throw std::runtime_error(msg.str());
185  }
186  if (m_basis.cols() > m_basis.rows()) {
187  std::stringstream msg;
188  msg << "Error constructing DoFSpace: # basis columns (" << m_basis.cols()
189  << ") > expected dimension (" << m_basis.rows() << ").";
190  throw std::runtime_error(msg.str());
191  }
192 
196 }
197 
199 std::shared_ptr<Structure const> const &DoFSpace::shared_prim() const {
200  return m_shared_prim;
201 }
202 
205 DoFKey const &DoFSpace::dof_key() const { return m_dof_key; }
206 
208 std::optional<Eigen::Matrix3l> const &DoFSpace::transformation_matrix_to_super()
209  const {
211 }
212 
214 std::optional<std::set<Index>> const &DoFSpace::sites() const {
215  return m_sites;
216 }
217 
220  return transformation_matrix_to_super().has_value() && sites().has_value() &&
221  (sites()->size() == transformation_matrix_to_super()->determinant() *
222  shared_prim()->basis().size());
223 }
224 
227 Eigen::MatrixXd const &DoFSpace::basis() const { return m_basis; }
228 
230 Index DoFSpace::dim() const { return m_basis.rows(); }
231 
233 Index DoFSpace::subspace_dim() const { return m_basis.cols(); }
234 
236 std::vector<std::string> const &DoFSpace::axis_glossary() const {
237  return m_axis_glossary;
238 }
239 
242 std::optional<std::vector<Index>> const &DoFSpace::axis_site_index() const {
243  return m_axis_site_index;
244 }
245 
248 std::optional<std::vector<Index>> const &DoFSpace::axis_dof_component() const {
249  return m_axis_dof_component;
250 }
251 
258  DoFSpace const &dof_space) {
259  if (!AnisoValTraits(dof_space.dof_key()).global()) {
260  if (config.supercell().shared_prim() != dof_space.shared_prim()) {
261  return false;
262  }
263  if (config.supercell().sym_info().transformation_matrix_to_super() !=
264  dof_space.transformation_matrix_to_super()) {
265  return false;
266  }
267  }
268  return true;
269 }
270 
273  DoFSpace const &dof_space) {
274  if (!is_valid_dof_space(config, dof_space)) {
275  std::stringstream msg;
276  msg << "Error: DoFSpace is not valid for given configuration." << std::endl;
277  throw std::runtime_error(msg.str());
278  }
279 }
280 
285  DoFSpace const &dof_space) {
286  using namespace DoFSpace_impl;
288 
289  auto const &dof_key = dof_space.dof_key();
290  auto const &basis = dof_space.basis();
291 
292  if (AnisoValTraits(dof_key).global()) {
293  auto const &dof_values = config.configdof().global_dof(dof_key).values();
294  return basis.colPivHouseholderQr().solve(dof_values);
295  } else {
296  if (dof_key == "occ") {
297  auto const &dof_values = config.configdof().occupation().cast<double>();
298  return basis.colPivHouseholderQr().solve(dof_values);
299  } else {
300  Eigen::VectorXd vector_values = Eigen::VectorXd::Zero(dof_space.dim());
301  Eigen::MatrixXd const &matrix_values =
302  config.configdof().local_dof(dof_key).values();
303 
304  auto const &axis_dof_component = dof_space.axis_dof_component().value();
305  auto const &axis_site_index = dof_space.axis_site_index().value();
306 
307  for (Index i = 0; i < dof_space.dim(); ++i) {
308  vector_values[i] =
309  matrix_values(axis_dof_component[i], axis_site_index[i]);
310  }
311  return basis.colPivHouseholderQr().solve(vector_values);
312  }
313  }
314 }
315 
317 void set_dof_value(Configuration &config, DoFSpace const &dof_space,
319  using namespace DoFSpace_impl;
321 
322  if (normal_coordinate.size() != dof_space.subspace_dim()) {
323  std::stringstream msg;
324  msg << "Error in set_dof_value: normal coordinate size ("
325  << normal_coordinate.size() << ") != # basis axes ("
326  << dof_space.subspace_dim() << ").";
327  throw std::runtime_error(msg.str());
328  }
329 
330  auto const &dof_key = dof_space.dof_key();
331  auto const &basis = dof_space.basis();
332 
333  if (AnisoValTraits(dof_key).global()) {
334  config.configdof().set_global_dof(dof_key, basis * normal_coordinate);
335  } else {
336  if (dof_key == "occ") {
337  std::stringstream msg;
338  msg << "Error: set_dof_value is not supported for occupation."
339  << std::endl;
340  throw std::runtime_error(msg.str());
341  }
342 
343  auto &local_dof = config.configdof().local_dof(dof_key);
344  Eigen::VectorXd vector_values = basis * normal_coordinate;
345  Eigen::MatrixXd matrix_values = local_dof.values();
346 
347  auto const &axis_dof_component = dof_space.axis_dof_component().value();
348  auto const &axis_site_index = dof_space.axis_site_index().value();
349 
350  for (Index i = 0; i < dof_space.dim(); ++i) {
351  matrix_values(axis_dof_component[i], axis_site_index[i]) =
352  vector_values[i];
353  }
354 
355  local_dof.set_values(matrix_values);
356  }
357 }
358 
360  DoFKey dof_key, xtal::BasicStructure const &prim,
361  std::optional<Eigen::Matrix3l> const &transformation_matrix_to_super,
362  std::optional<std::set<Index>> const &sites) {
363  if (AnisoValTraits(dof_key).global()) {
364  return prim.global_dof(dof_key).dim();
365  } else {
366  using namespace DoFSpace_impl;
368  dof_key, transformation_matrix_to_super, sites);
369 
370  xtal::UnitCellCoordIndexConverter unitcellcoord_index_converter(
371  *transformation_matrix_to_super, prim.basis().size());
372  Index dof_space_dimension = 0;
373  for (Index site_index : *sites) {
374  Index sublattice_index =
375  unitcellcoord_index_converter(site_index).sublattice();
376  xtal::Site const &site = prim.basis()[sublattice_index];
377  if (dof_key == "occ") {
378  dof_space_dimension += site.occupant_dof().size();
379  } else if (site.has_dof(dof_key)) {
380  dof_space_dimension += site.dof(dof_key).dim();
381  }
382  }
383  return dof_space_dimension;
384  }
385 }
386 
388 std::vector<std::string> make_axis_glossary(
389  DoFKey dof_key, xtal::BasicStructure const &prim,
390  std::optional<Eigen::Matrix3l> const &transformation_matrix_to_super,
391  std::optional<std::set<Index>> const &sites) {
392  std::vector<std::string> axis_glossary;
393 
394  if (AnisoValTraits(dof_key).global()) {
395  // Global DoF, axis_glossary comes straight from the DoF
396  axis_glossary = component_descriptions(prim.global_dof(dof_key));
397  } else {
398  using namespace DoFSpace_impl;
400  dof_key, transformation_matrix_to_super, sites);
401 
402  xtal::UnitCellCoordIndexConverter unitcellcoord_index_converter(
403  *transformation_matrix_to_super, prim.basis().size());
404  // Generate full axis_glossary for all active sites of the config_region
405  for (Index site_index : *sites) {
406  Index sublattice_index =
407  unitcellcoord_index_converter(site_index).sublattice();
408  xtal::Site const &site = prim.basis()[sublattice_index];
409  if (dof_key == "occ") {
410  for (auto const &molecule : site.occupant_dof()) {
411  axis_glossary.push_back("occ[" + std::to_string(site_index + 1) +
412  "][" + molecule.name() + "]");
413  }
414  } else if (site.has_dof(dof_key)) {
415  std::vector<std::string> tdescs =
416  component_descriptions(site.dof(dof_key));
417  for (std::string const &desc : tdescs) {
418  axis_glossary.push_back(desc + "[" + std::to_string(site_index + 1) +
419  "]");
420  }
421  }
422  if (!site.has_dof(dof_key)) continue;
423  }
424  }
425  return axis_glossary;
426 }
427 
430  DoFKey dof_key, xtal::BasicStructure const &prim,
431  std::optional<Eigen::Matrix3l> const &transformation_matrix_to_super,
432  std::optional<std::set<Index>> const &sites,
433  std::vector<std::string> &axis_glossary,
434  std::optional<std::vector<Index>> &axis_site_index,
435  std::optional<std::vector<Index>> &axis_dof_component) {
436  if (AnisoValTraits(dof_key).global()) {
437  axis_glossary.clear();
438  axis_site_index = std::nullopt;
439  axis_dof_component = std::nullopt;
440 
441  // Global DoF, axis_glossary comes straight from the DoF
442  axis_glossary = component_descriptions(prim.global_dof(dof_key));
443  } else {
444  using namespace DoFSpace_impl;
446  dof_key, transformation_matrix_to_super, sites);
447 
448  axis_glossary.clear();
449  axis_site_index = std::vector<Index>();
450  axis_dof_component = std::vector<Index>();
451 
452  xtal::UnitCellCoordIndexConverter unitcellcoord_index_converter(
453  *transformation_matrix_to_super, prim.basis().size());
454  // Generate full axis_glossary for all active sites of the config_region
455  for (Index site_index : *sites) {
456  Index sublattice_index =
457  unitcellcoord_index_converter(site_index).sublattice();
458  xtal::Site const &site = prim.basis()[sublattice_index];
459  if (dof_key == "occ") {
460  Index i = 0;
461  for (auto const &molecule : site.occupant_dof()) {
462  axis_glossary.push_back("occ[" + std::to_string(site_index + 1) +
463  "][" + molecule.name() + "]");
464  axis_dof_component->push_back(i);
465  axis_site_index->push_back(site_index);
466  ++i;
467  }
468  } else if (site.has_dof(dof_key)) {
469  std::vector<std::string> tdescs =
470  component_descriptions(site.dof(dof_key));
471  Index i = 0;
472  for (std::string const &desc : tdescs) {
473  axis_glossary.push_back(desc + "[" + std::to_string(site_index + 1) +
474  "]");
475  axis_dof_component->push_back(i);
476  axis_site_index->push_back(site_index);
477  ++i;
478  }
479  }
480  if (!site.has_dof(dof_key)) continue;
481  }
482  }
483 }
484 
487 DoFSpace make_dof_space(DoFKey dof_key, ConfigEnumInput const &input_state,
488  std::optional<Eigen::MatrixXd> const &basis) {
489  auto const &supercell = input_state.configuration().supercell();
490 
491  return DoFSpace(supercell.shared_prim(), dof_key,
492  supercell.sym_info().transformation_matrix_to_super(),
493  input_state.sites(), basis);
494 }
495 
510 // }
514  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
515  std::vector<PermuteIterator> const &group,
516  MasterSymGroup &symrep_master_group, SymGroupRepID &id) {
517  MasterSymGroup &g = symrep_master_group;
518  DoFKey dof_key = dof_space.dof_key();
519  xtal::BasicStructure const &prim_struc = dof_space.shared_prim()->structure();
520 
521  // Populate temporary objects for two cases
522  // CASE 1: DoF is global (use prim_struc's list of global DoFs, rather than
523  // relying on val_traits.is_global()
524  if (prim_struc.global_dofs().count(dof_key)) {
525  // Global DoF, use point group only
526  SymGroup pointgroup = make_point_group(group, sym_info.supercell_lattice());
527  g = make_master_sym_group(pointgroup, sym_info.supercell_lattice());
528 
529  id = g.allocate_representation();
530  SymGroupRep const &rep = *(sym_info.global_dof_symrep(dof_key).rep_ptr());
531  for (Index i = 0; i < pointgroup.size(); ++i) {
532  Index fg_ix = pointgroup[i].index();
533  g[i].set_rep(id, *rep[fg_ix]);
534  }
535 
536  }
537  // CASE 2: DoF is local
538  else {
539  if (!dof_space.sites().has_value()) {
540  throw std::runtime_error(
541  "Error in make_dof_space_symrep: Local DoF, but no sites");
542  }
543  auto group_and_ID = make_collective_dof_symrep(dof_space.sites().value(),
544  sym_info, dof_key, group);
545  g = group_and_ID.first;
546  g.is_temporary_of(group_and_ID.first);
547  id = group_and_ID.second;
548  }
549 
550  return g.representation(id);
551 }
552 
561  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
562  std::vector<PermuteIterator> const &group, bool calc_wedges) {
563  // We need a temporary mastersymgroup to manage the symmetry representation
564  // for the DoF
565  MasterSymGroup g;
566  SymGroupRepID id;
567  SymGroupRep const &rep =
568  make_dof_space_symrep(dof_space, sym_info, group, g, id);
569 
570  // Generate report, based on constructed inputs
571  VectorSpaceSymReport result =
572  vector_space_sym_report(rep, g, dof_space.basis(), calc_wedges);
573  result.axis_glossary = dof_space.axis_glossary();
574 
575  return result;
576 }
577 
586  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
587  std::vector<PermuteIterator> const &group, bool calc_wedges) {
588  // We need a temporary mastersymgroup to manage the symmetry representation
589  // for the DoF
590  MasterSymGroup g;
591  SymGroupRepID id;
592  SymGroupRep const &rep =
593  make_dof_space_symrep(dof_space, sym_info, group, g, id);
594 
595  // Generate report, based on constructed inputs
597  vector_space_sym_report_v2(rep, g, dof_space.basis(), calc_wedges);
598  result.axis_glossary = dof_space.axis_glossary();
599 
600  return result;
601 }
602 
605  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
606  std::vector<PermuteIterator> const &group, bool calc_wedges,
607  std::optional<VectorSpaceSymReport> &symmetry_report) {
608  using namespace DoFSpace_impl;
609 
610  try {
611  symmetry_report =
612  vector_space_sym_report(dof_space, sym_info, group, calc_wedges);
613  } catch (std::exception &e) {
614  error_report(dof_space, sym_info, group, calc_wedges, symmetry_report);
615  CASM::err_log() << "Error constructing vector space symmetry report: "
616  << e.what() << std::endl;
617  throw e;
618  }
619  // check for error occuring for "disp"
620  if (symmetry_report->symmetry_adapted_dof_subspace.cols() <
621  dof_space.basis().cols()) {
622  error_report(dof_space, sym_info, group, calc_wedges, symmetry_report);
623  std::stringstream msg;
624  msg << "Error in make_symmetry_adapted_dof_space: "
625  << "symmetry_adapted_dof_subspace.cols() < dof_space.basis().cols()";
626  throw make_symmetry_adapted_dof_space_error(msg.str());
627  }
628 
629  return DoFSpace(dof_space.shared_prim(), dof_space.dof_key(),
630  sym_info.transformation_matrix_to_super(), dof_space.sites(),
631  symmetry_report->symmetry_adapted_dof_subspace);
632 }
633 
636  DoFSpace const &dof_space, SupercellSymInfo const &sym_info,
637  std::vector<PermuteIterator> const &group, bool calc_wedges,
638  std::optional<SymRepTools_v2::VectorSpaceSymReport> &symmetry_report) {
639  using namespace DoFSpace_impl;
640 
641  try {
642  symmetry_report =
643  vector_space_sym_report_v2(dof_space, sym_info, group, calc_wedges);
644  } catch (std::exception &e) {
645  error_report_v2(dof_space, sym_info, group, calc_wedges, symmetry_report);
646  CASM::err_log() << "Error constructing vector space symmetry report: "
647  << e.what() << std::endl;
648  throw e;
649  }
650  // check for error occuring for "disp"
651  if (symmetry_report->symmetry_adapted_subspace.cols() <
652  dof_space.basis().cols()) {
653  error_report_v2(dof_space, sym_info, group, calc_wedges, symmetry_report);
654  std::stringstream msg;
655  msg << "Error in make_symmetry_adapted_dof_space_v2: "
656  << "symmetry_adapted_subspace.cols() < dof_space.basis().cols()";
657  throw make_symmetry_adapted_dof_space_error(msg.str());
658  }
659 
660  return DoFSpace(dof_space.shared_prim(), dof_space.dof_key(),
661  sym_info.transformation_matrix_to_super(), dof_space.sites(),
662  symmetry_report->symmetry_adapted_subspace);
663 }
664 
674  if (AnisoValTraits(dof_space.dof_key()).global() ||
675  dof_space.dof_key() == "occ" || !dof_space.includes_all_sites()) {
676  std::stringstream msg;
677  msg << "Error in exclude_homogeneous_mode_space: Must be a DoF space for a "
678  "local continuous degrees of freedom that includes all sites in the "
679  "supercell.";
680  throw std::runtime_error(msg.str());
681  }
682 
683  Eigen::MatrixXd null_space =
684  make_homogeneous_mode_space(dof_space).transpose().fullPivLu().kernel();
685 
686  return DoFSpace{dof_space.shared_prim(), dof_space.dof_key(),
687  dof_space.transformation_matrix_to_super(), dof_space.sites(),
688  null_space};
689 }
690 
741  if (AnisoValTraits(dof_space.dof_key()).global() ||
742  dof_space.dof_key() == "occ" || !dof_space.includes_all_sites()) {
743  std::stringstream msg;
744  msg << "Error in make_homogeneous_mode_space: Must be a DoF space for a "
745  "local continuous degrees of freedom that includes all sites in the "
746  "supercell.";
747  throw std::runtime_error(msg.str());
748  }
749 
750  auto const &dof_key = dof_space.dof_key();
751  auto const &prim = *dof_space.shared_prim();
752  auto const &T = *dof_space.transformation_matrix_to_super();
753  auto const &sites = *dof_space.sites();
754 
756  std::vector<DoFSetInfo> prim_dof_info = local_dof_info(prim)[dof_key];
757 
759  std::vector<DoFSetInfo> sites_dof_info;
760  // b: sublattice index
761  // l: linear index in supercell
762  // bijk: UnitCellCoord, integral site coordinates
763  xtal::UnitCellCoordIndexConverter l_to_bijk(T, prim.basis().size());
764  for (Index l : sites) {
765  Index b = l_to_bijk(l).sublattice();
766  xtal::Site const &site = prim.basis()[b];
767  if (site.has_dof(dof_key)) {
768  sites_dof_info.push_back(prim_dof_info[b]);
769  }
770  }
771 
772  // standard_dof_values = dof_info.basis() * prim_dof_values
773  // dof_info.inv_basis() * standard_dof_values = prim_dof_values
774 
775  // find the common basis, in the standard DoF basis, among all sites:
776  int standard_basis_dim = prim_dof_info[0].basis().rows();
777  Eigen::MatrixXd I =
778  Eigen::MatrixXd::Identity(standard_basis_dim, standard_basis_dim);
779  Eigen::MatrixXd prod = I;
780  for (auto const &sublat_dof : prim_dof_info) {
781  prod = sublat_dof.basis() * sublat_dof.inv_basis() * prod;
782  }
783  // common_standard_basis is nullspace of (prod - I):
784  Eigen::MatrixXd common_standard_basis =
785  (prod - I).transpose().fullPivLu().kernel();
786 
787  if (common_standard_basis.isZero(TOL)) {
788  return Eigen::MatrixXd::Zero(dof_space.basis().rows(), 0);
789  }
790 
791  // construct homogeneous_mode_space by transforming common_standard_basis into
792  // the site basis values, and combining for each site
793  Eigen::MatrixXd homogeneous_mode_space{dof_space.basis().rows(),
794  common_standard_basis.cols()};
795 
796  Index row = 0; // block starting row
797  Index col = 0; // block starting column
798  for (auto const &site_dof : sites_dof_info) {
799  auto const &values = site_dof.inv_basis() * common_standard_basis;
800  int n_rows = values.rows();
801  int n_cols = values.cols();
802  homogeneous_mode_space.block(row, col, n_rows, n_cols) = values;
803  row += site_dof.dim();
804  }
805 
806  return homogeneous_mode_space;
807 }
808 
810  Eigen::MatrixXd const &column_vector_space, Eigen::MatrixXd const &subspace,
811  double tol) {
812  // Make a projection operator out of homogeneous mode space and project each
813  // of the basis vectors onto it If they have a partial projection (not full or
814  // zero) => translational modes are mixed between irreps
815  Eigen::MatrixXd proj_operator = subspace * subspace.transpose();
816  for (Index i = 0; i < column_vector_space.cols(); ++i) {
817  Eigen::VectorXd col_projection = proj_operator * column_vector_space.col(i);
818  if (col_projection.isZero(tol)) {
819  axes_not_in_subspace.push_back(i);
820  } else if (CASM::almost_equal(col_projection.normalized(),
821  column_vector_space.col(i).normalized(),
822  tol)) {
823  axes_in_subspace.push_back(i);
824  }
825 
826  else {
827  axes_mixed_with_subspace.push_back(i);
828  }
829  }
830 
831  if (axes_mixed_with_subspace.size() == 0) {
833  }
834 }
835 } // namespace CASM
Specifies traits of (possibly) anisotropic crystal properties.
bool global() const
Returns true if type is global.
const Supercell & supercell() const
Get the Supercell for this Configuration.
Index dim() const
Dimension of the DoFSet, equivalent to basis().cols()
Definition: DoFSet.hh:254
std::vector< std::string > m_axis_glossary
Names the DoF corresponding to each dimension (row) of the basis.
Definition: DoFSpace.hh:135
Eigen::MatrixXd const & basis() const
Definition: DoFSpace.cc:227
std::optional< std::vector< Index > > const & axis_site_index() const
Definition: DoFSpace.cc:242
Index subspace_dim() const
The DoF subspace dimension (equal to number of columns in basis).
Definition: DoFSpace.cc:233
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
DoFSpace(std::shared_ptr< Structure const > const &_shared_prim, DoFKey const &_dof_key, std::optional< Eigen::Matrix3l > const &_transformation_matrix_to_super=std::nullopt, std::optional< std::set< Index >> const &_sites=std::nullopt, std::optional< Eigen::MatrixXd > const &_basis=std::nullopt)
Definition: DoFSpace.cc:141
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::shared_ptr< Structure const > const & shared_prim() const
Shared prim structure.
Definition: DoFSpace.cc:199
std::vector< std::string > const & axis_glossary() const
Names the DoF corresponding to each dimension (row) of the basis.
Definition: DoFSpace.cc:236
DoFKey m_dof_key
Definition: DoFSpace.hh:122
std::shared_ptr< Structure const > m_shared_prim
Shared prim structure.
Definition: DoFSpace.hh:118
std::optional< std::vector< Index > > m_axis_dof_component
Definition: DoFSpace.hh:159
std::optional< Eigen::Matrix3l > m_transformation_matrix_to_super
Specifies the supercell for a local DoF space. Required for local DoF.
Definition: DoFSpace.hh:125
std::optional< std::set< Index > > m_sites
The sites included in a local DoF space. Required for local DoF.
Definition: DoFSpace.hh:128
Index dim() const
The DoF space dimension (equal to number of rows in basis).
Definition: DoFSpace.cc:230
Eigen::MatrixXd m_basis
Definition: DoFSpace.hh:132
DoFKey const & dof_key() const
Definition: DoFSpace.cc:205
std::optional< std::vector< Index > > m_axis_site_index
Definition: DoFSpace.hh:147
SymGroupRepID allocate_representation() const
Add a new empty representation.
Definition: SymGroup.cc:694
void set_rep(SymGroupRepID _rep_ID, SymOpRepresentation const &_op_rep, Index op_index) const
Definition: SymGroup.cc:479
void is_temporary_of(MasterSymGroup const &RHS)
Definition: SymGroup.hh:306
SymGroupRep const & representation(SymGroupRepID i) const
Const access of alternate Representations of a SymGroup.
Definition: SymGroup.cc:717
A class that collects all symmetry information for for performing symmetry transformations on the sit...
SymGroup const & factor_group() const
Subgroup of primitive-cell factor group operations that leave supercell lattice invariant.
const xtal::Lattice & supercell_lattice() const
const reference to supercell lattice
Eigen::Matrix3l transformation_matrix_to_super() const
long-int transformation from primitive lattice vectors to supercell lattice vectors supercell_lattice...
SymGroupRep::RemoteHandle const & global_dof_symrep(DoFKey const &_key) const
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
SymGroupRep const * rep_ptr() const
Definition: SymGroupRep.hh:221
SymGroupRep is an alternative representation of a SymGroup for something other than real space....
Definition: SymGroupRep.hh:31
Type-safe ID object for communicating and accessing Symmetry representation info.
BasicStructure specifies the lattice and atomic basis of a crystal.
std::map< DoFKey, DoFSet > const & global_dofs() const
DoFSet const & global_dof(std::string const &dof_type) const
const std::vector< Site > & basis() const
Index dim() const
Definition: DoFSet.hh:64
bool has_dof(std::string const &_dof_type) const
Definition: Site.cc:90
const std::vector< Molecule > & occupant_dof() const
Definition: Site.cc:68
SiteDoFSet const & dof(std::string const &_dof_type) const
Definition: Site.cc:78
Index total_sites() const
Returns the total number of sites within the superlattice.
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
std::set< Index > const & sites() const
Configuration const & configuration() const
MasterSymGroup make_master_sym_group(SymGroup const &_group, Lattice const &_lattice)
Definition: SymGroup.cc:2148
Generic1DDatumFormatter< Eigen::VectorXd, ConfigEnumDataType > normal_coordinate()
ConfigIO::GenericConfigFormatter< jsonParser > config()
Definition: ConfigIO.cc:777
void throw_if_missing_local_dof_requirements(DoFKey const &dof_key, std::optional< Eigen::Matrix3l > const &transformation_matrix_to_super, std::optional< std::set< Index >> const &sites)
Definition: DoFSpace.cc:21
void error_report_v2(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges, std::optional< SymRepTools_v2::VectorSpaceSymReport > &symmetry_report)
Print information in case constructing VectorSpaceSymReport fails.
Definition: DoFSpace.cc:79
void error_report(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges, std::optional< VectorSpaceSymReport > &symmetry_report)
Print information in case constructing VectorSpaceSymReport fails.
Definition: DoFSpace.cc:34
MatrixXiSupercellSymInfoFormatter transformation_matrix_to_super()
IdentitySymRepBuilder Identity()
std::vector< std::string > component_descriptions(DoFSet const &dofset)
Definition: DoFSet.cc:12
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
void set_dof_value(Configuration &config, DoFSpace const &dof_space, Eigen::VectorXd const &normal_coordinate)
Set config DoF value from a coordinate in the DoFSpace basis.
Definition: DoFSpace.cc:317
VectorSpaceSymReport vector_space_sym_report(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges=false)
Make VectorSpaceSymReport.
Definition: DoFSpace.cc:560
Eigen::VectorXd get_normal_coordinate(Configuration const &config, DoFSpace const &dof_space)
Return config DoF value as a coordinate in the DoFSpace basis.
Definition: DoFSpace.cc:284
Eigen::MatrixXd MatrixXd
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
std::pair< MasterSymGroup, SymGroupRepID > make_collective_dof_symrep(std::set< Index > const &site_indices, SupercellSymInfo const &_syminfo, DoFKey const &_key, std::vector< PermuteIterator > const &_group)
Make the matrix representation for group '_group' describing the transformation of DoF '_key' among a...
COORD_TYPE
Definition: enum.hh:6
DoFSpace exclude_homogeneous_mode_space(DoFSpace const &dof_space)
Removes the homogeneous mode space from the DoFSpace basis.
Definition: DoFSpace.cc:673
Log & log()
Definition: Log.hh:424
DoFSpace make_dof_space(DoFKey dof_key, ConfigEnumInput const &input_state, std::optional< Eigen::MatrixXd > const &basis=std::nullopt)
Definition: DoFSpace.cc:487
void write_prim(const xtal::BasicStructure &prim, fs::path filename, COORD_TYPE mode, bool include_va=false)
Write prim.json to file.
std::string brief_description(const SymOp &op, const xtal::Lattice &lat, SymInfoOptions opt=SymInfoOptions())
Print SymInfo to brief string.
Index get_dof_space_dimension(DoFKey dof_key, xtal::BasicStructure const &prim, std::optional< Eigen::Matrix3l > const &transformation_matrix_to_super=std::nullopt, std::optional< std::set< Index >> const &sites=std::nullopt)
Return dimension of DoFSpace.
Definition: DoFSpace.cc:359
std::vector< std::string > make_axis_glossary(DoFKey dof_key, xtal::BasicStructure const &prim, std::optional< Eigen::Matrix3l > const &transformation_matrix_to_super, std::optional< std::set< Index >> const &sites)
The axis_glossary gives names to an un-symmetrized coordinate system.
Definition: DoFSpace.cc:388
const COORD_TYPE FRAC
Definition: enum.hh:8
void make_dof_space_axis_info(DoFKey dof_key, xtal::BasicStructure const &prim, std::optional< Eigen::Matrix3l > const &transformation_matrix_to_super, std::optional< std::set< Index >> const &sites, std::vector< std::string > &axis_glossary, std::optional< std::vector< Index >> &axis_site_index, std::optional< std::vector< Index >> &axis_dof_component)
Make DoFSpace axis glossary, axis site index, and axis dof component.
Definition: DoFSpace.cc:429
const double TOL
Definition: definitions.hh:30
SymGroupRep const & make_dof_space_symrep(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, MasterSymGroup &symrep_master_group, SymGroupRepID &id)
Make a SymGroupRep for a DoFSpace.
Definition: DoFSpace.cc:513
std::string DoFKey
Definition: DoFDecl.hh:7
SymRepTools_v2::VectorSpaceSymReport vector_space_sym_report_v2(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges=false)
Make VectorSpaceSymReport.
Definition: DoFSpace.cc:585
void throw_if_invalid_dof_space(Configuration const &config, DoFSpace const &dof_space)
Throw if !is_valid_dof_space(config, dof_space)
Definition: DoFSpace.cc:272
bool is_valid_dof_space(Configuration const &config, DoFSpace const &dof_space)
Definition: DoFSpace.cc:257
Eigen::MatrixXd make_homogeneous_mode_space(DoFSpace const &dof_space)
Make the homogeneous mode space of a local DoFSpace.
Definition: DoFSpace.cc:740
DoFSpace make_symmetry_adapted_dof_space(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges, std::optional< VectorSpaceSymReport > &symmetry_report)
Make DoFSpace with symmetry adapated basis.
Definition: DoFSpace.cc:604
const COORD_TYPE CART
Definition: enum.hh:9
std::map< DoFKey, std::vector< CASM::DoFSetInfo > > local_dof_info(Structure const &_struc)
Definition: Structure.cc:395
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Eigen::VectorXd VectorXd
DoFSpace make_symmetry_adapted_dof_space_v2(DoFSpace const &dof_space, SupercellSymInfo const &sym_info, std::vector< PermuteIterator > const &group, bool calc_wedges, std::optional< SymRepTools_v2::VectorSpaceSymReport > &symmetry_report)
Make DoFSpace with symmetry adapated basis.
Definition: DoFSpace.cc:635
Log & err_log()
Definition: Log.hh:426
SymGroup make_point_group(const PermuteIteratorContainer &container, const Lattice &supercell_lattice)
Returns a SymGroup generated from a container of PermuteIterator.
ClexDescription & desc
Definition: settings.cc:138
Options for printing SymInfo.
Summary of data associated with the action of a symmetry group on a vector space.
std::vector< std::string > axis_glossary
Names given to individual axes in initial (un-adapted) vector space, corresponding to rows of symmetr...
std::vector< Index > axes_not_in_subspace
Definition: DoFSpace.hh:267
std::vector< Index > axes_in_subspace
Definition: DoFSpace.hh:268
VectorSpaceMixingInfo(Eigen::MatrixXd const &column_vector_space, Eigen::MatrixXd const &subspace, double tol)
Definition: DoFSpace.cc:809
std::vector< Index > axes_mixed_with_subspace
Definition: DoFSpace.hh:269
Summary of data associated with the action of a symmetry group on a vector space.
Definition: SymRepTools.hh:185
std::vector< std::string > axis_glossary
Names given to individual axes in initial (un-adapted) vector space, corresponding to rows of symmetr...
Definition: SymRepTools.hh:204