/** * loads atom dynamics file * @author Tobias Weber * @date Dec-2019 * @license GPLv3, see 'LICENSE' file */ #ifndef __MOLDYN_H__ #define __MOLDYN_H__ #include #include #include #include // for progress callback #include #include "libs/file.h" #include "libs/str.h" template class MolFrame { public: MolFrame() { m_config.reserve(128); } void AddAtomConfig(std::vector&& config) { m_config.emplace_back(std::move(config)); } void AddAtomConfig(const std::vector& config) { m_config.push_back(config); } std::size_t GetNumAtoms() const { return m_config.size(); } const std::vector& GetCoords(std::size_t atomidx) const { return m_config[atomidx]; } /** * removes all atoms at index idx */ void RemoveAtoms(std::size_t idx) { m_config.erase(m_config.begin()+idx); } private: // atoms -> coordinates std::vector> m_config; }; template class MolDyn { public: MolDyn() : m_baseA(3), m_baseB(3), m_baseC(3) { m_frames.reserve(16384); } void SetBaseA(t_real x, t_real y, t_real z) { m_baseA[0] = x; m_baseA[1] = y; m_baseA[2] = z; } void SetBaseB(t_real x, t_real y, t_real z) { m_baseB[0] = x; m_baseB[1] = y; m_baseB[2] = z; } void SetBaseC(t_real x, t_real y, t_real z) { m_baseC[0] = x; m_baseC[1] = y; m_baseC[2] = z; } const t_vec& GetBaseA() const { return m_baseA; } const t_vec& GetBaseB() const { return m_baseB; } const t_vec& GetBaseC() const { return m_baseC; } std::size_t GetFrameCount() const { return m_frames.size(); } const MolFrame& GetFrame(std::size_t frame) const { return m_frames[frame]; } std::size_t GetAtomCount() const { return m_vecAtoms.size(); } const std::string& GetAtomName(std::size_t idx) const { return m_vecAtoms[idx]; } unsigned int GetAtomNum(std::size_t idx) const { return m_vecAtomNums[idx]; } void AddAtomType(const std::string& name, unsigned int number) { m_vecAtoms.push_back(name); m_vecAtomNums.push_back(number); } void AddFrame(MolFrame&& frame) { m_frames.emplace_back(std::move(frame)); } void AddFrame(const MolFrame& frame) { m_frames.push_back(frame); } /** * removes all atoms at index idx */ void RemoveAtoms(std::size_t idx) { m_vecAtoms.erase(m_vecAtoms.begin() + idx); m_vecAtomNums.erase(m_vecAtomNums.begin() + idx); for(MolFrame& frame : m_frames) frame.RemoveAtoms(idx); } void Clear() { m_vecAtoms.clear(); m_vecAtomNums.clear(); m_frames.clear(); m_sigLoadProgress.disconnect_all_slots(); m_sigSaveProgress.disconnect_all_slots(); } /** * loading of files */ bool LoadFile(const std::string& filename, unsigned int frameskip = 0) { const std::string strDelim{" \t"}; std::ifstream ifstr{filename}; if(!ifstr) { std::cerr << "Cannot open \"" << filename << "\" for loading."; return 0; } std::size_t filesize = tl2::get_file_size(ifstr); std::cout << "File size: " << filesize / 1024 / 1024 << " MB." << std::endl; std::getline(ifstr, m_strSys); tl2::trim(m_strSys); std::cout << "System: " << m_strSys << std::endl; std::string strScale; std::getline(ifstr, strScale); t_real scale = tl2::str_to_var(strScale); std::cout << "scale: " << scale << std::endl; std::string strVecs1; std::string strVecs2; std::string strVecs3; std::getline(ifstr, strVecs1); std::getline(ifstr, strVecs2); std::getline(ifstr, strVecs3); std::vector _vecBase1, _vecBase2, _vecBase3; tl2::get_tokens(strVecs1, strDelim, _vecBase1); tl2::get_tokens(strVecs2, strDelim, _vecBase2); tl2::get_tokens(strVecs3, strDelim, _vecBase3); if(_vecBase1.size()!=3 || _vecBase2.size()!=3 || _vecBase3.size()!=3) { std::cerr << "Invalid base vectors." << std::endl; return 0; } SetBaseA(_vecBase1[0]*scale, _vecBase2[0]*scale, _vecBase3[0]*scale); SetBaseB(_vecBase1[1]*scale, _vecBase2[1]*scale, _vecBase3[1]*scale); SetBaseC(_vecBase1[2]*scale, _vecBase2[2]*scale, _vecBase3[2]*scale); std::string strAtoms; std::string strAtomNums; std::getline(ifstr, strAtoms); std::getline(ifstr, strAtomNums); tl2::get_tokens(strAtoms, strDelim, m_vecAtoms); tl2::get_tokens(strAtomNums, strDelim, m_vecAtomNums); if(m_vecAtoms.size() != m_vecAtomNums.size()) { std::cerr << "Atom size mismatch." << std::endl; return 0; } for(std::size_t i=0; i frame; for(std::size_t iAtomType=0; iAtomType atomconf; for(std::size_t iAtom=0; iAtom(strCoords, strDelim, vecCoords); if(vecCoords.size() != 3) { std::cerr << "Invalid coordinate." << std::endl; return 0; } // center cell (in rlu) vecCoords[0] -= 0.5; vecCoords[1] -= 0.5; vecCoords[2] -= 0.5; atomconf.emplace_back(std::move(vecCoords)); } frame.AddAtomConfig(std::move(atomconf)); } AddFrame(std::move(frame)); ++iNumConfigs; // skip frames for(unsigned int skipped=0; skipped& config = m_frames[frame]; // iterate atom types for(std::size_t atomidx=0; atomidx void SubscribeToLoadProgress(const subscriber& subs) { m_sigLoadProgress.connect(subs); } template void SubscribeToSaveProgress(const subscriber& subs) { m_sigSaveProgress.connect(subs); } template void UnsubscribeFromLoadProgress(const subscriber* subs=nullptr) { // TODO //if(!subs) m_sigLoadProgress.disconnect_all_slots(); } template void UnsubscribeFromSaveProgress(const subscriber* subs=nullptr) { // TODO //if(!subs) m_sigSaveProgress.disconnect_all_slots(); } private: std::string m_strSys; t_vec m_baseA; t_vec m_baseB; t_vec m_baseC; std::vector m_vecAtoms; std::vector m_vecAtomNums; std::vector> m_frames; boost::signals2::signal m_sigLoadProgress; boost::signals2::signal m_sigSaveProgress; }; #endif