From e825840a1e4449a82d756199a5e14c073f294c54 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Wed, 2 Sep 2026 15:34:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(numerical):=20=E5=AE=8C=E5=96=84PEBI?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E4=BF=AE=E6=94=B9=E5=90=8E=E7=9A=84=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=A4=B1=E6=95=88=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 区分网格输入变化和仅求解输入变化 - 储层属性提交时比较完整快照,避免无变化时推进版本 - 井、断层及裂缝几何变化后同时使网格和结果失效 - 储层、PVT、表皮及井筒储集等变化后仅使结果失效 - 补充裂缝宽度和Dfc等网格输入的变化判断 - 修复旧参数树下拉选项未写回数据管理器的问题 - 保持自动拟合候选参数回写逻辑不变 --- .../nmReservoirPropertiesDataSource.h | 16 ++- .../nmSubWxs/nmReservoirPropertiesSession.h | 4 +- .../nmNum/nmSubWxs/nmWxParameterProperty.h | 5 + .../nmReservoirPropertiesDataSource.cpp | 12 +- .../nmSubWxs/nmReservoirPropertiesSession.cpp | 109 ++++++++++++--- Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp | 117 +++++++++++++++- Src/nmNum/nmSubWxs/nmWxParameterProperty.cpp | 127 +++++++++++++++--- 7 files changed, 340 insertions(+), 50 deletions(-) diff --git a/Include/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.h b/Include/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.h index 6422d17..e908a75 100644 --- a/Include/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.h +++ b/Include/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "nmSubWxs_global.h" @@ -13,6 +13,14 @@ class nmDataAnalyzeManager; +/** @brief PEBI 正式输入提交后的失效等级。 */ +enum NM_PEBI_INPUT_CHANGE +{ + NM_PEBI_INPUT_UNCHANGED = 0, ///< 输入没有实际变化。 + NM_PEBI_RESULT_INPUT_CHANGED, ///< 仅求解输入变化,已有网格仍可复用。 + NM_PEBI_GRID_INPUT_CHANGED ///< 网格输入变化,网格和结果同时失效。 +}; + /** * @brief 储层参数编辑快照。 * @note 快照保存一次编辑会话所需的全部数据副本,不包含普通水平井。 @@ -55,12 +63,12 @@ public: /** * @brief 一次性提交编辑后的工作快照。 * @param oSnapshot 待提交的工作快照。 - * @param bGeometryChanged 井坐标或几何参数是否发生变化。 + * @param eInputChange 本次正式提交对应的PEBI输入失效等级。 * @param sError 输出的错误信息。 * @return 提交成功返回true。 */ virtual bool commitSnapshot(const nmReservoirPropertiesSnapshot& oSnapshot, - bool bGeometryChanged, + NM_PEBI_INPUT_CHANGE eInputChange, QString& sError) = 0; }; @@ -84,7 +92,7 @@ public: QString& sError) const; virtual bool commitSnapshot(const nmReservoirPropertiesSnapshot& oSnapshot, - bool bGeometryChanged, + NM_PEBI_INPUT_CHANGE eInputChange, QString& sError); private: diff --git a/Include/nmNum/nmSubWxs/nmReservoirPropertiesSession.h b/Include/nmNum/nmSubWxs/nmReservoirPropertiesSession.h index fa93af9..4d4cd41 100644 --- a/Include/nmNum/nmSubWxs/nmReservoirPropertiesSession.h +++ b/Include/nmNum/nmSubWxs/nmReservoirPropertiesSession.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "nmSubWxs_global.h" #include "nmReservoirPropertiesDataSource.h" @@ -87,6 +87,8 @@ public: const nmReservoirPropertiesSnapshot& workingSnapshot() const; private: + /** @brief 判断工作副本中的任一正式输入是否发生变化。 */ + bool isInputChanged() const; /** @brief 判断井坐标或几何参数是否发生变化。 */ bool isGeometryChanged() const; diff --git a/Include/nmNum/nmSubWxs/nmWxParameterProperty.h b/Include/nmNum/nmSubWxs/nmWxParameterProperty.h index 2b96f1f..0ea4a35 100644 --- a/Include/nmNum/nmSubWxs/nmWxParameterProperty.h +++ b/Include/nmNum/nmSubWxs/nmWxParameterProperty.h @@ -74,6 +74,11 @@ private: QString formatAttributeValue(const QVariant& value, const QString& unit); void addAttributeToTree(QTreeWidgetItem* parent, nmDataAttribute& attr, DataCategory category); + /** @brief 将单个属性所属的数据副本提交到当前数据管理器。 */ + void commitAttributeChange(DataCategory category, nmDataAttribute* pAttribute); + /** @brief 判断指定属性是否直接参与PEBI网格输入。 */ + bool isPebiGridInputAttribute(DataCategory category, + nmDataAttribute* pAttribute); public slots: void onWellSelected(); diff --git a/Src/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.cpp b/Src/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.cpp index 0502ac6..e5f3b1c 100644 --- a/Src/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.cpp +++ b/Src/nmNum/nmSubWxs/nmReservoirPropertiesDataSource.cpp @@ -1,4 +1,4 @@ -#include "nmReservoirPropertiesDataSource.h" +#include "nmReservoirPropertiesDataSource.h" #include "nmDataAnalyzeManager.h" #include "nmDataWellBase.h" @@ -84,7 +84,7 @@ bool nmAnalyzeManagerReservoirDataSource::loadSnapshot( bool nmAnalyzeManagerReservoirDataSource::commitSnapshot( const nmReservoirPropertiesSnapshot& oSnapshot, - bool bGeometryChanged, + NM_PEBI_INPUT_CHANGE eInputChange, QString& sError) { // 第一步:提交前再次校验数据管理器生命周期。 @@ -104,14 +104,18 @@ bool nmAnalyzeManagerReservoirDataSource::commitSnapshot( m_pDataManager->updateRegionMarkData(oSnapshot.m_vecRegionMarks); m_pDataManager->updateReservoirData(oSnapshot.m_oReservoir); - // 第三步:重建实时注册表映射,并在几何变化时统一通知画布和网格。 + // 第三步:重建实时注册表映射,并按正式输入差异推进一次版本。 m_pDataManager->syncWellAttrs(); m_pDataManager->syncGeometryAttrs(); - if (bGeometryChanged) + if (eInputChange == NM_PEBI_GRID_INPUT_CHANGED) { m_pDataManager->notifyDataChanged(); m_pDataManager->updateWellPlotByDataManager(); } + else if (eInputChange == NM_PEBI_RESULT_INPUT_CHANGED) + { + m_pDataManager->invalidatePebiResults(); + } // 第四步:兼容仍在使用旧参数树的窗口,提交完成后只刷新一次表格入口。 nmWxParameterProperty::notifyUpdateTable(); diff --git a/Src/nmNum/nmSubWxs/nmReservoirPropertiesSession.cpp b/Src/nmNum/nmSubWxs/nmReservoirPropertiesSession.cpp index 293b74c..cba9483 100644 --- a/Src/nmNum/nmSubWxs/nmReservoirPropertiesSession.cpp +++ b/Src/nmNum/nmSubWxs/nmReservoirPropertiesSession.cpp @@ -2,6 +2,7 @@ #include "nmAttrRegistry.h" #include "nmDataAttribute.h" +#include "rapidjson/document.h" namespace { @@ -12,12 +13,37 @@ bool sameValue(const QVariant& oLeft, const QVariant& oRight) return oLeft == oRight; } -/** @brief 比较两口井的网格相关参数。 */ -bool sameWellGeometry(nmDataWellBase& oLeft, nmDataWellBase& oRight) +template +bool sameDataObject(const T& oLeft, const T& oRight) +{ + rapidjson::Document oLeftDocument; + rapidjson::Document oRightDocument; + rapidjson::Value oLeftValue = oLeft.ToJsonValue( + oLeftDocument.GetAllocator()); + rapidjson::Value oRightValue = oRight.ToJsonValue( + oRightDocument.GetAllocator()); + return oLeftValue == oRightValue; +} + +template +bool sameDataVector(const QVector& vecLeft, const QVector& vecRight) +{ + if(vecLeft.size() != vecRight.size()) { + return false; + } + for(int nIndex = 0; nIndex < vecLeft.size(); ++nIndex) { + if(!sameDataObject(vecLeft[nIndex], vecRight[nIndex])) { + return false; + } + } + return true; +} + +/** @brief 比较两口井的平面位置。 */ +bool sameWellPosition(nmDataWellBase& oLeft, nmDataWellBase& oRight) { return sameValue(oLeft.getX().getValue(), oRight.getX().getValue()) && - sameValue(oLeft.getY().getValue(), oRight.getY().getValue()) && - sameValue(oLeft.getRadius().getValue(), oRight.getRadius().getValue()); + sameValue(oLeft.getY().getValue(), oRight.getY().getValue()); } } @@ -86,6 +112,10 @@ bool nmReservoirPropertiesSession::setValue(const QString& sParameterId, { return false; } + if (sameValue(value(sParameterId), oValue)) + { + return true; + } m_pAttrRegistry->setValue(sParameterId, oValue); return true; } @@ -117,9 +147,17 @@ bool nmReservoirPropertiesSession::setEnumCode(const QString& sParameterId, { return false; } - return nmReservoirParameterCatalog::setEnumCode(m_oWorkingSnapshot, - sParameterId, - sCode); + if (enumCode(sParameterId) == sCode) + { + return true; + } + if (!nmReservoirParameterCatalog::setEnumCode(m_oWorkingSnapshot, + sParameterId, + sCode)) + { + return false; + } + return true; } bool nmReservoirPropertiesSession::commit(QString& sError) @@ -130,12 +168,20 @@ bool nmReservoirPropertiesSession::commit(QString& sError) return false; } - // 第一步:在提交前计算几何变更,供数据源决定是否重建网格和刷新画布。 - bool bGeometryChanged = isGeometryChanged(); + // 第一步:几何变化优先级最高;其他正式输入只推进结果版本。 + NM_PEBI_INPUT_CHANGE eInputChange = NM_PEBI_INPUT_UNCHANGED; + if (isGeometryChanged()) + { + eInputChange = NM_PEBI_GRID_INPUT_CHANGED; + } + else if (isInputChanged()) + { + eInputChange = NM_PEBI_RESULT_INPUT_CHANGED; + } // 第二步:将完整工作副本一次性交给数据源;失败时继续保留当前编辑内容。 if (!m_pDataSource->commitSnapshot(m_oWorkingSnapshot, - bGeometryChanged, + eInputChange, sError)) { return false; @@ -153,6 +199,29 @@ nmReservoirPropertiesSession::workingSnapshot() const return m_oWorkingSnapshot; } +bool nmReservoirPropertiesSession::isInputChanged() const +{ + // 完整结构化比较覆盖数值、枚举和批量导入,不依赖具体界面入口。 + return m_oOriginalSnapshot.m_nSolverModelType != + m_oWorkingSnapshot.m_nSolverModelType || + !sameDataObject(m_oOriginalSnapshot.m_oReservoir, + m_oWorkingSnapshot.m_oReservoir) || + !sameDataVector(m_oOriginalSnapshot.m_vecVerticalWells, + m_oWorkingSnapshot.m_vecVerticalWells) || + !sameDataVector(m_oOriginalSnapshot.m_vecVerticalFracturedWells, + m_oWorkingSnapshot.m_vecVerticalFracturedWells) || + !sameDataVector(m_oOriginalSnapshot.m_vecHorizontalFracturedWells, + m_oWorkingSnapshot.m_vecHorizontalFracturedWells) || + !sameDataVector(m_oOriginalSnapshot.m_vecRegionMarks, + m_oWorkingSnapshot.m_vecRegionMarks) || + !sameDataVector(m_oOriginalSnapshot.m_vecFaults, + m_oWorkingSnapshot.m_vecFaults) || + !sameDataVector(m_oOriginalSnapshot.m_vecFractures, + m_oWorkingSnapshot.m_vecFractures) || + !sameDataVector(m_oOriginalSnapshot.m_vecRegions, + m_oWorkingSnapshot.m_vecRegions); +} + bool nmReservoirPropertiesSession::isGeometryChanged() const { // 第一步:对象数量变化视为几何变化,虽然当前对话框本身不提供增删操作。 @@ -173,7 +242,9 @@ bool nmReservoirPropertiesSession::isGeometryChanged() const const_cast(m_oOriginalSnapshot.m_vecVerticalWells[nIndex]); nmDataVerticalWell& oWorking = const_cast(m_oWorkingSnapshot.m_vecVerticalWells[nIndex]); - if (!sameWellGeometry(oOriginal, oWorking)) + if (!sameWellPosition(oOriginal, oWorking) || + !sameValue(oOriginal.getRadius().getValue(), + oWorking.getRadius().getValue())) { return true; } @@ -184,11 +255,15 @@ bool nmReservoirPropertiesSession::isGeometryChanged() const m_oOriginalSnapshot.m_vecVerticalFracturedWells[nIndex]); nmDataVerticalFracturedWell& oWorking = const_cast( m_oWorkingSnapshot.m_vecVerticalFracturedWells[nIndex]); - if (!sameWellGeometry(oOriginal, oWorking) || + if (!sameWellPosition(oOriginal, oWorking) || !sameValue(oOriginal.getFractureHalfLength().getValue(), oWorking.getFractureHalfLength().getValue()) || !sameValue(oOriginal.getFractureAngle().getValue(), - oWorking.getFractureAngle().getValue())) + oWorking.getFractureAngle().getValue()) || + !sameValue(oOriginal.getWidth().getValue(), + oWorking.getWidth().getValue()) || + !sameValue(oOriginal.getDfc().getValue(), + oWorking.getDfc().getValue())) { return true; } @@ -201,7 +276,7 @@ bool nmReservoirPropertiesSession::isGeometryChanged() const nmDataHorizontalFracturedWell& oWorking = const_cast( m_oWorkingSnapshot.m_vecHorizontalFracturedWells[nIndex]); - if (!sameWellGeometry(oOriginal, oWorking) || + if (!sameWellPosition(oOriginal, oWorking) || !sameValue(oOriginal.getWellLength().getValue(), oWorking.getWellLength().getValue()) || !sameValue(oOriginal.getDrainAngle().getValue(), oWorking.getDrainAngle().getValue()) || !sameValue(oOriginal.getNumberOfFractures().getValue(), @@ -209,7 +284,11 @@ bool nmReservoirPropertiesSession::isGeometryChanged() const !sameValue(oOriginal.getFractureHalfLength().getValue(), oWorking.getFractureHalfLength().getValue()) || !sameValue(oOriginal.getFractureAngle().getValue(), - oWorking.getFractureAngle().getValue())) + oWorking.getFractureAngle().getValue()) || + !sameValue(oOriginal.getWidth().getValue(), + oWorking.getWidth().getValue()) || + !sameValue(oOriginal.getDfc().getValue(), + oWorking.getDfc().getValue())) { return true; } diff --git a/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp b/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp index acac0bb..d8fcbeb 100644 --- a/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp +++ b/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp @@ -33,6 +33,86 @@ #include "nmWellEditorController.h" +namespace +{ + +bool sameAttributeValue(nmDataAttribute& oLeft, nmDataAttribute& oRight) +{ + return oLeft.getValue() == oRight.getValue(); +} + +/** @brief 比较井对象的完整结构化数据,覆盖射孔和全部求解属性。 */ +bool hasPebiInputChanged(nmDataWellBase* pOldWell, + nmDataWellBase* pNewWell) +{ + if(pOldWell == nullptr || pNewWell == nullptr) { + return pOldWell != pNewWell; + } + + rapidjson::Document oOldDocument; + rapidjson::Document oNewDocument; + rapidjson::Value oOldValue = pOldWell->ToJsonValue( + oOldDocument.GetAllocator()); + rapidjson::Value oNewValue = pNewWell->ToJsonValue( + oNewDocument.GetAllocator()); + return oOldValue != oNewValue; +} + +/** @brief 比较两口井实际传给网格DLL的输入。 */ +bool hasPebiGridInputChanged(nmDataWellBase* pOldWell, + nmDataWellBase* pNewWell) +{ + if(pOldWell == nullptr || pNewWell == nullptr || + pOldWell->getWellType() != pNewWell->getWellType()) { + return true; + } + + if(!sameAttributeValue(pOldWell->getX(), pNewWell->getX()) || + !sameAttributeValue(pOldWell->getY(), pNewWell->getY())) { + return true; + } + + nmDataVerticalFracturedWell* pOldVerticalFractured = + dynamic_cast(pOldWell); + nmDataVerticalFracturedWell* pNewVerticalFractured = + dynamic_cast(pNewWell); + if(pOldVerticalFractured != nullptr || pNewVerticalFractured != nullptr) { + return pOldVerticalFractured == nullptr || + pNewVerticalFractured == nullptr || + pOldVerticalFractured->getFracs() != + pNewVerticalFractured->getFracs() || + !sameAttributeValue(pOldVerticalFractured->getWidth(), + pNewVerticalFractured->getWidth()) || + !sameAttributeValue(pOldVerticalFractured->getDfc(), + pNewVerticalFractured->getDfc()); + } + + nmDataHorizontalFracturedWell* pOldHorizontalFractured = + dynamic_cast(pOldWell); + nmDataHorizontalFracturedWell* pNewHorizontalFractured = + dynamic_cast(pNewWell); + if(pOldHorizontalFractured != nullptr || pNewHorizontalFractured != nullptr) { + return pOldHorizontalFractured == nullptr || + pNewHorizontalFractured == nullptr || + pOldHorizontalFractured->getFracs() != + pNewHorizontalFractured->getFracs() || + !sameAttributeValue(pOldHorizontalFractured->getWidth(), + pNewHorizontalFractured->getWidth()) || + !sameAttributeValue(pOldHorizontalFractured->getDfc(), + pNewHorizontalFractured->getDfc()); + } + + nmDataVerticalWell* pOldVertical = + dynamic_cast(pOldWell); + nmDataVerticalWell* pNewVertical = + dynamic_cast(pNewWell); + return pOldVertical == nullptr || pNewVertical == nullptr || + !sameAttributeValue(pOldVertical->getRadius(), + pNewVertical->getRadius()); +} + +} + nmWxEditWellPlot::nmWxEditWellPlot(QWidget *parent, ZxDataWell* pZxDataWell, nmDataWellBase* pNmDataWell) : iDlgBase(parent) , m_pMainSplitter(nullptr) @@ -567,14 +647,27 @@ void nmWxEditWellPlot::onOkClicked() return; } + nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance(); + if(pManager == nullptr) { + iDlgBase::reject(); + return; + } + + // 正式写回前冻结差异,赋值完成后实时对象已经无法再提供旧值。 + nmDataWellBase* pStoredWell = pManager->findWellByInstanceId( + m_pNmDataWell->getWellInstanceId()); + const bool bInputChanged = hasPebiInputChanged( + pStoredWell, m_pNmDataWell); + const bool bGridInputChanged = + hasPebiGridInputChanged(pStoredWell, m_pNmDataWell); + // 应用时间变表皮状态到真实数据 - nmDataWellBase* pRealWell = nmDataAnalyzeManager::getCurrentInstance()->getCurWellData(); + nmDataWellBase* pRealWell = pManager->getCurWellData(); if(pRealWell && pRealWell->getWellName() == m_pNmDataWell->getWellName()) { pRealWell->setTimeDependentSkin(m_pNmDataWell->isTimeDependentSkin()); } - nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance(); NM_WELL_MODEL currentWellType = m_pNmDataWell->getWellType(); // 根据井类型调用对应的update方法 @@ -583,27 +676,36 @@ void nmWxEditWellPlot::onOkClicked() if(auto * verticalWell = dynamic_cast(m_pNmDataWell)) { QVector wells; wells.append(*verticalWell); // 添加井的副本到QVector中 - manager->updateVerticalWells(wells); + pManager->updateVerticalWells(wells); } } else if(currentWellType == NM_WELL_MODEL::Vertical_Fractured_Well) { // 转换为垂直压裂井类型 if(auto * verticalFracturedWell = dynamic_cast(m_pNmDataWell)) { QVector wells; wells.append(*verticalFracturedWell); // 添加井的副本到QVector中 - manager->updateVerticalFracturedWells(wells); + pManager->updateVerticalFracturedWells(wells); } } else if(currentWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) { // 转换为水平压裂井类型 if(auto * horizontalFracturedWell = dynamic_cast(m_pNmDataWell)) { QVector wells; wells.append(*horizontalFracturedWell); // 添加井的副本到QVector中 - manager->updateHorizontalFracturedWells(wells); + pManager->updateHorizontalFracturedWells(wells); } } else { iDlgBase::reject(); return; } + // 人工确认后的输入变化必须推进版本,阻止后台旧任务提交过期结果。 + if(bInputChanged) { + if(bGridInputChanged) { + pManager->notifyDataChanged(); + } else { + pManager->invalidatePebiResults(); + } + } + // 更新完成后,通知参数界面刷新 nmWxParameterProperty::notifyUpdateTable(); @@ -745,7 +847,10 @@ void nmWxEditWellPlot::onWellNameEditingFinished() { if(m_pNmDataWell && m_pWellNameLineEdit) { // 获取编辑框中的文本并更新数据模型 - m_pNmDataWell->setWellName(m_pWellNameLineEdit->text()); + const QString sWellName = m_pWellNameLineEdit->text(); + if(m_pNmDataWell->getWellName() != sWellName) { + m_pNmDataWell->setWellName(sWellName); + } } } diff --git a/Src/nmNum/nmSubWxs/nmWxParameterProperty.cpp b/Src/nmNum/nmSubWxs/nmWxParameterProperty.cpp index 6810efd..031f801 100644 --- a/Src/nmNum/nmSubWxs/nmWxParameterProperty.cpp +++ b/Src/nmNum/nmSubWxs/nmWxParameterProperty.cpp @@ -311,6 +311,7 @@ void nmWxParameterProperty::onItemDoubleClicked(QTreeWidgetItem* item, int colum void nmWxParameterProperty::onComboBoxSelectionChanged(int index) { + Q_UNUSED(index); QComboBox* comboBox = qobject_cast(sender()); if(!comboBox) return; @@ -327,10 +328,16 @@ void nmWxParameterProperty::onComboBoxSelectionChanged(int index) nmDataAttribute* attr = item->data(1, Qt::UserRole).value(); if(attr) { + DataCategory category = static_cast( + item->data(1, Qt::UserRole + 1).toInt()); + QVariant oldValue = attr->getValue(); QString selectedValue = comboBox->currentText(); attr->setValue(selectedValue); // 更新界面显示文本 item->setText(1, selectedValue); + if(oldValue != attr->getValue()) { + commitAttributeChange(category, attr); + } } m_pTreeWidget->removeItemWidget(item, 1); @@ -390,47 +397,127 @@ void nmWxParameterProperty::onEditingFinished() attr->setValue(newValue); item->setText(1, formatAttributeValue(newValue, attr->getUnit())); - // 根据数据类别更新对应的数据到数据中心 - nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance(); + if(oldValue != newValue) { + commitAttributeChange(category, attr); + } + + editor->deleteLater(); +} + +void nmWxParameterProperty::commitAttributeChange( + DataCategory category, + nmDataAttribute* pAttribute) +{ + nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance(); + if(pManager == nullptr || pAttribute == nullptr) { + return; + } + // 第一步:先把当前页面持有的完整对象副本写回实时数据。 switch(category) { case ReservoirCat: - manager->updateReservoirData(m_reservior); + pManager->updateReservoirData(m_reservior); break; - case VerticalWellCat: - manager->updateVerticalWells(m_vecVerticalWells); + pManager->updateVerticalWells(m_vecVerticalWells); break; - case VerticalFracturedWellCat: - manager->updateVerticalFracturedWells(m_vecVerticalFracturedWells); + pManager->updateVerticalFracturedWells(m_vecVerticalFracturedWells); break; - case HorizontalFracturedWellCat: - manager->updateHorizontalFracturedWells(m_vecHorizontalFracturedWells); + pManager->updateHorizontalFracturedWells(m_vecHorizontalFracturedWells); break; - case FaultCat: - manager->updateFaultData(m_vecDataFaults); + pManager->updateFaultData(m_vecDataFaults); break; - case FractureCat: - manager->updateFractureData(m_vecDataFractures); + pManager->updateFractureData(m_vecDataFractures); break; - case RegionCat: - manager->updateRegionData(m_vecDataRegions); + pManager->updateRegionData(m_vecDataRegions); break; - case RegionMarkCat: - manager->updateRegionMarkData(m_vecRegionMark); + pManager->updateRegionMarkData(m_vecRegionMark); break; - default: - break; + return; } - editor->deleteLater(); + // 第二步:正式输入提交必须推进版本,使后台旧任务不能通过最终校验。 + if(isPebiGridInputAttribute(category, pAttribute)) { + pManager->notifyDataChanged(); + } else { + pManager->invalidatePebiResults(); + } +} + +bool nmWxParameterProperty::isPebiGridInputAttribute( + DataCategory category, + nmDataAttribute* pAttribute) +{ + if(pAttribute == nullptr) { + return false; + } + + if(category == VerticalWellCat) { + for(int nIndex = 0; nIndex < m_vecVerticalWells.size(); ++nIndex) { + nmDataVerticalWell& oWell = m_vecVerticalWells[nIndex]; + if(pAttribute == &oWell.getX() || + pAttribute == &oWell.getY() || + pAttribute == &oWell.getRadius()) { + return true; + } + } + } else if(category == VerticalFracturedWellCat) { + for(int nIndex = 0; nIndex < m_vecVerticalFracturedWells.size(); ++nIndex) { + nmDataVerticalFracturedWell& oWell = m_vecVerticalFracturedWells[nIndex]; + if(pAttribute == &oWell.getX() || + pAttribute == &oWell.getY() || + pAttribute == &oWell.getFractureHalfLength() || + pAttribute == &oWell.getFractureAngle() || + pAttribute == &oWell.getWidth() || + pAttribute == &oWell.getDfc()) { + return true; + } + } + } else if(category == HorizontalFracturedWellCat) { + for(int nIndex = 0; nIndex < m_vecHorizontalFracturedWells.size(); ++nIndex) { + nmDataHorizontalFracturedWell& oWell = + m_vecHorizontalFracturedWells[nIndex]; + if(pAttribute == &oWell.getX() || + pAttribute == &oWell.getY() || + pAttribute == &oWell.getWellLength() || + pAttribute == &oWell.getDrainAngle() || + pAttribute == &oWell.getNumberOfFractures() || + pAttribute == &oWell.getFractureHalfLength() || + pAttribute == &oWell.getFractureAngle() || + pAttribute == &oWell.getWidth() || + pAttribute == &oWell.getDfc()) { + return true; + } + } + } else if(category == FaultCat) { + for(int nIndex = 0; nIndex < m_vecDataFaults.size(); ++nIndex) { + nmDataFault& oFault = m_vecDataFaults[nIndex]; + if(pAttribute == &oFault.getStartX() || + pAttribute == &oFault.getStartY() || + pAttribute == &oFault.getEndX() || + pAttribute == &oFault.getEndY()) { + return true; + } + } + } else if(category == FractureCat) { + for(int nIndex = 0; nIndex < m_vecDataFractures.size(); ++nIndex) { + nmDataFracture& oFracture = m_vecDataFractures[nIndex]; + if(pAttribute == &oFracture.getStartX() || + pAttribute == &oFracture.getStartY() || + pAttribute == &oFracture.getEndX() || + pAttribute == &oFracture.getEndY()) { + return true; + } + } + } + return false; } void nmWxParameterProperty::appendReservoirToTree(nmDataReservoir &reservoir)