|
|
|
@ -4529,7 +4529,7 @@ double nmCalculationAutoFitPSO::calculateCurveError(
|
|
|
|
const QVector<QPointF>& curve1, const QVector<QPointF>& curve2) const
|
|
|
|
const QVector<QPointF>& curve1, const QVector<QPointF>& curve2) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 两条已经对齐到同一 X 网格的曲线误差。
|
|
|
|
// 两条已经对齐到同一 X 网格的曲线误差。
|
|
|
|
// 使用“相对误差为主、绝对误差为辅”的点误差,并对极端值做保护。
|
|
|
|
// 点误差保持无量纲,避免油水压力和气井拟压力因数值尺度不同而不可比。
|
|
|
|
if(curve1.size() != curve2.size() || curve1.isEmpty()) {
|
|
|
|
if(curve1.size() != curve2.size() || curve1.isEmpty()) {
|
|
|
|
return 1e10;
|
|
|
|
return 1e10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -4550,7 +4550,6 @@ double nmCalculationAutoFitPSO::calculateCurveError(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double totalError = 0.0;
|
|
|
|
double totalError = 0.0;
|
|
|
|
double totalWeight = 0.0;
|
|
|
|
|
|
|
|
int validPoints = 0;
|
|
|
|
int validPoints = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < curve1.size(); ++i) {
|
|
|
|
for(int i = 0; i < curve1.size(); ++i) {
|
|
|
|
@ -4562,33 +4561,16 @@ double nmCalculationAutoFitPSO::calculateCurveError(
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 自适应权重:Y 值越大权重越小,避免大幅值段完全主导误差。
|
|
|
|
double pointError = calculatePointError(y1, y2);
|
|
|
|
double weightFactor = qMin(100.0, qAbs(y1) * 0.01);
|
|
|
|
|
|
|
|
double weight = 1.0 / (1.0 + weightFactor);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 相对误差和绝对误差的组合 - 添加数值保护
|
|
|
|
|
|
|
|
double yMax = qMax(qAbs(y1), qAbs(y2));
|
|
|
|
|
|
|
|
yMax = qMax(1e-12, yMax); // 防止除零
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double relativeError = qAbs(y1 - y2) / yMax;
|
|
|
|
|
|
|
|
double absoluteError = qAbs(y1 - y2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 限制误差值避免爆炸
|
|
|
|
|
|
|
|
relativeError = qMin(1e6, relativeError);
|
|
|
|
|
|
|
|
absoluteError = qMin(1e6, absoluteError);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 误差组合:相对误差为主,绝对误差为辅
|
|
|
|
|
|
|
|
double pointError = 0.7 * relativeError + 0.3 * absoluteError;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(isFiniteNumber(pointError) && pointError < 1e10) {
|
|
|
|
if(isFiniteNumber(pointError) && pointError < 1e10) {
|
|
|
|
totalError += weight * pointError * pointError;
|
|
|
|
totalError += pointError * pointError;
|
|
|
|
totalWeight += weight;
|
|
|
|
|
|
|
|
validPoints++;
|
|
|
|
validPoints++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(totalWeight > 0 && validPoints > 0) {
|
|
|
|
if(validPoints > 0) {
|
|
|
|
double result = sqrt(totalError / totalWeight);
|
|
|
|
double result = sqrt(totalError / validPoints);
|
|
|
|
|
|
|
|
|
|
|
|
// 最终检查
|
|
|
|
// 最终检查
|
|
|
|
if(!isFiniteNumber(result)) {
|
|
|
|
if(!isFiniteNumber(result)) {
|
|
|
|
@ -4775,8 +4757,7 @@ double nmCalculationAutoFitPSO::calculateLogLogCurveError(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double nmCalculationAutoFitPSO::calculateWeightedPointError(
|
|
|
|
double nmCalculationAutoFitPSO::calculatePointError(double target, double result) const
|
|
|
|
double target, double result, double timeWeight) const
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!isFiniteNumber(target) || !isFiniteNumber(result)) {
|
|
|
|
if(!isFiniteNumber(target) || !isFiniteNumber(result)) {
|
|
|
|
return 1e10;
|
|
|
|
return 1e10;
|
|
|
|
@ -4792,7 +4773,6 @@ double nmCalculationAutoFitPSO::calculateWeightedPointError(
|
|
|
|
double relativeError = qAbs(target - result) / qMax(1e-10, yMax);
|
|
|
|
double relativeError = qAbs(target - result) / qMax(1e-10, yMax);
|
|
|
|
|
|
|
|
|
|
|
|
// 组合误差:对数误差占 70%,线性误差占 30%。
|
|
|
|
// 组合误差:对数误差占 70%,线性误差占 30%。
|
|
|
|
// timeWeight 当前没有参与最终公式,保留参数是为了后续按时间段加权扩展。
|
|
|
|
|
|
|
|
return 0.7 * logError + 0.3 * relativeError;
|
|
|
|
return 0.7 * logError + 0.3 * relativeError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -4867,6 +4847,17 @@ QVector<QVector<double>> nmCalculationAutoFitPSO::runSolverDll()
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 线程结束后检查真实执行结果,防止失败时复用上一粒子的旧曲线。
|
|
|
|
|
|
|
|
dllTask->wait();
|
|
|
|
|
|
|
|
if(!dllTask->wasSuccessful()) {
|
|
|
|
|
|
|
|
DEBUG_OUT("DLL solver task reported failure");
|
|
|
|
|
|
|
|
delete dllTask;
|
|
|
|
|
|
|
|
dllTask = nullptr;
|
|
|
|
|
|
|
|
--m_evaluationInProgress;
|
|
|
|
|
|
|
|
m_consecutiveFailures++;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证结果数据是否已更新。DLL 任务会把结果写回 DataManager 中的目标井对象。
|
|
|
|
// 验证结果数据是否已更新。DLL 任务会把结果写回 DataManager 中的目标井对象。
|
|
|
|
nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
|
nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance();
|
|
|
|
//QVector<nmDataWellBase*> wells = dataManager->getWellDataList();
|
|
|
|
//QVector<nmDataWellBase*> wells = dataManager->getWellDataList();
|
|
|
|
|