You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Include/nmNum/nmCalculation/nmCalculationAutoFitLM.h

209 lines
6.5 KiB
C

#ifndef NMCALCULATIONAUTOFITLM_H
#define NMCALCULATIONAUTOFITLM_H
#include <QObject>
#include <QVector>
#include <QPointF>
#include <QString>
#include <QStringList>
#include <QFile>
#include <limits>
#include "nmCalculation_global.h"
class nmDataWellBase;
// 双对数曲线误差分解。total 是 LM 候选接受和排序的唯一依据;时间窗口误差
// 用于细搜选参,原有上下、左右和形状量仅保留为过程诊断。
struct AutoFitObjectiveBreakdownLM {
bool valid;
double total;
double pressureLoss;
double derivativeLoss;
QVector<double> residualVector;
QVector<int> timeWindowBegin;
QVector<int> timeWindowEnd;
QVector<double> timeWindowStart;
QVector<double> timeWindowEndTime;
QVector<double> timeWindowPressureLoss;
QVector<double> timeWindowDerivativeLoss;
QVector<double> timeWindowLoss;
double verticalCommonBias;
double verticalLoss;
bool verticalReliable;
double horizontalPhysicalShift;
double horizontalLoss;
bool horizontalReliable;
bool registrationAmbiguous;
double shapeLoss;
double lateDerivativeSlopeBias;
double lateDerivativeTrendLoss;
bool lateDerivativeTrendReliable;
double coverage;
AutoFitObjectiveBreakdownLM()
: valid(false)
, total(1.0e10)
, pressureLoss(std::numeric_limits<double>::quiet_NaN())
, derivativeLoss(std::numeric_limits<double>::quiet_NaN())
, verticalCommonBias(std::numeric_limits<double>::quiet_NaN())
, verticalLoss(std::numeric_limits<double>::quiet_NaN())
, verticalReliable(false)
, horizontalPhysicalShift(std::numeric_limits<double>::quiet_NaN())
, horizontalLoss(std::numeric_limits<double>::quiet_NaN())
, horizontalReliable(false)
, registrationAmbiguous(false)
, shapeLoss(std::numeric_limits<double>::quiet_NaN())
, lateDerivativeSlopeBias(std::numeric_limits<double>::quiet_NaN())
, lateDerivativeTrendLoss(std::numeric_limits<double>::quiet_NaN())
, lateDerivativeTrendReliable(false)
, coverage(std::numeric_limits<double>::quiet_NaN())
{}
};
// 有限差分 + LM/信赖域拟合的停止原因。
enum StopReasonLM {
LM_CONTINUE_OPTIMIZATION = 0,
LM_TARGET_ACHIEVED = 1,
LM_TRUE_CONVERGENCE = 2,
LM_LOCAL_OPTIMUM = 3,
LM_MAX_ITERATIONS = 4,
LM_USER_STOPPED = 5,
LM_CONSECUTIVE_FAILURES = 6,
LM_OPTIMIZATION_FAILED = 7
};
class NMCALCULATION_EXPORT nmCalculationAutoFitLM : public QObject
{
Q_OBJECT
public:
explicit nmCalculationAutoFitLM(QObject* parent = 0);
~nmCalculationAutoFitLM();
void setTargetLogLogData(const QVector<QVector<double> >& targetData);
bool startAutoFitting();
void stopFitting();
QVector<double> getBestSolution() const;
double getBestFitness() const;
AutoFitObjectiveBreakdownLM getLastObjectiveBreakdown() const;
QString getLastError() const;
bool isRunning() const;
int getCurrentIteration() const;
int getTotalEvaluations() const;
void resetOptimizer();
void setTargetWellName(const QString& wellName);
signals:
void progressUpdated(int iteration, double bestFitness);
void fittingFinished(bool success, const QString& message);
void bestCurveUpdated(QVector<QVector<double> > targetData,
QVector<QVector<double> > bestData,
int iteration,
double fitness);
void logMessageGenerated(const QString& message);
private:
void initializeTemporaryDirectory();
void cleanupTemporaryDirectory();
bool removeDirectoryRecursively(const QString& path);
void cleanupOldTemporaryDirectories();
bool loadAllConfigFromDataManager();
void loadOptimizationConfig();
void loadParameterBounds();
void extractUserInitialValues();
// 有限差分 + LM/信赖域核心算法。
StopReasonLM runTrustRegionFitting();
bool evaluateTrustRegionPoint(const QVector<double>& parameters,
double* fitness,
AutoFitObjectiveBreakdownLM* breakdown,
QVector<QVector<double> >* curve,
int* elapsedMs);
double evaluateFitness(const QVector<double>& parameters);
void applyParametersToDataManager(const QVector<double>& parameters);
void updateReservoirParameters(const QVector<double>& parameters);
void updateWellParameters(const QVector<double>& parameters);
void updateWellToDataManager(nmDataWellBase* pWell);
QVector<QVector<double> > runSolver();
QVector<QVector<double> > runSolverDll();
bool runFinalFullSolver();
void saveOptimizationResult();
void validateAndProtectFinalResult();
QString getStopReasonDescription(StopReasonLM reason) const;
int getEnabledParameterCount() const;
// LM 运行轨迹。
void initializeTraceFile();
void closeTraceFile();
void writeTraceHeader();
void writeTraceMetaFile();
void writeTraceRow(int iteration,
int parameterIndex,
const QString& phase,
const QVector<double>& parameters,
double solverObjective,
bool solverSuccess,
int elapsedMs,
const QString& decision,
const AutoFitObjectiveBreakdownLM* objectiveBreakdown = nullptr);
QVector<double> buildTraceParameterVector(const QVector<double>& selectedParameters) const;
void emitRunSummary(bool success, StopReasonLM finalReason);
bool validateParameters(const QVector<double>& parameters) const;
bool validateLogLogData(const QVector<QVector<double> >& logLogData) const;
bool validateInitialValues() const;
bool validateSolverResult(const QVector<QVector<double> >& result) const;
double calculateLogLogCurveError(const QVector<QVector<double> >& target,
const QVector<QVector<double> >& result) const;
private:
bool m_isRunning;
bool m_shouldStop;
int m_currentIteration;
QString m_lastError;
QVector<double> m_initialValues;
QVector<double> m_globalBestPosition;
double m_globalBestFitness;
AutoFitObjectiveBreakdownLM m_globalBestObjectiveBreakdown;
QVector<QVector<double> > m_lastEvaluatedLogLogData;
QVector<QVector<double> > m_globalBestLogLogData;
mutable AutoFitObjectiveBreakdownLM m_lastObjectiveBreakdown;
QVector<QVector<double> > m_userInitialLogLogData;
AutoFitObjectiveBreakdownLM m_userInitialObjectiveBreakdown;
// 参数索引0 k1 skin2 wellboreC3 phi4 h5 Ct
// 6 Cf7 Swi8 Dfc9 fractureHalfLength。
QVector<bool> m_parameterSelected;
QVector<double> m_parameterLower;
QVector<double> m_parameterUpper;
QVector<int> m_enabledParamIndices;
QVector<QVector<double> > m_targetLogLogData;
QString m_targetWellName;
int m_maxIterations;
double m_targetError;
int m_totalEvaluations;
int m_successfulEvaluations;
volatile int m_evaluationInProgress;
int m_consecutiveFailures;
int m_maxConsecutiveFailures;
QVector<double> m_userInitialSolution;
double m_userInitialFitness;
bool m_hasValidUserSolution;
QString m_tempDirectory;
QString m_traceRunId;
QString m_traceFilePath;
QString m_traceMetaFilePath;
QFile m_traceFile;
};
#endif // NMCALCULATIONAUTOFITLM_H