#include "nmDataHorizontalFracturedWell.h" #include "nmDataAnalyzeManager.h" #include "nmDataReservoir.h" nmDataHorizontalFracturedWell::nmDataHorizontalFracturedWell() : nmDataHorizontalWell() { m_pReservoir = nmDataAnalyzeManager::getCurrentInstance()->getReservoirData(); double horizontalSectionLength = 200.0; m_wellLength.setValue(horizontalSectionLength); m_dLastWellLength = horizontalSectionLength; m_modelingType = nmDataAttribute("Modeling type", "Simple", "", UNIT_TYPE_DIMENSIONLESS, QStringList() << "Simple" << "SRVB" << "Trilinear" << "Complex", QStringList()); m_fractureModel = nmDataAttribute("Fracture model", "Infinite conductivity", "", UNIT_TYPE_DIMENSIONLESS, QStringList() << "Infinite conductivity" << "Finite conductivity", QStringList()); m_dFc = nmDataAttribute("dFc", 1000, "md.m", UNIT_TYPE_CONDUCTIVITY, QStringList(), QStringList() << "md.ft" << "md.m" << "m^3"); m_numberOfFractures = nmDataAttribute("Number of fractures", 15, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); m_fractureHalfLength = nmDataAttribute("Fracture half length", 50.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().toDouble(), "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", 90.0000, "o", UNIT_TYPE_ANGLE, QStringList(), QStringList() << "o" << "radian"); m_stimulatedZonesAroundFracture = nmDataAttribute("Stimulated zones around fracture", "true", "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); m_stimulationRadius = nmDataAttribute("Stimulation radius", 30.0000, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km"); m_permeabilityMultiplier = nmDataAttribute("Permeability multiplier", 5.000000, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); m_porosityMultiplier = nmDataAttribute("Porosity multiplier", 5.00000, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); // 多段压裂水平井 m_eWellType = NM_WELL_MODEL::Horizontal_Fractured_Well; // 释放所有射孔段对象 qDeleteAll(m_vecPerforations); m_vecPerforations.clear(); // 重新定义属于多段压裂水平井的第一条射孔段 nmDataPerforation* defaultPerforation = new nmDataPerforation(); defaultPerforation->getMdStart().setValue(m_bottomholeMD.getValue().toDouble() + 150.0); defaultPerforation->getMdEnd().setValue(m_bottomholeMD.getValue().toDouble() + m_wellLength.getValue().toDouble() + 150.0); m_vecPerforations.append(defaultPerforation); // 添加指针 this->connectAttributeSignals(); } // 拷贝构造函数 nmDataHorizontalFracturedWell::nmDataHorizontalFracturedWell(const nmDataHorizontalFracturedWell& other) : nmDataHorizontalWell(other) { *this = other; // 使用赋值运算符实现 this->connectAttributeSignals(); } // 赋值运算符 nmDataHorizontalFracturedWell& nmDataHorizontalFracturedWell::operator=(const nmDataHorizontalFracturedWell& other) { if (this != &other) { nmDataHorizontalWell::operator=(other); m_modelingType = other.m_modelingType; m_fractureModel = other.m_fractureModel; m_dFc = other.m_dFc; m_numberOfFractures = other.m_numberOfFractures; 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_stimulatedZonesAroundFracture = other.m_stimulatedZonesAroundFracture; m_stimulationRadius = other.m_stimulationRadius; m_permeabilityMultiplier = other.m_permeabilityMultiplier; m_porosityMultiplier = other.m_porosityMultiplier; m_vecFracs = other.m_vecFracs; m_fractureMds = other.m_fractureMds; } return *this; } nmDataWellBase* nmDataHorizontalFracturedWell::clone() const { return new nmDataHorizontalFracturedWell(*this); } // 序列化 nmDataHorizontalFracturedWell 为 RapidJSON Value rapidjson::Value nmDataHorizontalFracturedWell::ToJsonValue(rapidjson::Document::AllocatorType& allocator) const { // 序列化水平井参数 rapidjson::Value horizontalFractureWellObject = nmDataHorizontalWell::ToJsonValue(allocator); // 序列化 nmDataAttribute 类型的成员 // 调用 nmDataAttribute 自身的 ToJsonValue 方法进行递归序列化 horizontalFractureWellObject.AddMember("ModelingType", m_modelingType.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("FractureModel", m_fractureModel.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("dFc", m_dFc.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("NumberOfFractures", m_numberOfFractures.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("FractureHalfLength", m_fractureHalfLength.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("FractureHeight", m_fractureHeight.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("FractureMidPointHeight", m_fractureMidPointHeight.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("Width", m_width.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("FractureAngle", m_fractureAngle.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("StimulatedZonesAroundFracture", m_stimulatedZonesAroundFracture.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("StimulationRadius", m_stimulationRadius.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("PermeabilityMultiplier", m_permeabilityMultiplier.ToJsonValue(allocator), allocator); horizontalFractureWellObject.AddMember("PorosityMultiplier", m_porosityMultiplier.ToJsonValue(allocator), allocator); return horizontalFractureWellObject; // 返回序列化后的 RapidJSON Value } // 从 RapidJSON Value 反序列化数据到 nmDataHorizontalFracturedWell void nmDataHorizontalFracturedWell::FromJsonValue(const rapidjson::Value& jsonValue) { // 反序列化水平井参数 nmDataHorizontalWell::FromJsonValue(jsonValue); // 反序列化 nmDataAttribute 类型的成员 // 调用 nmDataAttribute 自身的 FromJsonValue 方法进行递归反序列化 if (jsonValue.HasMember("ModelingType") && jsonValue["ModelingType"].IsObject()) { m_modelingType.FromJsonValue(jsonValue["ModelingType"]); } 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("NumberOfFractures") && jsonValue["NumberOfFractures"].IsObject()) { m_numberOfFractures.FromJsonValue(jsonValue["NumberOfFractures"]); } 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"]); } if (jsonValue.HasMember("StimulatedZonesAroundFracture") && jsonValue["StimulatedZonesAroundFracture"].IsObject()) { m_stimulatedZonesAroundFracture.FromJsonValue(jsonValue["StimulatedZonesAroundFracture"]); } if (jsonValue.HasMember("StimulationRadius") && jsonValue["StimulationRadius"].IsObject()) { m_stimulationRadius.FromJsonValue(jsonValue["StimulationRadius"]); } if (jsonValue.HasMember("PermeabilityMultiplier") && jsonValue["PermeabilityMultiplier"].IsObject()) { m_permeabilityMultiplier.FromJsonValue(jsonValue["PermeabilityMultiplier"]); } if (jsonValue.HasMember("PorosityMultiplier") && jsonValue["PorosityMultiplier"].IsObject()) { m_porosityMultiplier.FromJsonValue(jsonValue["PorosityMultiplier"]); } // 计算裂缝相关信息 this->setFracs(); } void nmDataHorizontalFracturedWell::connectAttributeSignals() { // 基础井位置 connect(&this->getX(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged())); connect(&this->getY(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged())); connect(&this->getWellLength(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged())); connect(&this->getDrainAngle(), SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged())); // 多段压裂水平井属性 connect(&m_modelingType, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_fractureModel, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_dFc, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_numberOfFractures, SIGNAL(sigValueChanged()), this, SLOT(onFractureAttributeChanged())); 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())); connect(&m_stimulatedZonesAroundFracture, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_stimulationRadius, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_permeabilityMultiplier, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); connect(&m_porosityMultiplier, SIGNAL(sigValueChanged()), this, SIGNAL(sigWellDataChanged())); } void nmDataHorizontalFracturedWell::getPerforationAllowedMdRange(nmDataPerforation* pPerfToValidate, double& dUpperAllowedMd, double& dLowerAllowedMd) { // 直接调用父类的实现 nmDataHorizontalWell::getPerforationAllowedMdRange(pPerfToValidate, dUpperAllowedMd, dLowerAllowedMd); } void nmDataHorizontalFracturedWell::onFractureAttributeChanged() { this->setFracs(); // 重新计算裂缝点 emit sigWellDataChanged(); // 发送井数据改变的通用信号 } void nmDataHorizontalFracturedWell::setModelingType(const nmDataAttribute& attr) { m_modelingType = attr; } void nmDataHorizontalFracturedWell::setFractureModel(const nmDataAttribute& attr) { m_fractureModel = attr; } void nmDataHorizontalFracturedWell::setNumberOfFractures(const nmDataAttribute& attr) { m_numberOfFractures = attr; } void nmDataHorizontalFracturedWell::setFractureHalfLength(const nmDataAttribute& attr) { m_fractureHalfLength = attr; } void nmDataHorizontalFracturedWell::setFractureHeight(const nmDataAttribute& attr) { m_fractureHeight = attr; } void nmDataHorizontalFracturedWell::setFractureMidPointHeight(const nmDataAttribute& attr) { m_fractureMidPointHeight = attr; } void nmDataHorizontalFracturedWell::setWidth(const nmDataAttribute& attr) { m_width = attr; } void nmDataHorizontalFracturedWell::setFractureAngle(const nmDataAttribute& attr) { m_fractureAngle = attr; } void nmDataHorizontalFracturedWell::setStimulatedZonesAroundFracture(const nmDataAttribute& attr) { m_stimulatedZonesAroundFracture = attr; } void nmDataHorizontalFracturedWell::setStimulationRadius(const nmDataAttribute& attr) { m_stimulationRadius = attr; } void nmDataHorizontalFracturedWell::setPermeabilityMultiplier(const nmDataAttribute& attr) { m_permeabilityMultiplier = attr; } void nmDataHorizontalFracturedWell::setPorosityMultiplier(const nmDataAttribute& attr) { m_porosityMultiplier = attr; } void nmDataHorizontalFracturedWell::setFracs() { m_vecFracs.clear(); // 清空旧的俯视图裂缝数据 m_fractureMds.clear(); // 清空旧的裂缝测深数据 QVector> vecFractures; // 井的位置 double wellX = this->getX().getValue().toDouble(); double wellY = this->getY().getValue().toDouble(); // 获取裂缝半长 double halfLength = this->getFractureHalfLength().getValue().toDouble(); // 获取裂缝数量 int fracturedNum = this->getNumberOfFractures().getValue().toInt(); // 获取井长 double wellLength = this->getWellLength().getValue().toDouble(); // 确保这里获取的是 double 值 // 获取井的排水角度(与X轴的夹角,通常是度) double drainAngleDegrees = this->getDrainAngle().getValue().toDouble(); // 将井的排水角度从度转换为弧度 double drainAngleRad = drainAngleDegrees * M_PI / 180.0; // 使用标准的 M_PI 常量 // 获取裂缝相对于井筒的“相对角度”(度) // 根据你的图片,这个角度是裂缝与井筒轴线的夹角。 double dFractureRelativeAngleDegrees = this->getFractureAngle().getValue().toDouble(); // 将裂缝的相对角度从度转换为弧度 double fractureRelativeAngleRad = dFractureRelativeAngleDegrees * M_PI / 180.0; // 确保至少有两个裂缝(端点的两个) if (fracturedNum < 2) { fracturedNum = 2; } // 计算相邻裂缝之间的间隔比例 double intervalRatio = 1.0 / (fracturedNum - 1); // 绘制裂缝 for (int i = 0; i < fracturedNum; ++i) { // 计算当前裂缝交点在井线上的测深(裂缝到井口的距离) double currentFractureMD = i * intervalRatio * wellLength; m_fractureMds.append(currentFractureMD + wellX); // 将MD存储起来,这里需要考虑井口起点 // 计算裂缝中心点在世界坐标系中的X, Y 坐标 // 裂缝中心点沿着井筒方向延伸 double fracCenterX = wellX + currentFractureMD * cos(drainAngleRad); double fracCenterY = wellY + currentFractureMD * sin(drainAngleRad); // 计算裂缝在世界坐标系中的**绝对角度**(弧度) // 现在,绝对角度就是井筒方向加上裂缝的相对角度 double fractureAbsoluteAngleRad = drainAngleRad + fractureRelativeAngleRad; // 计算裂缝端点的偏移量 double dx_frac = halfLength * cos(fractureAbsoluteAngleRad); double dy_frac = halfLength * sin(fractureAbsoluteAngleRad); // 计算裂缝的两点坐标 QPointF startPoint(fracCenterX - dx_frac, fracCenterY - dy_frac); QPointF endPoint(fracCenterX + dx_frac, fracCenterY + dy_frac); QPair frac; frac.first = startPoint; frac.second = endPoint; vecFractures.push_back(frac); } m_vecFracs = vecFractures; } nmDataAttribute& nmDataHorizontalFracturedWell::getModelingType() { return m_modelingType; } nmDataAttribute& nmDataHorizontalFracturedWell::getFractureModel() { return m_fractureModel; } nmDataAttribute& nmDataHorizontalFracturedWell::getNumberOfFractures() { return m_numberOfFractures; } nmDataAttribute& nmDataHorizontalFracturedWell::getFractureHalfLength() { return m_fractureHalfLength; } nmDataAttribute& nmDataHorizontalFracturedWell::getFractureHeight() { return m_fractureHeight; } nmDataAttribute& nmDataHorizontalFracturedWell::getFractureMidPointHeight() { return m_fractureMidPointHeight; } nmDataAttribute& nmDataHorizontalFracturedWell::getWidth() { return m_width; } nmDataAttribute& nmDataHorizontalFracturedWell::getFractureAngle() { return m_fractureAngle; } nmDataAttribute& nmDataHorizontalFracturedWell::getStimulatedZonesAroundFracture() { return m_stimulatedZonesAroundFracture; } nmDataAttribute& nmDataHorizontalFracturedWell::getStimulationRadius() { return m_stimulationRadius; } nmDataAttribute& nmDataHorizontalFracturedWell::getPermeabilityMultiplier() { return m_permeabilityMultiplier; } nmDataAttribute& nmDataHorizontalFracturedWell::getPorosityMultiplier() { return m_porosityMultiplier; } void nmDataHorizontalFracturedWell::setDfc(const nmDataAttribute& attr) { m_dFc = attr; } nmDataAttribute& nmDataHorizontalFracturedWell::getDfc() { return m_dFc; } QVector>& nmDataHorizontalFracturedWell::getFracs(){ return m_vecFracs; } // 新增:获取裂缝测深列表的实现 QVector nmDataHorizontalFracturedWell::getFractureMds() const { return m_fractureMds; }