30 return std::string(1, (
char)(i + (
int)
'a'));
107 std::stringstream tstr;
111 bool first_char =
true;
124 for (
int j = 0; j <
m_to_n.cols(); j++) {
131 if (!first_char &&
m_to_n(i, j) > 0) tstr <<
'+';
133 else if (
m_to_n(i, j) < 0)
137 tstr << std::abs(
m_to_n(i, j));
155 std::stringstream tstr;
161 bool first_char =
true;
174 for (
int j = 0; j <
m_to_x.cols(); j++) {
175 double coeff =
m_to_x(i, j);
196 else if (coeff > 0) {
222 std::stringstream ss;
224 auto comp_x_str = [&]() {
return "comp(" +
comp_var(i) +
")"; };
226 auto comp_n_str = [&](
int j) {
return "comp_n(" +
m_components[j] +
")"; };
228 auto delta_str = [&](
int j) {
229 std::stringstream tss;
232 tss <<
"(" << comp_n_str(j) <<
" - " <<
m_origin(j) <<
")";
236 tss << comp_n_str(j);
241 ss << comp_x_str() <<
" = ";
242 bool first_term =
true;
243 for (
int j = 0; j <
m_to_x.cols(); ++j) {
244 double coeff =
m_to_x(i, j);
254 ss <<
" - " << -coeff <<
"*" << delta_str(j);
256 ss << coeff <<
"*" << delta_str(j);
263 ss <<
" + " << coeff <<
"*" << delta_str(j);
265 ss << coeff <<
"*" << delta_str(j);
281 std::stringstream ss;
283 auto comp_x_str = [&](
int j) {
return "comp(" +
comp_var(j) +
")"; };
285 auto comp_n_str = [&](
int j) {
return "comp_n(" +
m_components[j] +
")"; };
287 ss << comp_n_str(i) <<
" = ";
288 bool first_term =
true;
295 for (
int j = 0; j <
m_to_n.cols(); ++j) {
296 double coeff =
m_to_n(i, j);
306 ss <<
" - " << -coeff <<
"*" << comp_x_str(j);
308 ss << coeff <<
"*" << comp_x_str(j);
315 ss <<
" + " << coeff <<
"*" << comp_x_str(j);
317 ss << coeff <<
"*" << comp_x_str(j);
337 std::stringstream ss;
339 auto print_chem_pot = [&](
int j) {
343 ss <<
"param_chem_pot(" <<
comp_var(i) <<
") = ";
345 bool first_term =
true;
346 for (
int j = 0; j < Mt.cols(); ++j) {
347 double coeff = Mt(i, j);
360 ss << print_chem_pot(j);
365 ss <<
"- " << print_chem_pot(j);
369 else if (coeff > 0) {
373 ss << coeff <<
"*" << print_chem_pot(j);
378 ss << coeff <<
"*" << print_chem_pot(j);
406 tmp.col(c) = _end_member;
414 throw std::runtime_error(
415 std::string(
"Error in CompositionConverter: origin or end member "
416 "vector size does not match components size."));
449 std::stringstream tstr;
452 for (
int i = 0; i < vec.size(); i++) {
473 std::ostream &stream,
474 const std::map<std::string, CompositionConverter> &map) {
475 if (map.size() == 0) {
481 stream << std::setw(10) <<
"KEY"
483 stream << std::setw(10) <<
"ORIGIN"
485 for (
int i = 0; i < map.begin()->second.independent_compositions(); i++) {
486 stream << std::setw(10) << comp_var(i) <<
" ";
489 stream <<
"GENERAL FORMULA";
492 stream << std::setw(10) <<
" ---"
494 stream << std::setw(10) <<
" ---"
496 for (
int i = 0; i < map.begin()->second.independent_compositions(); i++) {
497 stream << std::setw(10) <<
" ---"
501 stream <<
"---" << std::endl;
503 for (
auto it = map.cbegin(); it != map.cend(); ++it) {
504 stream << std::setw(10) << it->first <<
" ";
505 stream << std::setw(10) << it->second.origin_formula() <<
" ";
506 for (
int i = 0; i < it->second.independent_compositions(); ++i) {
507 stream << std::setw(10) << it->second.end_member_formula(i) <<
" ";
510 stream << std::setw(10) << it->second.mol_formula() <<
"\n";
525 stream << std::string(indent,
' ') << f.
comp_formula(i) <<
"\n";
539 for (
int i = 0; i < f.
components().size(); ++i) {
540 stream << std::string(indent,
' ') << f.
comp_n_formula(i) <<
"\n";
581 std::vector<std::string> struc_mol_name =
586 bool has_Va = (Va_index != struc_mol_name.size());
591 E.row(Va_index) = Eigen::VectorXd::Zero(E.cols());
593 for (
int i = 0; i < E.cols(); i++) {
594 E.col(i) /= E.col(i).sum();
599 for (
int i = 0; i < M.cols(); ++i) {
600 M.col(i) = E.col(i + 1) - E.col(0);
618 Qr.setThreshold(tol);
619 auto Q = Qr.matrixQ();
620 return Q.leftCols(Qr.rank());
636 Qr.setThreshold(tol);
637 auto Q = Qr.matrixQ();
638 return Q.rightCols(Q.cols() - Qr.rank());
Convert between number of species per unit cell and parametric composition.
Eigen::VectorXd mol_composition(const Eigen::VectorXd &x) const
Convert parametric composition, 'x', to number of mol per prim, 'n'.
Eigen::MatrixXd m_end_members
Column vector matrix, rows == m_components.size(), cols == rank of parametric composition space.
std::string comp_formula(size_type i) const
Return formula for comp(i) in terms of comp_n(A), comp_n(B), ...
Eigen::VectorXd chem_pot(const Eigen::VectorXd param_chem_pot) const
Convert dG/dx to dG/dn.
std::string _n_formula(const Eigen::VectorXd &vec) const
Return formula for 'n'.
void _calc_conversion_matrices()
Calculate conversion matrices m_to_n and m_to_x.
Eigen::VectorXd m_origin
Vector, size == m_components.size(), specifying the num_mols_per_prim of each component at the origin...
Eigen::MatrixXd m_to_x
Conversion matrix: x = m_to_x*(n - origin)
Eigen::VectorXd end_member(size_type i) const
The mol composition of the parameteric composition axes end members.
std::string origin_formula() const
Return formula for origin.
std::string param_formula() const
Return formula for n->x.
void _check_size(const Eigen::MatrixXd &vec) const
Check that origin and end member vectors have same size as the number of components.
Eigen::VectorXd param_composition(const Eigen::VectorXd &n) const
Convert number of mol per prim, 'n' to parametric composition 'x'.
std::string comp_n_formula(size_type i) const
Return formula for comp_n(components()[i]) in terms of comp(a), comp(b), ...
static std::string comp_var(size_type i)
Composition variable names: "a", "b", ...
Eigen::VectorXd dparam_composition(const Eigen::VectorXd &dn) const
Convert change in number of atoms per prim, 'dn' to change in parametric composition 'dx'.
Eigen::VectorXd origin() const
The mol composition of the parameteric composition axes origin.
std::string param_chem_pot_formula(size_type i) const
Return formula for param_chem_pot(i) in terms of chem_pot(A), chem_pot(B), ...
size_type independent_compositions() const
The dimensionality of the composition space.
Eigen::VectorXd param_chem_pot(const Eigen::VectorXd chem_pot) const
Convert dG/dn to dG/dx.
std::string mol_formula() const
Return formula for x->n.
Eigen::VectorXd dmol_composition(const Eigen::VectorXd &dx) const
Convert change in parametric composition, 'dx', to change in number of mol per prim,...
void _add_end_member(Eigen::VectorXd _end_member)
Helps make variadic template constructor possible.
Eigen::MatrixXd dparam_dmol() const
Return the matrix Mij = dx_i/dn_j.
Eigen::MatrixXd dmol_dparam() const
Return the matrix Mij = dn_i/dx_j.
Eigen::MatrixXd m_to_n
Conversion matrix: n = origin + m_to_n*x.
std::vector< std::string > components() const
The order of components in mol composition vectors.
std::vector< std::string > m_components
List of all allowed components names in the prim, position in vector is reference for origin and end_...
std::string end_member_formula(size_type i) const
Return formula for end member.
Eigen::MatrixXd prim_end_members() const
Return all possible end members as row matrix.
std::vector< std::vector< std::string > > AllowedOccupants
void generate_prim_end_members()
const std::vector< std::string > & components() const
Components are in order of appearance precedence in allowed_occs()
Eigen::Matrix< typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime > inverse(const Eigen::MatrixBase< Derived > &M)
Return the integer inverse matrix of an invertible integer matrix.
static bool _is_vacancy(const std::string &name)
A vacancy is any Specie/Molecule with (name == "VA" || name == "va" || name == "Va")
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
void display_comp_n(std::ostream &stream, const CompositionConverter &f, int indent=0)
Pretty-print comp_n in terms of comp.
Eigen::MatrixXd composition_space(const ParamComposition::AllowedOccupants &_allowed_occs, double tol=1e-14)
Return the composition space of a ParamComposition::AllowedOccupants.
void display_param_chem_pot(std::ostream &stream, const CompositionConverter &f, int indent=0)
Pretty-print param_chem_pot in terms of chem_pot.
void display_composition_axes(std::ostream &stream, const std::map< std::string, CompositionConverter > &map)
Pretty-print map of name/CompositionConverter pairs.
Eigen::MatrixXd _composition_space(const ParamComposition::AllowedOccupants &_allowed_occs, double tol)
Non-orthogonal composition space.
GenericDatumFormatter< std::string, DataObject > name()
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Index find_index_if(Iterator begin, Iterator end, UnaryPredicate p)
Equivalent to std::distance(begin, std::find_if(begin, end, p))
Eigen::MatrixXd end_members(const ParamComposition::AllowedOccupants &_allowed_occs)
Serialize CompositionConverter to JSON.
Eigen::MatrixXd null_composition_space(const ParamComposition::AllowedOccupants &_allowed_occs, double tol=1e-14)
Return the null composition space of a ParamComposition::AllowedOccupants.
void display_comp(std::ostream &stream, const CompositionConverter &f, int indent=0)
Pretty-print comp in terms of comp_n.
INDEX_TYPE Index
For long integer indexing: