统一外部数据的读取

This commit is contained in:
陈浩南 2023-10-12 17:58:13 +08:00
parent 4b2971d54d
commit 3c4f60bf8f
8 changed files with 78 additions and 86 deletions

View File

@ -11,7 +11,7 @@ namespace ufo
Eigen::Vector<unsigned, 3> SuperCellMultiplier; Eigen::Vector<unsigned, 3> SuperCellMultiplier;
std::optional<Eigen::Matrix<double, 3, 3>> SuperCellDeformation; std::optional<Eigen::Matrix<double, 3, 3>> SuperCellDeformation;
std::vector<Eigen::Vector3d> Qpoints; std::vector<Eigen::Vector3d> Qpoints;
std::string OutputFilename; DataFile OutputFile;
InputType(std::string config_file); InputType(std::string config_file);
}; };

View File

@ -16,10 +16,8 @@ namespace ufo
std::pair<unsigned, unsigned> Resolution; std::pair<unsigned, unsigned> Resolution;
std::pair<double, double> Range; std::pair<double, double> Range;
std::optional<std::vector<double>> YTicks; std::optional<std::vector<double>> YTicks;
std::string PictureFilename; DataFile PictureFile;
std::optional<std::vector<DataFile>> DataFiles;
struct DataFileType { std::string Filename, Format; };
std::optional<std::vector<DataFileType>> DataFiles;
}; };
std::vector<FigureConfigType> Figures; std::vector<FigureConfigType> Figures;
@ -28,7 +26,7 @@ namespace ufo
UnfoldedDataType(std::string filename); UnfoldedDataType(std::string filename);
UnfoldedDataType() = default; UnfoldedDataType() = default;
}; };
std::string UnfoldedDataFilename; DataFile UnfoldedDataFile;
UnfoldedDataType UnfoldedData; UnfoldedDataType UnfoldedData;
InputType(std::string config_file); InputType(std::string config_file);

View File

@ -121,6 +121,20 @@ namespace ufo
protected: protected:
std::optional<HighFive::File> File_; std::optional<HighFive::File> File_;
}; };
struct DataFile
{
std::string Filename;
std::string Format;
std::map<std::string, std::any> ExtraParameters;
inline DataFile() = default;
DataFile
(
YAML::Node node, std::set<std::string> supported_format,
std::string config_file, bool allow_same_as_config_file = false
);
};
}; };
} }

View File

@ -32,17 +32,10 @@ namespace ufo
// 在单胞内取几个平面波的基矢 // 在单胞内取几个平面波的基矢
Eigen::Vector<unsigned, 3> PrimativeCellBasisNumber; Eigen::Vector<unsigned, 3> PrimativeCellBasisNumber;
struct InputOutputFile
{
std::string FileName;
std::string Format;
std::map<std::string, std::any> ExtraParameters;
};
// 从哪个文件读入 AtomPosition, 以及这个文件的格式, 格式可选值包括 "yaml" // 从哪个文件读入 AtomPosition, 以及这个文件的格式, 格式可选值包括 "yaml"
InputOutputFile AtomPositionInputFile; DataFile AtomPositionInputFile;
// 从哪个文件读入 QpointData, 以及这个文件的格式, 格式可选值包括 "yaml" 和 "hdf5" // 从哪个文件读入 QpointData, 以及这个文件的格式, 格式可选值包括 "yaml" 和 "hdf5"
InputOutputFile QpointDataInputFile; DataFile QpointDataInputFile;
// 超胞中原子的坐标,每行表示一个原子的坐标,单位为埃 // 超胞中原子的坐标,每行表示一个原子的坐标,单位为埃
Eigen::MatrixX3d AtomPosition; Eigen::MatrixX3d AtomPosition;
@ -72,7 +65,7 @@ namespace ufo
// yaml-human-readable: 使用 yaml 格式输出, 但是输出的结果更适合人类阅读, // yaml-human-readable: 使用 yaml 格式输出, 但是输出的结果更适合人类阅读,
// 包括合并相近的模式, 去除权重过小的模式, 限制输出的小数位数. // 包括合并相近的模式, 去除权重过小的模式, 限制输出的小数位数.
// zpp: 使用 zpp-bits 序列化, 可以直接被 plot.cpp 读取 // zpp: 使用 zpp-bits 序列化, 可以直接被 plot.cpp 读取
std::vector<InputOutputFile> QpointDataOutputFile; std::vector<DataFile> QpointDataOutputFile;
// 从文件中读取输入 (包括一个较小的配置文件, 和一个 hdf5 或者一个 yaml 文件), 文件中应当包含: // 从文件中读取输入 (包括一个较小的配置文件, 和一个 hdf5 或者一个 yaml 文件), 文件中应当包含:
// 单胞的格矢: PrimativeCell 单位为埃 直接从 phonopy 的输出中复制 // 单胞的格矢: PrimativeCell 单位为埃 直接从 phonopy 的输出中复制

