|
|
|
|
@ -211,6 +211,46 @@ bool isFiniteSolverNumber(double value)
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double calculateSensitivityPressureRmse(const QVector<QVector<double> >& measured,
|
|
|
|
|
const QVector<QVector<double> >& simulated,
|
|
|
|
|
const QAtomicInt* cancelRequested)
|
|
|
|
|
{
|
|
|
|
|
if(measured.size() < 2 || simulated.size() < 2 || simulated[0].isEmpty() ||
|
|
|
|
|
measured[0].size() != measured[1].size() ||
|
|
|
|
|
simulated[0].size() != simulated[1].size()) return -1.0;
|
|
|
|
|
const QVector<double>& times = simulated[0];
|
|
|
|
|
const QVector<double>& pressures = simulated[1];
|
|
|
|
|
for(int i = 0; i < times.size(); ++i) {
|
|
|
|
|
if((i % 256) == 0 && isTaskCancellationRequested(cancelRequested)) return -1.0;
|
|
|
|
|
if(!isFiniteSolverNumber(times[i]) || !isFiniteSolverNumber(pressures[i]) ||
|
|
|
|
|
(i > 0 && times[i] <= times[i - 1])) return -1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在实测时间上线性插值原始压力,只统计覆盖范围内的有效点,不外推。
|
|
|
|
|
double squaredError = 0.0;
|
|
|
|
|
int count = 0;
|
|
|
|
|
for(int i = 0; i < measured[0].size(); ++i) {
|
|
|
|
|
if((i % 256) == 0 && isTaskCancellationRequested(cancelRequested)) return -1.0;
|
|
|
|
|
const double time = measured[0][i];
|
|
|
|
|
const double pressure = measured[1][i];
|
|
|
|
|
if(!isFiniteSolverNumber(time) || !isFiniteSolverNumber(pressure) ||
|
|
|
|
|
time < times.first() || time > times.last()) continue;
|
|
|
|
|
const int right = static_cast<int>(
|
|
|
|
|
std::lower_bound(times.constBegin(), times.constEnd(), time) - times.constBegin());
|
|
|
|
|
double predicted = pressures[right];
|
|
|
|
|
if(times[right] != time) {
|
|
|
|
|
const double fraction = (time - times[right - 1]) / (times[right] - times[right - 1]);
|
|
|
|
|
predicted = pressures[right - 1] + fraction * (pressures[right] - pressures[right - 1]);
|
|
|
|
|
}
|
|
|
|
|
const double residual = predicted - pressure;
|
|
|
|
|
squaredError += residual * residual;
|
|
|
|
|
++count;
|
|
|
|
|
}
|
|
|
|
|
// 普通 Monte-Carlo 的各点权重均为 1;无有效点不能当作完全拟合。
|
|
|
|
|
return count > 0 && isFiniteSolverNumber(squaredError)
|
|
|
|
|
? std::sqrt(squaredError / count) : -1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool savedPseudoPressure(const nmDataBinaryTools::NM_PEBI_SCENE& scene,
|
|
|
|
|
double pressure, double& result)
|
|
|
|
|
{
|
|
|
|
|
@ -1012,6 +1052,13 @@ bool nmCalculationDllPebiSolverTask::executeSensitivityBatch()
|
|
|
|
|
result.m_vecPressure = m_autoFitResultPressure;
|
|
|
|
|
result.m_vecLogLog = m_autoFitResultLogLog;
|
|
|
|
|
result.m_vecSemiLog = m_autoFitResultSemiLog;
|
|
|
|
|
if(m_pSensitivityResult->m_calcType == nmDataSensitive::CALC_MONTE_CARLO) {
|
|
|
|
|
// 使用求解时冻结的目标井实测压力,不读取界面后来修改的数据。
|
|
|
|
|
const int target = m_pInputSnapshot->m_oSensitivityBaseline.m_nTarget;
|
|
|
|
|
result.m_dPressureRmse = calculateSensitivityPressureRmse(
|
|
|
|
|
m_pInputSnapshot->m_oGridInput.m_vecWellInputs[target].m_vecHistoryPressure,
|
|
|
|
|
result.m_vecPressure, &m_nCancelRequested);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
result.m_sFailureReason = m_sFailureReason;
|
|
|
|
|
}
|
|
|
|
|
@ -1023,6 +1070,7 @@ bool nmCalculationDllPebiSolverTask::executeSensitivityBatch()
|
|
|
|
|
result.m_vecPressure.clear();
|
|
|
|
|
result.m_vecLogLog.clear();
|
|
|
|
|
result.m_vecSemiLog.clear();
|
|
|
|
|
result.m_dPressureRmse = -1.0;
|
|
|
|
|
} else if(!result.m_bSucceeded) {
|
|
|
|
|
++failed;
|
|
|
|
|
}
|
|
|
|
|
|