1.流量为空时,流量段数量设为 0,不会出现 -1 被转换成巨大数组长度的问题。

2.计算误差时跳过目标曲线第一个点,修复公共时间轴端点的浮点误差
feature/AutoFit-Optimize-20260821
lvjunjie 3 weeks ago
parent 8b7f63f063
commit c210cd7b39

@ -6568,15 +6568,17 @@ double nmCalculationAutoFitPSO::calculateLogLogCurveError(
// 无法比较的采样行先跳过;有限但非正的导数无法进入双对数空间,
// 当前数据又没有逐点有效掩码,因此遇到这种导数时判本次评价无效。
auto prepareCurve = [valueFloor](const QVector<QVector<double> >& data,
int firstIndex,
QVector<QPointF>* pressure,
QVector<QPointF>* derivative) -> bool {
if(!pressure || !derivative || data.size() < 3 ||
data[0].size() != data[1].size() ||
data[0].size() != data[2].size()) {
data[0].size() != data[2].size() ||
firstIndex < 0 || firstIndex >= data[0].size()) {
return false;
}
for(int i = 0; i < data[0].size(); ++i) {
for(int i = firstIndex; i < data[0].size(); ++i) {
if(!isFiniteNumber(data[0][i]) ||
!isFiniteNumber(data[1][i]) ||
!isFiniteNumber(data[2][i]) ||
@ -6624,8 +6626,9 @@ double nmCalculationAutoFitPSO::calculateLogLogCurveError(
QVector<QPointF> targetDerivative;
QVector<QPointF> resultPressure;
QVector<QPointF> resultDerivative;
if(!prepareCurve(target, &targetPressure, &targetDerivative) ||
!prepareCurve(result, &resultPressure, &resultDerivative)) {
// 模拟结果已跳过 DLL 首点,因此误差计算同步忽略目标曲线首点。
if(!prepareCurve(target, 1, &targetPressure, &targetDerivative) ||
!prepareCurve(result, 0, &resultPressure, &resultDerivative)) {
return invalidLoss;
}
@ -6721,7 +6724,14 @@ double nmCalculationAutoFitPSO::calculateLogLogCurveError(
(targetLogMaxX - targetLogMinX) /
(numPoints - 1);
commonLogX[i] = logX;
// 首尾直接使用原始端点,避免 exp(log(t)) 的舍入误差越过严格插值边界。
if(i == 0) {
commonX[i] = targetMinX;
} else if(i == numPoints - 1) {
commonX[i] = targetMaxX;
} else {
commonX[i] = qExp(logX);
}
if(!interpolateLogValue(
targetPressure, commonX[i],
@ -7017,10 +7027,14 @@ double nmCalculationAutoFitPSO::calculateLogLogCurveError(
return false;
}
double shiftedX = qExp(
qBound(resultLogMinX,
// 对数时间还原后再次限制到原始端点,避免 exp(log(t)) 的
// 舍入误差越过严格插值边界。
double shiftedX = qBound(
resultMinX,
qExp(qBound(resultLogMinX,
shiftedLogX,
resultLogMaxX));
resultLogMaxX)),
resultMaxX);
double resultLogPressure = 0.0;
double resultLogDerivative = 0.0;
if(!interpolateLogValue(

@ -887,7 +887,8 @@ bool nmCalculationDllPebiSolverTask::savePebiModeResult(
// 准备流量段数据
QVector<QPointF> vecTimeQ = pWellData->getFlowPoints();
int nTimeNumQ = vecTimeQ.size() - 1; // 移除第一个 0 点
// 无流量井保持空数组,避免将 -1 作为 vector 长度。
int nTimeNumQ = qMax(0, vecTimeQ.size() - 1); // 移除第一个 0 点
std::vector<double> timeQ(nTimeNumQ);
std::vector<double> q(nTimeNumQ);
@ -899,10 +900,21 @@ bool nmCalculationDllPebiSolverTask::savePebiModeResult(
// 调用外部 DLL 计算双对数曲线
std::vector<Point> logPreResultFromDll; // 存储 DLL 的计算结果
int iSectionFlowIndex = pWellData->getIndexF();
// 无流量井仍保留压力结果,但没有流量制度时无法计算双对数和半对数。
HMODULE hMod_solver = nTimeNumQ > 0
? LoadLibrary(L"singlePhaseSolverDll.dll")
: nullptr;
HMODULE hMod_solver = LoadLibrary(L"singlePhaseSolverDll.dll");
if(nTimeNumQ <= 0) {
vvecLogLog.clear();
vvecLogLog.append(QVector<double>());
vvecLogLog.append(QVector<double>());
vvecLogLog.append(QVector<double>());
if(hMod_solver) {
vvecSemiLog.clear();
vvecSemiLog.append(QVector<double>());
vvecSemiLog.append(QVector<double>());
} else if(hMod_solver) {
typedef bool (*PreLog)(const std::vector<Point>&, const int&, double*, double*, int, std::vector<Point>&);
PreLog preLogFun = (PreLog)GetProcAddress(hMod_solver, "logLogPre");

Loading…
Cancel
Save