View File

@ -17,7 +17,7 @@ namespace ufo
for (auto& qpoint : input["Qpoints"].as<std::vector<std::vector<double>>>()) for (auto& qpoint : input["Qpoints"].as<std::vector<std::vector<double>>>())
Qpoints.push_back(Eigen::Vector3d Qpoints.push_back(Eigen::Vector3d
{{qpoint.at(0)}, {qpoint.at(1)}, {qpoint.at(2)}}); {{qpoint.at(0)}, {qpoint.at(1)}, {qpoint.at(2)}});
OutputFilename = input["OutputFilename"].as<std::string>(); OutputFile = DataFile(input["OutputFile"], {"yaml"}, config_file);
} }
void FoldSolver::OutputType::write(std::string filename) const void FoldSolver::OutputType::write(std::string filename) const
{ {
@ -44,7 +44,7 @@ namespace ufo
Input_.SuperCellDeformation Input_.SuperCellDeformation
)); ));
} }
Output_->write(Input_.OutputFilename); Output_->write(Input_.OutputFile.Filename);
return *this; return *this;
} }

View File

@ -30,27 +30,20 @@ namespace ufo
throw std::runtime_error("Not enough lines in a figure"); throw std::runtime_error("Not enough lines in a figure");
Figures.back().Resolution = figure["Resolution"].as<std::pair<unsigned, unsigned>>(); Figures.back().Resolution = figure["Resolution"].as<std::pair<unsigned, unsigned>>();
Figures.back().Range = figure["Range"].as<std::pair<double, double>>(); Figures.back().Range = figure["Range"].as<std::pair<double, double>>();
Figures.back().PictureFilename = figure["PictureFilename"].as<std::string>(); Figures.back().PictureFile
= DataFile(figure["PictureFile"], {"png"}, config_file);
if (figure["YTicks"]) if (figure["YTicks"])
Figures.back().YTicks = figure["YTicks"].as<std::vector<double>>(); Figures.back().YTicks = figure["YTicks"].as<std::vector<double>>();
if (figure["DataFiles"]) if (figure["DataFiles"])
{ {
Figures.back().DataFiles.emplace(); Figures.back().DataFiles.emplace();
for (auto& data_file : figure["DataFiles"].as<std::vector<YAML::Node>>()) for (auto& data_file : figure["DataFiles"].as<std::vector<YAML::Node>>())
{ Figures.back().DataFiles->emplace_back()
Figures.back().DataFiles->emplace_back = DataFile(data_file, {"hdf5", "zpp"}, config_file);
(
data_file["Filename"].as<std::string>(),
data_file["Format"].as<std::string>()
);
if (!std::set{ "hdf5"s, "zpp"s }.contains(Figures.back().DataFiles->back().Format))
throw std::runtime_error(fmt::format("Unknown data file format: {}",
Figures.back().DataFiles->back().Format));
}
} }
} }
UnfoldedDataFilename = input["UnfoldedDataFilename"].as<std::string>(); UnfoldedDataFile = DataFile(input["UnfoldedDataFile"], {"zpp"}, config_file);
UnfoldedData = UnfoldedDataType(UnfoldedDataFilename); UnfoldedData = UnfoldedDataType(UnfoldedDataFile.Filename);
} }
const PlotSolver::OutputType& PlotSolver::OutputType::write(std::string filename, std::string format) const const PlotSolver::OutputType& PlotSolver::OutputType::write(std::string filename, std::string format) const
{ {
@ -96,7 +89,7 @@ namespace ufo
auto y_ticks = figure.YTicks.value_or(std::vector<double>{}); auto y_ticks = figure.YTicks.value_or(std::vector<double>{});
for (auto& _ : y_ticks) for (auto& _ : y_ticks)
_ = (_ - figure.Range.first) / (figure.Range.second - figure.Range.first) * figure.Resolution.second; _ = (_ - figure.Range.first) / (figure.Range.second - figure.Range.first) * figure.Resolution.second;
plot(values, figure.PictureFilename, x_ticks, y_ticks); plot(values, figure.PictureFile.Filename, x_ticks, y_ticks);
Output_->emplace_back(); Output_->emplace_back();
Output_->back().Values = std::move(values); Output_->back().Values = std::move(values);
Output_->back().XTicks = std::move(x_ticks); Output_->back().XTicks = std::move(x_ticks);

View File

@ -14,4 +14,34 @@ namespace ufo
x * range[1] * range[2] + y * range[2] + z x * range[1] * range[2] + y * range[2] + z
}; };
} }
Solver::DataFile::DataFile
(YAML::Node node, std::set<std::string> supported_format, std::string config_file, bool allow_same_as_config_file)
{
if (auto _ = node["SameAsConfigFile"])
{
auto __ = _.as<bool>();
if (__ && !allow_same_as_config_file)
throw std::runtime_error("\"SameAsConfigFile: true\" is not allowed here.");
ExtraParameters["SameAsConfigFile"] = __;
if (__)
{
Filename = config_file;
Format = "yaml";
return;
}
}
Filename = node["Filename"].as<std::string>();
Format = node["Format"].as<std::string>();
if (!supported_format.contains(Format))
throw std::runtime_error(fmt::format("Unsupported format: \"{}\"", Format));
if (auto _ = node["RelativeToConfigFile"])
{
auto __ = _.as<bool>();
ExtraParameters["RelativeToConfigFile"] = __;
if (__)
Filename = std::filesystem::path(config_file).parent_path() / Filename;
}
};
} }

