28 #ifndef CHEMISTRY_QC_BASIS_SHELLORDER_HPP
29 #define CHEMISTRY_QC_BASIS_SHELLORDER_HPP
35 #include <Eigen/Dense>
36 #include <chemistry/molecule/molecule.h>
37 #include <chemistry/qc/basis/basis.h>
39 #include "kcluster.hpp"
56 using Vector3 = KCluster::Vector3;
66 com_(Vector3::Zero(3))
75 for(
auto i = 0; i < mol->
natom(); ++i){
76 atoms_.push_back(
Atom(mol->atom(i), i));
88 nclusters_ = nclusters;
91 compute_clusters(nclusters_);
93 std::vector<Shell> shells = cluster_shells(new_parent_basis);
98 std::vector<KCluster>& get_clusters(std::size_t nclusters) {
99 nclusters_ = nclusters;
100 compute_clusters(nclusters_);
108 return compute_shell_ranges();
115 void compute_clusters(std::size_t nclusters){
125 void init_clusters(){
129 auto ordering = [&](
const Atom &a,
const Atom &b){
131 const Vector3 va = Eigen::Map<const Vector3>(a.r(),3);
132 const Vector3 vb = Eigen::Map<const Vector3>(b.r(),3);
135 double da = Vector3(va - com_).norm();
136 double db = Vector3(vb - com_).norm();
142 else if(va[0] != vb[0]){
143 return (va[0] < vb[0]);
145 else if(va[1] != vb[1]){
146 return (va[1] < vb[1]);
148 else if(va[2] != vb[2]){
149 return (va[2] < vb[2]);
156 std::sort(atoms_.begin(), atoms_.end(), ordering);
160 for(
auto i = 0; i < nclusters_; ++i){
162 Vector3(atoms_[i].r(0), atoms_[i].r(1), atoms_[i].r(2))
167 attach_to_closest_cluster();
173 void attach_to_closest_cluster(){
175 for(
const auto atom : atoms_){
177 double smallest = clusters_[0].distance(atom);
180 std::size_t kindex = 0;
183 for(
auto i = 1; i < nclusters_; ++i){
185 double dist = clusters_[i].distance(atom);
195 clusters_[kindex].add_atom(atom);
199 for(
auto& cluster : clusters_){
200 cluster.sort_atoms();
205 void k_means_search(std::size_t niter = 100){
208 for(
auto i = 0; i < niter; ++i){
213 for(
auto &cluster : clusters_){ cluster.guess_center(); }
216 attach_to_closest_cluster();
227 std::vector<Shell> shells;
229 for(
const auto& cluster : clusters_){
231 for(
const auto& atom : cluster.atoms()){
233 std::size_t center_ = atom.mol_index();
235 std::size_t nshells_on_atom =
239 for(
auto i = 0; i < nshells_on_atom; ++i){
240 shells.push_back(Shell(
241 new_parent_basis, center_,
242 basis_->operator()(center_, i)));
255 range.reserve(nclusters_);
261 for(
auto i = 0; i < nclusters_; ++i){
263 std::size_t shells_in_cluster = 0;
265 for(
const auto atom : clusters_[i].atoms()){
267 std::size_t atom_index = atom.mol_index();
272 range.push_back(range.at(i) + shells_in_cluster);
281 void sort_clusters(){
282 std::sort(clusters_.begin(), clusters_.end(),
283 [&](
const KCluster &a,
const KCluster &b){
284 return ((a.center()-com_).
norm() < (b.center()-com_).
norm());}
289 std::size_t nclusters_ = 0;
290 std::vector<Atom> atoms_;
292 std::vector<KCluster> clusters_;