CASM
AClustersApproachtoStatisticalMechanics
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules
enum.cc
Go to the documentation of this file.
1 #include <cstring>
2 
4 #include "casm/clex/PrimClex.hh"
5 #include "casm/clex/ScelEnum.hh"
9 
10 namespace CASM {
11 
12  namespace Completer {
14 
16  bool required = false;
17 
18  m_desc.add_options()
19  ("help,h", "Print help message.")
20  ("desc",
21  po::value<std::vector<std::string> >(&m_desc_vec)->multitoken()->zero_tokens(),
22  "Print extended usage description. "
23  "Use '--desc MethodName [MethodName2...]' for detailed option description. "
24  "Partial matches of method names will be included.")
25  ("method,m", po::value<std::string>(&m_method), "Method to use: Can use number shortcuts in this option.")
26  ("min", po::value<int>(&m_min_volume)->default_value(1), "Min volume")
27  ("max", po::value<int>(&m_max_volume), "Max volume")
28  ("filter",
29  po::value<std::vector<std::string> >(&m_filter_strs)->multitoken()->value_name(ArgHandler::query()),
30  "Filter configuration enumeration so that only configurations matching a "
31  "'casm query'-type expression are recorded")
32  ("all,a",
33  po::bool_switch(&m_all_existing)->default_value(false),
34  "Enumerate configurations for all existing supercells");
35 
37  add_settings_suboption(required);
38  add_input_suboption(required);
41 
42  return;
43  }
44  }
45 
46 
47  // ///////////////////////////////////////
48  // 'enum' function for casm
49  // (add an 'if-else' statement in casm.cpp to call this)
50 
51  int enum_command(const CommandArgs &args) {
52 
53  //casm enum --settings input.json
54  //- enumerate supercells, configs, hop local configurations, etc.
55 
56  EnumeratorMap *enumerators;
57  std::unique_ptr<PrimClex> uniq_primclex;
59  Completer::EnumOption enum_opt;
60  po::variables_map &vm = enum_opt.vm();
61  const fs::path &root = args.root;
62 
63  try {
64  po::store(po::parse_command_line(args.argc, args.argv, enum_opt.desc()), vm); // can throw
65 
66  if(!vm.count("help") && !vm.count("desc")) {
67 
68  if(root.empty()) {
69  args.err_log.error("No casm project found");
70  args.err_log << std::endl;
71  return ERR_NO_PROJ;
72  }
73 
74  if(vm.count("method") != 1) {
75  args.err_log << "Error in 'casm enum'. The --method option is required." << std::endl;
76  return ERR_INVALID_ARG;
77  }
78 
79  if(vm.count("settings") + vm.count("input") == 2) {
80  args.err_log << "Error in 'casm enum'. The options --settings or --input may not both be chosen." << std::endl;
81  return ERR_INVALID_ARG;
82  }
83  }
84 
85  if(!root.empty()) {
86  primclex = &make_primclex_if_not(args, uniq_primclex);
87  enumerators = &primclex->settings().enumerator_handler().map();
88  }
89 
92  if(vm.count("help")) {
93  args.log << "\n";
94  args.log << enum_opt.desc() << std::endl;
95 
96  if(!root.empty()) {
97  args.log << "The enumeration methods are:\n\n";
98 
99  int counter = 0;
100  for(const auto &e : *enumerators) {
101  args.log << " " << counter << ") " << e.name() << std::endl;
102  ++counter;
103  }
104  }
105 
106  args.log << "\nFor complete options description, use 'casm enum --desc MethodName'.\n\n";
107 
108  return 0;
109  }
110 
111  po::notify(vm); // throws on error, so do after help in case
112  // there are any problems
113 
114  if(vm.count("desc") && enum_opt.desc_vec().size()) {
115  args.log << "\n";
116 
117  bool match = false;
118  for(const auto &in_name : enum_opt.desc_vec()) {
119  for(const auto &e : *enumerators) {
120  if(e.name().substr(0, in_name.size()) == in_name) {
121  args.log << e.help() << std::endl;
122  match = true;
123  }
124  }
125  }
126 
127  if(!match) {
128 
129  if(!root.empty()) {
130  args.log << "No match found. The enumeration methods are:\n\n";
131 
132  int counter = 0;
133  for(const auto &e : *enumerators) {
134  args.log << " " << counter << ") " << e.name() << std::endl;
135  ++counter;
136  }
137  }
138  }
139 
140  return 0;
141  }
142 
143  if(vm.count("desc")) {
144  args.log << "\n";
145  args.log << enum_opt.desc() << std::endl;
146 
147  args.log << "DESCRIPTION\n" << std::endl;
148 
149  args.log << " casm enum --settings input.json \n"
150  " casm enum --input '{...JSON...}' \n"
151  " - Input settings in JSON format to run an enumeration. The expected \n"
152  " format is: \n"
153  "\n"
154  " {\n"
155  " \"MethodName\": {\n"
156  " \"option1\" : ...,\n"
157  " \"option2\" : ...,\n"
158  " ...\n"
159  " }\n"
160  " }\n"
161  "\n";
162 
163  if(!root.empty()) {
164  args.log << "The enumeration methods are:\n\n";
165 
166  int counter = 0;
167  for(const auto &e : *enumerators) {
168  args.log << " " << counter << ") " << e.name() << std::endl;
169  ++counter;
170  }
171 
172 
173  args.log << "\nFor complete options help for a particular method, \n"
174  "use 'casm enum --desc MethodName'.\n\n";
175 
176  args.log << "Custom enumerator plugins can be added by placing source code \n"
177  "in the CASM project directory: \n"
178  " " << primclex->dir().enumerator_plugins() << " \n\n";
179  }
180 
181  return 0;
182  }
183  }
184  catch(po::error &e) {
185  args.err_log << enum_opt.desc() << std::endl;
186  args.err_log << "ERROR: " << e.what() << std::endl << std::endl;
187  return ERR_INVALID_ARG;
188  }
189  catch(std::exception &e) {
190  args.err_log << enum_opt.desc() << std::endl;
191  args.err_log << "ERROR: " << e.what() << std::endl << std::endl;
192  return ERR_UNKNOWN;
193  }
194 
195  jsonParser input;
196  if(vm.count("settings")) {
197  input = jsonParser {enum_opt.settings_path()};
198  }
199  else if(vm.count("input")) {
200  input = jsonParser::parse(enum_opt.input_str());
201  }
202  //int res = enumerators->find(enum_opt.method())->run(*primclex, input, enum_opt);
203  auto lambda = [&](const EnumInterfaceBase & e) {
204  return e.name().substr(0, enum_opt.method().size()) == enum_opt.method();
205  };
206  int count = std::count_if(enumerators->begin(), enumerators->end(), lambda);
207 
208  if(count == 1) {
209  auto it = std::find_if(enumerators->begin(), enumerators->end(), lambda);
210 
211  return it->run(*primclex, input, enum_opt);
212  }
213  else if(count < 1) {
214  // allows for number aliasing
215  try {
216  int m = stoi(enum_opt.method());
217  if(m < std::distance(enumerators->begin(), enumerators->end()) &&
218  m >= 0) {
219  auto it = enumerators->begin();
220  for(int k = 0; k < m; ++k) {
221  ++it;
222  }
223  return it->run(*primclex, input, enum_opt);
224  }
225  }
226  catch(...) {}
227  args.log << "No match found. The enumeration methods are:\n\n";
228 
229  int counter = 0;
230  for(const auto &e : *enumerators) {
231  args.log << " " << counter << ") " << e.name() << std::endl;
232  ++counter;
233  }
234  return ERR_INVALID_ARG;
235 
236  }
237  else if(count > 1) {
238  args.err_log << "Multiple matches found for --method " << std::endl;
239  return ERR_INVALID_ARG;
240  }
241  throw std::runtime_error("Unknown error in EnumCommand::run");
242 
243  };
244 
245 }
246 
Data structure holding basic CASM command info.
void add_verbosity_suboption()
Add a –verbosity suboption. Default "standard" of "none", "quiet", "standard", "verbose", "debug" or an int 0-100.
Definition: Handlers.cc:289
#define ERR_UNKNOWN
int enum_command(const CommandArgs &args)
Definition: enum.cc:51
void add_scelnames_suboption()
Add a –scelnames suboption.
Definition: Handlers.cc:346
#define ERR_INVALID_ARG
const DirectoryStructure & dir() const
Definition: PrimClex.hh:112
PrimClex * primclex
Definition: settings.cc:101
const fs::path settings_path() const
Returns the path corresponding to add_settings_suboption.
Definition: Handlers.cc:180
void add_settings_suboption(bool required=true)
Add a –settings suboption. Expects a corresponding casm format to go with it.
Definition: Handlers.cc:296
Base class for generic use of enumerators that may be accessed through the API.
Definition: Enumerator.hh:418
std::string method() const
Definition: Handlers.hh:825
Main CASM namespace.
Definition: complete.cpp:8
void initialize() override
Fill in the options descriptions accordingly.
Definition: enum.cc:15
fs::path enumerator_plugins() const
Return enumerators plugin dir.
void add_input_suboption(bool required=true)
Add a –input suboption. Expects a corresponding casm format to go with it.
Definition: Handlers.cc:311
iterator begin()
Definition: unique_map.hh:247
EnumeratorHandler & enumerator_handler()
std::string input_str() const
Returns the path corresponding to add_input_suboption.
Definition: Handlers.cc:184
const po::options_description & desc()
Get the program options, filled with the initialized values.
Definition: Handlers.cc:160
std::vector< std::string > m_desc_vec
Definition: Handlers.hh:849
static std::string query()
Get value_type string for query completion.
Definition: Handlers.cc:51
po::options_description m_desc
Boost program options. All the derived classes have them, but will fill them up themselves.
Definition: Handlers.hh:126
ProjectSettings & settings()
Definition: PrimClex.hh:116
const std::vector< std::string > & desc_vec() const
Definition: Handlers.hh:821
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:52
void add_confignames_suboption()
Add a –confignames suboption.
Definition: Handlers.cc:365
po::variables_map & vm()
Get the variables map.
Definition: Handlers.cc:145
PrimClex & make_primclex_if_not(const CommandArgs &args, std::unique_ptr< PrimClex > &uniq_primclex)
If !_primclex, construct new PrimClex stored in uniq_primclex, then return reference to existing or c...
static jsonParser parse(const std::string &str)
Construct a jsonParser from a string containing JSON data.
Definition: jsonParser.hh:312
std::map wrapper to enforce a 1-1 ValueType->KeyType relationship
Definition: unique_map.hh:141
void error(const std::string &what)
Definition: Log.hh:86
std::vector< std::string > m_filter_strs
Definition: Handlers.hh:855
#define ERR_NO_PROJ