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/nmDataWellBase.h

359 lines
15 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.

#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 返回井别对应相去除可选 (0,0) 占位点后的真实流动段。 */
QVector<QPointF> getFlowSegmentPoints() 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 返回当前选中的压力记录 Gauge Code未选中时为空。 */
QString getSelectedPressureGaugeCode() const;
/** @brief 返回当前选中的流量记录 Gauge Code未选中时为空。 */
QString getSelectedFlowGaugeCode() const;
/** @brief 返回全部压力记录(包含损坏/空/身份无效记录)。 */
QVector<nmPressureGaugeRecord> getPressureRecords() const;
/** @brief 返回全部流量记录(包含损坏/空/身份无效记录)。 */
QVector<nmFlowGaugeRecord> getFlowRecords() const;
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为空表示未选中
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;
};