From ec384f7483ce6c1473254b2ffeeedfd82a748b4c Mon Sep 17 00:00:00 2001 From: lvjunjie Date: Thu, 10 Sep 2026 10:20:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(nmNum):=20=E7=A7=BB=E9=99=A4=E5=82=A8?= =?UTF-8?q?=E5=B1=82=E5=8E=9A=E5=BA=A6=E5=8F=8A=E5=8E=8B=E7=BC=A9=E7=B3=BB?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E8=87=AA=E5=8A=A8=E6=8B=9F=E5=90=88=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除厚度、综合压缩系数 Ct、岩石压缩系数 Cf 的拟合控件、选择标志、上下界及配置读写代码 - 同步精简 LM、PSO 参数向量,调整剩余参数索引、初值读取和拟合结果回写 - 更新拟合记录字段及元数据版本,保持参数名称与索引一致 - 保留厚度、Ct、Cf 作为求解器和代理模型的固定输入,拟合过程不再调整 --- .../nmCalculation/nmCalculationAutoFitLM.h | 4 +- .../nmCalculation/nmCalculationAutoFitPSO.h | 13 +- Include/nmNum/nmData/nmDataAutomaticFitting.h | 39 --- Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h | 3 - .../nmCalculation/nmCalculationAutoFitLM.cpp | 119 +++------ .../nmCalculation/nmCalculationAutoFitPSO.cpp | 97 ++----- Src/nmNum/nmData/nmDataAutomaticFitting.cpp | 81 ------ Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp | 241 +++++------------- 8 files changed, 133 insertions(+), 464 deletions(-) diff --git a/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h b/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h index 8473904..f9fce51 100644 --- a/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h +++ b/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h @@ -165,8 +165,8 @@ private: QVector > m_userInitialLogLogData; AutoFitObjectiveBreakdownLM m_userInitialObjectiveBreakdown; - // 参数索引:0 k,1 skin,2 wellboreC,3 phi,4 h,5 Ct, - // 6 Cf,7 Swi,8 Dfc,9 fractureHalfLength。 + // 参数索引:0 k,1 skin,2 wellboreC,3 phi,4 Swi, + // 5 Dfc,6 fractureHalfLength。 QVector m_parameterSelected; QVector m_parameterLower; QVector m_parameterUpper; diff --git a/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h b/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h index f4e9b9b..00ea3c9 100644 --- a/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h +++ b/Include/nmNum/nmCalculation/nmCalculationAutoFitPSO.h @@ -20,7 +20,7 @@ class QProcess; // PSO粒子结构 // 这里的 position / velocity / bestPosition 只保存“用户勾选参与拟合的参数”, -// 不是完整的 11 个储层/井筒参数。完整参数向量会在写 trace 或调用代理模型时 +// 拟合参数为 k/skin/wellboreC/phi/Swi。包含固定储层输入的物理参数向量在写 trace 或调用代理模型时 // 通过 buildTraceParameterVector() 重新组装。 // // surrogate* 和 screeningDecision 是 PSO 加速筛选的辅助字段。真实 pbest / gbest @@ -295,13 +295,12 @@ private: // // 参数索引约定: // 0 k 渗透率;1 skin 表皮系数;2 wellboreC 井筒储集; - // 3 phi 孔隙度;4 h 储层厚度;5 Ct 综合压缩系数; - // 6 Cf 岩石压缩系数;7 Swi 初始含水饱和度。 + // 3 phi 孔隙度;4 Swi 初始含水饱和度。 // m_enabledParamIndices 保存被用户勾选的参数索引,粒子的 position 维度与它一致。 - QVector m_parameterSelected; // 完整 8 个参数是否被用户勾选参与拟合。 - QVector m_parameterLower; // 完整 8 个参数的搜索下界。 - QVector m_parameterUpper; // 完整 8 个参数的搜索上界。 - QVector m_enabledParamIndices; // 被勾选参数在完整 8 维体系中的索引。 + QVector m_parameterSelected; // 0 k,1 skin,2 wellboreC,3 phi,4 Swi。 + QVector m_parameterLower; // 5 个拟合参数的搜索下界。 + QVector m_parameterUpper; // 5 个拟合参数的搜索上界。 + QVector m_enabledParamIndices; // 被勾选参数在 5 维拟合参数中的索引。 QVector > m_targetLogLogData; // 目标井 history log-log 曲线:time/pressure/derivative。 QString m_targetWellName; // 目标井名称;读写井参数和读取模拟曲线都依赖它。 diff --git a/Include/nmNum/nmData/nmDataAutomaticFitting.h b/Include/nmNum/nmData/nmDataAutomaticFitting.h index 98829eb..d8a3e52 100644 --- a/Include/nmNum/nmData/nmDataAutomaticFitting.h +++ b/Include/nmNum/nmData/nmDataAutomaticFitting.h @@ -47,27 +47,6 @@ public: nmDataAttribute& getPorosityMin(); void setPorosityMin(const nmDataAttribute& porosityMin); - // Getter and Setter for thicknessMax - nmDataAttribute& getThicknessMax(); - void setThicknessMax(const nmDataAttribute& thicknessMax); - // Getter and Setter for thicknessMin - nmDataAttribute& getThicknessMin(); - void setThicknessMin(const nmDataAttribute& thicknessMin); - - // Getter and Setter for ctMax - nmDataAttribute& getCtMax(); - void setCtMax(const nmDataAttribute& ctMax); - // Getter and Setter for ctMin - nmDataAttribute& getCtMin(); - void setCtMin(const nmDataAttribute& ctMin); - - // Getter and Setter for cfMax - nmDataAttribute& getCfMax(); - void setCfMax(const nmDataAttribute& cfMax); - // Getter and Setter for cfMin - nmDataAttribute& getCfMin(); - void setCfMin(const nmDataAttribute& cfMin); - // Getter and Setter for swiMax nmDataAttribute& getSwiMax(); void setSwiMax(const nmDataAttribute& swiMax); @@ -116,15 +95,6 @@ public: bool getPorositySelected() const; void setPorositySelected(bool selected); - bool getThicknessSelected() const; - void setThicknessSelected(bool selected); - - bool getCtSelected() const; - void setCtSelected(bool selected); - - bool getCfSelected() const; - void setCfSelected(bool selected); - bool getSwiSelected() const; void setSwiSelected(bool selected); @@ -140,9 +110,6 @@ private: nmDataAttribute m_skinMax; nmDataAttribute m_wellboreStorageMax; nmDataAttribute m_porosityMax; - nmDataAttribute m_thicknessMax; - nmDataAttribute m_ctMax; - nmDataAttribute m_cfMax; nmDataAttribute m_swiMax; nmDataAttribute m_fractureConductivityMax; nmDataAttribute m_fractureHalfLengthMax; @@ -152,9 +119,6 @@ private: nmDataAttribute m_skinMin; nmDataAttribute m_wellboreStorageMin; nmDataAttribute m_porosityMin; - nmDataAttribute m_thicknessMin; - nmDataAttribute m_ctMin; - nmDataAttribute m_cfMin; nmDataAttribute m_swiMin; nmDataAttribute m_fractureConductivityMin; nmDataAttribute m_fractureHalfLengthMin; @@ -170,9 +134,6 @@ private: bool m_skinSelected; // 是否选择表皮系数进行拟合 bool m_wellboreStorageSelected; // 是否选择井筒储集系数进行拟合 bool m_porositySelected; // 是否选择孔隙度进行拟合 - bool m_thicknessSelected; // 是否选择储层厚度进行拟合 - bool m_ctSelected; // 是否选择综合压缩系数进行拟合 - bool m_cfSelected; // 是否选择岩石压缩系数进行拟合 bool m_swiSelected; // 是否选择初始含水饱和度进行拟合 bool m_fractureConductivitySelected; // 是否选择裂缝导流能力进行拟合 bool m_fractureHalfLengthSelected; // 是否选择裂缝半长进行拟合 diff --git a/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h b/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h index 8d10dc8..56e21a2 100644 --- a/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h +++ b/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h @@ -88,9 +88,6 @@ private: QCheckBox* m_sCheckBox; // 表皮系数 QCheckBox* m_cCheckBox; // 井筒储集系数 QCheckBox* m_phiCheckBox; // 孔隙度 - QCheckBox* m_hCheckBox; // 储层厚度 - QCheckBox* m_ctCheckBox; // 综合压缩系数 - QCheckBox* m_cfCheckBox; // 岩石压缩系数 QCheckBox* m_swiCheckBox; // 初始含水饱和度 QCheckBox* m_dfcCheckBox; // 裂缝导流能力 QCheckBox* m_fractureHalfLengthCheckBox; // 裂缝半长 diff --git a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp index 48f40da..c3f3c41 100644 --- a/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationAutoFitLM.cpp @@ -129,11 +129,11 @@ static QString jsonStringArray(const QStringList& values) } // 信赖域搜索统一在 [0, 1] 内部坐标工作。正值参数使用对数坐标,使内部相同步长 -// 表示近似相同的相对变化,避免 k、C、Ct、Cf 等跨数量级参数被线性尺度支配; +// 表示近似相同的相对变化,避免 k、C、Dfc 等跨数量级参数被线性尺度支配; // skin 可为负数、Swi 的物理意义是线性比例,因此二者保持有界线性坐标。 static bool useTrustRegionLogScale(int parameterIndex, double lower, double upper) { - return parameterIndex != 1 && parameterIndex != 7 && + return parameterIndex != 1 && parameterIndex != 4 && lower > 0.0 && upper > lower; } @@ -284,7 +284,7 @@ static int trustRegionDominantComponent( } // 求解选中参数对应的阻尼正规方程。上下和左右诊断量保留方向;形状没有 -// 天然正负,因此使用 shapeLoss 对参数的局部导数。参数最多八维,使用带 +// 天然正负,因此使用 shapeLoss 对参数的局部导数。参数最多七维,使用带 // 部分主元的高斯消元即可处理该小矩阵,并在主元退化时明确返回失败。 static bool solveTrustRegionLinearSystem( QVector > matrix, @@ -453,9 +453,6 @@ static QStringList traceParameterNames() << "skin" << "wellboreC" << "phi" - << "h" - << "Ct" - << "Cf" << "Swi" << "Dfc" << "fractureHalfLength"; @@ -743,9 +740,6 @@ void nmCalculationAutoFitLM::writeTraceHeader() << "skin" << "wellboreC" << "phi" - << "h" - << "Ct" - << "Cf" << "Swi" << "Dfc" << "fractureHalfLength" @@ -804,7 +798,7 @@ void nmCalculationAutoFitLM::writeTraceMetaFile() QTextStream out(&metaFile); out << "{\n"; - out << " \"schema_version\": 1,\n"; + out << " \"schema_version\": 2,\n"; out << " \"trace_type\": \"finite_difference_lm_trust_region\",\n"; out << " \"run_id\": " << jsonEscape(m_traceRunId) << ",\n"; out << " \"created_at\": " @@ -861,7 +855,7 @@ void nmCalculationAutoFitLM::writeTraceRow( << QString::number(iteration) << QString::number(parameterIndex) << csvEscape(phase); - for(int i = 0; i < 10; ++i) { + for(int i = 0; i < 7; ++i) { cols << traceParamAt(fullParams, i); } cols << traceNumber(solverObjective) @@ -919,10 +913,10 @@ void nmCalculationAutoFitLM::emitRunSummary(bool success, StopReasonLM finalReas QVector nmCalculationAutoFitLM::buildTraceParameterVector(const QVector& selectedParameters) const { - // 将 LM 内部使用的“启用参数向量”还原成完整 10 维参数向量。 + // 将 LM 内部使用的“启用参数向量”还原成完整 7 维参数向量。 // 未启用的参数从当前 DataManager 读取,启用的参数用 selectedParameters 覆盖。 // trace CSV 和 meta 使用该完整向量记录一次候选评价。 - QVector fullParams(10, 0.0); + QVector fullParams(7, 0.0); nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); @@ -930,10 +924,7 @@ QVector nmCalculationAutoFitLM::buildTraceParameterVector(const QVector< nmDataReservoir reservoirData = dataManager->getReservoirDataCopy(); fullParams[0] = reservoirData.getPermeability().getValue().toDouble(); fullParams[3] = reservoirData.getPorosity().getValue().toDouble(); - fullParams[4] = reservoirData.getThickness().getValue().toDouble(); - fullParams[5] = reservoirData.getCt().getValue().toDouble(); - fullParams[6] = reservoirData.getCf().getValue().toDouble(); - fullParams[7] = reservoirData.getSwi().getValue().toDouble(); + fullParams[4] = reservoirData.getSwi().getValue().toDouble(); nmDataWellBase* pTargetWell = dataManager->findWellByName(m_targetWellName); @@ -949,15 +940,15 @@ QVector nmCalculationAutoFitLM::buildTraceParameterVector(const QVector< nmDataVerticalFracturedWell* fracturedWell = dynamic_cast(pTargetWell); if(fracturedWell) { - fullParams[8] = fracturedWell->getDfc().getValue().toDouble(); - fullParams[9] = fracturedWell->getFractureHalfLength().getValue().toDouble(); + fullParams[5] = fracturedWell->getDfc().getValue().toDouble(); + fullParams[6] = fracturedWell->getFractureHalfLength().getValue().toDouble(); } } else if(pTargetWell->getWellType() == NM_WELL_MODEL::Horizontal_Fractured_Well) { nmDataHorizontalFracturedWell* fracturedWell = dynamic_cast(pTargetWell); if(fracturedWell) { - fullParams[8] = fracturedWell->getDfc().getValue().toDouble(); - fullParams[9] = fracturedWell->getFractureHalfLength().getValue().toDouble(); + fullParams[5] = fracturedWell->getDfc().getValue().toDouble(); + fullParams[6] = fracturedWell->getFractureHalfLength().getValue().toDouble(); } } } @@ -1008,28 +999,25 @@ void nmCalculationAutoFitLM::loadParameterBounds() // 读取用户勾选的拟合参数及上下界。 // // 这里构建三个核心数组: - // - m_parameterSelected[10]:完整参数体系中每个参数是否参与拟合; - // - m_parameterLower/Upper[10]:完整参数体系的搜索上下界; + // - m_parameterSelected[7]:完整参数体系中每个参数是否参与拟合; + // - m_parameterLower/Upper[7]:完整参数体系的搜索上下界; // - m_enabledParamIndices:把粒子内部紧凑向量映射回完整参数索引。 nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); nmDataAutomaticFitting fittingData = dataManager->getAutomaticFittingDataCopy(); // 获取参数选择状态 - m_parameterSelected.resize(10); + m_parameterSelected.resize(7); m_parameterSelected[0] = fittingData.getPermeabilitySelected(); m_parameterSelected[1] = fittingData.getSkinSelected(); m_parameterSelected[2] = fittingData.getWellboreStorageSelected(); m_parameterSelected[3] = fittingData.getPorositySelected(); - m_parameterSelected[4] = fittingData.getThicknessSelected(); - m_parameterSelected[5] = fittingData.getCtSelected(); - m_parameterSelected[6] = fittingData.getCfSelected(); - m_parameterSelected[7] = fittingData.getSwiSelected(); - m_parameterSelected[8] = fittingData.getFractureConductivitySelected(); - m_parameterSelected[9] = fittingData.getFractureHalfLengthSelected(); + m_parameterSelected[4] = fittingData.getSwiSelected(); + m_parameterSelected[5] = fittingData.getFractureConductivitySelected(); + m_parameterSelected[6] = fittingData.getFractureHalfLengthSelected(); // 获取参数边界 - m_parameterLower.resize(10); - m_parameterUpper.resize(10); + m_parameterLower.resize(7); + m_parameterUpper.resize(7); m_parameterLower[0] = fittingData.getPermeabilityMin().getValue().toDouble(); m_parameterUpper[0] = fittingData.getPermeabilityMax().getValue().toDouble(); @@ -1043,23 +1031,14 @@ void nmCalculationAutoFitLM::loadParameterBounds() m_parameterLower[3] = fittingData.getPorosityMin().getValue().toDouble(); m_parameterUpper[3] = fittingData.getPorosityMax().getValue().toDouble(); - m_parameterLower[4] = fittingData.getThicknessMin().getValue().toDouble(); - m_parameterUpper[4] = fittingData.getThicknessMax().getValue().toDouble(); + m_parameterLower[4] = fittingData.getSwiMin().getValue().toDouble(); + m_parameterUpper[4] = fittingData.getSwiMax().getValue().toDouble(); - m_parameterLower[5] = fittingData.getCtMin().getValue().toDouble(); - m_parameterUpper[5] = fittingData.getCtMax().getValue().toDouble(); + m_parameterLower[5] = fittingData.getFractureConductivityMin().getValue().toDouble(); + m_parameterUpper[5] = fittingData.getFractureConductivityMax().getValue().toDouble(); - m_parameterLower[6] = fittingData.getCfMin().getValue().toDouble(); - m_parameterUpper[6] = fittingData.getCfMax().getValue().toDouble(); - - m_parameterLower[7] = fittingData.getSwiMin().getValue().toDouble(); - m_parameterUpper[7] = fittingData.getSwiMax().getValue().toDouble(); - - m_parameterLower[8] = fittingData.getFractureConductivityMin().getValue().toDouble(); - m_parameterUpper[8] = fittingData.getFractureConductivityMax().getValue().toDouble(); - - m_parameterLower[9] = fittingData.getFractureHalfLengthMin().getValue().toDouble(); - m_parameterUpper[9] = fittingData.getFractureHalfLengthMax().getValue().toDouble(); + m_parameterLower[6] = fittingData.getFractureHalfLengthMin().getValue().toDouble(); + m_parameterUpper[6] = fittingData.getFractureHalfLengthMax().getValue().toDouble(); // 更新启用参数索引 m_enabledParamIndices.clear(); @@ -1256,8 +1235,8 @@ bool nmCalculationAutoFitLM::startAutoFitting() // 裂缝参数会改变网格输入;标记失效后,最终求解任务会基于新快照重建网格。 const bool fractureGridParameterSelected = - (m_parameterSelected.size() > 8 && m_parameterSelected[8]) || - (m_parameterSelected.size() > 9 && m_parameterSelected[9]); + (m_parameterSelected.size() > 5 && m_parameterSelected[5]) || + (m_parameterSelected.size() > 6 && m_parameterSelected[6]); if(fractureGridParameterSelected) { nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); @@ -1427,23 +1406,11 @@ void nmCalculationAutoFitLM::extractUserInitialValues() initialValue = reservoirData.getPorosity().getValue().toDouble(); break; - case 4: // 储层厚度 - initialValue = reservoirData.getThickness().getValue().toDouble(); - break; - - case 5: // 综合压缩系数 - initialValue = reservoirData.getCt().getValue().toDouble(); - break; - - case 6: // 岩石压缩系数 - initialValue = reservoirData.getCf().getValue().toDouble(); - break; - - case 7: // 初始含水饱和度 + case 4: // 初始含水饱和度 initialValue = reservoirData.getSwi().getValue().toDouble(); break; - case 8: // 裂缝导流能力 + case 5: // 裂缝导流能力 if(pTargetWell && pTargetWell->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) { nmDataVerticalFracturedWell* fracturedWell = dynamic_cast(pTargetWell); @@ -1459,7 +1426,7 @@ void nmCalculationAutoFitLM::extractUserInitialValues() } break; - case 9: // 裂缝半长 + case 6: // 裂缝半长 if(pTargetWell && pTargetWell->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) { nmDataVerticalFracturedWell* fracturedWell = dynamic_cast(pTargetWell); @@ -2553,8 +2520,8 @@ double nmCalculationAutoFitLM::evaluateFitness(const QVector& parameters // Dfc 和裂缝半长属于网格输入。标记网格失效,使下一次任务基于当前参数快照重建。 const bool fractureGridParameterSelected = - (m_parameterSelected.size() > 8 && m_parameterSelected[8]) || - (m_parameterSelected.size() > 9 && m_parameterSelected[9]); + (m_parameterSelected.size() > 5 && m_parameterSelected[5]) || + (m_parameterSelected.size() > 6 && m_parameterSelected[6]); if(fractureGridParameterSelected) { dataManager->invalidatePebiGrid(); } @@ -2721,7 +2688,7 @@ void nmCalculationAutoFitLM::updateReservoirParameters(const QVector& pa nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); nmDataReservoir reservoirData = dataManager->getReservoirDataCopy(); - // paramIndex 是粒子 position 中的索引;i 是完整 10 个参数体系中的索引。 + // paramIndex 是粒子 position 中的索引;i 是完整 7 个参数体系中的索引。 // 只有 m_parameterSelected[i] 为 true 时,才从 parameters 中消费一个值。 int paramIndex = 0; @@ -2738,19 +2705,7 @@ void nmCalculationAutoFitLM::updateReservoirParameters(const QVector& pa reservoirData.getPorosity().setValue(value); break; - case 4: // 储层厚度 - reservoirData.getThickness().setValue(value); - break; - - case 5: // 综合压缩系数 - reservoirData.getCt().setValue(value); - break; - - case 6: // 岩石压缩系数 - reservoirData.getCf().setValue(value); - break; - - case 7: // 初始含水饱和度 + case 4: // 初始含水饱和度 reservoirData.getSwi().setValue(value); break; } @@ -2828,7 +2783,7 @@ void nmCalculationAutoFitLM::updateWellParameters(const QVector& paramet } break; - case 8: { // 裂缝导流能力 + case 5: { // 裂缝导流能力 if(pVerticalFracturedWell || pHorizontalFracturedWell) { dfcAttr.setValue(value); updateDfc = true; @@ -2836,7 +2791,7 @@ void nmCalculationAutoFitLM::updateWellParameters(const QVector& paramet } break; - case 9: { // 裂缝半长 + case 6: { // 裂缝半长 if(pVerticalFracturedWell || pHorizontalFracturedWell) { fractureHalfLengthAttr.setValue(value); updateFractureHalfLength = true; diff --git a/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp b/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp index 95badd3..dfb1ab1 100644 --- a/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationAutoFitPSO.cpp @@ -426,16 +426,13 @@ static QString findExecutableInPath(const QString& executableName) static QStringList traceParameterNames() { - // trace 和 trace meta 使用的完整参数名顺序。 - // 这个顺序必须与 buildTraceParameterVector() 和 m_parameterSelected 的 0-7 索引一致。 + // 拟合参数顺序与 m_parameterSelected 的 0-4 索引一致。 + // 代理输入仍使用 buildTraceParameterVector() 的物理参数顺序。 QStringList names; names << "k" << "skin" << "wellboreC" << "phi" - << "h" - << "Ct" - << "Cf" << "Swi"; return names; } @@ -979,7 +976,9 @@ bool nmCalculationAutoFitPSO::writeTraceMetaFile(const QString& filePath) enabledNames << ((paramIndex >= 0 && paramIndex < parameterNames.size()) ? parameterNames[paramIndex] : QString::number(paramIndex)); } - QVector initialFullParams = buildTraceParameterVector(m_initialValues); + QVector initialPhysicalParams = buildTraceParameterVector(m_initialValues); + QVector initialFullParams = initialPhysicalParams.mid(0, 4); + initialFullParams.append(initialPhysicalParams[7]); // Swi 在物理输入中的位置不变。 QVector targetTime = m_targetLogLogData.size() > 0 ? m_targetLogLogData[0] : QVector(); QVector targetPressure = m_targetLogLogData.size() > 1 ? m_targetLogLogData[1] : QVector(); QVector targetDerivative = m_targetLogLogData.size() > 2 ? m_targetLogLogData[2] : QVector(); @@ -987,7 +986,7 @@ bool nmCalculationAutoFitPSO::writeTraceMetaFile(const QString& filePath) QTextStream out(&metaFile); out << "{\n"; - out << " \"schema_version\": 1,\n"; + out << " \"schema_version\": 2,\n"; out << " \"trace_type\": \"pso_baseline_replay_meta\",\n"; out << " \"run_id\": " << jsonEscape(m_traceRunId) << ",\n"; out << " \"created_at\": " << jsonEscape(QDateTime::currentDateTime().toString(Qt::ISODate)) << ",\n"; @@ -1046,8 +1045,8 @@ bool nmCalculationAutoFitPSO::writeTraceMetaFile(const QString& filePath) QVector nmCalculationAutoFitPSO::buildTraceParameterVector(const QVector& selectedParameters) const { - // 将粒子内部使用的“启用参数向量”还原成完整 8 维参数向量。 - // 未启用的参数从当前 DataManager 读取,启用的参数用 selectedParameters 覆盖。 + // 代理输入保留 k/skin/wellboreC/phi/h/Ct/Cf/Swi 的 8 维物理参数顺序。 + // h/Ct/Cf 始终读取储层固定值,仅用候选值覆盖剩余拟合参数。 // trace CSV、候选 CSV、代理训练域检查都需要这个完整向量。 QVector fullParams(8, 0.0); @@ -1073,8 +1072,9 @@ QVector nmCalculationAutoFitPSO::buildTraceParameterVector(const QVector for(int i = 0; i < selectedParameters.size() && i < m_enabledParamIndices.size(); ++i) { int paramIndex = m_enabledParamIndices[i]; - if(paramIndex >= 0 && paramIndex < fullParams.size()) { - fullParams[paramIndex] = selectedParameters[i]; + if(paramIndex >= 0 && paramIndex < m_parameterSelected.size()) { + const int physicalIndex = paramIndex == 4 ? 7 : paramIndex; + fullParams[physicalIndex] = selectedParameters[i]; } } @@ -1993,14 +1993,9 @@ bool nmCalculationAutoFitPSO::isSurrogateRunContextSupported(QString* reason) co return false; } - // 参数门控:只有训练数据中 Cf 实际变化的 T2/T4 允许 Cf 参与拟合。 - // 用户勾选其它参数时,代理无法可靠反映这些参数变化,直接禁用代理筛选。 + // 代理支持拟合 k/skin/wellboreC/phi;Swi 不在训练输入集中。 QVector allowedParamIndices; - allowedParamIndices << 0 << 1 << 2 << 3 << 4; - - if(parameterDomain.variableCf) { - allowedParamIndices << 6; - } + allowedParamIndices << 0 << 1 << 2 << 3; for(int i = 0; i < m_enabledParamIndices.size(); ++i) { if(!allowedParamIndices.contains(m_enabledParamIndices[i])) { @@ -2714,26 +2709,23 @@ void nmCalculationAutoFitPSO::loadParameterBounds() // 读取用户勾选的拟合参数及上下界。 // // 这里构建三个核心数组: - // - m_parameterSelected[8]:完整参数体系中每个参数是否参与拟合; - // - m_parameterLower/Upper[8]:完整参数体系的搜索上下界; + // - m_parameterSelected[5]:完整参数体系中每个参数是否参与拟合; + // - m_parameterLower/Upper[5]:完整参数体系的搜索上下界; // - m_enabledParamIndices:把粒子内部紧凑向量映射回完整参数索引。 nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); nmDataAutomaticFitting fittingData = dataManager->getAutomaticFittingDataCopy(); // 获取参数选择状态 - m_parameterSelected.resize(8); + m_parameterSelected.resize(5); m_parameterSelected[0] = fittingData.getPermeabilitySelected(); m_parameterSelected[1] = fittingData.getSkinSelected(); m_parameterSelected[2] = fittingData.getWellboreStorageSelected(); m_parameterSelected[3] = fittingData.getPorositySelected(); - m_parameterSelected[4] = fittingData.getThicknessSelected(); - m_parameterSelected[5] = fittingData.getCtSelected(); - m_parameterSelected[6] = fittingData.getCfSelected(); - m_parameterSelected[7] = fittingData.getSwiSelected(); + m_parameterSelected[4] = fittingData.getSwiSelected(); // 获取参数边界 - m_parameterLower.resize(8); - m_parameterUpper.resize(8); + m_parameterLower.resize(5); + m_parameterUpper.resize(5); m_parameterLower[0] = fittingData.getPermeabilityMin().getValue().toDouble(); m_parameterUpper[0] = fittingData.getPermeabilityMax().getValue().toDouble(); @@ -2747,17 +2739,8 @@ void nmCalculationAutoFitPSO::loadParameterBounds() m_parameterLower[3] = fittingData.getPorosityMin().getValue().toDouble(); m_parameterUpper[3] = fittingData.getPorosityMax().getValue().toDouble(); - m_parameterLower[4] = fittingData.getThicknessMin().getValue().toDouble(); - m_parameterUpper[4] = fittingData.getThicknessMax().getValue().toDouble(); - - m_parameterLower[5] = fittingData.getCtMin().getValue().toDouble(); - m_parameterUpper[5] = fittingData.getCtMax().getValue().toDouble(); - - m_parameterLower[6] = fittingData.getCfMin().getValue().toDouble(); - m_parameterUpper[6] = fittingData.getCfMax().getValue().toDouble(); - - m_parameterLower[7] = fittingData.getSwiMin().getValue().toDouble(); - m_parameterUpper[7] = fittingData.getSwiMax().getValue().toDouble(); + m_parameterLower[4] = fittingData.getSwiMin().getValue().toDouble(); + m_parameterUpper[4] = fittingData.getSwiMax().getValue().toDouble(); // 更新启用参数索引 m_enabledParamIndices.clear(); @@ -3400,19 +3383,7 @@ void nmCalculationAutoFitPSO::extractUserInitialValues() initialValue = reservoirData.getPorosity().getValue().toDouble(); break; - case 4: // 储层厚度 - initialValue = reservoirData.getThickness().getValue().toDouble(); - break; - - case 5: // 综合压缩系数 - initialValue = reservoirData.getCt().getValue().toDouble(); - break; - - case 6: // 岩石压缩系数 - initialValue = reservoirData.getCf().getValue().toDouble(); - break; - - case 7: // 初始含水饱和度 + case 4: // 初始含水饱和度 initialValue = reservoirData.getSwi().getValue().toDouble(); break; } @@ -4196,7 +4167,7 @@ void nmCalculationAutoFitPSO::updateReservoirParameters(const QVector& p nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance(); nmDataReservoir reservoirData = dataManager->getReservoirDataCopy(); - // paramIndex 是粒子 position 中的索引;i 是完整 8 个参数体系中的索引。 + // paramIndex 是粒子 position 中的索引;i 是完整 5 个拟合参数体系中的索引。 // 只有 m_parameterSelected[i] 为 true 时,才从 parameters 中消费一个值。 int paramIndex = 0; @@ -4213,19 +4184,7 @@ void nmCalculationAutoFitPSO::updateReservoirParameters(const QVector& p reservoirData.getPorosity().setValue(value); break; - case 4: // 储层厚度 - reservoirData.getThickness().setValue(value); - break; - - case 5: // 综合压缩系数 - reservoirData.getCt().setValue(value); - break; - - case 6: // 岩石压缩系数 - reservoirData.getCf().setValue(value); - break; - - case 7: // 初始含水饱和度 + case 4: // 初始含水饱和度 reservoirData.getSwi().setValue(value); break; } @@ -4657,14 +4616,6 @@ bool nmCalculationAutoFitPSO::validateParameters(const QVector& paramete return false; } - break; - - case 5: // 综合压缩系数:必须大于零 - if(value <= 1e-8) { - DEBUG_OUT(QString("Rejecting near-zero total compressibility: %1").arg(value)); - return false; - } - break; } } diff --git a/Src/nmNum/nmData/nmDataAutomaticFitting.cpp b/Src/nmNum/nmData/nmDataAutomaticFitting.cpp index 45dd167..e6639a0 100644 --- a/Src/nmNum/nmData/nmDataAutomaticFitting.cpp +++ b/Src/nmNum/nmData/nmDataAutomaticFitting.cpp @@ -7,9 +7,6 @@ nmDataAutomaticFitting::nmDataAutomaticFitting() m_skinSelected = true; // 默认选中 m_wellboreStorageSelected = true; // 默认选中 m_porositySelected = true; // 默认选中 - m_thicknessSelected = true; // 默认选中 - m_ctSelected = true; // 默认选中 - m_cfSelected = false; // 默认不选中 m_swiSelected = false; // 默认不选中 m_fractureConductivitySelected = false; // 仅压裂井可用,默认不选中 m_fractureHalfLengthSelected = false; // 仅压裂井可用,默认不选中 @@ -19,9 +16,6 @@ nmDataAutomaticFitting::nmDataAutomaticFitting() m_skinMax = nmDataAttribute("Skin Max", QVariant(), ""); m_wellboreStorageMax = nmDataAttribute("Wellbore Storage Max", QVariant(), "m^3/MPa"); m_porosityMax = nmDataAttribute("Porosity Max", QVariant(), ""); - m_thicknessMax = nmDataAttribute("Thickness Max", QVariant(), "m"); - m_ctMax = nmDataAttribute("Ct Max", QVariant(), ""); - m_cfMax = nmDataAttribute("Cf Max", QVariant(), ""); m_swiMax = nmDataAttribute("Swi Max", QVariant(), ""); m_fractureConductivityMax = nmDataAttribute("Fracture Conductivity Max", QVariant(), "md.m"); m_fractureHalfLengthMax = nmDataAttribute("Fracture Half Length Max", QVariant(), "m"); @@ -30,9 +24,6 @@ nmDataAutomaticFitting::nmDataAutomaticFitting() m_skinMin = nmDataAttribute("Skin Min", QVariant(), ""); m_wellboreStorageMin = nmDataAttribute("Wellbore Storage Min", QVariant(), "m^3/MPa"); m_porosityMin = nmDataAttribute("Porosity Min", QVariant(), ""); - m_thicknessMin = nmDataAttribute("Thickness Min", QVariant(), "m"); - m_ctMin = nmDataAttribute("Ct Min", QVariant(), ""); - m_cfMin = nmDataAttribute("Cf Min", QVariant(), ""); m_swiMin = nmDataAttribute("Swi Min", QVariant(), ""); m_fractureConductivityMin = nmDataAttribute("Fracture Conductivity Min", QVariant(), "mD.m"); m_fractureHalfLengthMin = nmDataAttribute("Fracture Half Length Min", QVariant(), "m"); @@ -61,9 +52,6 @@ nmDataAutomaticFitting& nmDataAutomaticFitting::operator=(const nmDataAutomaticF m_skinSelected = other.m_skinSelected; m_wellboreStorageSelected = other.m_wellboreStorageSelected; m_porositySelected = other.m_porositySelected; - m_thicknessSelected = other.m_thicknessSelected; - m_ctSelected = other.m_ctSelected; - m_cfSelected = other.m_cfSelected; m_swiSelected = other.m_swiSelected; m_fractureConductivitySelected = other.m_fractureConductivitySelected; m_fractureHalfLengthSelected = other.m_fractureHalfLengthSelected; @@ -73,9 +61,6 @@ nmDataAutomaticFitting& nmDataAutomaticFitting::operator=(const nmDataAutomaticF m_skinMax = other.m_skinMax; m_wellboreStorageMax = other.m_wellboreStorageMax; m_porosityMax = other.m_porosityMax; - m_thicknessMax = other.m_thicknessMax; - m_ctMax = other.m_ctMax; - m_cfMax = other.m_cfMax; m_swiMax = other.m_swiMax; m_fractureConductivityMax = other.m_fractureConductivityMax; m_fractureHalfLengthMax = other.m_fractureHalfLengthMax; @@ -85,9 +70,6 @@ nmDataAutomaticFitting& nmDataAutomaticFitting::operator=(const nmDataAutomaticF m_skinMin = other.m_skinMin; m_wellboreStorageMin = other.m_wellboreStorageMin; m_porosityMin = other.m_porosityMin; - m_thicknessMin = other.m_thicknessMin; - m_ctMin = other.m_ctMin; - m_cfMin = other.m_cfMin; m_swiMin = other.m_swiMin; m_fractureConductivityMin = other.m_fractureConductivityMin; m_fractureHalfLengthMin = other.m_fractureHalfLengthMin; @@ -110,9 +92,6 @@ rapidjson::Value nmDataAutomaticFitting::ToJsonValue(rapidjson::Document::Alloca fittingObject.AddMember("SkinSelected", m_skinSelected, allocator); fittingObject.AddMember("WellboreStorageSelected", m_wellboreStorageSelected, allocator); fittingObject.AddMember("PorositySelected", m_porositySelected, allocator); - fittingObject.AddMember("ThicknessSelected", m_thicknessSelected, allocator); - fittingObject.AddMember("CtSelected", m_ctSelected, allocator); - fittingObject.AddMember("CfSelected", m_cfSelected, allocator); fittingObject.AddMember("SwiSelected", m_swiSelected, allocator); fittingObject.AddMember("FractureConductivitySelected", m_fractureConductivitySelected, allocator); fittingObject.AddMember("FractureHalfLengthSelected", m_fractureHalfLengthSelected, allocator); @@ -122,9 +101,6 @@ rapidjson::Value nmDataAutomaticFitting::ToJsonValue(rapidjson::Document::Alloca fittingObject.AddMember("SkinMax", m_skinMax.ToJsonValue(allocator), allocator); fittingObject.AddMember("WellboreStorageMax", m_wellboreStorageMax.ToJsonValue(allocator), allocator); fittingObject.AddMember("PorosityMax", m_porosityMax.ToJsonValue(allocator), allocator); - fittingObject.AddMember("ThicknessMax", m_thicknessMax.ToJsonValue(allocator), allocator); - fittingObject.AddMember("CtMax", m_ctMax.ToJsonValue(allocator), allocator); - fittingObject.AddMember("CfMax", m_cfMax.ToJsonValue(allocator), allocator); fittingObject.AddMember("SwiMax", m_swiMax.ToJsonValue(allocator), allocator); fittingObject.AddMember("FractureConductivityMax", m_fractureConductivityMax.ToJsonValue(allocator), allocator); fittingObject.AddMember("FractureHalfLengthMax", m_fractureHalfLengthMax.ToJsonValue(allocator), allocator); @@ -134,9 +110,6 @@ rapidjson::Value nmDataAutomaticFitting::ToJsonValue(rapidjson::Document::Alloca fittingObject.AddMember("SkinMin", m_skinMin.ToJsonValue(allocator), allocator); fittingObject.AddMember("WellboreStorageMin", m_wellboreStorageMin.ToJsonValue(allocator), allocator); fittingObject.AddMember("PorosityMin", m_porosityMin.ToJsonValue(allocator), allocator); - fittingObject.AddMember("ThicknessMin", m_thicknessMin.ToJsonValue(allocator), allocator); - fittingObject.AddMember("CtMin", m_ctMin.ToJsonValue(allocator), allocator); - fittingObject.AddMember("CfMin", m_cfMin.ToJsonValue(allocator), allocator); fittingObject.AddMember("SwiMin", m_swiMin.ToJsonValue(allocator), allocator); fittingObject.AddMember("FractureConductivityMin", m_fractureConductivityMin.ToJsonValue(allocator), allocator); fittingObject.AddMember("FractureHalfLengthMin", m_fractureHalfLengthMin.ToJsonValue(allocator), allocator); @@ -165,15 +138,6 @@ void nmDataAutomaticFitting::FromJsonValue(const rapidjson::Value& jsonValue) if (jsonValue.HasMember("PorositySelected") && jsonValue["PorositySelected"].IsBool()) { m_porositySelected = jsonValue["PorositySelected"].GetBool(); } - if (jsonValue.HasMember("ThicknessSelected") && jsonValue["ThicknessSelected"].IsBool()) { - m_thicknessSelected = jsonValue["ThicknessSelected"].GetBool(); - } - if (jsonValue.HasMember("CtSelected") && jsonValue["CtSelected"].IsBool()) { - m_ctSelected = jsonValue["CtSelected"].GetBool(); - } - if (jsonValue.HasMember("CfSelected") && jsonValue["CfSelected"].IsBool()) { - m_cfSelected = jsonValue["CfSelected"].GetBool(); - } if (jsonValue.HasMember("SwiSelected") && jsonValue["SwiSelected"].IsBool()) { m_swiSelected = jsonValue["SwiSelected"].GetBool(); } @@ -199,15 +163,6 @@ void nmDataAutomaticFitting::FromJsonValue(const rapidjson::Value& jsonValue) if (jsonValue.HasMember("PorosityMax") && jsonValue["PorosityMax"].IsObject()) { m_porosityMax.FromJsonValue(jsonValue["PorosityMax"]); } - if (jsonValue.HasMember("ThicknessMax") && jsonValue["ThicknessMax"].IsObject()) { - m_thicknessMax.FromJsonValue(jsonValue["ThicknessMax"]); - } - if (jsonValue.HasMember("CtMax") && jsonValue["CtMax"].IsObject()) { - m_ctMax.FromJsonValue(jsonValue["CtMax"]); - } - if (jsonValue.HasMember("CfMax") && jsonValue["CfMax"].IsObject()) { - m_cfMax.FromJsonValue(jsonValue["CfMax"]); - } if (jsonValue.HasMember("SwiMax") && jsonValue["SwiMax"].IsObject()) { m_swiMax.FromJsonValue(jsonValue["SwiMax"]); } @@ -232,15 +187,6 @@ void nmDataAutomaticFitting::FromJsonValue(const rapidjson::Value& jsonValue) if (jsonValue.HasMember("PorosityMin") && jsonValue["PorosityMin"].IsObject()) { m_porosityMin.FromJsonValue(jsonValue["PorosityMin"]); } - if (jsonValue.HasMember("ThicknessMin") && jsonValue["ThicknessMin"].IsObject()) { - m_thicknessMin.FromJsonValue(jsonValue["ThicknessMin"]); - } - if (jsonValue.HasMember("CtMin") && jsonValue["CtMin"].IsObject()) { - m_ctMin.FromJsonValue(jsonValue["CtMin"]); - } - if (jsonValue.HasMember("CfMin") && jsonValue["CfMin"].IsObject()) { - m_cfMin.FromJsonValue(jsonValue["CfMin"]); - } if (jsonValue.HasMember("SwiMin") && jsonValue["SwiMin"].IsObject()) { m_swiMin.FromJsonValue(jsonValue["SwiMin"]); } @@ -280,15 +226,6 @@ void nmDataAutomaticFitting::setWellboreStorageSelected(bool selected) { m_wellb bool nmDataAutomaticFitting::getPorositySelected() const { return m_porositySelected; } void nmDataAutomaticFitting::setPorositySelected(bool selected) { m_porositySelected = selected; } -bool nmDataAutomaticFitting::getThicknessSelected() const { return m_thicknessSelected; } -void nmDataAutomaticFitting::setThicknessSelected(bool selected) { m_thicknessSelected = selected; } - -bool nmDataAutomaticFitting::getCtSelected() const { return m_ctSelected; } -void nmDataAutomaticFitting::setCtSelected(bool selected) { m_ctSelected = selected; } - -bool nmDataAutomaticFitting::getCfSelected() const { return m_cfSelected; } -void nmDataAutomaticFitting::setCfSelected(bool selected) { m_cfSelected = selected; } - bool nmDataAutomaticFitting::getSwiSelected() const { return m_swiSelected; } void nmDataAutomaticFitting::setSwiSelected(bool selected) { m_swiSelected = selected; } @@ -312,15 +249,6 @@ void nmDataAutomaticFitting::setWellboreStorageMax(const nmDataAttribute& wellbo nmDataAttribute& nmDataAutomaticFitting::getPorosityMax() { return m_porosityMax; } void nmDataAutomaticFitting::setPorosityMax(const nmDataAttribute& porosityMax) { m_porosityMax = porosityMax; } -nmDataAttribute& nmDataAutomaticFitting::getThicknessMax() { return m_thicknessMax; } -void nmDataAutomaticFitting::setThicknessMax(const nmDataAttribute& thicknessMax) { m_thicknessMax = thicknessMax; } - -nmDataAttribute& nmDataAutomaticFitting::getCtMax() { return m_ctMax; } -void nmDataAutomaticFitting::setCtMax(const nmDataAttribute& ctMax) { m_ctMax = ctMax; } - -nmDataAttribute& nmDataAutomaticFitting::getCfMax() { return m_cfMax; } -void nmDataAutomaticFitting::setCfMax(const nmDataAttribute& cfMax) { m_cfMax = cfMax; } - nmDataAttribute& nmDataAutomaticFitting::getSwiMax() { return m_swiMax; } void nmDataAutomaticFitting::setSwiMax(const nmDataAttribute& swiMax) { m_swiMax = swiMax; } @@ -343,15 +271,6 @@ void nmDataAutomaticFitting::setWellboreStorageMin(const nmDataAttribute& wellbo nmDataAttribute& nmDataAutomaticFitting::getPorosityMin() { return m_porosityMin; } void nmDataAutomaticFitting::setPorosityMin(const nmDataAttribute& porosityMin) { m_porosityMin = porosityMin; } -nmDataAttribute& nmDataAutomaticFitting::getThicknessMin() { return m_thicknessMin; } -void nmDataAutomaticFitting::setThicknessMin(const nmDataAttribute& thicknessMin) { m_thicknessMin = thicknessMin; } - -nmDataAttribute& nmDataAutomaticFitting::getCtMin() { return m_ctMin; } -void nmDataAutomaticFitting::setCtMin(const nmDataAttribute& ctMin) { m_ctMin = ctMin; } - -nmDataAttribute& nmDataAutomaticFitting::getCfMin() { return m_cfMin; } -void nmDataAutomaticFitting::setCfMin(const nmDataAttribute& cfMin) { m_cfMin = cfMin; } - nmDataAttribute& nmDataAutomaticFitting::getSwiMin() { return m_swiMin; } void nmDataAutomaticFitting::setSwiMin(const nmDataAttribute& swiMin) { m_swiMin = swiMin; } diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp index 7fb61d6..492544d 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp @@ -165,7 +165,7 @@ void nmWxAutomaticFitting::setParameterRowVisible(QTableWidget* table, int row, } } -// 隐藏参数行后重新整理序号,让界面看起来像删除了不需要的参数。 +// 按当前模型和井型可用的参数行重新整理显示序号。 void nmWxAutomaticFitting::renumberVisibleParameterRows(QTableWidget* table) { if(!table) { @@ -189,7 +189,7 @@ void nmWxAutomaticFitting::renumberVisibleParameterRows(QTableWidget* table) } } -// 根据当前模型类型控制 Ct/Cf/Swi,并根据目标井类型控制裂缝导流能力显示。 +// 拟合表仅包含可优化参数,按模型和目标井类型控制显示。 void nmWxAutomaticFitting::updateParameterVisibility(QTableWidget* table, NM_SOLVER_MODEL_TYPE eType) { if(!table) { @@ -200,35 +200,7 @@ void nmWxAutomaticFitting::updateParameterVisibility(QTableWidget* table, NM_SOL setParameterRowVisible(table, row, true); } - bool showCt = false; - bool showCf = false; - bool showSwi = false; - - switch(eType) { - case SMT_Oil_ConstPvt: - case SMT_Water_ConstPvt: - // 常量PVT使用综合压缩系数Ct。 - showCt = true; - break; - case SMT_Oil_VariablePvt: - case SMT_Water_VariablePvt: - case SMT_Gas_VariablePvt: - // 变化PVT使用岩石压缩系数Cf。 - showCf = true; - break; - case SMT_Oil_Water_TwoPhase: - // 油水两相使用Cf,并且只有它需要初始含水饱和度Swi。 - showCf = true; - showSwi = true; - break; - default: - showCf = true; - break; - } - - setParameterRowVisible(table, 5, showCt); // Ct - setParameterRowVisible(table, 6, showCf); // Cf - setParameterRowVisible(table, 7, showSwi); // Swi + setParameterRowVisible(table, 4, eType == SMT_Oil_Water_TwoPhase); // Swi // Dfc 只属于垂直压裂井和多段压裂水平井。普通井隐藏并取消勾选, // 防止切换目标井后不可见的裂缝参数仍进入拟合参数向量。 @@ -243,8 +215,8 @@ void nmWxAutomaticFitting::updateParameterVisibility(QTableWidget* table, NM_SOL wellType == NM_WELL_MODEL::Horizontal_Fractured_Well; } } - setParameterRowVisible(table, 8, showFractureConductivity); // Dfc - setParameterRowVisible(table, 9, showFractureConductivity); // 裂缝半长 + setParameterRowVisible(table, 5, showFractureConductivity); // Dfc + setParameterRowVisible(table, 6, showFractureConductivity); // 裂缝半长 renumberVisibleParameterRows(table); } @@ -255,10 +227,10 @@ bool nmWxAutomaticFitting::getPhysicalParameterRange(int parameterIndex, { static const char* parameterNames[] = { "Result_K", "Result_W_Skin", "Result_W_C", "Result_phi", - "Result_h", "Result_Cti", "Result_Cf", "Result_Swi", "Result_W_Dfc", + "Result_Swi", "Result_W_Dfc", "W_FractureHalfLength" }; - if(parameterIndex < 0 || parameterIndex >= 10) { + if(parameterIndex < 0 || parameterIndex >= 7) { return false; } @@ -266,7 +238,7 @@ bool nmWxAutomaticFitting::getPhysicalParameterRange(int parameterIndex, return false; } - if(parameterIndex == 7) { + if(parameterIndex == 4) { double soi = reservoirData.getSoi().getValue().toDouble(); double sgi = reservoirData.getSgi().getValue().toDouble(); if(nmAutoFitUiIsFinite(soi) && nmAutoFitUiIsFinite(sgi)) { @@ -324,26 +296,14 @@ void nmWxAutomaticFitting::setParameterRange(int parameterIndex, automaticFittingData.getPorosityMax().setValue(maxValue); break; case 4: - automaticFittingData.getThicknessMin().setValue(minValue); - automaticFittingData.getThicknessMax().setValue(maxValue); - break; - case 5: - automaticFittingData.getCtMin().setValue(minValue); - automaticFittingData.getCtMax().setValue(maxValue); - break; - case 6: - automaticFittingData.getCfMin().setValue(minValue); - automaticFittingData.getCfMax().setValue(maxValue); - break; - case 7: automaticFittingData.getSwiMin().setValue(minValue); automaticFittingData.getSwiMax().setValue(maxValue); break; - case 8: + case 5: automaticFittingData.getFractureConductivityMin().setValue(minValue); automaticFittingData.getFractureConductivityMax().setValue(maxValue); break; - case 9: + case 6: automaticFittingData.getFractureHalfLengthMin().setValue(minValue); automaticFittingData.getFractureHalfLengthMax().setValue(maxValue); break; @@ -359,7 +319,7 @@ void nmWxAutomaticFitting::setParameterRange(int parameterIndex, void nmWxAutomaticFitting::updateRangeForParameter(int parameterIndex, double centerValue) { - if(!m_parameterTable || parameterIndex < 0 || parameterIndex >= 10 + if(!m_parameterTable || parameterIndex < 0 || parameterIndex >= 7 || !nmAutoFitUiIsFinite(centerValue)) { return; } @@ -395,17 +355,17 @@ void nmWxAutomaticFitting::updateRangeForParameter(int parameterIndex, newMin = qMax(physicalMin, reference - skinHalfRange); newMax = qMin(physicalMax, reference + skinHalfRange); } else if(reference > 0.0 - && !(parameterIndex == 7 && centerValue <= 0.0) - && !(parameterIndex == 8 && centerValue <= 0.0)) { + && !(parameterIndex == 4 && centerValue <= 0.0) + && !(parameterIndex == 5 && centerValue <= 0.0)) { const double lowerFactor = 0.1; const double upperFactor = 10.0; newMin = qMax(physicalMin, reference * lowerFactor); newMax = qMin(physicalMax, reference * upperFactor); - } else if(parameterIndex == 7) { + } else if(parameterIndex == 4) { // 没有可靠 Swi 初值时,不把搜索范围压缩到零附近。 newMin = physicalMin; newMax = physicalMax; - } else if(parameterIndex == 8) { + } else if(parameterIndex == 5) { // Dfc=0 表示无限导流,不存在以零为中心的连续倍率范围。 newMin = physicalMin; newMax = physicalMax; @@ -429,7 +389,7 @@ void nmWxAutomaticFitting::initializeSuggestedParameterRanges() return; } - for(int parameterIndex = 0; parameterIndex < 10; ++parameterIndex) { + for(int parameterIndex = 0; parameterIndex < 7; ++parameterIndex) { QTableWidgetItem* initialItem = m_parameterTable->item(parameterIndex, 3); if(initialItem) { bool initialOk = false; @@ -456,7 +416,7 @@ void nmWxAutomaticFitting::normalizeSavedParameterRanges() return; } - for(int parameterIndex = 0; parameterIndex < 10; ++parameterIndex) { + for(int parameterIndex = 0; parameterIndex < 7; ++parameterIndex) { QTableWidgetItem* minItem = m_parameterTable->item(parameterIndex, 2); QTableWidgetItem* maxItem = m_parameterTable->item(parameterIndex, 4); QTableWidgetItem* initialItem = m_parameterTable->item(parameterIndex, 3); @@ -478,7 +438,7 @@ void nmWxAutomaticFitting::normalizeSavedParameterRanges() const bool savedRangeValid = savedMinOk && savedMaxOk && nmAutoFitUiIsFinite(savedMin) && nmAutoFitUiIsFinite(savedMax) && savedMax >= savedMin - && !(parameterIndex == 8 && savedMax <= 1.0e-10); + && !(parameterIndex == 5 && savedMax <= 1.0e-10); if(savedRangeValid && physicalMax >= physicalMin) { const double clippedMin = qMax(savedMin, physicalMin); @@ -507,19 +467,19 @@ bool nmWxAutomaticFitting::validateParameterTable(QString& errorMessage, int par errorMessage = tr("The parameter table is unavailable."); return false; } - if(parameterIndex < -1 || parameterIndex >= 10) { + if(parameterIndex < -1 || parameterIndex >= 7) { errorMessage = tr("The parameter row is invalid."); return false; } static const char* parameterNames[] = { "Permeability", "Skin", "Wellbore storage", "Porosity", - "Thickness", "Ct", "Cf", "Swi", "Fracture conductivity", + "Swi", "Fracture conductivity", "Fracture half length" }; const int firstParameterIndex = parameterIndex < 0 ? 0 : parameterIndex; - const int lastParameterIndex = parameterIndex < 0 ? 10 : parameterIndex + 1; + const int lastParameterIndex = parameterIndex < 0 ? 7 : parameterIndex + 1; for(int currentParameterIndex = firstParameterIndex; currentParameterIndex < lastParameterIndex; ++currentParameterIndex) { // 隐藏参数不参与当前模型拟合,不用它们的历史值阻塞当前设置。 @@ -581,7 +541,7 @@ bool nmWxAutomaticFitting::validateParameterTable(QString& errorMessage, int par } // 底层用 Dfc=0 表示无限导流,这是离散模型选项,不属于有限导流拟合域。 - if(currentParameterIndex == 8 && m_dfcCheckBox->isChecked() + if(currentParameterIndex == 5 && m_dfcCheckBox->isChecked() && (minValue <= 1.0e-10 || initialValue <= 1.0e-10)) { errorMessage = tr("The minimum value of %1 must be greater than zero for automatic fitting.") .arg(tr(parameterNames[currentParameterIndex])); @@ -632,20 +592,6 @@ nmWxAutomaticFitting::nmWxAutomaticFitting(QWidget *parent) // 自动范围始终开启;用户在表格中修改上下限后,itemChanged 会临时切换为手工范围。 m_autoParameterRanges = true; - NM_SOLVER_MODEL_TYPE solverModelType = pManager->getSolverModelType(); - // 未保存过配置时只保留参数选择的相态默认值,不再覆盖数据对象中的初值或范围。 - if(!hasSavedFittingData) { - if(solverModelType == SMT_Oil_ConstPvt || - solverModelType == SMT_Water_ConstPvt) { - // T1/T3 的综合压缩系数默认不参与拟合。 - automaticFittingData.setCtSelected(false); - } else if(solverModelType == SMT_Oil_VariablePvt || - solverModelType == SMT_Water_VariablePvt) { - // T2/T4 的岩石压缩系数默认参与拟合。 - automaticFittingData.setCfSelected(true); - } - } - setupUI(); setWindowTitle(tr("Automatic fitting")); setModal(true); @@ -716,7 +662,7 @@ void nmWxAutomaticFitting::setupUI() void nmWxAutomaticFitting::setupParameterTable() { // 创建表格 - m_parameterTable = new QTableWidget(10, 6, this); + m_parameterTable = new QTableWidget(7, 6, this); // 设置表头 QStringList headers; @@ -785,66 +731,36 @@ void nmWxAutomaticFitting::setupParameterTable() m_parameterTable->setItem(3, 4, new QTableWidgetItem(QString::number(automaticFittingData.getPorosityMax().getValue().toDouble()))); m_parameterTable->setItem(3, 5, new QTableWidgetItem("")); - // 储层厚度 (Thickness) - m_parameterTable->setItem(4, 0, new QTableWidgetItem("5")); - m_hCheckBox = new QCheckBox(tr("Thickness")); - m_hCheckBox->setChecked(automaticFittingData.getThicknessSelected()); - m_parameterTable->setCellWidget(4, 1, m_hCheckBox); - m_parameterTable->setItem(4, 2, new QTableWidgetItem(QString::number(automaticFittingData.getThicknessMin().getValue().toDouble()))); - m_parameterTable->setItem(4, 3, new QTableWidgetItem(QString::number(reservoirData.getThickness().getValue().toDouble()))); - m_parameterTable->setItem(4, 4, new QTableWidgetItem(QString::number(automaticFittingData.getThicknessMax().getValue().toDouble()))); - m_parameterTable->setItem(4, 5, new QTableWidgetItem(tr("m"))); - - // 综合压缩系数 (Ct) - m_parameterTable->setItem(5, 0, new QTableWidgetItem("6")); - m_ctCheckBox = new QCheckBox(tr("Ct")); - m_ctCheckBox->setChecked(automaticFittingData.getCtSelected()); - m_parameterTable->setCellWidget(5, 1, m_ctCheckBox); - m_parameterTable->setItem(5, 2, new QTableWidgetItem(QString::number(automaticFittingData.getCtMin().getValue().toDouble()))); - m_parameterTable->setItem(5, 3, new QTableWidgetItem(QString::number(reservoirData.getCt().getValue().toDouble()))); - m_parameterTable->setItem(5, 4, new QTableWidgetItem(QString::number(automaticFittingData.getCtMax().getValue().toDouble()))); - m_parameterTable->setItem(5, 5, new QTableWidgetItem("")); - - // 岩石压缩系数 (Cf) - m_parameterTable->setItem(6, 0, new QTableWidgetItem("7")); - m_cfCheckBox = new QCheckBox(tr("Cf")); - m_cfCheckBox->setChecked(automaticFittingData.getCfSelected()); - m_parameterTable->setCellWidget(6, 1, m_cfCheckBox); - m_parameterTable->setItem(6, 2, new QTableWidgetItem(QString::number(automaticFittingData.getCfMin().getValue().toDouble()))); - m_parameterTable->setItem(6, 3, new QTableWidgetItem(QString::number(reservoirData.getCf().getValue().toDouble()))); - m_parameterTable->setItem(6, 4, new QTableWidgetItem(QString::number(automaticFittingData.getCfMax().getValue().toDouble()))); - m_parameterTable->setItem(6, 5, new QTableWidgetItem("")); - // 初始含水饱和度 (Swi) - m_parameterTable->setItem(7, 0, new QTableWidgetItem("8")); + m_parameterTable->setItem(4, 0, new QTableWidgetItem("5")); m_swiCheckBox = new QCheckBox(tr("Swi")); m_swiCheckBox->setChecked(automaticFittingData.getSwiSelected()); - m_parameterTable->setCellWidget(7, 1, m_swiCheckBox); - m_parameterTable->setItem(7, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMin().getValue().toDouble()))); - m_parameterTable->setItem(7, 3, new QTableWidgetItem(QString::number(reservoirData.getSwi().getValue().toDouble()))); - m_parameterTable->setItem(7, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMax().getValue().toDouble()))); - m_parameterTable->setItem(7, 5, new QTableWidgetItem("")); + m_parameterTable->setCellWidget(4, 1, m_swiCheckBox); + m_parameterTable->setItem(4, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMin().getValue().toDouble()))); + m_parameterTable->setItem(4, 3, new QTableWidgetItem(QString::number(reservoirData.getSwi().getValue().toDouble()))); + m_parameterTable->setItem(4, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMax().getValue().toDouble()))); + m_parameterTable->setItem(4, 5, new QTableWidgetItem("")); // 裂缝导流能力 (Dfc)。该行只对压裂井显示,初值在 onWellSelected() 中 // 从当前目标井读取,其他裂缝几何参数保持固定,不进入自动拟合。 - m_parameterTable->setItem(8, 0, new QTableWidgetItem("9")); + m_parameterTable->setItem(5, 0, new QTableWidgetItem("6")); m_dfcCheckBox = new QCheckBox(tr("Fracture conductivity")); m_dfcCheckBox->setChecked(automaticFittingData.getFractureConductivitySelected()); - m_parameterTable->setCellWidget(8, 1, m_dfcCheckBox); - m_parameterTable->setItem(8, 2, new QTableWidgetItem(QString::number(automaticFittingData.getFractureConductivityMin().getValue().toDouble()))); - m_parameterTable->setItem(8, 3, new QTableWidgetItem()); - m_parameterTable->setItem(8, 4, new QTableWidgetItem(QString::number(automaticFittingData.getFractureConductivityMax().getValue().toDouble()))); - m_parameterTable->setItem(8, 5, new QTableWidgetItem(tr("md.m"))); + m_parameterTable->setCellWidget(5, 1, m_dfcCheckBox); + m_parameterTable->setItem(5, 2, new QTableWidgetItem(QString::number(automaticFittingData.getFractureConductivityMin().getValue().toDouble()))); + m_parameterTable->setItem(5, 3, new QTableWidgetItem()); + m_parameterTable->setItem(5, 4, new QTableWidgetItem(QString::number(automaticFittingData.getFractureConductivityMax().getValue().toDouble()))); + m_parameterTable->setItem(5, 5, new QTableWidgetItem(tr("md.m"))); // 裂缝半长。该行与 Dfc 一样只对压裂井显示,初值从当前目标井读取。 - m_parameterTable->setItem(9, 0, new QTableWidgetItem("10")); + m_parameterTable->setItem(6, 0, new QTableWidgetItem("7")); m_fractureHalfLengthCheckBox = new QCheckBox(tr("Fracture half length")); m_fractureHalfLengthCheckBox->setChecked(automaticFittingData.getFractureHalfLengthSelected()); - m_parameterTable->setCellWidget(9, 1, m_fractureHalfLengthCheckBox); - m_parameterTable->setItem(9, 2, new QTableWidgetItem(QString::number(automaticFittingData.getFractureHalfLengthMin().getValue().toDouble()))); - m_parameterTable->setItem(9, 3, new QTableWidgetItem()); - m_parameterTable->setItem(9, 4, new QTableWidgetItem(QString::number(automaticFittingData.getFractureHalfLengthMax().getValue().toDouble()))); - m_parameterTable->setItem(9, 5, new QTableWidgetItem(tr("m"))); + m_parameterTable->setCellWidget(6, 1, m_fractureHalfLengthCheckBox); + m_parameterTable->setItem(6, 2, new QTableWidgetItem(QString::number(automaticFittingData.getFractureHalfLengthMin().getValue().toDouble()))); + m_parameterTable->setItem(6, 3, new QTableWidgetItem()); + m_parameterTable->setItem(6, 4, new QTableWidgetItem(QString::number(automaticFittingData.getFractureHalfLengthMax().getValue().toDouble()))); + m_parameterTable->setItem(6, 5, new QTableWidgetItem(tr("m"))); // 设置表格行为 for(int i = 0; i < m_parameterTable->rowCount(); ++i) { @@ -1047,12 +963,9 @@ void nmWxAutomaticFitting::onReverseSelection() if(!m_parameterTable->isRowHidden(1)) m_sCheckBox->setChecked(!m_sCheckBox->isChecked()); if(!m_parameterTable->isRowHidden(2)) m_cCheckBox->setChecked(!m_cCheckBox->isChecked()); if(!m_parameterTable->isRowHidden(3)) m_phiCheckBox->setChecked(!m_phiCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(4)) m_hCheckBox->setChecked(!m_hCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(5)) m_ctCheckBox->setChecked(!m_ctCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(6)) m_cfCheckBox->setChecked(!m_cfCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(7)) m_swiCheckBox->setChecked(!m_swiCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(8)) m_dfcCheckBox->setChecked(!m_dfcCheckBox->isChecked()); - if(!m_parameterTable->isRowHidden(9)) m_fractureHalfLengthCheckBox->setChecked(!m_fractureHalfLengthCheckBox->isChecked()); + if(!m_parameterTable->isRowHidden(4)) m_swiCheckBox->setChecked(!m_swiCheckBox->isChecked()); + if(!m_parameterTable->isRowHidden(5)) m_dfcCheckBox->setChecked(!m_dfcCheckBox->isChecked()); + if(!m_parameterTable->isRowHidden(6)) m_fractureHalfLengthCheckBox->setChecked(!m_fractureHalfLengthCheckBox->isChecked()); } void nmWxAutomaticFitting::onParameterTableItemChanged(QTableWidgetItem* item) @@ -1169,8 +1082,6 @@ void nmWxAutomaticFitting::onAccept() // 检查是否有参数被选中 bool hasSelectedParams = m_kCheckBox->isChecked() || m_sCheckBox->isChecked() || m_cCheckBox->isChecked() || m_phiCheckBox->isChecked() || - m_hCheckBox->isChecked() || - m_ctCheckBox->isChecked() || m_cfCheckBox->isChecked() || m_swiCheckBox->isChecked() || m_dfcCheckBox->isChecked() || m_fractureHalfLengthCheckBox->isChecked(); @@ -1186,9 +1097,6 @@ void nmWxAutomaticFitting::onAccept() if(m_sCheckBox->isChecked()) selectedParameterNames << tr("Skin"); if(m_cCheckBox->isChecked()) selectedParameterNames << tr("Wellbore storage"); if(m_phiCheckBox->isChecked()) selectedParameterNames << tr("Porosity"); - if(m_hCheckBox->isChecked()) selectedParameterNames << tr("Thickness"); - if(m_ctCheckBox->isChecked()) selectedParameterNames << tr("Ct"); - if(m_cfCheckBox->isChecked()) selectedParameterNames << tr("Cf"); if(m_swiCheckBox->isChecked()) selectedParameterNames << tr("Swi"); if(m_dfcCheckBox->isChecked()) selectedParameterNames << tr("Fracture conductivity"); if(m_fractureHalfLengthCheckBox->isChecked()) selectedParameterNames << tr("Fracture half length"); @@ -1286,19 +1194,19 @@ void nmWxAutomaticFitting::onWellSelected(int index) // 设置井筒储集系数(Wellbore storage) m_parameterTable->item(2, 3)->setText(QString::number(wellboreStorageValue)); - if(fracturedWell && m_parameterTable->item(8, 3)) { - m_parameterTable->item(8, 3)->setText(QString::number(fractureConductivityValue)); + if(fracturedWell && m_parameterTable->item(5, 3)) { + m_parameterTable->item(5, 3)->setText(QString::number(fractureConductivityValue)); } - if(fracturedWell && m_parameterTable->item(9, 3)) { - m_parameterTable->item(9, 3)->setText(QString::number(fractureHalfLengthValue)); + if(fracturedWell && m_parameterTable->item(6, 3)) { + m_parameterTable->item(6, 3)->setText(QString::number(fractureHalfLengthValue)); } if(m_autoParameterRanges) { updateRangeForParameter(1, skinValue); updateRangeForParameter(2, wellboreStorageValue); if(fracturedWell) { - updateRangeForParameter(8, fractureConductivityValue); - updateRangeForParameter(9, fractureHalfLengthValue); + updateRangeForParameter(5, fractureConductivityValue); + updateRangeForParameter(6, fractureHalfLengthValue); } } } @@ -1306,14 +1214,11 @@ void nmWxAutomaticFitting::onWellSelected(int index) void nmWxAutomaticFitting::setAutomaticFittingValue() { - // 保存参数选择状态 + // 保存剩余拟合参数的选择状态,LM 和 PSO 共用此配置。 automaticFittingData.setPermeabilitySelected(m_kCheckBox->isChecked()); automaticFittingData.setSkinSelected(m_sCheckBox->isChecked()); automaticFittingData.setWellboreStorageSelected(m_cCheckBox->isChecked()); automaticFittingData.setPorositySelected(m_phiCheckBox->isChecked()); - automaticFittingData.setThicknessSelected(m_hCheckBox->isChecked()); - automaticFittingData.setCtSelected(m_ctCheckBox->isChecked()); - automaticFittingData.setCfSelected(m_cfCheckBox->isChecked()); automaticFittingData.setSwiSelected(m_swiCheckBox->isChecked()); automaticFittingData.setFractureConductivitySelected(m_dfcCheckBox->isChecked()); automaticFittingData.setFractureHalfLengthSelected(m_fractureHalfLengthCheckBox->isChecked()); @@ -1335,41 +1240,26 @@ void nmWxAutomaticFitting::setAutomaticFittingValue() automaticFittingData.getPorosityMin().setValue(m_parameterTable->item(3, 2)->text().toDouble()); automaticFittingData.getPorosityMax().setValue(m_parameterTable->item(3, 4)->text().toDouble()); - // 保存储层厚度的最小值和最大值 - automaticFittingData.getThicknessMin().setValue(m_parameterTable->item(4, 2)->text().toDouble()); - automaticFittingData.getThicknessMax().setValue(m_parameterTable->item(4, 4)->text().toDouble()); - - // 保存综合压缩系数的最小值和最大值 - automaticFittingData.getCtMin().setValue(m_parameterTable->item(5, 2)->text().toDouble()); - automaticFittingData.getCtMax().setValue(m_parameterTable->item(5, 4)->text().toDouble()); - - // 保存岩石压缩系数的最小值和最大值 - automaticFittingData.getCfMin().setValue(m_parameterTable->item(6, 2)->text().toDouble()); - automaticFittingData.getCfMax().setValue(m_parameterTable->item(6, 4)->text().toDouble()); - // 保存初始含水饱和度的最小值和最大值 - automaticFittingData.getSwiMin().setValue(m_parameterTable->item(7, 2)->text().toDouble()); - automaticFittingData.getSwiMax().setValue(m_parameterTable->item(7, 4)->text().toDouble()); + automaticFittingData.getSwiMin().setValue(m_parameterTable->item(4, 2)->text().toDouble()); + automaticFittingData.getSwiMax().setValue(m_parameterTable->item(4, 4)->text().toDouble()); // 保存裂缝导流能力的最小值和最大值 - automaticFittingData.getFractureConductivityMin().setValue(m_parameterTable->item(8, 2)->text().toDouble()); - automaticFittingData.getFractureConductivityMax().setValue(m_parameterTable->item(8, 4)->text().toDouble()); + automaticFittingData.getFractureConductivityMin().setValue(m_parameterTable->item(5, 2)->text().toDouble()); + automaticFittingData.getFractureConductivityMax().setValue(m_parameterTable->item(5, 4)->text().toDouble()); // 保存裂缝半长的最小值和最大值 - automaticFittingData.getFractureHalfLengthMin().setValue(m_parameterTable->item(9, 2)->text().toDouble()); - automaticFittingData.getFractureHalfLengthMax().setValue(m_parameterTable->item(9, 4)->text().toDouble()); + automaticFittingData.getFractureHalfLengthMin().setValue(m_parameterTable->item(6, 2)->text().toDouble()); + automaticFittingData.getFractureHalfLengthMax().setValue(m_parameterTable->item(6, 4)->text().toDouble()); // 保存迭代参数 automaticFittingData.getIterationCount().setValue(m_iterationEdit->text().toInt()); automaticFittingData.getErrorTolerance().setValue(m_errorLimitEdit->text().toDouble()); - // 保存储层数据的初值 + // 只写回仍可编辑的储层初值,厚度和压缩系数保留原始精度和值。 reservoirData.getPermeability().setValue(m_parameterTable->item(0, 3)->text().toDouble()); // 渗透率 reservoirData.getPorosity().setValue(m_parameterTable->item(3, 3)->text().toDouble()); // 孔隙度 - reservoirData.getThickness().setValue(m_parameterTable->item(4, 3)->text().toDouble()); // 储层厚度 - reservoirData.getCt().setValue(m_parameterTable->item(5, 3)->text().toDouble()); // 综合压缩系数 - reservoirData.getCf().setValue(m_parameterTable->item(6, 3)->text().toDouble()); // 岩石压缩系数 - reservoirData.getSwi().setValue(m_parameterTable->item(7, 3)->text().toDouble()); // 初始含水饱和度 + reservoirData.getSwi().setValue(m_parameterTable->item(4, 3)->text().toDouble()); // 初始含水饱和度 // 更新储层数据(全局) nmDataAnalyzeManager::getCurrentInstance()->updateReservoirData(reservoirData); @@ -1382,8 +1272,8 @@ void nmWxAutomaticFitting::setAutomaticFittingValue() if(!selectedWellName.isEmpty()) { double newSkinValue = m_parameterTable->item(1, 3)->text().toDouble(); double newWellboreStorageValue = m_parameterTable->item(2, 3)->text().toDouble(); - double newFractureConductivityValue = m_parameterTable->item(8, 3)->text().toDouble(); - double newFractureHalfLengthValue = m_parameterTable->item(9, 3)->text().toDouble(); + double newFractureConductivityValue = m_parameterTable->item(5, 3)->text().toDouble(); + double newFractureHalfLengthValue = m_parameterTable->item(6, 3)->text().toDouble(); // 直接从数据管理器获取目标井 nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance(); @@ -1689,12 +1579,9 @@ void nmWxAutomaticFitting::updateBestParametersToTable() if(m_sCheckBox->isChecked()) enabledParams.append(1); // 表皮系数 if(m_cCheckBox->isChecked()) enabledParams.append(2); // 井筒储集系数 if(m_phiCheckBox->isChecked()) enabledParams.append(3); // 孔隙度 - if(m_hCheckBox->isChecked()) enabledParams.append(4); // 储层厚度 - if(m_ctCheckBox->isChecked()) enabledParams.append(5); // 综合压缩系数 - if(m_cfCheckBox->isChecked()) enabledParams.append(6); // 岩石压缩系数 - if(m_swiCheckBox->isChecked()) enabledParams.append(7); // 初始含水饱和度 - if(m_dfcCheckBox->isChecked()) enabledParams.append(8); // 裂缝导流能力 - if(m_fractureHalfLengthCheckBox->isChecked()) enabledParams.append(9); // 裂缝半长 + if(m_swiCheckBox->isChecked()) enabledParams.append(4); // 初始含水饱和度 + if(m_dfcCheckBox->isChecked()) enabledParams.append(5); // 裂缝导流能力 + if(m_fractureHalfLengthCheckBox->isChecked()) enabledParams.append(6); // 裂缝半长 // 更新参数值和范围 for (int i = 0; i < bestSolution.size() && i < enabledParams.size(); ++i) {