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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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