|
|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
|
|
|
|
#include "nmAttrRegistry.h"
|
|
|
|
|
|
|
|
|
|
@ -13,6 +13,7 @@
|
|
|
|
|
|
|
|
|
|
#include "ZxDataWell.h"
|
|
|
|
|
#include "ZxBaseUtil.h"
|
|
|
|
|
#include <QSet>
|
|
|
|
|
#include "zxLogInstance.h"
|
|
|
|
|
|
|
|
|
|
#include "nmDataReservoir.h"
|
|
|
|
|
@ -71,6 +72,40 @@
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
|
|
|
|
// 井基参数名 → 数据成员访问器的映射描述
|
|
|
|
|
struct WellParaDesc {
|
|
|
|
|
const char* sName; // 参数基名,如 "W_X"
|
|
|
|
|
nmDataAttribute* (*getAttr)(nmDataWellBase&); // 访问器函数指针
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static nmDataAttribute* getParaX(nmDataWellBase& w) { return &w.getX(); }
|
|
|
|
|
static nmDataAttribute* getParaY(nmDataWellBase& w) { return &w.getY(); }
|
|
|
|
|
static nmDataAttribute* getParaRw(nmDataWellBase& w) { return &w.getRadius(); }
|
|
|
|
|
static nmDataAttribute* getParaC(nmDataWellBase& w) { return &w.getWellboreStorage(); }
|
|
|
|
|
static nmDataAttribute* getParaSkin(nmDataWellBase& w)
|
|
|
|
|
{
|
|
|
|
|
return w.getPerforationCount() > 0 ? &w.getPerforation(0)->getSkin() : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const WellParaDesc WELL_PARA_DESCS[] = {
|
|
|
|
|
{"W_X", &getParaX},
|
|
|
|
|
{"W_Y", &getParaY},
|
|
|
|
|
{"W_Rw", &getParaRw},
|
|
|
|
|
{"W_C", &getParaC},
|
|
|
|
|
{"W_Skin", &getParaSkin},
|
|
|
|
|
};
|
|
|
|
|
static const int WELL_PARA_DESC_COUNT = sizeof(WELL_PARA_DESCS) / sizeof(WELL_PARA_DESCS[0]);
|
|
|
|
|
|
|
|
|
|
static bool isWellParaAttrName(const QString& name)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < WELL_PARA_DESC_COUNT; ++i) {
|
|
|
|
|
if (name.endsWith(QString("_") + WELL_PARA_DESCS[i].sName)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
// 清空指定目录下的所有旧文件和子目录,但保留目录本身
|
|
|
|
|
bool clearDirectoryContents(const QString& dirPath)
|
|
|
|
|
@ -579,6 +614,9 @@ nmDataWellBase* nmDataAnalyzeManager::changeWellType(nmDataWellBase* pOldWellDat
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString wellCode = pOldWellData->getWellCode();
|
|
|
|
|
const QString wellName = pOldWellData->getWellName();
|
|
|
|
|
|
|
|
|
|
if(!removeWell(pOldWellData)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
@ -589,6 +627,10 @@ nmDataWellBase* nmDataAnalyzeManager::changeWellType(nmDataWellBase* pOldWellDat
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pNewWellData->setWellCode(wellCode);
|
|
|
|
|
pNewWellData->setWellName(wellName);
|
|
|
|
|
appendNmWellData(pNewWellData);
|
|
|
|
|
|
|
|
|
|
return pNewWellData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -621,18 +663,33 @@ bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历 m_vWellData,找到并移除指定的井对象
|
|
|
|
|
for(auto it = m_vWellData.begin(); it != m_vWellData.end(); ++it) {
|
|
|
|
|
if(*it == pWellData) {
|
|
|
|
|
m_vWellData.erase(it);
|
|
|
|
|
delete pWellData;
|
|
|
|
|
pWellData = nullptr;
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
return true; // 成功移除并删除井对象
|
|
|
|
|
if (!m_vWellData.contains(pWellData)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString removedCode = pWellData->getWellCode();
|
|
|
|
|
QString removedName = pWellData->getWellName();
|
|
|
|
|
|
|
|
|
|
// 先从 registry 清理该井的所有属性,避免野指针
|
|
|
|
|
if (m_pAttrRegistry) {
|
|
|
|
|
for (int i = 0; i < WELL_PARA_DESC_COUNT; ++i) {
|
|
|
|
|
QString name = removedCode + "_" + WELL_PARA_DESCS[i].sName;
|
|
|
|
|
m_pAttrRegistry->unregAttr(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 倒序移除全部匹配项,兼容旧逻辑可能遗留的重复指针。
|
|
|
|
|
for (int i = m_vWellData.size() - 1; i >= 0; --i) {
|
|
|
|
|
if (m_vWellData[i] == pWellData) {
|
|
|
|
|
m_vWellData.remove(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
delete pWellData;
|
|
|
|
|
pWellData = nullptr;
|
|
|
|
|
|
|
|
|
|
return false; // 如果未找到该井对象,返回 false
|
|
|
|
|
emit sigWellRemoved(removedCode, removedName);
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData)
|
|
|
|
|
@ -659,16 +716,37 @@ void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData)
|
|
|
|
|
|
|
|
|
|
void nmDataAnalyzeManager::clearAllWellData()
|
|
|
|
|
{
|
|
|
|
|
// 遍历并删除所有井对象
|
|
|
|
|
typedef QPair<QString, QString> WellIdentity;
|
|
|
|
|
QList<WellIdentity> removedWells;
|
|
|
|
|
|
|
|
|
|
// 遍历并删除所有井对象,兼容旧逻辑可能遗留的重复指针。
|
|
|
|
|
QSet<nmDataWellBase*> deletedWells;
|
|
|
|
|
foreach(nmDataWellBase* pWell, m_vWellData) {
|
|
|
|
|
if(pWell != nullptr) {
|
|
|
|
|
if(pWell != nullptr && !deletedWells.contains(pWell)) {
|
|
|
|
|
deletedWells.insert(pWell);
|
|
|
|
|
removedWells.append(qMakePair(pWell->getWellCode(), pWell->getWellName()));
|
|
|
|
|
delete pWell;
|
|
|
|
|
pWell = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 清空数组
|
|
|
|
|
m_vWellData.clear();
|
|
|
|
|
m_pCurDataWell = nullptr;
|
|
|
|
|
m_vecCalculationWells.clear();
|
|
|
|
|
|
|
|
|
|
// 清理 registry 中所有井相关属性
|
|
|
|
|
if (m_pAttrRegistry) {
|
|
|
|
|
foreach (const QString& name, m_pAttrRegistry->registeredNames()) {
|
|
|
|
|
if (isWellParaAttrName(name)) {
|
|
|
|
|
m_pAttrRegistry->unregAttr(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (const WellIdentity& well, removedWells) {
|
|
|
|
|
emit sigWellRemoved(well.first, well.second);
|
|
|
|
|
}
|
|
|
|
|
emit dataChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<nmDataWellBase*> nmDataAnalyzeManager::getWellDataList() const
|
|
|
|
|
@ -1264,13 +1342,44 @@ void nmDataAnalyzeManager::appendWellData(ZxDataWell* pWellData)
|
|
|
|
|
// 设置流量段索引
|
|
|
|
|
pHFracturedWell->setIndexF(nIndexF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知面板新增井分组
|
|
|
|
|
{
|
|
|
|
|
syncWellAttrs();
|
|
|
|
|
QString code = pWellData->getCode();
|
|
|
|
|
QString name = pWellData->getName();
|
|
|
|
|
QStringList paras;
|
|
|
|
|
for (int i = 0; i < WELL_PARA_DESC_COUNT; ++i) {
|
|
|
|
|
paras << WELL_PARA_DESCS[i].sName;
|
|
|
|
|
}
|
|
|
|
|
emit sigWellAdded(code, name, paras);
|
|
|
|
|
if (m_pAttrRegistry)
|
|
|
|
|
m_pAttrRegistry->refreshAll();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmDataAnalyzeManager::appendNmWellData(nmDataWellBase* pWellData)
|
|
|
|
|
{
|
|
|
|
|
if (pWellData == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
m_vWellData.append(pWellData);
|
|
|
|
|
if (!m_vWellData.contains(pWellData))
|
|
|
|
|
{
|
|
|
|
|
m_vWellData.append(pWellData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知面板新增井分组
|
|
|
|
|
{
|
|
|
|
|
syncWellAttrs();
|
|
|
|
|
QString code = pWellData->getWellCode();
|
|
|
|
|
QString name = pWellData->getWellName();
|
|
|
|
|
QStringList paras;
|
|
|
|
|
for (int i = 0; i < WELL_PARA_DESC_COUNT; ++i) {
|
|
|
|
|
paras << WELL_PARA_DESCS[i].sName;
|
|
|
|
|
}
|
|
|
|
|
emit sigWellAdded(code, name, paras);
|
|
|
|
|
if (m_pAttrRegistry)
|
|
|
|
|
m_pAttrRegistry->refreshAll();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @brief 创建油藏数据对象,从界面读取PVT单值和分层数据,构建reservoir对象
|
|
|
|
|
@ -1356,48 +1465,40 @@ nmAttrRegistry* nmDataAnalyzeManager::getAttrRegistry() const
|
|
|
|
|
return m_pAttrRegistry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 井基参数名 → 数据成员访问器的映射描述
|
|
|
|
|
struct WellParaDesc {
|
|
|
|
|
const char* sName; // 参数基名,如 "W_X"
|
|
|
|
|
nmDataAttribute* (*getAttr)(nmDataWellBase&); // 访问器函数指针
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static nmDataAttribute* getParaX(nmDataWellBase& w) { return &w.getX(); }
|
|
|
|
|
static nmDataAttribute* getParaY(nmDataWellBase& w) { return &w.getY(); }
|
|
|
|
|
static nmDataAttribute* getParaRw(nmDataWellBase& w) { return &w.getRadius(); }
|
|
|
|
|
static nmDataAttribute* getParaC(nmDataWellBase& w) { return &w.getWellboreStorage(); }
|
|
|
|
|
static nmDataAttribute* getParaSkin(nmDataWellBase& w)
|
|
|
|
|
{
|
|
|
|
|
return w.getPerforationCount() > 0 ? &w.getPerforation(0)->getSkin() : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const WellParaDesc WELL_PARA_DESCS[] = {
|
|
|
|
|
{"W_X", &getParaX},
|
|
|
|
|
{"W_Y", &getParaY},
|
|
|
|
|
{"W_Rw", &getParaRw},
|
|
|
|
|
{"W_C", &getParaC},
|
|
|
|
|
{"W_Skin", &getParaSkin},
|
|
|
|
|
};
|
|
|
|
|
static const int WELL_PARA_DESC_COUNT = sizeof(WELL_PARA_DESCS) / sizeof(WELL_PARA_DESCS[0]);
|
|
|
|
|
|
|
|
|
|
void nmDataAnalyzeManager::registerWellAttrs()
|
|
|
|
|
void nmDataAnalyzeManager::syncWellAttrs()
|
|
|
|
|
{
|
|
|
|
|
if (m_pAttrRegistry == NULL) return;
|
|
|
|
|
|
|
|
|
|
QSet<QString> activeAttrNames;
|
|
|
|
|
QSet<QString> activeWellCodes;
|
|
|
|
|
foreach (nmDataWellBase* pWell, m_vWellData)
|
|
|
|
|
{
|
|
|
|
|
if (pWell == nullptr) continue;
|
|
|
|
|
|
|
|
|
|
QString code = pWell->getWellCode();
|
|
|
|
|
if (code.isEmpty()) continue;
|
|
|
|
|
if (code.isEmpty() || activeWellCodes.contains(code)) continue;
|
|
|
|
|
activeWellCodes.insert(code);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < WELL_PARA_DESC_COUNT; ++i)
|
|
|
|
|
{
|
|
|
|
|
nmDataAttribute* pAttr = WELL_PARA_DESCS[i].getAttr(*pWell);
|
|
|
|
|
if (pAttr != NULL)
|
|
|
|
|
{
|
|
|
|
|
m_pAttrRegistry->regAttr(code + "_" + WELL_PARA_DESCS[i].sName, pAttr);
|
|
|
|
|
QString name = code + "_" + WELL_PARA_DESCS[i].sName;
|
|
|
|
|
activeAttrNames.insert(name);
|
|
|
|
|
m_pAttrRegistry->regAttr(name, pAttr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 精确清理已经不存在的井参数注册,兼容 wellCode 自身包含下划线。
|
|
|
|
|
foreach (const QString& name, m_pAttrRegistry->registeredNames())
|
|
|
|
|
{
|
|
|
|
|
if (isWellParaAttrName(name) && !activeAttrNames.contains(name))
|
|
|
|
|
{
|
|
|
|
|
m_pAttrRegistry->unregAttr(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmDataReservoir nmDataAnalyzeManager::getReservoirDataCopy() const
|
|
|
|
|
@ -1679,8 +1780,8 @@ void nmDataAnalyzeManager::applyDiagnosticResults(nmDataDiagnostic* diagnostic,
|
|
|
|
|
nmDataPerforation* firstPerforation = wellData->getPerforation(0);
|
|
|
|
|
if(firstPerforation) {
|
|
|
|
|
firstPerforation->getSkin().setValue(diagnosticSkin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmDataAutomaticFitting* nmDataAnalyzeManager::createAutomaticFittingData()
|
|
|
|
|
|