#include "nmDataAnalyzeManager.h" #include "nmDataAnalyzeContext.h" #include "nmDataAnalyzeContextProvider.h" #include "nmDataPlotContext.h" #include "nmDataPlotContextProvider.h" #include "nmDataWellBase.h" #include "nmDataVerticalWell.h" #include "nmDataVerticalFracturedWell.h" #include "nmDataHorizontalFracturedWell.h" #include "ZxDataWell.h" #include "ZxBaseUtil.h" #include "zxLogInstance.h" #include "nmDataReservoir.h" #include "nmDataRegionMark.h" #include "nmDataOutline.h" #include "nmDataRegion.h" #include "nmDataFracture.h" #include "nmDataFault.h" #include "nmDataMeasuringScale.h" #include "nmDataMeasure.h" #include "nmDataAxis.h" #include "nmDataGeoRef.h" #include "nmDataDiagnostic.h" #include "nmDataForecast.h" #include "nmDataAutomaticFitting.h" #include "nmDataSensitive.h" #include "nmDataPvtParaForPebi.h" #include "ZxDataWell.h" #include "ZxDataGaugeP.h" #include "ZxDataGaugeF.h" #include "zxSysUtils.h" #include "ZxDataProject.h" #include "nmDataMixedResults.h" #include "nmDataLayer.h" #include "nmDataUtils.h" #include "mAlgDefines.h" #include "nmDataJsonTools.h" // JSON工具类 #include "nmTranslationManager.h" #include "iAnalRun.h" #include "ZxDataAnalRun.h" #include #include #include #include "singlePhaseSolver.h" #include #include #include #include #include #include "nmDataTimeStepSetting.h" #include #include #include namespace { // 多条PVT曲线都可能带压力横坐标,只保存第一次读到的有效横坐标 void setPebiPressureIfEmpty(nmDataPvtParaForPebi* pPvtPara, const QVector& vecX) { if(pPvtPara != nullptr && pPvtPara->getPressure().isEmpty() && !vecX.isEmpty()) { pPvtPara->setPressure(vecX); } } // 根据当前PVT相态决定需要访问哪些相态页。 // 这里只控制PVT页面读取范围,后续参数默认值和PEBI赋值逻辑保持不变。 void resolvePvtPhaseReadFlags(PvtFluidType eType, bool& bReadOil, bool& bReadGas, bool& bReadWater) { bReadOil = false; bReadGas = false; bReadWater = false; switch(eType) { case WFT_Oil: // 单相油:只访问油相页,避免访问不存在的气/水相页 bReadOil = true; break; case WFT_Gas: // 单相气:只访问气相页 bReadGas = true; break; case WFT_Water: // 单相水:只访问水相页 bReadWater = true; break; case WFT_Oil_Water: // 油水:访问油相和水相页,不访问气相页 bReadOil = true; bReadWater = true; break; default: // 未识别相态不主动读取相态页,避免PVT工具输出缺失子窗口日志 break; } } // 从Diffusion右侧结果表中提取指定列数据 bool extractDiffusionColumn(const VVecDouble& vvec, int nColumn, QVector& vecValues) { vecValues.clear(); if(vvec.isEmpty() || nColumn < 0) { return false; } if(vvec.size() > nColumn && vvec[nColumn].size() > 4 && vvec[nColumn].size() > vvec.size()) { vecValues = vvec[nColumn]; return !vecValues.isEmpty(); } // Diffusion结果表通常按行保存:[自变量, 结果1, 结果2] for(int i = 0; i < vvec.size(); ++i) { if(vvec[i].size() > nColumn) { vecValues.append(vvec[i][nColumn]); } } if(!vecValues.isEmpty()) { return true; } // 兼容少量按列缓存的数据 if(vvec.size() > nColumn) { vecValues = vvec[nColumn]; } return !vecValues.isEmpty(); } // 根据饱和度坐标计算互补饱和度,例如油水相渗中由Sw得到So QVector complementSaturation(const QVector& vecSaturation) { QVector vecResult; vecResult.reserve(vecSaturation.size()); for(int i = 0; i < vecSaturation.size(); ++i) { vecResult.append(1.0 - vecSaturation[i]); } return vecResult; } // 将数组顺序反转,用于把Diffusion中按Sw递增的数据整理为按So递增的数据 QVector reversedVector(const QVector& vecValues) { QVector vecResult; vecResult.reserve(vecValues.size()); for(int i = vecValues.size(); i > 0; --i) { vecResult.append(vecValues[i - 1]); } return vecResult; } // 将油水两相Diffusion相渗结果映射到PEBI求解器需要的饱和度和相对渗透率字段 void applyDiffusionKkToPebiPvt(nmDataPvtParaForPebi* pPvtPara, const VVecDouble& vvecKK) { if(vvecKK.isEmpty()) { return; } QVector vecS; QVector vecKr1; QVector vecKr2; if(!extractDiffusionColumn(vvecKK, 0, vecS)) { return; } extractDiffusionColumn(vvecKK, 1, vecKr1); extractDiffusionColumn(vvecKK, 2, vecKr2); // 油水:第一列为Sw,So按1-Sw生成,后续列为Kro/Krw pPvtPara->setSw(vecS); // PEBI默认相渗以So为横坐标,Diffusion表按Sw递增保存,这里整体转为So递增方向 pPvtPara->setSo(reversedVector(complementSaturation(vecS))); if(!vecKr1.isEmpty()) { pPvtPara->setKro(reversedVector(vecKr1)); } if(!vecKr2.isEmpty()) { pPvtPara->setKrw(reversedVector(vecKr2)); } } } ZX_DEFINE_DYNAMIC(DataAnalyzeManager, nmDataAnalyzeManager) nmDataAnalyzeManager::nmDataAnalyzeManager(): ZxDataObjectBin(0) { m_reservoirData = nullptr; m_outlineData = nullptr; m_pMeasuringScaleData = nullptr; m_pebiPvtPara = nullptr; m_pMixedResults = nullptr; m_pLayerData = nullptr; m_pCurDataWell = nullptr; m_pMeasureData = nullptr; m_axisData = nullptr; m_pNmGuiPlot = nullptr; m_pGeoRefData = nullptr; m_pTimeStep = nullptr; //m_pPerCloData = nullptr; m_pAutomaticFittingData = nullptr; m_pDiagnosticData = nullptr; //m_pSkinVsRateData = nullptr; //m_pFlowSegmentData = nullptr; m_pForecastData = nullptr; m_pSensitiveData = nullptr; m_backgroundImageInfo.bIsVisible = false; m_dScalarRangeP[0] = 0.0; m_dScalarRangeP[1] = 0.0; // 初始化混合参数数据(Temp) //m_pMixedResults = new nmDataMixedResults; // 初始化储层数据 m_pLayerData = new nmDataLayer; m_eGridType = NM_Grid_Type::NM_Grid_PEBI; //默认网格类型为PEBI this->initDefaultDisplaySettings(); // 初始化中英文翻译映射 nmTranslationManager::initTranslations(); m_bIsLoadData = false; // 获取完整路径 //QString appPath = QCoreApplication::applicationFilePath(); //qDebug() << "完整应用路径:" << appPath; // 许可证路径 //m_licensePath = appPath + "/../../3rd/Pebi/license/HXNWTM_license.dat"; // 获取完整路径 QString appPath = QCoreApplication::applicationFilePath(); // 获取应用程序所在的目录 QString appDir = QFileInfo(appPath).absolutePath(); // 定义从应用程序目录到许可证目录的相对路径 QString relativeJump = "/../Res/license/HXNWTM_license.dat"; // 将目录和相对跳转路径拼接 m_licensePath = appDir + relativeJump; } // 初始化静态成员 QMap nmDataAnalyzeManager::s_mapDataAnalManager; iSubWndFitting* nmDataAnalyzeManager::s_pCurSubWndFitting = nullptr; nmDataAnalyzeManager* nmDataAnalyzeManager::getInstanceByFitting(iSubWndFitting* pSubWndF) { if(s_mapDataAnalManager.contains(pSubWndF)) { return s_mapDataAnalManager[pSubWndF]; } nmDataAnalyzeManager* pInstance = new nmDataAnalyzeManager(); s_mapDataAnalManager[pSubWndF] = pInstance; return pInstance; } nmDataAnalyzeManager* nmDataAnalyzeManager::getCurrentInstance() { if(s_mapDataAnalManager.contains(s_pCurSubWndFitting)) { return s_mapDataAnalManager[s_pCurSubWndFitting]; } else { return nullptr; } } nmDataWellBase *nmDataAnalyzeManager::createWell(NM_WELL_MODEL eWellType) { // 根据当前Fitting窗口来获取对应的井相关数据 iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting(); nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider(); Q_ASSERT(nullptr != pSubWndFitting); Q_ASSERT(nullptr != pContextProvider); nmDataWellBase* pWellData = nullptr; // 新建一口井,默认直井 if(eWellType == NM_WELL_MODEL::Vertical_Well) { // 直接使用子类指针创建对象 nmDataVerticalWell* verticalWell = new nmDataVerticalWell; pWellData = static_cast(verticalWell); } else if(eWellType == NM_WELL_MODEL::Vertical_Fractured_Well) { // 直接使用子类指针创建对象 nmDataVerticalFracturedWell* vFracturedWell = new nmDataVerticalFracturedWell; pWellData = static_cast(vFracturedWell); } else if(eWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) { // 直接使用子类指针创建对象 nmDataHorizontalFracturedWell* hFracturedWell = new nmDataHorizontalFracturedWell; pWellData = static_cast(hFracturedWell); } // 默认井才可以选择当前流动段,其余井默认选择最后一段 if(pWellData == nullptr) { return nullptr; } if(m_vWellData.count() == 0) { int nIndexF = -1; // 第一口井就选择界面上的流动段索引 // 流动段索引由窗口层上下文提供,数据层不直接访问窗口对象 if(pSubWndFitting != nullptr && pContextProvider != nullptr) { if(pContextProvider->getCurrentSegmentIndex(pSubWndFitting, nIndexF)) { // 设置当前流动段索引 pWellData->setIndexF(nIndexF); } } } m_vWellData.append(pWellData); emit dataChanged(); return pWellData; } // 实现 changeWellType 函数 nmDataWellBase* nmDataAnalyzeManager::changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType) { if(pOldWellData == nullptr) { return nullptr; } if(!removeWell(pOldWellData)) { return nullptr; } nmDataWellBase* pNewWellData = createWell(eTargetWellType); if(pNewWellData == nullptr) { return nullptr; } return pNewWellData; } // 实现 removeWell 函数 bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData) { if(pWellData == nullptr) { return false; } // 遍历 m_vWellData,找到并移除指定的井对象 for(auto it = m_vWellData.begin(); it != m_vWellData.end(); ++it) { if(*it == pWellData) { m_vWellData.erase(it); delete pWellData; pWellData = nullptr; emit dataChanged(); return true; // 成功移除并删除井对象 } } return false; // 如果未找到该井对象,返回 false } void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData) { nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider(); if (m_pNmGuiPlot != nullptr && pPlotContextProvider != nullptr) { // 移除所有井图元 pPlotContextProvider->removeWellPlotByData(m_pNmGuiPlot, pWellData); removeWell(pWellData); } } void nmDataAnalyzeManager::clearAllWellData() { // 遍历并删除所有井对象 foreach(nmDataWellBase* pWell, m_vWellData) { if(pWell != nullptr) { delete pWell; pWell = nullptr; } } // 清空数组 m_vWellData.clear(); } QVector nmDataAnalyzeManager::getWellDataList() const { return m_vWellData; } //QVector nmDataAnalyzeManager::getWellDataListCopy() const //{ // QVector result; // result.reserve(m_vWellData.size()); // // foreach(const nmDataWellBase* well, m_vWellData) { // if(well) { // result.append(*well); // 调用拷贝构造函数 // } // } // // return result; //} //void nmDataAnalyzeManager::updateWellData(const QVector& newData) //{ // // // 确保数量一致 // if (newData.size() != m_vWellData.size()) { // return; // } // // for (int i = 0; i < newData.size(); ++i) { // nmDataWellBase* existingWell = m_vWellData[i]; // const nmDataWellBase& newWell = newData[i]; // // if (existingWell && existingWell->getWellName() == newWell.getWellName()) { // // 根据类型更新数据 // if (auto existingVFractured = dynamic_cast(existingWell)) { // if (auto newVFractured = dynamic_cast(&newWell)) { // *existingVFractured = *newVFractured; // } // } // else if (auto existingHFractured = dynamic_cast(existingWell)) { // if (auto newHFractured = dynamic_cast(&newWell)) { // *existingHFractured = *newHFractured; // } // } else if (auto existingVertical = dynamic_cast(existingWell)) { // if (auto newVertical = dynamic_cast(&newWell)) { // *existingVertical = *newVertical; // 调用赋值运算符 // } // } // } // } // //} void nmDataAnalyzeManager::updateVerticalWells(const QVector& wells) { foreach(const auto& newWell, wells) { foreach(auto* existingWell, m_vWellData) { if(auto * vWell = dynamic_cast(existingWell)) { if(vWell->getWellName() == newWell.getWellName()) { *vWell = newWell; // 调用赋值运算符 break; } } } } } void nmDataAnalyzeManager::updateVerticalFracturedWells(const QVector& wells) { foreach(const auto& newWell, wells) { foreach(auto* existingWell, m_vWellData) { if(auto * vWell = dynamic_cast(existingWell)) { if(vWell->getWellName() == newWell.getWellName()) { *vWell = newWell; // 调用赋值运算符 break; } } } } } void nmDataAnalyzeManager::updateHorizontalFracturedWells(const QVector& wells) { foreach(const auto& newWell, wells) { foreach(auto* existingWell, m_vWellData) { if(auto * vWell = dynamic_cast(existingWell)) { if(vWell->getWellName() == newWell.getWellName()) { *vWell = newWell; // 调用赋值运算符 break; } } } } } // 获取所有直井数据 QVector nmDataAnalyzeManager::getVerticalWellData() const { QVector verticalWells; foreach(nmDataWellBase* well, m_vWellData) { nmDataVerticalWell* vWell = dynamic_cast(well); if(vWell && !dynamic_cast(well)) { // 确保不是垂直裂缝井 verticalWells.append(vWell); } } return verticalWells; } // 获取所有垂直裂缝井数据 QVector nmDataAnalyzeManager::getVerticalFracturedWellData() const { QVector vFracturedWells; foreach(nmDataWellBase* well, m_vWellData) { nmDataVerticalFracturedWell* vFracturedWell = dynamic_cast(well); if(vFracturedWell) { vFracturedWells.append(vFracturedWell); } } return vFracturedWells; } // 获取所有多段压裂水平井数据 QVector nmDataAnalyzeManager::getHorizontalFracturedWellData() const { QVector hFracturedWells; foreach(nmDataWellBase* well, m_vWellData) { nmDataHorizontalFracturedWell* hFracturedWell = dynamic_cast(well); if(hFracturedWell) { hFracturedWells.append(hFracturedWell); } } return hFracturedWells; } nmDataWellBase* nmDataAnalyzeManager::findWellByName(QString wellName) const { foreach(nmDataWellBase* pWell, m_vWellData) { if(pWell && pWell->getWellName() == wellName) { return pWell; // 找到匹配的井,返回指针 } } return nullptr; // 未找到匹配的井,返回 nullptr } void nmDataAnalyzeManager::initCurWellData() { // 获取当前默认井数据 ZxDataWell* pWellData = zxCurWell; if(pWellData == nullptr) { return; } // 判断是哪一种井类型,初始化对应的参数 QString wellClass = pWellData->getWellClassEn(); // 获取当前井的压力、流量数据 ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP); ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF); ZxDataGaugeP* pGaugeP = nullptr; ZxDataGaugeF* pGaugeF = nullptr; // 遍历压力数据列表 for(int i = 0; i < m_listGaugeP.size(); ++i) { if(pGaugeP = dynamic_cast(m_listGaugeP[i])) { // 拿到第一条压力数据 break; } } // 遍历流量数据列表 for(int i = 0; i < m_listGaugeF.size(); ++i) { if(pGaugeF = dynamic_cast(m_listGaugeF[i])) { // 拿到第一条流量数据 break; } } // 获取的压力、流量数据 QVector vecPtsP, vecPtsF; // 临时存储x,y坐标 VecDouble vecX, vecY; if(pGaugeP != nullptr) { // 获取压力数据 if(pGaugeP->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsP.append(pt); } } } if(pGaugeF != nullptr) { vecX.clear(); vecY.clear(); // 获取流量数据 if(pGaugeF->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsF.append(pt); } } } if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) { // 初始化直井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Well); nmDataVerticalWell* pVerticalWell = dynamic_cast(pWell); if(pVerticalWell == nullptr) { return; } pVerticalWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pVerticalWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pVerticalWell->setX(tempAttr); tempAttr = pVerticalWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pVerticalWell->setY(tempAttr); tempAttr = pVerticalWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pVerticalWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pVerticalWell->setPressurePoints(vecPtsP); pVerticalWell->setFlowPoints(vecPtsF); QVector> vvecHistoryPressureData; //压力历史数据 QVector> vvecHistoryLogData; // 历史双对数曲线数据 QVector> vvecHistorySemiLogData; // 历史半对数曲线数据 this->calculationLogData(pVerticalWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData); // 使用setter方法存储历史数据到井对象中 pVerticalWell->setHistoryPressure(vvecHistoryPressureData); pVerticalWell->setHistoryLogLog(vvecHistoryLogData); pVerticalWell->setHistorySemiLog(vvecHistorySemiLogData); // 设置为当前查看的井 this->setCurWellData(pVerticalWell); } else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) { // 初始化垂直裂缝井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Fractured_Well); nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast(pWell); if(pVFracturedWell == nullptr) { return; } pVFracturedWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pVFracturedWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pVFracturedWell->setX(tempAttr); tempAttr = pVFracturedWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pVFracturedWell->setY(tempAttr); tempAttr = pVFracturedWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pVFracturedWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pVFracturedWell->setPressurePoints(vecPtsP); pVFracturedWell->setFlowPoints(vecPtsF); QVector> vvecHistoryPressureData; //压力历史数据 QVector> vvecHistoryLogData; // 历史双对数曲线数据 QVector> vvecHistorySemiLogData; // 历史半对数曲线数据 this->calculationLogData(pVFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData); // 使用setter方法存储历史数据到井对象中 pVFracturedWell->setHistoryPressure(vvecHistoryPressureData); pVFracturedWell->setHistoryLogLog(vvecHistoryLogData); pVFracturedWell->setHistorySemiLog(vvecHistorySemiLogData); // 更新裂缝位置信息 pVFracturedWell->setFracs(); // 设置为当前查看的井 this->setCurWellData(pVFracturedWell); } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) { // 初始化多段压裂水平井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well); nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast(pWell); if(pHFracturedWell == nullptr) { return; } pHFracturedWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pHFracturedWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pHFracturedWell->setX(tempAttr); tempAttr = pHFracturedWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pHFracturedWell->setY(tempAttr); tempAttr = pHFracturedWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pHFracturedWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pHFracturedWell->setPressurePoints(vecPtsP); pHFracturedWell->setFlowPoints(vecPtsF); QVector> vvecHistoryPressureData; //压力历史数据 QVector> vvecHistoryLogData; // 历史双对数曲线数据 QVector> vvecHistorySemiLogData; // 历史半对数曲线数据 this->calculationLogData(pHFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData); //使用setter方法存储历史数据到井对象中 pHFracturedWell->setHistoryPressure(vvecHistoryPressureData); pHFracturedWell->setHistoryLogLog(vvecHistoryLogData); pHFracturedWell->setHistorySemiLog(vvecHistorySemiLogData); // 计算裂缝数据 pHFracturedWell->setFracs(); // 设置为当前查看的井 this->setCurWellData(pHFracturedWell); } } void nmDataAnalyzeManager::calculationLogData( nmDataWellBase* pWellData, QVector>& vvecHistoryData, QVector>& vvecLogPreData, QVector>& vvecSemiLogPreData) { // 清空输出参数 vvecHistoryData.clear(); vvecLogPreData.clear(); vvecSemiLogPreData.clear(); if(pWellData == nullptr) { return; } // 初始化二维数组结构 vvecHistoryData.resize(2); // [0]=x, [1]=y vvecLogPreData.resize(3); // [0]=x, [1]=y, [2]=z vvecSemiLogPreData.resize(2); // [0]=x, [1]=pointData[0] // 准备压力数据 QVector vecPressure = pWellData->getPressurePoints(); std::vector wellPressureData; // 填充 wellPressureData 和 vvecHistoryData foreach(const QPointF& qpoint, vecPressure) { // wellPressureData Point pt; pt.x = qpoint.x(); pt.y = qpoint.y(); pt.z = 0.0; wellPressureData.push_back(pt); // vvecHistoryData vvecHistoryData[0].append(qpoint.x()); // x vvecHistoryData[1].append(qpoint.y()); // y } // 准备流量段数据 QVector vecTimeQ = pWellData->getFlowPoints(); int nTimeNumQ = vecTimeQ.size() - 1; std::vector timeQ(nTimeNumQ); std::vector q(nTimeNumQ); for(int i = 0; i < nTimeNumQ; ++i) { timeQ[i] = vecTimeQ[i + 1].x(); q[i] = vecTimeQ[i + 1].y(); } // 调用 DLL 计算双对数曲线 std::vector logPre; int iSectionFlowIndex = pWellData->getIndexF(); HMODULE hMod_solver = LoadLibrary(L"singlePhaseSolverDll.dll"); if(hMod_solver) { typedef bool (*PreLog)(const std::vector&, const int&, double*, double*, int, std::vector&); PreLog preLogFun = (PreLog)GetProcAddress(hMod_solver, "logLogPre"); if(nullptr == preLogFun) { FreeLibrary(hMod_solver); std::cout << "preLogFun failed!\n"; return; } preLogFun(wellPressureData, iSectionFlowIndex, timeQ.data(), q.data(), nTimeNumQ, logPre); // 不添加最后一个元素 for(uint i = 0; i < logPre.size() - 1; i++) { //logFile << logPre[i].x << "\t" << logPre[i].y << "\t" << logPre[i].z << "\t" << std::endl; vvecLogPreData[0].append(logPre[i].x); // x vvecLogPreData[1].append(logPre[i].y); // y vvecLogPreData[2].append(logPre[i].z); // z } // 填充半对数曲线数据 (x, pointData[0]) foreach(const auto& point, logPre) { vvecSemiLogPreData[0].append(point.x); // x double y_value = point.pointData.empty() ? 0.0 : point.pointData[0]; vvecSemiLogPreData[1].append(y_value); // pointData[0] 或默认值 } FreeLibrary(hMod_solver); } } void nmDataAnalyzeManager::appendWellData(ZxDataWell* pWellData) { if(pWellData == nullptr) { return; } // 判断是哪一种井类型,初始化对应的参数 QString sWellClass = pWellData->getWellClassEn(); // 获取当前井的压力、流量数据 ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP); ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF); ZxDataGaugeP* pGaugeP = nullptr; ZxDataGaugeF* pGaugeF = nullptr; // 遍历压力数据列表 for(int i = 0; i < m_listGaugeP.size(); ++i) { if(pGaugeP = dynamic_cast(m_listGaugeP[i])) { // 拿到第一条压力数据 break; } } // 遍历流量数据列表 for(int i = 0; i < m_listGaugeF.size(); ++i) { if(pGaugeF = dynamic_cast(m_listGaugeF[i])) { // 拿到第一条流量数据 break; } } // 获取的压力、流量数据 QVector vecPtsP, vecPtsF; // 临时存储x,y坐标 VecDouble vecX, vecY; if(pGaugeP != nullptr) { // 获取压力数据 if(pGaugeP->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsP.append(pt); } } } if(pGaugeF != nullptr) { vecX.clear(); vecY.clear(); // 获取流量数据 if(pGaugeF->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsF.append(pt); } } } int nIndexF; //当前井的流动段索引 // 更新当前井的流动段的索引,默认为最后一段 nIndexF = vecPtsF.count() - 1; if(ZxBaseUtil::isSameStr(sWellClass, "VerticalWell")) { // 初始化直井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Well); nmDataVerticalWell* pVerticalWell = dynamic_cast(pWell); if(pVerticalWell == nullptr) { return; } pVerticalWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pVerticalWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pVerticalWell->setX(tempAttr); tempAttr = pVerticalWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pVerticalWell->setY(tempAttr); tempAttr = pVerticalWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pVerticalWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pVerticalWell->setPressurePoints(vecPtsP); pVerticalWell->setFlowPoints(vecPtsF); // 设置流量段索引 pVerticalWell->setIndexF(nIndexF); } else if(ZxBaseUtil::isSameStr(sWellClass, "VerticalFracturedWell")) { // 初始化垂直裂缝井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Fractured_Well); nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast(pWell); if(pVFracturedWell == nullptr) { return; } pVFracturedWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pVFracturedWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pVFracturedWell->setX(tempAttr); tempAttr = pVFracturedWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pVFracturedWell->setY(tempAttr); tempAttr = pVFracturedWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pVFracturedWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pVFracturedWell->setPressurePoints(vecPtsP); pVFracturedWell->setFlowPoints(vecPtsF); // 更新裂缝位置信息 pVFracturedWell->setFracs(); // 设置流量段索引 pVFracturedWell->setIndexF(nIndexF); } else if(ZxBaseUtil::isSameStr(sWellClass, "HorizontalFracturedWell")) { // 初始化多段压裂水平井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well); nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast(pWell); if(pHFracturedWell == nullptr) { return; } pHFracturedWell->setWellName(pWellData->getName()); nmDataAttribute tempAttr = pHFracturedWell->getX(); tempAttr.setValue(pWellData->getLocationX()); pHFracturedWell->setX(tempAttr); tempAttr = pHFracturedWell->getY(); tempAttr.setValue(pWellData->getLocationY()); pHFracturedWell->setY(tempAttr); tempAttr = pHFracturedWell->getRadius(); tempAttr.setValue(pWellData->getWellRadius()); pHFracturedWell->setRadius(tempAttr); // 设置井的压力数据、流量数据 pHFracturedWell->setPressurePoints(vecPtsP); pHFracturedWell->setFlowPoints(vecPtsF); // 计算裂缝数据 pHFracturedWell->setFracs(); // 设置流量段索引 pHFracturedWell->setIndexF(nIndexF); } } void nmDataAnalyzeManager::appendNmWellData(nmDataWellBase* pWellData) { if (pWellData == nullptr) return; m_vWellData.append(pWellData); } void nmDataAnalyzeManager::createReservoir() { // 根据当前Fitting窗口来获取对应的井相关数据 iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting(); nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider(); Q_ASSERT(nullptr != pSubWndFitting); Q_ASSERT(nullptr != pContextProvider); // 定义获取的分层数据 VVecVariant vvecLayerData; // 定义返回结果的 QMap QMap mapParaValues; // 相态类型 PvtFluidType eType = WFT_Null; if(nullptr != pSubWndFitting && nullptr != pContextProvider) { // 读取界面选择的PVT相态类型 pContextProvider->getBasicPft(pSubWndFitting, eType); //QString sMainPft =pSubWndFitting->getBasicMainPft(); //QString sPftDesc = pSubWndFitting->getBasicPftDesc(); // 只读取当前相态存在的PVT页,避免PVT工具输出PhaseGas/PhaseWater缺失日志 QStringList listParas; bool bReadOilPvt = false; bool bReadGasPvt = false; bool bReadWaterPvt = false; resolvePvtPhaseReadFlags(eType, bReadOilPvt, bReadGasPvt, bReadWaterPvt); // 储层基础数据这里只需要体积系数和粘度;不属于当前相态的参数继续走默认值 if(bReadOilPvt) { listParas << "Bo" << "Miuo"; } if(bReadGasPvt) { listParas << "Bg" << "Miug"; } if(bReadWaterPvt) { listParas << "Bw" << "Miuw"; } listParas << "Ct"; pContextProvider->getPvtParaValues(pSubWndFitting, listParas, mapParaValues); // 读取分层数据 pContextProvider->getBasicDataLayers(pSubWndFitting, vvecLayerData); } // 获取油体积系数和油相粘度 double dBo = mapParaValues.value("Bo", 1.5); // 如果键不存在,返回默认值 1.5 double dMiuo = mapParaValues.value("Miuo", 1); // 如果键不存在,返回默认值 1 // 获取气体积系数和气相粘度、参考温度 double dBg = mapParaValues.value("Bg", 1); // 如果键不存在,返回默认值 1.5 double dMiug = mapParaValues.value("Miug", 1); // 如果键不存在,返回默认值 1 double dTempGas = 100;// 气藏温度,TODO,应该从分析界面获取 // 获取水体积系数和水相粘度 double dBw = mapParaValues.value("Bw", 1); double dMiuw = mapParaValues.value("Miuw", 1); // 获取综合压缩系数 double dCt = mapParaValues.value("Ct", 0.1); // 获取初始油、气、水饱和度---------王老师那的是临时数据,没法获取 //double dSo = mapParaValues.value("Ko", 1); //double dSg = mapParaValues.value("Sg", 0); //double dSw = mapParaValues.value("Sw", 0); // 检查 vvecLayerData 是否有效,有效重新赋值,无效设置默认值 double dThickness = 10; double dPorosity = 0.5; double dCf = 1.00; // 岩石压缩系数 double dInitialPre = 30.0; if(!vvecLayerData.isEmpty() && vvecLayerData[0].size() >= 5) { dThickness = vvecLayerData[0][1].toDouble(); dPorosity = vvecLayerData[0][2].toDouble(); dCf = vvecLayerData[0][3].toDouble(); dInitialPre = vvecLayerData[0][4].toDouble(); } // 判断是否已有油藏参数数据 if(m_reservoirData != nullptr) { delete m_reservoirData; m_reservoirData = nullptr; } m_reservoirData = new nmDataReservoir; nmDataAttribute tempAttr; // 将界面相态转换为内部储层相态,后续再映射为求解器T if(eType == WFT_Oil) { m_reservoirData->setPhaseType(PHASE_Oil); tempAttr = m_reservoirData->getBo();// 油体积系数 tempAttr.setValue(dBo); m_reservoirData->setBo(tempAttr); tempAttr = m_reservoirData->getMiuo();// 油相黏度 tempAttr.setValue(dMiuo); m_reservoirData->setMiuo(tempAttr); } else if(eType == WFT_Gas) { m_reservoirData->setPhaseType(PHASE_Gas); // TODO:这里先使用用一个变量,后续根据需求再进行分类 tempAttr = m_reservoirData->getBo();// 气体积系数 tempAttr.setValue(dBg); m_reservoirData->setBo(tempAttr); tempAttr = m_reservoirData->getMiuo();// 气相黏度 tempAttr.setValue(dMiug); m_reservoirData->setMiuo(tempAttr); m_reservoirData->setTempGasRe(dTempGas); // 气藏温度 } else if(eType == WFT_Water) { m_reservoirData->setPhaseType(PHASE_Water); tempAttr = m_reservoirData->getBo();// 水体积系数 tempAttr.setValue(dBw); m_reservoirData->setBo(tempAttr); tempAttr = m_reservoirData->getMiuo();// 水相黏度 tempAttr.setValue(dMiuw); m_reservoirData->setMiuo(tempAttr); } else if(eType == WFT_Oil_Water) { m_reservoirData->setPhaseType(PHASE_Oil_Water); tempAttr = m_reservoirData->getBo();// 油体积系数 tempAttr.setValue(dBo); m_reservoirData->setBo(tempAttr); tempAttr = m_reservoirData->getMiuo();// 油相黏度 tempAttr.setValue(dMiuo); m_reservoirData->setMiuo(tempAttr); } else { m_reservoirData->setPhaseType(PHASE_UNKNOWN); } tempAttr = m_reservoirData->getInitialPressure();//初始压力 tempAttr.setValue(dInitialPre); m_reservoirData->setInitialPressure(tempAttr); tempAttr = m_reservoirData->getReservoirType(); tempAttr.setValue("Homogeneous"); m_reservoirData->setReservoirType(tempAttr); tempAttr = m_reservoirData->getThickness();// 储层厚度 tempAttr.setValue(dThickness); m_reservoirData->setThickness(tempAttr); tempAttr = m_reservoirData->getCt(); // 综合压缩系数 tempAttr.setValue(dCt); m_reservoirData->setCt(tempAttr); tempAttr = m_reservoirData->getPorosity();// 孔隙度 tempAttr.setValue(dPorosity); m_reservoirData->setPorosity(tempAttr); tempAttr = m_reservoirData->getCf();// 岩石压缩系数 tempAttr.setValue(dCf); m_reservoirData->setCf(tempAttr); // 清空现有分层数据 qDeleteAll(m_vecLayers); m_vecLayers.clear(); // 创建一个默认分层 nmDataLayer* defaultLayer = new nmDataLayer(); // 设置默认分层参数 defaultLayer->setTop(6000.0); // 默认顶深 defaultLayer->setThickness(dThickness); // 使用从框架获取的厚度值 defaultLayer->setBottom(6000.0 + dThickness); // 计算底深 defaultLayer->setIsChecked(false); // 默认未选中 defaultLayer->setColor(QColor(0, 255, 0)); // 设置默认颜色(绿色) // 将默认分层添加到分层列表 m_vecLayers.append(defaultLayer); } nmDataAxis* nmDataAnalyzeManager::getAxisData() const { return m_axisData; } void nmDataAnalyzeManager::setAxisData(nmDataAxis* pAxisData) { if(pAxisData != nullptr) { m_axisData = pAxisData; } } nmDataReservoir* nmDataAnalyzeManager::getReservoirData() const { return m_reservoirData; } nmDataReservoir nmDataAnalyzeManager::getReservoirDataCopy() const { if(m_reservoirData) { return *m_reservoirData; // 调用拷贝构造函数 } return nmDataReservoir(); // 返回默认构造对象 } void nmDataAnalyzeManager::updateReservoirData(const nmDataReservoir& newData) { if(m_reservoirData) { *m_reservoirData = newData; // 调用赋值运算符 } } nmDataGeoRef* nmDataAnalyzeManager::createGeoRefData() { if(m_pGeoRefData != nullptr) { delete m_pGeoRefData; m_pGeoRefData = nullptr; } m_pGeoRefData = new nmDataGeoRef; return m_pGeoRefData; } nmDataGeoRef* nmDataAnalyzeManager::getGeoRefData() const { return m_pGeoRefData; } nmDataGeoRef nmDataAnalyzeManager::getGeoRefDataCopy() const { if(m_pGeoRefData) { return *m_pGeoRefData; // 调用拷贝构造函数 } return nmDataGeoRef(); // 返回默认构造对象 } void nmDataAnalyzeManager::updateGeoRefData(const nmDataGeoRef& newData) { if(m_pGeoRefData == nullptr) { m_pGeoRefData = new nmDataGeoRef; } *m_pGeoRefData = newData; // 调用赋值运算符 } nmDataForecast* nmDataAnalyzeManager::createForecastData() { if(m_pForecastData != nullptr) { delete m_pForecastData; m_pForecastData = nullptr; } m_pForecastData = new nmDataForecast; return m_pForecastData; } nmDataForecast* nmDataAnalyzeManager::getForecastData() const { return m_pForecastData; } nmDataForecast nmDataAnalyzeManager::getForecastDataCopy() const { if(m_pForecastData) { return *m_pForecastData; // 调用拷贝构造函数 } return nmDataForecast(); // 返回默认构造对象 } void nmDataAnalyzeManager::updateForecastData(const nmDataForecast& newData) { if(m_pForecastData == nullptr) { m_pForecastData = new nmDataForecast; } *m_pForecastData = newData; // 调用赋值运算符 } nmDataSensitive* nmDataAnalyzeManager::createSensitiveData() { // 如果已有数据,先删除再创建 if (m_pSensitiveData != nullptr) { delete m_pSensitiveData; m_pSensitiveData = nullptr; } // 创建一个新的 nmDataSensitive 对象 m_pSensitiveData = new nmDataSensitive(); // 初始化 Calculation Type m_pSensitiveData->setCalculationType(nmDataSensitive::CALC_DETERMINISTIC); // 设置总模型数为 0,后面可以通过 setTotalModelCount 修改 m_pSensitiveData->setTotalModelCount(0); // 创建变量列表 QList vars; // 定义一个通用的添加变量的辅助函数 auto addVar = [&](const QString& group, const QString& name, double model, double min, double max, const QString& unit) { nmDataSensitive::VariableSampling vs; vs.setVarGroup(group); // 设置变量组 vs.setVarName(name); // 设置变量名 vs.setEnabled(false); // 默认不勾选 vs.setMode(nmDataSensitive::VariableSampling::MODE_AUTOMATIC); // 自动模式 vs.setLog(false); // 默认不选 Log vs.setNumber(5); // 默认 Number 为 5 // 设置 modelValue、minValue、maxValue 和单位 nmDataAttribute& modelValue = vs.getModelValue(); modelValue.setName(name + " Model"); modelValue.setUnit(unit); modelValue.setValue(model); nmDataAttribute& minValue = vs.getMinValue(); minValue.setName(name + " Min"); minValue.setUnit(unit); minValue.setValue(min); nmDataAttribute& maxValue = vs.getMaxValue(); maxValue.setName(name + " Max"); maxValue.setUnit(unit); maxValue.setValue(max); vars.append(vs); // 将变量添加到变量列表中 }; // 初始化变量组和每个变量 // === Tested Well === addVar("Tested Well", "Zw", 15.0, 7.5, 30.0, "ft"); addVar("Tested Well", "Hw", 10.0, 5.0, 20.0, "ft"); addVar("Tested Well", "Lw", 12.0, 6.0, 18.0, "ft"); addVar("Tested Well", "Skin", 1.0, 0.5, 1.5, "dimensionless"); addVar("Tested Well", "C", 0.3, 0.1, 1.0, "dimensionless"); // === Reservoir === addVar("Reservoir", "Pi", 1000.0, 800.0, 1200.0, "psi"); addVar("Reservoir", "k", 150.0, 100.0, 200.0, "mD"); addVar("Reservoir", "h", 50.0, 30.0, 70.0, "ft"); addVar("Reservoir", "φ", 0.2, 0.1, 0.4, "dimensionless"); addVar("Reservoir", "ntg", 0.9, 0.7, 1.0, "dimensionless"); addVar("Reservoir", "kz/kr", 1.0, 0.5, 1.5, "dimensionless"); // === Pvt === addVar("Pvt", "Total compressibility", 5e-6, 2e-6, 8e-6, "1/psi"); // 将变量列表设置到敏感性数据对象中 m_pSensitiveData->setVariables(vars); // 返回已初始化的敏感性数据对象 return m_pSensitiveData; } nmDataSensitive* nmDataAnalyzeManager::getSensitiveData() const { return m_pSensitiveData; } nmDataSensitive nmDataAnalyzeManager::getSensitiveDataCopy() const { if(m_pSensitiveData) { return *m_pSensitiveData; // 调用拷贝构造函数 } return nmDataSensitive(); // 返回默认构造对象 } void nmDataAnalyzeManager::updateSensitiveData(const nmDataSensitive& newData) { if(m_pSensitiveData == nullptr) { m_pSensitiveData = new nmDataSensitive(); } *m_pSensitiveData = newData; // 调用赋值运算符 } nmDataDiagnostic* nmDataAnalyzeManager::getDiagnosticData() const { return m_pDiagnosticData; } bool nmDataAnalyzeManager::resetFromDiagnostic() { // 获取当前井和储层数据 nmDataWellBase* pCurrentWell = getCurWellData(); nmDataReservoir* pReservoirData = getReservoirData(); if(!pCurrentWell || !pReservoirData) { return false; } // 获取"双对数"线性数据 QVector> rawData = pCurrentWell->getHistoryLogLog(); if(rawData.isEmpty() || rawData.size() != 3) { return false; } try { // 创建诊断对象并使用修正后的数据 if(!m_pDiagnosticData) { m_pDiagnosticData = new nmDataDiagnostic(); } m_pDiagnosticData->resetFromDiagnostic(rawData, pCurrentWell, pReservoirData); // 应用诊断结果到相应参数 applyDiagnosticResults(m_pDiagnosticData, pCurrentWell, pReservoirData); return true; } catch(...) { return false; } } bool nmDataAnalyzeManager::resetFromAnalytical() { // 获取当前井和储层数据 nmDataWellBase* pCurrentWell = getCurWellData(); nmDataReservoir* pReservoirData = getReservoirData(); if(!pCurrentWell || !pReservoirData) { return false; } try { // 重置储层参数为默认值 pReservoirData->resetToDefaults(); // 重置井参数为默认值 pCurrentWell->resetToDefaults(); return true; } catch(...) { return false; } } // 应用诊断结果 void nmDataAnalyzeManager::applyDiagnosticResults(nmDataDiagnostic* diagnostic, nmDataWellBase* wellData, nmDataReservoir* reservoirData) { if(!diagnostic || !wellData || !reservoirData) return; // 获取诊断结果 double diagnosticPerm = diagnostic->getDiagnosticPermeability().getValue().toDouble(); double diagnosticStorage = diagnostic->getDiagnosticWellboreStorage().getValue().toDouble(); double diagnosticTrans = diagnostic->getDiagnosticTransmissibility().getValue().toDouble(); double diagnosticSkin = diagnostic->getDiagnosticSkin().getValue().toDouble(); // 应用渗透率到储层数据 nmDataAttribute& reservoirPerm = reservoirData->getPermeability(); reservoirPerm.setValue(diagnosticPerm); // 应用井筒储存到井数据 nmDataAttribute& wellStorage = wellData->getWellboreStorage(); wellStorage.setValue(diagnosticStorage); // 应用导流能力到储层数据 nmDataAttribute& reservoirTrans = reservoirData->getTransmissibility(); reservoirTrans.setValue(diagnosticTrans); // 应用皮损系数到井的第一段射孔 if(wellData->getPerforationCount() > 0) { nmDataPerforation* firstPerforation = wellData->getPerforation(0); if(firstPerforation) { firstPerforation->getSkin().setValue(diagnosticSkin); } } } nmDataAutomaticFitting* nmDataAnalyzeManager::createAutomaticFittingData() { if(m_pAutomaticFittingData != nullptr) { delete m_pAutomaticFittingData; m_pAutomaticFittingData = nullptr; } m_pAutomaticFittingData = new nmDataAutomaticFitting; return m_pAutomaticFittingData; } nmDataAutomaticFitting* nmDataAnalyzeManager::getAutomaticFittingData() const { return m_pAutomaticFittingData; } nmDataAutomaticFitting nmDataAnalyzeManager::getAutomaticFittingDataCopy() const { if(m_pAutomaticFittingData) { return *m_pAutomaticFittingData; // 调用拷贝构造函数 } return nmDataAutomaticFitting(); // 返回默认构造对象 } void nmDataAnalyzeManager::updateAutomaticFittingData(const nmDataAutomaticFitting& newData) { if(m_pAutomaticFittingData == nullptr) { m_pAutomaticFittingData = new nmDataAutomaticFitting; } *m_pAutomaticFittingData = newData; // 调用赋值运算符 } void nmDataAnalyzeManager::initPvtParaFromSubFit() { // 根据当前Fitting窗口来获取对应的井相关数据 iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting(); nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider(); Q_ASSERT(nullptr != pSubWndFitting); Q_ASSERT(nullptr != pContextProvider); // 获取PEBI网格需要的Pvt数据 // 定义返回结果的 QMap QMap mapPebiPvtPara; if(nullptr != pSubWndFitting && nullptr != pContextProvider) { PvtFluidType eType = WFT_Null; pContextProvider->getBasicPft(pSubWndFitting, eType); bool bReadOilPvt = false; bool bReadGasPvt = false; bool bReadWaterPvt = false; resolvePvtPhaseReadFlags(eType, bReadOilPvt, bReadGasPvt, bReadWaterPvt); QStringList listPvtParas; // 单值参数同样按当前相态筛选,避免读取不存在的Phase子窗口 if(bReadOilPvt) { listPvtParas << "Pb" //压力, MPa << "Rs" //溶解气油比, m^3/m^3 << "Bo" //油体积系数, m^3/m^3 << "Co" //油压缩系数, 1/MPa << "Miuo" //油粘度, mPa·s << "Rhoo"; //油密度, kg/m^3 } if(bReadGasPvt) { listPvtParas << "Rv" //凝析油气比, m^3/m^3 << "Bg" //气体积系数, m^3/m^3 << "Cg" //气压缩系数, 1/MPa << "Miug" //气粘度, mPa·s << "Rhog" //气密度, kg/m^3 << "Zg"; //气偏差因子, 1 } if(bReadWaterPvt) { listPvtParas << "Rsw" //溶解气水比, m^3/m^3 << "Bw" //水体积系数, m^3/m^3 << "Cw" //水压缩系数, 1/MPa << "Miuw" //水粘度, mPa·s << "Rhow"; //水密度, kg/m^3 } // Ct/Cf为基础单值参数,保留原有读取逻辑 listPvtParas << "Ct" << "Cf"; //QVector vecPressure; // 压力, MPa QVector vecRso; // 溶解气油比, m^3/m^3 QVector vecBo; // 油体积系数, m^3/m^3 QVector vecCo; // 油压缩系数, 1/MPa QVector vecMiuo; // 油粘度, mPa·s QVector vecRouo; // 油密度, kg/m^3 QVector vecRv; // 凝析油气比, m^3/m^3 QVector vecBg; // 气体积系数, m^3/m^3 QVector vecCg; // 气压缩系数, 1/MPa QVector vecMiug; // 气粘度, mPa·s QVector vecRoug; // 气密度, kg/m^3 QVector vecZ; // 气偏差因子, 1 QVector vecRsw; // 溶解气水比, m^3/m^3 QVector vecBw; // 水体积系数, m^3/m^3 QVector vecCw; // 水压缩系数, 1/MPa QVector vecMiuw; // 水粘度, mPa·s QVector vecRouw; // 水密度, kg/m^3 pContextProvider->getPvtParaValues(pSubWndFitting, listPvtParas, mapPebiPvtPara); VecDouble vecX; // 判断是否已有PebiPvt参数数据 if(m_pebiPvtPara != nullptr) { delete m_pebiPvtPara; m_pebiPvtPara = nullptr; } m_pebiPvtPara = new nmDataPvtParaForPebi; // 饱和压力为单值参数,读到时覆盖求解器默认值 if(mapPebiPvtPara.contains("Pb")) { m_pebiPvtPara->setPb(nmDataAttribute("Pb", mapPebiPvtPara.value("Pb"), "MPa")); } // PVT结果曲线也只读取当前相态已有的页,缺失相态保留PEBI默认数据 if(bReadOilPvt) { // 气油比 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Rs", vecX, vecRso); m_pebiPvtPara->setRso(vecRso); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 油体积系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Bo", vecX, vecBo); m_pebiPvtPara->setBo(vecBo); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 油压缩系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Co", vecX, vecCo); m_pebiPvtPara->setCo(vecCo); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 油密度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Rhoo", vecX, vecRouo); m_pebiPvtPara->setRouo(vecRouo); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 油粘度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Miuo", vecX, vecMiuo); m_pebiPvtPara->setMiuo(vecMiuo); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); } if(bReadGasPvt) { // 凝析油气比 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Rv", vecX, vecRv); m_pebiPvtPara->setRv(vecRv); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 气体积系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Bg", vecX, vecBg); m_pebiPvtPara->setBg(vecBg); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 气压缩系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Cg", vecX, vecCg); m_pebiPvtPara->setCg(vecCg); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 气粘度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Miug", vecX, vecMiug); m_pebiPvtPara->setMiug(vecMiug); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 气密度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Rhog", vecX, vecRoug); m_pebiPvtPara->setRoug(vecRoug); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 气偏差因子 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Zg", vecX, vecZ); m_pebiPvtPara->setZ(vecZ); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); } if(bReadWaterPvt) { // 溶解气水比 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Rsw", vecX, vecRsw); m_pebiPvtPara->setRsw(vecRsw); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 水体积系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Bw", vecX, vecBw); m_pebiPvtPara->setBw(vecBw); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 水压缩系数 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Cw", vecX, vecCw); m_pebiPvtPara->setCw(vecCw); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 水粘度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Miuw", vecX, vecMiuw); m_pebiPvtPara->setMiuw(vecMiuw); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); // 水密度 pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Rhow", vecX, vecRouw); m_pebiPvtPara->setRouw(vecRouw); setPebiPressureIfEmpty(m_pebiPvtPara, vecX); } if(eType == WFT_Oil_Water) { // Diffusion相关数据来自Diffusion页面,只在油水两相时读取 // DSO_KK:相渗结果,主要用于So/Kro/Sw/Krw VVecDouble vvecDiffusionKK; if(pContextProvider->getDiffusionRstOf(pSubWndFitting, DSO_KK, vvecDiffusionKK)) { applyDiffusionKkToPebiPvt(m_pebiPvtPara, vvecDiffusionKK); } } } //// 吸附气量,王老师界面没有,油相暂时不需要 //m_pebiPvtPara->setV(vecV); // //// 渗透率比,王老师界面没有,油相暂时不需要 //m_pebiPvtPara->setKKinitial(vecKKinitial); //// 岩石压缩系数比,王老师界面没有,油相暂时不需要 //m_pebiPvtPara->setCfCfinitial(vecCfCfinitial); //// 相渗,单相暂时用不到 ////QVector< QVector > vvec; ////pSubWndFitting->getDiffusionRstOf(DiffusionSubOption::DSO_KK, vvec); ////QVector vecSw; ////QVector vecKro; ////QVector vecKrw; //// 遍历 vvec 中的每个子向量 ////foreach (const QVector& innerVec , vvec) { //// // 确保每个子向量确实有3个元素 //// if (innerVec.size() >= 3) { //// vecSw.append(innerVec[0]); // 第一个元素是 Sw //// vecKro.append(innerVec[1]); // 第二个元素是 Kro //// vecKrw.append(innerVec[2]); // 第三个元素是 Krw //// } ////} //// 油饱和度 //m_pebiPvtPara->setSo(vecSo); //// 油相对渗透率 //m_pebiPvtPara->setKro(vecKro); //// 气饱和度 //m_pebiPvtPara->setSg(vecSg); //// 气相对渗透率 //m_pebiPvtPara->setKrg(vecKrg); //// 水饱和度 //m_pebiPvtPara->setSw(vecSw); //// 水相对渗透率 //m_pebiPvtPara->setKrw(vecKrw); // 调用 getPvtParaValues 函数获取参数值 //pSubWndFitting->getPvtParaValues(listPvtParas, mapPebiPvtPara); //m_pebiPvtPara->setZ(mapPebiPvtPara.contains("Zg") ? // QVector(200, mapPebiPvtPara["Zg"]) : //QVector(200, 1)); // 下面参数单项流不需要 //m_pebiPvtPara->setRv(mapPebiPvtPara.contains("Rv") ? // QVector(200, mapPebiPvtPara["Rv"]) : //QVector(200, 0)); //m_pebiPvtPara->setV(mapPebiPvtPara.contains("V") ? // QVector(200, mapPebiPvtPara["V"]) : //QVector(200, 0)); //m_pebiPvtPara->setKKinitial(mapPebiPvtPara.contains("k_kinitial") ? // QVector(200, mapPebiPvtPara["k_kinitial"]) : //QVector(200, 1)); //m_pebiPvtPara->setCfCfinitial(mapPebiPvtPara.contains("Cf_Cfinitial") ? // QVector(200, mapPebiPvtPara["Cf_Cfinitial"]) : //QVector(200, 1)); //// 饱和度与相对渗透率(大小为100) //m_pebiPvtPara->setSo(mapPebiPvtPara.contains("So") ? //QVector(100, mapPebiPvtPara["So"]) : //QVector(100, 0)); //m_pebiPvtPara->setKro(mapPebiPvtPara.contains("Kro") ? // QVector(100, mapPebiPvtPara["Kro"]) : //QVector(100, 0)); //m_pebiPvtPara->setSg(mapPebiPvtPara.contains("Sg") ? // QVector(100, mapPebiPvtPara["Sg"]) : //QVector(100, 0)); //m_pebiPvtPara->setKrg(mapPebiPvtPara.contains("Krg") ? // QVector(100, mapPebiPvtPara["Krg"]) : //QVector(100, 0)); //m_pebiPvtPara->setSw(mapPebiPvtPara.contains("Sw") ? // QVector(100, mapPebiPvtPara["Sw"]) : //QVector(100, 0)); //m_pebiPvtPara->setKrw(mapPebiPvtPara.contains("Krw") ? // QVector(100, mapPebiPvtPara["Krw"]) : //QVector(100, 0)); } nmDataRegionMark *nmDataAnalyzeManager::createRegionMark() { nmDataRegionMark* regionMarkData = new nmDataRegionMark; m_vRegionMarkData.append(regionMarkData); return regionMarkData; } QVector nmDataAnalyzeManager::getRegionMarkDataList() const { return m_vRegionMarkData; } bool nmDataAnalyzeManager::removeRegionMarkData(nmDataRegionMark * pData) { if(pData) { // 遍历 m_vRegionMarkData 数组,找到并移除对应的对象 for(int i = 0; i < m_vRegionMarkData.size(); ++i) { if(m_vRegionMarkData[i] == pData) { delete m_vRegionMarkData[i]; // 释放内存 m_vRegionMarkData.remove(i); return true; // 移除成功,返回 true } } } return false; // 未找到或移除失败,返回 false } QVector nmDataAnalyzeManager::getRegionMarkDataListCopy() const { QVector result; result.reserve(m_vRegionMarkData.size()); foreach(const nmDataRegionMark* regionMark, m_vRegionMarkData) { if(regionMark) { result.append(*regionMark); // 调用拷贝构造函数 } } return result; } void nmDataAnalyzeManager::updateRegionMarkData(const QVector& newData) { // 确保数量一致 if(newData.size() != m_vRegionMarkData.size()) { return; } for(int i = 0; i < newData.size(); ++i) { if(m_vRegionMarkData[i]) { // 只更新内容,不改变指针 *m_vRegionMarkData[i] = newData[i]; // 调用赋值运算符 } } } nmDataOutline *nmDataAnalyzeManager::createOutline() { if(m_outlineData != nullptr) { delete m_outlineData; m_outlineData = nullptr; } m_outlineData = new nmDataOutline; return m_outlineData; } nmDataOutline* nmDataAnalyzeManager::getOutlineData() { return m_outlineData; } bool nmDataAnalyzeManager::removeOutlineData() { if(m_outlineData) { delete m_outlineData; // 删除边界数据对象 m_outlineData = nullptr; return true; // 移除成功,返回 true } return false; // 未找到或移除失败,返回 false } nmDataOutline nmDataAnalyzeManager::getOutlineDataCopy() const { if(m_outlineData) { return *m_outlineData; // 调用拷贝构造函数 } nmDataOutline obj; return obj; // 返回默认构造对象 } void nmDataAnalyzeManager::updateOutlineData(const nmDataOutline & newData) { if(m_outlineData) { *m_outlineData = newData; // 调用赋值运算符 } } nmDataRegion *nmDataAnalyzeManager::createRegion() { nmDataRegion* regionData = new nmDataRegion; m_vRegionData.append(regionData); return regionData; } QVector nmDataAnalyzeManager::getRegionDataList() const { return m_vRegionData; } bool nmDataAnalyzeManager::removeRegionData(nmDataRegion * pData) { if(pData) { // 遍历 m_vRegionData 数组,找到并移除对应的对象 for(int i = 0; i < m_vRegionData.size(); ++i) { if(m_vRegionData[i] == pData) { delete m_vRegionData[i]; // 释放内存 m_vRegionData.remove(i); return true; // 移除成功,返回 true } } } return false; // 未找到或移除失败,返回 false } QVector nmDataAnalyzeManager::getRegionDataListCopy() const { QVector result; result.reserve(m_vRegionData.size()); foreach(const nmDataRegion* region, m_vRegionData) { if(region) { result.append(*region); // 调用拷贝构造函数 } } return result; } void nmDataAnalyzeManager::updateRegionData(const QVector& newData) { // 确保数量一致 if(newData.size() != m_vRegionData.size()) { return; } for(int i = 0; i < newData.size(); ++i) { if(m_vRegionData[i]) { // 只更新内容,不改变指针 *m_vRegionData[i] = newData[i]; // 调用赋值运算符 } } } nmDataFracture *nmDataAnalyzeManager::createFracture() { nmDataFracture* fractureData = new nmDataFracture; m_vFractureData.append(fractureData); return fractureData; } QVector nmDataAnalyzeManager::getFractureDataList() const { return m_vFractureData; } QVector nmDataAnalyzeManager::getDFNFractureDataList() const { QVector vecDFNs; // 遍历 m_vFractureData 数组,找到并移除对应的对象 for(int i = 0; i < m_vFractureData.size(); ++i) { if(m_vFractureData[i]->getFractureType().getValue() == tr("DFN")) { vecDFNs.append(m_vFractureData[i]); } } return vecDFNs; } bool nmDataAnalyzeManager::removeFractureData(nmDataFracture * pData) { if(pData) { // 遍历 m_vFractureData 数组,找到并移除对应的对象 for(int i = 0; i < m_vFractureData.size(); ++i) { if(m_vFractureData[i] == pData) { delete m_vFractureData[i]; // 释放内存 m_vFractureData.remove(i); emit dataChanged(); return true; // 移除成功,返回 true } } } return false; // 未找到或移除失败,返回 false } QVector nmDataAnalyzeManager::getFractureDataListCopy() const { QVector result; result.reserve(m_vFractureData.size()); foreach(const nmDataFracture* fracture, m_vFractureData) { if(fracture) { result.append(*fracture); // 调用拷贝构造函数 } } return result; } void nmDataAnalyzeManager::updateFractureData(const QVector& newData) { // 确保数量一致 if(newData.size() != m_vFractureData.size()) { return; } for(int i = 0; i < newData.size(); ++i) { if(m_vFractureData[i]) { // 只更新内容,不改变指针 *m_vFractureData[i] = newData[i]; // 调用赋值运算符 } } } nmDataFault *nmDataAnalyzeManager::createFault() { nmDataFault* faultData = new nmDataFault; m_vFaultData.append(faultData); return faultData; } QVector nmDataAnalyzeManager::getFaultDataList() const { return m_vFaultData; } bool nmDataAnalyzeManager::removeFaultData(nmDataFault * pData) { if(pData) { // 遍历 m_vFaultData 数组,找到并移除对应的对象 for(int i = 0; i < m_vFaultData.size(); ++i) { if(m_vFaultData[i] == pData) { delete m_vFaultData[i]; // 释放内存 m_vFaultData.remove(i); emit dataChanged(); return true; // 移除成功,返回 true } } } return false; // 未找到或移除失败,返回 false } QVector nmDataAnalyzeManager::getFaultDataListCopy() const { QVector result; result.reserve(m_vFaultData.size()); foreach(const nmDataFault* fault, m_vFaultData) { if(fault) { result.append(*fault); // 调用拷贝构造函数 } } return result; } void nmDataAnalyzeManager::updateFaultData(const QVector& newData) { // 确保数量一致 if(newData.size() != m_vFaultData.size()) { return; } for(int i = 0; i < newData.size(); ++i) { if(m_vFaultData[i]) { // 只更新内容,不改变指针 *m_vFaultData[i] = newData[i]; // 调用赋值运算符 } } } nmGuiPlot* nmDataAnalyzeManager::getPlot() const { return m_pNmGuiPlot; } void nmDataAnalyzeManager::setPlot(nmGuiPlot * plot) { m_pNmGuiPlot = plot; } void nmDataAnalyzeManager::updateWellPlotByDataManager() { nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider(); if (m_pNmGuiPlot != nullptr && pPlotContextProvider != nullptr) { pPlotContextProvider->updateWellPlots(m_pNmGuiPlot, this); } } QVector nmDataAnalyzeManager::getValueAllConnectablePoints() { QVector vecAllPoints; // 遍历所有断层数据 foreach(nmDataFault* fault, m_vFaultData) { if(fault) { QVector faultPoints = fault->getFaultPoints(); foreach(const QPointF& point, faultPoints) { vecAllPoints.append(point); } } } // 遍历所有裂缝数据 foreach(nmDataFracture* fracture, m_vFractureData) { if(fracture) { QVector fracturePoints = fracture->getFracturePoints(); foreach(const QPointF& point, fracturePoints) { vecAllPoints.append(point); } } } // 遍历所有复合区数据 foreach(nmDataRegion* region, m_vRegionData) { if(region) { QVector regionPoints = region->getVecPts(); foreach(const QPointF& point, regionPoints) { vecAllPoints.append(point); } } } // 处理边界数据 if(m_outlineData) { QVector outlinePoints = m_outlineData->getOutlinePoints(); // 圆形边界,特殊处理 if(m_outlineData->getOutlineType() == NM_Round_Outline_Type) { outlinePoints.remove(0); // 圆心 outlinePoints.remove(0); // 半径 } foreach(const QPointF& point, outlinePoints) { vecAllPoints.append(point); } } // 垂直裂缝井的裂缝两个端点 // 遍历所有井数据 foreach(nmDataWellBase* well, m_vWellData) { if(well == nullptr) { continue; } if(well->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) { nmDataVerticalFracturedWell* pVFwell = dynamic_cast(well); if(pVFwell == nullptr) { continue; } QVector fracsPoints = pVFwell->getFracs(); foreach(const QPointF& point, fracsPoints) { vecAllPoints.append(point); } } } return vecAllPoints; } QVector nmDataAnalyzeManager::getPosAllConnectablePoints() { // 将绘图坐标系转为qt坐标系 QVector vecValues = this->getValueAllConnectablePoints(); QVector vecPos; Q_ASSERT(m_pNmGuiPlot != nullptr); nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider(); if(m_pNmGuiPlot == nullptr || pPlotContextProvider == nullptr) { return vecPos; } pPlotContextProvider->getPosForValue(m_pNmGuiPlot, vecValues, vecPos); // TODO:没有m_pNmGuiPlot的情况下怎么办,也就是加载的时候 return vecPos; } QVector nmDataAnalyzeManager::removePosByObject(QObject * obj) { // 获取所有可连接的点(屏幕坐标) QVector vecAllPoints = this->getPosAllConnectablePoints(); // 创建一个临时容器用于存储要移除的点 QVector pointsToRemove; // 检查传入的对象类型并收集相关点 if(nmDataFault * fault = dynamic_cast(obj)) { QVector faultPoints = fault->getFaultPoints(); foreach(const QPointF& point, faultPoints) { pointsToRemove.append(point); } } else if(nmDataFracture * fracture = dynamic_cast(obj)) { QVector fracturePoints = fracture->getFracturePoints(); foreach(const QPointF& point, fracturePoints) { pointsToRemove.append(point); } } else if(nmDataRegion * region = dynamic_cast(obj)) { QVector regionPoints = region->getVecPts(); foreach(const QPointF& point, regionPoints) { pointsToRemove.append(point); } } else if(nmDataVerticalFracturedWell * well = dynamic_cast(obj)) { QVector fracsPoints = well->getFracs(); foreach(const QPointF& point, fracsPoints) { pointsToRemove.append(point); } } else if(m_outlineData == obj) { QVector outlinePoints = m_outlineData->getOutlinePoints(); if(m_outlineData->getOutlineType() == NM_Round_Outline_Type) { outlinePoints.remove(0); // 圆心 outlinePoints.remove(0); // 半径 } foreach(const QPointF& point, outlinePoints) { pointsToRemove.append(point); } } // change to Pos QVector vecPosRemove; nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider(); if(m_pNmGuiPlot && pPlotContextProvider) { pPlotContextProvider->getPosForValue(m_pNmGuiPlot, pointsToRemove, vecPosRemove); } // 移除与特定对象相关的点 QVector::iterator itRemove; for(itRemove = vecPosRemove.begin(); itRemove != vecPosRemove.end(); ++itRemove) { QPointF pointToRemove = *itRemove; for(int i = 0; i < vecAllPoints.size(); ++i) { if(vecAllPoints[i] == pointToRemove) { vecAllPoints.remove(i); break; // 只移除第一个匹配的点 } } } return vecAllPoints; } nmDataMeasuringScale *nmDataAnalyzeManager::getMeasuringScaleData() { if(m_pMeasuringScaleData == nullptr) { m_pMeasuringScaleData = new nmDataMeasuringScale; } return m_pMeasuringScaleData; } void nmDataAnalyzeManager::setMeasuringScaleData(nmDataMeasuringScale * pMeasuringScaleData) { if(m_pMeasuringScaleData != nullptr) { delete m_pMeasuringScaleData; m_pMeasuringScaleData = nullptr; } m_pMeasuringScaleData = pMeasuringScaleData; } nmDataMeasure *nmDataAnalyzeManager::getMeasureData() { if(m_pMeasureData == nullptr) { m_pMeasureData = new nmDataMeasure; } return m_pMeasureData; } void nmDataAnalyzeManager::setMeasureData(nmDataMeasure * pMeasureData) { if(m_pMeasureData != nullptr) { delete m_pMeasureData; m_pMeasureData = nullptr; } m_pMeasureData = pMeasureData; } bool nmDataAnalyzeManager::removeMeasureData() { if(m_pMeasureData) { delete m_pMeasureData; m_pMeasureData = nullptr; return true; // 移除成功,返回 true } return false; // 未找到或移除失败,返回 false } NM_Grid_Type nmDataAnalyzeManager::getGridType() { return m_eGridType; } void nmDataAnalyzeManager::setGridType(NM_Grid_Type newGridType) { m_eGridType = newGridType; } // 获取Pebi网格求解数据接口 // 获取压力历史数据 QVector> nmDataAnalyzeManager::getPebiSolverHistoryDataByName(const QString & wellName) { QVector> vvecHisotryData; QVector vX; QVector vY; // 验证井名有效性 if(wellName.isEmpty()) { return vvecHisotryData; } // 从结果文件中读取数据 QString sHistoryDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/Pressure.txt"; if(!QFile::exists(sHistoryDataFilePath)) { return vvecHisotryData; } QStringList sContent = nmDataUtils::readNmDataFile(sHistoryDataFilePath); QRegExp regex("\\s+"); for(int i = 0; i < sContent.size(); i++) { QString sData = sContent[i].trimmed(); if(sData.isEmpty()) continue; QStringList sXY = sData.split(regex, QString::SkipEmptyParts); if(sXY.size() == 2) { bool okX, okY; double x = sXY[0].toDouble(&okX); double y = sXY[1].toDouble(&okY); if(okX && okY) { vX.append(x); vY.append(y); } } } vvecHisotryData.append(vX); vvecHisotryData.append(vY); return vvecHisotryData; } QVector> nmDataAnalyzeManager::getPebiSolverLogPreDataByName(const QString & wellName) { QVector> vvecLogPreData; QVector vX; QVector vY; QVector vZ; // 验证井名有效性 if(wellName.isEmpty()) { return vvecLogPreData; } // 从结果文件中读取数据 QString sLogPreDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/Loglog.txt"; if(!QFile::exists(sLogPreDataFilePath)) { return vvecLogPreData; } QStringList sContent = nmDataUtils::readNmDataFile(sLogPreDataFilePath); QRegExp regex("\\s+"); for(int i = 0; i < sContent.size() - 1; i++) { QString sData = sContent[i].trimmed(); if(sData.isEmpty()) continue; QStringList sXYZ = sData.split(regex, QString::SkipEmptyParts); if(sXYZ.size() == 3) { bool okX, okY, okZ; double x = sXYZ[0].toDouble(&okX); double y = sXYZ[1].toDouble(&okY); double z = sXYZ[2].toDouble(&okZ); if(okX && okY && okZ) { vX.append(x); vY.append(y); vZ.append(z); } } } vvecLogPreData.append(vX); vvecLogPreData.append(vY); vvecLogPreData.append(vZ); return vvecLogPreData; } QVector> nmDataAnalyzeManager::getPebiSolverSemiLogPreDataByName(const QString & wellName) { QVector> vvecSemiLogPreData; QVector vX; QVector vY; // 验证井名有效性 if(wellName.isEmpty()) { return vvecSemiLogPreData; } // 从结果文件中读取数据 QString sSemiLogPreDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/SemiLog.txt"; if(!QFile::exists(sSemiLogPreDataFilePath)) { return vvecSemiLogPreData; } QStringList sContent = nmDataUtils::readNmDataFile(sSemiLogPreDataFilePath); QRegExp regex("\\s+"); for(int i = 0; i < sContent.size(); i++) { QString sData = sContent[i].trimmed(); if(sData.isEmpty()) continue; QStringList sXY = sData.split(regex, QString::SkipEmptyParts); if(sXY.size() == 2) { bool okX, okY; double x = sXY[0].toDouble(&okX); double y = sXY[1].toDouble(&okY); if(okX && okY) { vX.append(x); vY.append(y); } } } vvecSemiLogPreData.append(vX); vvecSemiLogPreData.append(vY); return vvecSemiLogPreData; } nmDataPvtParaForPebi* nmDataAnalyzeManager::getPebiPvtPara() { return m_pebiPvtPara; } nmDataMixedResults* nmDataAnalyzeManager::getMixedResults() { return m_pMixedResults; } nmDataMixedResults* nmDataAnalyzeManager::createMixedResult() { if(m_pMixedResults != nullptr) { delete m_pMixedResults; m_pMixedResults = nullptr; } m_pMixedResults = new nmDataMixedResults; return m_pMixedResults; } nmDataLayer* nmDataAnalyzeManager::getLayerData() { // 1. 删除 m_vecLayers 中当前存储的所有 nmDataLayer 对象,释放内存 qDeleteAll(m_vecLayers); // 2. 清空 m_vecLayers 自身,移除所有指针 m_vecLayers.clear(); return m_pLayerData; } void nmDataAnalyzeManager::setLayers(QVector vecLayers) { m_vecLayers = vecLayers; } QVector nmDataAnalyzeManager::getLayers() { return m_vecLayers; } double nmDataAnalyzeManager::getMinLayerTop() { // 在计算前初始化边界值 double m_dMinLayerTop = DBL_MAX; // 复制新数据并计算边界 foreach(const nmDataLayer* layer , m_vecLayers) { if(layer) { // 更新缓存的最小顶深度 m_dMinLayerTop = qMin(m_dMinLayerTop, layer->getTop()); } } // 如果 m_vecLayers 为空,可以设置默认值 if(m_vecLayers.isEmpty()) { m_dMinLayerTop = 0.0; } return m_dMinLayerTop; } // 新增的实现:返回存储的最大底深度 double nmDataAnalyzeManager::getMaxLayerBottom() { // 在计算前初始化边界值 double m_dMaxLayerBottom = DBL_MIN; // 复制新数据并计算边界 foreach(const nmDataLayer* layer , m_vecLayers) { if(layer) { // 更新缓存的最大顶深度 m_dMaxLayerBottom = qMax(m_dMaxLayerBottom, layer->getBottom()); } } // 如果 m_vecLayers 为空,可以设置默认值 if(m_vecLayers.isEmpty()) { m_dMaxLayerBottom = 0.0; } return m_dMaxLayerBottom; } void nmDataAnalyzeManager::appendCalculationWell(const QPair& well) { m_vecCalculationWells.append(well); } void nmDataAnalyzeManager::insertCalculationWell(int index, const QPair& well) { if(index < 0 || index > m_vecCalculationWells.size()) { return; // 索引无效,不执行插入操作 } m_vecCalculationWells.insert(index, well); } bool nmDataAnalyzeManager::removeCalculationWell(int index) { if(index < 0 || index >= m_vecCalculationWells.size()) { return false; // 索引无效,返回 false } m_vecCalculationWells.remove(index); return true; } void nmDataAnalyzeManager::clearCalculationWells() { m_vecCalculationWells.clear(); } QVector> nmDataAnalyzeManager::getCalculationWells() const { return m_vecCalculationWells; } bool nmDataAnalyzeManager::isContainsWellName(const QString & wellName) const { for(int i = 0; i < m_vecCalculationWells.size(); ++i) { const QPair& well = m_vecCalculationWells[i]; if(well.first == NM_WELL_MODEL::Unknow_Well) { continue; } if(well.second == wellName) { return true; } } return false; } // 设置当前查看井 void nmDataAnalyzeManager::setCurWellData(nmDataWellBase * wellData) { m_pCurDataWell = wellData; } // 获取当前查看井 nmDataWellBase* nmDataAnalyzeManager::getCurWellData() { return m_pCurDataWell; } void nmDataAnalyzeManager::notifyDataChanged() { emit dataChanged(); } void nmDataAnalyzeManager::setDisplaySettings(const QVector& displaySettings) { m_vecDisplaySettings = displaySettings; } QVector nmDataAnalyzeManager::getDisplaySettings() const { return m_vecDisplaySettings; } bool nmDataAnalyzeManager::updateCategoryDisplaySetting(const QString & categoryName, const CategoryDisplayInfo & info) { for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == categoryName) { m_vecDisplaySettings[i].value = info; return true; } } return false; } void nmDataAnalyzeManager::initDefaultDisplaySettings() { m_vecDisplaySettings.clear(); // Contour DisplaySetting contourSetting; contourSetting.key = tr("Contour"); contourSetting.value.isRootChecked = true; // 默认选中 m_vecDisplaySettings.append(contourSetting); // Faults DisplaySetting faultsSetting; faultsSetting.key = tr("Faults"); faultsSetting.value.isRootChecked = true; m_vecDisplaySettings.append(faultsSetting); // Images DisplaySetting imagesSetting; imagesSetting.key = tr("Images"); imagesSetting.value.isRootChecked = true; m_vecDisplaySettings.append(imagesSetting); // Wells DisplaySetting wellsSetting; wellsSetting.key = tr("Wells"); wellsSetting.value.isRootChecked = true; m_vecDisplaySettings.append(wellsSetting); // Fractures DisplaySetting fracturesSetting; fracturesSetting.key = tr("Fractures"); fracturesSetting.value.isRootChecked = true; m_vecDisplaySettings.append(fracturesSetting); // Limits DisplaySetting limitsSetting; limitsSetting.key = tr("Regions"); limitsSetting.value.isRootChecked = true; m_vecDisplaySettings.append(limitsSetting); // RegionMarks DisplaySetting regionsSetting; regionsSetting.key = tr("RegionMarks"); regionsSetting.value.isRootChecked = true; m_vecDisplaySettings.append(regionsSetting); } CategoryDisplayInfo* nmDataAnalyzeManager::findCategoryDisplayInfo(const QString & categoryName) { for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == categoryName) { return &m_vecDisplaySettings[i].value; } } return nullptr; } bool nmDataAnalyzeManager::appendDisplaySetting(const DisplaySetting & displaySetting) { // 检查是否已存在相同key的设置 foreach(const auto& setting, m_vecDisplaySettings) { if(setting.key == displaySetting.key) { return false; // 已存在相同key,添加失败 } } // 添加新的显示设置 m_vecDisplaySettings.append(displaySetting); return true; } bool nmDataAnalyzeManager::removeDisplaySetting(const QString & categoryName) { // 遍历查找并删除指定key的设置 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == categoryName) { m_vecDisplaySettings.remove(i); return true; // 删除成功 } } return false; // 未找到指定key的设置,删除失败 } bool nmDataAnalyzeManager::addChildItemsToCategory(const QString & parentCategory, const QStringList & childNames, bool defaultChecked) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个子项名称创建ChildCategoryDisplayInfo并添加到父类别 for(int j = 0; j < childNames.size(); ++j) { ChildCategoryDisplayInfo childInfo; childInfo.name = childNames.at(j); childInfo.isChecked = defaultChecked; childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; // 子项启用状态取决于父项 m_vecDisplaySettings[i].value.childItems.append(childInfo); } return true; } } return false; } void nmDataAnalyzeManager::refreshChildItemsDisplay() { // 步骤1: 清空所有父节点的子节点 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { m_vecDisplaySettings[i].value.childItems.clear(); } // 更新边界和位图 CategoryDisplayInfo outlineInfo, imageInfo; outlineInfo.isRootChecked = m_outlineData->getPlotVisible(); imageInfo.isRootChecked = this->m_backgroundImageInfo.bIsVisible; this->updateCategoryDisplaySetting(tr("Contour"), outlineInfo); this->updateCategoryDisplaySetting(tr("Images"), imageInfo); // 步骤2: 重新添加子节点,根据不同数据容器中的对象名称生成子节点 // 为 "Wells" 分类添加子节点 addWellChildItemsToCategory(tr("Wells")); // 为 "Faults" 分类添加子节点 addFaultChildItemsToCategory(tr("Faults")); // 为 "Fractures" 分类添加子节点 addFractureChildItemsToCategory(tr("Fractures")); // 为 "Regions" 分类添加子节点 addRegionChildItemsToCategory(tr("Regions")); // 为 "RegionMarks" 分类添加子节点 addRegionMarkChildItemsToCategory(tr("RegionMarks")); } // 为Wells分类添加子节点 void nmDataAnalyzeManager::addWellChildItemsToCategory(const QString & parentCategory) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个井对象创建子节点 for(int j = 0; j < m_vWellData.size(); ++j) { if(m_vWellData[j]) { ChildCategoryDisplayInfo childInfo; childInfo.name = m_vWellData[j]->getWellName(); childInfo.isChecked = m_vWellData[j]->getPlotVisible(); childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; m_vecDisplaySettings[i].value.childItems.append(childInfo); } } return; } } } // 为Faults分类添加子节点 void nmDataAnalyzeManager::addFaultChildItemsToCategory(const QString & parentCategory) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个断层对象创建子节点 for(int j = 0; j < m_vFaultData.size(); ++j) { if(m_vFaultData[j]) { ChildCategoryDisplayInfo childInfo; childInfo.name = m_vFaultData[j]->getFaultName(); childInfo.isChecked = m_vFaultData[j]->getPlotVisible(); childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; m_vecDisplaySettings[i].value.childItems.append(childInfo); } } return; } } } // 为Fractures分类添加子节点 void nmDataAnalyzeManager::addFractureChildItemsToCategory(const QString & parentCategory) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个裂缝对象创建子节点 for(int j = 0; j < m_vFractureData.size(); ++j) { if(m_vFractureData[j]) { ChildCategoryDisplayInfo childInfo; childInfo.name = m_vFractureData[j]->getFractureName(); childInfo.isChecked = m_vFractureData[j]->getPlotVisible(); childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; m_vecDisplaySettings[i].value.childItems.append(childInfo); } } return; } } } // 为Regions分类添加子节点 void nmDataAnalyzeManager::addRegionChildItemsToCategory(const QString & parentCategory) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个复合区对象创建子节点 for(int j = 0; j < m_vRegionData.size(); ++j) { if(m_vRegionData[j]) { ChildCategoryDisplayInfo childInfo; childInfo.name = m_vRegionData[j]->getRegoinName(); childInfo.isChecked = m_vRegionData[j]->getPlotVisible(); childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; m_vecDisplaySettings[i].value.childItems.append(childInfo); } } return; } } } // 为RegionMarks分类添加子节点 void nmDataAnalyzeManager::addRegionMarkChildItemsToCategory(const QString & parentCategory) { // 查找父类别 for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { if(m_vecDisplaySettings[i].key == parentCategory) { // 为每个区域标记对象创建子节点 for(int j = 0; j < m_vRegionMarkData.size(); ++j) { if(m_vRegionMarkData[j]) { ChildCategoryDisplayInfo childInfo; childInfo.name = m_vRegionMarkData[j]->getRegionMarkName(); childInfo.isChecked = m_vRegionMarkData[j]->getPlotVisible(); childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; m_vecDisplaySettings[i].value.childItems.append(childInfo); } } return; } } } void nmDataAnalyzeManager::setAllCategoriesRootVisibility(bool bIsVisible) { for(int i = 0; i < m_vecDisplaySettings.size(); ++i) { m_vecDisplaySettings[i].value.isRootChecked = bIsVisible; } } void nmDataAnalyzeManager::setBackgroundImageInfo(const BackgroundImageInfo & info) { m_backgroundImageInfo = info; } const BackgroundImageInfo& nmDataAnalyzeManager::getBackgroundImageInfo() const { return m_backgroundImageInfo; } // 从 JSON 文件读取数据到 C++ 对象 bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath) { rapidjson::Document doc; // 调用 nmDataJsonTools 读取 JSON 文件到 Document if(!nmDataJsonTools::ReadDomFromFile(filePath, doc)) { qDebug() << "Error: Failed to read DOM from file:" << filePath; return false; } // 清空现有数据,确保从头加载新数据 foreach(nmDataFracture* pFractureData, m_vFractureData) { delete pFractureData; // 释放堆上分配的 nmDataFracture 对象 } m_vFractureData.clear(); foreach(nmDataFault* pFaultData, m_vFaultData) { delete pFaultData; // 释放堆上分配的 nmDataFault 对象 } m_vFaultData.clear(); foreach(nmDataRegion* pRegionData, m_vRegionData) { delete pRegionData; // 释放堆上分配的 nmDataRegion 对象 } m_vRegionData.clear(); foreach(nmDataRegionMark* pRegionMarkData, m_vRegionMarkData) { delete pRegionMarkData; // 释放堆上分配的 nmDataRegionMark 对象 } m_vRegionMarkData.clear(); foreach(nmDataLayer* pLayerData, m_vecLayers) { delete pLayerData; // 释放堆上分配的 nmDataLayer 对象 } m_vecLayers.clear(); if(m_reservoirData) { delete m_reservoirData; m_reservoirData = nullptr; } if(m_axisData) { delete m_axisData; m_axisData = nullptr; } if(m_outlineData) { delete m_outlineData; m_outlineData = nullptr; } if(m_pMixedResults) { delete m_pMixedResults; m_pMixedResults = nullptr; } if(m_pGeoRefData) { delete m_pGeoRefData; m_pGeoRefData = nullptr; } if(m_pTimeStep) { delete m_pTimeStep; m_pTimeStep = nullptr; } if(m_pSensitiveData) { delete m_pSensitiveData; m_pSensitiveData = nullptr; } //if(m_pPerCloData) { // delete m_pPerCloData; // m_pPerCloData = nullptr; //} if(m_pAutomaticFittingData) { delete m_pAutomaticFittingData; m_pAutomaticFittingData = nullptr; } //if(m_pebiPvtPara) { // delete m_pebiPvtPara; // m_pebiPvtPara = nullptr; //} foreach(nmDataWellBase* pWellData, m_vWellData) { delete pWellData; // 释放堆上分配的 nmDataWellBase 对象 } m_vWellData.clear(); // 解析 "Fractures" 数组 if(doc.HasMember("Fractures") && doc["Fractures"].IsArray()) { const rapidjson::Value& fracturesJson = doc["Fractures"]; for(rapidjson::SizeType i = 0; i < fracturesJson.Size(); ++i) { // 动态创建 nmDataFracture 对象,并获取其指针 nmDataFracture* fracture = new nmDataFracture(); fracture->FromJsonValue(fracturesJson[i]); // 调用 nmDataFracture 自身的反序列化方法 m_vFractureData.append(fracture); // 将指针添加到 QVector } } // 解析 "Faults" 数组 if(doc.HasMember("Faults") && doc["Faults"].IsArray()) { const rapidjson::Value& faultsJson = doc["Faults"]; for(rapidjson::SizeType i = 0; i < faultsJson.Size(); ++i) { // 动态创建 nmDataFault 对象,并获取其指针 nmDataFault* fault = new nmDataFault(); fault->FromJsonValue(faultsJson[i]); // 调用 nmDataFault 自身的反序列化方法 m_vFaultData.append(fault); // 将指针添加到 QVector } } // 解析 "Regions" 数组 if(doc.HasMember("Regions") && doc["Regions"].IsArray()) { const rapidjson::Value& regionsJson = doc["Regions"]; for(rapidjson::SizeType i = 0; i < regionsJson.Size(); ++i) { // 动态创建 nmDataRegion 对象,并获取其指针 nmDataRegion* region = new nmDataRegion(); // 传入this作为父对象 region->FromJsonValue(regionsJson[i]); // 调用 nmDataRegion 自身的反序列化方法 m_vRegionData.append(region); // 将指针添加到 QVector } } // 解析 "RegionMarks" 数组 if(doc.HasMember("RegionMarks") && doc["RegionMarks"].IsArray()) { const rapidjson::Value& regionMarksJson = doc["RegionMarks"]; for(rapidjson::SizeType i = 0; i < regionMarksJson.Size(); ++i) { // 动态创建 nmDataRegionMark 对象,并获取其指针 nmDataRegionMark* regionMark = new nmDataRegionMark(); // 传入this作为父对象 regionMark->FromJsonValue(regionMarksJson[i]); // 调用 nmDataRegion 自身的反序列化方法 m_vRegionMarkData.append(regionMark); // 将指针添加到 QVector } } // 解析 "Layers" 数组 if(doc.HasMember("Layers") && doc["Layers"].IsArray()) { const rapidjson::Value& layersJson = doc["Layers"]; for(rapidjson::SizeType i = 0; i < layersJson.Size(); ++i) { // 动态创建 nmDataRegion 对象,并获取其指针 nmDataLayer* layer = new nmDataLayer(); // 传入this作为父对象 layer->FromJsonValue(layersJson[i]); // 调用 nmDataLayer 自身的反序列化方法 m_vecLayers.append(layer); // 将指针添加到 QVector } } // 解析 "Reservoir" 对象 if(doc.HasMember("Reservoir") && doc["Reservoir"].IsObject()) { m_reservoirData = new nmDataReservoir; m_reservoirData->FromJsonValue(doc["Reservoir"]); } // 解析 "Axis" 对象 if(doc.HasMember("Axis") && doc["Axis"].IsObject()) { m_axisData = new nmDataAxis; m_axisData->FromJsonValue(doc["Axis"]); } // 解析 "Outline" 对象 if(doc.HasMember("Outline") && doc["Outline"].IsObject()) { m_outlineData = new nmDataOutline; m_outlineData->FromJsonValue(doc["Outline"]); } // 解析 "GeoRef" 对象 if(doc.HasMember("GeoReference") && doc["GeoReference"].IsObject()) { m_pGeoRefData = new nmDataGeoRef; m_pGeoRefData->FromJsonValue(doc["GeoReference"]); } // 解析 "AutomaticFitting" 对象 if(doc.HasMember("AutomaticFitting") && doc["AutomaticFitting"].IsObject()) { m_pAutomaticFittingData = new nmDataAutomaticFitting; m_pAutomaticFittingData->FromJsonValue(doc["AutomaticFitting"]); } // 解析 "Sensitive" 对象 if(doc.HasMember("Sensitive") && doc["Sensitive"].IsObject()) { m_pSensitiveData = new nmDataSensitive; m_pSensitiveData->FromJsonValue(doc["Sensitive"]); } // 解析 "PVT" 对象 //if(doc.HasMember("PVT") && doc["PVT"].IsObject()) { // m_pebiPvtPara = new nmDataPvtParaForPebi; // m_pebiPvtPara->FromJsonValue(doc["PVT"]); //} // 解析 "MixResult" 对象 if(doc.HasMember("MixResult") && doc["MixResult"].IsObject()) { m_pMixedResults = new nmDataMixedResults; m_pMixedResults->FromJsonValue(doc["MixResult"]); } // 解析 "Wells" 数组 if(doc.HasMember("Wells") && doc["Wells"].IsArray()) { const rapidjson::Value& wellsJson = doc["Wells"]; for(rapidjson::SizeType i = 0; i < wellsJson.Size(); ++i) { //// 动态创建 nmDataFault 对象,并获取其指针 //nmDataWellBase* well = new nmDataWellBase(); // 传入this作为父对象 //well->FromJsonValue(wellsJson[i]); // 调用 nmDataFault 自身的反序列化方法 //m_vWellData.append(well); // 将指针添加到 QVector // 获取当前井的JSON对象 const rapidjson::Value& wellItemJson = wellsJson[i]; // 临时指针,用于指向新创建的井对象 nmDataWellBase* pWell = nullptr; // 井类型 NM_WELL_MODEL eWellType = NM_WELL_MODEL::Unknow_Well; // 1. 读取 wellType if(wellItemJson.HasMember("WellType") && wellItemJson["WellType"].IsInt()) { eWellType = static_cast(wellItemJson["WellType"].GetInt()); } // 2. 根据 eWellType 动态创建不同的井类型实例 switch(eWellType) { case NM_WELL_MODEL::Vertical_Well: pWell = new nmDataVerticalWell; break; case NM_WELL_MODEL::Vertical_Fractured_Well: pWell = new nmDataVerticalFracturedWell; break; case NM_WELL_MODEL::Horizontal_Fractured_Well: pWell = new nmDataHorizontalFracturedWell; break; // TODO: 添加其他具体的井类型 default: break; } // 3. 调用具体井类型的 FromJsonValue 方法进行反序列化 if(pWell) { // 确保 well 对象已成功创建 pWell->FromJsonValue(wellItemJson); // 调用其自身的反序列化方法 m_vWellData.append(pWell); // 将指针添加到 QVector // TODO:将最后一口井设置为当前井(临时) //this->setCurWellData(pWell); } } } // 设置当前井 // 获取当前默认井数据 ZxDataWell* pWellData = zxCurWell; // 查找是否有当前井的数据 nmDataWellBase* pCurWell = nullptr; if(pWellData != nullptr) { pCurWell = this->findWellByName(pWellData->getName()); } if (pCurWell != nullptr) { this->setCurWellData(pCurWell); } else { // 设置第一口井为当前井 if (m_vWellData.size() > 0) { this->setCurWellData(m_vWellData[0]); } } // 解析 时间步 对象 if(doc.HasMember("TimeStep") && doc["TimeStep"].IsObject()) { m_pTimeStep = new nmDataTimeStepSetting; m_pTimeStep->FromJsonValue(doc["TimeStep"]); } return true; } // 将 C++ 对象数据写入 JSON 文件 bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath) { rapidjson::Document doc; doc.SetObject(); // 根节点是对象 rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); // 获取内存分配器 // 构建 "Fractures" 数组的 JSON Value rapidjson::Value fracturesJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataFracture 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataFracture* pFractureData, m_vFractureData) { if(pFractureData) { // 检查指针是否有效 fracturesJsonArray.PushBack(pFractureData->ToJsonValue(allocator), allocator); } } doc.AddMember("Fractures", fracturesJsonArray, allocator); // 构建 "Faults" 数组的 JSON Value rapidjson::Value faultsJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataFault 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataFault* pFaultData, m_vFaultData) { if(pFaultData) { // 检查指针是否有效 faultsJsonArray.PushBack(pFaultData->ToJsonValue(allocator), allocator); } } doc.AddMember("Faults", faultsJsonArray, allocator); // 构建 "Regions" 数组的 JSON Value rapidjson::Value regionsJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataRegion 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataRegion* pRegionData, m_vRegionData) { if(pRegionData) { // 检查指针是否有效 regionsJsonArray.PushBack(pRegionData->ToJsonValue(allocator), allocator); } } doc.AddMember("Regions", regionsJsonArray, allocator); // 构建 "RegionMarks" 数组的 JSON Value rapidjson::Value regionMarksJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataRegionMark 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataRegionMark* pRegionMarkData, m_vRegionMarkData) { if(pRegionMarkData) { // 检查指针是否有效 regionMarksJsonArray.PushBack(pRegionMarkData->ToJsonValue(allocator), allocator); } } doc.AddMember("RegionMarks", regionMarksJsonArray, allocator); // 构建 "Layers" 数组的 JSON Value rapidjson::Value layersJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataLayer 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataLayer* pLayerData, m_vecLayers) { if(pLayerData) { // 检查指针是否有效 layersJsonArray.PushBack(pLayerData->ToJsonValue(allocator), allocator); } } doc.AddMember("Layers", layersJsonArray, allocator); // 序列化 "Reservoir" if(m_reservoirData) { rapidjson::Value reservoirJson(rapidjson::kObjectType); reservoirJson = m_reservoirData->ToJsonValue(allocator); doc.AddMember("Reservoir", reservoirJson, allocator); } // 序列化 "Axis" if(m_axisData) { rapidjson::Value axisJson(rapidjson::kObjectType); axisJson = m_axisData->ToJsonValue(allocator); doc.AddMember("Axis", axisJson, allocator); } // 序列化 "Outline" if(m_outlineData) { rapidjson::Value outlineJson(rapidjson::kObjectType); outlineJson = m_outlineData->ToJsonValue(allocator); doc.AddMember("Outline", outlineJson, allocator); } // 序列化 "Reservoir" if(m_pGeoRefData) { rapidjson::Value geoRefJson(rapidjson::kObjectType); geoRefJson = m_pGeoRefData->ToJsonValue(allocator); doc.AddMember("GeoReference", geoRefJson, allocator); } //// 序列化 "PerforationClosing" //if(m_pPerCloData) { // rapidjson::Value perCloJson(rapidjson::kObjectType); // perCloJson = m_pPerCloData->ToJsonValue(allocator); // doc.AddMember("PerforationClosing", perCloJson, allocator); //} //// 序列化 "SkinVsRate" //if(m_pSkinVsRateData) { // rapidjson::Value skinJson(rapidjson::kObjectType); // skinJson = m_pSkinVsRateData->ToJsonValue(allocator); // doc.AddMember("SkinVsRate", skinJson, allocator); //} // 序列化 "AutomaticFitting" if(m_pAutomaticFittingData) { rapidjson::Value autofitJson(rapidjson::kObjectType); autofitJson = m_pAutomaticFittingData->ToJsonValue(allocator); doc.AddMember("AutomaticFitting", autofitJson, allocator); } // 序列化 "PVT" //if(m_pebiPvtPara) { // rapidjson::Value pvtJson(rapidjson::kObjectType); // pvtJson = m_pebiPvtPara->ToJsonValue(allocator); // doc.AddMember("PVT", pvtJson, allocator); //} // 序列化 "MixResult" if(m_pMixedResults) { rapidjson::Value mixResultsJson(rapidjson::kObjectType); mixResultsJson = m_pMixedResults->ToJsonValue(allocator); doc.AddMember("MixResult", mixResultsJson, allocator); } // 序列化 "Sensitive" if(m_pSensitiveData) { rapidjson::Value sensitiveJson(rapidjson::kObjectType); sensitiveJson = m_pSensitiveData->ToJsonValue(allocator); doc.AddMember("Sensitive", sensitiveJson, allocator); } // 构建 "Wells" 数组的 JSON Value rapidjson::Value wellsJsonArray(rapidjson::kArrayType); // 遍历存储 nmDataWellBase 指针的 QVector,并解引用指针来调用 ToJsonValue 方法 foreach(nmDataWellBase* pWellData, m_vWellData) { if(nmDataVerticalFracturedWell * pVerticalFracturedWell = dynamic_cast(pWellData)) { // 检查指针是否有效 wellsJsonArray.PushBack(pVerticalFracturedWell->ToJsonValue(allocator), allocator); } else if(nmDataHorizontalFracturedWell * pHorizontalFracturedWell = dynamic_cast(pWellData)) { // 检查指针是否有效 wellsJsonArray.PushBack(pHorizontalFracturedWell->ToJsonValue(allocator), allocator); } else if(nmDataHorizontalWell * pHorizontalWell = dynamic_cast(pWellData)) { // 检查指针是否有效 wellsJsonArray.PushBack(pHorizontalWell->ToJsonValue(allocator), allocator); } else if(nmDataVerticalWell * pVerticalWell = dynamic_cast(pWellData)) { // 检查指针是否有效 wellsJsonArray.PushBack(pVerticalWell->ToJsonValue(allocator), allocator); } } doc.AddMember("Wells", wellsJsonArray, allocator); // 序列化 时间步数据 if(m_pTimeStep) { rapidjson::Value timeStepJson(rapidjson::kObjectType); timeStepJson = m_pTimeStep->ToJsonValue(allocator); doc.AddMember("TimeStep", timeStepJson, allocator); } // 将最终构建好的 Document 写入文件 if(!nmDataJsonTools::WriteDomToFile(doc, filePath)) { qDebug() << "Error: Failed to write DOM to file:" << filePath; return false; } return true; } bool nmDataAnalyzeManager::saveNmResult(QString sRstCode, iSubWndFitting* pSubWndF) { Q_ASSERT(nullptr != pSubWndF); // 通过窗口层上下文获取保存目录 nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider(); Q_ASSERT(nullptr != pContextProvider); QString sDir; if(pContextProvider == nullptr || !pContextProvider->getSaveResultDir(pSubWndF, sRstCode, sDir)) { return false; } QString sResultPath = sDir + "/Results"; this->ensureDirectoryExists(sResultPath); // 将数据写入Json文件 this->WriteProjectData(sResultPath + "/Numerical_Parameters.json"); // --- 保存所有井的历史数据到独立目录 /WellHistory --- QString sWellHistoryDataPath = sDir + "/WellHistory"; this->ensureDirectoryExists(sWellHistoryDataPath); QVector vecAllWells = nmDataAnalyzeManager::getCurrentInstance()->getWellDataList(); // 获取所有井 // 遍历所有井,保存历史数据 for(int wellIdx = 0; wellIdx < vecAllWells.size(); ++wellIdx) { nmDataWellBase* pWellData = vecAllWells[wellIdx]; if(pWellData) { this->saveWellHistoryData(sWellHistoryDataPath, pWellData); } } // 保存非结构化网格数据 QString sGridPath = sDir + "/Grid"; if(!m_pVtkUnstructuredGrid) { // 如果没有网格对象,说明没有生成网格,直接返回 return true; } this->ensureDirectoryExists(sGridPath); // 将实时划分出来的网格写入文件 this->writeUnstructuredGridToFile(m_pVtkUnstructuredGrid, sGridPath + "/CurrentGrid.vtu"); // 保存结果里的基础网格 if(!m_pResultBaseGrid) { // 无基础网格对象,说明没有进行计算,返回 return true; } // 保存场图里的基础网格 this->writeUnstructuredGridToFile(m_pResultBaseGrid, sGridPath + "/ResultGrid.vtu"); // 保存场图中的井位置相关信息 this->saveWellLocations(sGridPath + "/ResultWellLocations.bin"); // --- 保存时间步压力数据 (m_mapTimeStepDataP) --- QString sTimeStepDataFilePath = sDir + "/TimeStepData/PressureTimeSteps.bin"; // 单个二进制文件路径 QString sTimeStepDataDirPath = sDir + "/TimeStepData"; // 确保目录存在 this->ensureDirectoryExists(sTimeStepDataDirPath); // 将时间步数据写入二进制文件中 if(!writeTimeStepDataMapToBinaryFile(sTimeStepDataFilePath)) { qDebug() << QString("Failed to save all time step data map to binary file: %1").arg(sTimeStepDataFilePath); return false; // 返回失败 } // 保存参与计算井的结果数据 QString sWellRstDataPath = sDir + "/WellRst"; this->ensureDirectoryExists(sWellRstDataPath); QVector> vecWells = nmDataAnalyzeManager::getCurrentInstance()->getCalculationWells(); // 遍历每口井,保存里面计算出来的数据 for(int wellIdx = 0; wellIdx < vecWells.size(); ++wellIdx) { NM_WELL_MODEL wellType = vecWells[wellIdx].first; // 获取井的类型 QString wellName = vecWells[wellIdx].second; // 获取井的名称 // 跳过裂缝(或未知井类型) if(wellType == NM_WELL_MODEL::Unknow_Well) { continue; } nmDataWellBase* pWellData = nmDataAnalyzeManager::getCurrentInstance()->findWellByName(wellName); if(pWellData) { this->saveWellCalRstData(sWellRstDataPath, pWellData); } } return true; } bool nmDataAnalyzeManager::loadNmResult(QString sLoadAnalDir) { // 将Json文件内容读取出来 QString sResultPath = sLoadAnalDir + "/Results/Numerical_Parameters.json"; this->ReadProjectData(sResultPath); // 读取当前网格文件 QString sCurrentGridPath = sLoadAnalDir + "/Grid/CurrentGrid.vtu"; this->readUnstructuredGridFromFile(m_pVtkUnstructuredGrid, sCurrentGridPath); // 读取结果基础网格文件 QString sResultGridPath = sLoadAnalDir + "/Grid/ResultGrid.vtu"; this->readUnstructuredGridFromFile(m_pResultBaseGrid, sResultGridPath); // 加载场图中的井位置相关信息 QString sResultWellLocationPath = sLoadAnalDir + "/Grid/ResultWellLocations.bin"; this->loadWellLocations(sResultWellLocationPath); // --- 加载时间步压力数据 (m_mapTimeStepDataP) --- QString sTimeStepDataFilePath = sLoadAnalDir + "/TimeStepData/PressureTimeSteps.bin"; // 读取时间步数据 if(!readTimeStepDataMapFromBinaryFile(sTimeStepDataFilePath)) { qDebug() << QString("Failed to load all time step data map from binary file: %1").arg(sTimeStepDataFilePath); } // --- 加载所有井的历史数据从独立目录 /WellHistory --- QString sWellHistoryDataPath = sLoadAnalDir + "/WellHistory"; this->ensureDirectoryExists(sWellHistoryDataPath); // 遍历所有井,尝试加载历史数据 for(int i = 0; i < m_vWellData.size(); i++) { this->loadWellHistoryData(sWellHistoryDataPath, m_vWellData[i]); } // 获取参与计算井的结果数据 QString sWellRstDataPath = sLoadAnalDir + "/WellRst"; this->ensureDirectoryExists(sWellRstDataPath); for(int i = 0; i < m_vWellData.size(); i++) { this->loadWellCalRstData(sWellRstDataPath, m_vWellData[i]); } // 读完后加载井的压力、流量数据 this->loadWellPreAndFlow(); if (m_pVtkUnstructuredGrid != nullptr) m_bIsLoadData = true; return true; } bool nmDataAnalyzeManager::ensureDirectoryExists(const QString & dirPath) { QDir dir(dirPath); if(!dir.exists()) { qDebug() << QString("Directory does not exist, attempting to create: %1").arg(dirPath); if(!dir.mkpath(dirPath)) { qDebug() << QString("Failed to create directory: %1").arg(dirPath); return false; } qDebug() << QString("Directory created successfully: %1").arg(dirPath); } else { qDebug() << QString("Directory already exists: %1").arg(dirPath); } return true; } void nmDataAnalyzeManager::loadWellPreAndFlow() { // 获取当前工区里所有的ZxDataWell井 if(zxCurProject == nullptr) { return; } ZxDataObjectList wellList = zxCurProject->getChildren(iDataModelType::sTypeWell); foreach(nmDataWellBase* pWell, m_vWellData) { if(pWell == nullptr) { continue; } QString sWellName = pWell->getWellName(); ZxDataWell* pWellData = nullptr; for(int i = 0; i < wellList.size(); i++) { ZxDataWell* pCandidateWell = dynamic_cast(wellList[i]); if(pCandidateWell != nullptr && pCandidateWell->getName() == sWellName) { pWellData = pCandidateWell; break; } } // 拿到了井的数据 if(pWellData) { // 获取当前井的压力、流量数据 ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP); ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF); ZxDataGaugeP* pGaugeP = nullptr; ZxDataGaugeF* pGaugeF = nullptr; // 遍历压力数据列表 for(int i = 0; i < m_listGaugeP.size(); ++i) { if(pGaugeP = dynamic_cast(m_listGaugeP[i])) { // 拿到第一条压力数据 break; } } // 遍历流量数据列表 for(int i = 0; i < m_listGaugeF.size(); ++i) { if(pGaugeF = dynamic_cast(m_listGaugeF[i])) { // 拿到第一条流量数据 break; } } // 获取的压力、流量数据 QVector vecPtsP, vecPtsF; // 临时存储x,y坐标 VecDouble vecX, vecY; if(pGaugeP != nullptr) { // 获取压力数据 if(pGaugeP->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsP.append(pt); } } } if(pGaugeF != nullptr) { vecX.clear(); vecY.clear(); // 获取流量数据 if(pGaugeF->getDataVecXY(vecX, vecY)) { int pointCount = vecX.size(); if(pointCount > vecY.size()) { pointCount = vecY.size(); } for(int i = 0; i < pointCount; ++i) { QPointF pt(vecX[i], vecY[i]); vecPtsF.append(pt); } } } // 设置井的压力数据、流量数据 pWell->setPressurePoints(vecPtsP); pWell->setFlowPoints(vecPtsF); } } } vtkSmartPointer nmDataAnalyzeManager::getUnstructuredGrid() const { return m_pVtkUnstructuredGrid; } void nmDataAnalyzeManager::setUnstructuredGrid(vtkSmartPointer grid) { m_pVtkUnstructuredGrid = grid; } vtkSmartPointer nmDataAnalyzeManager::getUnstructuredGridCopy() const { vtkSmartPointer pCopyGrid = vtkSmartPointer::New(); if(m_pVtkUnstructuredGrid) { // 执行深拷贝:复制网格的所有几何和拓扑信息 pCopyGrid->DeepCopy(m_pVtkUnstructuredGrid); } return pCopyGrid; } vtkSmartPointer nmDataAnalyzeManager::getResultBaseGrid() const { return m_pResultBaseGrid; } void nmDataAnalyzeManager::setResultBaseGrid(vtkSmartPointer grid) { m_pResultBaseGrid = grid; } vtkSmartPointer nmDataAnalyzeManager::getResultBaseGridCopy() const { vtkSmartPointer pCopyGrid = vtkSmartPointer::New(); if(m_pResultBaseGrid) { // 执行深拷贝:复制网格的所有几何和拓扑信息 pCopyGrid->DeepCopy(m_pResultBaseGrid); } return pCopyGrid; } bool nmDataAnalyzeManager::writeUnstructuredGridToFile(vtkSmartPointer grid, const QString& filePath) { // 检查是否存在有效的网格数据 if(!grid) { return false; } // 根据文件扩展名决定使用哪种格式 if(filePath.endsWith(".vtu", Qt::CaseInsensitive)) { // 使用XML格式(推荐格式) vtkNew writer; writer->SetInputData(grid); // 设置输入数据 writer->SetFileName(filePath.toStdString().c_str()); // 设置输出文件名 writer->SetDataModeToBinary(); // 设置为二进制模式,也可以用SetDataModeToAscii()设为文本模式 writer->Write(); // 执行写入操作 } else if(filePath.endsWith(".vtk", Qt::CaseInsensitive)) { // 使用传统的VTK格式 vtkNew writer; writer->SetInputData(grid); // 设置输入数据 writer->SetFileName(filePath.toStdString().c_str()); // 设置输出文件名 writer->SetFileTypeToBinary(); // 设置为二进制模式,也可以用SetFileTypeToASCII()设为文本模式 writer->Write(); // 执行写入操作 } else { return false; // 不支持的文件扩展名 } return true; // 写入成功 } bool nmDataAnalyzeManager::readUnstructuredGridFromFile(vtkSmartPointer& grid, const QString& filePath) { // 检查文件是否存在 if(!QFile::exists(filePath)) { return false; } // 根据文件扩展名选择不同的读取器 if(filePath.endsWith(".vtu", Qt::CaseInsensitive)) { // 使用XML格式读取器 vtkNew reader; reader->SetFileName(filePath.toStdString().c_str()); // 设置输入文件名 reader->Update(); // 执行读取操作 grid = reader->GetOutput(); // 获取读取的数据 } else if(filePath.endsWith(".vtk", Qt::CaseInsensitive)) { // 使用传统VTK格式读取器 vtkNew reader; reader->SetFileName(filePath.toStdString().c_str()); // 设置输入文件名 reader->Update(); // 执行读取操作 grid = reader->GetOutput(); // 获取读取的数据 } else { return false; // 不支持的文件扩展名 } // 检查是否成功读取了有效的网格数据 if(grid && grid->GetNumberOfPoints() > 0) { return true; } return false; // 读取失败 } void nmDataAnalyzeManager::addTimeStep(double time, vtkSmartPointer data) { if(!data || data->GetNumberOfTuples() == 0) return; m_mapTimeStepDataP.insert(time, data); } vtkSmartPointer nmDataAnalyzeManager::getTimeStepData(double time) const { if(m_mapTimeStepDataP.contains(time)) { return m_mapTimeStepDataP.value(time); } return nullptr; } QList nmDataAnalyzeManager::getTimeStepKeys() { return m_mapTimeStepDataP.keys(); } bool nmDataAnalyzeManager::isTimeStepDataEmpty() { return m_mapTimeStepDataP.isEmpty(); } /** * @brief 辅助函数:将整个时间步数据QMap保存到单个二进制文件。 * 文件中依次存储:QMap大小、每个时间键、每个vtkDoubleArray的大小、每个vtkDoubleArray的数据。 * @param filePath 文件保存的完整路径。 * @return 写入成功返回true,否则返回false。 */ bool nmDataAnalyzeManager::writeTimeStepDataMapToBinaryFile(const QString& filePath) { QFile file(filePath); // 使用 Truncate 模式确保如果文件已存在,会被清空并覆盖 if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { qDebug() << QString("Failed to open file for writing (TimeStepDataMap): %1").arg(filePath); return false; } QDataStream out(&file); out.setVersion(QDataStream::Qt_4_8); // 当前项目Qt版本 // 1. 写入 QMap 的元素数量 out << (qint32)m_mapTimeStepDataP.size(); // 2. 遍历 QMap,依次写入每个时间键和对应的 vtkDoubleArray 数据 for(auto it = m_mapTimeStepDataP.constBegin(); it != m_mapTimeStepDataP.constEnd(); ++it) { double time = it.key(); vtkSmartPointer data = it.value(); // 写入时间键 out << time; // 写入 vtkDoubleArray 的元素数量 qint64 numberOfTuples = data ? data->GetNumberOfTuples() : 0; out << numberOfTuples; // 写入 vtkDoubleArray 的数据 if(data && numberOfTuples > 0) { for(qint64 i = 0; i < numberOfTuples; ++i) { out << data->GetValue(i); } } } file.close(); return true; } /** * @brief 辅助函数:从单个二进制文件加载整个时间步数据QMap。 * @param filePath 文件所在的完整路径。 * @return 加载成功返回true,否则返回false。 */ bool nmDataAnalyzeManager::readTimeStepDataMapFromBinaryFile(const QString& filePath) { m_mapTimeStepDataP.clear(); // 清空现有数据,准备加载新数据 m_dScalarRangeP[0] = DBL_MAX; // 初始化最小值为最大浮点数 m_dScalarRangeP[1] = -DBL_MAX; // 初始化最大值为最小浮点数 QFile file(filePath); if(!file.open(QIODevice::ReadOnly)) { qDebug() << QString("Failed to open file for reading (TimeStepDataMap): %1").arg(filePath); return false; } QDataStream in(&file); in.setVersion(QDataStream::Qt_4_8); // 必须与写入时的版本一致 // 1. 读取 QMap 的元素数量 qint32 mapSize; in >> mapSize; if(mapSize < 0) { // 简单校验 qDebug() << QString("Invalid map size read from binary file: %1").arg(filePath); file.close(); return false; } // 2. 循环读取每个时间键和对应的 vtkDoubleArray 数据 for(qint32 k = 0; k < mapSize; ++k) { double time; in >> time; // 读取时间键 qint64 numberOfTuples; in >> numberOfTuples; // 读取 vtkDoubleArray 的元素数量 vtkSmartPointer data = vtkSmartPointer::New(); data->SetNumberOfComponents(1); // 假设是单分量数组 data->SetNumberOfTuples(numberOfTuples); // 设置数组大小 // 设置数组名称 data->SetName("p"); if(numberOfTuples > 0) { double currentMin = DBL_MAX; double currentMax = -DBL_MAX; for(qint64 i = 0; i < numberOfTuples; ++i) { double value; in >> value; data->SetValue(i, value); // 更新当前时间步的范围 currentMin = qMin(currentMin, value); currentMax = qMax(currentMax, value); } // 更新全局范围 m_dScalarRangeP[0] = qMin(m_dScalarRangeP[0], currentMin); m_dScalarRangeP[1] = qMax(m_dScalarRangeP[1], currentMax); } m_mapTimeStepDataP.insert(time, data); } file.close(); return true; } bool nmDataAnalyzeManager::saveWellHistoryData(QString sDir, nmDataWellBase* pWellData) { Q_ASSERT(nullptr != pWellData); if(nullptr == pWellData) { return false; } // 构建文件路径,文件名为:[WellName]_History.bin QString wellName = pWellData->getWellName(); if(wellName.isEmpty()) { return false; } QString filePath = sDir + "/" + wellName + "_History.bin"; QFile file(filePath); if(!file.open(QIODevice::WriteOnly)) { return false; } QDataStream out(&file); out.setVersion(QDataStream::Qt_4_8); // 只写入历史数据 out << pWellData->getHistoryPressure(); out << pWellData->getHistoryLogLog(); out << pWellData->getHistorySemiLog(); file.close(); return true; } bool nmDataAnalyzeManager::loadWellHistoryData(QString sDir, nmDataWellBase* pWellData) { Q_ASSERT(nullptr != pWellData); if(nullptr == pWellData) { return false; } QString sWellName = pWellData->getWellName(); if(sWellName.isEmpty()) { return false; } // 文件名为:[WellName]_History.bin QString filePath = sDir + "/" + sWellName + "_History.bin"; QFile file(filePath); if(!file.open(QIODevice::ReadOnly)) { return false; } QDataStream in(&file); in.setVersion(QDataStream::Qt_4_8); // 只需要读取历史数据 QVector> historyPressureData; QVector> historyLoglogData; QVector> historySemiLogData; // 只读取历史数据 in >> historyPressureData; in >> historyLoglogData; in >> historySemiLogData; pWellData->setHistoryPressure(historyPressureData); pWellData->setHistoryLogLog(historyLoglogData); pWellData->setHistorySemiLog(historySemiLogData); file.close(); return true; } bool nmDataAnalyzeManager::saveWellCalRstData(QString sDir, nmDataWellBase* pWellData) { Q_ASSERT(nullptr != pWellData); if(nullptr == pWellData) { return false; } // 构建文件路径,为每口井的结果创建一个独立文件 QString wellName = pWellData->getWellName(); if(wellName.isEmpty()) { return false; } QString filePath = sDir + "/" + wellName + "_Results.bin"; // QFile file(filePath); if(!file.open(QIODevice::WriteOnly)) { return false; } QDataStream out(&file); out.setVersion(QDataStream::Qt_4_8); // 设置数据流版本,保证未来兼容性 // 写入数据 // QDataStream 可以直接序列化 QVector> out << pWellData->getResultPressure(); out << pWellData->getResultLogLog(); out << pWellData->getResultSemiLog(); file.close(); return true; } bool nmDataAnalyzeManager::loadWellCalRstData(QString sDir, nmDataWellBase* pWellData) { Q_ASSERT(nullptr != pWellData); if(nullptr == pWellData) { return false; } QString sWellName = pWellData->getWellName(); if(sWellName.isEmpty()) { return false; } QString filePath = sDir + "/" + sWellName + "_Results.bin"; QFile file(filePath); if(!file.open(QIODevice::ReadOnly)) { return false; } QDataStream in(&file); in.setVersion(QDataStream::Qt_4_8); // 确保与写入时版本一致 // 读取数据到 pWellData 的成员变量 QVector> pressureData; QVector> loglogData; QVector> semiLogData; in >> pressureData; in >> loglogData; in >> semiLogData; pWellData->setResultPressure(pressureData); pWellData->setResultLogLog(loglogData); pWellData->setResultSemiLog(semiLogData); //// 存储当前井名称和二维位置到映射 //QPointF ptWellCoords(pWellData->getX().getValue().toDouble(), pWellData->getY().getValue().toDouble()); //addWellLocation(sWellName, ptWellCoords); // 将当前井添加到参与计算井列表中 this->appendCalculationWell(QPair(pWellData->getWellType(), pWellData->getWellName())); file.close(); return true; } void nmDataAnalyzeManager::getScalarRangeP(double range[2]) const { range[0] = m_dScalarRangeP[0]; range[1] = m_dScalarRangeP[1]; } void nmDataAnalyzeManager::setScalarRangeP(double min, double max) { m_dScalarRangeP[0] = min; m_dScalarRangeP[1] = max; } void nmDataAnalyzeManager::addWellLocation(const QString& wellName, const QPointF& location) { m_mapWellLocations.insert(wellName, location); } QPointF nmDataAnalyzeManager::getWellLocation(const QString& wellName) const { return m_mapWellLocations.value(wellName, QPointF()); // 如果未找到,返回默认的QPointF(0,0) } bool nmDataAnalyzeManager::removeWellLocation(const QString& wellName) { return m_mapWellLocations.remove(wellName) > 0; } void nmDataAnalyzeManager::clearWellLocations() { m_mapWellLocations.clear(); } QMap nmDataAnalyzeManager::getAllWellLocations() const { return m_mapWellLocations; } bool nmDataAnalyzeManager::saveWellLocations(const QString& filePath) { QFile file(filePath); if(!file.open(QIODevice::WriteOnly)) { return false; } QDataStream out(&file); out.setVersion(QDataStream::Qt_4_8); qDebug() << "Map size before writting:" << m_mapWellLocations.size(); out << m_mapWellLocations; file.close(); return true; } bool nmDataAnalyzeManager::loadWellLocations(const QString& filePath) { QFile file(filePath); if(!file.open(QIODevice::ReadOnly)) { return false; } QDataStream in(&file); in.setVersion(QDataStream::Qt_4_8); in >> m_mapWellLocations; qDebug() << "Map size after reading:" << m_mapWellLocations.size(); file.close(); return true; } //void nmDataAnalyzeManager::createTimeStep() //{ // if (m_pTimeStep != nullptr) // { // delete m_pTimeStep; // m_pTimeStep = nullptr; // } // // // 获取当前井下流量的时间范围 // QVector vecFlowPoints; // if (m_pCurDataWell){ // vecFlowPoints = m_pCurDataWell->getFlowPoints(); // } // // // 计算起始时间和终止时间 // // 检查坐标数组是否为空,以防止访问越界 // if (!vecFlowPoints.isEmpty()) { // // 起始时间就是第一个点的横坐标 // double dStartTime = vecFlowPoints.first().x(); // // // 终止时间是所有点的横坐标之和 // double dEndTime = 0.0; // foreach (const QPointF& point, vecFlowPoints) { // dEndTime += point.x(); // } // // m_pTimeStep = new nmDataTimeStepSetting(dStartTime,dEndTime); // } //} nmDataTimeStepSetting* nmDataAnalyzeManager::createTimeStep() { if (m_pTimeStep != nullptr) { delete m_pTimeStep; m_pTimeStep = nullptr; } m_pTimeStep = new nmDataTimeStepSetting; return m_pTimeStep; } nmDataTimeStepSetting* nmDataAnalyzeManager::getTimeStep() { return m_pTimeStep; } // 获取许可证路径 void nmDataAnalyzeManager::setLicensePath(const QString& licensePath) { m_licensePath = licensePath; } QString nmDataAnalyzeManager::getLicensePath() const { return m_licensePath; }