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/Src/nmNum/nmData/nmDataVerticalFracturedWell...

276 lines
12 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.

#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;
}