You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/ML/Training/Training/GridCacheIO.cpp

516 lines
15 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "GridCacheIO.h"
// ---------------- public ----------------
bool GridCacheIO::fileExists(const std::string& filename)
{
std::ifstream fs(filename.c_str(), std::ios::binary);
return fs.good();
}
bool GridCacheIO::saveGrid(const std::string& filename,
HX_NWTM_GRID_OUTPUT2 grid,
const HX_NWTM_GRID_INPUT& gridInput)
{
// 写入前先清洗,避免把 DLL 未初始化的 n 写进缓存
sanitizeGridOutput2(grid);
std::ofstream fs(filename.c_str(), std::ios::binary);
if (!fs) {
std::cerr << "GridCacheIO::saveGrid: 无法打开 " << filename << std::endl;
return false;
}
GridCacheHeader hdr;
hdr.magic = (unsigned int)MAGIC;
hdr.version = (unsigned int)VERSION;
hdr.reserved = 0;
hdr.sceneKey = computeSceneKey64(gridInput);
hdr.nCells = (unsigned int)grid.Trinodexy.size();
if (!writeHeader(fs, hdr)) {
std::cerr << "GridCacheIO::saveGrid: 写 header 失败\n";
return false;
}
if (!writeGridOutput2(fs, grid)) {
std::cerr << "GridCacheIO::saveGrid: 写 gridOutput2 失败\n";
return false;
}
return fs.good();
}
bool GridCacheIO::isCacheMatch(const std::string& filename,
const HX_NWTM_GRID_INPUT& expectedGridInput)
{
std::ifstream fs(filename.c_str(), std::ios::binary);
if (!fs) return false;
GridCacheHeader hdr;
if (!readHeader(fs, hdr)) return false;
if (hdr.magic != (unsigned int)MAGIC) return false;
if (hdr.version != (unsigned int)VERSION) return false;
unsigned long long key = computeSceneKey64(expectedGridInput);
return (hdr.sceneKey == key);
}
bool GridCacheIO::loadGrid(const std::string& filename,
HX_NWTM_GRID_OUTPUT2& grid,
const HX_NWTM_GRID_INPUT& expectedGridInput)
{
std::ifstream fs(filename.c_str(), std::ios::binary);
if (!fs) {
std::cerr << "GridCacheIO::loadGrid: 无法打开 " << filename << std::endl;
return false;
}
GridCacheHeader hdr;
if (!readHeader(fs, hdr)) {
std::cerr << "GridCacheIO::loadGrid: 读 header 失败\n";
return false;
}
if (hdr.magic != (unsigned int)MAGIC) {
std::cerr << "GridCacheIO::loadGrid: magic 错误\n";
return false;
}
if (hdr.version != (unsigned int)VERSION) {
std::cerr << "GridCacheIO::loadGrid: version 错误\n";
return false;
}
unsigned long long expectedKey = computeSceneKey64(expectedGridInput);
if (hdr.sceneKey != expectedKey) {
std::cerr << "GridCacheIO::loadGrid: sceneKey 不匹配\n";
return false;
}
if (!readGridOutput2(fs, grid)) {
std::cerr << "GridCacheIO::loadGrid: 读 gridOutput2 失败\n";
return false;
}
// 读取后清洗,保证 n 字段稳定
sanitizeGridOutput2(grid);
// 快速一致性检查
if (hdr.nCells != (unsigned int)grid.Trinodexy.size()) {
std::cerr << "GridCacheIO::loadGrid: nCells 不匹配,缓存可能损坏\n";
return false;
}
return fs.good();
}
// ---------------- header io ----------------
bool GridCacheIO::writeHeader(std::ofstream& fs, const GridCacheHeader& hdr)
{
if (!writeUInt(fs, hdr.magic)) return false;
if (!writeUInt(fs, hdr.version)) return false;
if (!writeUInt(fs, hdr.reserved)) return false;
if (!writeULL(fs, hdr.sceneKey)) return false;
if (!writeUInt(fs, hdr.nCells)) return false;
return true;
}
bool GridCacheIO::readHeader(std::ifstream& fs, GridCacheHeader& hdr)
{
if (!readUInt(fs, hdr.magic)) return false;
if (!readUInt(fs, hdr.version)) return false;
if (!readUInt(fs, hdr.reserved)) return false;
if (!readULL(fs, hdr.sceneKey)) return false;
if (!readUInt(fs, hdr.nCells)) return false;
return true;
}
// ---------------- sanitize ----------------
void GridCacheIO::sanitizeGridOutput2(HX_NWTM_GRID_OUTPUT2& g)
{
// 这些 n 字段在日志里出现了“随机大数”,非常像 DLL 未初始化/非确定性字段
// 最安全策略:统一用 vector size 来覆盖它们,避免缓存写入/读出后污染流程。
g.ZhiJingNeiBianJie.n = (int)g.ZhiJingNeiBianJie.XiLinw.size();
g.LieFengJingNeiBianJie.n = (int)g.LieFengJingNeiBianJie.XiLinf.size();
g.DuoJiYaLieShuiPingJingNeiBianJie.n = (int)g.DuoJiYaLieShuiPingJingNeiBianJie.XiLinh.size();
g.WaiBianJie.n = (int)g.WaiBianJie.WaiBianh.size();
// 内部断层:用 faultb1 的行数作为 n你对比时 vector 内容一致,而 n 不一致)
g.NeiBuDuanCeng.n = (int)g.NeiBuDuanCeng.faultb1.size();
// 预处理矩阵numk 如果为 0 或异常,可用 ia 大小兜底(这里不强制覆盖,只做兜底)
if (g.YuChuLiJuZhen.numk < 0) g.YuChuLiJuZhen.numk = 0;
}
// ---------------- FNV1a hash ----------------
unsigned long long GridCacheIO::fnv1a64_init()
{
return 14695981039346656037ULL; // offset basis
}
void GridCacheIO::fnv1a64_update(unsigned long long& h, const void* data, size_t len)
{
const unsigned char* p = (const unsigned char*)data;
const unsigned long long prime = 1099511628211ULL;
for (size_t i = 0; i < len; ++i) {
h ^= (unsigned long long)p[i];
h *= prime;
}
}
void GridCacheIO::hashInt(unsigned long long& h, int v)
{
fnv1a64_update(h, &v, sizeof(int));
}
void GridCacheIO::hashUInt(unsigned long long& h, unsigned int v)
{
fnv1a64_update(h, &v, sizeof(unsigned int));
}
void GridCacheIO::hashDouble(unsigned long long& h, double v)
{
fnv1a64_update(h, &v, sizeof(double));
}
void GridCacheIO::hashVec1D(unsigned long long& h, const dVec1& v)
{
unsigned int sz = (unsigned int)v.size();
hashUInt(h, sz);
for (size_t i = 0; i < v.size(); ++i) hashDouble(h, v[i]);
}
void GridCacheIO::hashIVec1D(unsigned long long& h, const iVec1& v)
{
unsigned int sz = (unsigned int)v.size();
hashUInt(h, sz);
for (size_t i = 0; i < v.size(); ++i) hashInt(h, v[i]);
}
void GridCacheIO::hashVec2D(unsigned long long& h, const dVec2& v)
{
unsigned int rows = (unsigned int)v.size();
hashUInt(h, rows);
for (size_t i = 0; i < v.size(); ++i) {
unsigned int cols = (unsigned int)v[i].size();
hashUInt(h, cols);
for (size_t j = 0; j < v[i].size(); ++j) hashDouble(h, v[i][j]);
}
}
void GridCacheIO::hashIVec2D(unsigned long long& h, const iVec2& v)
{
unsigned int rows = (unsigned int)v.size();
hashUInt(h, rows);
for (size_t i = 0; i < v.size(); ++i) {
unsigned int cols = (unsigned int)v[i].size();
hashUInt(h, cols);
for (size_t j = 0; j < v[i].size(); ++j) hashInt(h, v[i][j]);
}
}
void GridCacheIO::hashVec3D(unsigned long long& h, const dVec3& v)
{
unsigned int depth = (unsigned int)v.size();
hashUInt(h, depth);
for (size_t i = 0; i < v.size(); ++i) {
hashVec2D(h, v[i]);
}
}
unsigned long long GridCacheIO::computeSceneKey64(const HX_NWTM_GRID_INPUT& in)
{
unsigned long long h = fnv1a64_init();
// 只 hash 会影响网格生成的关键输入(串场景保护)
hashInt(h, in.D);
hashDouble(h, in.GridControl);
hashVec2D(h, in.Boundary);
hashVec2D(h, in.VerticalWell);
hashVec2D(h, in.HorizontalWell);
hashVec2D(h, in.FractureVerticalWell);
hashVec3D(h, in.MultistageFracturedHorizontalWell);
hashVec2D(h, in.InclinedWell);
hashVec2D(h, in.Fault);
return h;
}
// ---------------- primitive io ----------------
bool GridCacheIO::writeUInt(std::ofstream& fs, unsigned int v)
{
fs.write((const char*)&v, sizeof(unsigned int));
return fs.good();
}
bool GridCacheIO::writeULL(std::ofstream& fs, unsigned long long v)
{
fs.write((const char*)&v, sizeof(unsigned long long));
return fs.good();
}
bool GridCacheIO::writeInt(std::ofstream& fs, int v)
{
fs.write((const char*)&v, sizeof(int));
return fs.good();
}
bool GridCacheIO::writeDouble(std::ofstream& fs, double v)
{
fs.write((const char*)&v, sizeof(double));
return fs.good();
}
bool GridCacheIO::readUInt(std::ifstream& fs, unsigned int& v)
{
fs.read((char*)&v, sizeof(unsigned int));
return fs.good();
}
bool GridCacheIO::readULL(std::ifstream& fs, unsigned long long& v)
{
fs.read((char*)&v, sizeof(unsigned long long));
return fs.good();
}
bool GridCacheIO::readInt(std::ifstream& fs, int& v)
{
fs.read((char*)&v, sizeof(int));
return fs.good();
}
bool GridCacheIO::readDouble(std::ifstream& fs, double& v)
{
fs.read((char*)&v, sizeof(double));
return fs.good();
}
bool GridCacheIO::writeSafeSize(std::ofstream& fs, size_t sz)
{
unsigned int u = (unsigned int)sz; // 存为 uint32
return writeUInt(fs, u);
}
bool GridCacheIO::readSafeSize(std::ifstream& fs, size_t& sz)
{
unsigned int u = 0;
if (!readUInt(fs, u)) return false;
// 防御:防止读到异常大值导致内存爆炸
const unsigned int MAX_SIZE = 100000000U;
if (u > MAX_SIZE) return false;
sz = (size_t)u;
return true;
}
// ---------------- vector io ----------------
bool GridCacheIO::writeVec1D(std::ofstream& fs, const dVec1& v)
{
if (!writeSafeSize(fs, v.size())) return false;
for (size_t i = 0; i < v.size(); ++i) {
if (!writeDouble(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::writeIVec1D(std::ofstream& fs, const iVec1& v)
{
if (!writeSafeSize(fs, v.size())) return false;
for (size_t i = 0; i < v.size(); ++i) {
if (!writeInt(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::writeVec2D(std::ofstream& fs, const dVec2& v)
{
if (!writeSafeSize(fs, v.size())) return false;
for (size_t i = 0; i < v.size(); ++i) {
if (!writeVec1D(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::writeIVec2D(std::ofstream& fs, const iVec2& v)
{
if (!writeSafeSize(fs, v.size())) return false;
for (size_t i = 0; i < v.size(); ++i) {
if (!writeIVec1D(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::writeVec3D(std::ofstream& fs, const dVec3& v)
{
if (!writeSafeSize(fs, v.size())) return false;
for (size_t i = 0; i < v.size(); ++i) {
if (!writeVec2D(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::readVec1D(std::ifstream& fs, dVec1& v)
{
size_t sz = 0;
if (!readSafeSize(fs, sz)) return false;
v.resize(sz);
for (size_t i = 0; i < sz; ++i) {
if (!readDouble(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::readIVec1D(std::ifstream& fs, iVec1& v)
{
size_t sz = 0;
if (!readSafeSize(fs, sz)) return false;
v.resize(sz);
for (size_t i = 0; i < sz; ++i) {
if (!readInt(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::readVec2D(std::ifstream& fs, dVec2& v)
{
size_t rows = 0;
if (!readSafeSize(fs, rows)) return false;
v.resize(rows);
for (size_t i = 0; i < rows; ++i) {
if (!readVec1D(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::readIVec2D(std::ifstream& fs, iVec2& v)
{
size_t rows = 0;
if (!readSafeSize(fs, rows)) return false;
v.resize(rows);
for (size_t i = 0; i < rows; ++i) {
if (!readIVec1D(fs, v[i])) return false;
}
return true;
}
bool GridCacheIO::readVec3D(std::ifstream& fs, dVec3& v)
{
size_t depth = 0;
if (!readSafeSize(fs, depth)) return false;
v.resize(depth);
for (size_t i = 0; i < depth; ++i) {
if (!readVec2D(fs, v[i])) return false;
}
return true;
}
// ---------------- gridOutput2 io ----------------
bool GridCacheIO::writeGridOutput2(std::ofstream& fs, const HX_NWTM_GRID_OUTPUT2& g)
{
// 顶层
if (!writeVec2D(fs, g.Trinodexy)) return false;
if (!writeVec1D(fs, g.Area)) return false;
if (!writeVec2D(fs, g.D)) return false;
// ZhiJingNeiBianJie
if (!writeInt(fs, g.ZhiJingNeiBianJie.n)) return false;
if (!writeVec2D(fs, g.ZhiJingNeiBianJie.XiLinw)) return false;
if (!writeVec2D(fs, g.ZhiJingNeiBianJie.lw)) return false;
if (!writeVec2D(fs, g.ZhiJingNeiBianJie.dw)) return false;
if (!writeVec1D(fs, g.ZhiJingNeiBianJie.rw)) return false;
if (!writeIVec2D(fs, g.ZhiJingNeiBianJie.inwell)) return false;
// LieFengJingNeiBianJie
if (!writeInt(fs, g.LieFengJingNeiBianJie.n)) return false;
if (!writeVec2D(fs, g.LieFengJingNeiBianJie.XiLinf)) return false;
if (!writeVec2D(fs, g.LieFengJingNeiBianJie.lf)) return false;
if (!writeVec2D(fs, g.LieFengJingNeiBianJie.df)) return false;
if (!writeVec1D(fs, g.LieFengJingNeiBianJie.xf)) return false;
if (!writeIVec2D(fs, g.LieFengJingNeiBianJie.infra)) return false;
// DuoJiYaLieShuiPingJingNeiBianJie
if (!writeInt(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.n)) return false;
if (!writeVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.XiLinh)) return false;
if (!writeVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.lh)) return false;
if (!writeVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.dh)) return false;
if (!writeVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.dsxf)) return false;
if (!writeIVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.inhor)) return false;
if (!writeIVec1D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.nhor)) return false;
// WaiBianJie
if (!writeInt(fs, g.WaiBianJie.n)) return false;
if (!writeVec2D(fs, g.WaiBianJie.WaiBianh)) return false;
if (!writeVec2D(fs, g.WaiBianJie.WaiBianl)) return false;
if (!writeVec2D(fs, g.WaiBianJie.WaiBiand)) return false;
// NeiBuDuanCeng
if (!writeInt(fs, g.NeiBuDuanCeng.n)) return false;
if (!writeVec2D(fs, g.NeiBuDuanCeng.faultb1)) return false;
if (!writeVec2D(fs, g.NeiBuDuanCeng.faultb2)) return false;
if (!writeVec2D(fs, g.NeiBuDuanCeng.faultl1)) return false;
if (!writeVec2D(fs, g.NeiBuDuanCeng.faultd1)) return false;
// YuChuLiJuZhen
if (!writeIVec1D(fs, g.YuChuLiJuZhen.ia)) return false;
if (!writeIVec1D(fs, g.YuChuLiJuZhen.ja)) return false;
if (!writeIVec2D(fs, g.YuChuLiJuZhen.nzeros)) return false;
if (!writeInt(fs, g.YuChuLiJuZhen.numk)) return false;
return true;
}
bool GridCacheIO::readGridOutput2(std::ifstream& fs, HX_NWTM_GRID_OUTPUT2& g)
{
if (!readVec2D(fs, g.Trinodexy)) return false;
if (!readVec1D(fs, g.Area)) return false;
if (!readVec2D(fs, g.D)) return false;
if (!readInt(fs, g.ZhiJingNeiBianJie.n)) return false;
if (!readVec2D(fs, g.ZhiJingNeiBianJie.XiLinw)) return false;
if (!readVec2D(fs, g.ZhiJingNeiBianJie.lw)) return false;
if (!readVec2D(fs, g.ZhiJingNeiBianJie.dw)) return false;
if (!readVec1D(fs, g.ZhiJingNeiBianJie.rw)) return false;
if (!readIVec2D(fs, g.ZhiJingNeiBianJie.inwell)) return false;
if (!readInt(fs, g.LieFengJingNeiBianJie.n)) return false;
if (!readVec2D(fs, g.LieFengJingNeiBianJie.XiLinf)) return false;
if (!readVec2D(fs, g.LieFengJingNeiBianJie.lf)) return false;
if (!readVec2D(fs, g.LieFengJingNeiBianJie.df)) return false;
if (!readVec1D(fs, g.LieFengJingNeiBianJie.xf)) return false;
if (!readIVec2D(fs, g.LieFengJingNeiBianJie.infra)) return false;
if (!readInt(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.n)) return false;
if (!readVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.XiLinh)) return false;
if (!readVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.lh)) return false;
if (!readVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.dh)) return false;
if (!readVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.dsxf)) return false;
if (!readIVec2D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.inhor)) return false;
if (!readIVec1D(fs, g.DuoJiYaLieShuiPingJingNeiBianJie.nhor)) return false;
if (!readInt(fs, g.WaiBianJie.n)) return false;
if (!readVec2D(fs, g.WaiBianJie.WaiBianh)) return false;
if (!readVec2D(fs, g.WaiBianJie.WaiBianl)) return false;
if (!readVec2D(fs, g.WaiBianJie.WaiBiand)) return false;
if (!readInt(fs, g.NeiBuDuanCeng.n)) return false;
if (!readVec2D(fs, g.NeiBuDuanCeng.faultb1)) return false;
if (!readVec2D(fs, g.NeiBuDuanCeng.faultb2)) return false;
if (!readVec2D(fs, g.NeiBuDuanCeng.faultl1)) return false;
if (!readVec2D(fs, g.NeiBuDuanCeng.faultd1)) return false;
if (!readIVec1D(fs, g.YuChuLiJuZhen.ia)) return false;
if (!readIVec1D(fs, g.YuChuLiJuZhen.ja)) return false;
if (!readIVec2D(fs, g.YuChuLiJuZhen.nzeros)) return false;
if (!readInt(fs, g.YuChuLiJuZhen.numk)) return false;
return true;
}