#ifndef NMPEBIRESULTSNAPSHOT_H #define NMPEBIRESULTSNAPSHOT_H #include "nmData_global.h" #include "nmDataNumericalAnalysisCase.h" #include #include #include #include #include #include #include class vtkDoubleArray; class vtkUnstructuredGrid; class nmPebiResultSnapshotBuilder; class nmPebiResultSnapshotRenderAdapter; class nmPebiResultSnapshotSerializer; /** @brief 一条求解器槽位在最后成功结果中的冻结描述。 */ struct NM_DATA_EXPORT nmPebiResultSolverSlot { /** @brief 初始化为未分配的真实井槽位。 */ nmPebiResultSolverSlot(); /** @brief 求解器中的连续槽位下标。 */ int m_nSolverIndex; /** @brief 槽位是实际井还是手工裂缝。 */ NM_SOLVER_ENTRY_KIND m_eEntryKind; /** @brief 实际井 UUID;手工裂缝槽位必须为空。 */ QString m_sWellInstanceId; /** @brief 求解时冻结的井编码。 */ QString m_sWellCode; /** @brief 求解时冻结的井模型类型。 */ NM_WELL_MODEL m_eWellType; }; /** @brief 一口结果井的历史曲线和计算曲线。 */ struct NM_DATA_EXPORT nmPebiResultWellCurves { // 二维容器沿用现有绘图数据约定:每个子数组是一条数据序列, // 同一组曲线内各序列点数必须一致,快照不改变序列含义和单位。 /** @brief 求解时冻结的历史压力曲线数据序列组。 */ QVector > m_vecHistoryPressure; /** @brief 求解时冻结的历史双对数曲线数据序列组。 */ QVector > m_vecHistoryLogLog; /** @brief 求解时冻结的历史半对数曲线数据序列组。 */ QVector > m_vecHistorySemiLog; /** @brief 最后成功求解的压力曲线数据序列组。 */ QVector > m_vecResultPressure; /** @brief 最后成功求解的双对数曲线数据序列组。 */ QVector > m_vecResultLogLog; /** @brief 最后成功求解的半对数曲线数据序列组。 */ QVector > m_vecResultSemiLog; }; /** @brief 一口结果井在求解成功时冻结的完整值数据。 */ struct NM_DATA_EXPORT nmPebiResultWellSnapshot { /** @brief 初始化空的结果井元数据。 */ nmPebiResultWellSnapshot(); /** @brief 求解时井对象的稳定 UUID。 */ QString m_sWellInstanceId; /** @brief 求解时冻结的井编码。 */ QString m_sWellCode; /** @brief 求解时冻结的井名称。 */ QString m_sWellName; /** @brief 求解时冻结的井模型类型。 */ NM_WELL_MODEL m_eWellType; /** @brief 求解时冻结的井角色。 */ NM_CASE_WELL_MODE m_eWellMode; /** @brief 求解时冻结的井平面位置。 */ QPointF m_oLocation; /** @brief 求解时是否存在射孔数据。 */ bool m_bHasPerforation; /** @brief 求解时是否启用表皮参数。 */ bool m_bHasSkin; /** @brief 求解时是否启用裂缝导流能力参数。 */ bool m_bHasDfc; /** @brief 求解时井筒半径。 */ double m_dRadius; /** @brief 求解时井筒储集系数。 */ double m_dWellboreStorage; /** @brief 求解时表皮系数。 */ double m_dSkin; /** @brief 求解时裂缝导流能力。 */ double m_dDfc; /** @brief 求解时冻结的历史曲线和计算曲线。 */ nmPebiResultWellCurves m_oCurves; }; /** @brief 结果参数页使用的求解时储层参数。 */ struct NM_DATA_EXPORT nmPebiResultReservoirParameters { /** @brief 初始化空的储层参数。 */ nmPebiResultReservoirParameters(); /** @brief 初始地层压力 Pi。 */ double m_dInitialPressure; /** @brief 储层渗透率 K。 */ double m_dPermeability; /** @brief 储层有效厚度 h。 */ double m_dThickness; /** @brief 储层孔隙度 phi。 */ double m_dPorosity; /** @brief 总压缩系数 Cti。 */ double m_dTotalCompressibility; /** @brief 岩石压缩系数 Cf。 */ double m_dRockCompressibility; /** @brief 初始含油饱和度 Soi。 */ double m_dOilSaturation; /** @brief 初始含气饱和度 Sgi。 */ double m_dGasSaturation; /** @brief 初始含水饱和度 Swi。 */ double m_dWaterSaturation; }; /** @brief 求解时使用的常量 PVT 和全部变化 PVT 数组。 */ struct NM_DATA_EXPORT nmPebiResultPvtParameters { /** @brief 初始化空的 PVT 参数。 */ nmPebiResultPvtParameters(); /** @brief 是否保存了有效泡点压力。 */ bool m_bHasBubblePoint; /** @brief 求解时泡点压力。 */ double m_dBubblePoint; /** @brief 求解时常量原油体积系数 Bo。 */ double m_dConstantBo; /** @brief 求解时常量原油黏度 Miuo。 */ double m_dConstantMiuo; /** @brief 求解时常量天然气体积系数 Bg。 */ double m_dConstantBg; /** @brief 求解时常量天然气黏度 Miug。 */ double m_dConstantMiug; /** @brief 求解时常量地层水体积系数 Bw。 */ double m_dConstantBw; /** @brief 求解时常量地层水黏度 Miuw。 */ double m_dConstantMiuw; /** @brief 变化 PVT 的压力采样数组。 */ QVector m_vecPressure; /** @brief 溶解气油比 Rso 数组。 */ QVector m_vecRso; /** @brief 原油体积系数 Bo 数组。 */ QVector m_vecBo; /** @brief 原油压缩系数 Co 数组。 */ QVector m_vecCo; /** @brief 原油黏度 Miuo 数组。 */ QVector m_vecMiuo; /** @brief 原油密度 Rouo 数组。 */ QVector m_vecRouo; /** @brief 挥发油气比 Rv 数组。 */ QVector m_vecRv; /** @brief 天然气体积系数 Bg 数组。 */ QVector m_vecBg; /** @brief 天然气压缩系数 Cg 数组。 */ QVector m_vecCg; /** @brief 天然气黏度 Miug 数组。 */ QVector m_vecMiug; /** @brief 天然气密度 Roug 数组。 */ QVector m_vecRoug; /** @brief 天然气偏差因子 Z 数组。 */ QVector m_vecZ; /** @brief 地层水溶解气比 Rsw 数组。 */ QVector m_vecRsw; /** @brief 地层水体积系数 Bw 数组。 */ QVector m_vecBw; /** @brief 地层水压缩系数 Cw 数组。 */ QVector m_vecCw; /** @brief 地层水黏度 Miuw 数组。 */ QVector m_vecMiuw; /** @brief 地层水密度 Rouw 数组。 */ QVector m_vecRouw; /** @brief PVT 原始 V 数组。 */ QVector m_vecV; /** @brief PVT 原始 KkInitial 数组。 */ QVector m_vecKkInitial; /** @brief PVT 原始 CfCfInitial 数组。 */ QVector m_vecCfCfInitial; /** @brief 油相饱和度 So 数组。 */ QVector m_vecSo; /** @brief 油相相对渗透率 Kro 数组。 */ QVector m_vecKro; /** @brief 气相饱和度 Sg 数组。 */ QVector m_vecSg; /** @brief 气相相对渗透率 Krg 数组。 */ QVector m_vecKrg; /** @brief 水相饱和度 Sw 数组。 */ QVector m_vecSw; /** @brief 水相相对渗透率 Krw 数组。 */ QVector m_vecKrw; }; /** @brief 结果页面和追溯所需的求解时设置。 */ struct NM_DATA_EXPORT nmPebiResultSolverSettings { /** @brief 初始化空的求解设置。 */ nmPebiResultSolverSettings(); /** @brief 求解时流体模型类型。 */ int m_nSolverModelType; /** @brief 求解时 PEBI 线性求解器类型。 */ int m_nPebiSolverType; /** @brief 求解时 OpenMP 线程数。 */ int m_nOmpThreads; /** @brief 求解时 ILU 预条件复用步数。 */ int m_nIluReuseSteps; /** @brief 求解时网格控制值。 */ double m_dGridControl; /** @brief 是否保存了时间步控制设置。 */ bool m_bHasTimeStepSettings; /** @brief 时间步增长指数。 */ double m_dTimeGrowthExponent; /** @brief 最小时间步长。 */ double m_dMinDeltaT; /** @brief 最大时间步长。 */ double m_dMaxDeltaT; }; /** * @brief 最后一次成功 PEBI 求解的完整只读结果。 * * 普通调用方只能读取值类型,或要求快照把结构和压力绑定到调用方拥有的 * VTK 对象,不能取得快照内部 VTK 对象的可写指针。 */ class NM_DATA_EXPORT nmPebiResultSnapshot { public: /** @brief 释放快照独占的网格、压力帧和冻结结果数据。 */ ~nmPebiResultSnapshot(); /** @brief 返回快照 UUID。 */ QString getSnapshotId() const; /** @brief 返回求解候选使用的网格输入版本。 */ quint64 getGridInputRevision() const; /** @brief 返回求解候选使用的求解输入版本。 */ quint64 getResultInputRevision() const; /** @brief 返回快照是否已通过 Builder 的完整校验。 */ bool isComplete() const; /** @brief 返回完整求解器槽位数量。 */ int getSolverSlotCount() const; /** @brief 按槽位下标返回只读描述,越界时返回 NULL。 */ const nmPebiResultSolverSlot* getSolverSlotAt(int nIndex) const; /** @brief 返回快照结果井数量。 */ int getWellCount() const; /** @brief 按存储下标返回只读结果井,越界时返回 NULL。 */ const nmPebiResultWellSnapshot* getWellAt(int nIndex) const; /** @brief 按井 UUID 查找只读结果井,不存在时返回 NULL。 */ const nmPebiResultWellSnapshot* findWell( const QString& sWellInstanceId) const; /** @brief 返回结果井下拉框使用的有序 UUID 列表。 */ const QStringList& getDisplayWellInstanceIds() const; /** @brief 判断井 UUID 是否属于可显示结果井列表。 */ bool isDisplayWell(const QString& sWellInstanceId) const; /** @brief 返回结果基础网格单元数。 */ vtkIdType getResultCellCount() const; /** @brief 返回压力时间步数量。 */ int getPressureFrameCount() const; /** @brief 返回指定压力帧的时间,越界时返回 0。 */ double getPressureTimeAt(int nIndex) const; /** @brief 返回全部压力帧的全局标量范围。 */ bool getScalarRange(double aRange[2]) const; /** @brief 返回求解时冻结的储层参数。 */ const nmPebiResultReservoirParameters& getReservoirParameters() const; /** @brief 返回求解时冻结的完整 PVT 参数。 */ const nmPebiResultPvtParameters& getPvtParameters() const; /** @brief 返回求解时冻结的求解设置。 */ const nmPebiResultSolverSettings& getSolverSettings() const; private: struct PressureFrame { /** @brief 初始化空压力帧。 */ PressureFrame(); /** @brief 该压力帧对应的求解时间。 */ double m_dTime; /** @brief 快照规范持有的单分量单元压力数组。 */ vtkSmartPointer m_pPressure; }; /** @brief 仅允许 Builder 创建未完成候选。 */ nmPebiResultSnapshot(); /** @brief 禁止复制,避免无意深拷贝大网格和全部压力帧。 */ nmPebiResultSnapshot(const nmPebiResultSnapshot&); /** @brief 禁止赋值,避免无意复制大结果载荷。 */ nmPebiResultSnapshot& operator=(const nmPebiResultSnapshot&); /** * @brief 只复制拓扑到适配器拥有的渲染网格,不复制快照的 CellData。 * @note VTK 7.1 的 CopyStructure 会共享点和单元拓扑,适配器不得修改它们。 */ bool copyResultGridStructure(vtkUnstructuredGrid* pTargetGrid) const; /** * @brief 将快照压力帧临时共享绑定到适配器的独立渲染网格。 * @note 目标网格会临时持有同一 VTK 数组引用,下游流程不得改写数组。 */ bool bindPressureFrame(int nIndex, vtkUnstructuredGrid* pTargetGrid) const; /** @brief 将一帧压力复制到适配器复用的缓冲数组。 */ bool copyPressureFrame(int nIndex, vtkDoubleArray* pTargetPressure) const; private: // 网格与压力分开保存,避免基础网格通过 CellData 暴露可变压力数组。 /** @brief 快照 UUID。 */ QString m_sSnapshotId; /** @brief 生成结果时使用的网格输入版本。 */ quint64 m_nGridInputRevision; /** @brief 生成结果时使用的求解输入版本。 */ quint64 m_nResultInputRevision; /** @brief 是否已由 Builder 完整校验并封闭。 */ bool m_bComplete; /** @brief 不含压力 p 数组和活动标量的结果基础网格。 */ vtkSmartPointer m_pResultGrid; /** @brief 按时间严格递增保存的全部压力帧。 */ QVector m_vecPressureFrames; /** @brief 全部压力帧中的全局最小值。 */ double m_dScalarMin; /** @brief 全部压力帧中的全局最大值。 */ double m_dScalarMax; /** @brief 完整且连续的求解器槽位顺序。 */ QVector m_vecSolverSlots; /** @brief 求解时冻结的全部结果井。 */ QVector m_vecWells; /** @brief 结果井下拉框使用的有序井 UUID 子集。 */ QStringList m_listDisplayWellInstanceIds; /** @brief 求解时冻结的储层参数。 */ nmPebiResultReservoirParameters m_oReservoirParameters; /** @brief 求解时冻结的完整 PVT 参数。 */ nmPebiResultPvtParameters m_oPvtParameters; /** @brief 求解时冻结的求解设置。 */ nmPebiResultSolverSettings m_oSolverSettings; // 只有 Builder 和后续 v3 序列化器可以在发布前填充私有数据。 friend class nmPebiResultSnapshotBuilder; friend class nmPebiResultSnapshotRenderAdapter; friend class nmPebiResultSnapshotSerializer; }; #endif // NMPEBIRESULTSNAPSHOT_H