# 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; }