diff --git a/include/tadah/mlip/neighbor_list_db.h b/include/tadah/mlip/neighbor_list_db.h index acd4ea43ddce7a012f84f0cd619d9c70ed576081..9c062e119aae85f62315bd3ae08e6abe9a8eaccb 100644 --- a/include/tadah/mlip/neighbor_list_db.h +++ b/include/tadah/mlip/neighbor_list_db.h @@ -5,7 +5,6 @@ #include <tadah/mlip/neighbor_list.h> #include <tadah/mlip/structure_db.h> -// #include <tadah/mlip/structure_neighbor_view.h> namespace tadah { namespace mlip { diff --git a/include/tadah/mlip/structure.h b/include/tadah/mlip/structure.h index 5bafff0c7cfba27b8f00edc1f41aab1a1fb7d1a5..3ebe47f34f8730cb83b38c8ce066d044d0f591e7 100644 --- a/include/tadah/mlip/structure.h +++ b/include/tadah/mlip/structure.h @@ -12,17 +12,17 @@ #include <tadah/core/periodic_table.h> #include <tadah/core/core_types.h> #include <tadah/core/vec3d_soa_view.h> +#include <tadah/core/vec3d_soa_const_view.h> + +// TODO This class must be reworked such that it does not store any data +// It should be a lightweight handle similar to how Atom works. -// Forward-declare classes to avoid circular includes namespace tadah { namespace mlip { + +// Forward-declare classes to avoid circular includes class Atom; // We'll define it in "atom.h" class StructureDB; // We'll define it in "structure_db.h" -} // namespace mlip -} // namespace tadah - -namespace tadah { -namespace mlip { /** * @brief Represents a subrange of SoA arrays for storing atoms. @@ -87,6 +87,9 @@ public: Vec3dSoAView positionView(size_t i); Vec3dSoAView forceView(size_t i); + Vec3dSoAConstView positionView(size_t i) const; + Vec3dSoAConstView forceView(size_t i) const; + /** * @brief Converts a global index to a local index within this structure. * @@ -219,4 +222,3 @@ private: } // namespace tadah #endif // TADAH_MLIP_STRUCTURE_H - diff --git a/include/tadah/mlip/structure_inl.h b/include/tadah/mlip/structure_inl.h index b49cfb89dc4b02e3ccb97ee27e4dd73cf226062a..55c8a5fadb24bcdabb7d53c2e79e7f19ed095889 100644 --- a/include/tadah/mlip/structure_inl.h +++ b/include/tadah/mlip/structure_inl.h @@ -69,6 +69,14 @@ inline Vec3dSoAView Structure::forceView(size_t i) { return Vec3dSoAView( fx(i), fy(i), fz(i) ); } +inline Vec3dSoAConstView Structure::positionView(size_t i) const +{ + return Vec3dSoAConstView( &x(i), &y(i), &z(i) ); +} +inline Vec3dSoAConstView Structure::forceView(size_t i) const +{ + return Vec3dSoAConstView( &fx(i), &fy(i), &fz(i) ); +} inline int Structure::read(std::ifstream &ifs) { diff --git a/include/tadah/mlip/structure_neighbor_view.h b/include/tadah/mlip/structure_neighbor_view.h index 21b9b1b11d684e849dc72006ff6713276477acbb..fb871478d2b54c0ab262d3475db2210b5cd7d0b7 100644 --- a/include/tadah/mlip/structure_neighbor_view.h +++ b/include/tadah/mlip/structure_neighbor_view.h @@ -91,7 +91,7 @@ public: } /** - * @brief Returns the X-shift pointer, if HPC code uses shifts. + * @brief Returns the X-shift pointer. */ inline const int* getShiftXPtr(std::size_t localAtomIndex) const { if (localAtomIndex >= str_.natoms()) { diff --git a/src/dm_bf_linear.cpp b/src/dm_bf_linear.cpp index 483c263d7c330f7f25c9ccec1e835406f854bf4f..77f84db27b2015bdc5aed340ec33ebab4c2a7f7c 100644 --- a/src/dm_bf_linear.cpp +++ b/src/dm_bf_linear.cpp @@ -1,68 +1,75 @@ #include <tadah/mlip/design_matrix/functions/basis_functions/dm_bf_linear.h> -//CONFIG::Registry<DM_Function_Base>::Register<DM_BF_Linear> DM_BF_Linear_1( "BF_Linear" ); -//CONFIG::Registry<DM_Function_Base,Config&>::Register<DM_BF_Linear> DM_BF_Linear_2( "BF_Linear" ); - namespace tadah { namespace mlip { DM_BF_Linear::DM_BF_Linear() {} -DM_BF_Linear::DM_BF_Linear(const Config &c): - Function_Base(c), - DM_BF_Base(c), - BF_Linear(c) -{} -size_t DM_BF_Linear::get_phi_cols(const Config &config) -{ +DM_BF_Linear::DM_BF_Linear(const Config &c) + : Function_Base(c), DM_BF_Base(c), BF_Linear(c) {} +size_t DM_BF_Linear::get_phi_cols(const Config &config) { size_t cols = config.get<size_t>("DSIZE"); return cols; } void DM_BF_Linear::calc_phi_energy_row(phi_type &Phi, size_t &row, - const double fac, const Structure &, const StructureNeighborView &st_nb, const StDescriptors &st_d) -{ - for (size_t i=0; i<st_d.naed(); ++i) { - const aed_type &aed = st_d.get_aed(i); - for (size_t j=0; j<aed.size(); ++j) { - Phi(row,j)+=aed[j]*fac; + const double fac, const Structure &, + const StructureNeighborView &st_nb, + const StDescriptors &st_d) { + for (size_t a = 0; a < st_d.naed(); ++a) { + const aed_type &aed = st_d.get_aed(a); + for (size_t j = 0; j < aed.size(); ++j) { + Phi(row, j) += aed[j] * fac; } } row++; } void DM_BF_Linear::calc_phi_force_rows(phi_type &Phi, size_t &row, - const double fac, const Structure &st, const StructureNeighborView &st_nb, const StDescriptors &st_d) -{ + const double fac, const Structure &st, + const StructureNeighborView &st_nb, + const StDescriptors &st_d) { - for (size_t a=0; a<st.natoms(); ++a) { - for (size_t jj=0; jj<st_d.fd[a].size(); ++jj) { - const size_t j=st.near_neigh_idx[a][jj]; - const size_t aa = st.get_nn_iindex(a,j,jj); + for (size_t a = 0; a < st.natoms(); ++a) { + const std::size_t *NbPtr = st_nb.getNeighborsPtr(a); + size_t NNbrs = st_nb.numNeighbors(a); + const Vec3dSoAConstView ri = st.positionView(a); + const aed_type &aedi = st_d.get_aed(a); + for (size_t jj=0; jj<NNbrs; ++jj) { + size_t gj = NbPtr[jj]; + size_t j= st.globalToLocal(gj); // j is local to st + size_t aa = getAAIndex(a, j, jj) const fd_type &fij = st_d.fd[a][jj]; const fd_type &fji = st_d.fd[j][aa]; - for (size_t k=0; k<3; ++k) { - for (size_t d=0; d<fij.rows(); ++d) { - Phi(row+k,d) -= fac*(fij(d,k)-fji(d,k)); + for (size_t k = 0; k < 3; ++k) { + for (size_t d = 0; d < fij.rows(); ++d) { + Phi(row + k, d) -= fac * (fij(d, k) - fji(d, k)); } } } - row+=3; + row += 3; } } void DM_BF_Linear::calc_phi_stress_rows(phi_type &Phi, size_t &row, - const double fac[6], const Structure &st, const StructureNeighborView &st_nb, const StDescriptors &st_d) -{ - double V_inv = 1/st.get_volume(); - for (size_t i=0; i<st.natoms(); ++i) { - const Vec3d &ri = st(i).position; - for (size_t jj=0; jj<st_d.fd[i].size(); ++jj) { - const size_t j=st.near_neigh_idx[i][jj]; - const size_t ii = st.get_nn_iindex(i,j,jj); - const fd_type &fdij = st_d.fd[i][jj]; - const fd_type &fdji = st_d.fd[j][ii]; - const Vec3d &rj = st.nn_pos(i,jj); - size_t mn=0; - for (size_t x=0; x<3; ++x) { - for (size_t y=x; y<3; ++y) { - for (size_t d=0; d<fdij.rows(); ++d) { - Phi(row+mn,d) += V_inv*(fdij(d,y)-fdji(d,y))*0.5*fac[mn]*(ri(x)-rj(x)); + const double fac[6], + const Structure &st, + const StructureNeighborView &st_nb, + const StDescriptors &st_d) { + double V_inv = 1 / st.get_volume(); + for (size_t a = 0; a < st.natoms(); ++a) { + const std::size_t* NbPtr = st_nb.getNeighborsPtr(a); + size_t NNbrs = st_nb.numNeighbors(a); + const Vec3dSoAConstView ri = st.positionView(a); + const aed_type& aedi = st_d.get_aed(a); + for (size_t jj=0; jj<NNbrs; ++jj) { + size_t gj = NbPtr[jj]; + size_t j= st.globalToLocal(gj); // j is local to st + size_t aa = getAAIndex(a, j, jj) + const fd_type &fdij = st_d.fd[a][jj]; + const fd_type &fdji = st_d.fd[j][aa]; + const Vec3d &rj = st.nn_pos(a, jj); + size_t mn = 0; + for (size_t x = 0; x < 3; ++x) { + for (size_t y = x; y < 3; ++y) { + for (size_t d = 0; d < fdij.rows(); ++d) { + Phi(row + mn, d) += V_inv * (fdij(d, y) - fdji(d, y)) * 0.5 * + fac[mn] * (ri(x) - rj(x)); } mn++; } @@ -71,5 +78,5 @@ void DM_BF_Linear::calc_phi_stress_rows(phi_type &Phi, size_t &row, } row += 6; } -} -} +} // namespace mlip +} // namespace tadah diff --git a/src/dm_bf_polynomial2.cpp b/src/dm_bf_polynomial2.cpp index 24f22e31975963a5cffd4d9304d47b6ffe7570b2..b139f79e51b172244ae9e8d67feff18a8b468c2c 100644 --- a/src/dm_bf_polynomial2.cpp +++ b/src/dm_bf_polynomial2.cpp @@ -2,9 +2,6 @@ #include "tadah/models/functions/function_base.h" #include <tadah/mlip/design_matrix/functions/basis_functions/dm_bf_polynomial2.h> -//CONFIG::Registry<DM_Function_Base>::Register<DM_BF_Polynomial2> DM_BF_Polynomial2_1( "BF_Polynomial2" ); -//CONFIG::Registry<DM_Function_Base,Config&>::Register<DM_BF_Polynomial2> DM_BF_Polynomial2_2( "BF_Polynomial2" ); - namespace tadah { namespace mlip { DM_BF_Polynomial2::DM_BF_Polynomial2() {} @@ -45,7 +42,7 @@ void DM_BF_Polynomial2::calc_phi_force_rows(phi_type &Phi, const std::size_t* NbPtr = st_nb.getNeighborsPtr(a); size_t NNbrs = st_nb.numNeighbors(a); - const Vec3dSoAView ri = st.positionView(a); + const Vec3dSoAView ra = st.positionView(a); const aed_type& aedi = st_d.get_aed(a); for (size_t jj=0; jj<NNbrs; ++jj) { @@ -79,32 +76,40 @@ void DM_BF_Polynomial2::calc_phi_stress_rows(phi_type &Phi, const Structure &st, const StructureNeighborView &st_nb, const StDescriptors &st_d) { - double V_inv = 1/st.get_volume(); - for (size_t a=0; a<st.natoms(); ++a) { + double V_inv = 1 / st.get_volume(); + for (size_t a = 0; a < st.natoms(); ++a) { - const std::size_t* NbPtr = st_nb.getNeighborsPtr(a); + const std::size_t *NbPtr = st_nb.getNeighborsPtr(a); size_t NNbrs = st_nb.numNeighbors(a); - const Vec3dSoAView ri = st.positionView(a); - const aed_type& aedi = st_d.get_aed(a); + const Vec3dSoAView ra = st.positionView(a); + const aed_type &aedi = st_d.get_aed(a); + Vec3d rj; + for (size_t jj = 0; jj < NNbrs; ++jj) { + size_t gj = NbPtr[jj]; + size_t j = st.globalToLocal(gj); // j is local to st + size_t aa = getAAIndex(a, j, jj); - for (size_t jj=0; jj<NNbrs; ++jj) { + auto sx = st.getShiftXPtr(j); + auto sy = st.getShiftYPtr(j); + auto sz = st.getShiftZPtr(j); + + rj(0) = st(j).x() + sx*st.cell(0,0) + sy*st.cell(0,1) + sz*st.cell(0,2); + rj(1) = st(j).y() + sx*st.cell(1,0) + sy*st.cell(1,1) + sz*st.cell(1,2); + rj(2) = st(j).z() + sx*st.cell(2,0) + sy*st.cell(2,1) + sz*st.cell(2,2); - size_t gj = NbPtr[jj]; - size_t j= st.globalToLocal(gj); // j is local to st - size_t aa = getAAIndex(a, j, jj) const fd_type &fdji = st_d.fd[j][aa]; const fd_type &fdij = st_d.fd[a][jj]; - const Vec3d &rj = st.nn_pos(a,jj); - const aed_type& aedj = st_d.get_aed(j); - size_t mn=0; - for (size_t x=0; x<3; ++x) { - for (size_t y=x; y<3; ++y) { - size_t b=0; - for (size_t i=0; i<fdij.rows(); ++i) { - for (size_t ii=i; ii<fdij.rows(); ++ii) { - Phi(row+mn,b) += V_inv*0.5*fac[mn]*(ri(x)-rj(x)) - *(fdij(i,y)*aedi(ii) + fdij(ii,y)*aedi(i) - - fdji(i,y)*aedj(ii) - fdji(ii,y)*aedj(i)); + const aed_type &aedj = st_d.get_aed(j); + size_t mn = 0; + for (size_t x = 0; x < 3; ++x) { + for (size_t y = x; y < 3; ++y) { + size_t b = 0; + for (size_t i = 0; i < fdij.rows(); ++i) { + for (size_t ii = i; ii < fdij.rows(); ++ii) { + Phi(row + mn, b) += + V_inv * 0.5 * fac[mn] * (ra(x) - rj(x)) * + (fdij(i, y) * aedi(ii) + fdij(ii, y) * aedi(i) - + fdji(i, y) * aedj(ii) - fdji(ii, y) * aedj(i)); b++; } } diff --git a/src/structure.cpp b/src/structure.cpp deleted file mode 100644 index ee3ca19c640ae715b5e7d92070e5cebadf3e023d..0000000000000000000000000000000000000000 --- a/src/structure.cpp +++ /dev/null @@ -1,354 +0,0 @@ -#include <tadah/mlip/structure.h> -#include <tadah/core/periodic_table.h> - -#include <stdexcept> -#include <cmath> - -Structure::Structure() { - PeriodicTable::initialize(); -} - -const Atom &Structure::operator()(const size_t i) const{ - return atoms[i]; -} - -void Structure::add_atom(Atom a) { - atoms.push_back(a); -} -void Structure::remove_atom(const size_t i) { - atoms.erase(atoms.begin()+i); -} - -Vec3d Structure::nn_pos(const size_t i, const size_t n) const -{ - // (A) Global index of this neighbor - const size_t neighborIndex = near_neigh_idx[i][n]; - - // (B) Atom's original "unshifted" position: - const Vec3d &posNeighbor = atoms[neighborIndex].position; - - // (C) Convert the stored shift -> real displacement shiftDisp - // If near_neigh_shift[i][n] is an integer triple (n1, n2, n3), - // multiply by the cell. Otherwise, if it's already in real space, - // you can just do: Vec3d shiftDisp = near_neigh_shift[i][n]. - Vec3d shift = near_neigh_shift[i][n]; // might be (n1, n2, n3) - - // If shift is integer triple (n1, n2, n3), multiply with cell: - Vec3d shiftDisp; - shiftDisp[0] = shift[0]*cell(0,0) + shift[1]*cell(0,1) + shift[2]*cell(0,2); - shiftDisp[1] = shift[0]*cell(1,0) + shift[1]*cell(1,1) + shift[2]*cell(1,2); - shiftDisp[2] = shift[0]*cell(2,0) + shift[1]*cell(2,1) + shift[2]*cell(2,2); - - // (D) Final neighbor position = unshifted position + shiftDisp - Vec3d posShifted = posNeighbor + shiftDisp; - return posShifted; -} - -size_t Structure::natoms() const { - return atoms.size(); -} - -size_t Structure::nn_size(size_t i) const { - return near_neigh_idx[i].size(); -} - -int Structure::read(std::ifstream &ifs) { - std::string line; - // ignore extra empty lines - std::getline(ifs,line); - if(line.empty()) return 1; - - // OK, process structural data - // read first line as a label - label = line; - - // the second line could be energy or - // a scalling factors eweight fweight sweight - std::getline(ifs,line); - std::stringstream stream(line); - std::string temp; - size_t count = 0; - while(stream >> temp) { ++count;} - - if (count == 3) { - stream.clear(); - stream.seekg(0, std::ios::beg); - stream >> eweight >> fweight >> sweight; - std::getline(ifs,line); - std::stringstream stream2(line); - // energy and T - stream2 >> energy; - if(stream2) stream2 >> T; - } - else if (count == 2) { - stream.clear(); - stream.seekg(0, std::ios::beg); - // energy and T - stream >> energy >> T; - } - else { - energy = std::stod(line); - } - - // 3 lines, 9 elements are for the cell matrix - for (int i=0; i<3; ++i) - for (int j=0; j<3; ++j) - ifs >> cell(i,j); - - // 3 lines, 9 elements are for the stress matrix - // if (use_stress) - for (int i=0; i<3; ++i) - for (int j=0; j<3; ++j) - ifs >> stress(i,j); - - // move to next line - std::getline(ifs,line); - - // make sure atoms vector is empty - atoms.clear(); - - char symbol[3]; - double px,py,pz,fx,fy,fz; - while(std::getline(ifs,line)) { - if(line.empty()) break; - //if(line == " ") break; - if(line == "\r") break; // detects windows newline - - std::istringstream tmp(line); - tmp >> symbol >> px >> py >> pz >> fx >> fy >> fz; - Element e = PeriodicTable::find_by_symbol(symbol); - atoms.push_back(Atom(e,px,py,pz,fx,fy,fz)); - //Atom &a = atoms.back(); - - //tmp >> a.label >> a.position(0) >> a.position(1) >> a.position(2); - // if (use_force) - //tmp >> a.force(0) >> a.force(1) >> a.force(2); - //std::cout << a.force(0) << " " << a.force(1) << " " << a.force(2) << std::endl;; - } - return 0; -} - -void Structure::read(const std::string fn) { - std::ifstream ifs(fn); - if (!ifs.is_open()) { - throw std::runtime_error("File does not exist: "+fn); - } - read(ifs); - ifs.close(); -} - -void Structure::save(std::ofstream &ofs) const { - ofs << label << std::endl; - ofs << eweight << " " << fweight << " " << sweight << std::endl; - ofs << energy << std::endl; - for (int i=0; i<3; ++i) { - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << cell(i,0); - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << cell(i,1); - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << cell(i,2); - ofs << std::endl; - } - - for (int i=0; i<3; ++i) { - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << stress(i,0); - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << stress(i,1); - ofs << std::fixed << std::right << std::setw(w) << std::setprecision(p) << stress(i,2); - ofs << std::endl; - } - - for (const Atom &a:atoms) { - ofs << a.symbol[0] << a.symbol[1]; - ofs << std::setw(w-2) << std::fixed << std::right - << std::setprecision(p) << a.position(0); - ofs << std::setw(w) << std::fixed << std::right - << std::setprecision(p) << a.position(1); - ofs << std::setw(w) << std::fixed << std::right - << std::setprecision(p) << a.position(2); - ofs << std::setw(w) << std::fixed << std::right - << std::setprecision(p) << a.force(0); - ofs << std::setw(w) << std::fixed << std::right - << std::setprecision(p) << a.force(1); - ofs << std::setw(w) << std::fixed << std::right - << std::setprecision(p) << a.force(1); - ofs << std::endl; - } -} - -void Structure::save(const std::string fn) const { - std::ofstream ofs(fn); - save(ofs); - ofs.close(); -} -size_t Structure::get_nn_iindex(const size_t i, const size_t j, const size_t jj) const { - Vec3d shift_ijj = -near_neigh_shift[i][jj]; - size_t ii = 0; - - for (size_t x=0; x<near_neigh_idx[j].size(); ++x) { - if (near_neigh_idx[j][x] == i) - if (near_neigh_shift[j][ii] == shift_ijj) - break; - ii++; - } - return ii; - -} -double Structure::get_volume() const { - return cell.row(0)*(cell.row(1).cross(cell.row(2))); -} -double Structure::get_density() const { - double V = get_volume(); - V*=1e-24; // convert to cm^3 - double amu = 1.66053906660e-24; // g - double mass = 0; - for (const auto& a:atoms) mass += PeriodicTable::get_mass(a.Z); - return amu*mass/V; -} - -double Structure::get_temperature() const { - return T; -} - -double Structure::get_virial_pressure() const { - return stress.trace()/get_volume()/3; -} - -double Structure::get_pressure(double T, double kB) const { - double vpress = get_virial_pressure(); - return vpress + natoms()*kB*T/get_volume(); -} -bool Structure::operator==(const Structure& st) const -{ - double EPSILON = std::numeric_limits<double>::epsilon(); - bool result = - cell.isApprox(st.cell, EPSILON) - && stress.isApprox(st.stress, EPSILON) - && natoms()==st.natoms() - && (std::fabs(eweight-st.eweight) < EPSILON) - && (std::fabs(fweight-st.fweight) < EPSILON) - && (std::fabs(sweight-st.sweight) < EPSILON) - && (std::fabs(energy-st.energy) < EPSILON) - ; - if (!result) return result; - for (size_t i=0;i<natoms();++i) { - result = atoms[i]==st.atoms[i]; - if (!result) return result; - } - return result; -} -bool Structure::is_the_same(const Structure& st, double thr) const -{ - bool result = - cell.isApprox(st.cell, thr) - && natoms()==st.natoms(); - if (!result) return result; - - size_t count=0;; - for (size_t i=0;i<natoms();++i) { - for (size_t j=i;j<natoms();++j) { - result = atoms[i].is_the_same(st.atoms[j], thr); - if (result) count++; - } - } - - return count==natoms() ? true : false; -} -int Structure::next_structure(std::ifstream &ifs) { - std::string line; - std::getline(ifs,line); - if(line.empty()) return 0; - - std::getline(ifs,line); - // the second line could be energy or - // a scalling factors eweight fweight sweight - std::stringstream stream(line); - std::string temp; - size_t count = 0; - while(stream >> temp) { ++count;} - // optional if second line is a weight - if (count==3) - std::getline(ifs,line); - - for (size_t i=0; i<6;++i) - std::getline(ifs,line); - - int natoms=0; - while(std::getline(ifs,line)) { - if(line.empty()) break; - if(line == "\r") break; // detects windows newline - natoms++; - } - return natoms; -} -void Structure::clear_nn() { - near_neigh_shift.clear(); - near_neigh_idx.clear(); -} - -std::vector<Atom>::iterator Structure::begin() { - return atoms.begin(); -} - -std::vector<Atom>::iterator Structure::end() { - return atoms.end(); -} - -std::vector<Atom>::const_iterator Structure::begin() const { - return atoms.cbegin(); -} - -std::vector<Atom>::const_iterator Structure::end() const { - return atoms.cend(); -} -void Structure::dump_to_file(std::ostream& file, size_t prec) const { - const int n = 5; - file << label << std::endl; - file << std::fixed << std::setprecision(prec); - file << eweight << " " << fweight << " " << sweight << std::endl; - file << energy << " " << T << std::endl; - - file - << std::setw(prec+n) << cell(0,0) << " " - << std::setw(prec+n) << cell(0,1) << " " - << std::setw(prec+n) << cell(0,2) << " " << std::endl - << std::setw(prec+n) << cell(1,0) << " " - << std::setw(prec+n) << cell(1,1) << " " - << std::setw(prec+n) << cell(1,2) << " " << std::endl - << std::setw(prec+n) << cell(2,0) << " " - << std::setw(prec+n) << cell(2,1) << " " - << std::setw(prec+n) << cell(2,2) << " " << std::endl; - - file - << std::setw(prec+n) << stress(0,0) << " " - << std::setw(prec+n) << stress(0,1) << " " - << std::setw(prec+n) << stress(0,2) << " " << std::endl - << std::setw(prec+n) << stress(1,0) << " " - << std::setw(prec+n) << stress(1,1) << " " - << std::setw(prec+n) << stress(1,2) << " " << std::endl - << std::setw(prec+n) << stress(2,0) << " " - << std::setw(prec+n) << stress(2,1) << " " - << std::setw(prec+n) << stress(2,2) << " " << std::endl; - - for (const auto& a : atoms) { - file << std::setw(2) << a.symbol << " " - << std::setw(prec+n) << a.position[0] << " " - << std::setw(prec+n) << a.position[1] << " " - << std::setw(prec+n) << a.position[2] << " " - << std::setw(prec+n) << a.force[0] << " " - << std::setw(prec+n) << a.force[1] << " " - << std::setw(prec+n) << a.force[2] << std::endl; - } - file << std::endl; -} -void Structure::dump_to_file(const std::string& filepath, size_t prec) const { - std::ofstream file(filepath, std::ios::app); // Open in append mode - if (!file.is_open()) { - std::cerr << "Error: Could not open file for writing: " << filepath << std::endl; - return; - } - dump_to_file(file,prec); - file.close(); -} -std::set<Element> Structure::get_unique_elements() const{ - std::set<Element> unique_elements; - for (const auto& a:atoms) unique_elements.insert(a); - return unique_elements; -} diff --git a/src/structure_db.cpp b/src/structure_db.cpp deleted file mode 100644 index f1aaa36f17971a77b3c18ab8a31e0653aab409fb..0000000000000000000000000000000000000000 --- a/src/structure_db.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "tadah/core/element.h" -#include <tadah/mlip/structure_db.h> -#include <tadah/core/periodic_table.h> -#include <cstdio> -#include <cctype> // For std::isspace - -StructureDB::StructureDB() { - PeriodicTable::initialize(); -} -StructureDB::StructureDB(Config &config) { - PeriodicTable::initialize(); - add(config); -} - -void StructureDB::add(const std::string fn) { - std::ifstream ifs(fn); - if (!ifs.is_open()) { - throw std::runtime_error("DBFILE does not exist: "+fn); - } - parseFile(fn); - while (true) { - structures.push_back(Structure()); - int t = structures.back().read(ifs); - - // did we read structure succesfully? - // if not remove last object from the list - if (t==1) structures.pop_back(); - - if (ifs.eof()) break; - } - ifs.close(); -} -int StructureDB::add(const std::string fn, size_t first, int N) { - std::ifstream ifs(fn); - if (!ifs.is_open()) { - throw std::runtime_error("DBFILE does not exist: "+fn); - } - - // move iterator to the first structure we want to read - for (size_t i=0; i<first; ++i) { - Structure::next_structure(ifs); - } - - int count=0; - while (count++<N) { - structures.push_back(Structure()); - int t = structures.back().read(ifs); - - // did we read structure succesfully? - // if not remove last object from the list - if (t==1) structures.pop_back(); - - if (ifs.eof()) break; - } - ifs.close(); - - return --count; -} - -void StructureDB::add(const Structure &s) { - structures.push_back(s); -} -void StructureDB::add(const StructureDB &stdb) { - for (const auto &s: stdb) add(s); -} - -void StructureDB::remove(size_t i) { - structures.erase(structures.begin()+i); -} - -void StructureDB::add(Config &config) { - for (const std::string &s : config("DBFILE")) { - dbidx.push_back(size()); - add(s); - } - dbidx.push_back(size()); -} - -size_t StructureDB::size() const { - return structures.size(); -} - -size_t StructureDB::size(size_t n) const { - return dbidx[n+1]-dbidx[n]; -} - -Structure &StructureDB::operator()(size_t s) { - return structures[s]; -} - -const Structure &StructureDB::operator()(size_t s) const { - return structures[s]; -} - -Atom &StructureDB::operator()(size_t s, size_t a) { - return structures[s].atoms[a]; -} -size_t StructureDB::calc_natoms() const { - size_t natoms=0; - for (auto struc: structures) natoms += struc.natoms(); - return natoms; -} -size_t StructureDB::calc_natoms(size_t n) const { - size_t start = dbidx[n]; - size_t stop = dbidx[n+1]; - size_t natoms=0; - for (size_t i=start; i<stop; ++i) { - natoms += (*this)(i).natoms(); - } - return natoms; -} -std::set<Element> StructureDB::get_unique_elements() const { - std::set<Element> s; - for (const auto & st: structures) { - std::set<Element> u = st.get_unique_elements(); - s.insert(u.cbegin(),u.cend()); - } - return s; -} -std::set<Element> StructureDB::find_unique_elements(const std::string &fn) { - std::set<Element> s; - std::ifstream ifs(fn); - std::string line; - - if (!ifs.is_open()) { - std::cerr << "Could not open the file." << std::endl; - } - - char symbol[3]; - while (std::getline(ifs, line)) { - // the second line could be energy or - // a scalling factors eweight fweight sweight - std::getline(ifs,line); - std::stringstream stream(line); - size_t count = std::distance(std::istream_iterator<std::string>(stream), - std::istream_iterator<std::string>()); - - if (count == 3) - std::getline(ifs,line); - - for (size_t i=0; i<6; ++i) - std::getline(ifs,line); - - while (std::getline(ifs, line)) { - if(line.empty()) break; - sscanf(line.c_str(), "%2s", symbol); - s.insert(PeriodicTable::find_by_symbol(symbol)); - } - - } - return s; -} -std::set<Element> StructureDB::find_unique_elements(const Config &c) { - std::set<Element> s; - for (const auto& fn: c("DBFILE")) { - std::set<Element> temp = find_unique_elements(fn); - s.insert(temp.begin(), temp.end()); - } - return s; -} - -template <typename T,typename U> -std::pair<T,U> operator+(const std::pair<T,U> &l,const std::pair<T,U> &r) { - return {l.first+r.first,l.second+r.second}; -} -std::pair<int,int> StructureDB::count(const Config &config) { - std::pair<int, int> res=std::make_pair(0,0); - for (const std::string &fn : config("DBFILE")) { - res = res + count(fn); - } - return res; -} - -std::pair<int,int> StructureDB::count(const std::string fn){ - int nstruc=0; - int natoms_tot=0; - - std::ifstream ifs(fn); - if (!ifs.is_open()) { - throw std::runtime_error("DBFILE does not exist: "+fn); - } - int natoms = Structure::next_structure(ifs); - while(natoms) { - natoms_tot += natoms; - natoms = Structure::next_structure(ifs); - nstruc++; - } - - std::pair<int,int> res = std::make_pair(nstruc,natoms_tot); - return res; -} -void StructureDB::clear_nn() { - for (auto &struc: structures) struc.clear_nn(); -} -void StructureDB::check_atoms_key(Config &config, std::set<Element> &unique_elements) { - bool error=false; - - if (config.exist("ATOMS")) { - // user set this key so here we check does it correspond to unique_elements - if (unique_elements.size()!=config.size("ATOMS")) { - error=true; - } - - auto set_it = unique_elements.begin(); - auto atoms_it = config("ATOMS").begin(); - while (set_it != unique_elements.end() && atoms_it != config("ATOMS").end()) { - if (set_it->symbol != (*atoms_it)) { - error=true; - } - ++set_it; - ++atoms_it; - } - if (error) { - throw std::runtime_error("\n" - "Mismatch between elements in datasets and ATOMS in the config file.\n" - "Please either update the ATOMS in the config file or remove ATOMS\n" - "key completely. Tadah! will automatically configure this key.\n" - ); - } - } else { - for (const auto &s : unique_elements) config.add("ATOMS", s.symbol); - } -} -void StructureDB::check_watoms_key(Config &config, std::set<Element> &unique_elements) { - bool error=false; - - if (config.exist("WATOMS")) { - // user set this key so here we check does it correspond to unique_elements - if (unique_elements.size()!=config.size("WATOMS")) { - error=true; - } - if (error) { - throw std::runtime_error("\n" - "Mismatch between elements in datasets and WATOMS in the config file.\n" - "Please either update the WATOMS in the config file or remove WATOMS\n" - "key completely. In the latter case Tadah! will use default values.\n" - ); - } - } else { - for (const auto &s : unique_elements) config.add("WATOMS", s.Z); - } -} - -std::vector<Structure>::iterator StructureDB::begin() { - return structures.begin(); -} - -std::vector<Structure>::iterator StructureDB::end() { - return structures.end(); -} - -std::vector<Structure>::const_iterator StructureDB::begin() const { - return structures.cbegin(); -} - -std::vector<Structure>::const_iterator StructureDB::end() const { - return structures.cend(); -} -void StructureDB::dump_to_file(const std::string& filepath, size_t prec) const { - std::ofstream file(filepath, std::ios::app); // Open in append mode - if (!file.is_open()) { - std::cerr << "Error: Could not open file for writing: " << filepath << std::endl; - return; - } - for (const auto &s : structures) { - s.dump_to_file(file,prec); - } - file.close(); -} - -std::string StructureDB::summary() const { - std::string str = "# of structures : " + to_string(structures.size()); - - str += " | # of atoms : " + to_string(calc_natoms()); - - str += " | Elements : "; - std::set<Element> ue = get_unique_elements(); - for (const auto &e: ue) str+= e.symbol + " "; - str+="\n"; - return str; -} -void StructureDB::parseFile(const std::string& filename) -{ - std::ifstream fin(filename, std::ios::in | std::ios::binary); - if (!fin.is_open()) - { - std::cerr << "Error: could not open file " << filename << "\n"; - return; - } - - std::size_t header_size = 9; - - // Increase buffer size to speed up I/O on large files. - static const size_t BUFSIZE = 100ULL << 20; // 100 MiB - char* buffer = new char[BUFSIZE]; - fin.rdbuf()->pubsetbuf(buffer, BUFSIZE); - - std::vector<size_t> blockLineCounts; - blockLineCounts.reserve(10000); // Pre-allocate to reduce repeated allocations - - size_t currentBlockCount = 0; - std::string line; - - while (true) - { - if (!std::getline(fin, line)) - { - // End of file or read error - break; - } - - if (isBlankLine(line)) - { - // We reached the end of the current block - if (currentBlockCount > 0) - { - blockLineCounts.push_back(currentBlockCount-header_size); - currentBlockCount = 0; - } - } - else - { - // Non-empty line => belongs to the current block - currentBlockCount++; - } - } - - // If the last block didn’t end with a blank line, close it out - if (currentBlockCount > 0) - { - blockLineCounts.push_back(currentBlockCount-header_size); - } - - fin.close(); - delete[] buffer; - - // Print the results - std::cout << "Found " << blockLineCounts.size() << " blocks.\n"; - for (size_t i = 0; i < blockLineCounts.size(); i+=1000) - { - std::cout << "Block " << i << " has " - << blockLineCounts[i] << " atoms\n"; - } -} - -bool StructureDB::isBlankLine(const std::string& line) const -{ - for (char c : line) - { - if (!std::isspace(static_cast<unsigned char>(c))) - { - return false; - } - } - return true; -}