7 #include "casm/external/Eigen/Dense"
8 #include "casm/external/qhull/libqhullcpp/QhullFacetList.h"
9 #include "casm/external/qhull/libqhullcpp/QhullVertexSet.h"
28 double _singular_value_tol,
29 double _bottom_facet_tol) :
30 m_selection(_selection),
31 m_comp_calculator(_comp_calculator),
32 m_energy_calculator(_energy_calculator) {
46 mat(Ncomp, i) =
energy(*it);
51 PCA pca(mat.topRows(Ncomp), _singular_value_tol);
57 orgQhull::PointCoordinates points(reduced_mat.rows(),
"");
60 points.append(reduced_mat.size(), reduced_mat.data());
63 std::string qh_command =
"";
64 m_hull.runQhull(points.comment().c_str(), points.dimension(), points.count(), &*points.coordinates(), qh_command.c_str());
67 if(
m_hull.hasQhullMessage()) {
68 std::cerr <<
"\nQhull message:\n" <<
m_hull.qhullMessage();
69 m_hull.clearQhullMessage();
70 throw std::runtime_error(
"Qhull Error (see message)");
85 auto begin =
m_hull.facetList().begin();
86 auto end =
m_hull.facetList().end();
87 int dim =
m_hull.dimension();
89 Eigen::Map<const Eigen::VectorXd> outnorm((*begin).hyperplane().begin(), dim);
91 for(
auto facet_it = begin; facet_it != end; ++facet_it) {
94 new(&outnorm) Eigen::Map<const Eigen::VectorXd>((*facet_it).hyperplane().begin(), dim);
95 b = -outnorm(dim - 1);
97 if(b > _bottom_facet_tol) {
107 orgQhull::QhullVertexSet vertices = (*facet_it).first.vertices();
108 for(
auto vertex_it = vertices.begin(); vertex_it != vertices.end(); ++vertex_it) {
137 std::advance(it, point.id());
154 int dim =
m_hull.dimension();
155 Eigen::Map<const Eigen::VectorXd> reduced_hyperplane(facet.hyperplane().begin(), dim);
157 Eigen::VectorXd _mu = Eigen::VectorXd::Constant(dim - 1, reduced_hyperplane(dim - 1));
159 return _mu.cwiseQuotient(
expand().leftCols(dim - 1) * reduced_hyperplane.head(dim - 1));
173 hyperplane.head(mu.size()) = mu.cwiseInverse();
174 hyperplane(mu.size()) = 1.0;
175 hyperplane.normalize();
185 Eigen::Map<const Eigen::VectorXd> reduced_vertex_point(it->point().begin(), it->point().size());
187 double offset = reduced_hyperplane.dot(reduced_vertex_point);
189 if(offset > max_offset) {
213 _point.tail(1)(0) =
energy(config);
240 orgQhull::QhullPoint qpoint(_reduced_point.size(), _reduced_point.data());
248 a = -(facet_it->first).distance(qpoint);
249 b = facet_it->second;
250 if(a / b < dist_to_hull) {
251 dist_to_hull = a / b;
258 namespace Hull_impl {
265 typedef std::map<std::string, std::pair<bool, bool> > CheckMap;
267 CheckMap invalid_data;
270 invalid_data[it.name()] = std::make_pair(comp_calculator.
validate(*it), energy_calculator.
validate(*it));
274 if(invalid_data.size()) {
275 std::cerr <<
"Invalid data for hull construction:\n";
279 Formatter(
"configname",
"", [](CheckMap::value_type v) {
282 Formatter(
"composition",
"", [](CheckMap::value_type v) {
283 return v.second.first ?
"OK" :
"invalid";
285 Formatter(
"energy",
"", [](CheckMap::value_type v) {
286 return v.second.second ?
"OK" :
"invalid";
290 std::cerr << f(invalid_data.begin(), invalid_data.end()) <<
"\n";
292 std::stringstream ss;
293 ss <<
"Error in Hull(): Invalid composition or energy data. \n"
294 "Make sure you have set composition axes, all selected configurations\n"
295 "have calculation results, and you have set your chemical reference.";
296 throw std::runtime_error(ss.str());
Eigen::MatrixXd pad(const Eigen::MatrixXd &M, int n)
Construct a matrix consisting of blocks M and Identity(n,n)
const_iterator selected_config_cbegin() const
double dist_to_hull(const Configuration &config) const
The distance a Configuration is above the hull along the energy axis.
Eigen::VectorXd composition(const Configuration &config) const
Use the CompCalculator to return the composition of a Configuration.
iterator selected_config_begin()
const orgQhull::Qhull & data() const
const Access the hull object directly
notstd::cloneable_ptr< CompCalculator > m_comp_calculator
std::vector< std::pair< orgQhull::QhullFacet, double > > m_bottom_facets
const Configuration & configuration(const orgQhull::QhullPoint &point) const
Return the configuration corresponding to any point.
Eigen::VectorXd mu(const orgQhull::QhullFacet facet) const
Return the chemical potential corresponding to a facet.
Hull(const ConstConfigSelection &_selection, const CompCalculator &_comp_calculator=ConfigIO::SpeciesFrac(), const EnergyCalculator &_energy_calculator=ConfigIO::formation_energy_per_species(), double _singular_value_tol=1e-14, double _bottom_facet_tol=1e-14)
Constructor for convex hull in composition/energy space.
Principle component analysis.
EigenIndex Index
For long integer indexing:
std::set< orgQhull::QhullVertex, CompareVertex > m_bottom_vertices
iterator selected_config_end()
double energy(const Configuration &config) const
Use the EnergyCalculator to return the energy of a Configuration.
const_iterator selected_config_cend() const
T max(const T &A, const T &B)
T min(const T &A, const T &B)
const Eigen::MatrixXd & reduce() const
Orthogonal transformation matrix from a point in full comp/energy space to dimension-reduced comp/ene...
const Eigen::Transpose< const Eigen::MatrixXd > expand() const
Orthogonal transformation matrix from a point in the dimension-reduced comp/energy space to the full ...
Eigen::VectorXd reduced_point(const Configuration &config) const
Return a vector corresponding to the coordinate of a given configuration in the reduced composition/e...
Eigen::VectorXd point(const Configuration &config) const
Return a vector corresponding to the coordinate of a given configuration in full composition/energy s...
notstd::cloneable_ptr< EnergyCalculator > m_energy_calculator
ConstConfigSelection m_selection
const Configuration & groundstate(const Eigen::VectorXd &mu) const
Return the 0K ground state corresponding to the input chemical potential.
A Configuration represents the values of all degrees of freedom in a Supercell.
void _validate_input(const ConstConfigSelection &selection, const Hull::CompCalculator &comp_calculator, const Hull::EnergyCalculator &energy_calculator)
Print informational message and throw exception if input data is not valid.