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("");
// 设置边界点