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/nmData/nmDataAnalyzeManager.h

944 lines
38 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 NMDATAANALYZEMANAGER_H
#define NMDATAANALYZEMANAGER_H
#include <QObject>
#include "ZxDataObjectBin.h"
#include "nmData_global.h"
#include "nmDefines.h"
#include "nmDataVerticalWell.h"
#include "nmDataHorizontalWell.h"
#include "nmDataVerticalFracturedWell.h"
#include "nmDataHorizontalFracturedWell.h"
#include "nmDataNumericalAnalysisCase.h"
#include "nmNumericalResultPersistence.h"
#include "nmDataGaugeRecord.h"
#include "nmGridDefine.h"
#include <QMap>
#include <QVector>
#include <QPointF>
#include <QRectF>
#include <QPair>
#include <QString>
#include <QStringList>
#include <QList>
#include <QMutex>
#include <QSharedPointer>
#include <QWaitCondition>
#include <vector>
#include <vtkUnstructuredGrid.h>
#include <vtkSmartPointer.h>
// 子类别显示信息结构
struct ChildCategoryDisplayInfo {
QString name; // 子项名称
bool isChecked; // 子项是否选中
bool isEnabled; // 子项是否启用 (取决于父项的选中状态)
};
// 类别显示信息结构
struct CategoryDisplayInfo {
bool isRootChecked; // 根节点是否选中
QVector<ChildCategoryDisplayInfo> childItems; // 子节点信息列表
};
// 整体
struct DisplaySetting {
QString key;
CategoryDisplayInfo value;
};
// 油藏地图显示信息结构体
struct BackgroundImageInfo {
bool bIsVisible; // 是否显示背景图片到地图
QString sFilePath; // 背景图片的文件路径
QImage objImage; // 具体的QImage对象
};
/* 插值测点数据 */
struct NM_DATA_EXPORT nmPropertyInterpolationPointData {
nmPropertyInterpolationPointData()
: x(0.0), y(0.0), value(0.0)
{
}
nmPropertyInterpolationPointData(double xValue, double yValue, double propertyValue)
: x(xValue), y(yValue), value(propertyValue)
{
}
double x;
double y;
double value;
};
/* 一组属性插值数据及其Kriging参数 */
struct NM_DATA_EXPORT nmPropertyInterpolationDataSet {
nmPropertyInterpolationDataSet()
: property("k"),
xDisplayUnit("m"),
yDisplayUnit("m"),
valueDisplayUnit("mD"),
rangeDisplayUnit("m"),
useForCalculation(false),
showPoints(true),
showLabels(true),
nugget(0.01),
sill(100.0),
range(1000.0),
model(0)
{
}
QString name;
QString property;
// 仅记录界面显示单位坐标、Range及属性值始终按基准单位保存.
QString xDisplayUnit;
QString yDisplayUnit;
QString valueDisplayUnit;
QString rangeDisplayUnit;
bool useForCalculation;
QVector<nmPropertyInterpolationPointData> points;
bool showPoints;
bool showLabels;
double nugget;
double sill;
double range;
int model;
};
enum NM_SOLVER_MODEL_TYPE {
SMT_Oil_ConstPvt = 1,
SMT_Oil_VariablePvt = 2,
SMT_Water_ConstPvt = 3,
SMT_Water_VariablePvt = 4,
SMT_Gas_VariablePvt = 5,
SMT_Gas_PseudoPressure = 6,
SMT_Oil_Gas_TwoPhase = 7,
SMT_Oil_Water_TwoPhase = 8,
SMT_Gas_Water_TwoPhase = 9,
SMT_Oil_Gas_Water_ThreePhase = 10
};
/** @brief 判断求解模型是否包含指定工程井别对应的流量相。 */
inline bool nmSolverModelSupportsWellCategory(
NM_SOLVER_MODEL_TYPE eSolverModelType,
NM_WELL_CATEGORY eWellCategory)
{
switch(eSolverModelType) {
case SMT_Oil_ConstPvt:
case SMT_Oil_VariablePvt:
return eWellCategory == NM_WellCategory_Oil;
case SMT_Water_ConstPvt:
case SMT_Water_VariablePvt:
return eWellCategory == NM_WellCategory_Water;
case SMT_Gas_VariablePvt:
case SMT_Gas_PseudoPressure:
return eWellCategory == NM_WellCategory_Gas;
case SMT_Oil_Gas_TwoPhase:
return eWellCategory == NM_WellCategory_Oil ||
eWellCategory == NM_WellCategory_Gas;
case SMT_Oil_Water_TwoPhase:
return eWellCategory == NM_WellCategory_Oil ||
eWellCategory == NM_WellCategory_Water;
case SMT_Gas_Water_TwoPhase:
return eWellCategory == NM_WellCategory_Gas ||
eWellCategory == NM_WellCategory_Water;
case SMT_Oil_Gas_Water_ThreePhase:
return nmIsValidWellCategory(eWellCategory);
default:
return false;
}
}
class nmDataWellBase;
class ZxDataWell;
class nmDataReservoir;
class nmDataRegionMark;
class nmDataRegion;
class nmDataOutline;
class nmDataFracture;
class nmDataFault;
class nmDataAxis;
class nmGuiPlot;
class nmDataMeasuringScale;
class nmDataMeasure;
class nmDataPvtParaForPebi;
class nmDataMixedResults;
class nmDataLayer;
class nmDataGeoRef;
class nmDataAutomaticFitting;
class nmDataDiagnostic;
class nmDataForecast;
class ZxDataWell;
class iSubWndFitting;
class nmDataTimeStepSetting;
class nmDataSensitive;
class nmAttrRegistry;
class nmPebiResultSnapshot;
struct nmPebiResultWellSnapshot;
class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
{
ZX_DECLARE_DYNAMIC
Q_OBJECT
public:
/** @brief PEBI线性求解器类型稳定编码。 */
enum PebiSolverType
{
PebiSolverCpuAccelerated = 1,
PebiSolverOriginal = 2
};
nmDataAnalyzeManager();
// 释放当前流动段分析独占的数据对象
~nmDataAnalyzeManager();
// 分析窗口和数据管理器的映射关系
static QMap<iSubWndFitting*, nmDataAnalyzeManager*> s_mapDataAnalManager;
// 当前操作的分析窗体
static iSubWndFitting* s_pCurSubWndFitting;
// 根据流动段分析窗口的指针作为唯一标识
static nmDataAnalyzeManager* getInstanceByFitting(iSubWndFitting* pSubWndF);
// 流动段分析窗口销毁后,移除并释放对应的数据管理器
static void removeInstanceByFitting(iSubWndFitting* pSubWndF);
/**
* @brief 根据流动段分析窗口指针key查找对应的分析管理器实例value
* @param pSubWndF 流动段分析窗口指针作为key
* @return 返回对应的 nmDataAnalyzeManager 实例指针,如果未找到则返回 nullptr
*/
static nmDataAnalyzeManager* findManagerByFitting(iSubWndFitting* pSubWndF)
{
return s_mapDataAnalManager.value(pSubWndF, nullptr);
}
static iSubWndFitting* getCurrentFitting()
{
return s_pCurSubWndFitting;
}
static void setCurrentFitting(iSubWndFitting* pSubWndF)
{
s_pCurSubWndFitting = pSubWndF;
}
// 获取当前分析窗体下的指针
static nmDataAnalyzeManager* getCurrentInstance();
/**
* @brief 枚举工程井下全部压力、流量测量记录并逐条判定可用状态。
* @note 仅当工程井对象为空或井别无效时返回 false单条记录损坏/为空
* 不影响返回值,只会体现为该记录的 eStatus。
*/
static bool readFrameworkWellCurves(
ZxDataWell* pWellData,
QVector<nmPressureGaugeRecord>& vecPressureRecords,
QVector<nmFlowGaugeRecord>& vecFlowRecords,
NM_WELL_CATEGORY& eWellCategory);
/**
* @brief 将枚举到的记录列表写入数值井,并按默认规则选中压力/流量记录。
* @note 找不到任何可用记录时仍会写入列表,只是选中 Code 为空,不阻止建井。
*/
static void applyGaugeRecordsToWell(
nmDataWellBase* pWellData,
const QVector<nmPressureGaugeRecord>& vecPressureRecords,
const QVector<nmFlowGaugeRecord>& vecFlowRecords);
// 井的接口
// 添加井
nmDataWellBase* createWell(NM_WELL_MODEL eWellType);
nmDataWellBase* changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType);
/**
* @brief 判断指定井是否为创建数值分析时绑定的固定主井。
* @note 主井身份只按 PrimaryWellCode 判断,与当前查看井无关。
*/
bool isPrimaryWell(const nmDataWellBase* pWellData) const;
/**
* @brief 判断指定实时井是否允许从当前数值分析中删除。
* @note 只有本管理器拥有且不是固定主井的井才允许删除。
*/
bool canRemoveWell(const nmDataWellBase* pWellData) const;
/**
* @brief 删除一口非主分析井。
* @return 删除成功返回 true主井、空指针或非本管理器井返回 false。
*/
bool removeWell(nmDataWellBase* pWellData);
/** @brief 同时移除一口非主分析井的图元和实时数据。 */
void removeWellDataAndPlot(nmDataWellBase* pWellData);
/**
* @brief 清空所有井数据
* @note 会删除所有井对象并清空数组
*/
void clearAllWellData();
// 获取井的数据
QVector<nmDataWellBase*> getWellDataList() const;
// 井副本数据
//QVector<nmDataWellBase> getWellDataListCopy() const;
// TODO:有问题,不会更新不同类型的井数据
//void updateWellData(const QVector<nmDataWellBase>& newData);
/** @brief 按稳定 UUID 回写直井数据,并恢复井与最后结果快照的弱关联。 */
void updateVerticalWells(const QVector<nmDataVerticalWell>& wells);
/** @brief 按稳定 UUID 回写压裂直井数据,并恢复井与最后结果快照的弱关联。 */
void updateVerticalFracturedWells(const QVector<nmDataVerticalFracturedWell>& wells);
/** @brief 按稳定 UUID 回写多段压裂水平井数据,并恢复井与最后结果快照的弱关联。 */
void updateHorizontalFracturedWells(const QVector<nmDataHorizontalFracturedWell>& wells);
// 返回分类后的井数据
// 获取所有直井数据
QVector<nmDataVerticalWell*> getVerticalWellData() const;
// 获取所有垂直裂缝井数据
QVector<nmDataVerticalFracturedWell*> getVerticalFracturedWellData() const;
// 获取所有多段压裂水平井数据
QVector<nmDataHorizontalFracturedWell*> getHorizontalFracturedWellData() const;
// 通过井的名称查找井数据
//nmDataWellBase* findWellByName(const QString& wellName) const;
nmDataWellBase* findWellByName(QString wellName) const;
/**
* @brief 通过项目唯一井编码查找井数据。
* @note 数值计算、网格和结果关联必须调用该接口;井名查找只保留给界面显示逻辑。
*/
nmDataWellBase* findWellByCode(const QString& sWellCode) const;
/**
* @brief 通过井对象稳定 UUID 查找当前实时井。
* @note 结果界面用该接口判断快照井是否已删除;井编码或名称不能替代 UUID。
*/
nmDataWellBase* findWellByInstanceId(
const QString& sWellInstanceId) const;
// 初始化测试井数据,即点击数值解的时候,将当前井添加到里面
void initCurWellData();
/**
* @brief 按需把项目井加入数值 Map并复制对应的流量和压力数据。
* @return 已存在或成功创建的数值井;井型不支持时返回空指针。
*/
nmDataWellBase* appendWellData(ZxDataWell* pWellData);
// 直接添加自定义的井数据
void appendNmWellData(nmDataWellBase* pWellData);
/**
* @brief 原子替换一口数值井并同步当前井、计算井和属性注册表。
* @param pOldWell 被替换对象,成功后删除。
* @param pNewWell 新对象,必须预先保留与旧井相同的 UUID成功后由管理器接管所有权。
* @return 替换成功返回true失败时两个对象所有权均不改变。
*/
bool replaceWellData(nmDataWellBase* pOldWell,
nmDataWellBase* pNewWell);
// 初始化油藏参数
void createReservoir();
// 获取油藏参数
nmDataReservoir* getReservoirData() const;
// 返回油藏副本数据
nmDataReservoir getReservoirDataCopy() const;
void updateReservoirData(const nmDataReservoir& newData);
// 初始化坐标轴参数
nmDataAxis* getAxisData() const;
void setAxisData(nmDataAxis* pAxisData);
// 从流动段分析窗口获取对应的PVT相关数据
void initPvtParaFromSubFit();
// 初始化区域标记参数
nmDataRegionMark* createRegionMark();
// 获取区域标记数据
QVector<nmDataRegionMark*> getRegionMarkDataList() const;
// 移除区域标记数据
bool removeRegionMarkData(nmDataRegionMark* pData);
// 返回区域标记副本数据
QVector<nmDataRegionMark> getRegionMarkDataListCopy() const;
void updateRegionMarkData(const QVector<nmDataRegionMark>& newData);
// 初始化边界数据
nmDataOutline* createOutline();
nmDataOutline* getOutlineData();
/** @brief 按当前数值井包围盒及四周 1500m 留量创建一次性默认矩形边界。 */
bool createDefaultOutlineFromWells();
/** @brief 计算当前数值分析全部有效井位置的包围盒。 */
bool calculateNumericalWellBounds(QRectF& oBounds) const;
// 移除边界数据
bool removeOutlineData();
// 返回边界副本数据
nmDataOutline getOutlineDataCopy() const;
void updateOutlineData(const nmDataOutline& newData);
// 初始化复合区数据
nmDataRegion* createRegion();
// 获取复合区数据
QVector<nmDataRegion*> getRegionDataList() const;
// 移除复合区数据
bool removeRegionData(nmDataRegion* pData);
// 返回复合区副本数据
QVector<nmDataRegion> getRegionDataListCopy() const;
void updateRegionData(const QVector<nmDataRegion>& newData);
// 初始化裂缝数据
nmDataFracture* createFracture();
// 获取所有裂缝数据
QVector<nmDataFracture*> getFractureDataList() const;
// 获取DNF生成的裂缝数据
QVector<nmDataFracture*> getDFNFractureDataList() const;
// 移除裂缝数据
bool removeFractureData(nmDataFracture* pData);
// 返回裂缝副本数据
QVector<nmDataFracture> getFractureDataListCopy() const;
void updateFractureData(const QVector<nmDataFracture>& newData);
// 初始化断层数据
nmDataFault* createFault();
// 获取断层数据
QVector<nmDataFault*> getFaultDataList() const;
// 移除断层数据
bool removeFaultData(nmDataFault* pData);
// 返回断层数据副本
QVector<nmDataFault> getFaultDataListCopy() const;
// 更新断层数据
void updateFaultData(const QVector<nmDataFault>& newData);
// 绘图
nmGuiPlot* getPlot() const;
void setPlot(nmGuiPlot* plot);
// 更新井图元
void updateWellPlotByDataManager();
// 获取所有可连接的点(Value实际坐标)
QVector<QPointF> getValueAllConnectablePoints();
// 获取所有可连接的点(Pos屏幕坐标)
QVector<QPointF> getPosAllConnectablePoints();
// 根据传入的指针,去掉对应的点的坐标
QVector<QPointF> removePosByObject(QObject* obj);
// 比例尺数据对象相关
nmDataMeasuringScale* getMeasuringScaleData();
void setMeasuringScaleData(nmDataMeasuringScale *pMeasuringScaleData);
// 测量相关
nmDataMeasure* getMeasureData();
void setMeasureData(nmDataMeasure *pMeasureData);
bool removeMeasureData();
// 模型参考点相关
nmDataGeoRef* createGeoRefData();
nmDataGeoRef* getGeoRefData() const;
nmDataGeoRef getGeoRefDataCopy() const;
void updateGeoRefData(const nmDataGeoRef& newData);
// 预测相关
nmDataForecast* createForecastData();
nmDataForecast* getForecastData() const;
nmDataForecast getForecastDataCopy() const;
void updateForecastData(const nmDataForecast& newData);
// 敏感性分析相关
nmDataSensitive* createSensitiveData();
nmDataSensitive* getSensitiveData() const;
nmDataSensitive getSensitiveDataCopy() const;
void updateSensitiveData(const nmDataSensitive& newData);
// 自动拟合相关
nmDataAutomaticFitting* createAutomaticFittingData();
nmDataAutomaticFitting* getAutomaticFittingData() const;
nmDataAutomaticFitting getAutomaticFittingDataCopy() const;
void updateAutomaticFittingData(const nmDataAutomaticFitting& newData);
// 诊断参数相关
nmDataDiagnostic* getDiagnosticData() const;
// 应用诊断结果
void applyDiagnosticResults(nmDataDiagnostic* diagnostic, nmDataWellBase* wellData, nmDataReservoir* reservoirData);
// 重置功能相关方法
bool resetFromDiagnostic(); // 诊断重置业务逻辑
bool resetFromAnalytical(); // 分析重置业务逻辑
// 网格类型
NM_Grid_Type getGridType();
void setGridType(NM_Grid_Type newGridType);
// 求解模型类型
NM_SOLVER_MODEL_TYPE getSolverModelType() const;
void setSolverModelType(NM_SOLVER_MODEL_TYPE newSolverModelType);
/** @brief 获取PEBI求解器类型1为CPU加速求解器2为原求解器。 */
int getPebiSolverType() const;
/** @brief 设置PEBI求解器类型。 */
void setPebiSolverType(int nSolverType);
/** @brief 获取PEBI求解器的OpenMP线程数。 */
int getPebiOmpThreads() const;
/** @brief 设置PEBI求解器的OpenMP线程数。 */
void setPebiOmpThreads(int nOmpThreads);
/** @brief 获取PEBI求解器的ILU复用步数。 */
int getPebiIluReuseSteps() const;
/** @brief 设置PEBI求解器的ILU复用步数。 */
void setPebiIluReuseSteps(int nIluReuseSteps);
// 获取Pebi网格求解数据接口
// 获取压力历史数据
QVector<QVector<double >> getPebiSolverHistoryDataByName(const QString& wellName);
// 获取压力对数信息
QVector<QVector<double >> getPebiSolverLogPreDataByName(const QString& wellName);
// 获取压力半对数数据
QVector<QVector<double >> getPebiSolverSemiLogPreDataByName(const QString& wellName);
// 获取PEBI求解器需要的pvt数据
nmDataPvtParaForPebi* getPebiPvtPara();
// 获取气单相变化 PVT 求解所需的压力/拟压力转换表。
bool getPebiPseudoPressureTable(std::vector<double>& pressure,
std::vector<double>& pseudoPressure);
// 获取混合结果参数
nmDataMixedResults* getMixedResults();
// 创建混合结果参数对象
nmDataMixedResults* createMixedResult();
// 获取储层数据
nmDataLayer* getLayerData();
// 添加多储层数据
void setLayers(QVector<nmDataLayer*> vecLayers);
// 获取多储层数据
QVector<nmDataLayer*> getLayers();
// 获取储层边界数据
double getMinLayerTop();
double getMaxLayerBottom();
// 在末尾追加一个新的井信息
void appendCalculationWell(const QPair<NM_WELL_MODEL, QString>& well);
// 在指定位置插入一个新的井信息
void insertCalculationWell(int index, const QPair<NM_WELL_MODEL, QString>& well);
// 移除指定位置的井信息
bool removeCalculationWell(int index);
// 清空容器
void clearCalculationWells();
// 返回井信息的副本
QVector<QPair<NM_WELL_MODEL, QString>> getCalculationWells() const;
// 查询当前计算井中是否有某口井
bool isContainsWellName(const QString& wellName) const;
/** @brief 返回当前窗口的数值分析方案,管理器保留对象所有权。 */
nmDataNumericalAnalysisCase* getNumericalAnalysisCase();
/** @brief 返回只读数值分析方案,管理器保留对象所有权。 */
const nmDataNumericalAnalysisCase* getNumericalAnalysisCase() const;
/** @brief 后台任务开始使用本管理器;与 endBackgroundUse() 必须成对调用。 */
void beginBackgroundUse();
/** @brief 后台任务结束使用本管理器;最后一个任务退出时唤醒析构等待。 */
void endBackgroundUse();
/**
* @brief 初始化固定主分析井 WellCode。
* @note 分析运行期间不允许清空或更换;整体 clear 后可重新初始化。
*/
void setPrimaryWellCode(const QString& sWellCode);
/** @brief 返回当前主分析井 WellCode。 */
QString getPrimaryWellCode() const;
/** @brief 启停手工包含的其他有产量井;不影响 Map 无产量观察井。 */
void setIncludeOtherWells(bool bInclude);
/** @brief 返回 Include Other Wells 总开关状态。 */
bool getIncludeOtherWells() const;
/** @brief 设置当前方案的 PEBI 网格疏密控制值。 */
void setPebiGridControl(double dGridControl);
/** @brief 返回当前方案的 PEBI 网格疏密控制值。 */
double getPebiGridControl() const;
/** @brief 保存其他有产量井选择;非法井、主井和无产量井会被过滤。 */
void setIncludedCalculationWells(const QVector<nmCalculationWellRef>& vecWells);
/** @brief 返回用户在 Include Other Wells 中保存的有产量井。 */
QVector<nmCalculationWellRef> getIncludedCalculationWells() const;
/** @brief 返回真实求解井:主井、全部 Map 无产量井及已包含主动井。 */
QVector<nmCalculationWellRef> getEffectiveCalculationWells() const;
/** @brief 从有效求解井集合查询井角色,未参与井按观察井返回。 */
NM_CASE_WELL_MODE getCalculationWellMode(const QString& sWellCode) const;
/** @brief 判断井是否属于当前真实求解井集合。 */
bool isWellSelectedForCalculation(const QString& sWellCode) const;
/** @brief 清空网格生成器写入的 DLL 井槽位顺序。 */
void clearSolverWellOrder();
/** @brief 向 DLL 井槽位顺序末尾追加一个真实井或裂缝条目。 */
void appendSolverWell(const nmSolverWellRef& oWellRef);
/** @brief 在指定 DLL 下标插入井或裂缝条目,并重新编号。 */
void insertSolverWell(int nIndex, const nmSolverWellRef& oWellRef);
/** @brief 返回网格确定的 DLL 井槽位顺序,与包含井选择相互独立。 */
QVector<nmSolverWellRef> getSolverWellOrder() const;
/** @brief 整体替换 DLL 井槽位顺序,并由分析方案统一重编号。 */
void setSolverWellOrder(const QVector<nmSolverWellRef>& vecSolverWellOrder);
/**
* @brief 按输入版本一次性提交后台生成的井顺序和 VTK 网格。
* @return 输入仍为当前版本且提交成功时返回 true过期结果不修改现有成果。
*/
bool commitPebiGridResult(
quint64 nGridInputRevision,
const QVector<nmSolverWellRef>& vecSolverWellOrder,
vtkSmartPointer<vtkUnstructuredGrid> pGrid);
/** @brief 主线程登记当前分析正在生成指定输入版本的 PEBI 网格。 */
void beginPebiGridGeneration(quint64 nGridInputRevision);
/** @brief 主线程结束当前建网活动,并通知等待同一分析的求解流程。 */
void endPebiGridGeneration(bool bSucceeded);
/** @brief 判断当前分析是否仍处于防抖等待、后台建网或待提交阶段。 */
bool isPebiGridGenerationActive() const;
/** @brief 将当前输入版本登记为已成功生成网格。 */
void markPebiGridBuilt();
/** @brief 仅在后台划分期间输入未变化时登记网格成功。 */
bool markPebiGridBuiltIfCurrent(quint64 nGridInputRevision);
/** @brief 几何或求解井集合变化后,使 PEBI 网格和结果失效。 */
void invalidatePebiGrid();
/** @brief 产量、PVT 等变化后,仅使 PEBI 结果失效。 */
void invalidatePebiResults();
/** @brief 判断当前 PEBI 网格是否与最新输入一致。 */
bool isPebiGridValid() const;
/** @brief 判断是否存在一套可保存和查看的 PEBI 结果。 */
bool hasPebiResults() const;
/** @brief 返回最后一次成功求解发布的完整只读结果快照。 */
QSharedPointer<const nmPebiResultSnapshot>
getPebiResultSnapshot() const;
/** @brief 是否已发布完整结果快照。 */
bool hasPebiResultSnapshot() const;
/** @brief 快照的网格和求解输入版本是否仍与当前输入一致。 */
bool isPebiResultSnapshotCurrent() const;
/** @brief 返回快照查看状态中的当前结果井 UUID。 */
QString getCurrentResultWellInstanceId() const;
/** @brief 按快照 UUID 切换结果井,空值表示选择第一口可显示井。 */
bool setCurrentResultWellInstanceId(
const QString& sWellInstanceId);
/**
* @brief 主线程按输入版本一次性发布完整结果快照。
* @note 无论成功或失败都会清空传入候选的可写引用;旧快照仅在成功时替换。
*/
bool commitPebiResultSnapshot(
QSharedPointer<nmPebiResultSnapshot>& pCandidate,
QString* pError = NULL);
/** @brief 清除最后结果快照及其结果井查看状态。 */
void clearPebiResultSnapshot();
// 设置当前查看井
void setCurWellData(nmDataWellBase* wellData);
// 获取当前查看井
nmDataWellBase* getCurWellData();
void notifyDataChanged();
/// @brief 对象新增或删除后刷新参数面板,并通知网格更新
void notifyGeometryListChanged();
/// @brief 仅刷新参数面板中的对象名称,避免改名触发网格重建
void notifyParameterObjectNameChanged();
/**
* @brief 设置显示设置信息。
* @param displaySettings 包含所有类别显示状态的QVector。
*/
void setDisplaySettings(const QVector<DisplaySetting>& displaySettings);
/**
* @brief 获取当前显示设置信息。
* @return 包含所有类别显示状态的QVector。
*/
QVector<DisplaySetting> getDisplaySettings() const;
/**
* @brief 更新单个类别的显示设置。
* @param categoryName 类别名称。
* @param info 要更新的CategoryDisplayInfo。
* @return 如果找到并更新了指定类别返回true否则返回false
*/
bool updateCategoryDisplaySetting(const QString& categoryName, const CategoryDisplayInfo& info);
// 初始化默认显示设置
void initDefaultDisplaySettings();
// 用于查找类别
CategoryDisplayInfo* findCategoryDisplayInfo(const QString& categoryName);
/**
* @brief 向显示设置向量中添加一个子元素。
* @param displaySetting 要添加的DisplaySetting结构。
* @return 添加成功返回true否则返回false如已存在相同key
*/
bool appendDisplaySetting(const DisplaySetting& displaySetting);
/**
* @brief 从显示设置向量中删除指定key的子元素。
* @param categoryName 要删除的类别的key。
* @return 删除成功返回true否则返回false如未找到
*/
bool removeDisplaySetting(const QString& categoryName);
/**
* @brief 为指定的父类别添加子项
* @param parentCategory 父类别名称(如"Wells", "Faults"等)
* @param childNames 要添加的子项名称列表
* @param defaultChecked 子项的默认选中状态
* @return 添加成功返回true如果父类别不存在则返回false
*/
bool nmDataAnalyzeManager::addChildItemsToCategory(const QString& parentCategory,
const QStringList& childNames,
bool defaultChecked);
// 刷新当前显示的子节点
void nmDataAnalyzeManager::refreshChildItemsDisplay();
void addWellChildItemsToCategory(const QString& parentCategory);
void addFaultChildItemsToCategory(const QString& parentCategory);
void addFractureChildItemsToCategory(const QString& parentCategory);
void addRegionChildItemsToCategory(const QString& parentCategory);
void addRegionMarkChildItemsToCategory(const QString& parentCategory);
/**
* @brief 设置所有类别的根节点可见性
* @param isVisible true为全部可见false为全部不可见
*/
void setAllCategoriesRootVisibility(bool bIsVisible);
// 设置背景图片信息
void setBackgroundImageInfo(const BackgroundImageInfo& info);
// 获取背景图片信息
const BackgroundImageInfo& getBackgroundImageInfo() const;
/* 获取及设置属性插值数据组 */
QVector<nmPropertyInterpolationDataSet> getPropertyInterpolationDataSets() const;
void setPropertyInterpolationDataSets(const QVector<nmPropertyInterpolationDataSet>& dataSets);
// 统一的读写整个项目数据的方法
// @param filePath JSON文件的路径
// @return 读取成功返回 true否则返回 false
bool ReadProjectData(const QString& filePath);
// 统一的写整个项目数据的方法
// @param filePath JSON文件的路径
// @return 写入成功返回 true否则返回 false
bool WriteProjectData(
const QString& filePath,
const nmNumericalWindowPayloadReferences* pPayloadReferences = NULL);
/**
* @brief 将本窗口完整写入保存会话指定的 v3 代次目录。
* @note 主 JSON 最后写入,并在返回前校验全部引用文件。
*/
bool saveNmResultV3(
const QString& sWindowDirectory,
nmNumericalFileReference& oMainJsonReference,
QString* pError = NULL);
/**
* @brief 校验一个 v3 窗口主 JSON 明确引用的全部载荷。
* @note 保存会话用它复核从旧根清单保留、但本轮未重写的窗口。
*/
static bool validateNmResultV3Window(
const QString& sWindowDirectory,
const QString& sMainJsonPath,
QString* pError = NULL);
// 加载本地成果到内存中
// @param sLoadAnalDir 加载的分析目录
// @return 保存成功返回 true否则返回 false
bool loadNmResult(QString sLoadAnalDir);
// 辅助函数:确保目录存在,如果不存在则创建
bool ensureDirectoryExists(const QString& dirPath);
/**
* @brief 判断指定目录是否存在。
* @param sDirPath 要检查的目录路径。
* @return 如果目录存在且可访问则返回true否则返回false。
*/
static bool isDirExist(const QString& sDirPath)
{
QFileInfo dirInfo(sDirPath);
bool bExists = dirInfo.exists() && dirInfo.isDir();
return bExists;
}
// 加载井数组里对应的压力、流量数据,这个是在井里没有这些数据的情况下调用
/** @brief 按保存井别重新读取工程井压力和流量,任一井映射失败时返回 false。 */
bool loadWellPreAndFlow();
// 设置当前分析下的VTK网格对象
void setUnstructuredGrid(vtkSmartPointer<vtkUnstructuredGrid> grid);
// 获取当前分析下的VTK网格对象
vtkSmartPointer<vtkUnstructuredGrid> getUnstructuredGrid() const;
// 清理当前分析下的VTK网格对象
void clearUnstructuredGrid();
// 创建时间步数据
//void createTimeStep();
nmDataTimeStepSetting* createTimeStep();
// 获取时间步数据
nmDataTimeStepSetting* getTimeStep();
void calculationLogData(
nmDataWellBase* pWellData,
QVector<QVector<double>>& vvecHistoryData,
QVector<QVector<double>>& vvecLogPreData,
QVector<QVector<double>>& vvecSemiLogPreData);
// 获取许可证路径
void setLicensePath(const QString& licensePath);
QString getLicensePath() const;
// 获取属性注册表
nmAttrRegistry* getAttrRegistry() const;
/// @brief 同步所有井的参数到 nmAttrRegistry
/// @note wellCode + "_W_XX" 作为注册名,使双向绑定链路适用于井参数
/// @note 增量同步:自动清理已删除井的注册,注册新增井的参数
void syncWellAttrs();
/// @brief 按“对象编码 + XML 参数名”注册几何对象参数
void syncGeometryAttrs();
signals:
void dataChanged();
/// @brief 井数据准备完成信号
void sigWellAdded(QString wellCode, QString wellName, QStringList baseParas);
/// @brief 井删除信号removeWell 发出)
void sigWellRemoved(QString wellCode, QString wellName);
/// @brief 参数面板中的对象列表或对象名称发生变化
void sigGeometryListChanged();
/** @brief 当前分析最后一次排队的 PEBI 建网流程已经结束。 */
void sigPebiGridGenerationFinished(quint64 nGridInputRevision,
bool bSucceeded);
/** @brief 并行结果快照或其结果井选择已经改变。 */
void sigPebiResultSnapshotChanged();
private:
/** @brief 按 UUID 给当前实时井统一绑定或解除最后结果快照弱引用。 */
void rebindPebiResultSnapshotToWells();
/** @brief 在候选 Manager 内完整读取并校验一套 v3 成果。 */
bool loadNmResultV3InPlace(const QString& sLoadAnalDir);
/** @brief 通过交换所有权一次发布已完整校验的候选项目状态。 */
void swapLoadedProjectState(nmDataAnalyzeManager& oLoadedManager);
/** @brief 项目状态替换后用新对象地址重建属性注册表。 */
void rebuildLoadedAttributeRegistry();
/** @brief 创建本数据管理器的成果窗口;只用于读取本成果上下文,不拥有对象。 */
iSubWndFitting* m_pOwnerFitting;
/** @brief 保护后台使用计数和析构等待条件。 */
QMutex m_oBackgroundUseMutex;
/** @brief DataManager 析构时等待全部后台任务停止访问。 */
QWaitCondition m_oNoBackgroundUseCondition;
int m_nBackgroundUseCount; ///< 当前持有 DataManager 使用权的后台任务数量。
/** @brief 仅由主线程维护;覆盖建网防抖、后台计算和结果提交整个阶段。 */
bool m_bPebiGridGenerationActive;
quint64 m_nPebiGridGenerationRevision; ///< 当前建网活动对应的输入版本。
// 存储井的数据
QVector<nmDataWellBase*> m_vWellData;
// 断层数据
QVector<nmDataFault*> m_vFaultData;
// 裂缝数据
QVector<nmDataFracture*> m_vFractureData;
// 复合区数据
QVector<nmDataRegion*> m_vRegionData;
// 区域标记数据
QVector<nmDataRegionMark*> m_vRegionMarkData;
// 边界数据
nmDataOutline* m_outlineData;
// 坐标轴范围数据
nmDataAxis* m_axisData;
// 自动拟合数据
nmDataAutomaticFitting* m_pAutomaticFittingData;
// 油藏数据
nmDataReservoir* m_reservoirData;
// 存储nmGuiPlot,绘图
nmGuiPlot* m_pNmGuiPlot;
// 比例尺信息
nmDataMeasuringScale* m_pMeasuringScaleData;
// 测量信息
nmDataMeasure* m_pMeasureData;
// 模型参考点信息
nmDataGeoRef* m_pGeoRefData;
// 预测信息
nmDataForecast* m_pForecastData;
// 敏感性信息
nmDataSensitive* m_pSensitiveData;
// 诊断参数
nmDataDiagnostic* m_pDiagnosticData;
// 网格类型
NM_Grid_Type m_eGridType;
// 求解模型类型
NM_SOLVER_MODEL_TYPE m_eSolverModelType;
/** @brief PEBI求解器类型1为CPU加速求解器2为原求解器。 */
int m_nPebiSolverType;
/** @brief PEBI求解器的OpenMP线程数。 */
int m_nPebiOmpThreads;
/** @brief PEBI求解器的ILU复用步数。 */
int m_nPebiIluReuseSteps;
// Pvt数据(Pebi)
nmDataPvtParaForPebi* m_pebiPvtPara;
// 混合结果参数
nmDataMixedResults* m_pMixedResults;
// 储层数据
nmDataLayer* m_pLayerData;
QVector<nmDataLayer*> m_vecLayers; // 通过储层对话框后初始化的数组,临时
// 孔射封堵
//nmDataPerforationClosing* m_pPerCloData;
// 当前数值分析方案:保存选井、井角色、当前网格槽位和三个输入版本。
nmDataNumericalAnalysisCase m_oNumericalAnalysisCase;
/** @brief 最后一次成功求解发布的完整只读结果。 */
QSharedPointer<const nmPebiResultSnapshot> m_pPebiResultSnapshot;
/** @brief 快照查看状态中当前选择的结果井 UUID。 */
QString m_sCurrentResultWellInstanceId;
// 当前查看的是哪一口井的数据,也是哪一口测试井
nmDataWellBase* m_pCurDataWell;
// 显示设置信息
QVector<DisplaySetting> m_vecDisplaySettings;
/* 属性插值数据组 */
QVector<nmPropertyInterpolationDataSet> m_vecPropertyInterpolationDataSets;
// 背景图片信息
BackgroundImageInfo m_backgroundImageInfo;
// VTK非结构化网格对象用于展示网格划分窗体
vtkSmartPointer<vtkUnstructuredGrid> m_pVtkUnstructuredGrid;
// 时间步设置数据
nmDataTimeStepSetting* m_pTimeStep;
// 属性注册表(普通指针,手动管理,析构函数末尾 delete
nmAttrRegistry* m_pAttrRegistry;
// 许可证路径
QString m_licensePath;
public:
// 数据是否是从本地加载进来的
bool m_bIsLoadData;
};
#endif // NMDATAANALYZEMANAGER_H