|
|
#pragma once
|
|
|
|
|
|
#include "nmData_global.h"
|
|
|
#include "nmDefines.h"
|
|
|
#include "nmDataAttribute.h"
|
|
|
#include "nmDataGaugeRecord.h"
|
|
|
#include "ZxDataObjectDbl.h"
|
|
|
|
|
|
#include "nmDataPerforation.h"
|
|
|
#include <QWeakPointer>
|
|
|
//#include "nmDataReservoir.h"
|
|
|
//#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
class nmDataReservoir;
|
|
|
class nmDataAnalyzeManager;
|
|
|
class nmPebiResultSnapshot;
|
|
|
|
|
|
class NM_DATA_EXPORT nmDataWellBase : public nmDataBase
|
|
|
{
|
|
|
Q_OBJECT
|
|
|
public:
|
|
|
nmDataWellBase();
|
|
|
nmDataWellBase(const nmDataWellBase& other);
|
|
|
~nmDataWellBase();
|
|
|
nmDataWellBase& operator=(const nmDataWellBase& other);
|
|
|
|
|
|
// 创建当前对象的深拷贝
|
|
|
virtual nmDataWellBase* clone() const = 0;
|
|
|
|
|
|
// 实现 nmDataBase 的抽象方法:将当前 C++ 对象序列化为 RapidJSON Value
|
|
|
virtual rapidjson::Value ToJsonValue(rapidjson::Document::AllocatorType& allocator) const override;
|
|
|
// 实现 nmDataBase 的抽象方法:从 RapidJSON Value 反序列化数据到当前 C++ 对象
|
|
|
virtual void FromJsonValue(const rapidjson::Value& jsonValue) override;
|
|
|
|
|
|
// 统一连接 nmDataAttribute 的信号
|
|
|
virtual void connectAttributeSignals();
|
|
|
|
|
|
// 用于获取某个射孔的允许MD范围
|
|
|
virtual void getPerforationAllowedMdRange(nmDataPerforation* pPerfToValidate,
|
|
|
double& dUpperAllowedMd,
|
|
|
double& dLowerAllowedMd) = 0;
|
|
|
|
|
|
public:
|
|
|
// 手动发送信号,通知参数视图进行更新
|
|
|
void notifyParameterChanged();
|
|
|
|
|
|
signals:
|
|
|
// 数据模型发生改变时发出的信号,通知所有监听者刷新视图
|
|
|
void sigWellDataChanged();
|
|
|
// 专门用于通知参数视图更新,通常在模型视图完成交互后发出。
|
|
|
void sigParameterChanged();
|
|
|
|
|
|
public slots:
|
|
|
// 井身长度变化,更新射孔位置
|
|
|
void slotWellLengthChanged();
|
|
|
|
|
|
public:
|
|
|
// 属性的 set 和 get 方法
|
|
|
void setWellName(const QString& name);
|
|
|
QString getWellName() const;
|
|
|
|
|
|
void setWellCode(const QString& code);
|
|
|
QString getWellCode() const;
|
|
|
|
|
|
/** @brief 保存工程井的油井、气井或水井井别;该值不由数值井编辑器修改。 */
|
|
|
void setWellCategory(NM_WELL_CATEGORY eWellCategory);
|
|
|
/** @brief 返回工程井井别,用于选择历史曲线的参考流量相。 */
|
|
|
NM_WELL_CATEGORY getWellCategory() const;
|
|
|
|
|
|
/** @brief 返回井对象的稳定实例标识,与可编辑井编码相互独立。 */
|
|
|
QString getWellInstanceId() const;
|
|
|
/** @brief 项目加载或井型替换时恢复已有实例标识。 */
|
|
|
bool restoreWellInstanceId(const QString& sWellInstanceId);
|
|
|
/** @brief 为新建井生成不带花括号的 UUID。 */
|
|
|
static QString createWellInstanceId();
|
|
|
|
|
|
void setX(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getX(); // 修改为返回引用
|
|
|
|
|
|
void setY(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getY(); // 修改为返回引用
|
|
|
|
|
|
void setRadius(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getRadius(); // 修改为返回引用
|
|
|
|
|
|
void setDrillFloorElevation(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getDrillFloorElevation(); // 修改为返回引用
|
|
|
|
|
|
void setZw(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getZw(); // 修改为返回引用
|
|
|
|
|
|
void setWellLength(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getWellLength(); // 修改为返回引用
|
|
|
|
|
|
void setRateDependentSkin(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getRateDependentSkin(); // 修改为返回引用
|
|
|
|
|
|
void setdSdQ(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getdSdQ(); // 修改为返回引用
|
|
|
|
|
|
void setWellboreModel(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getWellboreModel(); // 修改为返回引用
|
|
|
|
|
|
void setWellboreStorage(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getWellboreStorage(); // 修改为返回引用
|
|
|
|
|
|
void setBottomholeMD(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getBottomholeMD(); // 修改为返回引用
|
|
|
|
|
|
// Location---位置
|
|
|
void setInputWellHead(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getInputWellHead();
|
|
|
|
|
|
void setWellHeadX(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getWellHeadX();
|
|
|
|
|
|
void setWellHeadY(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getWellHeadY();
|
|
|
|
|
|
// Wellbore---井储
|
|
|
void setCInitialCFinal(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getCInitialCFinal();
|
|
|
|
|
|
void setDtChangingStorage(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getDtChangingStorage();
|
|
|
|
|
|
void setLeakSkin(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getLeakSkin();
|
|
|
|
|
|
// Wellbore---井储
|
|
|
void setFinalWellboreStorage(const nmDataAttribute& attr);
|
|
|
nmDataAttribute& getFinalWellboreStorage();
|
|
|
|
|
|
// 获取压力曲线点数据
|
|
|
QVector<QPointF> getPressurePoints() const;
|
|
|
// 设置压力曲线点数据
|
|
|
void setPressurePoints(const QVector<QPointF>& points);
|
|
|
// 获取井别对应相的流量曲线点数据,供现有历史曲线逻辑使用
|
|
|
QVector<QPointF> getFlowPoints() const;
|
|
|
// 设置井别对应相的流量曲线点数据
|
|
|
void setFlowPoints(const QVector<QPointF>& points);
|
|
|
/** @brief 返回工程井别对应的历史曲线参考相。 */
|
|
|
NM_PHASE_TYPE getReferenceFlowPhase() const;
|
|
|
/** @brief 获取或设置指定油、气、水相的原始流量点。 */
|
|
|
QVector<QPointF> getFlowPoints(NM_PHASE_TYPE eFlowPhase) const;
|
|
|
void setFlowPoints(NM_PHASE_TYPE eFlowPhase,
|
|
|
const QVector<QPointF>& points);
|
|
|
/** @brief 返回指定相去除可选 (0,0) 占位点后的真实流动段。 */
|
|
|
QVector<QPointF> getFlowSegmentPoints(NM_PHASE_TYPE eFlowPhase) const;
|
|
|
/** @brief 返回指定相的真实流动段数量。 */
|
|
|
int getFlowSegmentCount(NM_PHASE_TYPE eFlowPhase) const;
|
|
|
/** @brief 指定相是否至少包含一个真实流动段。 */
|
|
|
bool hasFlowPhaseData(NM_PHASE_TYPE eFlowPhase) const;
|
|
|
/** @brief 油、气、水中是否至少有一相包含真实流动段。 */
|
|
|
bool hasAnyFlowData() const;
|
|
|
/** @brief 全部框架记录中是否存在至少一个可用的非零产量相。 */
|
|
|
bool hasAvailableFlowRate() const;
|
|
|
/** @brief 返回当前启用相的公共流量制度;优先取井别对应相。 */
|
|
|
QVector<QPointF> getFlowSegmentPoints() const;
|
|
|
/** @brief 返回当前公共流量制度采用的参考相;没有启用相时返回 Unknown。 */
|
|
|
NM_PHASE_TYPE getFlowSchedulePhase() const;
|
|
|
/** @brief 返回当前启用相共用的真实流动段数量。 */
|
|
|
int getFlowSegmentCount() const;
|
|
|
/** @brief 校验当前流动段索引是否位于一基的真实流动段范围内。 */
|
|
|
bool hasValidFlowSectionIndex() const;
|
|
|
|
|
|
/** @brief 设置全部压力记录列表(不改变当前选中 Code)。 */
|
|
|
void setPressureRecords(const QVector<nmPressureGaugeRecord>& vecRecords);
|
|
|
/** @brief 设置全部流量记录列表(不改变当前选中 Code)。 */
|
|
|
void setFlowRecords(const QVector<nmFlowGaugeRecord>& vecRecords);
|
|
|
/** @brief 按 Gauge Code 选中一条压力记录;传入空字符串表示无选中。 */
|
|
|
void selectPressureGaugeCode(const QString& sGaugeCode);
|
|
|
/** @brief 按 Gauge Code 选中一条流量记录;传入空字符串表示无选中。 */
|
|
|
void selectFlowGaugeCode(const QString& sGaugeCode);
|
|
|
/**
|
|
|
* @brief 切换选中流量记录:把当前 m_nIndexF 写回旧记录的 nIndexF,
|
|
|
* 再用新记录的 nIndexF 恢复并按新记录的真实段数校验当前索引。
|
|
|
* @note UI 层切换流量记录下拉时必须调用本方法,而不是直接调用 selectFlowGaugeCode,
|
|
|
* 否则流动段索引不会跟随记录切换正确恢复。
|
|
|
*/
|
|
|
void switchSelectedFlowGaugeCode(const QString& sGaugeCode);
|
|
|
/** @brief 返回当前选中的压力记录 Gauge Code,未选中时为空。 */
|
|
|
QString getSelectedPressureGaugeCode() const;
|
|
|
/** @brief 返回当前选中的流量记录 Gauge Code,未选中时为空。 */
|
|
|
QString getSelectedFlowGaugeCode() const;
|
|
|
/** @brief 返回全部压力记录(包含损坏/空/身份无效记录)。 */
|
|
|
QVector<nmPressureGaugeRecord> getPressureRecords() const;
|
|
|
/** @brief 返回全部流量记录(包含损坏/空/身份无效记录)。 */
|
|
|
QVector<nmFlowGaugeRecord> getFlowRecords() const;
|
|
|
/** @brief 返回指定相是否作为当前流量制度的一部分传给求解器。 */
|
|
|
bool isFlowPhaseUsed(NM_PHASE_TYPE eFlowPhase) const;
|
|
|
/** @brief 设置指定相是否参与当前流量制度;井别不会随此状态改变。 */
|
|
|
void setFlowPhaseUsed(NM_PHASE_TYPE eFlowPhase, bool bUsed);
|
|
|
// 以下显式接口供现有 UI 和快照组装代码使用,语义与上面的分相接口一致。
|
|
|
// 三个开关只控制求解器输入,不修改框架原始记录,也不改变工程井井别。
|
|
|
bool getUseOilRate() const;
|
|
|
bool getUseGasRate() const;
|
|
|
bool getUseWaterRate() const;
|
|
|
void setUseOilRate(bool bUsed);
|
|
|
void setUseGasRate(bool bUsed);
|
|
|
void setUseWaterRate(bool bUsed);
|
|
|
|
|
|
int getIndexF() const;
|
|
|
void setIndexF(const int newIndex);
|
|
|
|
|
|
bool getPlotVisible() const;
|
|
|
void setPlotVisible(const bool newState);
|
|
|
|
|
|
// 图元外观属性 getter/setter
|
|
|
int getDotStyle() const { return m_nDotStyle; }
|
|
|
void setDotStyle(int style) { m_nDotStyle = style; }
|
|
|
int getDotColorR() const { return m_nDotColorR; }
|
|
|
int getDotColorG() const { return m_nDotColorG; }
|
|
|
int getDotColorB() const { return m_nDotColorB; }
|
|
|
void setDotColor(int r, int g, int b) { m_nDotColorR = r; m_nDotColorG = g; m_nDotColorB = b; }
|
|
|
double getDotRadius() const { return m_dDotRadius; }
|
|
|
void setDotRadius(double r) { m_dDotRadius = r; }
|
|
|
bool getDotFilling() const { return m_bDotFilling; }
|
|
|
void setDotFilling(bool b) { m_bDotFilling = b; }
|
|
|
bool getShowSubObjs() const { return m_bShowSubObjs; }
|
|
|
void setShowSubObjs(bool b) { m_bShowSubObjs = b; }
|
|
|
|
|
|
// 历史数据相关方法
|
|
|
QVector<QVector<double>> getHistoryPressure();
|
|
|
void setHistoryPressure(QVector<QVector<double>> pressureData);
|
|
|
|
|
|
QVector<QVector<double>> getHistoryLogLog();
|
|
|
void setHistoryLogLog(QVector<QVector<double>> loglogData);
|
|
|
|
|
|
QVector<QVector<double>> getHistorySemiLog();
|
|
|
void setHistorySemiLog(QVector<QVector<double>> semiLogData);
|
|
|
|
|
|
void setWellType(NM_WELL_MODEL newWellType);
|
|
|
NM_WELL_MODEL getWellType() const;
|
|
|
|
|
|
// 计算结果相关方法
|
|
|
/** @brief 返回当前井 UUID 在最后结果快照中的压力曲线;未绑定时返回空。 */
|
|
|
QVector<QVector<double>> getResultPressure();
|
|
|
|
|
|
/** @brief 返回当前井 UUID 在最后结果快照中的双对数曲线;未绑定时返回空。 */
|
|
|
QVector<QVector<double>> getResultLogLog();
|
|
|
|
|
|
/** @brief 返回当前井 UUID 在最后结果快照中的半对数曲线;未绑定时返回空。 */
|
|
|
QVector<QVector<double>> getResultSemiLog();
|
|
|
|
|
|
// 时间变表皮状态的getter和setter
|
|
|
bool isTimeDependentSkin() const;
|
|
|
void setTimeDependentSkin(bool enabled);
|
|
|
|
|
|
// 管理射孔段的方法
|
|
|
void addPerforation(nmDataPerforation* perforation); // 接受指针
|
|
|
void removePerforation(int index); // 根据索引移除
|
|
|
nmDataPerforation* getPerforation(int index); // 获取单个射孔段
|
|
|
nmDataPerforation getPerforationCopy(int index); // 获取单个射孔段副本
|
|
|
void updatePerforation(int index, const nmDataPerforation& newData); // 更新单个射孔段数据
|
|
|
int getPerforationCount(); // 获取射孔段数量
|
|
|
QVector<nmDataPerforation*>& getPerforations(); // 获取所有射孔段(返回指针的引用)
|
|
|
void clearPerforations(); // 清空所有射孔段数据
|
|
|
|
|
|
/**
|
|
|
* @brief 一次性应用井筒范围和完整射孔快照。
|
|
|
* @note 显式编辑时不触发井长变化的自动缩放,保证校验值与最终数据一致。
|
|
|
*/
|
|
|
bool applyWellboreEdit(double dBottomholeMd,
|
|
|
double dWellLength,
|
|
|
const QVector<nmDataPerforation>& vecPerforations);
|
|
|
|
|
|
// 井级别的流量和时间查询方法
|
|
|
double getTotalTimeRange() const;
|
|
|
double getFlowRateAtTime(double time) const;
|
|
|
QVector<double> getAllFlowStepBoundaries() const;
|
|
|
QVector<QPointF> getFlowStepsInTimeRange(double startTime, double endTime) const;
|
|
|
double findFlowStepBoundaryAtTime(double timePoint) const;
|
|
|
double findSmartFlowStepBoundary(double targetTime) const;
|
|
|
double findNearestFlowStepBoundary(double targetTime) const;
|
|
|
bool isTimeInFlowStepFirstHalf(double time) const;
|
|
|
|
|
|
// 射孔段相关的查询方法
|
|
|
QVector<double> getFlowStepBoundariesInSegment(int segmentIndex, int perforationIndex) const;
|
|
|
QVector<double> getAllBoundariesInSegment(int segmentIndex, int perforationIndex) const;
|
|
|
int countFlowStepsInSegment(int segmentIndex, int perforationIndex) const;
|
|
|
bool canFlowSegmentBeSplit(int segmentIndex, int perforationIndex) const;
|
|
|
double findNearestFlowStepBoundaryBeforeSegment(int segmentIndex, int perforationIndex) const;
|
|
|
|
|
|
// 判断是否基础射孔段
|
|
|
bool isBasePerforation();
|
|
|
|
|
|
void resetToDefaults(); // 重置所有参数为构造函数默认值
|
|
|
|
|
|
// 导出双对数历史曲线到 CSV
|
|
|
bool exportHistoryLogLogToCsv(const QString& outDir);
|
|
|
// 导出流量数据到 CSV
|
|
|
bool exportHistoryRateToCsv(const QString& outDir);
|
|
|
// 导出历史压力数据到 CSV
|
|
|
bool exportHistoryPressureToCsv(const QString& outDir);
|
|
|
// 导出求解结果双对数曲线到 CSV
|
|
|
bool exportResultLogLogToCsv(const QString& outDir);
|
|
|
// 导出求解结果压力数据到 CSV
|
|
|
bool exportResultPressureToCsv(const QString& outDir);
|
|
|
|
|
|
protected:
|
|
|
/** @brief 井实例 UUID,井型替换时保持不变,删除重建时必须变化。 */
|
|
|
QString m_sWellInstanceId;
|
|
|
QString m_wellName; // 井名
|
|
|
QString m_wellCode; // 井编码(项目级唯一标识,来自ZxDataWell::getCode())
|
|
|
NM_WELL_CATEGORY m_eWellCategory; // 工程井井别:油井、气井或水井
|
|
|
|
|
|
// Location---位置
|
|
|
nmDataAttribute m_inputWellHead; //井口坐标输入
|
|
|
nmDataAttribute m_wellHeadX; //井口坐标X
|
|
|
nmDataAttribute m_wellHeadY; //井口坐标Y
|
|
|
nmDataAttribute m_x; // X
|
|
|
nmDataAttribute m_y; // Y
|
|
|
|
|
|
// Geometry and properties---几何与属性
|
|
|
nmDataAttribute m_drillFloorElevation; // 钻台标高
|
|
|
nmDataAttribute m_radius; // 井径
|
|
|
nmDataAttribute m_zw; // Zw
|
|
|
nmDataAttribute m_wellLength; // 井身长度
|
|
|
nmDataAttribute m_rateDependentSkin; // 速度表皮
|
|
|
nmDataAttribute m_dSdQ; // dS/dQ 表皮关于产量的变化率
|
|
|
|
|
|
// Wellbore---井储
|
|
|
nmDataAttribute m_wellboreModel; // 井储模型
|
|
|
nmDataAttribute m_wellboreStorage; // 井筒储集系数
|
|
|
nmDataAttribute m_finalWellboreStorage; // 最终井储
|
|
|
nmDataAttribute m_cInitialCFinal; // 初始井储/最终井储
|
|
|
nmDataAttribute m_dtChangingStorage; //井储变化时间
|
|
|
nmDataAttribute m_leakSkin; // 漏失表皮
|
|
|
|
|
|
// Bottomhole conditions---井底条件
|
|
|
nmDataAttribute m_bottomholeMD; // 井底测量深度
|
|
|
|
|
|
QVector<nmPressureGaugeRecord> m_vecPressureRecords; // 全部压力测量记录(可能包含损坏/空/身份无效记录)
|
|
|
QVector<nmFlowGaugeRecord> m_vecFlowRecords; // 全部流量测量记录(可能包含损坏/空/身份无效记录)
|
|
|
QString m_sSelectedPressureGaugeCode; // 当前选中的压力记录 Gauge Code,为空表示未选中
|
|
|
QString m_sSelectedFlowGaugeCode; // 当前选中的流量记录 Gauge Code,为空表示未选中
|
|
|
bool m_bUseOilRate; // 当前流量制度是否传入油相产量
|
|
|
bool m_bUseGasRate; // 当前流量制度是否传入气相产量
|
|
|
bool m_bUseWaterRate; // 当前流量制度是否传入水相产量
|
|
|
|
|
|
int m_nIndexF; // 当前流量段的索引
|
|
|
|
|
|
bool m_bPlotVisible; // 图元是否可见
|
|
|
|
|
|
// 图元外观属性(用于保存/加载,由 Binder 在 syncWellData 和 _pushWellDataToGraphic 中同步)
|
|
|
int m_nDotStyle; // ZxDotType (int)
|
|
|
int m_nDotColorR; // QColor R
|
|
|
int m_nDotColorG; // QColor G
|
|
|
int m_nDotColorB; // QColor B
|
|
|
double m_dDotRadius; // 点半径
|
|
|
bool m_bDotFilling; // 是否填充
|
|
|
bool m_bShowSubObjs; // 是否显示子对象
|
|
|
|
|
|
// 添加时间变表皮状态字段
|
|
|
bool m_bTimeDependentSkin;
|
|
|
|
|
|
// 井类型
|
|
|
NM_WELL_MODEL m_eWellType;
|
|
|
|
|
|
// 历史数据
|
|
|
QVector<QVector<double>> m_vvecHsyPressure; // 历史压力数据
|
|
|
QVector<QVector<double>> m_vvecHsyLogLog; // 历史双对数数据
|
|
|
QVector<QVector<double>> m_vvecHsySemiLog; // 历史半对数数据
|
|
|
|
|
|
/** @brief 最后结果快照的弱引用,不延长历史结果生命周期。 */
|
|
|
QWeakPointer<const nmPebiResultSnapshot> m_pPebiResultSnapshot;
|
|
|
|
|
|
// 射孔段集合
|
|
|
QVector<nmDataPerforation*> m_vecPerforations;
|
|
|
|
|
|
// 记录原始井身长度,用于计算更新井身长度之后射孔段的位置
|
|
|
double m_dLastWellLength;
|
|
|
|
|
|
nmDataReservoir* m_pReservoir;
|
|
|
|
|
|
private:
|
|
|
/** @brief 由数据管理器按井 UUID 统一绑定或解除最后结果快照。 */
|
|
|
void bindPebiResultSnapshot(
|
|
|
const QWeakPointer<const nmPebiResultSnapshot>& pSnapshot);
|
|
|
|
|
|
/** @brief 只有所属数据管理器可以维护井与结果快照之间的弱关联。 */
|
|
|
friend class nmDataAnalyzeManager;
|
|
|
};
|