From 4deee622079a170359921b88178ae6773f2874c1 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Tue, 21 Jul 2026 14:20:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(nmNum):=20=E4=BF=AE=E5=A4=8D=E6=95=B0?= =?UTF-8?q?=E5=80=BC=E9=9D=A2=E6=9D=BF=E5=88=9D=E5=A7=8B=E5=8C=96=E5=92=8C?= =?UTF-8?q?=E5=A4=9A=E6=AE=B5=E5=8E=8B=E8=A3=82=E6=B0=B4=E5=B9=B3=E4=BA=95?= =?UTF-8?q?=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 补充数值面板初始化失败提示和空数据保护 - 统一使用 HorizontalMultiFracturedWell 井型 - 防止求解结果为空时发生越界 - 优化 Release 下左侧面板高度分配 - 同步中文翻译 --- Bin/Config/Lang/cn/nmNum_cn.qm | Bin 101181 -> 103081 bytes Bin/Config/Lang/cn/nmNum_cn.ts | 56 ++++++++++++++++ Src/nmNum/nmData/nmDataAnalyzeManager.cpp | 21 ++++-- Src/nmNum/nmPlot/nmGuiPlot.cpp | 2 +- Src/nmNum/nmPlot/nmObjPointWell.cpp | 8 +-- Src/nmNum/nmSubWnd/nmSubWndUtils.cpp | 74 +++++++++++++++------- 6 files changed, 128 insertions(+), 33 deletions(-) diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 6551396a5bcdbec002149a2073bf59d538e9e79c..bdc77257ab79843b77a2408f204d5cb53efec515 100644 GIT binary patch delta 11634 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 delta 10031 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 axoTJOvsc8f*9A@@b^AGa*P$z~kNh7>8Fi@u diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index 0c7177c..5879529 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -16,6 +16,18 @@ '%1' + + Numerical Panel Initialization Failed + 数值面板初始化失败 + + + The numerical panels could not be opened. + +Reason: %1 + 无法打开数值面板。 + +原因:%1 + iWxBase @@ -2841,6 +2853,50 @@ Supported types: Vertical, Vertical Fractured, and Horizontal Multi-Fractured Wells. 当前井类型“%1”暂不支持进行数值模拟。 支持的类型包括:直井、压裂直井以及多段压裂水平井。 + + The current window is not a flow-segment analysis window. + 当前窗口不是流动段分析窗口。 + + + The numerical panel containers have not been created. + 数值面板容器尚未创建。 + + + No current well is available. Please select a well and try again. + 未获取到当前井,请选择一口井后重试。 + + + The current well type '%1' is not supported. Supported types are Vertical, Vertical Fractured, and Horizontal Multi-Fractured Wells. + 当前井类型“%1”不受支持。支持的类型包括:直井、压裂直井和多段压裂水平井。 + + + The numerical data manager could not be created. + 无法创建数值数据管理器。 + + + The numerical well data could not be initialized for well '%1' (type: %2). Please check the well type and its pressure, flow-rate, and flow-segment data. + 无法初始化井“%1”(类型:%2)的数值井数据。请检查井类型以及压力、流量和流动段数据。 + + + The analytical rectangular-boundary data is incomplete. Missing parameters: %1. + 解析解的矩形边界数据不完整,缺少参数:%1。 + + + The rectangular-boundary data could not be created. + 无法创建矩形边界数据。 + + + The circular-boundary data could not be created. + 无法创建圆形边界数据。 + + + The default numerical boundary could not be created. + 无法创建默认数值边界。 + + + The numerical panel widgets could not be attached to their containers. + 无法将数值面板控件挂载到面板容器。 + nmSwitchOutlineConfirmationDlg diff --git a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp index e0d94de..114ff93 100644 --- a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp +++ b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp @@ -960,7 +960,7 @@ void nmDataAnalyzeManager::initCurWellData() // 设置为当前查看的井 this->setCurWellData(pVFracturedWell); - } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) { + } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell")) { // 初始化多段压裂水平井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well); @@ -1041,8 +1041,12 @@ void nmDataAnalyzeManager::calculationLogData( vvecHistoryData[1].append(qpoint.y()); // y } - // 准备流量段数据 + // Prepare flow-rate segment data. QVector vecTimeQ = pWellData->getFlowPoints(); + if(vecPressure.isEmpty() || vecTimeQ.size() < 2) { + return; + } + int nTimeNumQ = vecTimeQ.size() - 1; std::vector timeQ(nTimeNumQ); std::vector q(nTimeNumQ); @@ -1068,10 +1072,15 @@ void nmDataAnalyzeManager::calculationLogData( return; } - preLogFun(wellPressureData, iSectionFlowIndex, timeQ.data(), q.data(), nTimeNumQ, logPre); + bool bCalculated = preLogFun(wellPressureData, iSectionFlowIndex, + timeQ.data(), q.data(), nTimeNumQ, logPre); + if(!bCalculated || logPre.empty()) { + FreeLibrary(hMod_solver); + return; + } - // 不添加最后一个元素 - for(uint i = 0; i < logPre.size() - 1; i++) { + // The solver's final point is not part of the plotted result. + for(std::vector::size_type i = 0; i + 1 < logPre.size(); ++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 @@ -1213,7 +1222,7 @@ void nmDataAnalyzeManager::appendWellData(ZxDataWell* pWellData) pVFracturedWell->setFracs(); // 设置流量段索引 pVFracturedWell->setIndexF(nIndexF); - } else if(ZxBaseUtil::isSameStr(sWellClass, "HorizontalFracturedWell")) { + } else if(ZxBaseUtil::isSameStr(sWellClass, "HorizontalMultiFracturedWell")) { // 初始化多段压裂水平井默认参数 nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well); diff --git a/Src/nmNum/nmPlot/nmGuiPlot.cpp b/Src/nmNum/nmPlot/nmGuiPlot.cpp index 6693c6c..76e9bd7 100644 --- a/Src/nmNum/nmPlot/nmGuiPlot.cpp +++ b/Src/nmNum/nmPlot/nmGuiPlot.cpp @@ -369,7 +369,7 @@ void nmGuiPlot::initDefultGeoObj() // 设置为当前查看的井 nmDataAnalyzeManager::getCurrentInstance()->setCurWellData(m_VFracturedWell); - } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) { + } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell")) { // 初始化多段压裂水平井默认参数 nmDataWellBase* pWell = nmDataAnalyzeManager::getCurrentInstance()->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well); diff --git a/Src/nmNum/nmPlot/nmObjPointWell.cpp b/Src/nmNum/nmPlot/nmObjPointWell.cpp index ff31794..e2243f4 100644 --- a/Src/nmNum/nmPlot/nmObjPointWell.cpp +++ b/Src/nmNum/nmPlot/nmObjPointWell.cpp @@ -324,7 +324,7 @@ void nmObjPointWell::afterCreated() } else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) { // 切换当前井类型 m_enumWellType = NM_WELL_MODEL::Vertical_Fractured_Well; - } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) { + } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell")) { // 切换当前井类型 m_enumWellType = NM_WELL_MODEL::Horizontal_Fractured_Well; } else { @@ -485,7 +485,7 @@ void nmObjPointWell::editWell() } else if(m_enumWellType == NM_WELL_MODEL::Vertical_Fractured_Well) { sWellClass = "VerticalFracturedWell"; } else if(m_enumWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) { - sWellClass = "HorizontalFracturedWell"; + sWellClass = "HorizontalMultiFracturedWell"; } m_pWellData->setWellClassCn(sWellClass); } @@ -627,7 +627,7 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param) painter->restore(); - } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell") && m_pNmWellData != nullptr) { + } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell") && m_pNmWellData != nullptr) { Q_ASSERT(NULL != m_pAxisX); Q_ASSERT(NULL != m_pAxisY); @@ -763,7 +763,7 @@ void nmObjPointWell::setNmWellData(nmDataWellBase* wellData) m_enumWellType = NM_WELL_MODEL::Vertical_Well; } else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) { m_enumWellType = NM_WELL_MODEL::Vertical_Fractured_Well; - } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) { + } else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell")) { m_enumWellType = NM_WELL_MODEL::Horizontal_Fractured_Well; } } diff --git a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp index d8a487b..11e3057 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp @@ -1,4 +1,4 @@ -#include "zxLogInstance.h" +#include "zxLogInstance.h" #include "iRibbonXmlCmd.h" #include #include @@ -71,6 +71,15 @@ bool hasPvtCurve(iSubWndFitting* pSubWndF, PvtFluidType eType, const QStringList return false; } +bool showNmDockInitializationError(const QString& detail) +{ + QMessageBox::warning(nullptr, + QObject::tr("Numerical Panel Initialization Failed"), + QObject::tr("The numerical panels could not be opened.\n\nReason: %1") + .arg(detail)); + return false; +} + } nmSubWndUtils* nmSubWndUtils::getInstance() @@ -347,10 +356,11 @@ bool nmSubWndUtils::dealwithRibbonTab(iRibbonXmlTab* pTab, \ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) { iSubWndFitting* pSubWndF = dynamic_cast(pSubWnd); - Q_ASSERT(nullptr != pSubWndF); if(pSubWndF == nullptr) { - return false; + return showNmDockInitializationError( + tr("The current window is not a flow-segment analysis window.")); } + Q_ASSERT(nullptr != pSubWndF); // 如果当前分析没有对应相态的PVT相关参数,提示并返回 //PvtFluidType eType = pSubWndF->getBasicPft(); @@ -383,8 +393,12 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) iDockBaseWx* pWxDockNm1 = pSubWndF->getNmDockWx(0); iDockBaseWx* pWxDockNm2 = pSubWndF->getNmDockWx(1); - Q_ASSERT (nullptr != pWxDockNm1); - Q_ASSERT (nullptr != pWxDockNm2); + if(pWxDockNm1 == nullptr || pWxDockNm2 == nullptr) { + return showNmDockInitializationError( + tr("The numerical panel containers have not been created.")); + } + Q_ASSERT(nullptr != pWxDockNm1); + Q_ASSERT(nullptr != pWxDockNm2); if (pWxDockNm1->widget() != nullptr && pWxDockNm2->widget() != nullptr) { return true; //已经设定的话,则不再处理 @@ -393,7 +407,8 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) // 获取当前井并检查类型是否支持 ZxDataWell* pWellData = zxCurWell; if(pWellData == nullptr) { - return false; + return showNmDockInitializationError( + tr("No current well is available. Please select a well and try again.")); } QString wellClass = pWellData->getWellClassEn(); @@ -403,21 +418,21 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) supportedTypes << "VerticalWell" << "VerticalFracturedWell" << "HorizontalMultiFracturedWell"; if (!supportedTypes.contains(wellClass)) { - QMessageBox::warning(nullptr, tr("Unsupported Well Type"), - tr("The current well type '%1' is not supported for numerical modeling.\n" - "Supported types: Vertical, Vertical Fractured, and Horizontal Multi-Fractured Wells.") - .arg(pWellData->getWellClassCn())); - return false; + return showNmDockInitializationError( + tr("The current well type '%1' is not supported. Supported types are Vertical, " + "Vertical Fractured, and Horizontal Multi-Fractured Wells.") + .arg(pWellData->getWellClassCn())); } // 进入到这里,说明是新打开的流动段分析,所以需要动态创建数据管理中心 // 根据分析窗口创建唯一的数据管理对象 nmDataAnalyzeManager* pDataManager = nmDataAnalyzeManager::getInstanceByFitting(pSubWndF); - Q_ASSERT(nullptr != pDataManager); if(pDataManager == nullptr) { - return false; + return showNmDockInitializationError( + tr("The numerical data manager could not be created.")); } + Q_ASSERT(nullptr != pDataManager); // 每个成果窗口只需要绑定一次外层MDI激活信号。 // 后续切换成果窗口时,通过激活事件同步对应的数据中心和左侧面板。 @@ -445,10 +460,14 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) pDataManager->initCurWellData(); // 1.4 初始化边界数据 nmDataWellBase* pCurWell = pDataManager->getCurWellData(); - Q_ASSERT(nullptr != pCurWell); if(pCurWell == nullptr) { - return false; + return showNmDockInitializationError( + tr("The numerical well data could not be initialized for well '%1' (type: %2). " + "Please check the well type and its pressure, flow-rate, and flow-segment data.") + .arg(pWellData->getName()) + .arg(wellClass)); } + Q_ASSERT(nullptr != pCurWell); double dX = pCurWell->getX().getValue().toDouble(); double dY = pCurWell->getY().getValue().toDouble(); @@ -457,7 +476,6 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) QMap mapAnaParas; mapAnaParas.clear(); pSubWndF->getBrotherDockParas(mapAnaParas, false); - Q_ASSERT(mapAnaParas.count() > 0); // 解析解边界类型 m_Bdy_Type oBdyType = BT_None; @@ -480,15 +498,24 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) vecBdyDiss.clear(); QStringList list; list << "ne" << "se" << "we" << "ee"; + QStringList missingKeys; for(int i = 0; i < list.count(); i++) { QString s = list[i]; if(mapAnaParas.contains(s)) { vecBdyDiss << mapAnaParas[s].toDouble(); + } else { + missingKeys << s; } } + if(!missingKeys.isEmpty()) { + return showNmDockInitializationError( + tr("The analytical rectangular-boundary data is incomplete. Missing parameters: %1.") + .arg(missingKeys.join(", "))); + } + double top_dist = vecBdyDiss[0]; double right_dist = vecBdyDiss[1]; double bottom_dist = vecBdyDiss[2]; @@ -503,10 +530,11 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) vecBoundaryPoints << topLeft << topRight << bottomRight << bottomLeft; // 创建矩形边界数据对象 nmDataOutline* pOutlineData = pDataManager->createOutline(); - Q_ASSERT(pOutlineData); if(pOutlineData == nullptr) { - return false; + return showNmDockInitializationError( + tr("The rectangular-boundary data could not be created.")); } + Q_ASSERT(pOutlineData); // 设置默认边界名称 pOutlineData->setName(""); // 设置边界点 @@ -527,10 +555,11 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) // 创建圆形边界数据对象 nmDataOutline* pOutlineData = pDataManager->createOutline(); - Q_ASSERT(pOutlineData); if(pOutlineData == nullptr) { - return false; + return showNmDockInitializationError( + tr("The circular-boundary data could not be created.")); } + Q_ASSERT(pOutlineData); // 设置默认边界名称 pOutlineData->setName(""); // 设置半径 @@ -560,10 +589,11 @@ bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) // 如果解析解这里没有设置边界,数值解设置默认边界 // 创建默认矩形边界数据对象 nmDataOutline* pDefaultOutlineData = pDataManager->createOutline(); - Q_ASSERT(pDefaultOutlineData); if(pDefaultOutlineData == nullptr) { - return false; + return showNmDockInitializationError( + tr("The default numerical boundary could not be created.")); } + Q_ASSERT(pDefaultOutlineData); // 设置默认边界名称 pDefaultOutlineData->setName(""); // 设置边界点