fix(nmNum): 补齐气井目标历史曲线的拟压力转换

- 复用框架 calPS 接口和所属分析窗口配置,转换气井目标曲线的双对数、半对数计算输入
- 生成结果及开始自动拟合前刷新气井历史缓存,避免继续使用未转换的目标曲线
- 保留原始历史压力,转换失败时清除旧曲线有效标记,无曲线计算条件时跳过转换
develop
lvjunjie 3 weeks ago
parent 13a7318267
commit 4583e657cf

@ -54,4 +54,8 @@ class NM_DATA_EXPORT nmDataAnalyzeContextProvider {
// 获取当前结果窗口对应的数值结果保存目录
virtual bool getSaveResultDir(void* pFitting, const QString& sRstCode, QString& sDir) = 0;
// 使用所属分析窗口的配置,将原始压力逐点转换为拟压力。
virtual bool convertPressureToPseudoPressure(
void* pFitting, const VecDouble& vecPressure, VecDouble& vecPseudoPressure) = 0;
};

@ -49,6 +49,10 @@ class NM_SUB_WND_EXPORT nmSubWndDataAnalyzeController : public nmDataAnalyzeCont
// 获取当前结果窗口对应的数值结果保存目录
bool getSaveResultDir(void* pFitting, const QString& sRstCode, QString& sDir);
// 复用框架转换器,供气井历史曲线计算使用。
bool convertPressureToPseudoPressure(
void* pFitting, const VecDouble& vecPressure, VecDouble& vecPseudoPressure);
private:
nmSubWndDataAnalyzeController() {}
};

