From deb2ea03b5806870b72f39bf9a2a98c3e02eac8a Mon Sep 17 00:00:00 2001 From: chn Date: Fri, 6 Oct 2023 20:22:38 +0800 Subject: [PATCH] merge fold into main --- CMakeLists.txt | 2 +- fold.cpp | 98 -------------------------------------------- include/ufo/fold.hpp | 33 +++++++++++++++ src/fold.cpp | 87 +++++++++++++++++++++++++++++++++++++++ src/main.cpp | 6 ++- test.cpp | 27 ------------ 6 files changed, 126 insertions(+), 127 deletions(-) delete mode 100644 fold.cpp create mode 100644 include/ufo/fold.hpp create mode 100644 src/fold.cpp delete mode 100644 test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 94a92b5..6201320 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ find_package(TBB REQUIRED) find_package(Matplot++ REQUIRED) find_path(ZPP_BITS_INCLUDE_DIR zpp_bits.h REQUIRED) -add_executable(ufo src/unfold.cpp src/plot.cpp src/main.cpp) +add_executable(ufo src/fold.cpp src/unfold.cpp src/plot.cpp src/main.cpp) target_include_directories(ufo PRIVATE ${PROJECT_SOURCE_DIR}/include ${ZPP_BITS_INCLUDE_DIR}) target_link_libraries(ufo PRIVATE yaml-cpp Eigen3::Eigen fmt::fmt concurrencpp::concurrencpp HighFive_HighFive TBB::tbb Matplot++::matplot) diff --git a/fold.cpp b/fold.cpp deleted file mode 100644 index c39db2a..0000000 --- a/fold.cpp +++ /dev/null @@ -1,98 +0,0 @@ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - -using namespace std::literals; - -// 计算单胞中的 q 点在超胞中的对应 - -struct Input -{ - // 单胞的三个格矢,每行表示一个格矢的坐标,单位为埃 - Eigen::Matrix3d PrimativeCell; - // 单胞到超胞的格矢转换时用到的矩阵 - Eigen::Vector SuperCellMultiplier; - Eigen::Matrix SuperCellDeformation; - - // Q 点的坐标,单位为单胞的倒格矢 - std::vector QPointData; -}; -template<> struct YAML::convert { static bool decode(const Node& node, Input& input); }; - -struct Output -{ - // Q 点的坐标,单位为超胞的倒格矢 - std::vector QPointData; -}; - -int main(int argc, char** argv) -{ - if (argc != 3) - throw std::runtime_error("Usage: " + std::string(argv[0]) + " input.yaml output.yaml"); - - auto input = YAML::LoadFile(argv[1]).as(); - Output output; - - for (auto qpoint_by_reciprocal_primative_cell : input.QPointData) - { - // 计算出这个 q 点的绝对坐标, 再计算出它相对于超胞倒格子的相对坐标. 将这个结果取小数部分, 就得到了 meta qpoint 的坐标(相对于超胞倒格子) - std::cout << "PrimativeCell:\n" << input.PrimativeCell << "\n"; - auto reciprocal_primative_cell = input.PrimativeCell.inverse().transpose(); - std::cout << "reciprocal_primative_cell:\n" << reciprocal_primative_cell << "\n"; - auto qpoint = (qpoint_by_reciprocal_primative_cell.transpose() * reciprocal_primative_cell).transpose(); - std::cout << "qpoint:\n" << qpoint << "\n"; - auto reciprocal_super_cell = (input.SuperCellDeformation * input.SuperCellMultiplier.cast().asDiagonal() - * input.PrimativeCell).inverse().transpose(); - std::cout << "reciprocal_super_cell:\n" << reciprocal_super_cell << "\n"; - auto qpoint_by_reciprocal_super_cell = (qpoint.transpose() * reciprocal_super_cell.inverse()).transpose(); - std::cout << "qpoint_by_reciprocal_super_cell:\n" << qpoint_by_reciprocal_super_cell << "\n"; - auto meta_qpoint_by_reciprocal_super_cell = [&] - { auto _ = qpoint_by_reciprocal_super_cell.array(); return _ - _.floor(); }(); - std::cout << "meta_qpoint_by_reciprocal_super_cell:\n" << meta_qpoint_by_reciprocal_super_cell << "\n"; - output.QPointData.push_back(meta_qpoint_by_reciprocal_super_cell); - } - - std::ofstream(argv[2]) << [&] - { - std::stringstream print; - print << "QPointData:\n"; - for (auto& qpoint: output.QPointData) - print << fmt::format(" - [ {:.3f}, {:.3f}, {:.3f} ]\n", qpoint(0), qpoint(1), qpoint(2)); - return print.str(); - }(); -} - -bool YAML::convert::decode(const Node& node, Input& input) -{ - for (unsigned i = 0; i < 3; i++) - for (unsigned j = 0; j < 3; j++) - input.PrimativeCell(i, j) = node["lattice"][i][j].as(); - - input.SuperCellMultiplier.setZero(); - for (unsigned i = 0; i < 3; i++) - input.SuperCellMultiplier(i) = node["SuperCellMultiplier"][i].as(); - - for (unsigned i = 0; i < 3; i++) - for (unsigned j = 0; j < 3; j++) - input.SuperCellDeformation(i, j) = node["SuperCellDeformation"][i][j].as(); - - auto points = node["points"].as>>(); - - input.QPointData.resize(points.size()); - for (unsigned i = 0; i < points.size(); i++) - { - for (unsigned j = 0; j < 3; j++) - input.QPointData[i](j) = points[i][j]; - } - - return true; -} diff --git a/include/ufo/fold.hpp b/include/ufo/fold.hpp new file mode 100644 index 0000000..4179737 --- /dev/null +++ b/include/ufo/fold.hpp @@ -0,0 +1,33 @@ +# pragma once +# include + +namespace ufo +{ + class FoldSolver : public Solver + { + public: + struct InputType + { + Eigen::Matrix3d PrimativeCell; + Eigen::Vector SuperCellMultiplier; + std::optional> SuperCellDeformation; + std::vector Qpoints; + std::string OutputFilename; + + InputType(std::string config_file); + }; + struct OutputType + { + std::vector QPoints; + void write(std::string filename) const; + }; + protected: + InputType Input_; + std::optional Output_; + public: + FoldSolver(std::string config_file); + FoldSolver& operator()() override; + static Eigen::Vector3d fold(Eigen::Vector3d qpoint, Eigen::Vector super_cell_multiplier, + std::optional> super_cell_deformation); + }; +} \ No newline at end of file diff --git a/src/fold.cpp b/src/fold.cpp new file mode 100644 index 0000000..8f30e82 --- /dev/null +++ b/src/fold.cpp @@ -0,0 +1,87 @@ +# include + +namespace ufo +{ + FoldSolver::InputType::InputType(std::string config_file) + { + auto input = YAML::LoadFile(config_file); + for (unsigned i = 0; i < 3; i++) + for (unsigned j = 0; j < 3; j++) + PrimativeCell(i, j) = input["PrimativeCell"][i][j].as(); + for (unsigned i = 0; i < 3; i++) + SuperCellMultiplier(i) = input["SuperCellMultiplier"][i].as(); + if (input["SuperCellDeformation"]) + { + SuperCellDeformation.emplace(); + for (unsigned i = 0; i < 3; i++) + for (unsigned j = 0; j < 3; j++) + (*SuperCellDeformation)(i, j) = input["SuperCellDeformation"][i][j].as(); + } + for (auto& qpoint : input["Qpoints"].as>>()) + Qpoints.push_back(Eigen::Vector3d + {{qpoint.at(0)}, {qpoint.at(1)}, {qpoint.at(2)}}); + OutputFilename = input["OutputFilename"].as(); + } + void FoldSolver::OutputType::write(std::string filename) const + { + std::ofstream(filename) << [&] + { + std::stringstream print; + print << "QPoints:\n"; + for (auto& qpoint : QPoints) + print << fmt::format(" - [ {:.8f}, {:.8f}, {:.8f} ]\n", qpoint(0), qpoint(1), qpoint(2)); + return print.str(); + }(); + } + + FoldSolver::FoldSolver(std::string config_file) : Input_(config_file) {} + FoldSolver& FoldSolver::operator()() + { + if (!Output_) + { + Output_.emplace(); + for (auto& qpoint : Input_.Qpoints) + Output_->QPoints.push_back(fold + ( + qpoint, Input_.SuperCellMultiplier, + Input_.SuperCellDeformation + )); + } + Output_->write(Input_.OutputFilename); + return *this; + } + + Eigen::Vector3d FoldSolver::fold + ( + Eigen::Vector3d qpoint, Eigen::Vector super_cell_multiplier, + std::optional> super_cell_deformation + ) + { + // 首先需要将 q 点转移到超胞的倒格子中 + // 将 q 点坐标扩大, 然后取小数部分, 就可以了 + auto qpoint_by_reciprocal_modified_super_cell = super_cell_multiplier.cast().asDiagonal() * qpoint; + auto qpoint_in_reciprocal_modified_super_cell_by_reciprocal_modified_super_cell = + (qpoint_by_reciprocal_modified_super_cell.array() - qpoint_by_reciprocal_modified_super_cell.array().floor()) + .matrix(); + if (!super_cell_deformation) + return qpoint_in_reciprocal_modified_super_cell_by_reciprocal_modified_super_cell; + /* + 对 q 点平移数个 SupreCell, 直到它落在超胞的倒格子中 + 这等价于直接将 q 点坐标用 SuperCell 的倒格子表示, 然后取小数部分. + ModifiedSuperCell = SuperCellMultiplier * PrimativeCell + SuperCell = SuperCellDeformation * ModifiedSuperCell + ReciprocalModifiedSuperCell = ModifiedSuperCell.inverse().transpose() + ReciprocalSuperCell = SuperCell.inverse().transpose() + Qpoint = QpointByReciprocalModifiedSuperCell.transpose() * ReciprocalModifiedSuperCell + Qpoint = QpointByReciprocalSuperCell.transpose() * ReciprocalSuperCell + 整理可以得到: + QpointByReciprocalSuperCell = SuperCellDeformation * QpointByReciprocalModifiedSuperCell + */ + auto qpoint_in_reciprocal_modified_super_cell_by_reciprocal_super_cell = + (*super_cell_deformation * qpoint_in_reciprocal_modified_super_cell_by_reciprocal_modified_super_cell).eval(); + auto qpoint_in_reciprocal_super_cell_by_reciprocal_super_cell = + qpoint_in_reciprocal_modified_super_cell_by_reciprocal_super_cell.array() + - qpoint_in_reciprocal_modified_super_cell_by_reciprocal_super_cell.array().floor(); + return qpoint_in_reciprocal_super_cell_by_reciprocal_super_cell; + } +} diff --git a/src/main.cpp b/src/main.cpp index 01edab6..8bed4aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,14 @@ +# include +# include # include int main(int argc, const char** argv) { if (argc != 3) throw std::runtime_error(fmt::format("Usage: {} task config.yaml", argv[0])); - if (argv[1] == std::string("unfold")) + if (argv[1] == std::string("fold")) + ufo::FoldSolver{argv[2]}(); + else if (argv[1] == std::string("unfold")) ufo::UnfoldSolver{argv[2]}(); else if (argv[1] == std::string("plot")) ufo::PlotSolver{argv[2]}(); diff --git a/test.cpp b/test.cpp deleted file mode 100644 index 74c0c45..0000000 --- a/test.cpp +++ /dev/null @@ -1,27 +0,0 @@ -# include -# include -# include -# include -# include - -namespace Eigen -{ - constexpr auto serialize(auto & archive, Eigen::Matrix3d& matrix) - { - return archive(std::span(matrix.data(), 9)); - } - constexpr auto serialize(auto & archive, const Eigen::Matrix3d& matrix) - { - return archive(std::span(matrix.data(), 9)); - } -} - -int main() -{ - auto [data, in, out] = zpp::bits::data_in_out(); - std::vector PrimativeCell = { Eigen::Matrix3d::Identity() }; - out(PrimativeCell).or_throw(); - std::vector PrimativeCell2; - in(PrimativeCell2).or_throw(); - std::cout << PrimativeCell2[0] << std::endl; -} \ No newline at end of file