Compare commits

...

2 Commits

Author SHA1 Message Date
lvjunjie 57c3d613f6 feat(nmNum): 新增 LM 高度与形状预调整的三阶段拟合
- 优先根据压力与压力导数的上下偏差调整渗透率,对齐曲线高度
- 在固定对数时间网格计算双曲线斜率残差,优先改善形状并限制整体偏离
- 按形状改善与剩余预算切换阶段,第三阶段沿用仅按整体误差接受候选的 LM
- 联合缓存数值与形状灵敏度,复用阶段间模型并同步已接受参数及曲线
- 迭代候选求解失败后交由信赖域缩步,避免相同参数重复重试
- 补充三阶段拟合日志、跟踪诊断字段及中文翻译
2 weeks ago
lvjunjie e027bf14d6 feat(nmNum): 新增 LM 可切换目标点分层采样
- 拟合界面新增采样方式选择,默认保留原有固定 80 点模式
- 按目标有效时间点逐层加密,补充时间窗口边界与重叠区锚点
- 结合对数时间权重计算窗口误差与 Fisher 矩阵,切层后重建灵敏度
- 使用全部有效目标点验收候选参数,按停滞情况与剩余预算推进层级
- 补充分层采样日志、全目标点对比误差及中文翻译
3 weeks ago

Binary file not shown.

@ -664,6 +664,34 @@ Reason: %1</source>
</context>
<context>
<name>nmCalculationAutoFitLM</name>
<message>
<source>Failed to refresh the sampling layer from the current curve.</source>
<translation>无法根据当前曲线刷新采样层级。</translation>
</message>
<message>
<source>LM sampling refined: %1 / %2 target points; full-target error: %3</source>
<translation>LM 采样加密:%1 / %2 个目标点;全目标点误差:%3</translation>
</message>
<message>
<source>LM sampling: layered target points (%1 / %2); acceptance uses all valid target points.</source>
<translation>LM 采样方式:目标点分层采样(%1 / %2 点),使用全部有效目标点验收。</translation>
</message>
<message>
<source>LM sampling: fixed 80 points (original mode).</source>
<translation>LM 采样方式:固定 80 点(原模式)。</translation>
</message>
<message>
<source>Full-target comparison error: initial=%1; final=%2</source>
<translation>全目标点对比误差:初始=%1;最终=%2</translation>
</message>
<message>
<source>Unavailable</source>
<translation>不可用</translation>
</message>
<message>
<source>Budget exhausted before the full sampling layer; convergence is not confirmed.</source>
<translation>预算已耗尽,尚未进入完整采样层,未确认收敛。</translation>
</message>
<message>
<source>=== User Stop Request Received ===</source>
<translation>=== 用户停止请求已接收 ===</translation>
@ -949,8 +977,8 @@ Reason: %1</source>
<translation>连续 %1 次无有效改善,正在重建灵敏度模型进行确认</translation>
</message>
<message>
<source>Effective improvement threshold: max(%1, %2% of baseline error); %3 consecutive ineffective steps trigger convergence confirmation</source>
<translation>有效改善阈值:取 %1 与基准误差的 %2% 中较大值;连续 %3 次无有效改善后进行收敛确认</translation>
<source>Total-stage effective improvement threshold: max(%1, %2% of baseline error); %3 consecutive ineffective steps trigger convergence confirmation</source>
<translation>整体阶段有效改善阈值:取 %1 与基准误差的 %2% 中较大值;连续 %3 次无有效改善后进行收敛确认</translation>
</message>
<message>
<source>Sensitivity probe accepted: error reduced to %1</source>
@ -1088,6 +1116,74 @@ Reason: %1</source>
<source>Target well name is empty</source>
<translation>目标井名称为空</translation>
</message>
<message>
<source>LM stage 1: align curve height using permeability only (up to %1 evaluations).</source>
<translation>LM 阶段一:仅调整渗透率对齐曲线高度(最多求解 %1 次)。</translation>
</message>
<message>
<source>Permeability alignment: k=%1, height error=%2, shape error=%3, result=%4</source>
<translation>渗透率对齐:k=%1,上下误差=%2,形状误差=%3,结果=%4</translation>
</message>
<message>
<source>LM stage 2: optimize pressure and derivative shape; stop after 3 ineffective steps.</source>
<translation>LM 阶段二:优先调整压力和压力导数形状,连续 3 步无明显改善后切换。</translation>
</message>
<message>
<source>LM stage 3: original LM fitting; accept by total error only.</source>
<translation>LM 阶段三:按原有 LM 拟合,仅依据整体误差接受调整。</translation>
</message>
<message>
<source>Sensitivity probe accepted: total error=%1</source>
<translation>采用灵敏度试算点:整体误差=%1</translation>
</message>
<message>
<source>Shape stage ended: %1</source>
<translation>形状阶段结束:%1</translation>
</message>
<message>
<source>3 consecutive steps without effective shape improvement</source>
<translation>连续 3 步形状没有明显改善</translation>
</message>
<message>
<source>reserve remaining iterations and evaluations for total fitting</source>
<translation>为整体拟合保留剩余迭代和求解预算</translation>
</message>
<message>
<source>no valid shape sensitivity model</source>
<translation>没有有效的形状灵敏度模型</translation>
</message>
<message>
<source>no feasible shape descent step</source>
<translation>没有满足约束的形状下降步</translation>
</message>
<message>
<source>Permeability alignment ended: %1</source>
<translation>渗透率高度对齐结束:%1</translation>
</message>
<message>
<source>height evaluation budget reached</source>
<translation>达到高度调整求解预算</translation>
</message>
<message>
<source>stopped by user</source>
<translation>用户停止</translation>
</message>
<message>
<source>pressure and derivative height directions conflict</source>
<translation>压力与压力导数的上下调整方向冲突</translation>
</message>
<message>
<source>curve height is approximately aligned</source>
<translation>曲线高度已大致对齐</translation>
</message>
<message>
<source>2 consecutive steps without effective height improvement</source>
<translation>连续 2 步上下偏差没有明显改善</translation>
</message>
<message>
<source>permeability reached its bound</source>
<translation>渗透率已到达范围边界</translation>
</message>
</context>
<context>
<name>nmCalculationSolver</name>
@ -3794,6 +3890,22 @@ Supported types: Vertical, Vertical Fractured, and Horizontal Multi-Fractured We
</context>
<context>
<name>nmWxAutomaticFitting</name>
<message>
<source>LM sampling:</source>
<translation>LM 采样方式:</translation>
</message>
<message>
<source>Fixed sampling (80 points)</source>
<translation>固定采样(80 点)</translation>
</message>
<message>
<source>Layered target sampling</source>
<translation>目标点分层采样</translation>
</message>
<message>
<source>Layered sampling uses target-point subsets for directions and all valid target points for acceptance.</source>
<translation>逐层增加目标曲线采样点,并始终使用全部有效目标点判断拟合是否改善。</translation>
</message>
<message>
<source>Automatic fitting</source>
<translation>自动拟合</translation>

