@ -1212,9 +1212,9 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
QTextStream out ( & metaFile ) ;
out < < " { \n " ;
out < < " \" schema_version \" : 29 ,\n " ;
out < < " \" schema_version \" : 31 ,\n " ;
out < < " \" strategy \" : \" permeability_height_then_shape_then_joint_lm \" , \n " ;
out < < " \" height_acceptance \" : \" reliable_vertical_loss_decrease; no_shape_ loss_constraint\" , \n " ;
out < < " \" height_acceptance \" : \" reliable_vertical_loss_decrease; no_shape_ or_total_ loss_constraint\" , \n " ;
out < < " \" shape_priority \" : \" storage_then_skin_then_shape_without_wellbore_then_optional_wellbore_recheck \" , \n " ;
out < < " \" shape_metric \" : \" pressure_and_derivative_log_slopes_81_points_lag_8 \" , \n " ;
out < < " \" early_parallel_metric \" : \" pressure_and_derivative_log_slopes_first_window_81_points_lag_8 \" , \n " ;
@ -1225,16 +1225,16 @@ void nmCalculationAutoFitLM::writeTraceMetaFile()
out < < " \" early_initial_expansion_policy \" : \" before_first_accepted_shape_improvement; if_shape_worsens_double_coordinate_step_from_unchanged_base_up_to_parameter_bound; retain_base_on_failure \" , \n " ;
out < < " \" early_wellbore_acceptance \" : \" locked_gap_direction_and_early_shape_decrease \" , \n " ;
out < < " \" early_wellbore_total_constraint \" : false, \n " ;
out < < " \" shape_stage_total_ tolerance\" : \" max(0.02, 25% of stage entry total) \" ,\n " ;
out < < " \" shape_stage_total_ constraint\" : false ,\n " ;
out < < " \" shape_wellbore_parameters_frozen \" : true, \n " ;
out < < " \" shape_sensitivity_refresh \" : \" full Jacobian at joint shape entry and stagnation confirmation \" , \n " ;
out < < " \" shape_sensitivity_refresh \" : \" non_wellbore_columns_only at joint shape entry and stagnation confirmation; full Jacobian rebuilt at total-stage entry \" , \n " ;
out < < " \" shape_expansion_policy \" : \" one expansion per reliable shape direction, up to 2x when actual rho exceeds 0.75; retain ordinary step on failure \" , \n " ;
out < < " \" shape_global_parameter_selection \" : \" all_valid_non_wellbore_columns_with_positive_response \" , \n " ;
out < < " \" stage2_budget \" : \" adaptive, no fixed iteration or evaluation quota; full window/global rounds, 2 ineffective rounds then fresh-J confirmation \" , \n " ;
out < < " \" shape_round_improvement_threshold \" : \" max(0.0001, 1% of round entry shape loss) \" , \n " ;
out < < " \" iteration_count_scope \" : \" max_iterations applies to total-stage LM; trace iteration remains cumulative \" , \n " ;
out < < " \" wellbore_recheck_trigger \" : \" early loss exceeds initial early-stage exit by max(0.0001, 10%) \" , \n " ;
out < < " \" wellbore_recheck_acceptance \" : \" early decrease with fixed entry total and shape limits, each max(0.0001, 5%)\" , \n " ;
out < < " \" wellbore_recheck_acceptance \" : \" early decrease with fixed entry shape limit max(0.0001, 5%); no_total_loss_constraint \" , \n " ;
out < < " \" wellbore_recheck_budget \" : \" once when early shape degrades; each wellbore parameter stops after 2 ineffective steps, independent of total-stage budget \" , \n " ;
out < < " \" total_stage_shape_constraint \" : false, \n " ;
out < < " \" total_parameter_selection \" : \" all_valid_free_columns \" , \n " ;
@ -2038,7 +2038,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
StopReasonLM stopReason = LM_MAX_ITERATIONS ;
// jacobian 的行对应当前采样层的残差,列对应用户勾选的参数。
// Fisher 按当前阶段取数值或形状残差行 ,完整 Jacobian 在阶段之间复用 。
// Fisher 按当前阶段取数值或形状残差行 ;冻结列不参与形状差分,整体阶段重建全部列 。
QVector < QVector < double > > jacobian ;
QVector < bool > jacobianColumnValid ( dimensions , false ) ;
@ -2154,7 +2154,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
int heightStagnation = 0 ;
double heightScale = 1.0 ;
double heightSlope = - 1.0 ;
if ( permeabilityColumn > = 0 & & current . fitness > = m_targetError ) {
if ( permeabilityColumn > = 0 ) {
emit logMessageGenerated ( tr ( " LM stage 1: align curve height using permeability only (up to %1 evaluations). " )
. arg ( heightBudget ) ) ;
for ( int trial = 0 ; trial < heightBudget & & processPauseAndStop ( ) ; + + trial ) {
@ -2211,9 +2211,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( m_shouldStop ) return LM_USER_STOPPED ;
// 第二阶段不按迭代比例截断;普通形状按完整搜索轮次判断是否仍有显著改善。
// 井储、表皮保持冻结,总误差上限仍固定于普通形状阶段入口。
bool shapeStage = current . fitness > = m_targetError ;
double shapeValueLimit = current . fitness + qMax ( 0.02 , 0.25 * current . fitness ) ;
// 普通形状调整冻结井储、表皮,只按形状验收;总误差达标只在第三阶段判断。
bool shapeStage = true ;
bool jointShapeStarted = false ;
double shapeRoundBaseline = current . breakdown . shapeLoss ;
int shapeRoundNumber = 0 ;
@ -2230,7 +2229,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
bool wellboreRecheck = false ;
bool wellboreRecheckDone = false ;
double earlyWellboreBaseline = current . breakdown . earlyParallelLoss ;
double recheckTotalLimit = 0.0 ;
double recheckShapeLimit = 0.0 ;
// 先井储、再表皮;回检沿用相同顺序和前期指标,不回到形状阶段反复循环。
bool earlyShapeStage = shapeStage & & wellboreParameterCount > 0 ;
@ -2270,11 +2268,10 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
const int column = m_enabledParamIndices . indexOf ( earlyShapeParameter ) ;
return earlyGapDirection * ( point . coordinates [ column ] - base . coordinates [ column ] ) > 0.0 & &
point . breakdown . earlyParallelLoss < base . breakdown . earlyParallelLoss & &
( ! wellboreRecheck | | ( point . fitness < = recheckTotalLimit & &
point . breakdown . shapeLoss < = recheckShapeLimit ) ) ;
( ! wellboreRecheck | | point . breakdown . shapeLoss < = recheckShapeLimit ) ;
}
return shapeStage
? point . breakdown . shapeLoss < base . breakdown . shapeLoss & & point . fitness < = shapeValueLimit
? point . breakdown . shapeLoss < base . breakdown . shapeLoss
// 预调整结束后恢复原 LM: 有效候选只按整体误差下降接受。
: point . fitness < base . fitness ;
} ;
@ -2374,7 +2371,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
wellboreRecheck = false ;
effectiveImprovementBaseline = current . fitness ;
reuseSensitivityForNextStage ( ) ;
// 初调、回检只测井储/表皮 ;所有出口都在当前点重建完整 J, 不能把缺列模型带入整体 LM。
// 第二阶段只测各子阶段需要的列 ;所有出口都在当前点重建完整 J, 不能把缺列模型带入整体 LM。
jacobian . clear ( ) ;
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " full sensitivity at total-stage entry " ) ;
@ -2408,7 +2405,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
initialEarlyGapBias = trustRegionEarlyGapBias ( current . breakdown ) ;
earlyGapDirection = trustRegionEarlyGapDirection ( initialEarlyGapBias ) ;
earlyShapeHasImproved = false ;
recheckTotalLimit = current . fitness + qMax ( 1.0e-4 , 0.05 * current . fitness ) ;
// 回检只约束形状:允许总误差上升,但保护其他参数已调好的整体形状。
recheckShapeLimit = current . breakdown . shapeLoss + qMax ( 1.0e-4 , 0.05 * current . breakdown . shapeLoss ) ;
effectiveImprovementBaseline = current . breakdown . earlyParallelLoss ;
// 其他参数已改变,回检入口重测形状灵敏度,方向由本轮初始间距重新确定。
@ -2416,9 +2413,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
reuseSensitivityForNextStage ( ) ;
rebuildRequested = true ;
rebuildReason = QT_TR_NOOP ( " new sensitivity for wellbore recheck " ) ;
emit logMessageGenerated ( tr ( " Wellbore recheck: early error=%1, total limit=%2, shape limit=%3 ." )
emit logMessageGenerated ( tr ( " Wellbore recheck: early shape error=%1, shape limit=%2 ." )
. arg ( current . breakdown . earlyParallelLoss , 0 , ' g ' , 6 )
. arg ( recheck TotalLimit, 0 , ' g ' , 6 ) . arg ( recheck ShapeLimit, 0 , ' g ' , 6 ) ) ;
. arg ( recheck ShapeLimit, 0 , ' g ' , 6 ) ) ;
writeTraceRow ( m_currentIteration , - 1 , " stage_switch " , current . parameters , current . fitness ,
true , 0 , " shape_to_wellbore_recheck " , & current . breakdown ) ;
announceEarlyGapDirection ( ) ;
@ -2451,8 +2448,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
return ;
}
effectiveImprovementBaseline = current . breakdown . shapeLoss ;
// 井储、表皮可使总误差上升;联合形状阶段从当前工作点建立固定上限。
shapeValueLimit = current . fitness + qMax ( 0.02 , 0.25 * current . fitness ) ;
reuseSensitivityForNextStage ( ) ;
emit logMessageGenerated ( tr ( " Shape fitting continues with storage and skin fixed; a conditional wellbore recheck follows. " ) ) ;
writeTraceRow ( m_currentIteration , - 1 , " stage_switch " , current . parameters , current . fitness ,
@ -2567,6 +2562,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
auto rebuildSensitivity = [ & ] ( ) - > bool {
// 第二阶段差分不受第三阶段额度限制;每列仍只有有限的缩步和反向重试。
const int evaluationLimit = shapeStage ? ( std : : numeric_limits < int > : : max ) ( ) : maximumEvaluations ;
const int sensitivityColumnCount = shapeStage
? ( earlyShapeStage ? wellboreParameterCount : dimensions - wellboreParameterCount ) : dimensions ;
const TrustRegionEvaluation base = current ;
const QVector < double > baseResidual = trustRegionFullResidual ( base . breakdown ) ;
const int residualCount = baseResidual . size ( ) ;
@ -2594,6 +2591,8 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
+ + column ) {
const int parameterIndex = m_enabledParamIndices [ column ] ;
if ( earlyShapeStage & & parameterIndex ! = 1 & & parameterIndex ! = 2 ) continue ;
// 普通形状阶段跳过冻结的井储、表皮,避免无用正演;回检和整体阶段会重新差分。
if ( shapeStage & & ! earlyShapeStage & & ! parameterAllowedInStage ( column ) ) continue ;
const double lower = m_parameterLower [ parameterIndex ] ;
const double upper = m_parameterUpper [ parameterIndex ] ;
if ( upper < = lower ) continue ;
@ -2681,7 +2680,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
jacobianColumnValid [ column ] = true ;
columnBuilt = true ;
// 其他参数仍建立灵敏度供后续复用,但 不能绕过当前子阶段的选参限制。
// 前期同时测井储和表皮,但缓存探针 不能绕过当前子阶段的选参限制。
// 前期首次正式调整必须从小步开始,测形状灵敏度的大探针不能提前成为工作点。
if ( ( ! earlyShapeStage | | earlyShapeHasImproved ) & &
parameterAllowedInStage ( column ) & & acceptable ( probe , base ) & &
@ -2733,8 +2732,9 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
& current . breakdown ) ;
emit logMessageGenerated (
( earlyShapeStage ? tr ( " Sensitivity probe accepted: early shape error=%1 " )
: tr ( " Sensitivity probe accepted: total error=%1 " ) )
. arg ( earlyShapeStage ? current . breakdown . earlyParallelLoss : current . fitness , 0 , ' e ' , 4 ) ) ;
: ( shapeStage ? tr ( " Sensitivity probe accepted: shape error=%1 " )
: tr ( " Sensitivity probe accepted: total error=%1 " ) ) )
. arg ( stageError ( current ) , 0 , ' e ' , 4 ) ) ;
} else {
restoreEvaluationState ( current ) ;
}
@ -2751,7 +2751,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
emit logMessageGenerated (
tr ( " Sensitivity model rebuilt: %1/%2 parameter columns valid " )
. arg ( validColumnCount )
. arg ( dimensions ) ) ;
. arg ( sensitivityColumnCount ) ) ;
return true ;
} ;
@ -2772,7 +2772,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( shapeStage & & ! earlyShapeStage & & ! jointShapeStarted ) {
jointShapeStarted = true ;
shapeRoundBaseline = current . breakdown . shapeLoss ;
// 初调已改变井储/表皮,普通形状必须在新的工作点 测完整 响应。
// 初调已改变井储/表皮,普通形状必须在新的工作点 重测其余可调参数的 响应。
jacobian . clear ( ) ;
reuseSensitivityForNextStage ( ) ;
rebuildRequested = true ;
@ -2819,11 +2819,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
: LM_LOCAL_OPTIMUM ;
break ;
}
if ( shapeStage & & ! earlyShapeStage & & current . fitness < m_targetError ) {
finishShapeStage ( tr ( " total target reached during shape fitting " ) ) ;
- - iteration ;
continue ;
}
if ( ! shapeStage & & current . fitness < m_targetError ) {
promoteSampling ( true ) ;
stopReason = LM_TARGET_ACHIEVED ;
@ -2956,37 +2951,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
: buildTrustRegionFisherStep ( stepInformation , columns , current . coordinates ,
damping , trustRadius , minimumCoordinateStep , & step , & reduction ) ;
if ( ! stepBuilt ) continue ;
// 仅联合形状阶段预测总误差上限;井储、表皮步长不受总误差裁剪。
if ( shapeStage & & ! earlyShapeStage ) {
auto predictedGuard = [ & ] ( double scale ) - > double {
double energy = 0.0 ;
for ( int row = 0 ; row < current . breakdown . residualVector . size ( ) ; + + row ) {
double value = current . breakdown . residualVector [ row ] ;
for ( int column = 0 ; column < dimensions ; + + column )
value + = scale * jacobian [ row ] [ column ] * step [ column ] ;
energy + = value * value ;
}
return qSqrt ( energy ) ;
} ;
const double currentGuard = predictedGuard ( 0.0 ) ;
const double predictedLimit = currentGuard + 0.9 * qMax ( 0.0 , shapeValueLimit - currentGuard ) ;
if ( predictedGuard ( 1.0 ) > predictedLimit ) {
double low = 0.0 , high = 1.0 ;
for ( int search = 0 ; search < 32 ; + + search ) {
const double middle = 0.5 * ( low + high ) ;
if ( predictedGuard ( middle ) < = predictedLimit ) low = middle ;
else high = middle ;
}
const double stepScale = low ;
for ( int column = 0 ; column < dimensions ; + + column ) step [ column ] * = stepScale ;
if ( qSqrt ( trustRegionSquaredNorm ( step ) ) < minimumCoordinateStep ) continue ;
reduction = - trustRegionDotProduct ( stepInformation . gradient , step ) ;
for ( int a = 0 ; a < dimensions ; + + a )
for ( int b = 0 ; b < dimensions ; + + b )
reduction - = 0.5 * step [ a ] * stepInformation . matrix [ a ] [ b ] * step [ b ] ;
if ( ! isFiniteNumber ( reduction ) | | reduction < = 1.0e-14 ) continue ;
}
}
const double tolerance = 1.0e-12 * qMax ( predictedReduction , reduction ) ;
if ( selectedColumns . isEmpty ( ) | | reduction > predictedReduction + tolerance | |
( qAbs ( reduction - predictedReduction ) < = tolerance & &
@ -3141,7 +3105,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
}
// 普通形状步真实表现可靠时,沿同一联合方向最多扩步试算一次,不区分参数类型。
// 扩步 仍须通过固定总误差上限且优于原步 ,否则保留原候选。
// 扩步 只按整体形状验收,优于原步才替换 ,否则保留原候选。
if ( shapeStage & & ! earlyShapeStage & & acceptable ( candidate , current ) & & processPauseAndStop ( ) ) {
const double ordinaryEnergy = 0.5 * trustRegionSquaredNorm ( objectiveResidual ) ;
const double ordinaryReduction = ordinaryEnergy - 0.5 * trustRegionSquaredNorm ( candidate . breakdown . shapeResiduals ) ;
@ -3286,7 +3250,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
. arg ( iteration + 1 )
. arg ( componentDisplayName )
. arg ( selectedColumns . size ( ) )
. arg ( earlyShapeStage ? candidate . breakdown . earlyParallelLoss : candidate . fitness , 0 , ' e ' , 4 )
. arg ( stageError( candidate ) , 0 , ' e ' , 4 )
. arg ( accepted ? tr ( " accepted " ) : tr ( " rejected " ) ) ) ;
emit progressUpdated ( shapeStage ? - 1 : totalIterations , m_globalBestFitness ) ;
@ -3306,9 +3270,6 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
if ( stopReason = = LM_LOCAL_OPTIMUM | | samplingRefreshFailed ) break ;
}
if ( shapeStage & & ! earlyShapeStage & & current . fitness < m_targetError ) {
finishShapeStage ( tr ( " total target reached during shape fitting " ) ) ;
}
if ( ! shapeStage & & current . fitness < m_targetError ) {
promoteSampling ( true ) ;
stopReason = LM_TARGET_ACHIEVED ;
@ -3337,7 +3298,7 @@ StopReasonLM nmCalculationAutoFitLM::runTrustRegionFitting()
return LM_USER_STOPPED ;
}
if ( samplingRefreshFailed ) return LM_OPTIMIZATION_FAILED ;
if ( current . fitness < m_targetError ) {
if ( ! shapeStage & & current . fitness < m_targetError ) {
promoteSampling ( true ) ;
return samplingRefreshFailed ? LM_OPTIMIZATION_FAILED : LM_TARGET_ACHIEVED ;
}