CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
SuperConfigEnum.cc
Go to the documentation of this file.
9 
10 extern "C" {
13  }
14 }
15 
16 namespace CASM {
17 
18  const std::string SuperConfigEnum::enumerator_name = "SuperConfigEnum";
19 
20  const std::string SuperConfigEnum::interface_help =
21 
22  "SuperConfigEnum: \n\n"
23 
24  " supercells: ScelEnum JSON settings (default='{\"existing_only\"=true}')\n"
25  " Indicate supercells to enumerate super-configurations in using ScelEnum\n"
26  " input format, but the \"name\" option is not allowed. See 'ScelEnum' \n"
27  " description for details. \n\n"
28 
29  " subconfigs: string or JSON array\n"
30  " Indicate supercells to enumerate all occupational configurations in. May \n"
31  " be a JSON array of configuration names, or string specifying a \n"
32  " configuration selection file anme. By default, all existing supercells \n"
33  " are used. See 'ScelEnum' description for details. \n\n"
34 
35  " primitive_only: bool (default=true)\n"
36  " If true, only the primitive form of a configuration is saved in the \n"
37  " configuration list. Otherwise, both primitive and non-primitive \n"
38  " configurations are saved. \n\n"
39 
40  " filter: string (optional, default=None)\n"
41  " A query command to use to filter which configurations are kept. \n"
42  "\n"
43  " Examples:\n"
44  " To enumerate super-configurations of listed sub-configurations:\n"
45  " casm enum --method SuperConfigEnum -i \n"
46  " '{ \n"
47  " \"supercells\": { \n"
48  " \"max\": 4, \n"
49  " \"unit_cell\": \"SCEL2_1_2_1_0_0_0\" \n"
50  " },\n"
51  " \"subconfigs\": [\n"
52  " \"SCEL1_1_1_1_0_0_0/0\",\n"
53  " \"SCEL2_1_2_1_0_0_0/0\",\n"
54  " \"SCEL2_1_2_1_0_0_0/1\"\n"
55  " ]\n"
56  " }' \n"
57  "\n"
58  " To enumerate super-configurations of listed sub-configurations from a \n"
59  " selection file:\n"
60  " casm enum --method SuperConfigEnum -i \n"
61  " '{ \n"
62  " \"supercells\": { \n"
63  " \"max\": 4, \n"
64  " \"unit_cell\": \"SCEL2_1_2_1_0_0_0\" \n"
65  " }, \n"
66  " \"subconfigs\": \"selection_filename\"\n"
67  " }' \n"
68  "\n";
69 
74  const Supercell &unit_cell,
75  const jsonParser &kwargs,
76  std::map<Configuration, std::string> &prim_subconfig) {
77 
78  auto check_is_supercell = [&](const Lattice & plat) {
79  auto end = primclex.get_prim().factor_group().end();
80  return is_supercell(unit_cell.get_real_super_lattice(),
81  plat,
82  primclex.get_prim().factor_group().begin(),
83  end,
84  primclex.crystallography_tol()).first != end;
85  };
86 
87  if(!kwargs.contains("subconfigs")) {
88  throw std::invalid_argument(
89  "Error in SuperConfigEnum JSON input: 'subconfigs' is required");
90  }
91  Log &log = primclex.log();
92  log << "Input sub-configurations:\n";
93  if(kwargs["subconfigs"].is_array()) {
94  const jsonParser &j = kwargs["subconfigs"];
95  for(auto it = j.begin(); it != j.end(); ++it) {
96  const Configuration &config = primclex.configuration(it->get<std::string>());
97  log << " " << config.name() << "\n";
98  Configuration pconfig = config.primitive();
99  if(!check_is_supercell(pconfig.ideal_lattice())) {
100  primclex.err_log().error("Invalid subconfig");
101  primclex.err_log() << "subconfig: " << config.name() << "\n";
102  primclex.err_log() << "subconfig transf_mat: \n" << config.get_supercell().get_transf_mat() << "\n";
103  primclex.err_log() << "prim transf_mat: \n" << pconfig.get_supercell().get_transf_mat() << "\n";
104  primclex.err_log() << "unit cell: \n" << unit_cell.get_transf_mat() << "\n";
105  throw std::invalid_argument("Error in SuperConfigEnum: subconfig does not fit in the unit cell");
106  }
107  prim_subconfig.insert(std::make_pair(pconfig, config.name()));
108  }
109  }
110  else {
111  ConstConfigSelection selection(primclex, kwargs["subconfigs"].get<fs::path>());
112  for(auto it = selection.selected_config_begin(); it != selection.selected_config_end(); ++it) {
113  log << " " << it->name() << "\n";
114  Configuration pconfig = it->primitive();
115  if(!check_is_supercell(pconfig.ideal_lattice())) {
116  primclex.err_log().error("Invalid subconfig");
117  primclex.err_log() << "subconfig: " << it->name() << "\n";
118  primclex.err_log() << "subconfig transf_mat: \n" << it->get_supercell().get_transf_mat() << "\n";
119  primclex.err_log() << "prim transf_mat: \n" << pconfig.get_supercell().get_transf_mat() << "\n";
120  primclex.err_log() << "unit cell: \n" << unit_cell.get_transf_mat() << "\n";
121  throw std::invalid_argument("Error in SuperConfigEnum: subconfig does not fit in the unit cell");
122  }
123  prim_subconfig.insert(std::make_pair(pconfig, it->name()));
124  }
125  }
126  }
127 
131  const PrimClex &primclex,
132  Supercell &unit_cell,
133  const std::map<Configuration, std::string> &prim_subconfig,
134  std::vector<Configuration> &subconfig) {
135 
136  primclex.log() << "\nGenerating equivalents: \n";
137  for(auto &_pair : prim_subconfig) {
138  auto &pconfig = _pair.first;
139  FillSupercell f(unit_cell, pconfig, primclex.crystallography_tol());
140  ConfigEnumEquivalents e(f(pconfig));
141  for(auto it = e.begin(); it != e.end(); ++it) {
142  subconfig.push_back(*it);
143  primclex.log() << " Config: " << it->name() << "\n" << *it << "\n";
144  }
145  }
146  primclex.log() << std::endl;
147  }
148 
151  const jsonParser &_kwargs,
152  const Completer::EnumOption &enum_opt) {
153 
154  // -- Disallow 'name' & --scelnames options --
155  if(_kwargs.contains("name") || enum_opt.vm().count("scelnames")) {
156  throw std::invalid_argument(
157  "Error in SuperConfigEnum JSON input: 'name' is not allowed in the 'supercell' option");
158  }
159 
160  // -- Option to include non-primitive --
161  bool primitive_only = true;
162  _kwargs.get_if(primitive_only, "primitive_only");
163 
164  // -- make <SupercellEnumerator<Lattice> & filter_expr from input
165  std::unique_ptr<SupercellEnumerator<Lattice> > superlat_enum = make_enumerator_superlat_enum(primclex, _kwargs, enum_opt);
166  std::vector<std::string> filter_expr = make_enumerator_filter_expr(_kwargs, enum_opt);
167 
168  // -- Unit cell --
169  // the unit cell that will be the supercell of the subconfigs that are
170  // tiled to form the super-configurations
171  Supercell unit_cell(&primclex, *superlat_enum->begin());
172 
173 
174  // -- get primitive of all subconfigs from input--
175  std::map<Configuration, std::string> prim_subconfig;
177  primclex,
178  unit_cell,
179  _kwargs,
180  prim_subconfig);
181 
182 
183  // -- generate equivalents of each primitive config --
184  std::vector<Configuration> subconfig;
186  primclex,
187  unit_cell,
188  prim_subconfig,
189  subconfig);
190 
191  // -- Enumerator construction --
192  auto lambda = [&](Supercell & scel) {
193  return notstd::make_unique<SuperConfigEnum>(scel, subconfig.begin(), subconfig.end());
194  };
195 
196  int returncode = insert_configs_via_lattice_enum(
198  primclex,
199  superlat_enum->begin(),
200  superlat_enum->end(),
201  lambda,
202  filter_expr,
203  primitive_only);
204 
205  return returncode;
206  }
207 
209 
210  // check that all sub-config have same supercell
211  for(auto it = sub_config().begin(); it != sub_config().end(); ++it) {
212  if(&it->get_supercell() != &(sub_config().begin()->get_supercell())) {
213  throw std::runtime_error("Error constructing SuperConfigEnum: "
214  "Sub-Configurations with different Supercells");
215  }
216  }
217  m_sub_scel = &(m_sub_config.begin()->get_supercell());
218 
219  // construct PrimGrid
220  m_prim_grid = notstd::make_cloneable<PrimGrid>(
223  );
224 
225  // initialize 'm_counter' to count over all possible sub-config on
226  // each prim_grid site
228  Array<int>(prim_grid().size(), 0),
229  Array<int>(prim_grid().size(), sub_config().size() - 1),
230  Array<int>(prim_grid().size(), 1));
231 
232  // save indices for mapping occupants into super config
233  // so that: m_current->occ(m_index_map[i][j]) = m_sub_scel[i].occ(j)
234  // and same for all other site DoF
235  m_index_map.resize(prim_grid().size());
236  for(int i = 0; i < prim_grid().size(); ++i) {
238  for(int j = 0; j < _sub_supercell().num_sites(); ++j) {
239  UnitCellCoord uccord = _sub_supercell().uccoord(j) + ref;
240  Index linear_index = _target_supercell().find(uccord);
241  m_index_map[i].push_back(linear_index);
242  }
243  }
244 
245  m_current = notstd::make_cloneable<Configuration>(_target_supercell());
246 
247  auto has_occ = [](const Configuration & c) {
248  return c.has_occupation();
249  };
250  m_has_occ = std::any_of(m_sub_config.begin(), m_sub_config.end(), has_occ);
251 
252  auto has_disp = [](const Configuration & c) {
253  return c.has_displacement();
254  };
255  m_has_disp = std::any_of(m_sub_config.begin(), m_sub_config.end(), has_disp);
256 
257  _initialize(&(*m_current));
258  _fill(counter(), _current());
259 
260  // Make sure that current() satisfies requested conditions
261  if(!_check_current()) {
262  increment();
263  }
264 
265  // set step to 0
266  if(valid()) {
267  _set_step(0);
268  }
270  }
271 
272  // **** Mutators ****
273  // increment m_current and return a reference to it
275 
276  bool is_valid_config {false};
277 
278  while(!is_valid_config && ++m_counter) {
279  _fill(counter(), _current());
280  is_valid_config = _check_current();
281  }
282 
283  if(m_counter.valid()) {
284  _increment_step();
285  }
286  else {
287  _invalidate();
288  }
289  }
290 
293 
294  return true;
295  }
296 
302  void SuperConfigEnum::_fill(const Array<int> &counter_val,
303  Configuration &config) {
304 
305  // use m_sub_config, prim_grid(), and counter_val to set occupation in config
306  if(m_has_occ) {
307  m_current->init_occupation();
308  }
309 
310  if(m_has_disp) {
311  m_current->init_displacement();
312  }
313 
314  ConfigDoF &to = config.configdof();
315  for(Index i = 0; i < prim_grid().size(); ++i) {
316  Configuration &from = _sub_config()[counter_val[i]];
317  for(Index j = 0; j < _sub_supercell().num_sites(); ++j) {
318 
319  // copy site DoF
320  if(from.has_occupation()) {
321  to.occ(m_index_map[i][j]) = from.occ(j);
322  }
323 
324  if(from.has_displacement()) {
325  to.disp(m_index_map[i][j]) = from.disp(j);
326  }
327  }
328  }
329  }
330 
331 }
const_displacement_t disp(Index site_l) const
Occupant displacement.
int & occ(Index i)
Definition: ConfigDoF.hh:61
iterator end()
Returns iterator to end of JSON object or JSON array.
Definition: jsonParser.cc:465
const int & occ(Index site_l) const
Occupant variable on site l.
A Counter allows looping over many incrementing variables in one loop.
Definition: Counter.hh:71
std::vector< std::vector< Index > > m_index_map
m_current->occ(m_index_map[i][j]) = m_sub_scel[i].occ(j)
std::vector< std::string > make_enumerator_filter_expr(const jsonParser &_kwargs, const Completer::EnumOption &enum_opt)
Standardizes parsing casm enum filter expressions.
Definition: Enumerator.cc:91
bool get_if(T &t, const std::string &key, Args...args) const
Definition: jsonParser.hh:740
PrimClex * primclex
Definition: settings.cc:101
const std::vector< Configuration > & sub_config() const
Access the sub-configurations.
iterator selected_config_begin()
void _generate_equivalents(const PrimClex &primclex, Supercell &unit_cell, const std::map< Configuration, std::string > &prim_subconfig, std::vector< Configuration > &subconfig)
Unit Cell Coordinates.
const ConfigDoF & configdof() const
const Access the DoF
const Lattice & get_real_super_lattice() const
Definition: Supercell.hh:267
Base class for generic use of enumerators that may be accessed through the API.
Definition: Enumerator.hh:418
virtual jsonParser source(step_type step) const
Definition: Enumerator.hh:131
Configuration primitive() const
Return the primitive Configuration.
notstd::cloneable_ptr< Configuration > m_current
The 'current' Configuration.
Main CASM namespace.
Definition: complete.cpp:8
Counter< Array< int > > m_counter
Log & log
Definition: settings.cc:105
const Lattice & ideal_lattice() const
Represents a supercell of the primitive parent crystal structure.
Definition: Supercell.hh:37
iterator begin()
Returns const_iterator to beginning of JSON object or JSON array.
Definition: jsonParser.cc:440
Unit Cell Indices.
Log & log() const
Definition: Log.hh:255
bool _check_current() const
Returns true if current() satisifies requested conditions.
static const std::string enumerator_name
pair_type ref
Definition: settings.cc:110
Template class to be specialized for each enumerator that may be accessed via the API...
Definition: Enumerator.hh:521
void _init()
Used by constructor.
bool has_occupation() const
True if Configuration has occupation DoF.
value_type & _current()
Access the current ObjectType by reference.
Definition: Enumerator.hh:244
double crystallography_tol() const
Definition: PrimClex.hh:124
const MasterSymGroup & factor_group() const
Definition: Structure.cc:94
int insert_configs_via_lattice_enum(std::string method, PrimClex &primclex, LatticeIterator begin, LatticeIterator end, ConfigEnumConstructor f, std::vector< std::string > filter_expr, bool primitive_only)
Standardizes insertion from enumerators that construct configurations.
std::vector< Configuration > & _sub_config()
Access the sub-configurations.
EigenIndex Index
For long integer indexing:
Index size() const
Definition: PrimGrid.hh:108
void _invalidate()
Call if enumeration complete.
Definition: Enumerator.hh:169
A container class for the different degrees of freedom a Configuration might have.
Definition: ConfigDoF.hh:27
step_type step() const
Increments with each enumerated object.
Definition: Enumerator.hh:113
CASM::EnumInterfaceBase * make_SuperConfigEnum_interface()
std::unique_ptr< SupercellEnumerator< Lattice > > make_enumerator_superlat_enum(PrimClex &primclex, const jsonParser &_kwargs, const Completer::EnumOption &enum_opt)
Standardizes parsing casm enum input options to make an SupercellEnumerator ...
Definition: Enumerator.cc:57
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
UnitCellCoord uccoord(Index i) const
Definition: Supercell.hh:224
void _generate_primitives(PrimClex &primclex, const Supercell &unit_cell, const jsonParser &kwargs, std::map< Configuration, std::string > &prim_subconfig)
bool valid() const
Returns false if enumeration is complete.
Definition: Enumerator.hh:118
std::string name() const
SCELV_A_B_C_D_E_F/i.
const Configuration & configuration(const std::string &configname) const
access configuration by name (of the form "scellname/[NUMBER]", e.g., ("SCEL1_1_1_1_0_0_0/0") ...
Definition: PrimClex.cc:347
Index find(const UnitCellCoord &bijk) const
Definition: Supercell.cc:39
void increment() override
Implement increment.
T const * end() const
Definition: Array.hh:197
po::variables_map & vm()
Get the variables map.
Definition: Handlers.cc:145
void _set_step(step_type val)
Set current step value.
Definition: Enumerator.hh:154
void set_source(const jsonParser &source)
bool contains(const std::string &name) const
Return true if JSON object contains 'name'.
Definition: jsonParser.cc:500
std::vector< Configuration > m_sub_config
A vector containing each possible sub_config.
std::pair< bool, Eigen::MatrixXi > is_supercell(const Lattice &scel, const Lattice &unit, double tol)
Check if scel is a supercell of unitcell unit and some integer transformation matrix T...
Definition: Lattice.cc:1196
Supercell & _sub_supercell()
Access the sub-config supercell.
void error(const std::string &what)
Definition: Log.hh:86
const Array< int > & counter() const
Access the current value of the counter.
T const * begin() const
Definition: Array.hh:185
Supercell & get_supercell() const
Get the Supercell for this Configuration.
displacement_t disp(Index i)
Definition: ConfigDoF.hh:73
Definition: Log.hh:9
UnitCell unitcell(Index i) const
Definition: PrimGrid.cc:229
const Eigen::Matrix3i & get_transf_mat() const
Definition: Supercell.hh:263
void _fill(const Array< int > &counter_val, Configuration &config)
static int run(PrimClex &primclex, const jsonParser &kwargs, const Completer::EnumOption &enum_opt)
const PrimGrid & prim_grid() const
Access the PrimGrid.
Supercell & _target_supercell()
Access the super-config supercell.
bool has_displacement() const
True if Configuration has displacement DoF.
void _increment_step()
Increment current step value.
Definition: Enumerator.hh:159
static const std::string interface_help
Enumerate all equivalent Configurations in a Supercell, as generated by Supercell factor group symmet...
A Configuration represents the values of all degrees of freedom in a Supercell.
const Structure & get_prim() const
const Access to primitive Structure
Definition: PrimClex.cc:260
Index num_sites() const
Definition: Supercell.hh:220
Log & err_log() const
Definition: Log.hh:263
notstd::cloneable_ptr< PrimGrid > m_prim_grid
A PrimGrid that tiles thes sub_scel into the ref_scel.