CASM  1.1.0
A Clusters Approach to Statistical Mechanics
bset.cc
Go to the documentation of this file.
1 #include "casm/app/bset.hh"
2 
3 #include <boost/filesystem.hpp>
4 
9 #include "casm/casm_io/Log.hh"
12 #include "casm/clex/Clexulator.hh"
13 #include "casm/clex/PrimClex.hh"
18 
19 namespace CASM {
20 
21 namespace Completer {
22 
24 
28 
29  m_desc.add_options()(
30  //
31  "update,u", "Update basis set")(
32  //
33  "orbits", "Pretty-print orbit prototypes")(
34  //
35  "functions", "Pretty-print prototype cluster functions for each orbit")(
36  //
37  "clusters", "Pretty-print all clusters")(
38  //
39  "clex", po::value<std::string>()->value_name(ArgHandler::clex()),
40  "Select a non-default basis set to print by specifying the name of a "
41  "cluster expansion using the basis set")(
42  //
43  "print-invariant-group",
44  "Use with --orbits or --clusters to print the group that leaves clusters "
45  "invariant.")(
46  //
47  "print-equivalence-map",
48  "Use with --clusters to print the orbit equivalence map (sets of "
49  "symmetry operations that map the prototype cluster onto an equivalent "
50  "cluster / cosets of the invariant group).")(
51  //
52  "align",
53  "Use with --functions to print aligned functions ready to copy and paste "
54  "into a latex document")(
55  //
56  "no-compile",
57  "Use with --update to generate basis.json, clust.json, and "
58  "the basis function source code but not compile it.")(
59  //
60  "only-compile",
61  "Use with --update to keep the existing basis.json, clust.json, and "
62  "basis function source code but to re-compile it if the .so and .o files "
63  "do not exist.")(
64  //
65  "force,f", "Force overwrite");
66  return;
67 }
68 } // namespace Completer
69 
70 namespace bset_impl {
71 
72 // might be useful for other casm commands...
73 template <typename CommandType>
74 ClexDescription get_clex_description(const CommandType &cmd) {
75  const auto &vm = cmd.vm();
76  const auto &primclex = cmd.primclex();
77 
78  if (!vm.count("clex")) {
79  return primclex.settings().default_clex();
80  } else {
81  const auto &set = primclex.settings();
82  auto it =
83  set.cluster_expansions().find(vm["clex"].template as<std::string>());
84  if (it == set.cluster_expansions().end()) {
85  throw std::runtime_error{"Invalid --clex value: " +
86  vm["clex"].template as<std::string>()};
87  }
88  return it->second;
89  }
90 }
91 
93 bool any_existing_files(const std::string &bset, const BsetCommand &cmd) {
94  const DirectoryStructure &dir = cmd.primclex().dir();
95  const ProjectSettings &set = cmd.primclex().settings();
96 
97  bool _any_existing_files = false;
98  for (const auto &p : dir.bset_data(set.project_name(), bset)) {
99  if (fs::exists(p)) {
100  if (!_any_existing_files) {
101  log().custom("Found existing files");
102  _any_existing_files = true;
103  }
104  log() << "found: " << p << "\n";
105  }
106  }
107  return _any_existing_files;
108 }
109 
110 void check_force(const std::string &bset, const BsetCommand &cmd) {
111  const auto &vm = cmd.vm();
112 
114  if (any_existing_files(bset, cmd)) {
115  if (vm.count("force")) {
116  log() << "Using --force. Will overwrite existing files.\n" << std::endl;
117  } else {
118  throw CASM::runtime_error{
119  "Exiting due to existing files. Use --force to force overwrite.",
121  }
122  }
123 }
124 
126 void update_bset(const BsetCommand &cmd) {
127  const auto &vm = cmd.vm();
128  const auto &primclex = cmd.primclex();
129 
130  auto basis_set_name = get_clex_description(cmd).bset;
131 
132  // force compilation by default, opt out with --no-compile, or only compile
133  // with --only-compile
134  if (vm.count("only-compile")) {
135  auto clexulator = primclex.clexulator(basis_set_name);
136  return;
137  }
138 
139  if (!primclex.has_basis_set_specs(basis_set_name)) {
140  auto bspecs_path = primclex.dir().bspecs(basis_set_name);
141  throw CASM::runtime_error{
142  "'bspecs.json' file not found at: " + bspecs_path.string(),
144  }
145 
146  check_force(basis_set_name, cmd);
147 
148  try {
150  primclex.shared_prim(), primclex.settings(), basis_set_name,
151  primclex.basis_set_specs(basis_set_name), primclex.nlist());
152  } catch (std::exception &e) {
154  }
155 
156  // force compilation by default, opt out with --no-compile
157  if (!vm.count("no-compile")) {
158  auto clexulator = primclex.clexulator(basis_set_name);
159  }
160 }
161 
164 template <typename PrinterType>
166  public:
168 
169  template <typename OrbitVecType>
170  void operator()(OrbitVecType const &orbits) const;
171 
172  private:
174  PrinterType m_printer;
175 };
176 
179 void print_bset(const BsetCommand &cmd) {
180  auto const &vm = cmd.vm();
181  Log &log = CASM::log();
182  std::string basis_set_name = get_clex_description(cmd).bset;
183  auto const &primclex = cmd.primclex();
184 
185  auto const &shared_prim = primclex.shared_prim();
186  auto const &basis_set_specs = primclex.basis_set_specs(basis_set_name);
187  auto const &cluster_specs = *basis_set_specs.cluster_specs;
188 
189  std::vector<IntegralCluster> prototypes;
190  jsonParser clust_json{primclex.dir().clust(basis_set_name)};
191  read_clust(std::back_inserter(prototypes), clust_json, *shared_prim);
192 
193  OrbitPrinterOptions orbit_printer_options;
194  orbit_printer_options.coord_type = cmd.opt().coordtype_enum();
195  orbit_printer_options.indent_space = 4;
196  if (orbit_printer_options.coord_type != INTEGRAL) {
197  orbit_printer_options.delim = 0;
198  }
199  if (vm.count("print-invariant-group")) {
200  orbit_printer_options.print_invariant_group = true;
201  }
202  if (vm.count("print-equivalence-map")) {
203  orbit_printer_options.print_equivalence_map = true;
204  }
205 
206  if (vm.count("orbits")) {
207  OrbitPrinterAdapter<ProtoSitesPrinter> printer{log, orbit_printer_options};
208  for_all_orbits(cluster_specs, prototypes, printer);
209  }
210  if (vm.count("clusters")) {
211  OrbitPrinterAdapter<FullSitesPrinter> printer{log, orbit_printer_options};
212  for_all_orbits(cluster_specs, prototypes, printer);
213  }
214  if (vm.count("functions")) {
215  bool align = vm.count("align");
216  if (align) {
217  orbit_printer_options.itemize_orbits = true;
218  }
219  ClexBasisFunctionPrinter printer{log, shared_prim, basis_set_specs, align,
220  orbit_printer_options};
221  for_all_orbits(cluster_specs, prototypes, printer);
222  }
223 }
224 } // namespace bset_impl
225 
226 const std::string BsetCommand::name = "bset";
227 
229  : APICommand<Completer::BsetOption>(_args, _opt) {}
230 
232 
234  if (!in_project()) {
235  err_log().error("No casm project found");
236  err_log() << std::endl;
237  return ERR_NO_PROJ;
238  }
239 
240  if (vm().count("update")) {
241  return 0;
242  } else if (vm().count("orbits") || vm().count("clusters") ||
243  vm().count("functions")) {
244  return 0;
245  } else {
246  err_log() << "Error in 'casm bset'. Choose --update or one or more of "
247  "--orbits, --clusters, ----functions."
248  << std::endl;
249  return ERR_INVALID_ARG;
250  }
251 
252  return 0;
253 }
254 
255 int BsetCommand::help() const {
256  log() << opt().desc() << std::endl;
257  return 0;
258 }
259 
260 int BsetCommand::desc() const {
261  log() << "\n";
262  log() << opt().desc() << std::endl;
263 
264  log().indent() << "DESCRIPTION\n" << std::endl;
265  log().increase_indent();
266  log().indent() << "Generate and inspect cluster basis functions. A "
267  "bspecs.json file should be available at\n";
268 
269  log().increase_indent();
270  log().indent() << "$ROOT/basis_set/$current_bset/bspecs.json\n";
271  log().decrease_indent();
272 
273  log().indent() << std::endl;
274  log().indent() << "For a description of the bspecs.json file use one of:"
275  << std::endl;
276  log().increase_indent();
277  log() << "'casm format --bpsecs'" << std::endl;
278  log() << "'casm format --local_bpsecs'" << std::endl;
279  log().decrease_indent();
280 
281  log().decrease_indent();
282  log() << std::endl;
283 
284  return 0;
285 }
286 
287 int BsetCommand::run() const {
288  const auto &vm = this->vm();
289 
290  try {
291  if (vm.count("update")) {
292  bset_impl::update_bset(*this);
293  } else if (vm.count("orbits") || vm.count("clusters") ||
294  vm.count("functions")) {
295  bset_impl::print_bset(*this);
296  } else {
297  err_log() << "Error in 'casm bset'. Choose --update or one or more of "
298  "--orbits, --clusters, ----functions."
299  << std::endl;
300  return ERR_INVALID_ARG;
301  }
302  } catch (CASM::runtime_error &e) {
303  err_log() << e.what() << std::endl;
304  return e.code();
305  } catch (std::exception &e) {
306  err_log() << e.what() << std::endl;
307  return ERR_UNKNOWN;
308  }
309 
310  return 0;
311 }
312 
313 namespace bset_impl {
314 
315 template <typename PrinterType>
317  OrbitPrinterOptions _opt)
318  : m_log(_log), m_printer(_opt) {}
319 
320 template <typename PrinterType>
321 template <typename OrbitVecType>
323  OrbitVecType const &orbits) const {
324  print_clust(orbits.begin(), orbits.end(), m_log, m_printer);
325 }
326 
327 } // namespace bset_impl
328 } // namespace CASM
std::shared_ptr< Structure const > shared_prim
#define ERR_MISSING_INPUT_FILE
Definition: errors.hh:19
#define ERR_NO_PROJ
Definition: errors.hh:13
#define ERR_UNKNOWN
Definition: errors.hh:10
#define ERR_EXISTING_FILE
Definition: errors.hh:22
#define ERR_INVALID_ARG
Definition: errors.hh:7
#define ERR_INVALID_INPUT_FILE
Definition: errors.hh:16
PrimClex & primclex() const
Definition: APICommand.cc:17
bool in_project() const
Definition: APICommand.cc:15
const OptionType & opt() const
Definition: APICommand.hh:61
const po::variables_map & vm() const
Definition: APICommand.hh:59
'casm enum' implementation
Definition: bset.hh:12
int help() const override
Definition: bset.cc:255
BsetCommand(const CommandArgs &_args, Completer::BsetOption &_opt)
Definition: bset.cc:228
int run() const override
Definition: bset.cc:287
int vm_count_check() const override
Definition: bset.cc:233
static const std::string name
Definition: bset.hh:14
int desc() const override
Definition: bset.cc:260
static std::string clex()
Get value_type string for clex mode completion.
Definition: Handlers.cc:80
COORD_TYPE coordtype_enum() const
Return the coordinate type recasted as the CASM defined enum.
Definition: Handlers.cc:398
void initialize() override
Fill in the options descriptions accordingly.
Definition: bset.cc:25
const po::options_description & desc()
Get the program options, filled with the initialized values.
Definition: Handlers.cc:321
void add_help_suboption()
Add a plain –help and –desc suboptions.
Definition: Handlers.cc:561
po::options_description m_desc
Definition: Handlers.hh:260
void add_coordtype_suboption()
Add a –coord suboption to specify FRAC or CART.
Definition: Handlers.cc:725
Specification of CASM project directory structure.
Definition: Log.hh:48
void custom(const std::string &what)
Definition: Log.hh:139
Log & indent()
Definition: Log.hh:289
void increase_indent()
Definition: Log.hh:277
void error(const std::string &what)
Definition: Log.hh:129
void decrease_indent()
Definition: Log.hh:279
void operator()(OrbitVecType const &orbits) const
Definition: bset.cc:322
OrbitPrinterAdapter(Log &_log, OrbitPrinterOptions _opt)
Definition: bset.cc:316
int code() const
Definition: errors.hh:41
ProjectSettings & settings()
Definition: PrimClex.cc:224
const DirectoryStructure & dir() const
Access DirectoryStructure object. Throw if not set.
Definition: PrimClex.cc:230
void write_basis_set_data(std::shared_ptr< Structure const > shared_prim, ProjectSettings const &settings, std::string const &basis_set_name, ClexBasisSpecs const &basis_set_specs, PrimNeighborList &prim_neighbor_list)
Definition: PrimClex.cc:504
void update_bset(const BsetCommand &cmd)
Implements casm bset --update
Definition: bset.cc:126
void check_force(const std::string &bset, const BsetCommand &cmd)
Definition: bset.cc:110
bool any_existing_files(const std::string &bset, const BsetCommand &cmd)
Check for generated bset files, print messages when found to CASM::log()
Definition: bset.cc:93
void print_bset(const BsetCommand &cmd)
Definition: bset.cc:179
ClexDescription get_clex_description(const CommandType &cmd)
Definition: bset.cc:74
Main CASM namespace.
Definition: APICommand.hh:8
void for_all_orbits(ClusterSpecs const &cluster_specs, std::vector< IntegralCluster > const &generating_elements, FunctorType const &f)
void print_clust(ClusterOrbitIterator begin, ClusterOrbitIterator end, Log &out, OrbitPrinter printer)
Print IntegralCluster orbits.
Log & log()
Definition: Log.hh:424
const COORD_TYPE INTEGRAL
Definition: enum.hh:10
ClusterOutputIterator read_clust(ClusterOutputIterator result, const jsonParser &json, const Structure &prim, const SymGroup &generating_grp, const SymCompareType &sym_compare)
Read JSON containing Orbit<SymCompareType> prototypes.
Log & err_log()
Definition: Log.hh:426
PrimClex * primclex
Definition: settings.cc:135
DirectoryStructure const & dir
Definition: settings.cc:136
ProjectSettings & set
Definition: settings.cc:137
pair_type bset
Definition: settings.cc:145
Specifies a particular cluster expansion.
Data structure holding basic CASM command info.