diff --git a/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h b/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h index 1e65706..74eac3a 100644 --- a/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h +++ b/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h @@ -11,8 +11,6 @@ #include "nmCalculation_global.h" -class nmDataWellBase; - // 双对数曲线误差分解。total 是 LM 候选接受和排序的唯一依据, // 其余诊断量用于有限差分灵敏度分析和信赖域选参。 struct AutoFitObjectiveBreakdownLM { @@ -115,7 +113,6 @@ private: void applyParametersToDataManager(const QVector& parameters); void updateReservoirParameters(const QVector& parameters); void updateWellParameters(const QVector& parameters); - void updateWellToDataManager(nmDataWellBase* pWell); QVector > runSolver(); QVector > runSolverDll(); diff --git a/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h b/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h index cc1c958..0aa6fb0 100644 --- a/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h +++ b/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h @@ -14,7 +14,6 @@ // 前向声明 class nmCalculationDllPebiSolverTask; -class nmDataWellBase; class QTimer; class QProcess; @@ -160,7 +159,6 @@ private: void applyParametersToDataManager(const QVector& parameters); void updateReservoirParameters(const QVector& parameters); void updateWellParameters(const QVector& parameters); - void updateWellToDataManager(nmDataWellBase* pWell); // ===== 求解器相关 ===== QVector > runSolver(); diff --git a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp index f89497f..ee17e8e 100644 --- a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp @@ -3,7 +3,6 @@ #include "nmCalculationUtils.h" #include "nmDataAnalyzeManager.h" #include "nmDataWellBase.h" -#include "nmDataVerticalWell.h" #include "nmDataVerticalFracturedWell.h" #include "nmDataHorizontalFracturedWell.h" #include "nmDataReservoir.h" @@ -2776,7 +2775,34 @@ void nmCalculationAutoFitLM::updateWellParameters(const QVector& paramet if(!pWell) return; - //nmDataWellBase* pWell = wells[0]; // 使用第一口井 + // 先在参数副本中组装本次候选值,全部解析完成后再写回现有井对象。 + // 这样不会触发整井赋值,也不会删除并重建井内已有的射孔对象。 + nmDataPerforation* pPerforation = pWell->getPerforation(0); + nmDataAttribute skinAttr; + bool updateSkin = false; + if(pPerforation) { + skinAttr = pPerforation->getSkin(); + } + + nmDataAttribute wellboreAttr = pWell->getWellboreStorage(); + bool updateWellboreStorage = false; + + nmDataVerticalFracturedWell* pVerticalFracturedWell = + dynamic_cast(pWell); + nmDataHorizontalFracturedWell* pHorizontalFracturedWell = + dynamic_cast(pWell); + + nmDataAttribute dfcAttr; + nmDataAttribute fractureHalfLengthAttr; + if(pVerticalFracturedWell) { + dfcAttr = pVerticalFracturedWell->getDfc(); + fractureHalfLengthAttr = pVerticalFracturedWell->getFractureHalfLength(); + } else if(pHorizontalFracturedWell) { + dfcAttr = pHorizontalFracturedWell->getDfc(); + fractureHalfLengthAttr = pHorizontalFracturedWell->getFractureHalfLength(); + } + bool updateDfc = false; + bool updateFractureHalfLength = false; int paramIndex = 0; @@ -2786,58 +2812,31 @@ void nmCalculationAutoFitLM::updateWellParameters(const QVector& paramet switch(i) { case 1: { // 表皮系数 - nmDataPerforation* perf = pWell->getPerforation(0); - - if(perf) { - nmDataAttribute skinAttr = perf->getSkin(); + if(pPerforation) { skinAttr.setValue(value); - perf->setSkin(skinAttr); + updateSkin = true; } } break; case 2: { // 井筒储集系数 - nmDataAttribute wellboreAttr = pWell->getWellboreStorage(); wellboreAttr.setValue(value); - pWell->setWellboreStorage(wellboreAttr); + updateWellboreStorage = true; } break; case 8: { // 裂缝导流能力 - if(pWell->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) { - nmDataVerticalFracturedWell* fracturedWell = - dynamic_cast(pWell); - if(fracturedWell) { - nmDataAttribute dfc = fracturedWell->getDfc(); - dfc.setValue(value); - fracturedWell->setDfc(dfc); - } - } else if(pWell->getWellType() == NM_WELL_MODEL::Horizontal_Fractured_Well) { - nmDataHorizontalFracturedWell* fracturedWell = - dynamic_cast(pWell); - if(fracturedWell) { - nmDataAttribute dfc = fracturedWell->getDfc(); - dfc.setValue(value); - fracturedWell->setDfc(dfc); - } + if(pVerticalFracturedWell || pHorizontalFracturedWell) { + dfcAttr.setValue(value); + updateDfc = true; } } break; case 9: { // 裂缝半长 - // 直接修改井对象中的属性,复用已有信号重算裂缝端点。 - if(pWell->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) { - nmDataVerticalFracturedWell* fracturedWell = - dynamic_cast(pWell); - if(fracturedWell) { - fracturedWell->getFractureHalfLength().setValue(value); - } - } else if(pWell->getWellType() == NM_WELL_MODEL::Horizontal_Fractured_Well) { - nmDataHorizontalFracturedWell* fracturedWell = - dynamic_cast(pWell); - if(fracturedWell) { - fracturedWell->getFractureHalfLength().setValue(value); - } + if(pVerticalFracturedWell || pHorizontalFracturedWell) { + fractureHalfLengthAttr.setValue(value); + updateFractureHalfLength = true; } } break; @@ -2847,58 +2846,28 @@ void nmCalculationAutoFitLM::updateWellParameters(const QVector& paramet } } - // 根据井类型更新到数据管理器 - updateWellToDataManager(pWell); -} - -void nmCalculationAutoFitLM::updateWellToDataManager(nmDataWellBase* pWell) -{ - if(!pWell) return; - - nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); - NM_WELL_MODEL wellType = pWell->getWellType(); - - // DataManager 内部按井型维护不同容器。修改基类指针后,需要根据实际井型 - // 调用对应 update 接口,才能让后续求解器组装读到最新 skin / wellboreC。 - switch(wellType) { - case NM_WELL_MODEL::Vertical_Well: { - nmDataVerticalWell* pVerticalWell = dynamic_cast(pWell); - - if(pVerticalWell) { - QVector wells; - wells.append(*pVerticalWell); - dataManager->updateVerticalWells(wells); - } - - break; - } - - case NM_WELL_MODEL::Vertical_Fractured_Well: { - nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast(pWell); - - if(pVFracturedWell) { - QVector wells; - wells.append(*pVFracturedWell); - dataManager->updateVerticalFracturedWells(wells); - } - - break; - } - - case NM_WELL_MODEL::Horizontal_Fractured_Well: { - nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast(pWell); - - if(pHFracturedWell) { - QVector wells; - wells.append(*pHFracturedWell); - dataManager->updateHorizontalFracturedWells(wells); - } - - break; - } - - default: - break; + if(updateSkin) { + pPerforation->getSkin().setValue(skinAttr.getValue()); + } + if(updateWellboreStorage) { + pWell->getWellboreStorage().setValue(wellboreAttr.getValue()); + } + if(pVerticalFracturedWell) { + if(updateDfc) { + pVerticalFracturedWell->getDfc().setValue(dfcAttr.getValue()); + } + if(updateFractureHalfLength) { + pVerticalFracturedWell->getFractureHalfLength().setValue( + fractureHalfLengthAttr.getValue()); + } + } else if(pHorizontalFracturedWell) { + if(updateDfc) { + pHorizontalFracturedWell->getDfc().setValue(dfcAttr.getValue()); + } + if(updateFractureHalfLength) { + pHorizontalFracturedWell->getFractureHalfLength().setValue( + fractureHalfLengthAttr.getValue()); + } } } diff --git a/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp b/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp index 80f9ffa..0e0c36b 100644 --- a/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp @@ -3,7 +3,6 @@ #include "nmCalculationUtils.h" #include "nmDataAnalyzeManager.h" #include "nmDataWellBase.h" -#include "nmDataVerticalWell.h" #include "nmDataVerticalFracturedWell.h" #include "nmDataHorizontalFracturedWell.h" #include "nmDataReservoir.h" @@ -4209,7 +4208,17 @@ void nmCalculationAutoFitPSO::updateWellParameters(const QVector& parame if(!pWell) return; - //nmDataWellBase* pWell = wells[0]; // 使用第一口井 + // 先修改独立的参数副本,解析完成后再写回原井对象中的现有属性。 + // 不再整井赋值,避免拟合过程中删除并重建射孔对象。 + nmDataPerforation* pPerforation = pWell->getPerforation(0); + nmDataAttribute skinAttr; + bool updateSkin = false; + if(pPerforation) { + skinAttr = pPerforation->getSkin(); + } + + nmDataAttribute wellboreAttr = pWell->getWellboreStorage(); + bool updateWellboreStorage = false; int paramIndex = 0; @@ -4219,20 +4228,16 @@ void nmCalculationAutoFitPSO::updateWellParameters(const QVector& parame switch(i) { case 1: { // 表皮系数 - nmDataPerforation* perf = pWell->getPerforation(0); - - if(perf) { - nmDataAttribute skinAttr = perf->getSkin(); + if(pPerforation) { skinAttr.setValue(value); - perf->setSkin(skinAttr); + updateSkin = true; } } break; case 2: { // 井筒储集系数 - nmDataAttribute wellboreAttr = pWell->getWellboreStorage(); wellboreAttr.setValue(value); - pWell->setWellboreStorage(wellboreAttr); + updateWellboreStorage = true; } break; } @@ -4241,58 +4246,11 @@ void nmCalculationAutoFitPSO::updateWellParameters(const QVector& parame } } - // 根据井类型更新到数据管理器 - updateWellToDataManager(pWell); -} - -void nmCalculationAutoFitPSO::updateWellToDataManager(nmDataWellBase* pWell) -{ - if(!pWell) return; - - nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); - NM_WELL_MODEL wellType = pWell->getWellType(); - - // DataManager 内部按井型维护不同容器。修改基类指针后,需要根据实际井型 - // 调用对应 update 接口,才能让后续求解器组装读到最新 skin / wellboreC。 - switch(wellType) { - case NM_WELL_MODEL::Vertical_Well: { - nmDataVerticalWell* pVerticalWell = dynamic_cast(pWell); - - if(pVerticalWell) { - QVector wells; - wells.append(*pVerticalWell); - dataManager->updateVerticalWells(wells); - } - - break; - } - - case NM_WELL_MODEL::Vertical_Fractured_Well: { - nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast(pWell); - - if(pVFracturedWell) { - QVector wells; - wells.append(*pVFracturedWell); - dataManager->updateVerticalFracturedWells(wells); - } - - break; - } - - case NM_WELL_MODEL::Horizontal_Fractured_Well: { - nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast(pWell); - - if(pHFracturedWell) { - QVector wells; - wells.append(*pHFracturedWell); - dataManager->updateHorizontalFracturedWells(wells); - } - - break; - } - - default: - break; + if(updateSkin) { + pPerforation->getSkin().setValue(skinAttr.getValue()); + } + if(updateWellboreStorage) { + pWell->getWellboreStorage().setValue(wellboreAttr.getValue()); } } diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp index c6ecc8a..a1a145d 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp @@ -3,6 +3,7 @@ #include "nmCalculationAutoFitLM.h" #include "nmWxAutomaticfittingStart.h" #include "nmWxParameterProperty.h" +#include "nmAttrRegistry.h" #include "nmDataAnalyzeManager.h" #include "iSubWndFitting.h" #include "iSysParaHelper.h" @@ -1384,20 +1385,19 @@ void nmWxAutomaticFitting::setAutomaticFittingValue() nmDataWellBase* pTargetWell = manager->findWellByName(selectedWellName); if(pTargetWell) { - // 更新Skin + // 先修改井参数副本,最后写回原对象中的现有属性,保持射孔对象地址不变。 nmDataPerforation* perf = pTargetWell->getPerforation(0); if(perf) { nmDataAttribute skinAttr = perf->getSkin(); skinAttr.setValue(newSkinValue); - perf->setSkin(skinAttr); + perf->getSkin().setValue(skinAttr.getValue()); } // 更新井筒储集系数 nmDataAttribute wellboreAttr = pTargetWell->getWellboreStorage(); wellboreAttr.setValue(newWellboreStorageValue); - pTargetWell->setWellboreStorage(wellboreAttr); + pTargetWell->getWellboreStorage().setValue(wellboreAttr.getValue()); - // 根据井类型单独更新这一口井 NM_WELL_MODEL wellType = pTargetWell->getWellType(); // Dfc 属于压裂井对象;只修改这一项,裂缝位置、长度和段数保持原值。 @@ -1406,40 +1406,26 @@ void nmWxAutomaticFitting::setAutomaticFittingValue() if(fracturedWell) { nmDataAttribute dfc = fracturedWell->getDfc(); dfc.setValue(newFractureConductivityValue); - fracturedWell->setDfc(dfc); - fracturedWell->getFractureHalfLength().setValue(newFractureHalfLengthValue); + fracturedWell->getDfc().setValue(dfc.getValue()); + nmDataAttribute halfLength = fracturedWell->getFractureHalfLength(); + halfLength.setValue(newFractureHalfLengthValue); + fracturedWell->getFractureHalfLength().setValue(halfLength.getValue()); } } else if(wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) { nmDataHorizontalFracturedWell* fracturedWell = dynamic_cast(pTargetWell); if(fracturedWell) { nmDataAttribute dfc = fracturedWell->getDfc(); dfc.setValue(newFractureConductivityValue); - fracturedWell->setDfc(dfc); - fracturedWell->getFractureHalfLength().setValue(newFractureHalfLengthValue); + fracturedWell->getDfc().setValue(dfc.getValue()); + nmDataAttribute halfLength = fracturedWell->getFractureHalfLength(); + halfLength.setValue(newFractureHalfLengthValue); + fracturedWell->getFractureHalfLength().setValue(halfLength.getValue()); } } - if(wellType == NM_WELL_MODEL::Vertical_Well) { - nmDataVerticalWell* pVerticalWell = dynamic_cast(pTargetWell); - if(pVerticalWell != nullptr) { - QVector wells; - wells.append(*pVerticalWell); - manager->updateVerticalWells(wells); - } - } else if(wellType == NM_WELL_MODEL::Vertical_Fractured_Well) { - nmDataVerticalFracturedWell* pVerticalFracturedWell = dynamic_cast(pTargetWell); - if(pVerticalFracturedWell != nullptr) { - QVector wells; - wells.append(*pVerticalFracturedWell); - manager->updateVerticalFracturedWells(wells); - } - } else if(wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) { - nmDataHorizontalFracturedWell* pHorizontalFracturedWell = dynamic_cast(pTargetWell); - if(pHorizontalFracturedWell != nullptr) { - QVector wells; - wells.append(*pHorizontalFracturedWell); - manager->updateHorizontalFracturedWells(wells); - } + // 全部井参数落地后统一刷新一次右侧参数面板。 + if(manager->getAttrRegistry()) { + manager->getAttrRegistry()->refreshAll(); } } } @@ -1555,6 +1541,12 @@ void nmWxAutomaticFitting::onFittingFinished(bool success, const QString& messag disconnect(m_autoFitterLM, SIGNAL(fittingFinished(bool, QString)), this, SLOT(onFittingFinished(bool, QString))); } + + // 拟合候选值通过参数副本写回,结束时统一把最终值同步到右侧参数面板。 + nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance(); + if(manager && manager->getAttrRegistry()) { + manager->getAttrRegistry()->refreshAll(); + } if(success) { // 只有成功拟合的结果才用于生成下一轮范围,失败结果不污染当前配置。 updateBestParametersToTable();