diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 6551396..bdc7725 100644 Binary files a/Bin/Config/Lang/cn/nmNum_cn.qm and b/Bin/Config/Lang/cn/nmNum_cn.qm differ 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(""); // 设置边界点