plot 完成模式的查找

This commit is contained in:
2023-09-26 18:54:11 +08:00
parent 312dbd0529
commit e042ae4c15
5 changed files with 127 additions and 93 deletions

View File

@@ -1,93 +1,107 @@
# include <ufo/ufo.impl.hpp>
// 一个临时的程序, 用于将数据导出画图
struct Output
class FloatVector
{
struct QPointDataType_
{
std::vector<double> QPoint;
struct ModeDataType_
protected:
std::vector<double> Data_;
double LowerBound_, UpperBound_, Step_;
public:
FloatVector(double LowerBound, double UpperBound, double Step)
: LowerBound_(LowerBound), UpperBound_(UpperBound), Step_(Step), Data_((UpperBound - LowerBound) / Step + 1) {}
FloatVector(const FloatVector&) = default;
FloatVector(FloatVector&&) = default;
FloatVector& operator=(const FloatVector&) = default;
FloatVector& operator=(FloatVector&&) = default;
double& operator[](double i) { return Data_[static_cast<int>((i - LowerBound_) / Step_)]; }
double operator[](double i) const { return Data_[static_cast<int>((i - LowerBound_) / Step_)]; }
double lower_bound() const { return LowerBound_; }
double upper_bound() const { return UpperBound_; }
double step() const { return Step_; }
int size() const { return Data_.size(); }
std::map<double, double> to_map() const
{
double Frequency;
double Weight;
};
std::vector<ModeDataType_> ModeData;
};
std::vector<QPointDataType_> QPointData;
std::map<double, double> result;
for (int i = 0; i < Data_.size(); i++)
result[LowerBound_ + i * Step_] = Data_[i];
return result;
}
};
// BAND = 0.000000 0.000000 0.000000 0.500000 0.000000 0.000000 0.333333 0.333333 0.000000 0.000000 0.000000 0.000000 0 0 0.5 0.5 0 0.5 0.333333 0.333333 0.5 0 0 0.5
// BAND_LABELS = $\Gamma$ M K $\Gamma$ A L H A
// Gamma 0 0 0
// M 1/2 0 0
// K 1/3 1/3 0
// A 0 0 1/2
// L 1/2 0 1/2
// H 1/3 1/3 1/2
std::vector<std::vector<double>> Qpoints =
// 要被用来画图的路径
std::vector<Eigen::Vector3d> Qpoints =
{
{0, 0, 0},
{0.025, 0, 0},
{0.05, 0, 0},
{0.075, 0, 0},
{0.1, 0, 0},
{0.125, 0, 0},
{0.15, 0, 0},
{0.175, 0, 0},
{0.2, 0, 0},
{0.225, 0, 0},
{0.25, 0, 0},
{0.275, 0, 0},
{0.3, 0, 0},
{0.325, 0, 0},
{0.35, 0, 0},
{0.375, 0, 0},
{0.4, 0, 0},
{0.425, 0, 0},
{0.45, 0, 0},
{0.475, 0, 0},
{0.5, 0, 0}
{ 0, 0, 0 },
{ 0.5, 0, 0 },
{ 1. / 3, 1. / 3, 0 },
{ 0, 0, 0 },
{ 0, 0, 0.5 },
{ 0.5, 0, 0.5 },
{ 1. / 3, 1. / 3, 0.5 },
{ 0, 0, 0.5 }
};
double Threshold = 0.001;
int main(int argc, char** argv)
{
YAML::Node root = YAML::LoadFile(argv[1]);
Output output;
output.QPointData.resize(root["QPointData"].size());
for (int i = 0; i < root["QPointData"].size(); i++)
{
output.QPointData[i].QPoint = root["QPointData"][i]["QPoint"].as<std::vector<double>>();
output.QPointData[i].ModeData.resize(root["QPointData"][i]["ModeData"].size());
for (int j = 0; j < root["QPointData"][i]["ModeData"].size(); j++)
{
output.QPointData[i].ModeData[j].Frequency
= root["QPointData"][i]["ModeData"][j]["Frequency"].as<double>();
output.QPointData[i].ModeData[j].Weight
= root["QPointData"][i]["ModeData"][j]["Weight"].as<double>();
}
}
if (argc != 2)
throw std::runtime_error("Usage: plot output.zpp");
// 外层表示 q 点坐标, 内层表示频率
// 频率取 -5 到 30 THz, 每 0.1 THz 一个点
std::vector<std::vector<double>> data(21);
for (int i = 0; i < 21; i++)
Output output(argv[1]);
//
struct Point
{
data[i].resize(351);
Eigen::Vector3d QPoint;
FloatVector Weight;
double Distance;
};
std::vector<Point> Points;
double current_distance = 0;
// 对于每一条路径进行搜索
for (unsigned i = 0; i < Qpoints.size() - 1; i++)
{
std::vector<Point> point_of_this_path;
// 对于 output 中的每一个点, 检查这个点是否在路径上. 如果在, 把它加入到 point_of_this_path 中
for (auto& qpoint : output.QPointData)
if (std::abs(qpoint.QPoint[0] - Qpoints[i][0]) < 1e-3 &&
std::abs(qpoint.QPoint[1] - Qpoints[i][1]) < 1e-3 &&
std::abs(qpoint.QPoint[2] - Qpoints[i][2]) < 1e-3)
{
// 计算三点围成的三角形的面积的两倍
auto area = (Qpoints[i + 1] - Qpoints[i]).cross(qpoint.QPoint - Qpoints[i]).norm();
// 计算这个点到前两个点所在直线的距离
auto distance = area / (Qpoints[i + 1] - Qpoints[i]).norm();
// 如果这个点到前两个点所在直线的距离小于阈值, 则认为这个点在路径上
if (distance < Threshold)
{
for (auto& mode : qpoint.ModeData)
data[i][static_cast<int>((mode.Frequency + 5) * 10)] += mode.Weight;
break;
// 计算这个点到前两个点的距离, 两个距离都应该小于两点之间的距离
auto distance1 = (qpoint.QPoint - Qpoints[i]).norm();
auto distance2 = (qpoint.QPoint - Qpoints[i + 1]).norm();
auto distance3 = (Qpoints[i + 1] - Qpoints[i]).norm();
if (distance1 < distance3 + Threshold && distance2 < distance3 + Threshold)
// 如果这个点在终点处, 且这条路径不是最后一条, 则不加入
if (distance2 > Threshold || i == Qpoints.size() - 2)
{
auto& _ = point_of_this_path.emplace_back
(qpoint.QPoint, FloatVector{-5, 35, 0.1}, distance1);
for (auto& mode : qpoint.ModeData)
_.Weight[mode.Frequency] += mode.Weight;
}
}
}
// 对筛选结果排序
std::sort(point_of_this_path.begin(), point_of_this_path.end(),
[](const Point& a, const Point& b) { return a.Distance < b.Distance; });
// 去除非常接近的点
for (unsigned j = 1; j < point_of_this_path.size(); j++)
while
(
j < point_of_this_path.size()
&& point_of_this_path[j].Distance - point_of_this_path[j - 1].Distance < Threshold
)
point_of_this_path.erase(point_of_this_path.begin() + j);
// 将结果加入
for (auto& point : point_of_this_path)
Points.emplace_back(point.QPoint, point.Weight, point.Distance + current_distance);
current_distance += (Qpoints[i + 1] - Qpoints[i]).norm();
}
matplot::image(data, true);
matplot::colorbar().limits({0, 0.5});
matplot::show();
}