@ -206,6 +206,7 @@ bool isDisplayResultWell(
}
bool captureResultWellMetadata(
nmDataAnalyzeManager* pDataManager,
nmDataWellBase* pWellData,
bool bDisplayResultWell,
nmPebiWellInputSnapshot& oWellInput)
@ -219,6 +220,12 @@ bool captureResultWellMetadata(
return false;
}
// 发布结果前用当前配置重算气井历史曲线,替换旧项目中未转拟压力的缓存。
if(pDataManager->getSolverModelType() == SMT_Gas_VariablePvt
&& !pDataManager->updateWellHistoryData(pWellData)) {
return false;
}
const QString sCurrentGaugeInputSha1 =
pWellData->calculateGaugeInputSha1();
if(sCurrentGaugeInputSha1.isEmpty() ||
@ -862,6 +869,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
}
if(m_pInputSnapshot->m_oGridInput.m_vecWellInputs.isEmpty() ||
!captureResultWellMetadata(
m_pDataManager,
pWellData,
isDisplayResultWell(pAnalysisCase,
pWellData->getWellCode()),
@ -1050,6 +1058,7 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
mapWellsByCode.value(oWellRef.m_sWellCode, NULL);
if(pWellData == NULL ||
!captureResultWellMetadata(
m_pDataManager,
pWellData,
isDisplayResultWell(pAnalysisCase,
oWellRef.m_sWellCode),

@ -2186,8 +2186,9 @@ void nmDataAnalyzeManager::initCurWellData()
}
}
static void calculateLogDataFromGaugeInput(
static bool calculateLogDataFromGaugeInput(
const nmWellGaugeInputData& oGaugeInput,
bool bUsePseudoPressure, void* pFitting,
QVector<QVector<double>>& vvecHistoryData,
QVector<QVector<double>>& vvecLogPreData,
QVector<QVector<double>>& vvecSemiLogPreData)
@ -2234,9 +2235,24 @@ static void calculateLogDataFromGaugeInput(
pReferenceRates->size() != oGaugeInput.vecFlowDurations.size() ||
oGaugeInput.nFlowSectionIndex < 1 ||
oGaugeInput.nFlowSectionIndex > oGaugeInput.vecFlowDurations.size()) {
return;
return true;
}
// 原始历史压力保持 MPa;只有传给双对数、半对数算法的副本转换为拟压力。
if(bUsePseudoPressure && !vecPressure.isEmpty()) {
nmDataAnalyzeContextProvider* pContext = nmDataAnalyzeContext::provider();
VecDouble vecPseudoPressure;
if(pContext == nullptr
|| !pContext->convertPressureToPseudoPressure(
pFitting, vvecHistoryData[1], vecPseudoPressure)) {
qWarning() << "Failed to convert gas history pressure to pseudo-pressure.";
return false;
}
for(int i = 0; i < vecPseudoPressure.size(); ++i) {
wellPressureData[i].y = vecPseudoPressure[i];
}
}
const int nTimeNumQ = oGaugeInput.vecFlowDurations.size();
std::vector<double> timeQ(nTimeNumQ);
std::vector<double> q(nTimeNumQ);
@ -2259,14 +2275,14 @@ static void calculateLogDataFromGaugeInput(
if(nullptr == preLogFun) {
FreeLibrary(hMod_solver);
std::cout << "preLogFun failed!\n";
return;
return false;
}
bool bCalculated = preLogFun(wellPressureData, iSectionFlowIndex,
timeQ.data(), q.data(), nTimeNumQ, logPre);
if(!bCalculated || logPre.empty()) {
FreeLibrary(hMod_solver);
return;
return false;
}
// The solver's final point is not part of the plotted result.
@ -2285,7 +2301,9 @@ static void calculateLogDataFromGaugeInput(
}
FreeLibrary(hMod_solver);
return true;
}
return false;
}
nmDataWellBase* nmDataAnalyzeManager::appendWellData(ZxDataWell* pWellData)
@ -3039,7 +3057,8 @@ void nmDataAnalyzeManager::calculationLogData(
}
nmWellGaugeInputData oGaugeInput;
pWellData->buildGaugeInputData(oGaugeInput);
calculateLogDataFromGaugeInput(oGaugeInput, vvecHistoryData,
calculateLogDataFromGaugeInput(oGaugeInput,
getSolverModelType() == SMT_Gas_VariablePvt, m_pOwnerFitting, vvecHistoryData,
vvecLogPreData, vvecSemiLogPreData);
}
@ -3059,11 +3078,13 @@ bool nmDataAnalyzeManager::updateWellHistoryData(
QVector<QVector<double> > vecHistoryPressure;
QVector<QVector<double> > vecHistoryLogLog;
QVector<QVector<double> > vecHistorySemiLog;
calculateLogDataFromGaugeInput(oGaugeInput, vecHistoryPressure,
const bool bCalculated = calculateLogDataFromGaugeInput(oGaugeInput,
getSolverModelType() == SMT_Gas_VariablePvt, m_pOwnerFitting, vecHistoryPressure,
vecHistoryLogLog, vecHistorySemiLog);
// 转换或计算失败时清除旧曲线的有效标记,避免继续使用旧的压力曲线。
pWellData->setHistoryData(vecHistoryPressure, vecHistoryLogLog,
vecHistorySemiLog, sGaugeInputSha1);
return true;
vecHistorySemiLog, bCalculated ? sGaugeInputSha1 : QString());
return bCalculated;
}
bool nmDataAnalyzeManager::resetFromAnalytical()

@ -181,6 +181,36 @@ bool nmSubWndDataAnalyzeController::getDiffusionRstOf(void* pFitting, DiffusionS
return pSubWndFitting->getDiffusionRstOf(dso, vvec);
}
bool nmSubWndDataAnalyzeController::convertPressureToPseudoPressure(
void* pFitting, const VecDouble& vecPressure, VecDouble& vecPseudoPressure)
{
vecPseudoPressure.clear();
iSubWndFitting* pSubWndFitting = toFitting(pFitting);
iAnalRun* pAnalRun = pSubWndFitting ? pSubWndFitting->getAnalRun() : nullptr;
// 与模拟曲线保持一致,初始化所属窗口的配置后直接调用 calPS,不另做插值。
if(pAnalRun == nullptr
|| !pAnalRun->configPsAbouts(true, pSubWndFitting->getModelOption(),
false, pSubWndFitting->getAllWxPtr())) {
return false;
}
CalPseudoPressure converter = getPseudoPressureConverter();
if(converter == nullptr) {
return false;
}
VecDouble vecConverted;
vecConverted.reserve(vecPressure.size());
for(int i = 0; i < vecPressure.size(); ++i) {
double ps = 0.0;
if(!qIsFinite(vecPressure[i])
|| !converter(vecPressure[i], ps, -1) || !qIsFinite(ps)) {
return false;
}
vecConverted.append(ps);
}
vecPseudoPressure.swap(vecConverted);
return true;
}
bool nmSubWndDataAnalyzeController::getPseuRstOf(void* pFitting, VVecDouble& vvec)
{
// 先按当前井和相态配置拟压力算法,确保转换规则与自动拟合界面一致。

@ -968,6 +968,13 @@ void nmWxAutomaticFitting::onAccept()
}
}
// 开始拟合前重算气井目标,避免旧缓存或已修改的拟压力配置造成量纲不一致。
if(usePseudoPressure && !pManager->updateWellHistoryData(pTargetWell)) {
QMessageBox::warning(this, tr("Warning"),
tr("Gas pseudo-pressure data is unavailable or invalid."));
return;
}
// 油、气、水井统一读取所选目标井的历史曲线,不依赖主界面显示的结果井。
QVector<QVector<double> > targetLogLogData = pTargetWell->getHistoryLogLog();

Loading…
Cancel
Save