19 m_site_swaps(supercell()),
21 m_all_correlations(settings.all_correlations()),
22 m_event(primclex.composition_axes().components().size(), _clexulator().corr_size()) {
35 _log() <<
"formation_energy cluster expansion: " <<
desc.name <<
"\n";
36 _log() << std::setw(16) <<
"property: " <<
desc.property <<
"\n";
37 _log() << std::setw(16) <<
"calctype: " <<
desc.calctype <<
"\n";
38 _log() << std::setw(16) <<
"ref: " <<
desc.ref <<
"\n";
39 _log() << std::setw(16) <<
"bset: " <<
desc.bset <<
"\n";
40 _log() << std::setw(16) <<
"eci: " <<
desc.eci <<
"\n";
43 _log() <<
"\nSampling: \n";
44 _log() << std::setw(24) <<
"quantity" << std::setw(24) <<
"requested_precision" <<
"\n";
46 _log() << std::setw(24) << it->first;
47 if(it->second->must_converge()) {
48 _log() << std::setw(24) << it->second->requested_precision() << std::endl;
51 _log() << std::setw(24) <<
"none" << std::endl;
54 _log() <<
"\nautomatic convergence mode?: " << std::boolalpha <<
must_converge() << std::endl;
74 _log() << new_conditions << std::endl << std::endl;
88 _log() << msg <<
"\n";
105 _log() << new_conditions << std::endl;
116 if(configname ==
"default") {
119 else if(configname ==
"auto") {
120 std::tie(configdof, configname) =
_auto_motif(new_conditions);
122 else if(configname ==
"restricted_auto") {
138 throw std::runtime_error(
"Error: Must specify motif \"configname\" or \"configdof\"");
144 return std::make_pair(configdof, configname);
150 const std::string &msg) {
152 _log() << new_conditions << std::endl << std::endl;
158 _log() << msg <<
"\n";
188 int new_occupant = possible_mutation[
_mtrand().randInt(possible_mutation.size() - 1)];
194 _log() <<
" Mutating site (linear index): " << mutating_site <<
"\n"
195 <<
" Mutating site (b, i, j, k): " <<
supercell().
uccoord(mutating_site) <<
"\n"
196 <<
" Current occupant: " << current_occupant <<
" (" << site_occ[current_occupant].name <<
")\n"
197 <<
" Proposed occupant: " << new_occupant <<
" (" << site_occ[new_occupant].name <<
")\n\n"
217 <<
" d(N): " <<
m_event.
dN().transpose() <<
"\n"
218 <<
" dx_dn: \n" << Mpinv <<
"\n"
219 <<
" param_chem_pot.transpose() * dx_dn: \n" << param_chem_pot.transpose()*Mpinv <<
"\n"
220 <<
" param_chem_pot.transpose() * dx_dn * dN: " << param_chem_pot.transpose()*Mpinv *
m_event.
dN().cast<
double>() <<
"\n"
221 <<
" d(Nunit * param_chem_pot * x): " << exchange_chem_pot(new_species, curr_species) <<
"\n"
223 <<
" d(Epot): " <<
m_event.
dEf() - exchange_chem_pot(new_species, curr_species) <<
"\n"
235 if(event.
dEpot() < 0.0) {
239 _log() <<
"Probability to accept: 1.0\n" << std::endl;
244 double rand =
_mtrand().rand53();
249 _log() <<
"Probability to accept: " << prob <<
"\n"
250 <<
"Random number: " << rand <<
"\n" << std::endl;
325 auto less = [&](
const double & A,
const double & B) {
329 std::map<double, unsigned long, decltype(less)> hist(less);
341 int sublat = site_exch.
sublat()[exch_ind];
342 int current_occupant = config_dof.
occ(mutating_site);
345 const auto &possible = site_exch.
possible_swap()[sublat][current_occupant];
346 for(
auto new_occ_it = possible.begin(); new_occ_it != possible.end(); ++new_occ_it) {
348 _update_deltas(event, mutating_site, sublat, current_occupant, *new_occ_it);
351 double dpot_nrg =
event.dEpot();
355 err_log <<
" Defect lowered the potential energy. Your motif configuration "
356 <<
"is not the 0K ground state.\n" << std::endl;
357 throw std::runtime_error(
"Error calculating low temperature expansion. Not in the ground state.");
361 auto it = hist.find(dpot_nrg);
362 if(it == hist.end()) {
371 _log().
results(
"Ground state and point defect potential energy details");
376 _log() << std::setw(16) <<
"N/unitcell" <<
" "
377 << std::setw(16) <<
"dPE" <<
" "
378 << std::setw(24) <<
"N*exp(-dPE/kT)" <<
" "
379 << std::setw(16) <<
"dphi" <<
" "
380 << std::setw(16) <<
"phi" << std::endl;
385 for(
auto it = hist.rbegin(); it != hist.rend(); ++it) {
391 _log() << std::setw(16) <<
"(gs)" <<
" ";
394 _log() << std::setw(16) << std::setprecision(8) << (1.0 * it->second) /
supercell().
volume() <<
" ";
396 _log() << std::setw(16) << std::setprecision(8) << it->first <<
" "
397 << std::setw(24) << std::setprecision(8) << it->second *exp(-it->first *
m_condition.
beta()) <<
" "
398 << std::setw(16) << std::setprecision(8) << phi - phi_prev <<
" "
399 << std::setw(16) << std::setprecision(8) <<
potential_energy() - phi << std::endl;
403 _log() <<
"phi_LTE(1): " << std::setprecision(12) <<
potential_energy() - phi << std::endl << std::endl;
435 int current_occupant,
438 bool all_correlations)
const {
449 if(all_correlations) {
453 event.
dCorr().data());
457 auto end = begin +
_eci().
index().size();
461 event.
dCorr().data(),
472 if(all_correlations) {
485 auto end = begin +
_eci().
index().size();
499 event.dCorr() = after - before;
513 std::string colheader,
514 bool all_correlations)
const {
517 _log() << std::setw(12) <<
"i"
518 << std::setw(16) <<
"ECI"
519 << std::setw(16) << colheader
522 for(
int i = 0; i < corr.size(); ++i) {
525 bool calculated =
true;
527 if(index !=
_eci().index().size()) {
530 if(!all_correlations && index ==
_eci().index().size()) {
534 _log() << std::setw(12) << i
535 << std::setw(16) << std::setprecision(8) <<
eci;
537 _log() << std::setw(16) << std::setprecision(8) << corr[i];
540 _log() << std::setw(16) <<
"unknown";
552 int current_occupant,
553 int new_occupant)
const {
557 event.occupational_change().set(mutating_site, sublat, new_occupant);
561 for(
int i = 0; i <
event.dN().size(); ++i) {
566 event.set_dN(curr_species, -1);
567 event.set_dN(new_species, 1);
576 event.set_dEf(
_eci() * event.
dCorr().data());
612 _log() <<
"Semi-grand canonical ensemble: \n"
613 <<
" Thermodynamic potential (per unitcell), phi = -kT*ln(Z)/N \n"
614 <<
" Partition function, Z = sum_i exp(-N*potential_energy_i/kT) \n"
615 <<
" composition, comp_n = origin + M * comp_x \n"
616 <<
" parametric chemical potential, param_chem_pot = M.transpose() * chem_pot \n"
617 <<
" potential_energy (per unitcell) = formation_energy - param_chem_pot*comp_x \n\n"
620 <<
"M:\n" << M <<
"\n"
621 <<
"origin: " << origin.transpose() <<
"\n"
622 <<
"comp_n: " <<
comp_n().transpose() <<
"\n"
623 <<
"comp_x: " << comp_x.transpose() <<
"\n"
624 <<
"param_chem_pot: " << param_chem_pot.transpose() <<
"\n"
625 <<
" param_chem_pot*comp_x: " << param_chem_pot.dot(comp_x) <<
"\n"
627 <<
" formation_energy - param_chem_pot*comp_x: " <<
formation_energy() - param_chem_pot.dot(comp_x) <<
"\n"
636 _log() <<
"motif configname: default\n";
637 _log() <<
"using configuration with default occupation...\n" << std::endl;
647 _log() <<
"motif configname: auto\n";
648 _log() <<
"searching for minimum potential energy motif..." << std::endl;
651 auto compare = [&](
double A,
double B) {
655 _log() <<
"using conditions: \n";
656 _log() << cond << std::endl;
658 std::multimap<double, const Configuration *, decltype(compare)> configmap(
compare);
663 const Configuration &min_config = *(configmap.begin()->second);
664 double min_potential_energy = configmap.begin()->first;
665 auto eq_range = configmap.equal_range(min_potential_energy);
667 if(std::distance(eq_range.first, eq_range.second) > 1) {
668 _log() <<
"Warning: Found degenerate ground states with potential energy: "
669 << std::setprecision(8) << min_potential_energy << std::endl;
670 for(
auto it = eq_range.first; it != eq_range.second; ++it) {
671 _log() <<
" " << it->second->name() << std::endl;
673 _log() <<
"using: " << min_config.
name() <<
"\n" << std::endl;
676 _log() <<
"using: " << min_config.
name() <<
" with potential energy: "
677 << std::setprecision(8) << min_potential_energy <<
"\n" << std::endl;
680 return std::make_pair(
689 _log() <<
"motif configname: restricted_auto\n";
690 _log() <<
"searching for minimum potential energy motif..." << std::endl;
693 auto compare = [&](
double A,
double B) {
697 _log() <<
"using conditions: \n";
698 _log() << cond << std::endl;
700 std::multimap<double, const Configuration *, decltype(compare)> configmap(
compare);
708 auto begin = g.
begin();
712 std::vector<decltype(configmap)::const_iterator> allowed;
715 auto next_it = configmap.begin();
716 while(next_it != configmap.end()) {
717 auto eq_range = configmap.equal_range(next_it->first);
720 for(
auto it = eq_range.first; it != eq_range.second; ++it) {
721 const Lattice &motif_lat = it->second->get_supercell().get_real_super_lattice();
723 allowed.push_back(it);
733 next_it = eq_range.second;
736 if(!allowed.size()) {
737 _log() <<
"Found no enumerated configurations that will fill the supercell\n";
738 _log() <<
"using configuration with default occupation..." << std::endl;
739 return std::make_pair(
744 if(allowed.size() > 1) {
745 _log() <<
"Warning: Found degenerate allowed configurations with potential energy: "
746 << std::setprecision(8) << allowed[0]->first << std::endl;
747 for(
auto it = allowed.begin(); it != allowed.end(); ++it) {
748 _log() <<
" " << (*it)->second->name() << std::endl;
750 _log() <<
"using: " << allowed[0]->second->name() <<
"\n" << std::endl;
753 _log() <<
"using: " << allowed[0]->second->name() <<
" with potential energy: "
754 << std::setprecision(8) << allowed[0]->first <<
"\n" << std::endl;
757 return std::make_pair(
758 allowed[0]->second->fill_supercell(
_supercell(), g).configdof(),
759 allowed[0]->second->name());
766 _log() <<
"motif configname: " << configname <<
"\n";
767 _log() <<
"using configation: " << configname <<
"\n" << std::endl;
Eigen::MatrixXd dparam_dmol() const
Return the matrix Mij = dx_i/dn_j.
void write_results(const MonteSettings &settings, const MonteType &mc, Log &_log)
Will create new file or append to existing file results of the latest run.
Configuration fill_supercell(Supercell &scel, const SymOp &op) const
Fills supercell 'scel' with reoriented configuration, as if by apply(op,*this)
void clear_samples()
Clear all data from all samplers.
OccMod & occupational_change()
Access the occupational modification for this event.
const SuperNeighborList & nlist() const
const Access the SuperNeighborList via pointer stored by 'set_nlist'
void set_conditions(const CondType &new_conditions)
Set conditions and clear previously collected data.
void write_conditions_json(const MonteSettings &settings, const MonteType &mc, Index cond_index, Log &_log)
Write conditions to conditions.cond_index directory.
Eigen::VectorXd param_chem_pot() const
parametric chemical potential: dg/dcomp_x
VectorPropertyMap & _vector_properties()
const Access vector properties map
void results(const std::string &what)
Eigen::MatrixXd dmol_dparam() const
Return the matrix Mij = dn_i/dx_j.
Eigen::VectorXd origin() const
The mol composition of the parameteric composition axes origin.
size_type site_index() const
Returns the linear index corresponding to site in ConfigDoF.
double dEf() const
Return change in (extensive) formation energy associated with this event.
Eigen::VectorXd param_composition(const Eigen::VectorXd &n) const
Convert number of mol per prim, 'n' to parametric composition 'x'.
Eigen::VectorXd & _corr()
Correlations, normalized per primitive cell.
bool compare(const T &A, const T &B, double tol)
Floating point comparison with tol, return A < B.
ConfigDoF & _configdof() const
Access current microstate.
Data structure for storing information regarding a proposed grand canonical Monte Carlo event...
const SiteExchanger m_site_swaps
Keeps track of what sites can change to what.
fs::path get_path() const
Return casm project directory path.
const Configuration & config() const
const Access current microstate
const Eigen::VectorXd & comp_n() const
Number of atoms of each type, normalized per primitive cell.
Correlation correlations(const ConfigDoF &configdof, const Supercell &scel, Clexulator &clexulator)
Returns correlations using 'clexulator'. Supercell needs a correctly populated neighbor list...
const ConfigDoF & configdof() const
const Access the DoF
const ECIContainer & _eci() const
const Lattice & get_real_super_lattice() const
Index find_index(Iterator begin, Iterator end, const T &value)
Equivalent to std::distance(begin, std::find(begin, end, value))
bool check(const EventType &event)
Based on a random number, decide if the change in energy from the proposed event is low enough to be ...
ENSEMBLE
Monte Carlo ensemble type.
const ConfigDoF & configdof() const
const Access current microstate
double * m_formation_energy
Formation energy, normalized per primitive cell.
const ClexDescription & desc() const
void reset(const ConfigDoF &dof)
Set current microstate and clear samplers.
EventType m_event
Event to propose, check, accept/reject:
Eigen::VectorXd comp(const Configuration &config)
Returns parametric composition, as calculated using PrimClex::param_comp.
void _print_correlations(const Eigen::VectorXd &corr, std::string title, std::string colheader, bool all_correlations) const
Print correlations to _log()
double temperature() const
const std::vector< std::vector< std::vector< int > > > & possible_swap() const
For a given sublattice with a particular occupant, show what OTHER occupants it could be...
void set(const std::string &what)
void reject(const EventType &event)
Nothing needs to be done to reject a GrandCanonicalEvent.
bool m_all_correlations
If true, calculate all correlations; if false, calculate correlations with non-zero eci...
config_iterator config_end()
Configuration iterator: end.
bool debug() const
return true if running in debug mode
Eigen::MatrixXd exchange_chem_pot() const
matrix of exchange chemical potential, M(new, curr) = chem_pot(new) - chem_pot(curr) ...
Eigen::VectorXd & _comp_n()
Number of atoms of each type, normalized per primitive cell.
Eigen::VectorXd & dCorr()
Access the changes in (extensive) correlations associated with this event.
void write_results(Index cond_index) const
Write results to files.
Eigen::VectorXd * m_corr
Correlations, normalized per primitive cell.
void calc_point_corr(int b_index, double *corr_begin) const
Calculate point correlations about basis site 'b_index'.
const std::vector< double > & value() const
const Access ECI values
const std::vector< int > & sublat() const
sublat()[i] is the sublattice index for site variable_sites()[i]
SymGroup is a collection of symmetry operations that satisfy the group property The symmetry operatio...
Eigen::VectorXd comp_n(const ConfigDoF &configdof, const Supercell &scel)
Returns comp_n, the number of each molecule per primitive cell, ordered as Structure::get_struc_molec...
void _update_properties()
Calculate properties given current conditions.
void construct(const std::string &what)
void custom(const std::string &what)
void set_configdof(const ConfigDoF &configdof, const std::string &msg="")
Set configdof and clear previously collected data.
double formation_energy(const Configuration &config)
Returns the formation energy, normalized per unit cell.
void set_config_occ(const int *_occ_ptr)
Set pointer to data structure containing occupation variables.
const T & to_value() const
Returns the value the variable on the site being modified will change to.
double lte_grand_canonical_free_energy() const
Calculate the single spin flip low temperature expansion of the grand canonical potential.
double & _formation_energy()
Formation energy, normalized per primitive cell.
bool is_motif_configname() const
Returns true if configname of configuration to use as starting motif has been specified.
std::string motif_configname() const
Configname of configuration to use as starting motif.
static const int standard
const MasterSymGroup & factor_group() const
const double & potential_energy() const
Potential energy, normalized per primitive cell.
void set_nlist()
Set a pointer to the SuperNeighborList once it is ready.
double & _potential_energy()
Potential energy, normalized per primitive cell.
const std::vector< Index > & variable_sites() const
std::vector of indices into occupation array of ConfigDoF that have more than one allowed occupant ...
bool is_motif_configdof() const
Returns true if path to ConfigDoF file to use as starting motif has been specified.
const Supercell & supercell() const
const Access the Supercell that *this is based on
void write_trajectory(const MonteSettings &settings, const MonteCarlo &mc, Index cond_index, Log &_log)
Will create (and possibly overwrite) new file with all observations from run with conditions...
const EventType & propose()
Propose a new event, calculate delta properties, and return reference to it.
void calc_delta_point_corr(int b_index, int occ_i, int occ_f, double *corr_begin) const
Calculate the change in point correlations due to changing an occupant.
EigenIndex Index
For long integer indexing:
Index volume() const
Return number of primitive cells that fit inside of *this.
A container class for the different degrees of freedom a Configuration might have.
void calculate(const std::string &what)
const Eigen::VectorXd & corr() const
Correlations, normalized per primitive cell.
Array< CoordType > basis
Lattice vectors that specifies periodicity of the crystal.
const PrimClex & primclex() const
const Access the PrimClex that *this is based on
std::pair< ConfigDoF, std::string > _restricted_auto_motif(const GrandCanonicalConditions &cond) const
Generate minimum potential energy ConfigDoF for this supercell.
Eigen::VectorXd & _vector_property(std::string property_name)
const Access a particular vector property
const std::vector< size_type > & index() const
const Access orbit indices of ECI values
PrimClex is the top-level data structure for a CASM project.
UnitCellCoord uccoord(Index i) const
void write_observations(const MonteSettings &settings, const MonteCarlo &mc, Index cond_index, Log &_log)
Will create (and possibly overwrite) new file with all observations from run with conditions...
const CompositionConverter & composition_axes() const
const Access CompositionConverter object
bool m_use_deltas
If the supercell is large enough, calculate delta correlations directly.
void calc_restricted_point_corr(int b_index, double *corr_begin, size_type const *ind_list_begin, size_type const *ind_list_end) const
Calculate select point correlations about basis site 'b_index'.
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") ...
Clexulator & _clexulator() const
void calc_restricted_delta_point_corr(int b_index, int occ_i, int occ_f, double *corr_begin, size_type const *ind_list_begin, size_type const *ind_list_end) const
Calculate the change in select point correlations due to changing an occupant.
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Eigen::VectorXd * m_comp_n
Number of atoms of each type, normalized per primitive cell.
Interface base class for all types of Monte Carlo simulations (not meant to be used polymorphically) ...
std::pair< ConfigDoF, std::string > _auto_motif(const GrandCanonicalConditions &cond) const
Generate minimum potential energy ConfigDoF.
std::pair< ConfigDoF, std::string > set_state(const GrandCanonicalConditions &new_conditions, const GrandCanonicalSettings &settings)
Set configdof and conditions and clear previously collected data.
double dEpot() const
Return change in (extensive) potential energy, dEpot = dEf - sum_i(Nunit * param_chem_pot_i * dcomp_x...
void accept(const EventType &event)
Accept proposed event. Change configuration accordingly and update energies etc.
const double & formation_energy() const
Formation energy, normalized per primitive cell.
ConfigDoF _default_motif() const
Generate supercell filling ConfigDoF from default configuration.
ConfigDoF motif_configdof() const
ConfigDoF to use as starting motif.
const CondType & conditions() const
Return current conditions.
Supercell & _supercell() const
Access the Supercell that *this is based on.
static const Monte::ENSEMBLE ensemble
bool overlaps() const
Returns true if periodic images of the neighbor list overlap.
bool must_converge() const
Return true if convergence is requested.
const std::vector< std::vector< int > > & sublat_to_mol() const
Map the integer values from the possible swaps or variable sites arrays into actual species...
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...
void _update_deltas(GrandCanonicalEvent &event, Index mutating_site, int sublat, int current_occupant, int new_occupant) const
Calculate delta properties for an event and update the event with those properties.
double & _scalar_property(std::string property_name)
Access a particular scalar property.
void _set_dCorr(GrandCanonicalEvent &event, Index mutating_site, int sublat, int current_occupant, int new_occupant, bool use_deltas, bool all_correlations) const
Calculate delta correlations for an event.
void error(const std::string &what)
void set_nlist(const long int *_nlist_ptr)
Set pointer to neighbor list.
Index steps_per_pass() const
Return number of steps per pass. Equals number of sites with variable occupation. ...
double * m_potential_energy
Potential energy, normalized per primitive cell.
const Eigen::Matrix3i & get_transf_mat() const
ConfigDoF _configname_motif(const std::string &configname) const
Generate supercell filling ConfigDoF from configuration.
ScalarPropertyMap & _scalar_properties()
Access scalar properties map.
Clex m_formation_energy_clex
Holds Clexulator and ECI references.
Eigen::VectorXd correlations_vec(const ConfigDoF &configdof, const Supercell &scel, Clexulator &clexulator)
Returns correlations using 'clexulator'. Supercell needs a correctly populated neighbor list...
const SamplerMap & samplers() const
const Access sampler map
fs::path motif_configdof_path() const
Path to ConfigDoF file to use as starting motif.
const MonteSettings & settings() const
const Access settings used for construction
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
GrandCanonical(PrimClex &primclex, const SettingsType &settings, Log &_log)
Constructs a GrandCanonical object and prepares it for running based on MonteSettings.
GrandCanonicalConditions m_condition
Conditions (T, mu). Initially determined by m_settings, but can be changed halfway through the run...
A Configuration represents the values of all degrees of freedom in a Supercell.
const Structure & get_prim() const
const Access to primitive Structure
Eigen::VectorXl & dN()
Access change in number of species per supercell. Order as in CompositionConverter::components().