|
|
|
|
|
#include "nmDataVerticalFracturedWell.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "ZxBaseUtil.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
#include "nmDataReservoir.h"
|
|
|
|
|
|
|
|
|
|
|
|
nmDataVerticalFracturedWell::nmDataVerticalFracturedWell() : nmDataVerticalWell() {
|
|
|
|
|
|
m_pReservoir = nmDataAnalyzeManager::getCurrentInstance()->getReservoirData();
|
|
|
|
|
|
|
|
|
|
|
|
m_fractureModel = nmDataAttribute("Fracture model", "Finite conductivity", "", UNIT_TYPE_DIMENSIONLESS, QStringList() << "Infinite conductivity", QStringList());
|
|
|
|
|
|
m_dFc = nmDataAttribute("dFc", 1000.0, "md.m", UNIT_TYPE_CONDUCTIVITY, QStringList(), QStringList() << "md.ft" << "md.m" << "m^3");
|
|
|
|
|
|
m_fractureHalfLength = nmDataAttribute("Fracture half length", 20.0, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km");
|
|
|
|
|
|
m_fractureHeight = nmDataAttribute("Fracture height", m_pReservoir->getThickness().getValue() , "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km");
|
|
|
|
|
|
m_fractureMidPointHeight = nmDataAttribute("Fracture mid-point height", (m_fractureHeight.getValue().toDouble())/2 , "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km");
|
|
|
|
|
|
m_width = nmDataAttribute("Width", 0.00328084, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km");
|
|
|
|
|
|
m_fractureAngle = nmDataAttribute("Fracture angle", 0.0000, "o", UNIT_TYPE_ANGLE, QStringList(), QStringList() << "o" << "radian");
|
|
|
|
|
|
// 垂直裂缝井
|
|
|
|
|
|
m_eWellType = NM_WELL_MODEL::Vertical_Fractured_Well;
|
|
|
|
|
|
|
|
|
|
|
|
this->connectAttributeSignals();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 拷贝构造函数
|
|
|
|
|
|
nmDataVerticalFracturedWell::nmDataVerticalFracturedWell(const nmDataVerticalFracturedWell& other)
|
|
|
|
|
|
: nmDataVerticalWell(other)
|
|
|
|
|
|
{
|
|
|
|
|
|
*this = other; // 使用赋值运算符实现
|
|
|
|
|
|
this->connectAttributeSignals();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 赋值运算符
|
|
|
|
|
|
nmDataVerticalFracturedWell& nmDataVerticalFracturedWell::operator=(const nmDataVerticalFracturedWell& other) {
|
|
|
|
|
|
if (this != &other) {
|
|
|
|
|
|
nmDataVerticalWell::operator=(other);
|
|
|
|
|
|
m_fractureModel = other.m_fractureModel;
|
|
|
|
|
|
m_dFc = other.m_dFc;
|
|
|
|
|
|
m_fractureHalfLength = other.m_fractureHalfLength;
|
|
|
|
|
|
m_fractureHeight = other.m_fractureHeight;
|
|
|
|
|
|
m_fractureMidPointHeight = other.m_fractureMidPointHeight;
|
|
|
|
|
|
m_width = other.m_width;
|
|
|
|
|
|
m_fractureAngle = other.m_fractureAngle;
|
|
|
|
|
|
m_vecFracs = other.m_vecFracs;
|
|
|
|
|
|
}
|
|
|
|
|
|
return *this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataWellBase* nmDataVerticalFracturedWell::clone() const {
|
|
|
|
|
|
return new nmDataVerticalFracturedWell(*this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 序列化 nmDataVerticalFracturedWell 为 RapidJSON Value
|
|
|
|
|
|
rapidjson::Value nmDataVerticalFracturedWell::ToJsonValue(rapidjson::Document::AllocatorType& allocator) const
|
|
|
|
|
|
{
|
|
|
|
|
|
// 序列化直井参数
|
|
|
|
|
|
rapidjson::Value verticalFractureWellObject = nmDataVerticalWell::ToJsonValue(allocator);
|
|
|
|
|
|
|
|
|
|
|
|
// 序列化 nmDataAttribute 类型的成员
|
|
|
|
|
|
// 调用 nmDataAttribute 自身的 ToJsonValue 方法进行递归序列化
|
|
|
|
|
|
verticalFractureWellObject.AddMember("FractureModel", m_fractureModel.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("dFc", m_dFc.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("FractureHalfLength", m_fractureHalfLength.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("FractureHeight", m_fractureHeight.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("FractureMidPointHeight", m_fractureMidPointHeight.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("Width", m_width.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
verticalFractureWellObject.AddMember("FractureAngle", m_fractureAngle.ToJsonValue(allocator), allocator);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return verticalFractureWellObject; // 返回序列化后的 RapidJSON Value
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 从 RapidJSON Value 反序列化数据到 nmDataVerticalFracturedWell
|
|
|
|
|
|
void nmDataVerticalFracturedWell::FromJsonValue(const rapidjson::Value& jsonValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 反序列化直井参数
|
|
|
|
|
|
nmDataVerticalWell::FromJsonValue(jsonValue);
|
|
|
|
|
|
|
|
|
|
|
|
// 反序列化 nmDataAttribute 类型的成员
|
|
|
|
|
|
// 调用 nmDataAttribute 自身的 FromJsonValue 方法进行递归反序列化
|
|
|
|
|
|
if (jsonValue.HasMember("FractureModel") && jsonValue["FractureModel"].IsObject()) {
|
|
|
|
|
|
m_fractureModel.FromJsonValue(jsonValue["FractureModel"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("dFc") && jsonValue["dFc"].IsObject()) {
|
|
|
|
|
|
m_dFc.FromJsonValue(jsonValue["dFc"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("FractureHalfLength") && jsonValue["FractureHalfLength"].IsObject()) {
|
|
|
|
|
|
m_fractureHalfLength.FromJsonValue(jsonValue["FractureHalfLength"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("FractureHeight") && jsonValue["FractureHeight"].IsObject()) {
|
|
|
|
|
|
m_fractureHeight.FromJsonValue(jsonValue["FractureHeight"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("FractureMidPointHeight") && jsonValue["FractureMidPointHeight"].IsObject()) {
|
|
|
|
|
|
m_fractureMidPointHeight.FromJsonValue(jsonValue["FractureMidPointHeight"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("Width") && jsonValue["Width"].IsObject()) {
|
|
|
|
|
|
m_width.FromJsonValue(jsonValue["Width"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (jsonValue.HasMember("FractureAngle") && jsonValue["FractureAngle"].IsObject()) {
|
|
|
|
|
|
m_fractureAngle.FromJsonValue(jsonValue["FractureAngle"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算裂缝相关信息
|
|
|
|
|
|
this->setFracs();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::connectAttributeSignals() {
|
|
|
|
|
|
// 基础井位置
|
|
|
|
|
|
connect(&this->getX(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
connect(&this->getY(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
|
|
|
|
|
|
// 垂直裂缝井属性
|
|
|
|
|
|
connect(&m_fractureModel, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged()));
|
|
|
|
|
|
connect(&m_dFc, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged()));
|
|
|
|
|
|
connect(&m_fractureHalfLength, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
connect(&m_fractureHeight, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
connect(&m_fractureMidPointHeight, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
connect(&m_width, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
connect(&m_fractureAngle, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::getPerforationAllowedMdRange(nmDataPerforation* pPerfToValidate,
|
|
|
|
|
|
double& dUpperAllowedMd,
|
|
|
|
|
|
double& dLowerAllowedMd)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 获取裂缝和储层边界数据
|
|
|
|
|
|
double dFractureHeight = getFractureHeight().getValue().toDouble();
|
|
|
|
|
|
double dFractureMidPointHeight = getFractureMidPointHeight().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
// 从数据中心获取储层的最大底部MD
|
|
|
|
|
|
double dMaxReservoirBottom = nmDataAnalyzeManager::getCurrentInstance()->getMaxLayerBottom();
|
|
|
|
|
|
|
|
|
|
|
|
// 根据你提供的逻辑,将相对高度转换为绝对MD值
|
|
|
|
|
|
// fractureMidPointMd = 储层底部MD - 裂缝中点高度
|
|
|
|
|
|
double dFractureMidPointMd = dMaxReservoirBottom - dFractureMidPointHeight;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算裂缝的上下MD范围
|
|
|
|
|
|
double dFractureTopMd = dFractureMidPointMd - dFractureHeight / 2.0;
|
|
|
|
|
|
double dFractureBottomMd = dFractureMidPointMd + dFractureHeight / 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化允许范围为裂缝的MD范围
|
|
|
|
|
|
dUpperAllowedMd = dFractureTopMd;
|
|
|
|
|
|
dLowerAllowedMd = dFractureBottomMd;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 获取当前正在操作的射孔段的当前MD值
|
|
|
|
|
|
double dCurrentPerfMdStart = pPerfToValidate->getMdStart().getValue().toDouble();
|
|
|
|
|
|
double dCurrentPerfMdEnd = pPerfToValidate->getMdEnd().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 遍历所有射孔段,找到与当前射孔段相邻的上下边界
|
|
|
|
|
|
QVector<nmDataPerforation*>& vecAllPerforations = getPerforations();
|
|
|
|
|
|
|
|
|
|
|
|
foreach(nmDataPerforation* pOtherPerf, vecAllPerforations) {
|
|
|
|
|
|
if(pOtherPerf == pPerfToValidate) {
|
|
|
|
|
|
continue; // 跳过当前正在操作的射孔段本身
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dOtherStart = pOtherPerf->getMdStart().getValue().toDouble();
|
|
|
|
|
|
double dOtherEnd = pOtherPerf->getMdEnd().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查在当前射孔段上方的其他射孔段
|
|
|
|
|
|
// 如果 pOtherPerf 的结束MD 小于或等于当前射孔段的起始MD (考虑容差)
|
|
|
|
|
|
if(dOtherEnd <= dCurrentPerfMdStart + DBL_EPSILON) {
|
|
|
|
|
|
dUpperAllowedMd = std::max(dUpperAllowedMd, dOtherEnd);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 检查在当前射孔段下方的其他射孔段
|
|
|
|
|
|
// 如果 pOtherPerf 的起始MD 大于或等于当前射孔段的结束MD (考虑容差)
|
|
|
|
|
|
else if(dOtherStart >= dCurrentPerfMdEnd - DBL_EPSILON) {
|
|
|
|
|
|
dLowerAllowedMd = std::min(dLowerAllowedMd, dOtherStart);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 最后,确保计算出的范围不超出井筒的物理范围
|
|
|
|
|
|
double dWellboreTopMd = getBottomholeMD().getValue().toDouble();
|
|
|
|
|
|
double dWellboreBottomMd = dWellboreTopMd + getWellLength().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
dUpperAllowedMd = std::max(dUpperAllowedMd, dWellboreTopMd);
|
|
|
|
|
|
dLowerAllowedMd = std::min(dLowerAllowedMd, dWellboreBottomMd);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::onFractureAttributeChanged() {
|
|
|
|
|
|
this->setFracs(); // 重新计算裂缝点
|
|
|
|
|
|
emit sigWellDataChanged(); // 发送井数据改变的通用信号
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFractureModel(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_fractureModel = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFractureHalfLength(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_fractureHalfLength = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFractureHeight(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_fractureHeight = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFractureMidPointHeight(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_fractureMidPointHeight = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setWidth(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_width = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFractureAngle(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_fractureAngle = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getFractureModel() {
|
|
|
|
|
|
return m_fractureModel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getFractureHalfLength() {
|
|
|
|
|
|
return m_fractureHalfLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getFractureHeight() {
|
|
|
|
|
|
return m_fractureHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getFractureMidPointHeight() {
|
|
|
|
|
|
return m_fractureMidPointHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getWidth() {
|
|
|
|
|
|
return m_width;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getFractureAngle() {
|
|
|
|
|
|
return m_fractureAngle;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setDfc(const nmDataAttribute& attr) {
|
|
|
|
|
|
m_dFc = attr;
|
|
|
|
|
|
}
|
|
|
|
|
|
nmDataAttribute& nmDataVerticalFracturedWell::getDfc() {
|
|
|
|
|
|
return m_dFc;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmDataVerticalFracturedWell::setFracs() {
|
|
|
|
|
|
QVector<QPointF> vFracPoints;
|
|
|
|
|
|
|
|
|
|
|
|
// 井的位置
|
|
|
|
|
|
double x = this->getX().getValue().toDouble();
|
|
|
|
|
|
double y = this->getY().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取裂缝半长
|
|
|
|
|
|
double halfLength = this->getFractureHalfLength().getValue().toDouble();
|
|
|
|
|
|
// 获取裂缝角度(单位:度)
|
|
|
|
|
|
double fractureAngle = this->getFractureAngle().getValue().toDouble();
|
|
|
|
|
|
|
|
|
|
|
|
// 将角度从度转换为弧度
|
|
|
|
|
|
double angleRad = fractureAngle * M_PI / 180.0; // M_PI 是 π 的值,表示 180 度
|
|
|
|
|
|
|
|
|
|
|
|
// 计算裂缝的两点坐标
|
|
|
|
|
|
double leftX = x - halfLength * cos(angleRad); // 使用余弦计算水平分量
|
|
|
|
|
|
double leftY = y - halfLength * sin(angleRad); // 使用正弦计算垂直分量
|
|
|
|
|
|
double rightX = x + halfLength * cos(angleRad);
|
|
|
|
|
|
double rightY = y + halfLength * sin(angleRad);
|
|
|
|
|
|
|
|
|
|
|
|
QPointF leftP(leftX, leftY);
|
|
|
|
|
|
QPointF rightP(rightX, rightY);
|
|
|
|
|
|
|
|
|
|
|
|
vFracPoints.append(leftP);
|
|
|
|
|
|
vFracPoints.append(rightP);
|
|
|
|
|
|
|
|
|
|
|
|
m_vecFracs.clear();
|
|
|
|
|
|
m_vecFracs = vFracPoints;
|
|
|
|
|
|
|
|
|
|
|
|
// 发送井数据改变信号
|
|
|
|
|
|
//emit sigWellDataChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVector<QPointF> nmDataVerticalFracturedWell::getFracs() const {
|
|
|
|
|
|
return m_vecFracs;
|
|
|
|
|
|
}
|