CASM  1.1.0
A Clusters Approach to Statistical Mechanics
OccupationDoFTraits.cc
Go to the documentation of this file.
2 
3 #include <memory>
4 
6 #include "casm/basis_set/DoF.hh"
9 #include "casm/casm_io/container/json_io.hh" // TODO: remove
13 #include "casm/clex/ClexBasis.hh"
19 
20 namespace CASM {
21 
22 namespace DoF_impl {
23 
24 namespace {
25 double pretty(double value, double tol) {
26  double pretty_value = value;
27  if (std::abs(value) < tol) {
28  return 0.;
29  }
30  if (std::abs(std::round(value) - value) < tol) {
31  pretty_value = std::round(value);
32  }
33  return pretty_value;
34 }
35 } // namespace
36 
37 std::string OccupationDoFSpecs::_name() const {
38  return OccupationDoFTraits().name();
39 }
40 
41 std::vector<double> chebychev_sublat_prob_vec(Index occupant_dof_size) {
42  return std::vector<double>(occupant_dof_size, 1. / double(occupant_dof_size));
43 }
44 
45 std::vector<double> occupation_sublat_prob_vec(Index occupant_dof_size) {
46  std::vector<double> tprob(occupant_dof_size, 0.);
47  tprob[0] = 1.;
48  return tprob;
49 }
50 
51 std::vector<double> composition_sublat_prob_vec(
52  const OccupationDoFSpecs &occ_specs, Index sublat_index,
53  const std::vector<std::string> &allowed_occupants) {
54  for (const auto &sublat_comp : occ_specs.sublat_composition) {
55  if (sublat_comp.indices.find(sublat_index) != sublat_comp.indices.end()) {
56  std::vector<double> tprob(allowed_occupants.size(), 0.);
57  double tsum{0};
58  for (Index ns = 0; ns < allowed_occupants.size(); ns++) {
59  auto it = sublat_comp.values.find(allowed_occupants[ns]);
60  if (it == sublat_comp.values.end()) {
61  throw std::runtime_error(
62  "BasisFunctionSpecs error: basis site " +
63  std::to_string(sublat_index) +
64  " must have a composition specified for species " +
65  allowed_occupants[ns] + "\n");
66  }
67  tprob[ns] = it->second;
68  tsum += tprob[ns];
69  }
70  for (Index j = 0; j < tprob.size(); j++) {
71  tprob[j] /= tsum;
72  }
73  return tprob;
74  }
75  }
76  throw std::runtime_error(
77  "BasisFunctionSpecs error: compositions are not specified for basis "
78  "site " +
79  std::to_string(sublat_index) + "\n");
80 }
81 
82 namespace OccupationDoFSpecs_impl {
83 
88  Structure const &prim);
89 
91  std::vector<std::set<std::string>> allowed_molecule_names;
92 
94  Index b, DoF_impl::SublatComp const &sublat_comp,
95  const std::set<std::string> &allowed_molecule_names);
96  void check_molecule_names();
97  void check_sublat_indices();
98 };
99 
101  OccupationDoFSpecs const &_occ_specs, Structure const &prim)
102  : occ_specs(_occ_specs) {
103  // check_dof_keys();
107  auto tmp{CASM::xtal::allowed_molecule_names(prim)};
108  allowed_molecule_names.clear();
109  for (const auto &vec : tmp) {
110  allowed_molecule_names.push_back(
111  std::set<std::string>{vec.begin(), vec.end()});
112  }
113 
116  }
117 }
118 
120  Index b, DoF_impl::SublatComp const &sublat_comp,
121  std::set<std::string> const &allowed_molecule_names) {
122  for (const auto &name : allowed_molecule_names) {
123  if (sublat_comp.values.find(name) == sublat_comp.values.end()) {
124  error.insert("No composition is given for '" + name + " on sublattice " +
125  std::to_string(b) + ". Allowed molecules are: " +
127  }
128  }
129  auto begin = allowed_molecule_names.begin();
130  auto end = allowed_molecule_names.end();
131  for (const auto &pair : sublat_comp.values) {
132  if (std::find(begin, end, pair.first) == end) {
133  error.insert(to_string(pair.first) + " is not allowed on sublattice " +
134  std::to_string(b) + ". Allowed molecules are: " +
136  }
137  }
138 }
139 
141  for (const auto &sublat_comp : occ_specs.sublat_composition) {
142  for (const auto &b : sublat_comp.indices) {
143  if (b >= allowed_molecule_names.size()) {
144  error.insert("Sublattice index " + std::to_string(b) +
145  " is out of range.");
146  }
148  }
149  }
150 }
151 
153  std::set<Index> found;
154  for (const auto &sublat_comp : occ_specs.sublat_composition) {
155  for (const auto &b : sublat_comp.indices) {
156  if (b >= allowed_molecule_names.size()) {
157  error.insert("Sublattice index " + std::to_string(b) +
158  " is out of range.");
159  }
160  if (found.count(b)) {
161  error.insert("Sublattice index " + std::to_string(b) +
162  " is duplicated.");
163  }
164  found.insert(b);
165  }
166  }
167  for (Index b = 0; b < allowed_molecule_names.size(); ++b) {
168  if (!found.count(b) && allowed_molecule_names[b].size() > 1) {
169  error.insert("Missing sublattice index " + std::to_string(b) + ".");
170  }
171  }
172 }
173 
174 } // namespace OccupationDoFSpecs_impl
175 
176 Validator validate(OccupationDoFSpecs const &occ_specs, const Structure &prim) {
178 }
179 
180 // helper for _construct_orthonormal_discrete_functions
181 std::vector<double> _make_occ_probs(const Site &site, Index b_ind,
182  OccupationDoFSpecs const &occ_specs) {
183  std::vector<double> tprob;
184 
185  // options: CHEBYCHEV, OCCUPATION, COMPOSITION
186  if (occ_specs.site_basis_function_type ==
188  return chebychev_sublat_prob_vec(site.occupant_dof().size());
189  } else if (occ_specs.site_basis_function_type ==
191  return occupation_sublat_prob_vec(site.occupant_dof().size());
192  } else if (occ_specs.site_basis_function_type ==
194  return composition_sublat_prob_vec(occ_specs, b_ind,
195  site.allowed_occupants());
196  } else {
197  throw std::runtime_error(
198  "BasisFunctionSpecs error: unknown SITE_BASIS_FUNCTION_TYPE");
199  }
200 }
201 
202 // helper for OccupationDoFTraits::construct_site_bases
204  BasisSet &site_basis,
206  Structure const &prim, DoF_impl::OccupationDoFSpecs const &occ_specs) {
207  UnitCellCoord const &uccoord = orbit.prototype()[0];
208  Site const &site = uccoord.sublattice_site(prim);
209  Index sublattice_index = uccoord.sublattice();
210 
211  // convert vector<xtal::Molecule> to OccupantDoF<xtal::Molecule>
212  adapter::Adapter<OccupantDoF<xtal::Molecule>, std::vector<xtal::Molecule>>
213  adapter_f;
214  OccupantDoF<xtal::Molecule> allowed_occs =
215  adapter_f(site.occupant_dof(),
216  prim.occupant_symrep_IDs()[sublattice_index], sublattice_index);
217 
218  // construct reference occupation probabilities
219  std::vector<double> tprob =
220  _make_occ_probs(site, sublattice_index, occ_specs);
221 
222  if (tprob.size() != allowed_occs.size()) {
223  std::stringstream ss;
224  ss << "Error in OccupationDoFTraits::construct_site_bases: occ_probs "
225  "error.";
226  ss << " sublattice_index=" << sublattice_index << " ";
227  ss << " occ_probs=[";
228  for (Index i = 0; i < tprob.size(); ++i) {
229  if (i != 0) ss << ",";
230  ss << tprob[i];
231  }
232  ss << "]";
233  throw std::runtime_error(ss.str());
234  }
235 
236  // construct site invariant group
237  auto eq_map_range = orbit.equivalence_map(0);
238  SymGroup invariant_group{eq_map_range.first, eq_map_range.second};
239 
240  // construct site bases for the prototype site
242  allowed_occs, tprob, sublattice_index, invariant_group);
243 
244  return;
245 }
246 
250  Structure const &_prim,
251  std::vector<Orbit<PrimPeriodicSymCompare<IntegralCluster>>> &_asym_unit,
252  BasisFunctionSpecs const &_basis_function_specs) const {
253  // site bases, to be populated
254  std::vector<BasisSet> site_bases{_prim.basis().size()};
255 
256  // specifications, for how to construct site basis functions
257  auto const &occ_specs =
258  get<OccupationDoFSpecs>(this->name(), _basis_function_specs);
259 
260  // loop over orbits in the asymmetric unit
261  for (auto const &orbit : _asym_unit) {
262  UnitCellCoord const &prototype_uccoord = orbit.prototype()[0];
263  Site const &prototype_site = prototype_uccoord.sublattice_site(_prim);
264  Index prototype_sublattice_index = prototype_uccoord.sublattice();
265 
266  if (prototype_site.occupant_dof().size() < 2) {
267  continue;
268  }
269 
270  // construct site basis for prototype site in orbit
271  auto &prototype_site_basis = site_bases[prototype_sublattice_index];
272  _construct_orthonormal_discrete_functions(prototype_site_basis, orbit,
273  _prim, occ_specs);
274 
275  // construct site bases for all equivalent sites by:
276  // - applying symmetry to the site basis already constructed for the
277  // prototype site
278  // - setting necessary indices & ids
279  for (Index ne = 1; ne < orbit.size(); ne++) {
280  Index other_sublattice_index = orbit[ne][0].sublattice();
281  auto &other_site_basis = site_bases[other_sublattice_index];
282  other_site_basis = prototype_site_basis;
283  other_site_basis.apply_sym(orbit.equivalence_map()[ne][0]);
284  other_site_basis.accept(OccFuncBasisIndexer{(int)other_sublattice_index});
285  other_site_basis.set_dof_IDs({other_sublattice_index});
286  }
287  }
288  return site_bases;
289 }
290 
291 //************************************************************
293  Structure const &_prim,
294  std::map<UnitCellCoord, std::set<UnitCellCoord>> const &_nhood,
295  PrimNeighborList &_nlist, std::vector<BasisSet> const &site_bases,
296  std::string const &indent) const {
297  std::stringstream ss;
298  ss << indent << "switch(nlist_ind) {\n";
299  for (auto const &nbor : _nhood) {
300  ss << indent << "case " << _nlist.neighbor_index(nbor.first) << ":\n";
301  std::stringstream ssfunc;
302  // Put neighborhood in a sensible order:
303  std::map<Index, std::set<Index>> sublat_nhood;
304  for (auto const &ucc : nbor.second) {
305  sublat_nhood[ucc.sublattice()].insert(_nlist.neighbor_index(ucc));
306  }
307 
308  for (auto const &sublat : sublat_nhood) {
309  Index b = sublat.first;
310  for (Index n : sublat.second) {
311  for (Index f = 0; f < site_bases[b].size(); f++) {
312  ssfunc << indent << " ParamPack::Val<Scalar>::set(m_params, m_"
313  << site_basis_name() << "_param_key, " << f << ", " << n
314  << ", eval_occ_func_" << b << "_" << f << "(" << n << "));\n";
315  }
316  }
317  }
318  if (ssfunc.str().size()) {
319  ss << indent << " if(m_params.eval_mode(m_" << site_basis_name()
320  << "_param_key) != ParamPack::READ) {\n"
321  << ssfunc.str() << indent << " }\n";
322  }
323  ss << indent << " break;\n";
324  }
325  ss << indent << "}\n";
326  return ss.str();
327 }
328 
329 //************************************************************
330 
332  Structure const &_prim,
333  std::map<UnitCellCoord, std::set<UnitCellCoord>> const &_nhood,
334  PrimNeighborList &_nlist, std::vector<BasisSet> const &site_bases,
335  std::string const &indent) const {
336  std::stringstream ss, ssfunc;
337  std::map<Index, std::set<Index>> tot_nhood;
338  for (auto const &nbor : _nhood)
339  for (auto const &ucc : nbor.second)
340  tot_nhood[ucc.sublattice()].insert(_nlist.neighbor_index(ucc));
341 
342  for (auto const &nbor : tot_nhood) {
343  Index b = nbor.first;
344  for (Index n : nbor.second) {
345  for (Index f = 0; f < site_bases[b].size(); f++) {
346  ssfunc << indent << " ParamPack::Val<Scalar>::set(m_params, m_"
347  << site_basis_name() << "_param_key, " << f << ", " << n
348  << ", eval_occ_func_" << b << "_" << f << "(" << n << "));\n";
349  }
350  }
351  }
352  if (ssfunc.str().size()) {
353  ss << indent << "if(m_params.eval_mode(m_" << site_basis_name()
354  << "_param_key) != ParamPack::READ) {\n"
355  << ssfunc.str() << indent << "}\n";
356  }
357 
358  return ss.str();
359 }
360 //************************************************************
361 
363  Structure const &_prim, std::vector<BasisSet> const &_site_bases,
364  std::string const &indent) const {
365  std::stringstream stream;
366  std::vector<Orbit<PrimPeriodicSymCompare<IntegralCluster>>> asym_unit;
367  std::ostream nullstream(0);
368 
369  // TODO: This is a temporary fix to avoid changing the interface of
370  // OccupationDoFTraits. What can happen is making these functions take a
371  // shared_ptr, but what *really* needs to happen is fixing all the classes and
372  // functions (such as those in SymCompare) that are requesting Structures when
373  // all they really need is SymRepIDs. I can't fix all that right now though,
374  // so check this out: it's a shared pointer to an existing Structure, that has
375  // a custom destructor that does nothing.
376  auto _prim_ptr =
377  std::shared_ptr<const Structure>(&_prim, [](const Structure *) {});
378  make_prim_periodic_asymmetric_unit(_prim_ptr,
380  std::back_inserter(asym_unit), nullstream);
381 
382  for (Index no = 0; no < asym_unit.size(); no++) {
383  Index nb = asym_unit[no][0][0].sublattice();
384  if (_site_bases[nb].size() == 0) continue;
385  stream
386  << indent
387  << "// Occupation Function tables for basis sites in asymmetric unit "
388  << no << ":\n";
389  for (Index ne = 0; ne < asym_unit[no].size(); ne++) {
390  nb = asym_unit[no][ne][0].sublattice();
391  stream << indent << "// - basis site " << nb << ":\n";
392  for (Index f = 0; f < _site_bases[nb].size(); f++) {
393  stream << indent << "double "
394  << "m_occ_func_" << nb << '_' << f << '['
395  << _prim.basis()[nb].occupant_dof().size() << "];\n";
396  }
397  stream << '\n';
398  }
399  }
400  return stream.str();
401 }
402 
403 //************************************************************
404 
406  Structure const &_prim, std::vector<BasisSet> const &_site_bases,
407  const std::string &indent) const {
408  std::stringstream stream;
409  std::vector<Orbit<PrimPeriodicSymCompare<IntegralCluster>>> asym_unit;
410  std::ostream nullstream(0);
411 
412  // TODO: This is a temporary fix to avoid changing the interface of
413  // OccupationDoFTraits. What can happen is making these functions take a
414  // shared_ptr, but what *really* needs to happen is fixing all the classes and
415  // functions (such as those in SymCompare) that are requesting Structures when
416  // all they really need is SymRepIDs. I can't fix all that right now though,
417  // so check this out: it's a shared pointer to an existing Structure, that has
418  // a custom destructor that does nothing.
419  auto _prim_ptr =
420  std::shared_ptr<const Structure>(&_prim, [](const Structure *) {});
421  make_prim_periodic_asymmetric_unit(_prim_ptr,
423  std::back_inserter(asym_unit), nullstream);
424 
425  for (Index no = 0; no < asym_unit.size(); no++) {
426  Index nb = asym_unit[no][0][0].sublattice();
427  if (_site_bases[nb].size() == 0) continue;
428 
429  for (Index ne = 0; ne < asym_unit[no].size(); ne++) {
430  nb = asym_unit[no][ne][0].sublattice();
431 
432  stream
433  << indent
434  << "// Occupation Function evaluators and accessors for basis site "
435  << nb << ":\n";
436  for (Index f = 0; f < _site_bases[nb].size(); f++) {
437  stream << indent << "double const &eval_occ_func_" << nb << '_' << f
438  << "(const int &nlist_ind) const {\n"
439  << indent << " return "
440  << "m_occ_func_" << nb << '_' << f
441  << "[_configdof().occ(_l(nlist_ind))];\n"
442  << indent << "}\n\n"
443  <<
444 
445  indent << "double const &occ_func_" << nb << '_' << f
446  << "(const int &nlist_ind) const {\n"
447  << indent << " return "
448  << "m_params.read(m_" << site_basis_name() << "_param_key, " << f
449  << ", nlist_ind);\n"
450  << indent << "}\n";
451  }
452  stream << '\n';
453  }
454  }
455  return stream.str();
456 }
457 
458 //************************************************************
459 
460 std::vector<DoFType::ParamAllocation>
462  Structure const &_prim, std::vector<BasisSet> const &_bases) const {
463  std::vector<DoFType::ParamAllocation> result;
464  Index NB = 0;
465  for (BasisSet const &basis : _bases) {
466  NB = max(basis.size(), NB);
467  }
468  if (NB)
469  result.push_back(
471 
472  return result;
473 }
474 
475 //************************************************************
476 
478  Structure const &_prim, std::vector<BasisSet> const &_site_bases,
479  const std::string &indent) const {
480  std::stringstream stream;
481  stream.flags(std::ios::showpoint | std::ios::fixed | std::ios::right);
482  stream.precision(10);
483 
484  std::vector<Orbit<PrimPeriodicSymCompare<IntegralCluster>>> asym_unit;
485  std::ostream nullstream(0);
486 
487  // TODO: This is a temporary fix to avoid changing the interface of
488  // OccupationDoFTraits. What can happen is making these functions take a
489  // shared_ptr, but what *really* needs to happen is fixing all the classes and
490  // functions (such as those in SymCompare) that are requesting Structures when
491  // all they really need is SymRepIDs. I can't fix all that right now though,
492  // so check this out: it's a shared pointer to an existing Structure, that has
493  // a custom destructor that does nothing.
494  auto _prim_ptr =
495  std::shared_ptr<const Structure>(&_prim, [](const Structure *) {});
496  make_prim_periodic_asymmetric_unit(_prim_ptr,
498  std::back_inserter(asym_unit), nullstream);
499 
500  for (const auto &asym : asym_unit) {
501  for (const auto &equiv : asym) {
502  Index nb = equiv[0].sublattice();
503  for (Index f = 0; f < _site_bases[nb].size(); f++) {
504  for (Index s = 0; s < _prim.basis()[nb].occupant_dof().size(); s++) {
505  OccFuncEvaluator t_eval(s);
506  _site_bases[nb][f]->accept(t_eval);
507 
508  if (s == 0) stream << indent;
509  stream << "m_occ_func_" << nb << '_' << f << '[' << s
510  << "] = " << t_eval.value();
511  if (s + 1 == _prim.basis()[nb].occupant_dof().size())
512  stream << ";\n\n";
513  else
514  stream << ", ";
515  }
516  }
517  }
518  }
519  return stream.str();
520 }
521 
523  Site site,
524  Index site_ix) const {
525  std::stringstream ss;
526  if (site_bset.size() == 0) ss << " [No site basis functions]\n\n";
527  /* std::vector<DoF::RemoteHandle> handles(1, site.occupant_dof().handle()); */
528  // TODO: What is "s"? Do I need to know about this "s" elsewhere to use the
529  // remote handles
531  std::vector<DoF::RemoteHandle> handles{
532  DoF::RemoteHandle(DoFType::occupation().name(), "s", site_ix)};
533  int s;
534  handles[0] = s;
535  site_bset.register_remotes(handles);
536  for (Index f = 0; f < site_bset.size(); f++) {
537  for (s = 0; s < site.occupant_dof().size(); s++) {
538  if (s == 0) ss << " ";
539  ss << " \\phi_{" << site_ix << "," << f << "}["
540  << site.occupant_dof()[s].name()
541  << "] = " << pretty(site_bset[f]->remote_eval(), 1e-10);
542  if (s + 1 == site.occupant_dof().size())
543  ss << "\n";
544  else
545  ss << ", ";
546  }
547  }
548  return ss.str();
549 }
550 
551 std::vector<std::unique_ptr<FunctionVisitor>>
553  std::string const &nlist_specifier) const {
554  std::vector<std::unique_ptr<FunctionVisitor>> result;
555  result.push_back(std::unique_ptr<FunctionVisitor>(
556  new OccFuncLabeler("occ_func_%b_%f(" + nlist_specifier + ")")));
557  return result;
558 }
559 
560 std::vector<std::unique_ptr<FunctionVisitor>>
562  std::vector<std::unique_ptr<FunctionVisitor>> result;
563  result.push_back(std::unique_ptr<FunctionVisitor>(
564  new OccFuncLabeler("occ_func_%b_%f(%n)")));
565  return result;
566 }
567 
569  InputParser<BasisFunctionSpecs> &parser, Structure const &prim) const {
570  fs::path dof_specs_path{"dof_specs"};
571  fs::path subpath = dof_specs_path / this->name();
572  auto subparser = parser.subparse<OccupationDoFSpecs>(subpath, prim);
573  if (subparser->value) {
574  parser.value->dof_specs.push_back(std::move(subparser->value));
575  }
576 }
577 
579  const BasisFunctionSpecs &basis_function_specs, jsonParser &json,
580  Structure const &prim) const {
581  OccupationDoFSpecs const &occupation_dof_specs =
582  get<OccupationDoFSpecs>(this->name(), basis_function_specs);
583  CASM::to_json(occupation_dof_specs, json["dof_specs"][this->name()]);
584 }
585 
587  return new OccupationDoFTraits(*this);
588 }
589 
590 } // namespace DoF_impl
591 
592 namespace DoFType {
595 }
596 
597 std::unique_ptr<DoFSpecs> chebychev_bfuncs() {
598  return notstd::make_unique<DoF_impl::OccupationDoFSpecs>(
600 }
601 
602 std::unique_ptr<DoFSpecs> occupation_bfuncs() {
603  return notstd::make_unique<DoF_impl::OccupationDoFSpecs>(
605 }
606 
607 std::unique_ptr<DoFSpecs> composition_bfuncs(
608  std::vector<DoF_impl::SublatComp> sublat_composition) {
609  return notstd::make_unique<DoF_impl::OccupationDoFSpecs>(sublat_composition);
610 }
611 } // namespace DoFType
612 
613 namespace parse_OccupationDoFSpecs_impl {
614 
630 void from_json(std::vector<DoF_impl::SublatComp> &sublat_composition,
631  const jsonParser &json) {
632  sublat_composition.clear();
633  for (auto it = json.begin(); it != json.end(); ++it) {
634  std::set<Index> sublat_indices;
635  it->find("sublat_indices")->get(sublat_indices);
636  std::map<std::string, double> sublat_values;
637  it->find("composition")->get(sublat_values);
638  sublat_composition.emplace_back(sublat_indices, sublat_values);
639  }
640 }
641 
642 void to_json(std::vector<DoF_impl::SublatComp> const &sublat_composition,
643  jsonParser &json) {
644  json.put_array();
645  for (auto const &sublat_comp : sublat_composition) {
646  jsonParser tjson;
647  tjson["sublat_indices"] = sublat_comp.indices;
648  tjson["composition"] = sublat_comp.values;
649  json.push_back(tjson);
650  }
651 }
652 
659  auto it = parser.self.find("site_basis_functions");
660  if (it == parser.self.end()) {
661  parser.error.insert("Error: Required 'site_basis_functions' not found.");
662  } else {
663  if (it->is_string()) {
664  DoF_impl::SITE_BASIS_FUNCTION_TYPE site_basis_function_type;
665  it->get<DoF_impl::SITE_BASIS_FUNCTION_TYPE>(site_basis_function_type);
666  parser.value = notstd::make_unique<DoF_impl::OccupationDoFSpecs>(
667  site_basis_function_type);
668  } else if (it->is_array()) {
669  try {
670  std::vector<DoF_impl::SublatComp> sublat_composition;
671  parse_OccupationDoFSpecs_impl::from_json(sublat_composition, *it);
672  parser.value = notstd::make_unique<DoF_impl::OccupationDoFSpecs>(
673  sublat_composition);
674  } catch (std::exception &e) {
675  parser.error.insert(
676  "Error: 'site_basis_functions' is an array, but failed to read "
677  "sublattice compositions.");
678  }
679  } else {
680  parser.error.insert(
681  "Error: 'site_basis_functions' is neither a string nor an array with "
682  "sublattice compositions.");
683  }
684  }
685 }
686 } // namespace parse_OccupationDoFSpecs_impl
687 
688 // -- OccupationDoFSpecs IO --
689 
691  "site_basis_function_type";
692 
693 const std::multimap<DoF_impl::SITE_BASIS_FUNCTION_TYPE,
694  std::vector<std::string>>
695  traits<DoF_impl::SITE_BASIS_FUNCTION_TYPE>::strval = {
697  {"CHEBYCHEV", "Chebychev", "chebychev"}},
699  {"OCCUPATION", "Occupation", "occupation"}},
701  {"COMPOSITION", "Composition", "composition"}}};
702 
705 
706 void parse(InputParser<DoF_impl::OccupationDoFSpecs> &parser,
707  const Structure &prim) {
708  // read site_basis_functions from JSON (may be string or sublat compositions)
710 
711  // validate the sublat compositions w.r.t. the prim
712  parser.insert(DoF_impl::validate(*parser.value, prim));
713 }
714 
715 void to_json(DoF_impl::OccupationDoFSpecs const &occupation_dof_specs,
716  jsonParser &json) {
717  json.put_obj();
718  if (occupation_dof_specs.site_basis_function_type !=
720  json["site_basis_functions"] =
721  occupation_dof_specs.site_basis_function_type;
722  } else {
724  occupation_dof_specs.sublat_composition, json["site_basis_functions"]);
725  }
726 }
727 
728 } // namespace CASM
std::set< std::string > & s
#define ENUM_JSON_IO_DEF(ENUM)
Definition: json_io.hh:15
#define ENUM_IO_DEF(ENUM)
Definition: stream_io.hh:13
Index size() const
Definition: Array.hh:131
void construct_orthonormal_discrete_functions(const DiscreteDoF &allowed_occs, const Eigen::MatrixXd &gram_mat, Index basis_ind, const SymGroup &symgroup)
Definition: BasisSet.cc:631
int register_remotes(const std::vector< DoF::RemoteHandle > &remote_handles)
Definition: BasisSet.cc:440
std::string clexulator_point_prepare_string(Structure const &_prim, std::map< UnitCellCoord, std::set< UnitCellCoord >> const &_nhood, PrimNeighborList &_nlist, std::vector< BasisSet > const &site_bases, std::string const &indent) const override
void parse_dof_specs(InputParser< BasisFunctionSpecs > &parser, Structure const &prim) const override
Parse DoF-specific basis function specs & validate.
void dof_specs_to_json(BasisFunctionSpecs const &basis_function_specs, jsonParser &json, Structure const &prim) const override
Output DoF-specific basis function specs to json.
DoFType::Traits * _clone() const override
std::string site_basis_description(BasisSet site_bset, Site site, Index site_ix) const override
std::string clexulator_member_declarations_string(Structure const &_prim, std::vector< BasisSet > const &site_bases, std::string const &indent) const override
std::vector< std::unique_ptr< FunctionVisitor > > site_function_visitors(std::string const &nlist_specifier) const override
std::vector< DoFType::ParamAllocation > param_pack_allocation(Structure const &_prim, std::vector< BasisSet > const &_bases) const override
std::string clexulator_private_method_declarations_string(Structure const &_prim, std::vector< BasisSet > const &site_bases, std::string const &indent) const override
std::string clexulator_constructor_string(Structure const &_prim, std::vector< BasisSet > const &site_bases, std::string const &indent) const override
std::string clexulator_global_prepare_string(Structure const &_prim, std::map< UnitCellCoord, std::set< UnitCellCoord >> const &_nhood, PrimNeighborList &_nlist, std::vector< BasisSet > const &site_bases, std::string const &indent) const override
std::vector< BasisSet > construct_site_bases(Structure const &_prim, std::vector< Orbit< PrimPeriodicSymCompare< IntegralCluster >>> &_asym_unit, BasisFunctionSpecs const &_basis_function_specs) const override
Construct the site basis (if DOF_MODE is LOCAL) for a DoF, given its site.
std::vector< std::unique_ptr< FunctionVisitor > > clust_function_visitors() const override
Collection of all the traits specific to a DoF type.
Definition: DoFTraits.hh:59
std::string site_basis_name() const
Definition: DoFTraits.hh:71
std::string const & name() const
Definition: DoFTraits.hh:69
std::shared_ptr< InputParser< RequiredType > > subparse(fs::path option, Args &&... args)
std::unique_ptr< T > value
Definition: InputParser.hh:234
Index size() const override
Definition: DoF.hh:327
An Orbit of Element.
Definition: Orbit.hh:43
The PrimNeighborList gives the coordinates of UnitCell that are neighbors of the origin UnitCell.
Definition: NeighborList.hh:39
Scalar neighbor_index(UnitCellCoord const &_ucc)
Get neighborlist index of UnitCellCoord.
Structure specifies the lattice and atomic basis of a crystal.
Definition: Structure.hh:30
const std::vector< xtal::Site > & basis() const
Definition: Structure.hh:102
std::vector< SymGroupRepID > occupant_symrep_IDs() const
Definition: Structure.cc:128
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Definition: SymGroup.hh:42
iterator begin()
Returns const_iterator to beginning of JSON object or JSON array.
Definition: jsonParser.cc:497
iterator end()
Returns iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:520
jsonParser & put_obj()
Puts new empty JSON object.
Definition: jsonParser.hh:354
iterator find(const std::string &name)
Return iterator to JSON object value with 'name'.
Definition: jsonParser.cc:543
jsonParser & put_array()
Puts new empty JSON array.
Definition: jsonParser.hh:362
const std::vector< Molecule > & occupant_dof() const
Definition: Site.cc:68
std::vector< std::string > allowed_occupants() const
Definition: Site.cc:242
Unit Cell Coordinates.
const Site & sublattice_site(const PrimType &prim) const
Get reference to corresponding sublattice site in the unit structure.
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
Eigen::MatrixXd pretty(const Eigen::MatrixXd &M, double tol)
Round entries that are within tol of being integer to that integer value.
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
std::vector< std::vector< std::string > > allowed_molecule_names(BasicStructure const &_struc)
Returns a vector with a list of allowed molecule names at each site.
jsonParser & push_back(const T &value, Args &&... args)
Definition: jsonParser.hh:684
GenericDatumFormatter< std::string, ConfigEnumDataType > name()
Validator validate(OccupationDoFSpecs const &occ_specs, const Structure &prim)
std::vector< double > chebychev_sublat_prob_vec(Index occupant_dof_size)
std::vector< double > _make_occ_probs(const Site &site, Index b_ind, OccupationDoFSpecs const &occ_specs)
std::vector< double > composition_sublat_prob_vec(const OccupationDoFSpecs &occ_specs, Index sublat_index, const std::vector< std::string > &allowed_occupants)
std::vector< double > occupation_sublat_prob_vec(Index occupant_dof_size)
void _construct_orthonormal_discrete_functions(BasisSet &site_basis, Orbit< PrimPeriodicSymCompare< IntegralCluster >> const &orbit, Structure const &prim, DoF_impl::OccupationDoFSpecs const &occ_specs)
std::unique_ptr< DoFSpecs > occupation_bfuncs()
DoF_impl::OccupationDoFTraits occupation()
std::unique_ptr< DoFSpecs > composition_bfuncs(std::vector< DoF_impl::SublatComp > sublat_composition)
std::unique_ptr< DoFSpecs > chebychev_bfuncs()
void to_json(std::vector< DoF_impl::SublatComp > const &sublat_composition, jsonParser &json)
void from_json(std::vector< DoF_impl::SublatComp > &sublat_composition, const jsonParser &json)
void _require_site_basis_functions(InputParser< DoF_impl::OccupationDoFSpecs > &parser, const Structure &prim)
Main CASM namespace.
Definition: APICommand.hh:8
jsonParser & to_json(const ClexDescription &desc, jsonParser &json)
const double TOL
Definition: definitions.hh:30
GenericDatumFormatter< std::string, DataObject > name()
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
Definition: algorithm.hh:16
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)
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
Specify how to construct basis functions.
N-nary function that behaves as a constant (i.e. transform(arg1,arg2,...) == constant is true)
Definition: CASM_TMP.hh:92
void check_sublat_molecule_names(Index b, DoF_impl::SublatComp const &sublat_comp, const std::set< std::string > &allowed_molecule_names)
OccupationDoFSpecsValidator(OccupationDoFSpecs const &_occ_specs, Structure const &prim)
std::string _name() const override
SITE_BASIS_FUNCTION_TYPE site_basis_function_type
std::vector< SublatComp > sublat_composition
std::map< std::string, double > values
jsonParser const & self
Definition: InputParser.hh:81
Data structure to hold error and warning messages.
Definition: Validator.hh:10
std::set< std::string > error
Definition: Validator.hh:11