View File

@ -25,67 +25,31 @@ namespace ufo
for (unsigned i = 0; i < 3; i++) for (unsigned i = 0; i < 3; i++)
PrimativeCellBasisNumber(i) = node["PrimativeCellBasisNumber"][i].as<int>(); PrimativeCellBasisNumber(i) = node["PrimativeCellBasisNumber"][i].as<int>();
auto read_file_config = [filename](YAML::Node source, InputOutputFile& config) AtomPositionInputFile = DataFile
{ (
if (auto _ = source["SameAsConfigFile"]) node["AtomPositionInputFile"], {"yaml"},
{ filename, true
auto __ = _.as<bool>(); );
config.ExtraParameters["SameAsConfigFile"] = __; QpointDataInputFile = DataFile
if (__) (
{ node["QpointDataInputFile"], {"yaml", "hdf5"},
config.FileName = filename; filename, true
config.Format = "yaml"; );
return;
}
}
config.FileName = source["FileName"].as<std::string>();
config.Format = source["Format"].as<std::string>();
if (auto _ = source["RelativeToConfigFile"])
{
auto __ = _.as<bool>();
config.ExtraParameters["RelativeToConfigFile"] = __;
if (__)
config.FileName = std::filesystem::path(filename).parent_path() / config.FileName;
}
};
read_file_config(node["AtomPositionInputFile"], AtomPositionInputFile);
if (!std::set<std::string>{"yaml"}.contains(AtomPositionInputFile.Format))
throw std::runtime_error(fmt::format
("Unknown AtomPositionInputFile.Format: {}, should be \"yaml\".", AtomPositionInputFile.Format));
read_file_config(node["QpointDataInputFile"], QpointDataInputFile);
if (!std::set<std::string>{"yaml", "hdf5"}.contains(QpointDataInputFile.Format))
throw std::runtime_error(fmt::format
("Unknown QpointDataInputFile.Format: {}, should be \"yaml\" or \"hdf5\".", QpointDataInputFile.Format));
if (auto value = node["QpointDataOutputFile"]) if (auto value = node["QpointDataOutputFile"])
{ {
QpointDataOutputFile.resize(value.size()); QpointDataOutputFile.resize(value.size());
for (unsigned i = 0; i < value.size(); i++) for (unsigned i = 0; i < value.size(); i++)
{ QpointDataOutputFile[i] = DataFile
read_file_config(value[i], QpointDataOutputFile[i]);
if
( (
QpointDataOutputFile[i].ExtraParameters.contains("SameAsConfigFile") value[i], {"yaml", "yaml-human-readable", "zpp", "hdf5"},
&& std::any_cast<bool>(QpointDataOutputFile[i].ExtraParameters["SameAsConfigFile"]) filename, false
) );
throw std::runtime_error("QpointDataOutputFile.SameAsConfigFile should not be set.");
if
(
!std::set<std::string>{"yaml", "yaml-human-readable", "zpp", "hdf5"}
.contains(QpointDataOutputFile[i].Format)
)
throw std::runtime_error(fmt::format
(
"Unknown QpointDataOutputFile[{}].Format: {}, should be "
"\"yaml\", \"yaml-human-readable\", \"zpp\" or \"hdf5\".",
i, QpointDataOutputFile[i].Format
));
}
} }
} }
if (AtomPositionInputFile.Format == "yaml") if (AtomPositionInputFile.Format == "yaml")
{ {
auto node = YAML::LoadFile(AtomPositionInputFile.FileName); auto node = YAML::LoadFile(AtomPositionInputFile.Filename);
std::vector<YAML::Node> points; std::vector<YAML::Node> points;
if (auto _ = node["points"]) if (auto _ = node["points"])
points = _.as<std::vector<YAML::Node>>(); points = _.as<std::vector<YAML::Node>>();
@ -101,7 +65,7 @@ namespace ufo
} }
if (QpointDataInputFile.Format == "yaml") if (QpointDataInputFile.Format == "yaml")
{ {
auto node = YAML::LoadFile(QpointDataInputFile.FileName); auto node = YAML::LoadFile(QpointDataInputFile.Filename);
auto phonon = node["phonon"].as<std::vector<YAML::Node>>(); auto phonon = node["phonon"].as<std::vector<YAML::Node>>();
QpointData.resize(phonon.size()); QpointData.resize(phonon.size());
for (unsigned i = 0; i < phonon.size(); i++) for (unsigned i = 0; i < phonon.size(); i++)
@ -135,7 +99,7 @@ namespace ufo
{ {
std::vector<std::vector<std::vector<double>>> frequency, path; std::vector<std::vector<std::vector<double>>> frequency, path;
std::vector<std::vector<std::vector<std::vector<PhonopyComplex>>>> eigenvector_vector; std::vector<std::vector<std::vector<std::vector<PhonopyComplex>>>> eigenvector_vector;
Hdf5file{}.open_for_read(QpointDataInputFile.FileName).read(frequency, "/frequency") Hdf5file{}.open_for_read(QpointDataInputFile.Filename).read(frequency, "/frequency")
.read(eigenvector_vector, "/eigenvector") .read(eigenvector_vector, "/eigenvector")
.read(path, "/path"); .read(path, "/path");
std::vector size = { frequency.size(), frequency[0].size(), frequency[0][0].size() }; std::vector size = { frequency.size(), frequency[0].size(), frequency[0][0].size() };
@ -163,7 +127,7 @@ namespace ufo
(decltype(InputType::QpointDataOutputFile) output_files) const (decltype(InputType::QpointDataOutputFile) output_files) const
{ {
for (auto& output_file : output_files) for (auto& output_file : output_files)
write(output_file.FileName, output_file.Format); write(output_file.Filename, output_file.Format);
} }
void UnfoldSolver::OutputType::write(std::string filename, std::string format, unsigned percision) const void UnfoldSolver::OutputType::write(std::string filename, std::string format, unsigned percision) const
{ {