24 if(vec.size() != names.size()) {
25 std::cerr <<
"Error constructing ChemicalReferenceState: Number of species != vec.size()\n";
26 std::cerr <<
" get_struc_molecule_name: " << names <<
"\n";
27 std::cerr <<
" n(config): " << vec << std::endl;
28 throw std::runtime_error(
"Error constructing ChemicalReferenceState: Number of species != vec.size()");
31 for(
int i = 0; i < names.size(); ++i) {
44 const std::string
ChemicalReference::Desc =
"Returns a reference energy as interpolated via a composition-energy hyperplane.";
49 const std::vector<std::string> &ref_config) {
51 for(
int i = 0; i < ref_config.size(); ++i) {
60 for(
int i = 0; i < N.cols(); i++) {
61 N.col(i) = _N.col(i + 1) - _N.col(0);
68 auto Qr = N.transpose().fullPivHouseholderQr();
69 Qr.setThreshold(lin_alg_tol);
75 void _prune_ref_config(
const PrimClex &primclex,
76 std::vector<std::string> &ref_config,
85 while(_rank(N, lin_alg_tol) != N.cols()) {
90 double min_dist_ref = -1;
91 for(
int i = 0; i < ref_config.size(); ++i) {
92 double tot_dist = 0.0;
93 for(
int j = 0; j < ref_config.size(); ++j) {
95 tot_dist += (_N.col(i) - _N.col(j)).
norm();
98 if(tot_dist < min_dist) {
104 ref_config.erase(ref_config.begin() + min_dist_ref);
105 _N = _species_frac_matrix(primclex, ref_config);
106 N = _species_frac_space(_N);
116 const std::vector<std::string> &struc_mol_name,
126 bool has_Va = (Va_index != struc_mol_name.size());
129 _N.row(Va_index) = Eigen::VectorXd::Zero(_N.cols());
131 for(
int i = 0; i < _N.cols(); i++) {
132 _N.col(i) /= _N.col(i).sum();
140 int r = _rank(N, tol);
143 std::cerr <<
"Error in ChemicalReference::hyperplane " << std::endl;
144 std::cerr <<
"Input space (column vectors of atom_frac):\n" << N << std::endl;
145 std::cerr <<
"Rows correspond to: " <<
jsonParser(struc_mol_name) << std::endl;
146 std::cerr <<
"Input space rank: " << r << std::endl;
147 throw std::runtime_error(
"Error in ChemicalReference::hyperplane: Too many reference states specified");
157 for(
int i = 0; i < struc_mol.size(); i++) {
159 std::cerr <<
"Error in ChemicalReference::hyperplane " << std::endl;
160 std::cerr <<
"Initial struc_mol_name must be in same order as prim.get_struc_molecule()" << std::endl;
161 throw std::runtime_error(
"Error in ChemicalReference::hyperplane: Molecule name mismatch");
164 Index prim_N_mol = struc_mol.size();
169 Eigen::MatrixXd X = N.topRows(prim_N_mol).fullPivHouseholderQr().solve(C);
171 double relative_error = (N.topRows(prim_N_mol) * X - C).
norm() / C.norm();
173 if(relative_error > tol) {
174 std::cerr <<
"Error in ChemicalReference::hyperplane " << std::endl;
175 std::cerr <<
"Input space does not span the composition space of your prim." << std::endl;
177 std::cerr <<
"Input space (column vectors in atom_frac space):\n" << N.topRows(prim_N_mol) << std::endl;
178 std::cerr <<
"End members:\n" <<
end_members(prim) << std::endl;
179 std::cerr <<
"Prim space (column vectors in atom_frac space):\n" << C << std::endl;
180 std::cerr <<
"Rows correspond to: " <<
jsonParser(struc_mol_name) << std::endl;
181 std::cerr <<
"X, prim_space = input_space*X: \n" << X << std::endl;
182 std::cerr <<
"input_space*X: \n" << N.topRows(prim_N_mol)*X << std::endl;
183 std::cerr <<
"relative_error: " << relative_error << std::endl;
184 std::cerr <<
"tol: " << tol << std::endl;
186 throw std::runtime_error(
"Error in ChemicalReference::hyperplane: Input space does not span prim space");
194 relative_error = (_N.transpose() * P - E).
norm() / E.norm();
196 if(relative_error > tol) {
197 std::cerr <<
"Error in ChemicalReference::hyperplane " << std::endl;
198 std::cerr <<
"Could not solve for hyperplane reference." << std::endl;
200 std::cerr <<
"Input space (column vectors in atom_frac space), N:\n" << N << std::endl;
201 std::cerr <<
"Rows correspond to: " <<
jsonParser(struc_mol_name) << std::endl;
202 std::cerr <<
"Solve: _N.transpose()*P = E" << std::endl;
203 std::cerr <<
"_N.transpose():\n" << _N.transpose() << std::endl;
204 std::cerr <<
"Reference state energies, E:\n" << E << std::endl;
205 std::cerr <<
"P:\n" << P.transpose() << std::endl;
206 std::cerr <<
"relative_err: " << relative_error << std::endl;
207 std::cerr <<
"tol: " << tol << std::endl;
209 throw std::runtime_error(
"Error in ChemicalReference::hyperplane: Could not solve for hyperplane reference");
213 std::cerr <<
"Error in ChemicalReference::hyperplane " << std::endl;
214 std::cerr <<
"Non-zero pure Va reference: " << P.transpose() << std::endl;
215 std::cerr <<
"Elements correspond to: " <<
jsonParser(struc_mol_name) << std::endl;
217 throw std::runtime_error(
"Error in ChemicalReference::hyperplane: Input space does not span prim space");
220 return P.head(prim_N_mol);
237 for(
auto it = begin; it != end; ++it) {
238 if(!it->calc_properties().contains(
"relaxed_energy")) {
241 double curr_dist = (target -
comp(*it)).
norm();
243 (
almost_equal(curr_dist, close_dist,
TOL) && it->size() < res->size()) ||
244 (curr_dist < close_dist)) {
246 close_dist = curr_dist;
251 std::cerr <<
"Error in auto_chemical_reference: Could not find any configurations\n";
252 throw std::runtime_error(
"Error in auto_chemical_reference: Could not find any configurations");
264 std::vector<std::string> ref_config;
265 ref_config.push_back(closest_calculated_config(target));
267 for(
int i = 0; i < Naxes; i++) {
272 std::string
configname = closest_calculated_config(target);
276 std::cerr <<
"Error in auto_chemical_reference: Could not find enough calculated configurations\n";
277 throw std::runtime_error(
"Error in auto_chemical_reference: Could not find enough calculated configurations");
280 ref_config.push_back(configname);
287 _prune_ref_config(primclex, ref_config, lin_alg_tol);
290 std::vector<ChemicalReferenceState> ref_states;
291 for(
auto it = ref_config.begin(); it != ref_config.end(); ++it) {
AtomFrac SpeciesFrac
In the future, AtomFrac will actually be atoms only.
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Eigen::MatrixXd composition_space(const Structure &prim, double tol=1e-14)
Return the composition space of a Structure.
double energy_per_species
Energy in this reference state.
ChemicalReference auto_chemical_reference(const PrimClex &primclex, double lin_alg_tol)
Automatically set ChemicalReference using calculated Configurations with 'extreme' compositions...
bool is_vacancy(const std::string &name)
A vacancy is any Specie/Molecule with (name == "VA" || name == "va" || name == "Va") ...
Structure specifies the lattice and atomic basis of a crystal.
std::vector< Molecule > get_struc_molecule() const
Returns an Array of each possible Molecule in this Structure.
bool is_molecule_name(const Molecule &mol, std::string name)
Return true if Molecule name matches 'name', including Va checks.
static const std::string Name
std::map< std::string, double > species_num
Map of Molecule name : number of each species in reference state.
Eigen::VectorXd comp(const Configuration &config)
Returns parametric composition, as calculated using PrimClex::param_comp.
static const std::string Desc
config_iterator config_begin()
Configuration iterator: begin.
config_iterator config_end()
Configuration iterator: end.
Index find_index_if(Iterator begin, Iterator end, UnaryPredicate p)
Equivalent to std::distance(begin, std::find_if(begin, end, p))
std::vector< std::string > get_struc_molecule_name() const
Returns an Array of each possible Molecule in this Structure.
const Structure & get_prim() const
Get the primitive Structure for this Configuration.
std::vector< std::string > components() const
The order of components in mol composition vectors.
static Eigen::VectorXd _calc_hyperplane(const Structure &prim, const std::vector< std::string > &struc_mol_name, Eigen::MatrixXd N, Eigen::VectorXd E, double tol)
Convert a set of ChemicalReferenceState to a hyperplane, including checks.
T norm(const Tensor< T > &ttens)
EigenIndex Index
For long integer indexing:
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
PrimClex is the top-level data structure for a CASM project.
size_type independent_compositions() const
The dimensionality of the composition space.
const CompositionConverter & composition_axes() const
const Access CompositionConverter object
T max(const T &A, const T &B)
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") ...
ConfigIO::GenericConfigFormatter< std::string > configname()
Constructs DataFormmaterDictionary containing all Configuration DatumFormatters.
Eigen::MatrixXd end_members(const Structure &prim)
Generate a column matrix containing all the possible molecular end members.
ConfigIO::GenericConfigFormatter< double > relaxed_energy_per_species()
bool almost_equal(const GenericCluster< CoordType > &LHS, const GenericCluster< CoordType > &RHS, double tol)
Eigen::VectorXd species_frac(const Configuration &config)
Returns the composition as species fraction, with [Va] = 0.0, in the order of Structure::get_struc_mo...
A Configuration represents the values of all degrees of freedom in a Supercell.
const Structure & get_prim() const
const Access to primitive Structure