Compare commits

...

2 Commits

Author SHA1 Message Date
lvjunjie ee3bf4f692 fix(nmNum): 误差计算跳过负导数和零导数数据,调整结果生成阶段按钮内容,同步更新中文翻译。 3 weeks ago
lvjunjie 1968c790bc fix(nmNum): 统一自动拟合目标曲线读取来源
油、气、水井统一读取所选目标井的历史双对数曲线,移除气井从主界面读取曲线的逻辑及结果井一致性提示。
3 weeks ago

Binary file not shown.

@ -4171,7 +4171,7 @@ Supported types: Vertical, Vertical Fractured, and Horizontal Multi-Fractured We
</message>
<message>
<source>Finalizing...</source>
<translation>正在生成最终结果...</translation>
<translation>生成结果中</translation>
</message>
<message>
<source>Generating the final result with the current best parameters...</source>

@ -3086,8 +3086,7 @@ double nmCalculationAutoFitLM::calculateLogLogCurveError(
}
try {
// 无法比较的采样行先跳过;有限但非正的导数无法进入双对数空间,
// 当前数据又没有逐点有效掩码,因此遇到这种导数时判本次评价无效。
// 非正导数无法进入双对数空间,跳过对应采样行,使用剩余有效点比较。
auto prepareCurve = [valueFloor](const QVector<QVector<double> >& data,
int firstIndex,
QVector<QPointF>* pressure,
@ -3104,12 +3103,10 @@ double nmCalculationAutoFitLM::calculateLogLogCurveError(
!isFiniteNumber(data[1][i]) ||
!isFiniteNumber(data[2][i]) ||
data[0][i] <= 0.0 ||
data[1][i] <= 0.0) {
data[1][i] <= 0.0 ||
data[2][i] <= 0.0) {
continue;
}
if(data[2][i] <= 0.0) {
return false;
}
pressure->append(QPointF(data[0][i], data[1][i]));
derivative->append(

@ -10,8 +10,6 @@
#include "iParameter.h"
#include "mModuleDefines.h"
#include "mGui/mGuiAnal/iAnalRun.h"
#include "iGuiPlot.h"
#include "ZxObjCurve.h"
#include "mAlgDefines.h"
#pragma comment(lib, "mGuiAnal.lib")
@ -66,85 +64,6 @@ bool nmAutoFitReadPhysicalRange(const char* parameterName,
return true;
}
// 主界面气井双对数中的源曲线和导数曲线已经采用拟压力量纲.
// 自动拟合直接读取这两条显示曲线, 避免井对象中的原始压力历史数据与结果曲线量纲不一致.
// 两条曲线可能因无效点过滤而长度不同, 因此按时间坐标匹配共同有效点.
bool getMainHistoryLogLog(iSubWndFitting* fitting,
QVector<QVector<double> >& data,
QString& errorMessage)
{
data.clear();
if(!fitting) {
errorMessage = QObject::tr("The current fitting window is unavailable.");
return false;
}
QWidget* widget = fitting->getFitSubRstWxOf(FSRT_DoubleLog, false, &errorMessage);
iGuiPlot* plot = qobject_cast<iGuiPlot*>(widget);
if(!plot) {
errorMessage = QObject::tr("The main double-log plot is unavailable.");
return false;
}
ZxObjCurve* sourceCurve = plot->getCurve(s_Souce_Curve);
ZxObjCurve* derivativeCurve = plot->getCurve(s_Deriv_Curve);
if(!sourceCurve || !derivativeCurve) {
errorMessage = QObject::tr("The main double-log history curves are unavailable.");
return false;
}
QVector<QPointF> sourcePoints = sourceCurve->getAllValues();
QVector<QPointF> derivativePoints = derivativeCurve->getAllValues();
data.resize(3);
int sourceIndex = 0;
int derivativeIndex = 0;
while(sourceIndex < sourcePoints.size()
&& derivativeIndex < derivativePoints.size()) {
const QPointF sourcePoint = sourcePoints[sourceIndex];
const QPointF derivativePoint = derivativePoints[derivativeIndex];
const double sourceTime = sourcePoint.x();
const double derivativeTime = derivativePoint.x();
if(!nmAutoFitUiIsFinite(sourceTime) || sourceTime <= 0.0) {
++sourceIndex;
continue;
}
if(!nmAutoFitUiIsFinite(derivativeTime) || derivativeTime <= 0.0) {
++derivativeIndex;
continue;
}
const double timeTolerance = qMax(1.0,
qMax(qAbs(sourceTime), qAbs(derivativeTime))) * 1e-8;
if(qAbs(sourceTime - derivativeTime) <= timeTolerance) {
const double source = sourcePoint.y();
const double derivative = derivativePoint.y();
if(nmAutoFitUiIsFinite(source)
&& nmAutoFitUiIsFinite(derivative)
&& source > 0.0 && derivative > 0.0) {
data[0].append(sourceTime);
data[1].append(source);
data[2].append(derivative);
}
++sourceIndex;
++derivativeIndex;
} else if(sourceTime < derivativeTime) {
++sourceIndex;
} else {
++derivativeIndex;
}
}
if(data[0].size() < 5) {
data.clear();
errorMessage = QObject::tr("The main double-log history curves have too few valid points.");
return false;
}
return true;
}
}
// 设置某一行参数是否显示。隐藏时同步取消勾选并禁用,避免隐藏参数参与自动拟合。
@ -1033,21 +952,11 @@ void nmWxAutomaticFitting::onAccept()
return;
}
QVector<QVector<double> > targetLogLogData;
const bool usePseudoPressure = (pManager->getSolverModelType() == SMT_Gas_VariablePvt);
if(usePseudoPressure) {
// 目标曲线来自当前主界面, 必须确认界面显示的井就是用户选择的拟合井.
nmDataWellBase* pCurrentWell = pManager->getCurWellData();
if(!pCurrentWell || pCurrentWell->getWellName() != selectedWellName) {
QMessageBox::warning(this, tr("Warning"),
tr("Please display the selected gas well in the main result view before fitting."));
return;
}
iSubWndFitting* pFitting = nmDataAnalyzeManager::getCurrentFitting();
iAnalRun* pAnalRun = pFitting ? pFitting->getAnalRun() : nullptr;
// 自动拟合不依赖手动求解流程, 启动 PSO 前需要单独初始化同一拟压力转换器.
// 传入拟合窗口自己的页面数据, 保证目标曲线和每个粒子的结果使用同一 PVT 与模式.
// 气井求解结果的后处理仍需初始化当前分析的拟压力转换器。
if(!pAnalRun
|| !pAnalRun->configPsAbouts(true,
pFitting->getModelOption(),
@ -1057,17 +966,11 @@ void nmWxAutomaticFitting::onAccept()
tr("Gas pseudo-pressure data is unavailable or invalid."));
return;
}
QString curveError;
if(!getMainHistoryLogLog(pFitting, targetLogLogData, curveError)) {
QMessageBox::warning(this, tr("Warning"), curveError);
return;
}
} else {
// 油井和水井不使用拟压力, 继续读取井对象中原有的双对数历史数据.
targetLogLogData = pTargetWell->getHistoryLogLog();
}
// 油、气、水井统一读取所选目标井的历史曲线,不依赖主界面显示的结果井。
QVector<QVector<double> > targetLogLogData = pTargetWell->getHistoryLogLog();
if(targetLogLogData.isEmpty() || targetLogLogData.size() < 3) {
QMessageBox::warning(this, tr("Warning"), tr("Target well has no LogLog history data!"));
return;

Loading…
Cancel
Save