@ -12,7 +12,7 @@
#include "nmCalculation_global.h"
// 固定对数时间窗口的误差诊断。时间边界为不含重叠区的基础边界;
// rmsError 是局部加权均方根,energy 是对 total 平方的贡献。
// rmsError 是局部加权均方根,energy 是对当前层残差能量的贡献。
struct AutoFitTimeWindowLM {
double timeMin;
double timeMax;
@ -25,14 +25,19 @@ struct AutoFitTimeWindowLM {
{}
};
// 双对数曲线误差分解。total 是 LM 候选接受和排序的唯一依据,
// 时间窗口和残差用于 Fisher 选参,其余诊断量用于解释曲线失配。
// 双对数曲线误差分解。预调整使用纵向偏差,形状阶段使用双曲线斜率残差,
// 整体阶段只使用 total 接受候选;时间窗口和残差用于 Fisher 选参。
struct AutoFitObjectiveBreakdownLM {
bool valid;
double total;
double pressureLoss;
double derivativeLoss;
QVector<double> residualVector;
// 分层模式的残差属于当前层,total 属于全部目标点;固定模式坐标数组为空。
QVector<double> sampleCoordinates;
int samplingStride;
int fullPointCount;
double layerError;
QVector<AutoFitTimeWindowLM> timeWindows;
double verticalCommonBias;
double verticalLoss;
@ -41,6 +46,10 @@ struct AutoFitObjectiveBreakdownLM {
double horizontalLoss;
bool horizontalReliable;
bool registrationAmbiguous;
// 固定 log-time 网格上的双曲线斜率残差,独立于数值残差的采样层级。
QVector<double> shapeResiduals;
double pressureVerticalBias;
double derivativeVerticalBias;
double shapeLoss;
double lateDerivativeSlopeBias;
double lateDerivativeTrendLoss;
@ -51,6 +60,9 @@ struct AutoFitObjectiveBreakdownLM {
, total(1.0e10)
, pressureLoss(std::numeric_limits<double>::quiet_NaN())
, derivativeLoss(std::numeric_limits<double>::quiet_NaN())
, samplingStride(1)
, fullPointCount(80)
, layerError(1.0e10)
, verticalCommonBias(std::numeric_limits<double>::quiet_NaN())
, verticalLoss(std::numeric_limits<double>::quiet_NaN())
, verticalReliable(false)
@ -58,6 +70,8 @@ struct AutoFitObjectiveBreakdownLM {
, horizontalLoss(std::numeric_limits<double>::quiet_NaN())
, horizontalReliable(false)
, registrationAmbiguous(false)
, pressureVerticalBias(0.0)
, derivativeVerticalBias(0.0)
, shapeLoss(std::numeric_limits<double>::quiet_NaN())
, lateDerivativeSlopeBias(std::numeric_limits<double>::quiet_NaN())
, lateDerivativeTrendLoss(std::numeric_limits<double>::quiet_NaN())
@ -97,6 +111,7 @@ public:
int getTotalEvaluations() const;
void resetOptimizer();
void setTargetWellName(const QString& wellName);
void setLayeredSamplingEnabled(bool enabled);
signals:
void progressUpdated(int iteration, double bestFitness);
@ -125,7 +140,7 @@ private:
AutoFitObjectiveBreakdownLM* breakdown,
QVector<QVector<double> >* curve,
int* elapsedMs);
double evaluateFitness(const QVector<double>& parameters);
double evaluateFitness(const QVector<double>& parameters, bool retrySolver = true);
void applyParametersToDataManager(const QVector<double>& parameters);
void updateReservoirParameters(const QVector<double>& parameters);
@ -191,6 +206,9 @@ private:
double m_comparisonTimeMin;
double m_comparisonTimeMax;
QString m_targetWellName;
// 此开关由拟合界面传入;每轮重置层级,固定模式仍使用原来的 80 点目标。
bool m_layeredSampling;
int m_samplingStride;
int m_maxIterations;
double m_targetError;

@ -82,6 +82,8 @@ private:
QLineEdit* m_errorLimitEdit;
QComboBox* m_targetWellCombo;
QComboBox* m_algorithmCombo;
QLabel* m_samplingLabel;
QComboBox* m_samplingCombo;
QLabel* m_surrogateLabel;
QComboBox* m_surrogateCombo;

File diff suppressed because it is too large Load Diff

@ -724,6 +724,13 @@ void nmWxAutomaticFitting::setupControlPanel()
m_surrogateCombo->setCurrentIndex(automaticFittingData.getSurrogateScreeningEnabled() ? 1 : 0);
m_surrogateCombo->setMaximumWidth(160);
m_surrogateCombo->setMinimumWidth(160);
// 分层采样用于 LM 对比试验,每次打开默认使用原来的固定 80 点模式。
m_samplingLabel = new QLabel(tr("LM sampling:"));
m_samplingCombo = new QComboBox();
m_samplingCombo->addItem(tr("Fixed sampling (80 points)"));
m_samplingCombo->addItem(tr("Layered target sampling"));
m_samplingCombo->setMinimumWidth(180);
m_samplingCombo->setToolTip(tr("Layered sampling uses target-point subsets for directions and all valid target points for acceptance."));
connect(m_algorithmCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onAlgorithmChanged(int)));
onAlgorithmChanged(m_algorithmCombo->currentIndex());
@ -781,6 +788,10 @@ void nmWxAutomaticFitting::setupControlPanel()
m_controlLayout->addWidget(m_surrogateCombo);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(m_samplingLabel);
m_controlLayout->addWidget(m_samplingCombo);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(iterationLabel);
m_controlLayout->addWidget(m_iterationEdit);
m_controlLayout->addSpacing(15);
@ -802,6 +813,8 @@ void nmWxAutomaticFitting::onAlgorithmChanged(int index)
const bool usePSO = (index == 0);
m_surrogateLabel->setEnabled(usePSO);
m_surrogateCombo->setEnabled(usePSO);
m_samplingLabel->setEnabled(!usePSO);
m_samplingCombo->setEnabled(!usePSO);
}
void nmWxAutomaticFitting::setupButtons()
@ -1189,6 +1202,7 @@ void nmWxAutomaticFitting::startAutoFitting(const QVector<QVector<double>>& targ
m_autoFitterLM = new nmCalculationAutoFitLM(this);
m_autoFitterLM->setTargetLogLogData(targetData);
m_autoFitterLM->setTargetWellName(targetWellName);
m_autoFitterLM->setLayeredSamplingEnabled(m_samplingCombo->currentIndex() == 1);
} else {
DEBUG_UI("Creating PSO auto fitter");
m_autoFitterPSO = new nmCalculationAutoFitPSO(this);

Loading…
Cancel
Save