|
|
#ifndef NMCALCULATIONPEBIGRID_H
|
|
|
#define NMCALCULATIONPEBIGRID_H
|
|
|
|
|
|
#include "nmCalculation_global.h"
|
|
|
#include <QVector>
|
|
|
#include <QPointF>
|
|
|
#include <QString>
|
|
|
#include <QSet>
|
|
|
#include <QAtomicInt>
|
|
|
|
|
|
#include "pch.h"
|
|
|
#include "nmDataBinaryTools.h"
|
|
|
#include "nmDataNumericalAnalysisCase.h"
|
|
|
|
|
|
#include <vtkUnstructuredGrid.h>
|
|
|
#include <vtkSmartPointer.h>
|
|
|
|
|
|
class nmDataAnalyzeManager;
|
|
|
class nmDataWellBase;
|
|
|
|
|
|
/**
|
|
|
* @brief 一口求解井在输入捕获时形成的值快照。
|
|
|
*
|
|
|
* 井对象只允许在 DataManager 所属线程读取;后台准备场景和后处理曲线时只使用
|
|
|
* 这里的值,避免多井循环反复扫描 DataManager 或跨线程访问井对象。
|
|
|
*/
|
|
|
struct nmPebiWellInputSnapshot
|
|
|
{
|
|
|
nmPebiWellInputSnapshot()
|
|
|
: m_eWellCategory(NM_WellCategory_Unknown),
|
|
|
m_nFlowSectionIndex(1),
|
|
|
m_dRadius(0.0),
|
|
|
m_dWellboreStorage(0.0),
|
|
|
m_dSkin(0.0),
|
|
|
m_dDfc(0.0),
|
|
|
m_bRateControlled(false),
|
|
|
m_bRealWell(false),
|
|
|
m_bHasPerforation(false),
|
|
|
m_bHasDfc(false),
|
|
|
m_bDisplayResultWell(false)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
QString m_sWellCode; ///< 项目内稳定井编码。
|
|
|
QString m_sWellName; ///< 捕获时井名称。
|
|
|
QString m_sWellInstanceId; ///< 完整场结果使用的稳定井 UUID。
|
|
|
QVector<QPointF> m_vecFlowPoints; ///< 求解使用的流量制度。
|
|
|
NM_WELL_CATEGORY m_eWellCategory; ///< 求解时冻结的油井、气井或水井井别。
|
|
|
/** @brief 求解时冻结的历史压力曲线。 */
|
|
|
QVector<QVector<double> > m_vecHistoryPressure;
|
|
|
/** @brief 求解时冻结的历史双对数曲线。 */
|
|
|
QVector<QVector<double> > m_vecHistoryLogLog;
|
|
|
/** @brief 求解时冻结的历史半对数曲线。 */
|
|
|
QVector<QVector<double> > m_vecHistorySemiLog;
|
|
|
QPointF m_oLocation; ///< 求解时井平面位置。
|
|
|
int m_nFlowSectionIndex; ///< 当前流动段一基索引。
|
|
|
double m_dRadius; ///< 求解时井筒半径。
|
|
|
double m_dWellboreStorage; ///< 求解时井筒储集系数。
|
|
|
double m_dSkin; ///< 求解时表皮系数。
|
|
|
double m_dDfc; ///< 求解时裂缝导流能力。
|
|
|
bool m_bRateControlled; ///< 是否提供源汇项。
|
|
|
bool m_bRealWell; ///< 是否为真实井而非手工裂缝槽位。
|
|
|
bool m_bHasPerforation; ///< 求解时是否存在射孔。
|
|
|
bool m_bHasDfc; ///< 当前井型是否具有 Dfc 参数。
|
|
|
bool m_bDisplayResultWell; ///< 是否进入结果井下拉框。
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* @brief 一次 PEBI 网格任务使用的不可变输入快照。
|
|
|
*
|
|
|
* 该结构只保存值类型,不持有 DataManager、QObject 或井对象指针。主线程在
|
|
|
* 启动任务前完整填充,后台线程随后只读取本结构,从而避免与 Map 编辑并发访问。
|
|
|
*/
|
|
|
struct nmPebiGridInputSnapshot
|
|
|
{
|
|
|
/** @brief 创建空快照;m_bValid 为 false,不能直接提交给网格 DLL。 */
|
|
|
nmPebiGridInputSnapshot()
|
|
|
: m_nGridInputRevision(0),
|
|
|
m_bCaptured(false),
|
|
|
m_bValid(false)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
HX_NWTM_GRID_INPUT m_oGridInput; ///< 边界、井、断层和裂缝等 DLL 输入。
|
|
|
nmDataBinaryTools::NM_PEBI_SCENE m_oScene; ///< 与本次网格输入一致的 ML 场景数据。
|
|
|
QVector<nmSolverWellRef> m_vecSolverWellOrder; ///< DLL 数组槽位对应的稳定井编码顺序。
|
|
|
QVector<nmPebiWellInputSnapshot> m_vecWellInputs; ///< 与 DLL 井槽位严格对齐的值快照。
|
|
|
QString m_sLicensePath; ///< 网格 DLL 授权文件路径副本。
|
|
|
quint64 m_nGridInputRevision; ///< 捕获时的几何输入版本。
|
|
|
bool m_bCaptured; ///< DataManager 值是否已在所属线程完整捕获。
|
|
|
bool m_bValid; ///< 后台场景准备是否完成,可否提交给网格 DLL。
|
|
|
};
|
|
|
|
|
|
/**
|
|
|
* @brief 后台 PEBI 计算产生、尚未写回分析成果的局部结果。
|
|
|
*/
|
|
|
struct nmPebiGridResult
|
|
|
{
|
|
|
/** @brief 创建空结果;只有 m_bSucceeded 为 true 时才允许提交。 */
|
|
|
nmPebiGridResult()
|
|
|
: m_pUnstructuredGrid(nullptr),
|
|
|
m_nPebiCount(-1),
|
|
|
m_bSucceeded(false)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
HX_NWTM_GRID_OUTPUT1 m_oGridOutput1; ///< 网格 DLL 主输出。
|
|
|
HX_NWTM_GRID_OUTPUT2 m_oGridOutput2; ///< 网格 DLL 辅助输出。
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> m_pUnstructuredGrid; ///< 局部构造的 VTK 网格。
|
|
|
int m_nPebiCount; ///< DLL 返回的 PEBI 单元数量。
|
|
|
bool m_bSucceeded; ///< DLL 和 VTK 转换是否全部成功。
|
|
|
};
|
|
|
|
|
|
class NMCALCULATION_EXPORT nmCalculationPebiGrid
|
|
|
{
|
|
|
public:
|
|
|
/** @brief 返回进程内唯一的 PEBI 网格服务实例。 */
|
|
|
static nmCalculationPebiGrid* getInstance();
|
|
|
nmCalculationPebiGrid();
|
|
|
~nmCalculationPebiGrid();
|
|
|
|
|
|
/** @brief 在调用线程从 DataManager 复制一份完整且不含对象指针的网格输入。 */
|
|
|
bool captureInputSnapshot(nmDataAnalyzeManager* pDataManager,
|
|
|
nmPebiGridInputSnapshot& oSnapshot,
|
|
|
bool bDeferPreparation = false);
|
|
|
/** @brief 初始化手工求解的分批网格快照,只在 DataManager 所属线程调用。 */
|
|
|
bool beginManualInputSnapshot(nmDataAnalyzeManager* pDataManager,
|
|
|
nmPebiGridInputSnapshot& oSnapshot);
|
|
|
/** @brief 把一口有效井的几何和值追加到手工求解快照。 */
|
|
|
bool appendManualWellInputSnapshot(nmDataWellBase* pWellData,
|
|
|
int nWellMode,
|
|
|
nmPebiGridInputSnapshot& oSnapshot);
|
|
|
/** @brief 捕获非井输入并完成手工值快照;后台准备前 m_bValid 保持 false。 */
|
|
|
bool finishManualInputSnapshot(nmDataAnalyzeManager* pDataManager,
|
|
|
const QSet<QString>& setEffectiveWellCodes,
|
|
|
nmPebiGridInputSnapshot& oSnapshot);
|
|
|
/** @brief 只使用已捕获的值在后台组装场景;取消时保持 m_bValid 为 false。 */
|
|
|
bool prepareInputSnapshot(nmPebiGridInputSnapshot& oSnapshot,
|
|
|
const QAtomicInt* pCancelRequested = NULL);
|
|
|
/** @brief 仅使用值快照调用网格 DLL,并把输出保存在局部结果中。 */
|
|
|
bool calculateSnapshot(const nmPebiGridInputSnapshot& oSnapshot,
|
|
|
nmPebiGridResult& oResult,
|
|
|
bool bCreateUnstructuredGrid = true,
|
|
|
const QAtomicInt* pCancelRequested = NULL);
|
|
|
/** @brief 在主线程校验输入版本,并一次性提交井顺序、网格和单例缓存。 */
|
|
|
bool commitSnapshotResult(nmDataAnalyzeManager* pDataManager,
|
|
|
const nmPebiGridInputSnapshot& oSnapshot,
|
|
|
const nmPebiGridResult& oResult);
|
|
|
/** @brief 设置 PEBI 网格控制值,并同步到指定分析方案。 */
|
|
|
void setGridControl(double dGridControl,
|
|
|
nmDataAnalyzeManager* pDataManager = nullptr);
|
|
|
/** @brief 仅在缓存属于指定管理器时清理;空参数强制清理当前缓存。 */
|
|
|
void clearGridData(const nmDataAnalyzeManager* pDataManager = nullptr);
|
|
|
|
|
|
private:
|
|
|
/** @brief 从绑定数据管理器构造边界输入。 */
|
|
|
bool meshGenPebiBoundary(nmDataAnalyzeManager* pDataManager,
|
|
|
HX_NWTM_GRID_INPUT& inputObj);
|
|
|
/** @brief 按有效计算井集合构造井几何并记录 DLL 井顺序。 */
|
|
|
bool meshGenPebiWells(nmDataAnalyzeManager* pDataManager,
|
|
|
HX_NWTM_GRID_INPUT& inputObj,
|
|
|
QVector<nmSolverWellRef>& vecSolverWellOrder,
|
|
|
const QSet<QString>& setEffectiveWellCodes);
|
|
|
/** @brief 从 Map 构造断层输入。 */
|
|
|
bool meshGenPebiFault(nmDataAnalyzeManager* pDataManager,
|
|
|
HX_NWTM_GRID_INPUT& inputObj);
|
|
|
/** @brief 从 Map 构造手工裂缝输入和求解器占位条目。 */
|
|
|
bool meshGenPebiCrack(nmDataAnalyzeManager* pDataManager,
|
|
|
HX_NWTM_GRID_INPUT& inputObj,
|
|
|
QVector<nmSolverWellRef>& vecSolverWellOrder);
|
|
|
/** @brief 从已捕获值构造与网格输入一致的 ML 场景,不访问 DataManager。 */
|
|
|
bool buildPebiScene(nmPebiGridInputSnapshot& oSnapshot,
|
|
|
const QAtomicInt* pCancelRequested);
|
|
|
/** @brief 更新单例中的 DLL 输入输出缓存,不改变网格有效版本。 */
|
|
|
void commitOutputCache(nmDataAnalyzeManager* pDataManager,
|
|
|
const nmPebiGridInputSnapshot& oSnapshot,
|
|
|
const nmPebiGridResult& oResult);
|
|
|
|
|
|
// 生成vtk数据
|
|
|
void genPebiVTK(const HX_NWTM_GRID_OUTPUT1& P1, QString vtkDir);
|
|
|
|
|
|
// 根据网格输出结构体创建 vtkUnstructuredGrid 对象
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> createPebiUnstructuredGrid(
|
|
|
const HX_NWTM_GRID_OUTPUT1& P1,
|
|
|
const QAtomicInt* pCancelRequested = NULL);
|
|
|
|
|
|
// 日志输出
|
|
|
void logCurrentState();
|
|
|
void logInputParameters(const HX_NWTM_GRID_INPUT& input);
|
|
|
|
|
|
public:
|
|
|
/** @brief 非阻塞复制当前有效网格;DLL忙碌或缓存不匹配时返回 false。 */
|
|
|
bool copyCurrentGridFor(const nmDataAnalyzeManager* pDataManager,
|
|
|
quint64 nGridInputRevision,
|
|
|
HX_NWTM_GRID_OUTPUT1& oGridOutput1,
|
|
|
HX_NWTM_GRID_OUTPUT2& oGridOutput2,
|
|
|
int& nPebiCount,
|
|
|
const QAtomicInt* pCancelRequested = NULL) const;
|
|
|
/** @brief 主线程快速判断缓存归属和版本,不复制大型 DLL 输出。 */
|
|
|
bool isCurrentGridAvailableFor(const nmDataAnalyzeManager* pDataManager,
|
|
|
quint64 nGridInputRevision) const;
|
|
|
|
|
|
public:
|
|
|
/** @brief 在线程锁保护下返回最近一次网格输出 p1 的副本。 */
|
|
|
HX_NWTM_GRID_OUTPUT1 getGridOutput1();
|
|
|
/** @brief 在线程锁保护下返回最近一次网格输出 p2 的副本。 */
|
|
|
HX_NWTM_GRID_OUTPUT2 getGridOutput2();
|
|
|
/** @brief 返回最近一次网格划分生成的 PEBI 单元数量。 */
|
|
|
int getPebiCount() const;
|
|
|
private:
|
|
|
static nmCalculationPebiGrid* m_instance; ///< 进程内共享的 PEBI 网格服务实例。
|
|
|
|
|
|
HX_NWTM_GRID_INPUT p0; ///< 最近一次提交给网格 DLL 的输入快照。
|
|
|
HX_NWTM_GRID_OUTPUT1 p1; ///< 最近一次网格 DLL 主输出。
|
|
|
HX_NWTM_GRID_OUTPUT2 p2; ///< 最近一次网格 DLL 辅助输出。
|
|
|
double m_dGridControl; ///< 对应 HX_NWTM_GRID_INPUT::GridControl。
|
|
|
int m_nPebiCount; ///< 最近一次成功网格的单元数量,未生成时为 -1。
|
|
|
quint64 m_nCachedGridInputRevision; ///< 单例 DLL 输出对应的网格输入版本。
|
|
|
/** @brief 当前单例缓存所属的数据管理器,不拥有对象。 */
|
|
|
nmDataAnalyzeManager* m_pDataManager;
|
|
|
|
|
|
};
|
|
|
|
|
|
#endif // NMCALCULATIONPEBIGRID_H
|
|
|
|