|
|
#include "nmDataAnalyzeManager.h"
|
|
|
|
|
|
#include "nmDataAnalyzeContext.h"
|
|
|
#include "nmDataAnalyzeContextProvider.h"
|
|
|
#include "nmDataPlotContext.h"
|
|
|
#include "nmDataPlotContextProvider.h"
|
|
|
#include "nmDataWellBase.h"
|
|
|
#include "nmDataVerticalWell.h"
|
|
|
#include "nmDataVerticalFracturedWell.h"
|
|
|
#include "nmDataHorizontalFracturedWell.h"
|
|
|
|
|
|
#include "ZxDataWell.h"
|
|
|
#include "ZxBaseUtil.h"
|
|
|
#include "zxLogInstance.h"
|
|
|
|
|
|
#include "nmDataReservoir.h"
|
|
|
|
|
|
#include "nmDataRegionMark.h"
|
|
|
#include "nmDataOutline.h"
|
|
|
#include "nmDataRegion.h"
|
|
|
#include "nmDataFracture.h"
|
|
|
#include "nmDataFault.h"
|
|
|
#include "nmDataMeasuringScale.h"
|
|
|
#include "nmDataMeasure.h"
|
|
|
#include "nmDataAxis.h"
|
|
|
#include "nmDataGeoRef.h"
|
|
|
#include "nmDataDiagnostic.h"
|
|
|
#include "nmDataForecast.h"
|
|
|
#include "nmDataAutomaticFitting.h"
|
|
|
#include "nmDataSensitive.h"
|
|
|
|
|
|
|
|
|
#include "nmDataPvtParaForPebi.h"
|
|
|
#include "ZxDataWell.h"
|
|
|
#include "ZxDataGaugeP.h"
|
|
|
#include "ZxDataGaugeF.h"
|
|
|
#include "zxSysUtils.h"
|
|
|
#include "ZxDataProject.h"
|
|
|
|
|
|
#include "nmDataMixedResults.h"
|
|
|
#include "nmDataLayer.h"
|
|
|
#include "nmDataUtils.h"
|
|
|
|
|
|
#include "mAlgDefines.h"
|
|
|
|
|
|
#include "nmDataJsonTools.h" // JSON工具类
|
|
|
#include "nmTranslationManager.h"
|
|
|
|
|
|
#include "iAnalRun.h"
|
|
|
#include "ZxDataAnalRun.h"
|
|
|
|
|
|
#include <Windows.h>
|
|
|
#include <iostream>
|
|
|
#include <vector>
|
|
|
#include "singlePhaseSolver.h"
|
|
|
|
|
|
#include <vtkUnstructuredGridReader.h>
|
|
|
#include <vtkXMLUnstructuredGridReader.h>
|
|
|
#include <vtkUnstructuredGridWriter.h>
|
|
|
#include <vtkXMLUnstructuredGridWriter.h>
|
|
|
#include <vtkNew.h>
|
|
|
|
|
|
#include "nmDataTimeStepSetting.h"
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
#include <QDebug>
|
|
|
#include <QDir>
|
|
|
#include <QFile>
|
|
|
#include <QFileInfo>
|
|
|
|
|
|
namespace {
|
|
|
// 清空指定目录下的所有旧文件和子目录,但保留目录本身
|
|
|
bool clearDirectoryContents(const QString& dirPath)
|
|
|
{
|
|
|
if(dirPath.trimmed().isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDir dir(dirPath);
|
|
|
if(dir.isRoot()) {
|
|
|
qDebug() << QString("Refuse to clear root directory: %1").arg(dirPath);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if(!dir.exists()) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
QFileInfoList entries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden | QDir::System);
|
|
|
for(int i = 0; i < entries.size(); ++i) {
|
|
|
const QFileInfo& entry = entries.at(i);
|
|
|
bool bRemoved = false;
|
|
|
|
|
|
if(entry.isDir() && !entry.isSymLink()) {
|
|
|
bRemoved = clearDirectoryContents(entry.absoluteFilePath()) && dir.rmdir(entry.fileName());
|
|
|
} else {
|
|
|
bRemoved = QFile::remove(entry.absoluteFilePath());
|
|
|
}
|
|
|
|
|
|
if(!bRemoved) {
|
|
|
qDebug() << QString("Failed to remove old result item: %1").arg(entry.absoluteFilePath());
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 多条PVT曲线都可能带压力横坐标,只保存第一次读到的有效横坐标
|
|
|
void setPebiPressureIfEmpty(nmDataPvtParaForPebi* pPvtPara, const QVector<double>& vecX)
|
|
|
{
|
|
|
if(pPvtPara != nullptr && pPvtPara->getPressure().isEmpty() && !vecX.isEmpty()) {
|
|
|
pPvtPara->setPressure(vecX);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 根据当前PVT相态决定需要访问哪些相态页。
|
|
|
// 这里只控制PVT页面读取范围,后续参数默认值和PEBI赋值逻辑保持不变。
|
|
|
void resolvePvtPhaseReadFlags(PvtFluidType eType, bool& bReadOil, bool& bReadGas, bool& bReadWater)
|
|
|
{
|
|
|
bReadOil = false;
|
|
|
bReadGas = false;
|
|
|
bReadWater = false;
|
|
|
|
|
|
switch(eType) {
|
|
|
case WFT_Oil:
|
|
|
// 单相油:只访问油相页,避免访问不存在的气/水相页
|
|
|
bReadOil = true;
|
|
|
break;
|
|
|
case WFT_Gas:
|
|
|
// 单相气:只访问气相页
|
|
|
bReadGas = true;
|
|
|
break;
|
|
|
case WFT_Water:
|
|
|
// 单相水:只访问水相页
|
|
|
bReadWater = true;
|
|
|
break;
|
|
|
case WFT_Oil_Water:
|
|
|
// 油水:访问油相和水相页,不访问气相页
|
|
|
bReadOil = true;
|
|
|
bReadWater = true;
|
|
|
break;
|
|
|
default:
|
|
|
// 未识别相态不主动读取相态页,避免PVT工具输出缺失子窗口日志
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 从Diffusion右侧结果表中提取指定列数据
|
|
|
bool extractDiffusionColumn(const VVecDouble& vvec, int nColumn, QVector<double>& vecValues)
|
|
|
{
|
|
|
vecValues.clear();
|
|
|
if(vvec.isEmpty() || nColumn < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if(vvec.size() > nColumn && vvec[nColumn].size() > 4 && vvec[nColumn].size() > vvec.size()) {
|
|
|
vecValues = vvec[nColumn];
|
|
|
return !vecValues.isEmpty();
|
|
|
}
|
|
|
|
|
|
// Diffusion结果表通常按行保存:[自变量, 结果1, 结果2]
|
|
|
for(int i = 0; i < vvec.size(); ++i) {
|
|
|
if(vvec[i].size() > nColumn) {
|
|
|
vecValues.append(vvec[i][nColumn]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(!vecValues.isEmpty()) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 兼容少量按列缓存的数据
|
|
|
if(vvec.size() > nColumn) {
|
|
|
vecValues = vvec[nColumn];
|
|
|
}
|
|
|
|
|
|
return !vecValues.isEmpty();
|
|
|
}
|
|
|
|
|
|
// 根据饱和度坐标计算互补饱和度,例如油水相渗中由Sw得到So
|
|
|
QVector<double> complementSaturation(const QVector<double>& vecSaturation)
|
|
|
{
|
|
|
QVector<double> vecResult;
|
|
|
vecResult.reserve(vecSaturation.size());
|
|
|
|
|
|
for(int i = 0; i < vecSaturation.size(); ++i) {
|
|
|
vecResult.append(1.0 - vecSaturation[i]);
|
|
|
}
|
|
|
|
|
|
return vecResult;
|
|
|
}
|
|
|
|
|
|
// 将数组顺序反转,用于把Diffusion中按Sw递增的数据整理为按So递增的数据
|
|
|
QVector<double> reversedVector(const QVector<double>& vecValues)
|
|
|
{
|
|
|
QVector<double> vecResult;
|
|
|
vecResult.reserve(vecValues.size());
|
|
|
|
|
|
for(int i = vecValues.size(); i > 0; --i) {
|
|
|
vecResult.append(vecValues[i - 1]);
|
|
|
}
|
|
|
|
|
|
return vecResult;
|
|
|
}
|
|
|
|
|
|
// 将油水两相Diffusion相渗结果映射到PEBI求解器需要的饱和度和相对渗透率字段
|
|
|
void applyDiffusionKkToPebiPvt(nmDataPvtParaForPebi* pPvtPara, const VVecDouble& vvecKK)
|
|
|
{
|
|
|
if(vvecKK.isEmpty()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
QVector<double> vecS;
|
|
|
QVector<double> vecKr1;
|
|
|
QVector<double> vecKr2;
|
|
|
|
|
|
if(!extractDiffusionColumn(vvecKK, 0, vecS)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
extractDiffusionColumn(vvecKK, 1, vecKr1);
|
|
|
extractDiffusionColumn(vvecKK, 2, vecKr2);
|
|
|
|
|
|
// 油水:第一列为Sw,So按1-Sw生成,后续列为Kro/Krw
|
|
|
pPvtPara->setSw(vecS);
|
|
|
// PEBI默认相渗以So为横坐标,Diffusion表按Sw递增保存,这里整体转为So递增方向
|
|
|
pPvtPara->setSo(reversedVector(complementSaturation(vecS)));
|
|
|
if(!vecKr1.isEmpty()) {
|
|
|
pPvtPara->setKro(reversedVector(vecKr1));
|
|
|
}
|
|
|
if(!vecKr2.isEmpty()) {
|
|
|
pPvtPara->setKrw(reversedVector(vecKr2));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ZX_DEFINE_DYNAMIC(DataAnalyzeManager, nmDataAnalyzeManager)
|
|
|
|
|
|
nmDataAnalyzeManager::nmDataAnalyzeManager(): ZxDataObjectBin(0)
|
|
|
{
|
|
|
m_reservoirData = nullptr;
|
|
|
m_outlineData = nullptr;
|
|
|
m_pMeasuringScaleData = nullptr;
|
|
|
m_pebiPvtPara = nullptr;
|
|
|
m_pMixedResults = nullptr;
|
|
|
m_pLayerData = nullptr;
|
|
|
m_pCurDataWell = nullptr;
|
|
|
m_pMeasureData = nullptr;
|
|
|
m_axisData = nullptr;
|
|
|
m_pNmGuiPlot = nullptr;
|
|
|
m_pGeoRefData = nullptr;
|
|
|
m_pTimeStep = nullptr;
|
|
|
//m_pPerCloData = nullptr;
|
|
|
m_pAutomaticFittingData = nullptr;
|
|
|
m_pDiagnosticData = nullptr;
|
|
|
//m_pSkinVsRateData = nullptr;
|
|
|
//m_pFlowSegmentData = nullptr;
|
|
|
m_pForecastData = nullptr;
|
|
|
m_pSensitiveData = nullptr;
|
|
|
m_backgroundImageInfo.bIsVisible = false;
|
|
|
m_dScalarRangeP[0] = 0.0;
|
|
|
m_dScalarRangeP[1] = 0.0;
|
|
|
|
|
|
// 初始化混合参数数据(Temp)
|
|
|
//m_pMixedResults = new nmDataMixedResults;
|
|
|
// 初始化储层数据
|
|
|
m_pLayerData = new nmDataLayer;
|
|
|
m_eGridType = NM_Grid_Type::NM_Grid_PEBI; //默认网格类型为PEBI
|
|
|
this->initDefaultDisplaySettings();
|
|
|
// 初始化中英文翻译映射
|
|
|
nmTranslationManager::initTranslations();
|
|
|
m_bIsLoadData = false;
|
|
|
|
|
|
// 获取完整路径
|
|
|
//QString appPath = QCoreApplication::applicationFilePath();
|
|
|
//qDebug() << "完整应用路径:" << appPath;
|
|
|
// 许可证路径
|
|
|
//m_licensePath = appPath + "/../../3rd/Pebi/license/HXNWTM_license.dat";
|
|
|
|
|
|
// 获取完整路径
|
|
|
QString appPath = QCoreApplication::applicationFilePath();
|
|
|
|
|
|
// 获取应用程序所在的目录
|
|
|
QString appDir = QFileInfo(appPath).absolutePath();
|
|
|
|
|
|
// 定义从应用程序目录到许可证目录的相对路径
|
|
|
QString relativeJump = "/../Res/license/HXNWTM_license.dat";
|
|
|
|
|
|
// 将目录和相对跳转路径拼接
|
|
|
m_licensePath = appDir + relativeJump;
|
|
|
}
|
|
|
|
|
|
// 初始化静态成员
|
|
|
QMap<iSubWndFitting*, nmDataAnalyzeManager*> nmDataAnalyzeManager::s_mapDataAnalManager;
|
|
|
iSubWndFitting* nmDataAnalyzeManager::s_pCurSubWndFitting = nullptr;
|
|
|
|
|
|
nmDataAnalyzeManager* nmDataAnalyzeManager::getInstanceByFitting(iSubWndFitting* pSubWndF)
|
|
|
{
|
|
|
if(s_mapDataAnalManager.contains(pSubWndF)) {
|
|
|
return s_mapDataAnalManager[pSubWndF];
|
|
|
}
|
|
|
|
|
|
nmDataAnalyzeManager* pInstance = new nmDataAnalyzeManager();
|
|
|
s_mapDataAnalManager[pSubWndF] = pInstance;
|
|
|
return pInstance;
|
|
|
}
|
|
|
|
|
|
nmDataAnalyzeManager* nmDataAnalyzeManager::getCurrentInstance()
|
|
|
{
|
|
|
if(s_mapDataAnalManager.contains(s_pCurSubWndFitting)) {
|
|
|
return s_mapDataAnalManager[s_pCurSubWndFitting];
|
|
|
} else {
|
|
|
return nullptr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataWellBase *nmDataAnalyzeManager::createWell(NM_WELL_MODEL eWellType)
|
|
|
{
|
|
|
// 根据当前Fitting窗口来获取对应的井相关数据
|
|
|
iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider();
|
|
|
Q_ASSERT(nullptr != pSubWndFitting);
|
|
|
Q_ASSERT(nullptr != pContextProvider);
|
|
|
|
|
|
nmDataWellBase* pWellData = nullptr;
|
|
|
|
|
|
// 新建一口井,默认直井
|
|
|
if(eWellType == NM_WELL_MODEL::Vertical_Well) {
|
|
|
// 直接使用子类指针创建对象
|
|
|
nmDataVerticalWell* verticalWell = new nmDataVerticalWell;
|
|
|
pWellData = static_cast<nmDataWellBase*>(verticalWell);
|
|
|
} else if(eWellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
|
|
|
// 直接使用子类指针创建对象
|
|
|
nmDataVerticalFracturedWell* vFracturedWell = new nmDataVerticalFracturedWell;
|
|
|
pWellData = static_cast<nmDataWellBase*>(vFracturedWell);
|
|
|
} else if(eWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
|
|
|
// 直接使用子类指针创建对象
|
|
|
nmDataHorizontalFracturedWell* hFracturedWell = new nmDataHorizontalFracturedWell;
|
|
|
pWellData = static_cast<nmDataWellBase*>(hFracturedWell);
|
|
|
}
|
|
|
|
|
|
// 默认井才可以选择当前流动段,其余井默认选择最后一段
|
|
|
if(pWellData == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_vWellData.count() == 0) {
|
|
|
int nIndexF = -1;
|
|
|
// 第一口井就选择界面上的流动段索引
|
|
|
// 流动段索引由窗口层上下文提供,数据层不直接访问窗口对象
|
|
|
if(pSubWndFitting != nullptr && pContextProvider != nullptr) {
|
|
|
if(pContextProvider->getCurrentSegmentIndex(pSubWndFitting, nIndexF)) {
|
|
|
// 设置当前流动段索引
|
|
|
pWellData->setIndexF(nIndexF);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
m_vWellData.append(pWellData);
|
|
|
emit dataChanged();
|
|
|
return pWellData;
|
|
|
}
|
|
|
|
|
|
// 实现 changeWellType 函数
|
|
|
nmDataWellBase* nmDataAnalyzeManager::changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType)
|
|
|
{
|
|
|
if(pOldWellData == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
if(!removeWell(pOldWellData)) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
nmDataWellBase* pNewWellData = createWell(eTargetWellType);
|
|
|
|
|
|
if(pNewWellData == nullptr) {
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
return pNewWellData;
|
|
|
}
|
|
|
|
|
|
// 实现 removeWell 函数
|
|
|
bool nmDataAnalyzeManager::removeWell(nmDataWellBase* pWellData)
|
|
|
{
|
|
|
if(pWellData == nullptr) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 遍历 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; // 成功移除并删除井对象
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 如果未找到该井对象,返回 false
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::removeWellDataAndPlot(nmDataWellBase* pWellData)
|
|
|
{
|
|
|
nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider();
|
|
|
if (m_pNmGuiPlot != nullptr && pPlotContextProvider != nullptr)
|
|
|
{
|
|
|
// 移除所有井图元
|
|
|
pPlotContextProvider->removeWellPlotByData(m_pNmGuiPlot, pWellData);
|
|
|
removeWell(pWellData);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::clearAllWellData()
|
|
|
{
|
|
|
// 遍历并删除所有井对象
|
|
|
foreach(nmDataWellBase* pWell, m_vWellData) {
|
|
|
if(pWell != nullptr) {
|
|
|
delete pWell;
|
|
|
pWell = nullptr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 清空数组
|
|
|
m_vWellData.clear();
|
|
|
}
|
|
|
|
|
|
QVector<nmDataWellBase*> nmDataAnalyzeManager::getWellDataList() const
|
|
|
{
|
|
|
return m_vWellData;
|
|
|
}
|
|
|
|
|
|
//QVector<nmDataWellBase> nmDataAnalyzeManager::getWellDataListCopy() const
|
|
|
//{
|
|
|
// QVector<nmDataWellBase> result;
|
|
|
// result.reserve(m_vWellData.size());
|
|
|
//
|
|
|
// foreach(const nmDataWellBase* well, m_vWellData) {
|
|
|
// if(well) {
|
|
|
// result.append(*well); // 调用拷贝构造函数
|
|
|
// }
|
|
|
// }
|
|
|
//
|
|
|
// return result;
|
|
|
//}
|
|
|
|
|
|
//void nmDataAnalyzeManager::updateWellData(const QVector<nmDataWellBase>& newData)
|
|
|
//{
|
|
|
//
|
|
|
// // 确保数量一致
|
|
|
// if (newData.size() != m_vWellData.size()) {
|
|
|
// return;
|
|
|
// }
|
|
|
//
|
|
|
// for (int i = 0; i < newData.size(); ++i) {
|
|
|
// nmDataWellBase* existingWell = m_vWellData[i];
|
|
|
// const nmDataWellBase& newWell = newData[i];
|
|
|
//
|
|
|
// if (existingWell && existingWell->getWellName() == newWell.getWellName()) {
|
|
|
// // 根据类型更新数据
|
|
|
// if (auto existingVFractured = dynamic_cast<nmDataVerticalFracturedWell*>(existingWell)) {
|
|
|
// if (auto newVFractured = dynamic_cast<const nmDataVerticalFracturedWell*>(&newWell)) {
|
|
|
// *existingVFractured = *newVFractured;
|
|
|
// }
|
|
|
// }
|
|
|
// else if (auto existingHFractured = dynamic_cast<nmDataHorizontalFracturedWell*>(existingWell)) {
|
|
|
// if (auto newHFractured = dynamic_cast<const nmDataHorizontalFracturedWell*>(&newWell)) {
|
|
|
// *existingHFractured = *newHFractured;
|
|
|
// }
|
|
|
// } else if (auto existingVertical = dynamic_cast<nmDataVerticalWell*>(existingWell)) {
|
|
|
// if (auto newVertical = dynamic_cast<const nmDataVerticalWell*>(&newWell)) {
|
|
|
// *existingVertical = *newVertical; // 调用赋值运算符
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
//
|
|
|
//}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateVerticalWells(const QVector<nmDataVerticalWell>& wells)
|
|
|
{
|
|
|
foreach(const auto& newWell, wells) {
|
|
|
foreach(auto* existingWell, m_vWellData) {
|
|
|
if(auto * vWell = dynamic_cast<nmDataVerticalWell * >(existingWell)) {
|
|
|
if(vWell->getWellName() == newWell.getWellName()) {
|
|
|
*vWell = newWell; // 调用赋值运算符
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateVerticalFracturedWells(const QVector<nmDataVerticalFracturedWell>& wells)
|
|
|
{
|
|
|
foreach(const auto& newWell, wells) {
|
|
|
foreach(auto* existingWell, m_vWellData) {
|
|
|
if(auto * vWell = dynamic_cast<nmDataVerticalFracturedWell * >(existingWell)) {
|
|
|
if(vWell->getWellName() == newWell.getWellName()) {
|
|
|
*vWell = newWell; // 调用赋值运算符
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateHorizontalFracturedWells(const QVector<nmDataHorizontalFracturedWell>& wells)
|
|
|
{
|
|
|
foreach(const auto& newWell, wells) {
|
|
|
foreach(auto* existingWell, m_vWellData) {
|
|
|
if(auto * vWell = dynamic_cast<nmDataHorizontalFracturedWell * >(existingWell)) {
|
|
|
if(vWell->getWellName() == newWell.getWellName()) {
|
|
|
*vWell = newWell; // 调用赋值运算符
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取所有直井数据
|
|
|
QVector<nmDataVerticalWell*> nmDataAnalyzeManager::getVerticalWellData() const
|
|
|
{
|
|
|
QVector<nmDataVerticalWell*> verticalWells;
|
|
|
|
|
|
foreach(nmDataWellBase* well, m_vWellData) {
|
|
|
nmDataVerticalWell* vWell = dynamic_cast<nmDataVerticalWell*>(well);
|
|
|
|
|
|
if(vWell && !dynamic_cast<nmDataVerticalFracturedWell * >(well)) {
|
|
|
// 确保不是垂直裂缝井
|
|
|
verticalWells.append(vWell);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return verticalWells;
|
|
|
}
|
|
|
|
|
|
// 获取所有垂直裂缝井数据
|
|
|
QVector<nmDataVerticalFracturedWell*> nmDataAnalyzeManager::getVerticalFracturedWellData() const
|
|
|
{
|
|
|
QVector<nmDataVerticalFracturedWell*> vFracturedWells;
|
|
|
|
|
|
foreach(nmDataWellBase* well, m_vWellData) {
|
|
|
nmDataVerticalFracturedWell* vFracturedWell = dynamic_cast<nmDataVerticalFracturedWell*>(well);
|
|
|
|
|
|
if(vFracturedWell) {
|
|
|
vFracturedWells.append(vFracturedWell);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return vFracturedWells;
|
|
|
}
|
|
|
|
|
|
// 获取所有多段压裂水平井数据
|
|
|
QVector<nmDataHorizontalFracturedWell*> nmDataAnalyzeManager::getHorizontalFracturedWellData() const
|
|
|
{
|
|
|
QVector<nmDataHorizontalFracturedWell*> hFracturedWells;
|
|
|
|
|
|
foreach(nmDataWellBase* well, m_vWellData) {
|
|
|
nmDataHorizontalFracturedWell* hFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell*>(well);
|
|
|
|
|
|
if(hFracturedWell) {
|
|
|
hFracturedWells.append(hFracturedWell);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return hFracturedWells;
|
|
|
}
|
|
|
|
|
|
nmDataWellBase* nmDataAnalyzeManager::findWellByName(QString wellName) const
|
|
|
{
|
|
|
foreach(nmDataWellBase* pWell, m_vWellData) {
|
|
|
if(pWell && pWell->getWellName() == wellName) {
|
|
|
return pWell; // 找到匹配的井,返回指针
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nullptr; // 未找到匹配的井,返回 nullptr
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::initCurWellData()
|
|
|
{
|
|
|
// 获取当前默认井数据
|
|
|
ZxDataWell* pWellData = zxCurWell;
|
|
|
if(pWellData == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 判断是哪一种井类型,初始化对应的参数
|
|
|
QString wellClass = pWellData->getWellClassEn();
|
|
|
|
|
|
// 获取当前井的压力、流量数据
|
|
|
ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP);
|
|
|
ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF);
|
|
|
|
|
|
ZxDataGaugeP* pGaugeP = nullptr;
|
|
|
ZxDataGaugeF* pGaugeF = nullptr;
|
|
|
|
|
|
// 遍历压力数据列表
|
|
|
for(int i = 0; i < m_listGaugeP.size(); ++i) {
|
|
|
if(pGaugeP = dynamic_cast<ZxDataGaugeP * >(m_listGaugeP[i])) { // 拿到第一条压力数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 遍历流量数据列表
|
|
|
for(int i = 0; i < m_listGaugeF.size(); ++i) {
|
|
|
if(pGaugeF = dynamic_cast<ZxDataGaugeF * >(m_listGaugeF[i])) { // 拿到第一条流量数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取的压力、流量数据
|
|
|
QVector<QPointF> vecPtsP, vecPtsF;
|
|
|
// 临时存储x,y坐标
|
|
|
VecDouble vecX, vecY;
|
|
|
|
|
|
if(pGaugeP != nullptr) {
|
|
|
// 获取压力数据
|
|
|
if(pGaugeP->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsP.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(pGaugeF != nullptr) {
|
|
|
vecX.clear();
|
|
|
vecY.clear();
|
|
|
|
|
|
// 获取流量数据
|
|
|
if(pGaugeF->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsF.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) {
|
|
|
// 初始化直井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Well);
|
|
|
nmDataVerticalWell* pVerticalWell = dynamic_cast<nmDataVerticalWell*>(pWell);
|
|
|
if(pVerticalWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pVerticalWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pVerticalWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pVerticalWell->setX(tempAttr);
|
|
|
tempAttr = pVerticalWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pVerticalWell->setY(tempAttr);
|
|
|
tempAttr = pVerticalWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pVerticalWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pVerticalWell->setPressurePoints(vecPtsP);
|
|
|
pVerticalWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
QVector<QVector<double>> vvecHistoryPressureData; //压力历史数据
|
|
|
QVector<QVector<double>> vvecHistoryLogData; // 历史双对数曲线数据
|
|
|
QVector<QVector<double>> vvecHistorySemiLogData; // 历史半对数曲线数据
|
|
|
|
|
|
this->calculationLogData(pVerticalWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
|
|
|
|
|
|
// 使用setter方法存储历史数据到井对象中
|
|
|
pVerticalWell->setHistoryPressure(vvecHistoryPressureData);
|
|
|
pVerticalWell->setHistoryLogLog(vvecHistoryLogData);
|
|
|
pVerticalWell->setHistorySemiLog(vvecHistorySemiLogData);
|
|
|
|
|
|
// 设置为当前查看的井
|
|
|
this->setCurWellData(pVerticalWell);
|
|
|
} else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) {
|
|
|
|
|
|
// 初始化垂直裂缝井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Fractured_Well);
|
|
|
nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast<nmDataVerticalFracturedWell*>(pWell);
|
|
|
if(pVFracturedWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pVFracturedWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pVFracturedWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pVFracturedWell->setX(tempAttr);
|
|
|
tempAttr = pVFracturedWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pVFracturedWell->setY(tempAttr);
|
|
|
tempAttr = pVFracturedWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pVFracturedWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pVFracturedWell->setPressurePoints(vecPtsP);
|
|
|
pVFracturedWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
QVector<QVector<double>> vvecHistoryPressureData; //压力历史数据
|
|
|
QVector<QVector<double>> vvecHistoryLogData; // 历史双对数曲线数据
|
|
|
QVector<QVector<double>> vvecHistorySemiLogData; // 历史半对数曲线数据
|
|
|
|
|
|
this->calculationLogData(pVFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
|
|
|
|
|
|
// 使用setter方法存储历史数据到井对象中
|
|
|
pVFracturedWell->setHistoryPressure(vvecHistoryPressureData);
|
|
|
pVFracturedWell->setHistoryLogLog(vvecHistoryLogData);
|
|
|
pVFracturedWell->setHistorySemiLog(vvecHistorySemiLogData);
|
|
|
|
|
|
// 更新裂缝位置信息
|
|
|
pVFracturedWell->setFracs();
|
|
|
|
|
|
// 设置为当前查看的井
|
|
|
this->setCurWellData(pVFracturedWell);
|
|
|
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) {
|
|
|
|
|
|
// 初始化多段压裂水平井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well);
|
|
|
nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pWell);
|
|
|
if(pHFracturedWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pHFracturedWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pHFracturedWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pHFracturedWell->setX(tempAttr);
|
|
|
tempAttr = pHFracturedWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pHFracturedWell->setY(tempAttr);
|
|
|
tempAttr = pHFracturedWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pHFracturedWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pHFracturedWell->setPressurePoints(vecPtsP);
|
|
|
pHFracturedWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
QVector<QVector<double>> vvecHistoryPressureData; //压力历史数据
|
|
|
QVector<QVector<double>> vvecHistoryLogData; // 历史双对数曲线数据
|
|
|
QVector<QVector<double>> vvecHistorySemiLogData; // 历史半对数曲线数据
|
|
|
|
|
|
this->calculationLogData(pHFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
|
|
|
|
|
|
//使用setter方法存储历史数据到井对象中
|
|
|
pHFracturedWell->setHistoryPressure(vvecHistoryPressureData);
|
|
|
pHFracturedWell->setHistoryLogLog(vvecHistoryLogData);
|
|
|
pHFracturedWell->setHistorySemiLog(vvecHistorySemiLogData);
|
|
|
|
|
|
// 计算裂缝数据
|
|
|
pHFracturedWell->setFracs();
|
|
|
|
|
|
// 设置为当前查看的井
|
|
|
this->setCurWellData(pHFracturedWell);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::calculationLogData(
|
|
|
nmDataWellBase* pWellData,
|
|
|
QVector<QVector<double>>& vvecHistoryData,
|
|
|
QVector<QVector<double>>& vvecLogPreData,
|
|
|
QVector<QVector<double>>& vvecSemiLogPreData)
|
|
|
{
|
|
|
// 清空输出参数
|
|
|
vvecHistoryData.clear();
|
|
|
vvecLogPreData.clear();
|
|
|
vvecSemiLogPreData.clear();
|
|
|
|
|
|
if(pWellData == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 初始化二维数组结构
|
|
|
vvecHistoryData.resize(2); // [0]=x, [1]=y
|
|
|
vvecLogPreData.resize(3); // [0]=x, [1]=y, [2]=z
|
|
|
vvecSemiLogPreData.resize(2); // [0]=x, [1]=pointData[0]
|
|
|
|
|
|
// 准备压力数据
|
|
|
QVector<QPointF> vecPressure = pWellData->getPressurePoints();
|
|
|
std::vector<Point> wellPressureData;
|
|
|
|
|
|
// 填充 wellPressureData 和 vvecHistoryData
|
|
|
foreach(const QPointF& qpoint, vecPressure) {
|
|
|
// wellPressureData
|
|
|
Point pt;
|
|
|
pt.x = qpoint.x();
|
|
|
pt.y = qpoint.y();
|
|
|
pt.z = 0.0;
|
|
|
wellPressureData.push_back(pt);
|
|
|
|
|
|
// vvecHistoryData
|
|
|
vvecHistoryData[0].append(qpoint.x()); // x
|
|
|
vvecHistoryData[1].append(qpoint.y()); // y
|
|
|
}
|
|
|
|
|
|
// 准备流量段数据
|
|
|
QVector<QPointF> vecTimeQ = pWellData->getFlowPoints();
|
|
|
int nTimeNumQ = vecTimeQ.size() - 1;
|
|
|
std::vector<double> timeQ(nTimeNumQ);
|
|
|
std::vector<double> q(nTimeNumQ);
|
|
|
|
|
|
for(int i = 0; i < nTimeNumQ; ++i) {
|
|
|
timeQ[i] = vecTimeQ[i + 1].x();
|
|
|
q[i] = vecTimeQ[i + 1].y();
|
|
|
}
|
|
|
|
|
|
// 调用 DLL 计算双对数曲线
|
|
|
std::vector<Point> logPre;
|
|
|
int iSectionFlowIndex = pWellData->getIndexF();
|
|
|
|
|
|
HMODULE hMod_solver = LoadLibrary(L"singlePhaseSolverDll.dll");
|
|
|
|
|
|
if(hMod_solver) {
|
|
|
typedef bool (*PreLog)(const std::vector<Point>&, const int&, double*, double*, int, std::vector<Point>&);
|
|
|
PreLog preLogFun = (PreLog)GetProcAddress(hMod_solver, "logLogPre");
|
|
|
|
|
|
if(nullptr == preLogFun) {
|
|
|
FreeLibrary(hMod_solver);
|
|
|
std::cout << "preLogFun failed!\n";
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
preLogFun(wellPressureData, iSectionFlowIndex, timeQ.data(), q.data(), nTimeNumQ, logPre);
|
|
|
|
|
|
// 不添加最后一个元素
|
|
|
for(uint i = 0; i < logPre.size() - 1; i++) {
|
|
|
//logFile << logPre[i].x << "\t" << logPre[i].y << "\t" << logPre[i].z << "\t" << std::endl;
|
|
|
vvecLogPreData[0].append(logPre[i].x); // x
|
|
|
vvecLogPreData[1].append(logPre[i].y); // y
|
|
|
vvecLogPreData[2].append(logPre[i].z); // z
|
|
|
}
|
|
|
|
|
|
// 填充半对数曲线数据 (x, pointData[0])
|
|
|
foreach(const auto& point, logPre) {
|
|
|
vvecSemiLogPreData[0].append(point.x); // x
|
|
|
double y_value = point.pointData.empty() ? 0.0 : point.pointData[0];
|
|
|
vvecSemiLogPreData[1].append(y_value); // pointData[0] 或默认值
|
|
|
}
|
|
|
|
|
|
FreeLibrary(hMod_solver);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::appendWellData(ZxDataWell* pWellData)
|
|
|
{
|
|
|
if(pWellData == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 判断是哪一种井类型,初始化对应的参数
|
|
|
QString sWellClass = pWellData->getWellClassEn();
|
|
|
|
|
|
// 获取当前井的压力、流量数据
|
|
|
ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP);
|
|
|
ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF);
|
|
|
|
|
|
ZxDataGaugeP* pGaugeP = nullptr;
|
|
|
ZxDataGaugeF* pGaugeF = nullptr;
|
|
|
|
|
|
// 遍历压力数据列表
|
|
|
for(int i = 0; i < m_listGaugeP.size(); ++i) {
|
|
|
if(pGaugeP = dynamic_cast<ZxDataGaugeP * >(m_listGaugeP[i])) { // 拿到第一条压力数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 遍历流量数据列表
|
|
|
for(int i = 0; i < m_listGaugeF.size(); ++i) {
|
|
|
if(pGaugeF = dynamic_cast<ZxDataGaugeF * >(m_listGaugeF[i])) { // 拿到第一条流量数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取的压力、流量数据
|
|
|
QVector<QPointF> vecPtsP, vecPtsF;
|
|
|
// 临时存储x,y坐标
|
|
|
VecDouble vecX, vecY;
|
|
|
|
|
|
if(pGaugeP != nullptr) {
|
|
|
// 获取压力数据
|
|
|
if(pGaugeP->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsP.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(pGaugeF != nullptr) {
|
|
|
vecX.clear();
|
|
|
vecY.clear();
|
|
|
|
|
|
// 获取流量数据
|
|
|
if(pGaugeF->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsF.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int nIndexF; //当前井的流动段索引
|
|
|
|
|
|
// 更新当前井的流动段的索引,默认为最后一段
|
|
|
nIndexF = vecPtsF.count() - 1;
|
|
|
|
|
|
if(ZxBaseUtil::isSameStr(sWellClass, "VerticalWell")) {
|
|
|
// 初始化直井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Well);
|
|
|
nmDataVerticalWell* pVerticalWell = dynamic_cast<nmDataVerticalWell*>(pWell);
|
|
|
if(pVerticalWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pVerticalWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pVerticalWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pVerticalWell->setX(tempAttr);
|
|
|
tempAttr = pVerticalWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pVerticalWell->setY(tempAttr);
|
|
|
tempAttr = pVerticalWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pVerticalWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pVerticalWell->setPressurePoints(vecPtsP);
|
|
|
pVerticalWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
// 设置流量段索引
|
|
|
pVerticalWell->setIndexF(nIndexF);
|
|
|
} else if(ZxBaseUtil::isSameStr(sWellClass, "VerticalFracturedWell")) {
|
|
|
|
|
|
// 初始化垂直裂缝井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Vertical_Fractured_Well);
|
|
|
nmDataVerticalFracturedWell* pVFracturedWell = dynamic_cast<nmDataVerticalFracturedWell*>(pWell);
|
|
|
if(pVFracturedWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pVFracturedWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pVFracturedWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pVFracturedWell->setX(tempAttr);
|
|
|
tempAttr = pVFracturedWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pVFracturedWell->setY(tempAttr);
|
|
|
tempAttr = pVFracturedWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pVFracturedWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pVFracturedWell->setPressurePoints(vecPtsP);
|
|
|
pVFracturedWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
// 更新裂缝位置信息
|
|
|
pVFracturedWell->setFracs();
|
|
|
// 设置流量段索引
|
|
|
pVFracturedWell->setIndexF(nIndexF);
|
|
|
} else if(ZxBaseUtil::isSameStr(sWellClass, "HorizontalFracturedWell")) {
|
|
|
|
|
|
// 初始化多段压裂水平井默认参数
|
|
|
nmDataWellBase* pWell = this->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well);
|
|
|
nmDataHorizontalFracturedWell* pHFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pWell);
|
|
|
if(pHFracturedWell == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pHFracturedWell->setWellName(pWellData->getName());
|
|
|
nmDataAttribute tempAttr = pHFracturedWell->getX();
|
|
|
tempAttr.setValue(pWellData->getLocationX());
|
|
|
pHFracturedWell->setX(tempAttr);
|
|
|
tempAttr = pHFracturedWell->getY();
|
|
|
tempAttr.setValue(pWellData->getLocationY());
|
|
|
pHFracturedWell->setY(tempAttr);
|
|
|
tempAttr = pHFracturedWell->getRadius();
|
|
|
tempAttr.setValue(pWellData->getWellRadius());
|
|
|
pHFracturedWell->setRadius(tempAttr);
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pHFracturedWell->setPressurePoints(vecPtsP);
|
|
|
pHFracturedWell->setFlowPoints(vecPtsF);
|
|
|
|
|
|
// 计算裂缝数据
|
|
|
pHFracturedWell->setFracs();
|
|
|
|
|
|
// 设置流量段索引
|
|
|
pHFracturedWell->setIndexF(nIndexF);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::appendNmWellData(nmDataWellBase* pWellData)
|
|
|
{
|
|
|
if (pWellData == nullptr)
|
|
|
return;
|
|
|
m_vWellData.append(pWellData);
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::createReservoir()
|
|
|
{
|
|
|
// 根据当前Fitting窗口来获取对应的井相关数据
|
|
|
iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider();
|
|
|
Q_ASSERT(nullptr != pSubWndFitting);
|
|
|
Q_ASSERT(nullptr != pContextProvider);
|
|
|
|
|
|
// 定义获取的分层数据
|
|
|
VVecVariant vvecLayerData;
|
|
|
// 定义返回结果的 QMap
|
|
|
QMap<QString, double> mapParaValues;
|
|
|
// 相态类型
|
|
|
PvtFluidType eType = WFT_Null;
|
|
|
|
|
|
if(nullptr != pSubWndFitting && nullptr != pContextProvider) {
|
|
|
|
|
|
// 读取界面选择的PVT相态类型
|
|
|
pContextProvider->getBasicPft(pSubWndFitting, eType);
|
|
|
|
|
|
//QString sMainPft =pSubWndFitting->getBasicMainPft();
|
|
|
//QString sPftDesc = pSubWndFitting->getBasicPftDesc();
|
|
|
// 只读取当前相态存在的PVT页,避免PVT工具输出PhaseGas/PhaseWater缺失日志
|
|
|
QStringList listParas;
|
|
|
bool bReadOilPvt = false;
|
|
|
bool bReadGasPvt = false;
|
|
|
bool bReadWaterPvt = false;
|
|
|
resolvePvtPhaseReadFlags(eType, bReadOilPvt, bReadGasPvt, bReadWaterPvt);
|
|
|
|
|
|
// 储层基础数据这里只需要体积系数和粘度;不属于当前相态的参数继续走默认值
|
|
|
if(bReadOilPvt) {
|
|
|
listParas << "Bo" << "Miuo";
|
|
|
}
|
|
|
if(bReadGasPvt) {
|
|
|
listParas << "Bg" << "Miug";
|
|
|
}
|
|
|
if(bReadWaterPvt) {
|
|
|
listParas << "Bw" << "Miuw";
|
|
|
}
|
|
|
listParas << "Ct";
|
|
|
pContextProvider->getPvtParaValues(pSubWndFitting, listParas, mapParaValues);
|
|
|
|
|
|
// 读取分层数据
|
|
|
pContextProvider->getBasicDataLayers(pSubWndFitting, vvecLayerData);
|
|
|
}
|
|
|
|
|
|
// 获取油体积系数和油相粘度
|
|
|
double dBo = mapParaValues.value("Bo", 1.5); // 如果键不存在,返回默认值 1.5
|
|
|
double dMiuo = mapParaValues.value("Miuo", 1); // 如果键不存在,返回默认值 1
|
|
|
|
|
|
// 获取气体积系数和气相粘度、参考温度
|
|
|
double dBg = mapParaValues.value("Bg", 1); // 如果键不存在,返回默认值 1.5
|
|
|
double dMiug = mapParaValues.value("Miug", 1); // 如果键不存在,返回默认值 1
|
|
|
double dTempGas = 100;// 气藏温度,TODO,应该从分析界面获取
|
|
|
|
|
|
// 获取水体积系数和水相粘度
|
|
|
double dBw = mapParaValues.value("Bw", 1);
|
|
|
double dMiuw = mapParaValues.value("Miuw", 1);
|
|
|
|
|
|
// 获取综合压缩系数
|
|
|
double dCt = mapParaValues.value("Ct", 0.1);
|
|
|
|
|
|
// 获取初始油、气、水饱和度---------王老师那的是临时数据,没法获取
|
|
|
//double dSo = mapParaValues.value("Ko", 1);
|
|
|
//double dSg = mapParaValues.value("Sg", 0);
|
|
|
//double dSw = mapParaValues.value("Sw", 0);
|
|
|
|
|
|
// 检查 vvecLayerData 是否有效,有效重新赋值,无效设置默认值
|
|
|
double dThickness = 10;
|
|
|
double dPorosity = 0.5;
|
|
|
double dCf = 1.00; // 岩石压缩系数
|
|
|
double dInitialPre = 30.0;
|
|
|
|
|
|
if(!vvecLayerData.isEmpty() && vvecLayerData[0].size() >= 5) {
|
|
|
dThickness = vvecLayerData[0][1].toDouble();
|
|
|
dPorosity = vvecLayerData[0][2].toDouble();
|
|
|
dCf = vvecLayerData[0][3].toDouble();
|
|
|
dInitialPre = vvecLayerData[0][4].toDouble();
|
|
|
}
|
|
|
|
|
|
// 判断是否已有油藏参数数据
|
|
|
if(m_reservoirData != nullptr) {
|
|
|
delete m_reservoirData;
|
|
|
m_reservoirData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_reservoirData = new nmDataReservoir;
|
|
|
nmDataAttribute tempAttr;
|
|
|
|
|
|
// 将界面相态转换为内部储层相态,后续再映射为求解器T
|
|
|
if(eType == WFT_Oil) {
|
|
|
m_reservoirData->setPhaseType(PHASE_Oil);
|
|
|
tempAttr = m_reservoirData->getBo();// 油体积系数
|
|
|
tempAttr.setValue(dBo);
|
|
|
m_reservoirData->setBo(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getMiuo();// 油相黏度
|
|
|
tempAttr.setValue(dMiuo);
|
|
|
m_reservoirData->setMiuo(tempAttr);
|
|
|
|
|
|
} else if(eType == WFT_Gas) {
|
|
|
m_reservoirData->setPhaseType(PHASE_Gas);
|
|
|
// TODO:这里先使用用一个变量,后续根据需求再进行分类
|
|
|
tempAttr = m_reservoirData->getBo();// 气体积系数
|
|
|
tempAttr.setValue(dBg);
|
|
|
m_reservoirData->setBo(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getMiuo();// 气相黏度
|
|
|
tempAttr.setValue(dMiug);
|
|
|
m_reservoirData->setMiuo(tempAttr);
|
|
|
|
|
|
m_reservoirData->setTempGasRe(dTempGas); // 气藏温度
|
|
|
} else if(eType == WFT_Water) {
|
|
|
m_reservoirData->setPhaseType(PHASE_Water);
|
|
|
tempAttr = m_reservoirData->getBo();// 水体积系数
|
|
|
tempAttr.setValue(dBw);
|
|
|
m_reservoirData->setBo(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getMiuo();// 水相黏度
|
|
|
tempAttr.setValue(dMiuw);
|
|
|
m_reservoirData->setMiuo(tempAttr);
|
|
|
} else if(eType == WFT_Oil_Water) {
|
|
|
m_reservoirData->setPhaseType(PHASE_Oil_Water);
|
|
|
tempAttr = m_reservoirData->getBo();// 油体积系数
|
|
|
tempAttr.setValue(dBo);
|
|
|
m_reservoirData->setBo(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getMiuo();// 油相黏度
|
|
|
tempAttr.setValue(dMiuo);
|
|
|
m_reservoirData->setMiuo(tempAttr);
|
|
|
} else {
|
|
|
m_reservoirData->setPhaseType(PHASE_UNKNOWN);
|
|
|
}
|
|
|
|
|
|
tempAttr = m_reservoirData->getInitialPressure();//初始压力
|
|
|
tempAttr.setValue(dInitialPre);
|
|
|
m_reservoirData->setInitialPressure(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getReservoirType();
|
|
|
tempAttr.setValue("Homogeneous");
|
|
|
m_reservoirData->setReservoirType(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getThickness();// 储层厚度
|
|
|
tempAttr.setValue(dThickness);
|
|
|
m_reservoirData->setThickness(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getCt(); // 综合压缩系数
|
|
|
tempAttr.setValue(dCt);
|
|
|
m_reservoirData->setCt(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getPorosity();// 孔隙度
|
|
|
tempAttr.setValue(dPorosity);
|
|
|
m_reservoirData->setPorosity(tempAttr);
|
|
|
|
|
|
tempAttr = m_reservoirData->getCf();// 岩石压缩系数
|
|
|
tempAttr.setValue(dCf);
|
|
|
m_reservoirData->setCf(tempAttr);
|
|
|
|
|
|
// 清空现有分层数据
|
|
|
qDeleteAll(m_vecLayers);
|
|
|
m_vecLayers.clear();
|
|
|
|
|
|
// 创建一个默认分层
|
|
|
nmDataLayer* defaultLayer = new nmDataLayer();
|
|
|
|
|
|
// 设置默认分层参数
|
|
|
defaultLayer->setTop(6000.0); // 默认顶深
|
|
|
defaultLayer->setThickness(dThickness); // 使用从框架获取的厚度值
|
|
|
defaultLayer->setBottom(6000.0 + dThickness); // 计算底深
|
|
|
defaultLayer->setIsChecked(false); // 默认未选中
|
|
|
defaultLayer->setColor(QColor(0, 255, 0)); // 设置默认颜色(绿色)
|
|
|
|
|
|
// 将默认分层添加到分层列表
|
|
|
m_vecLayers.append(defaultLayer);
|
|
|
}
|
|
|
|
|
|
nmDataAxis* nmDataAnalyzeManager::getAxisData() const
|
|
|
{
|
|
|
return m_axisData;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setAxisData(nmDataAxis* pAxisData)
|
|
|
{
|
|
|
if(pAxisData != nullptr) {
|
|
|
m_axisData = pAxisData;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataReservoir* nmDataAnalyzeManager::getReservoirData() const
|
|
|
{
|
|
|
return m_reservoirData;
|
|
|
}
|
|
|
|
|
|
nmDataReservoir nmDataAnalyzeManager::getReservoirDataCopy() const
|
|
|
{
|
|
|
if(m_reservoirData) {
|
|
|
return *m_reservoirData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
return nmDataReservoir(); // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateReservoirData(const nmDataReservoir& newData)
|
|
|
{
|
|
|
if(m_reservoirData) {
|
|
|
*m_reservoirData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataGeoRef* nmDataAnalyzeManager::createGeoRefData()
|
|
|
{
|
|
|
if(m_pGeoRefData != nullptr) {
|
|
|
delete m_pGeoRefData;
|
|
|
m_pGeoRefData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pGeoRefData = new nmDataGeoRef;
|
|
|
return m_pGeoRefData;
|
|
|
}
|
|
|
|
|
|
nmDataGeoRef* nmDataAnalyzeManager::getGeoRefData() const
|
|
|
{
|
|
|
return m_pGeoRefData;
|
|
|
}
|
|
|
|
|
|
nmDataGeoRef nmDataAnalyzeManager::getGeoRefDataCopy() const
|
|
|
{
|
|
|
if(m_pGeoRefData) {
|
|
|
return *m_pGeoRefData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
return nmDataGeoRef(); // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateGeoRefData(const nmDataGeoRef& newData)
|
|
|
{
|
|
|
if(m_pGeoRefData == nullptr) {
|
|
|
m_pGeoRefData = new nmDataGeoRef;
|
|
|
}
|
|
|
|
|
|
*m_pGeoRefData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
|
|
|
nmDataForecast* nmDataAnalyzeManager::createForecastData()
|
|
|
{
|
|
|
if(m_pForecastData != nullptr) {
|
|
|
delete m_pForecastData;
|
|
|
m_pForecastData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pForecastData = new nmDataForecast;
|
|
|
return m_pForecastData;
|
|
|
}
|
|
|
|
|
|
nmDataForecast* nmDataAnalyzeManager::getForecastData() const
|
|
|
{
|
|
|
return m_pForecastData;
|
|
|
}
|
|
|
|
|
|
nmDataForecast nmDataAnalyzeManager::getForecastDataCopy() const
|
|
|
{
|
|
|
if(m_pForecastData) {
|
|
|
return *m_pForecastData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
return nmDataForecast(); // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateForecastData(const nmDataForecast& newData)
|
|
|
{
|
|
|
if(m_pForecastData == nullptr) {
|
|
|
m_pForecastData = new nmDataForecast;
|
|
|
}
|
|
|
|
|
|
*m_pForecastData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
|
|
|
nmDataSensitive* nmDataAnalyzeManager::createSensitiveData()
|
|
|
{
|
|
|
// 如果已有数据,先删除再创建
|
|
|
if (m_pSensitiveData != nullptr) {
|
|
|
delete m_pSensitiveData;
|
|
|
m_pSensitiveData = nullptr;
|
|
|
}
|
|
|
|
|
|
// 创建一个新的 nmDataSensitive 对象
|
|
|
m_pSensitiveData = new nmDataSensitive();
|
|
|
|
|
|
// 初始化 Calculation Type
|
|
|
m_pSensitiveData->setCalculationType(nmDataSensitive::CALC_DETERMINISTIC);
|
|
|
|
|
|
// 设置总模型数为 0,后面可以通过 setTotalModelCount 修改
|
|
|
m_pSensitiveData->setTotalModelCount(0);
|
|
|
|
|
|
// 创建变量列表
|
|
|
QList<nmDataSensitive::VariableSampling> vars;
|
|
|
|
|
|
// 定义一个通用的添加变量的辅助函数
|
|
|
auto addVar = [&](const QString& group,
|
|
|
const QString& name,
|
|
|
double model, double min, double max,
|
|
|
const QString& unit)
|
|
|
{
|
|
|
nmDataSensitive::VariableSampling vs;
|
|
|
vs.setVarGroup(group); // 设置变量组
|
|
|
vs.setVarName(name); // 设置变量名
|
|
|
vs.setEnabled(false); // 默认不勾选
|
|
|
vs.setMode(nmDataSensitive::VariableSampling::MODE_AUTOMATIC); // 自动模式
|
|
|
vs.setLog(false); // 默认不选 Log
|
|
|
vs.setNumber(5); // 默认 Number 为 5
|
|
|
|
|
|
// 设置 modelValue、minValue、maxValue 和单位
|
|
|
nmDataAttribute& modelValue = vs.getModelValue();
|
|
|
modelValue.setName(name + " Model");
|
|
|
modelValue.setUnit(unit);
|
|
|
modelValue.setValue(model);
|
|
|
|
|
|
nmDataAttribute& minValue = vs.getMinValue();
|
|
|
minValue.setName(name + " Min");
|
|
|
minValue.setUnit(unit);
|
|
|
minValue.setValue(min);
|
|
|
|
|
|
nmDataAttribute& maxValue = vs.getMaxValue();
|
|
|
maxValue.setName(name + " Max");
|
|
|
maxValue.setUnit(unit);
|
|
|
maxValue.setValue(max);
|
|
|
|
|
|
vars.append(vs); // 将变量添加到变量列表中
|
|
|
};
|
|
|
|
|
|
// 初始化变量组和每个变量
|
|
|
// === Tested Well ===
|
|
|
addVar("Tested Well", "Zw", 15.0, 7.5, 30.0, "ft");
|
|
|
addVar("Tested Well", "Hw", 10.0, 5.0, 20.0, "ft");
|
|
|
addVar("Tested Well", "Lw", 12.0, 6.0, 18.0, "ft");
|
|
|
addVar("Tested Well", "Skin", 1.0, 0.5, 1.5, "dimensionless");
|
|
|
addVar("Tested Well", "C", 0.3, 0.1, 1.0, "dimensionless");
|
|
|
|
|
|
// === Reservoir ===
|
|
|
addVar("Reservoir", "Pi", 1000.0, 800.0, 1200.0, "psi");
|
|
|
addVar("Reservoir", "k", 150.0, 100.0, 200.0, "mD");
|
|
|
addVar("Reservoir", "h", 50.0, 30.0, 70.0, "ft");
|
|
|
addVar("Reservoir", "φ", 0.2, 0.1, 0.4, "dimensionless");
|
|
|
addVar("Reservoir", "ntg", 0.9, 0.7, 1.0, "dimensionless");
|
|
|
addVar("Reservoir", "kz/kr", 1.0, 0.5, 1.5, "dimensionless");
|
|
|
|
|
|
// === Pvt ===
|
|
|
addVar("Pvt", "Total compressibility", 5e-6, 2e-6, 8e-6, "1/psi");
|
|
|
|
|
|
// 将变量列表设置到敏感性数据对象中
|
|
|
m_pSensitiveData->setVariables(vars);
|
|
|
|
|
|
// 返回已初始化的敏感性数据对象
|
|
|
return m_pSensitiveData;
|
|
|
}
|
|
|
|
|
|
nmDataSensitive* nmDataAnalyzeManager::getSensitiveData() const
|
|
|
{
|
|
|
return m_pSensitiveData;
|
|
|
}
|
|
|
|
|
|
nmDataSensitive nmDataAnalyzeManager::getSensitiveDataCopy() const
|
|
|
{
|
|
|
if(m_pSensitiveData) {
|
|
|
return *m_pSensitiveData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
return nmDataSensitive(); // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateSensitiveData(const nmDataSensitive& newData)
|
|
|
{
|
|
|
if(m_pSensitiveData == nullptr) {
|
|
|
m_pSensitiveData = new nmDataSensitive();
|
|
|
}
|
|
|
|
|
|
*m_pSensitiveData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
|
|
|
nmDataDiagnostic* nmDataAnalyzeManager::getDiagnosticData() const {
|
|
|
return m_pDiagnosticData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::resetFromDiagnostic()
|
|
|
{
|
|
|
// 获取当前井和储层数据
|
|
|
nmDataWellBase* pCurrentWell = getCurWellData();
|
|
|
nmDataReservoir* pReservoirData = getReservoirData();
|
|
|
|
|
|
if(!pCurrentWell || !pReservoirData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 获取"双对数"线性数据
|
|
|
QVector<QVector<double>> rawData = pCurrentWell->getHistoryLogLog();
|
|
|
if(rawData.isEmpty() || rawData.size() != 3) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
// 创建诊断对象并使用修正后的数据
|
|
|
if(!m_pDiagnosticData) {
|
|
|
m_pDiagnosticData = new nmDataDiagnostic();
|
|
|
}
|
|
|
|
|
|
m_pDiagnosticData->resetFromDiagnostic(rawData, pCurrentWell, pReservoirData);
|
|
|
|
|
|
// 应用诊断结果到相应参数
|
|
|
applyDiagnosticResults(m_pDiagnosticData, pCurrentWell, pReservoirData);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
catch(...) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::resetFromAnalytical()
|
|
|
{
|
|
|
// 获取当前井和储层数据
|
|
|
nmDataWellBase* pCurrentWell = getCurWellData();
|
|
|
nmDataReservoir* pReservoirData = getReservoirData();
|
|
|
|
|
|
if(!pCurrentWell || !pReservoirData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
// 重置储层参数为默认值
|
|
|
pReservoirData->resetToDefaults();
|
|
|
|
|
|
// 重置井参数为默认值
|
|
|
pCurrentWell->resetToDefaults();
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
catch(...) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 应用诊断结果
|
|
|
void nmDataAnalyzeManager::applyDiagnosticResults(nmDataDiagnostic* diagnostic, nmDataWellBase* wellData, nmDataReservoir* reservoirData)
|
|
|
{
|
|
|
if(!diagnostic || !wellData || !reservoirData) return;
|
|
|
|
|
|
// 获取诊断结果
|
|
|
double diagnosticPerm = diagnostic->getDiagnosticPermeability().getValue().toDouble();
|
|
|
double diagnosticStorage = diagnostic->getDiagnosticWellboreStorage().getValue().toDouble();
|
|
|
double diagnosticTrans = diagnostic->getDiagnosticTransmissibility().getValue().toDouble();
|
|
|
double diagnosticSkin = diagnostic->getDiagnosticSkin().getValue().toDouble();
|
|
|
|
|
|
// 应用渗透率到储层数据
|
|
|
nmDataAttribute& reservoirPerm = reservoirData->getPermeability();
|
|
|
reservoirPerm.setValue(diagnosticPerm);
|
|
|
|
|
|
// 应用井筒储存到井数据
|
|
|
nmDataAttribute& wellStorage = wellData->getWellboreStorage();
|
|
|
wellStorage.setValue(diagnosticStorage);
|
|
|
|
|
|
// 应用导流能力到储层数据
|
|
|
nmDataAttribute& reservoirTrans = reservoirData->getTransmissibility();
|
|
|
reservoirTrans.setValue(diagnosticTrans);
|
|
|
|
|
|
// 应用皮损系数到井的第一段射孔
|
|
|
if(wellData->getPerforationCount() > 0) {
|
|
|
nmDataPerforation* firstPerforation = wellData->getPerforation(0);
|
|
|
if(firstPerforation) {
|
|
|
firstPerforation->getSkin().setValue(diagnosticSkin);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataAutomaticFitting* nmDataAnalyzeManager::createAutomaticFittingData()
|
|
|
{
|
|
|
if(m_pAutomaticFittingData != nullptr) {
|
|
|
delete m_pAutomaticFittingData;
|
|
|
m_pAutomaticFittingData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pAutomaticFittingData = new nmDataAutomaticFitting;
|
|
|
return m_pAutomaticFittingData;
|
|
|
}
|
|
|
|
|
|
nmDataAutomaticFitting* nmDataAnalyzeManager::getAutomaticFittingData() const
|
|
|
{
|
|
|
return m_pAutomaticFittingData;
|
|
|
}
|
|
|
|
|
|
nmDataAutomaticFitting nmDataAnalyzeManager::getAutomaticFittingDataCopy() const
|
|
|
{
|
|
|
if(m_pAutomaticFittingData) {
|
|
|
return *m_pAutomaticFittingData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
return nmDataAutomaticFitting(); // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateAutomaticFittingData(const nmDataAutomaticFitting& newData)
|
|
|
{
|
|
|
if(m_pAutomaticFittingData == nullptr) {
|
|
|
m_pAutomaticFittingData = new nmDataAutomaticFitting;
|
|
|
}
|
|
|
|
|
|
*m_pAutomaticFittingData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::initPvtParaFromSubFit()
|
|
|
{
|
|
|
// 根据当前Fitting窗口来获取对应的井相关数据
|
|
|
iSubWndFitting* pSubWndFitting = nmDataAnalyzeManager::getCurrentFitting();
|
|
|
nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider();
|
|
|
Q_ASSERT(nullptr != pSubWndFitting);
|
|
|
Q_ASSERT(nullptr != pContextProvider);
|
|
|
|
|
|
if(nullptr != pSubWndFitting && nullptr != pContextProvider) {
|
|
|
PvtFluidType eType = WFT_Null;
|
|
|
pContextProvider->getBasicPft(pSubWndFitting, eType);
|
|
|
|
|
|
bool bReadOilPvt = false;
|
|
|
bool bReadGasPvt = false;
|
|
|
bool bReadWaterPvt = false;
|
|
|
resolvePvtPhaseReadFlags(eType, bReadOilPvt, bReadGasPvt, bReadWaterPvt);
|
|
|
|
|
|
|
|
|
//QVector<double> vecPressure; // 压力, MPa
|
|
|
QVector<double> vecRso; // 溶解气油比, m^3/m^3
|
|
|
QVector<double> vecBo; // 油体积系数, m^3/m^3
|
|
|
QVector<double> vecCo; // 油压缩系数, 1/MPa
|
|
|
QVector<double> vecMiuo; // 油粘度, mPa·s
|
|
|
QVector<double> vecRouo; // 油密度, kg/m^3
|
|
|
QVector<double> vecRv; // 凝析油气比, m^3/m^3
|
|
|
QVector<double> vecBg; // 气体积系数, m^3/m^3
|
|
|
QVector<double> vecCg; // 气压缩系数, 1/MPa
|
|
|
QVector<double> vecMiug; // 气粘度, mPa·s
|
|
|
QVector<double> vecRoug; // 气密度, kg/m^3
|
|
|
QVector<double> vecZ; // 气偏差因子, 1
|
|
|
QVector<double> vecRsw; // 溶解气水比, m^3/m^3
|
|
|
QVector<double> vecBw; // 水体积系数, m^3/m^3
|
|
|
QVector<double> vecCw; // 水压缩系数, 1/MPa
|
|
|
QVector<double> vecMiuw; // 水粘度, mPa·s
|
|
|
QVector<double> vecRouw; // 水密度, kg/m^3
|
|
|
|
|
|
VecDouble vecX;
|
|
|
|
|
|
// 判断是否已有PebiPvt参数数据
|
|
|
if(m_pebiPvtPara != nullptr) {
|
|
|
delete m_pebiPvtPara;
|
|
|
m_pebiPvtPara = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pebiPvtPara = new nmDataPvtParaForPebi;
|
|
|
|
|
|
// 气油比不按相态区分,所有情况都尝试读取
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Rs", vecX, vecRso);
|
|
|
m_pebiPvtPara->setRso(vecRso);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 其他PVT结果曲线只读取当前相态已有的页,缺失相态保留PEBI默认数据
|
|
|
if(bReadOilPvt) {
|
|
|
// 油体积系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Bo", vecX, vecBo);
|
|
|
m_pebiPvtPara->setBo(vecBo);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 油压缩系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Co", vecX, vecCo);
|
|
|
m_pebiPvtPara->setCo(vecCo);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 油密度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Rhoo", vecX, vecRouo);
|
|
|
m_pebiPvtPara->setRouo(vecRouo);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 油粘度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Oil, "Miuo", vecX, vecMiuo);
|
|
|
m_pebiPvtPara->setMiuo(vecMiuo);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
}
|
|
|
|
|
|
if(bReadGasPvt) {
|
|
|
|
|
|
// 气体积系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Bg", vecX, vecBg);
|
|
|
m_pebiPvtPara->setBg(vecBg);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 气压缩系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Cg", vecX, vecCg);
|
|
|
m_pebiPvtPara->setCg(vecCg);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 气粘度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Miug", vecX, vecMiug);
|
|
|
m_pebiPvtPara->setMiug(vecMiug);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 气密度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Rhog", vecX, vecRoug);
|
|
|
m_pebiPvtPara->setRoug(vecRoug);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 气偏差因子
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Gas, "Zg", vecX, vecZ);
|
|
|
m_pebiPvtPara->setZ(vecZ);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
}
|
|
|
|
|
|
if(bReadWaterPvt) {
|
|
|
// 溶解气水比
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Rsw", vecX, vecRsw);
|
|
|
m_pebiPvtPara->setRsw(vecRsw);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 水体积系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Bw", vecX, vecBw);
|
|
|
m_pebiPvtPara->setBw(vecBw);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 水压缩系数
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Cw", vecX, vecCw);
|
|
|
m_pebiPvtPara->setCw(vecCw);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 水粘度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Miuw", vecX, vecMiuw);
|
|
|
m_pebiPvtPara->setMiuw(vecMiuw);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
|
|
|
// 水密度
|
|
|
pContextProvider->getPvtRstOf(pSubWndFitting, WellFluidType::WFT_Water, "Rhow", vecX, vecRouw);
|
|
|
m_pebiPvtPara->setRouw(vecRouw);
|
|
|
setPebiPressureIfEmpty(m_pebiPvtPara, vecX);
|
|
|
}
|
|
|
|
|
|
if(eType == WFT_Oil_Water) {
|
|
|
// Diffusion相关数据来自Diffusion页面,只在油水两相时读取
|
|
|
// DSO_KK:相渗结果,主要用于So/Kro/Sw/Krw
|
|
|
VVecDouble vvecDiffusionKK;
|
|
|
if(pContextProvider->getDiffusionRstOf(pSubWndFitting, DSO_KK, vvecDiffusionKK)) {
|
|
|
applyDiffusionKkToPebiPvt(m_pebiPvtPara, vvecDiffusionKK);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
//// 吸附气量,王老师界面没有,油相暂时不需要
|
|
|
//m_pebiPvtPara->setV(vecV);
|
|
|
//
|
|
|
//// 渗透率比,王老师界面没有,油相暂时不需要
|
|
|
//m_pebiPvtPara->setKKinitial(vecKKinitial);
|
|
|
|
|
|
//// 岩石压缩系数比,王老师界面没有,油相暂时不需要
|
|
|
//m_pebiPvtPara->setCfCfinitial(vecCfCfinitial);
|
|
|
|
|
|
//// 相渗,单相暂时用不到
|
|
|
////QVector< QVector<double> > vvec;
|
|
|
////pSubWndFitting->getDiffusionRstOf(DiffusionSubOption::DSO_KK, vvec);
|
|
|
|
|
|
////QVector<double> vecSw;
|
|
|
////QVector<double> vecKro;
|
|
|
////QVector<double> vecKrw;
|
|
|
|
|
|
//// 遍历 vvec 中的每个子向量
|
|
|
////foreach (const QVector<double>& innerVec , vvec) {
|
|
|
//// // 确保每个子向量确实有3个元素
|
|
|
//// if (innerVec.size() >= 3) {
|
|
|
//// vecSw.append(innerVec[0]); // 第一个元素是 Sw
|
|
|
//// vecKro.append(innerVec[1]); // 第二个元素是 Kro
|
|
|
//// vecKrw.append(innerVec[2]); // 第三个元素是 Krw
|
|
|
//// }
|
|
|
////}
|
|
|
|
|
|
//// 油饱和度
|
|
|
//m_pebiPvtPara->setSo(vecSo);
|
|
|
|
|
|
//// 油相对渗透率
|
|
|
//m_pebiPvtPara->setKro(vecKro);
|
|
|
|
|
|
//// 气饱和度
|
|
|
//m_pebiPvtPara->setSg(vecSg);
|
|
|
|
|
|
//// 气相对渗透率
|
|
|
//m_pebiPvtPara->setKrg(vecKrg);
|
|
|
|
|
|
//// 水饱和度
|
|
|
//m_pebiPvtPara->setSw(vecSw);
|
|
|
|
|
|
//// 水相对渗透率
|
|
|
//m_pebiPvtPara->setKrw(vecKrw);
|
|
|
|
|
|
// 调用 getPvtParaValues 函数获取参数值
|
|
|
//pSubWndFitting->getPvtParaValues(listPvtParas, mapPebiPvtPara);
|
|
|
|
|
|
//m_pebiPvtPara->setZ(mapPebiPvtPara.contains("Zg") ?
|
|
|
// QVector<double>(200, mapPebiPvtPara["Zg"]) :
|
|
|
//QVector<double>(200, 1));
|
|
|
|
|
|
// 下面参数单项流不需要
|
|
|
|
|
|
//m_pebiPvtPara->setRv(mapPebiPvtPara.contains("Rv") ?
|
|
|
// QVector<double>(200, mapPebiPvtPara["Rv"]) :
|
|
|
//QVector<double>(200, 0));
|
|
|
|
|
|
//m_pebiPvtPara->setV(mapPebiPvtPara.contains("V") ?
|
|
|
// QVector<double>(200, mapPebiPvtPara["V"]) :
|
|
|
//QVector<double>(200, 0));
|
|
|
//m_pebiPvtPara->setKKinitial(mapPebiPvtPara.contains("k_kinitial") ?
|
|
|
// QVector<double>(200, mapPebiPvtPara["k_kinitial"]) :
|
|
|
//QVector<double>(200, 1));
|
|
|
//m_pebiPvtPara->setCfCfinitial(mapPebiPvtPara.contains("Cf_Cfinitial") ?
|
|
|
// QVector<double>(200, mapPebiPvtPara["Cf_Cfinitial"]) :
|
|
|
//QVector<double>(200, 1));
|
|
|
|
|
|
//// 饱和度与相对渗透率(大小为100)
|
|
|
//m_pebiPvtPara->setSo(mapPebiPvtPara.contains("So") ?
|
|
|
//QVector<double>(100, mapPebiPvtPara["So"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
//m_pebiPvtPara->setKro(mapPebiPvtPara.contains("Kro") ?
|
|
|
// QVector<double>(100, mapPebiPvtPara["Kro"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
//m_pebiPvtPara->setSg(mapPebiPvtPara.contains("Sg") ?
|
|
|
// QVector<double>(100, mapPebiPvtPara["Sg"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
//m_pebiPvtPara->setKrg(mapPebiPvtPara.contains("Krg") ?
|
|
|
// QVector<double>(100, mapPebiPvtPara["Krg"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
//m_pebiPvtPara->setSw(mapPebiPvtPara.contains("Sw") ?
|
|
|
// QVector<double>(100, mapPebiPvtPara["Sw"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
//m_pebiPvtPara->setKrw(mapPebiPvtPara.contains("Krw") ?
|
|
|
// QVector<double>(100, mapPebiPvtPara["Krw"]) :
|
|
|
//QVector<double>(100, 0));
|
|
|
}
|
|
|
|
|
|
nmDataRegionMark *nmDataAnalyzeManager::createRegionMark()
|
|
|
{
|
|
|
nmDataRegionMark* regionMarkData = new nmDataRegionMark;
|
|
|
m_vRegionMarkData.append(regionMarkData);
|
|
|
return regionMarkData;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataRegionMark*> nmDataAnalyzeManager::getRegionMarkDataList() const
|
|
|
{
|
|
|
return m_vRegionMarkData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeRegionMarkData(nmDataRegionMark * pData)
|
|
|
{
|
|
|
if(pData) {
|
|
|
// 遍历 m_vRegionMarkData 数组,找到并移除对应的对象
|
|
|
for(int i = 0; i < m_vRegionMarkData.size(); ++i) {
|
|
|
if(m_vRegionMarkData[i] == pData) {
|
|
|
delete m_vRegionMarkData[i]; // 释放内存
|
|
|
m_vRegionMarkData.remove(i);
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
QVector<nmDataRegionMark> nmDataAnalyzeManager::getRegionMarkDataListCopy() const
|
|
|
{
|
|
|
QVector<nmDataRegionMark> result;
|
|
|
result.reserve(m_vRegionMarkData.size());
|
|
|
|
|
|
foreach(const nmDataRegionMark* regionMark, m_vRegionMarkData) {
|
|
|
if(regionMark) {
|
|
|
result.append(*regionMark); // 调用拷贝构造函数
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateRegionMarkData(const QVector<nmDataRegionMark>& newData)
|
|
|
{
|
|
|
// 确保数量一致
|
|
|
if(newData.size() != m_vRegionMarkData.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < newData.size(); ++i) {
|
|
|
if(m_vRegionMarkData[i]) {
|
|
|
// 只更新内容,不改变指针
|
|
|
*m_vRegionMarkData[i] = newData[i]; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataOutline *nmDataAnalyzeManager::createOutline()
|
|
|
{
|
|
|
if(m_outlineData != nullptr) {
|
|
|
delete m_outlineData;
|
|
|
m_outlineData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_outlineData = new nmDataOutline;
|
|
|
return m_outlineData;
|
|
|
}
|
|
|
|
|
|
nmDataOutline* nmDataAnalyzeManager::getOutlineData()
|
|
|
{
|
|
|
return m_outlineData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeOutlineData()
|
|
|
{
|
|
|
if(m_outlineData) {
|
|
|
delete m_outlineData; // 删除边界数据对象
|
|
|
m_outlineData = nullptr;
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
nmDataOutline nmDataAnalyzeManager::getOutlineDataCopy() const
|
|
|
{
|
|
|
if(m_outlineData) {
|
|
|
return *m_outlineData; // 调用拷贝构造函数
|
|
|
}
|
|
|
|
|
|
nmDataOutline obj;
|
|
|
return obj; // 返回默认构造对象
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateOutlineData(const nmDataOutline & newData)
|
|
|
{
|
|
|
if(m_outlineData) {
|
|
|
*m_outlineData = newData; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataRegion *nmDataAnalyzeManager::createRegion()
|
|
|
{
|
|
|
nmDataRegion* regionData = new nmDataRegion;
|
|
|
m_vRegionData.append(regionData);
|
|
|
return regionData;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataRegion*> nmDataAnalyzeManager::getRegionDataList() const
|
|
|
{
|
|
|
return m_vRegionData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeRegionData(nmDataRegion * pData)
|
|
|
{
|
|
|
if(pData) {
|
|
|
// 遍历 m_vRegionData 数组,找到并移除对应的对象
|
|
|
for(int i = 0; i < m_vRegionData.size(); ++i) {
|
|
|
if(m_vRegionData[i] == pData) {
|
|
|
delete m_vRegionData[i]; // 释放内存
|
|
|
m_vRegionData.remove(i);
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
QVector<nmDataRegion> nmDataAnalyzeManager::getRegionDataListCopy() const
|
|
|
{
|
|
|
QVector<nmDataRegion> result;
|
|
|
result.reserve(m_vRegionData.size());
|
|
|
|
|
|
foreach(const nmDataRegion* region, m_vRegionData) {
|
|
|
if(region) {
|
|
|
result.append(*region); // 调用拷贝构造函数
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateRegionData(const QVector<nmDataRegion>& newData)
|
|
|
{
|
|
|
// 确保数量一致
|
|
|
if(newData.size() != m_vRegionData.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < newData.size(); ++i) {
|
|
|
if(m_vRegionData[i]) {
|
|
|
// 只更新内容,不改变指针
|
|
|
*m_vRegionData[i] = newData[i]; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmDataFracture *nmDataAnalyzeManager::createFracture()
|
|
|
{
|
|
|
nmDataFracture* fractureData = new nmDataFracture;
|
|
|
m_vFractureData.append(fractureData);
|
|
|
return fractureData;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataFracture*> nmDataAnalyzeManager::getFractureDataList() const
|
|
|
{
|
|
|
return m_vFractureData;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataFracture*> nmDataAnalyzeManager::getDFNFractureDataList() const
|
|
|
{
|
|
|
QVector<nmDataFracture*> vecDFNs;
|
|
|
|
|
|
// 遍历 m_vFractureData 数组,找到并移除对应的对象
|
|
|
for(int i = 0; i < m_vFractureData.size(); ++i) {
|
|
|
if(m_vFractureData[i]->getFractureType().getValue() == tr("DFN")) {
|
|
|
vecDFNs.append(m_vFractureData[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return vecDFNs;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeFractureData(nmDataFracture * pData)
|
|
|
{
|
|
|
if(pData) {
|
|
|
// 遍历 m_vFractureData 数组,找到并移除对应的对象
|
|
|
for(int i = 0; i < m_vFractureData.size(); ++i) {
|
|
|
if(m_vFractureData[i] == pData) {
|
|
|
delete m_vFractureData[i]; // 释放内存
|
|
|
m_vFractureData.remove(i);
|
|
|
emit dataChanged();
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
QVector<nmDataFracture> nmDataAnalyzeManager::getFractureDataListCopy() const
|
|
|
{
|
|
|
QVector<nmDataFracture> result;
|
|
|
result.reserve(m_vFractureData.size());
|
|
|
|
|
|
foreach(const nmDataFracture* fracture, m_vFractureData) {
|
|
|
if(fracture) {
|
|
|
result.append(*fracture); // 调用拷贝构造函数
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateFractureData(const QVector<nmDataFracture>& newData)
|
|
|
{
|
|
|
// 确保数量一致
|
|
|
if(newData.size() != m_vFractureData.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < newData.size(); ++i) {
|
|
|
if(m_vFractureData[i]) {
|
|
|
// 只更新内容,不改变指针
|
|
|
*m_vFractureData[i] = newData[i]; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
nmDataFault *nmDataAnalyzeManager::createFault()
|
|
|
{
|
|
|
nmDataFault* faultData = new nmDataFault;
|
|
|
m_vFaultData.append(faultData);
|
|
|
return faultData;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataFault*> nmDataAnalyzeManager::getFaultDataList() const
|
|
|
{
|
|
|
return m_vFaultData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeFaultData(nmDataFault * pData)
|
|
|
{
|
|
|
if(pData) {
|
|
|
// 遍历 m_vFaultData 数组,找到并移除对应的对象
|
|
|
for(int i = 0; i < m_vFaultData.size(); ++i) {
|
|
|
if(m_vFaultData[i] == pData) {
|
|
|
delete m_vFaultData[i]; // 释放内存
|
|
|
m_vFaultData.remove(i);
|
|
|
emit dataChanged();
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
QVector<nmDataFault> nmDataAnalyzeManager::getFaultDataListCopy() const
|
|
|
{
|
|
|
QVector<nmDataFault> result;
|
|
|
result.reserve(m_vFaultData.size());
|
|
|
|
|
|
foreach(const nmDataFault* fault, m_vFaultData) {
|
|
|
if(fault) {
|
|
|
result.append(*fault); // 调用拷贝构造函数
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateFaultData(const QVector<nmDataFault>& newData)
|
|
|
{
|
|
|
// 确保数量一致
|
|
|
if(newData.size() != m_vFaultData.size()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
for(int i = 0; i < newData.size(); ++i) {
|
|
|
if(m_vFaultData[i]) {
|
|
|
// 只更新内容,不改变指针
|
|
|
*m_vFaultData[i] = newData[i]; // 调用赋值运算符
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
nmGuiPlot* nmDataAnalyzeManager::getPlot() const
|
|
|
{
|
|
|
return m_pNmGuiPlot;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setPlot(nmGuiPlot * plot)
|
|
|
{
|
|
|
m_pNmGuiPlot = plot;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::updateWellPlotByDataManager()
|
|
|
{
|
|
|
nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider();
|
|
|
if (m_pNmGuiPlot != nullptr && pPlotContextProvider != nullptr)
|
|
|
{
|
|
|
pPlotContextProvider->updateWellPlots(m_pNmGuiPlot, this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> nmDataAnalyzeManager::getValueAllConnectablePoints()
|
|
|
{
|
|
|
QVector<QPointF> vecAllPoints;
|
|
|
|
|
|
// 遍历所有断层数据
|
|
|
foreach(nmDataFault* fault, m_vFaultData) {
|
|
|
if(fault) {
|
|
|
QVector<QPointF> faultPoints = fault->getFaultPoints();
|
|
|
|
|
|
foreach(const QPointF& point, faultPoints) {
|
|
|
vecAllPoints.append(point);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 遍历所有裂缝数据
|
|
|
foreach(nmDataFracture* fracture, m_vFractureData) {
|
|
|
if(fracture) {
|
|
|
QVector<QPointF> fracturePoints = fracture->getFracturePoints();
|
|
|
|
|
|
foreach(const QPointF& point, fracturePoints) {
|
|
|
vecAllPoints.append(point);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 遍历所有复合区数据
|
|
|
foreach(nmDataRegion* region, m_vRegionData) {
|
|
|
if(region) {
|
|
|
QVector<QPointF> regionPoints = region->getVecPts();
|
|
|
|
|
|
foreach(const QPointF& point, regionPoints) {
|
|
|
vecAllPoints.append(point);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 处理边界数据
|
|
|
if(m_outlineData) {
|
|
|
QVector<QPointF> outlinePoints = m_outlineData->getOutlinePoints();
|
|
|
|
|
|
// 圆形边界,特殊处理
|
|
|
if(m_outlineData->getOutlineType() == NM_Round_Outline_Type) {
|
|
|
outlinePoints.remove(0); // 圆心
|
|
|
outlinePoints.remove(0); // 半径
|
|
|
}
|
|
|
|
|
|
foreach(const QPointF& point, outlinePoints) {
|
|
|
vecAllPoints.append(point);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 垂直裂缝井的裂缝两个端点
|
|
|
// 遍历所有井数据
|
|
|
foreach(nmDataWellBase* well, m_vWellData) {
|
|
|
if(well == nullptr) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if(well->getWellType() == NM_WELL_MODEL::Vertical_Fractured_Well) {
|
|
|
nmDataVerticalFracturedWell* pVFwell = dynamic_cast<nmDataVerticalFracturedWell*>(well);
|
|
|
if(pVFwell == nullptr) {
|
|
|
continue;
|
|
|
}
|
|
|
QVector<QPointF> fracsPoints = pVFwell->getFracs();
|
|
|
|
|
|
foreach(const QPointF& point, fracsPoints) {
|
|
|
vecAllPoints.append(point);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return vecAllPoints;
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> nmDataAnalyzeManager::getPosAllConnectablePoints()
|
|
|
{
|
|
|
// 将绘图坐标系转为qt坐标系
|
|
|
QVector<QPointF> vecValues = this->getValueAllConnectablePoints();
|
|
|
QVector<QPointF> vecPos;
|
|
|
|
|
|
Q_ASSERT(m_pNmGuiPlot != nullptr);
|
|
|
nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider();
|
|
|
if(m_pNmGuiPlot == nullptr || pPlotContextProvider == nullptr) {
|
|
|
return vecPos;
|
|
|
}
|
|
|
|
|
|
pPlotContextProvider->getPosForValue(m_pNmGuiPlot, vecValues, vecPos);
|
|
|
|
|
|
// TODO:没有m_pNmGuiPlot的情况下怎么办,也就是加载的时候
|
|
|
|
|
|
return vecPos;
|
|
|
}
|
|
|
|
|
|
QVector<QPointF> nmDataAnalyzeManager::removePosByObject(QObject * obj)
|
|
|
{
|
|
|
// 获取所有可连接的点(屏幕坐标)
|
|
|
QVector<QPointF> vecAllPoints = this->getPosAllConnectablePoints();
|
|
|
|
|
|
// 创建一个临时容器用于存储要移除的点
|
|
|
QVector<QPointF> pointsToRemove;
|
|
|
|
|
|
// 检查传入的对象类型并收集相关点
|
|
|
if(nmDataFault * fault = dynamic_cast<nmDataFault * >(obj)) {
|
|
|
QVector<QPointF> faultPoints = fault->getFaultPoints();
|
|
|
|
|
|
foreach(const QPointF& point, faultPoints) {
|
|
|
pointsToRemove.append(point);
|
|
|
}
|
|
|
} else if(nmDataFracture * fracture = dynamic_cast<nmDataFracture * >(obj)) {
|
|
|
QVector<QPointF> fracturePoints = fracture->getFracturePoints();
|
|
|
|
|
|
foreach(const QPointF& point, fracturePoints) {
|
|
|
pointsToRemove.append(point);
|
|
|
}
|
|
|
} else if(nmDataRegion * region = dynamic_cast<nmDataRegion * >(obj)) {
|
|
|
QVector<QPointF> regionPoints = region->getVecPts();
|
|
|
|
|
|
foreach(const QPointF& point, regionPoints) {
|
|
|
pointsToRemove.append(point);
|
|
|
}
|
|
|
} else if(nmDataVerticalFracturedWell * well = dynamic_cast<nmDataVerticalFracturedWell * >(obj)) {
|
|
|
QVector<QPointF> fracsPoints = well->getFracs();
|
|
|
|
|
|
foreach(const QPointF& point, fracsPoints) {
|
|
|
pointsToRemove.append(point);
|
|
|
}
|
|
|
} else if(m_outlineData == obj) {
|
|
|
QVector<QPointF> outlinePoints = m_outlineData->getOutlinePoints();
|
|
|
|
|
|
if(m_outlineData->getOutlineType() == NM_Round_Outline_Type) {
|
|
|
outlinePoints.remove(0); // 圆心
|
|
|
outlinePoints.remove(0); // 半径
|
|
|
}
|
|
|
|
|
|
foreach(const QPointF& point, outlinePoints) {
|
|
|
pointsToRemove.append(point);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// change to Pos
|
|
|
QVector<QPointF> vecPosRemove;
|
|
|
|
|
|
nmDataPlotContextProvider* pPlotContextProvider = nmDataPlotContext::provider();
|
|
|
if(m_pNmGuiPlot && pPlotContextProvider) {
|
|
|
pPlotContextProvider->getPosForValue(m_pNmGuiPlot, pointsToRemove, vecPosRemove);
|
|
|
}
|
|
|
|
|
|
// 移除与特定对象相关的点
|
|
|
QVector<QPointF>::iterator itRemove;
|
|
|
|
|
|
for(itRemove = vecPosRemove.begin(); itRemove != vecPosRemove.end(); ++itRemove) {
|
|
|
QPointF pointToRemove = *itRemove;
|
|
|
|
|
|
for(int i = 0; i < vecAllPoints.size(); ++i) {
|
|
|
if(vecAllPoints[i] == pointToRemove) {
|
|
|
vecAllPoints.remove(i);
|
|
|
break; // 只移除第一个匹配的点
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return vecAllPoints;
|
|
|
}
|
|
|
|
|
|
nmDataMeasuringScale *nmDataAnalyzeManager::getMeasuringScaleData()
|
|
|
{
|
|
|
if(m_pMeasuringScaleData == nullptr) {
|
|
|
m_pMeasuringScaleData = new nmDataMeasuringScale;
|
|
|
}
|
|
|
|
|
|
return m_pMeasuringScaleData;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setMeasuringScaleData(nmDataMeasuringScale * pMeasuringScaleData)
|
|
|
{
|
|
|
if(m_pMeasuringScaleData != nullptr) {
|
|
|
delete m_pMeasuringScaleData;
|
|
|
m_pMeasuringScaleData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pMeasuringScaleData = pMeasuringScaleData;
|
|
|
}
|
|
|
|
|
|
nmDataMeasure *nmDataAnalyzeManager::getMeasureData()
|
|
|
{
|
|
|
if(m_pMeasureData == nullptr) {
|
|
|
m_pMeasureData = new nmDataMeasure;
|
|
|
}
|
|
|
|
|
|
return m_pMeasureData;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setMeasureData(nmDataMeasure * pMeasureData)
|
|
|
{
|
|
|
if(m_pMeasureData != nullptr) {
|
|
|
delete m_pMeasureData;
|
|
|
m_pMeasureData = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pMeasureData = pMeasureData;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeMeasureData()
|
|
|
{
|
|
|
if(m_pMeasureData) {
|
|
|
delete m_pMeasureData;
|
|
|
m_pMeasureData = nullptr;
|
|
|
return true; // 移除成功,返回 true
|
|
|
}
|
|
|
|
|
|
return false; // 未找到或移除失败,返回 false
|
|
|
}
|
|
|
|
|
|
NM_Grid_Type nmDataAnalyzeManager::getGridType()
|
|
|
{
|
|
|
return m_eGridType;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setGridType(NM_Grid_Type newGridType)
|
|
|
{
|
|
|
m_eGridType = newGridType;
|
|
|
}
|
|
|
|
|
|
// 获取Pebi网格求解数据接口
|
|
|
// 获取压力历史数据
|
|
|
QVector<QVector<double>> nmDataAnalyzeManager::getPebiSolverHistoryDataByName(const QString & wellName)
|
|
|
{
|
|
|
QVector<QVector<double>> vvecHisotryData;
|
|
|
QVector<double> vX;
|
|
|
QVector<double> vY;
|
|
|
|
|
|
// 验证井名有效性
|
|
|
if(wellName.isEmpty()) {
|
|
|
return vvecHisotryData;
|
|
|
}
|
|
|
|
|
|
// 从结果文件中读取数据
|
|
|
QString sHistoryDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/Pressure.txt";
|
|
|
|
|
|
if(!QFile::exists(sHistoryDataFilePath)) {
|
|
|
return vvecHisotryData;
|
|
|
}
|
|
|
|
|
|
QStringList sContent = nmDataUtils::readNmDataFile(sHistoryDataFilePath);
|
|
|
QRegExp regex("\\s+");
|
|
|
|
|
|
for(int i = 0; i < sContent.size(); i++) {
|
|
|
QString sData = sContent[i].trimmed();
|
|
|
|
|
|
if(sData.isEmpty()) continue;
|
|
|
|
|
|
QStringList sXY = sData.split(regex, QString::SkipEmptyParts);
|
|
|
|
|
|
if(sXY.size() == 2) {
|
|
|
bool okX, okY;
|
|
|
double x = sXY[0].toDouble(&okX);
|
|
|
double y = sXY[1].toDouble(&okY);
|
|
|
|
|
|
if(okX && okY) {
|
|
|
vX.append(x);
|
|
|
vY.append(y);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
vvecHisotryData.append(vX);
|
|
|
vvecHisotryData.append(vY);
|
|
|
|
|
|
return vvecHisotryData;
|
|
|
}
|
|
|
|
|
|
QVector<QVector<double>> nmDataAnalyzeManager::getPebiSolverLogPreDataByName(const QString & wellName)
|
|
|
{
|
|
|
QVector<QVector<double>> vvecLogPreData;
|
|
|
QVector<double> vX;
|
|
|
QVector<double> vY;
|
|
|
QVector<double> vZ;
|
|
|
|
|
|
// 验证井名有效性
|
|
|
if(wellName.isEmpty()) {
|
|
|
return vvecLogPreData;
|
|
|
}
|
|
|
|
|
|
// 从结果文件中读取数据
|
|
|
QString sLogPreDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/Loglog.txt";
|
|
|
|
|
|
if(!QFile::exists(sLogPreDataFilePath)) {
|
|
|
return vvecLogPreData;
|
|
|
}
|
|
|
|
|
|
QStringList sContent = nmDataUtils::readNmDataFile(sLogPreDataFilePath);
|
|
|
QRegExp regex("\\s+");
|
|
|
|
|
|
for(int i = 0; i < sContent.size() - 1; i++) {
|
|
|
QString sData = sContent[i].trimmed();
|
|
|
|
|
|
if(sData.isEmpty()) continue;
|
|
|
|
|
|
QStringList sXYZ = sData.split(regex, QString::SkipEmptyParts);
|
|
|
|
|
|
if(sXYZ.size() == 3) {
|
|
|
bool okX, okY, okZ;
|
|
|
double x = sXYZ[0].toDouble(&okX);
|
|
|
double y = sXYZ[1].toDouble(&okY);
|
|
|
double z = sXYZ[2].toDouble(&okZ);
|
|
|
|
|
|
if(okX && okY && okZ) {
|
|
|
vX.append(x);
|
|
|
vY.append(y);
|
|
|
vZ.append(z);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
vvecLogPreData.append(vX);
|
|
|
vvecLogPreData.append(vY);
|
|
|
vvecLogPreData.append(vZ);
|
|
|
|
|
|
return vvecLogPreData;
|
|
|
}
|
|
|
|
|
|
QVector<QVector<double>> nmDataAnalyzeManager::getPebiSolverSemiLogPreDataByName(const QString & wellName)
|
|
|
{
|
|
|
QVector<QVector<double>> vvecSemiLogPreData;
|
|
|
QVector<double> vX;
|
|
|
QVector<double> vY;
|
|
|
|
|
|
// 验证井名有效性
|
|
|
if(wellName.isEmpty()) {
|
|
|
return vvecSemiLogPreData;
|
|
|
}
|
|
|
|
|
|
// 从结果文件中读取数据
|
|
|
QString sSemiLogPreDataFilePath = ZxBaseUtil::getCurWellDirOf("Nm/Solver") + "output/Pebi/" + wellName + "/SemiLog.txt";
|
|
|
|
|
|
if(!QFile::exists(sSemiLogPreDataFilePath)) {
|
|
|
return vvecSemiLogPreData;
|
|
|
}
|
|
|
|
|
|
QStringList sContent = nmDataUtils::readNmDataFile(sSemiLogPreDataFilePath);
|
|
|
QRegExp regex("\\s+");
|
|
|
|
|
|
for(int i = 0; i < sContent.size(); i++) {
|
|
|
QString sData = sContent[i].trimmed();
|
|
|
|
|
|
if(sData.isEmpty()) continue;
|
|
|
|
|
|
QStringList sXY = sData.split(regex, QString::SkipEmptyParts);
|
|
|
|
|
|
if(sXY.size() == 2) {
|
|
|
bool okX, okY;
|
|
|
double x = sXY[0].toDouble(&okX);
|
|
|
double y = sXY[1].toDouble(&okY);
|
|
|
|
|
|
if(okX && okY) {
|
|
|
vX.append(x);
|
|
|
vY.append(y);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
vvecSemiLogPreData.append(vX);
|
|
|
vvecSemiLogPreData.append(vY);
|
|
|
|
|
|
return vvecSemiLogPreData;
|
|
|
}
|
|
|
|
|
|
nmDataPvtParaForPebi* nmDataAnalyzeManager::getPebiPvtPara()
|
|
|
{
|
|
|
return m_pebiPvtPara;
|
|
|
}
|
|
|
|
|
|
nmDataMixedResults* nmDataAnalyzeManager::getMixedResults()
|
|
|
{
|
|
|
return m_pMixedResults;
|
|
|
}
|
|
|
|
|
|
nmDataMixedResults* nmDataAnalyzeManager::createMixedResult()
|
|
|
{
|
|
|
if(m_pMixedResults != nullptr) {
|
|
|
delete m_pMixedResults;
|
|
|
m_pMixedResults = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pMixedResults = new nmDataMixedResults;
|
|
|
return m_pMixedResults;
|
|
|
}
|
|
|
|
|
|
nmDataLayer* nmDataAnalyzeManager::getLayerData()
|
|
|
{
|
|
|
// 1. 删除 m_vecLayers 中当前存储的所有 nmDataLayer 对象,释放内存
|
|
|
qDeleteAll(m_vecLayers);
|
|
|
// 2. 清空 m_vecLayers 自身,移除所有指针
|
|
|
m_vecLayers.clear();
|
|
|
|
|
|
return m_pLayerData;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setLayers(QVector<nmDataLayer*> vecLayers)
|
|
|
{
|
|
|
m_vecLayers = vecLayers;
|
|
|
}
|
|
|
|
|
|
QVector<nmDataLayer*> nmDataAnalyzeManager::getLayers()
|
|
|
{
|
|
|
return m_vecLayers;
|
|
|
}
|
|
|
|
|
|
double nmDataAnalyzeManager::getMinLayerTop()
|
|
|
{
|
|
|
// 在计算前初始化边界值
|
|
|
double m_dMinLayerTop = DBL_MAX;
|
|
|
|
|
|
// 复制新数据并计算边界
|
|
|
foreach(const nmDataLayer* layer , m_vecLayers) {
|
|
|
if(layer) {
|
|
|
// 更新缓存的最小顶深度
|
|
|
m_dMinLayerTop = qMin(m_dMinLayerTop, layer->getTop());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果 m_vecLayers 为空,可以设置默认值
|
|
|
if(m_vecLayers.isEmpty()) {
|
|
|
m_dMinLayerTop = 0.0;
|
|
|
}
|
|
|
return m_dMinLayerTop;
|
|
|
}
|
|
|
|
|
|
// 新增的实现:返回存储的最大底深度
|
|
|
double nmDataAnalyzeManager::getMaxLayerBottom()
|
|
|
{
|
|
|
// 在计算前初始化边界值
|
|
|
double m_dMaxLayerBottom = DBL_MIN;
|
|
|
|
|
|
// 复制新数据并计算边界
|
|
|
foreach(const nmDataLayer* layer , m_vecLayers) {
|
|
|
if(layer) {
|
|
|
// 更新缓存的最大顶深度
|
|
|
m_dMaxLayerBottom = qMax(m_dMaxLayerBottom, layer->getBottom());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果 m_vecLayers 为空,可以设置默认值
|
|
|
if(m_vecLayers.isEmpty()) {
|
|
|
m_dMaxLayerBottom = 0.0;
|
|
|
}
|
|
|
return m_dMaxLayerBottom;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::appendCalculationWell(const QPair<NM_WELL_MODEL, QString>& well)
|
|
|
{
|
|
|
m_vecCalculationWells.append(well);
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::insertCalculationWell(int index, const QPair<NM_WELL_MODEL, QString>& well)
|
|
|
{
|
|
|
if(index < 0 || index > m_vecCalculationWells.size()) {
|
|
|
return; // 索引无效,不执行插入操作
|
|
|
}
|
|
|
|
|
|
m_vecCalculationWells.insert(index, well);
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeCalculationWell(int index)
|
|
|
{
|
|
|
if(index < 0 || index >= m_vecCalculationWells.size()) {
|
|
|
return false; // 索引无效,返回 false
|
|
|
}
|
|
|
|
|
|
m_vecCalculationWells.remove(index);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::clearCalculationWells()
|
|
|
{
|
|
|
m_vecCalculationWells.clear();
|
|
|
}
|
|
|
|
|
|
QVector<QPair<NM_WELL_MODEL, QString>> nmDataAnalyzeManager::getCalculationWells() const
|
|
|
{
|
|
|
return m_vecCalculationWells;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::isContainsWellName(const QString & wellName) const
|
|
|
{
|
|
|
for(int i = 0; i < m_vecCalculationWells.size(); ++i) {
|
|
|
const QPair<NM_WELL_MODEL, QString>& well = m_vecCalculationWells[i];
|
|
|
|
|
|
if(well.first == NM_WELL_MODEL::Unknow_Well) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if(well.second == wellName) {
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 设置当前查看井
|
|
|
void nmDataAnalyzeManager::setCurWellData(nmDataWellBase * wellData)
|
|
|
{
|
|
|
m_pCurDataWell = wellData;
|
|
|
}
|
|
|
|
|
|
// 获取当前查看井
|
|
|
nmDataWellBase* nmDataAnalyzeManager::getCurWellData()
|
|
|
{
|
|
|
return m_pCurDataWell;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::notifyDataChanged()
|
|
|
{
|
|
|
emit dataChanged();
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setDisplaySettings(const QVector<DisplaySetting>& displaySettings)
|
|
|
{
|
|
|
m_vecDisplaySettings = displaySettings;
|
|
|
}
|
|
|
|
|
|
QVector<DisplaySetting> nmDataAnalyzeManager::getDisplaySettings() const
|
|
|
{
|
|
|
return m_vecDisplaySettings;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::updateCategoryDisplaySetting(const QString & categoryName, const CategoryDisplayInfo & info)
|
|
|
{
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == categoryName) {
|
|
|
m_vecDisplaySettings[i].value = info;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::initDefaultDisplaySettings()
|
|
|
{
|
|
|
m_vecDisplaySettings.clear();
|
|
|
|
|
|
// Contour
|
|
|
DisplaySetting contourSetting;
|
|
|
contourSetting.key = tr("Contour");
|
|
|
contourSetting.value.isRootChecked = true; // 默认选中
|
|
|
m_vecDisplaySettings.append(contourSetting);
|
|
|
|
|
|
// Faults
|
|
|
DisplaySetting faultsSetting;
|
|
|
faultsSetting.key = tr("Faults");
|
|
|
faultsSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(faultsSetting);
|
|
|
|
|
|
// Images
|
|
|
DisplaySetting imagesSetting;
|
|
|
imagesSetting.key = tr("Images");
|
|
|
imagesSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(imagesSetting);
|
|
|
|
|
|
// Wells
|
|
|
DisplaySetting wellsSetting;
|
|
|
wellsSetting.key = tr("Wells");
|
|
|
wellsSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(wellsSetting);
|
|
|
|
|
|
// Fractures
|
|
|
DisplaySetting fracturesSetting;
|
|
|
fracturesSetting.key = tr("Fractures");
|
|
|
fracturesSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(fracturesSetting);
|
|
|
|
|
|
// Limits
|
|
|
DisplaySetting limitsSetting;
|
|
|
limitsSetting.key = tr("Regions");
|
|
|
limitsSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(limitsSetting);
|
|
|
|
|
|
// RegionMarks
|
|
|
DisplaySetting regionsSetting;
|
|
|
regionsSetting.key = tr("RegionMarks");
|
|
|
regionsSetting.value.isRootChecked = true;
|
|
|
m_vecDisplaySettings.append(regionsSetting);
|
|
|
}
|
|
|
|
|
|
CategoryDisplayInfo* nmDataAnalyzeManager::findCategoryDisplayInfo(const QString & categoryName)
|
|
|
{
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == categoryName) {
|
|
|
return &m_vecDisplaySettings[i].value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::appendDisplaySetting(const DisplaySetting & displaySetting)
|
|
|
{
|
|
|
// 检查是否已存在相同key的设置
|
|
|
foreach(const auto& setting, m_vecDisplaySettings) {
|
|
|
if(setting.key == displaySetting.key) {
|
|
|
return false; // 已存在相同key,添加失败
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 添加新的显示设置
|
|
|
m_vecDisplaySettings.append(displaySetting);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeDisplaySetting(const QString & categoryName)
|
|
|
{
|
|
|
// 遍历查找并删除指定key的设置
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == categoryName) {
|
|
|
m_vecDisplaySettings.remove(i);
|
|
|
return true; // 删除成功
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false; // 未找到指定key的设置,删除失败
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::addChildItemsToCategory(const QString & parentCategory,
|
|
|
const QStringList & childNames,
|
|
|
bool defaultChecked)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个子项名称创建ChildCategoryDisplayInfo并添加到父类别
|
|
|
for(int j = 0; j < childNames.size(); ++j) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = childNames.at(j);
|
|
|
childInfo.isChecked = defaultChecked;
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked; // 子项启用状态取决于父项
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::refreshChildItemsDisplay()
|
|
|
{
|
|
|
// 步骤1: 清空所有父节点的子节点
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
m_vecDisplaySettings[i].value.childItems.clear();
|
|
|
}
|
|
|
|
|
|
// 更新边界和位图
|
|
|
CategoryDisplayInfo outlineInfo, imageInfo;
|
|
|
outlineInfo.isRootChecked = m_outlineData->getPlotVisible();
|
|
|
imageInfo.isRootChecked = this->m_backgroundImageInfo.bIsVisible;
|
|
|
this->updateCategoryDisplaySetting(tr("Contour"), outlineInfo);
|
|
|
this->updateCategoryDisplaySetting(tr("Images"), imageInfo);
|
|
|
|
|
|
// 步骤2: 重新添加子节点,根据不同数据容器中的对象名称生成子节点
|
|
|
// 为 "Wells" 分类添加子节点
|
|
|
addWellChildItemsToCategory(tr("Wells"));
|
|
|
|
|
|
// 为 "Faults" 分类添加子节点
|
|
|
addFaultChildItemsToCategory(tr("Faults"));
|
|
|
|
|
|
// 为 "Fractures" 分类添加子节点
|
|
|
addFractureChildItemsToCategory(tr("Fractures"));
|
|
|
|
|
|
// 为 "Regions" 分类添加子节点
|
|
|
addRegionChildItemsToCategory(tr("Regions"));
|
|
|
|
|
|
// 为 "RegionMarks" 分类添加子节点
|
|
|
addRegionMarkChildItemsToCategory(tr("RegionMarks"));
|
|
|
}
|
|
|
|
|
|
// 为Wells分类添加子节点
|
|
|
void nmDataAnalyzeManager::addWellChildItemsToCategory(const QString & parentCategory)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个井对象创建子节点
|
|
|
for(int j = 0; j < m_vWellData.size(); ++j) {
|
|
|
if(m_vWellData[j]) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = m_vWellData[j]->getWellName();
|
|
|
childInfo.isChecked = m_vWellData[j]->getPlotVisible();
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked;
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 为Faults分类添加子节点
|
|
|
void nmDataAnalyzeManager::addFaultChildItemsToCategory(const QString & parentCategory)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个断层对象创建子节点
|
|
|
for(int j = 0; j < m_vFaultData.size(); ++j) {
|
|
|
if(m_vFaultData[j]) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = m_vFaultData[j]->getFaultName();
|
|
|
childInfo.isChecked = m_vFaultData[j]->getPlotVisible();
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked;
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 为Fractures分类添加子节点
|
|
|
void nmDataAnalyzeManager::addFractureChildItemsToCategory(const QString & parentCategory)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个裂缝对象创建子节点
|
|
|
for(int j = 0; j < m_vFractureData.size(); ++j) {
|
|
|
if(m_vFractureData[j]) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = m_vFractureData[j]->getFractureName();
|
|
|
childInfo.isChecked = m_vFractureData[j]->getPlotVisible();
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked;
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 为Regions分类添加子节点
|
|
|
void nmDataAnalyzeManager::addRegionChildItemsToCategory(const QString & parentCategory)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个复合区对象创建子节点
|
|
|
for(int j = 0; j < m_vRegionData.size(); ++j) {
|
|
|
if(m_vRegionData[j]) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = m_vRegionData[j]->getRegoinName();
|
|
|
childInfo.isChecked = m_vRegionData[j]->getPlotVisible();
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked;
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 为RegionMarks分类添加子节点
|
|
|
void nmDataAnalyzeManager::addRegionMarkChildItemsToCategory(const QString & parentCategory)
|
|
|
{
|
|
|
// 查找父类别
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
if(m_vecDisplaySettings[i].key == parentCategory) {
|
|
|
// 为每个区域标记对象创建子节点
|
|
|
for(int j = 0; j < m_vRegionMarkData.size(); ++j) {
|
|
|
if(m_vRegionMarkData[j]) {
|
|
|
ChildCategoryDisplayInfo childInfo;
|
|
|
childInfo.name = m_vRegionMarkData[j]->getRegionMarkName();
|
|
|
childInfo.isChecked = m_vRegionMarkData[j]->getPlotVisible();
|
|
|
childInfo.isEnabled = m_vecDisplaySettings[i].value.isRootChecked;
|
|
|
|
|
|
m_vecDisplaySettings[i].value.childItems.append(childInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setAllCategoriesRootVisibility(bool bIsVisible)
|
|
|
{
|
|
|
for(int i = 0; i < m_vecDisplaySettings.size(); ++i) {
|
|
|
m_vecDisplaySettings[i].value.isRootChecked = bIsVisible;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setBackgroundImageInfo(const BackgroundImageInfo & info)
|
|
|
{
|
|
|
m_backgroundImageInfo = info;
|
|
|
}
|
|
|
|
|
|
const BackgroundImageInfo& nmDataAnalyzeManager::getBackgroundImageInfo() const
|
|
|
{
|
|
|
return m_backgroundImageInfo;
|
|
|
}
|
|
|
|
|
|
// 从 JSON 文件读取数据到 C++ 对象
|
|
|
bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
{
|
|
|
rapidjson::Document doc;
|
|
|
|
|
|
// 调用 nmDataJsonTools 读取 JSON 文件到 Document
|
|
|
if(!nmDataJsonTools::ReadDomFromFile(filePath, doc)) {
|
|
|
qDebug() << "Error: Failed to read DOM from file:" << filePath;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 读取已保存的成果井名称,待井数据加载完成后恢复。
|
|
|
QString sSavedCurWellName;
|
|
|
if(doc.HasMember("CurrentResultWellName") && doc["CurrentResultWellName"].IsString()) {
|
|
|
sSavedCurWellName = QString::fromUtf8(doc["CurrentResultWellName"].GetString());
|
|
|
}
|
|
|
|
|
|
// 清空现有数据,确保从头加载新数据
|
|
|
foreach(nmDataFracture* pFractureData, m_vFractureData) {
|
|
|
delete pFractureData; // 释放堆上分配的 nmDataFracture 对象
|
|
|
}
|
|
|
|
|
|
m_vFractureData.clear();
|
|
|
|
|
|
foreach(nmDataFault* pFaultData, m_vFaultData) {
|
|
|
delete pFaultData; // 释放堆上分配的 nmDataFault 对象
|
|
|
}
|
|
|
|
|
|
m_vFaultData.clear();
|
|
|
|
|
|
foreach(nmDataRegion* pRegionData, m_vRegionData) {
|
|
|
delete pRegionData; // 释放堆上分配的 nmDataRegion 对象
|
|
|
}
|
|
|
|
|
|
m_vRegionData.clear();
|
|
|
|
|
|
foreach(nmDataRegionMark* pRegionMarkData, m_vRegionMarkData) {
|
|
|
delete pRegionMarkData; // 释放堆上分配的 nmDataRegionMark 对象
|
|
|
}
|
|
|
|
|
|
m_vRegionMarkData.clear();
|
|
|
|
|
|
foreach(nmDataLayer* pLayerData, m_vecLayers) {
|
|
|
delete pLayerData; // 释放堆上分配的 nmDataLayer 对象
|
|
|
}
|
|
|
|
|
|
m_vecLayers.clear();
|
|
|
|
|
|
if(m_reservoirData) {
|
|
|
delete m_reservoirData;
|
|
|
m_reservoirData = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_axisData) {
|
|
|
delete m_axisData;
|
|
|
m_axisData = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_outlineData) {
|
|
|
delete m_outlineData;
|
|
|
m_outlineData = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_pMixedResults) {
|
|
|
delete m_pMixedResults;
|
|
|
m_pMixedResults = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_pGeoRefData) {
|
|
|
delete m_pGeoRefData;
|
|
|
m_pGeoRefData = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_pTimeStep) {
|
|
|
delete m_pTimeStep;
|
|
|
m_pTimeStep = nullptr;
|
|
|
}
|
|
|
|
|
|
if(m_pSensitiveData) {
|
|
|
delete m_pSensitiveData;
|
|
|
m_pSensitiveData = nullptr;
|
|
|
}
|
|
|
|
|
|
//if(m_pPerCloData) {
|
|
|
// delete m_pPerCloData;
|
|
|
// m_pPerCloData = nullptr;
|
|
|
//}
|
|
|
|
|
|
if(m_pAutomaticFittingData) {
|
|
|
delete m_pAutomaticFittingData;
|
|
|
m_pAutomaticFittingData = nullptr;
|
|
|
}
|
|
|
|
|
|
//if(m_pebiPvtPara) {
|
|
|
// delete m_pebiPvtPara;
|
|
|
// m_pebiPvtPara = nullptr;
|
|
|
//}
|
|
|
|
|
|
foreach(nmDataWellBase* pWellData, m_vWellData) {
|
|
|
delete pWellData; // 释放堆上分配的 nmDataWellBase 对象
|
|
|
}
|
|
|
|
|
|
m_vWellData.clear();
|
|
|
|
|
|
// 解析 "Fractures" 数组
|
|
|
if(doc.HasMember("Fractures") && doc["Fractures"].IsArray()) {
|
|
|
const rapidjson::Value& fracturesJson = doc["Fractures"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < fracturesJson.Size(); ++i) {
|
|
|
// 动态创建 nmDataFracture 对象,并获取其指针
|
|
|
nmDataFracture* fracture = new nmDataFracture();
|
|
|
fracture->FromJsonValue(fracturesJson[i]); // 调用 nmDataFracture 自身的反序列化方法
|
|
|
m_vFractureData.append(fracture); // 将指针添加到 QVector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析 "Faults" 数组
|
|
|
if(doc.HasMember("Faults") && doc["Faults"].IsArray()) {
|
|
|
const rapidjson::Value& faultsJson = doc["Faults"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < faultsJson.Size(); ++i) {
|
|
|
// 动态创建 nmDataFault 对象,并获取其指针
|
|
|
nmDataFault* fault = new nmDataFault();
|
|
|
fault->FromJsonValue(faultsJson[i]); // 调用 nmDataFault 自身的反序列化方法
|
|
|
m_vFaultData.append(fault); // 将指针添加到 QVector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析 "Regions" 数组
|
|
|
if(doc.HasMember("Regions") && doc["Regions"].IsArray()) {
|
|
|
const rapidjson::Value& regionsJson = doc["Regions"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < regionsJson.Size(); ++i) {
|
|
|
// 动态创建 nmDataRegion 对象,并获取其指针
|
|
|
nmDataRegion* region = new nmDataRegion(); // 传入this作为父对象
|
|
|
region->FromJsonValue(regionsJson[i]); // 调用 nmDataRegion 自身的反序列化方法
|
|
|
m_vRegionData.append(region); // 将指针添加到 QVector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析 "RegionMarks" 数组
|
|
|
if(doc.HasMember("RegionMarks") && doc["RegionMarks"].IsArray()) {
|
|
|
const rapidjson::Value& regionMarksJson = doc["RegionMarks"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < regionMarksJson.Size(); ++i) {
|
|
|
// 动态创建 nmDataRegionMark 对象,并获取其指针
|
|
|
nmDataRegionMark* regionMark = new nmDataRegionMark(); // 传入this作为父对象
|
|
|
regionMark->FromJsonValue(regionMarksJson[i]); // 调用 nmDataRegion 自身的反序列化方法
|
|
|
m_vRegionMarkData.append(regionMark); // 将指针添加到 QVector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析 "Layers" 数组
|
|
|
if(doc.HasMember("Layers") && doc["Layers"].IsArray()) {
|
|
|
const rapidjson::Value& layersJson = doc["Layers"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < layersJson.Size(); ++i) {
|
|
|
// 动态创建 nmDataRegion 对象,并获取其指针
|
|
|
nmDataLayer* layer = new nmDataLayer(); // 传入this作为父对象
|
|
|
layer->FromJsonValue(layersJson[i]); // 调用 nmDataLayer 自身的反序列化方法
|
|
|
m_vecLayers.append(layer); // 将指针添加到 QVector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 解析 "Reservoir" 对象
|
|
|
if(doc.HasMember("Reservoir") && doc["Reservoir"].IsObject()) {
|
|
|
m_reservoirData = new nmDataReservoir;
|
|
|
m_reservoirData->FromJsonValue(doc["Reservoir"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "Axis" 对象
|
|
|
if(doc.HasMember("Axis") && doc["Axis"].IsObject()) {
|
|
|
m_axisData = new nmDataAxis;
|
|
|
m_axisData->FromJsonValue(doc["Axis"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "Outline" 对象
|
|
|
if(doc.HasMember("Outline") && doc["Outline"].IsObject()) {
|
|
|
m_outlineData = new nmDataOutline;
|
|
|
m_outlineData->FromJsonValue(doc["Outline"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "GeoRef" 对象
|
|
|
if(doc.HasMember("GeoReference") && doc["GeoReference"].IsObject()) {
|
|
|
m_pGeoRefData = new nmDataGeoRef;
|
|
|
m_pGeoRefData->FromJsonValue(doc["GeoReference"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "AutomaticFitting" 对象
|
|
|
if(doc.HasMember("AutomaticFitting") && doc["AutomaticFitting"].IsObject()) {
|
|
|
m_pAutomaticFittingData = new nmDataAutomaticFitting;
|
|
|
m_pAutomaticFittingData->FromJsonValue(doc["AutomaticFitting"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "Sensitive" 对象
|
|
|
if(doc.HasMember("Sensitive") && doc["Sensitive"].IsObject()) {
|
|
|
m_pSensitiveData = new nmDataSensitive;
|
|
|
m_pSensitiveData->FromJsonValue(doc["Sensitive"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "PVT" 对象
|
|
|
//if(doc.HasMember("PVT") && doc["PVT"].IsObject()) {
|
|
|
// m_pebiPvtPara = new nmDataPvtParaForPebi;
|
|
|
// m_pebiPvtPara->FromJsonValue(doc["PVT"]);
|
|
|
//}
|
|
|
|
|
|
// 解析 "MixResult" 对象
|
|
|
if(doc.HasMember("MixResult") && doc["MixResult"].IsObject()) {
|
|
|
m_pMixedResults = new nmDataMixedResults;
|
|
|
m_pMixedResults->FromJsonValue(doc["MixResult"]);
|
|
|
}
|
|
|
|
|
|
// 解析 "Wells" 数组
|
|
|
if(doc.HasMember("Wells") && doc["Wells"].IsArray()) {
|
|
|
const rapidjson::Value& wellsJson = doc["Wells"];
|
|
|
|
|
|
for(rapidjson::SizeType i = 0; i < wellsJson.Size(); ++i) {
|
|
|
//// 动态创建 nmDataFault 对象,并获取其指针
|
|
|
//nmDataWellBase* well = new nmDataWellBase(); // 传入this作为父对象
|
|
|
//well->FromJsonValue(wellsJson[i]); // 调用 nmDataFault 自身的反序列化方法
|
|
|
//m_vWellData.append(well); // 将指针添加到 QVector
|
|
|
|
|
|
// 获取当前井的JSON对象
|
|
|
const rapidjson::Value& wellItemJson = wellsJson[i];
|
|
|
|
|
|
// 临时指针,用于指向新创建的井对象
|
|
|
nmDataWellBase* pWell = nullptr;
|
|
|
// 井类型
|
|
|
NM_WELL_MODEL eWellType = NM_WELL_MODEL::Unknow_Well;
|
|
|
|
|
|
// 1. 读取 wellType
|
|
|
if(wellItemJson.HasMember("WellType") && wellItemJson["WellType"].IsInt()) {
|
|
|
eWellType = static_cast<NM_WELL_MODEL>(wellItemJson["WellType"].GetInt());
|
|
|
}
|
|
|
|
|
|
// 2. 根据 eWellType 动态创建不同的井类型实例
|
|
|
switch(eWellType) {
|
|
|
case NM_WELL_MODEL::Vertical_Well:
|
|
|
pWell = new nmDataVerticalWell;
|
|
|
break;
|
|
|
|
|
|
case NM_WELL_MODEL::Vertical_Fractured_Well:
|
|
|
pWell = new nmDataVerticalFracturedWell;
|
|
|
break;
|
|
|
|
|
|
case NM_WELL_MODEL::Horizontal_Fractured_Well:
|
|
|
pWell = new nmDataHorizontalFracturedWell;
|
|
|
break;
|
|
|
|
|
|
// TODO: 添加其他具体的井类型
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
// 3. 调用具体井类型的 FromJsonValue 方法进行反序列化
|
|
|
if(pWell) { // 确保 well 对象已成功创建
|
|
|
pWell->FromJsonValue(wellItemJson); // 调用其自身的反序列化方法
|
|
|
m_vWellData.append(pWell); // 将指针添加到 QVector
|
|
|
|
|
|
// TODO:将最后一口井设置为当前井(临时)
|
|
|
//this->setCurWellData(pWell);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 设置当前井
|
|
|
// 获取当前默认井数据
|
|
|
ZxDataWell* pWellData = zxCurWell;
|
|
|
// 查找是否有当前井的数据
|
|
|
nmDataWellBase* pCurWell = nullptr;
|
|
|
if(!sSavedCurWellName.isEmpty()) {
|
|
|
pCurWell = this->findWellByName(sSavedCurWellName);
|
|
|
}
|
|
|
|
|
|
if(pCurWell == nullptr && pWellData != nullptr) {
|
|
|
pCurWell = this->findWellByName(pWellData->getName());
|
|
|
}
|
|
|
if (pCurWell != nullptr)
|
|
|
{
|
|
|
this->setCurWellData(pCurWell);
|
|
|
} else {
|
|
|
// 设置第一口井为当前井
|
|
|
if (m_vWellData.size() > 0)
|
|
|
{
|
|
|
this->setCurWellData(m_vWellData[0]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// 解析 时间步 对象
|
|
|
if(doc.HasMember("TimeStep") && doc["TimeStep"].IsObject()) {
|
|
|
m_pTimeStep = new nmDataTimeStepSetting;
|
|
|
m_pTimeStep->FromJsonValue(doc["TimeStep"]);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 将 C++ 对象数据写入 JSON 文件
|
|
|
bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath)
|
|
|
{
|
|
|
rapidjson::Document doc;
|
|
|
doc.SetObject(); // 根节点是对象
|
|
|
rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); // 获取内存分配器
|
|
|
|
|
|
// 构建 "Fractures" 数组的 JSON Value
|
|
|
rapidjson::Value fracturesJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataFracture 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataFracture* pFractureData, m_vFractureData) {
|
|
|
if(pFractureData) { // 检查指针是否有效
|
|
|
fracturesJsonArray.PushBack(pFractureData->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("Fractures", fracturesJsonArray, allocator);
|
|
|
|
|
|
// 构建 "Faults" 数组的 JSON Value
|
|
|
rapidjson::Value faultsJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataFault 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataFault* pFaultData, m_vFaultData) {
|
|
|
if(pFaultData) { // 检查指针是否有效
|
|
|
faultsJsonArray.PushBack(pFaultData->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("Faults", faultsJsonArray, allocator);
|
|
|
|
|
|
// 构建 "Regions" 数组的 JSON Value
|
|
|
rapidjson::Value regionsJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataRegion 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataRegion* pRegionData, m_vRegionData) {
|
|
|
if(pRegionData) { // 检查指针是否有效
|
|
|
regionsJsonArray.PushBack(pRegionData->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("Regions", regionsJsonArray, allocator);
|
|
|
|
|
|
// 构建 "RegionMarks" 数组的 JSON Value
|
|
|
rapidjson::Value regionMarksJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataRegionMark 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataRegionMark* pRegionMarkData, m_vRegionMarkData) {
|
|
|
if(pRegionMarkData) { // 检查指针是否有效
|
|
|
regionMarksJsonArray.PushBack(pRegionMarkData->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("RegionMarks", regionMarksJsonArray, allocator);
|
|
|
|
|
|
// 构建 "Layers" 数组的 JSON Value
|
|
|
rapidjson::Value layersJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataLayer 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataLayer* pLayerData, m_vecLayers) {
|
|
|
if(pLayerData) { // 检查指针是否有效
|
|
|
layersJsonArray.PushBack(pLayerData->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("Layers", layersJsonArray, allocator);
|
|
|
|
|
|
// 序列化 "Reservoir"
|
|
|
if(m_reservoirData) {
|
|
|
rapidjson::Value reservoirJson(rapidjson::kObjectType);
|
|
|
reservoirJson = m_reservoirData->ToJsonValue(allocator);
|
|
|
doc.AddMember("Reservoir", reservoirJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 序列化 "Axis"
|
|
|
if(m_axisData) {
|
|
|
rapidjson::Value axisJson(rapidjson::kObjectType);
|
|
|
axisJson = m_axisData->ToJsonValue(allocator);
|
|
|
doc.AddMember("Axis", axisJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 序列化 "Outline"
|
|
|
if(m_outlineData) {
|
|
|
rapidjson::Value outlineJson(rapidjson::kObjectType);
|
|
|
outlineJson = m_outlineData->ToJsonValue(allocator);
|
|
|
doc.AddMember("Outline", outlineJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 序列化 "Reservoir"
|
|
|
if(m_pGeoRefData) {
|
|
|
rapidjson::Value geoRefJson(rapidjson::kObjectType);
|
|
|
geoRefJson = m_pGeoRefData->ToJsonValue(allocator);
|
|
|
doc.AddMember("GeoReference", geoRefJson, allocator);
|
|
|
}
|
|
|
|
|
|
//// 序列化 "PerforationClosing"
|
|
|
//if(m_pPerCloData) {
|
|
|
// rapidjson::Value perCloJson(rapidjson::kObjectType);
|
|
|
// perCloJson = m_pPerCloData->ToJsonValue(allocator);
|
|
|
// doc.AddMember("PerforationClosing", perCloJson, allocator);
|
|
|
//}
|
|
|
|
|
|
//// 序列化 "SkinVsRate"
|
|
|
//if(m_pSkinVsRateData) {
|
|
|
// rapidjson::Value skinJson(rapidjson::kObjectType);
|
|
|
// skinJson = m_pSkinVsRateData->ToJsonValue(allocator);
|
|
|
// doc.AddMember("SkinVsRate", skinJson, allocator);
|
|
|
//}
|
|
|
|
|
|
// 序列化 "AutomaticFitting"
|
|
|
if(m_pAutomaticFittingData) {
|
|
|
rapidjson::Value autofitJson(rapidjson::kObjectType);
|
|
|
autofitJson = m_pAutomaticFittingData->ToJsonValue(allocator);
|
|
|
doc.AddMember("AutomaticFitting", autofitJson, allocator);
|
|
|
}
|
|
|
|
|
|
|
|
|
// 序列化 "PVT"
|
|
|
//if(m_pebiPvtPara) {
|
|
|
// rapidjson::Value pvtJson(rapidjson::kObjectType);
|
|
|
// pvtJson = m_pebiPvtPara->ToJsonValue(allocator);
|
|
|
// doc.AddMember("PVT", pvtJson, allocator);
|
|
|
//}
|
|
|
|
|
|
// 序列化 "MixResult"
|
|
|
if(m_pMixedResults) {
|
|
|
rapidjson::Value mixResultsJson(rapidjson::kObjectType);
|
|
|
mixResultsJson = m_pMixedResults->ToJsonValue(allocator);
|
|
|
doc.AddMember("MixResult", mixResultsJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 序列化 "Sensitive"
|
|
|
if(m_pSensitiveData) {
|
|
|
rapidjson::Value sensitiveJson(rapidjson::kObjectType);
|
|
|
sensitiveJson = m_pSensitiveData->ToJsonValue(allocator);
|
|
|
doc.AddMember("Sensitive", sensitiveJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 构建 "Wells" 数组的 JSON Value
|
|
|
rapidjson::Value wellsJsonArray(rapidjson::kArrayType);
|
|
|
|
|
|
// 遍历存储 nmDataWellBase 指针的 QVector,并解引用指针来调用 ToJsonValue 方法
|
|
|
foreach(nmDataWellBase* pWellData, m_vWellData) {
|
|
|
if(nmDataVerticalFracturedWell * pVerticalFracturedWell = dynamic_cast<nmDataVerticalFracturedWell * >(pWellData)) { // 检查指针是否有效
|
|
|
wellsJsonArray.PushBack(pVerticalFracturedWell->ToJsonValue(allocator), allocator);
|
|
|
} else if(nmDataHorizontalFracturedWell * pHorizontalFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell * >(pWellData)) { // 检查指针是否有效
|
|
|
wellsJsonArray.PushBack(pHorizontalFracturedWell->ToJsonValue(allocator), allocator);
|
|
|
} else if(nmDataHorizontalWell * pHorizontalWell = dynamic_cast<nmDataHorizontalWell * >(pWellData)) { // 检查指针是否有效
|
|
|
wellsJsonArray.PushBack(pHorizontalWell->ToJsonValue(allocator), allocator);
|
|
|
} else if(nmDataVerticalWell * pVerticalWell = dynamic_cast<nmDataVerticalWell * >(pWellData)) { // 检查指针是否有效
|
|
|
wellsJsonArray.PushBack(pVerticalWell->ToJsonValue(allocator), allocator);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
doc.AddMember("Wells", wellsJsonArray, allocator);
|
|
|
|
|
|
// 保存当前成果井名称,供下次加载成果时恢复。
|
|
|
if(m_pCurDataWell != nullptr) {
|
|
|
QString sCurrentResultWellName = m_pCurDataWell->getWellName();
|
|
|
doc.AddMember("CurrentResultWellName",
|
|
|
rapidjson::Value(sCurrentResultWellName.toStdString().c_str(), allocator).Move(),
|
|
|
allocator);
|
|
|
}
|
|
|
|
|
|
// 序列化 时间步数据
|
|
|
if(m_pTimeStep) {
|
|
|
rapidjson::Value timeStepJson(rapidjson::kObjectType);
|
|
|
timeStepJson = m_pTimeStep->ToJsonValue(allocator);
|
|
|
doc.AddMember("TimeStep", timeStepJson, allocator);
|
|
|
}
|
|
|
|
|
|
// 将最终构建好的 Document 写入文件
|
|
|
if(!nmDataJsonTools::WriteDomToFile(doc, filePath)) {
|
|
|
qDebug() << "Error: Failed to write DOM to file:" << filePath;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::saveNmResult(QString sRstCode, iSubWndFitting* pSubWndF)
|
|
|
{
|
|
|
Q_ASSERT(nullptr != pSubWndF);
|
|
|
// 通过窗口层上下文获取保存目录
|
|
|
nmDataAnalyzeContextProvider* pContextProvider = nmDataAnalyzeContext::provider();
|
|
|
Q_ASSERT(nullptr != pContextProvider);
|
|
|
QString sDir;
|
|
|
if(pContextProvider == nullptr || !pContextProvider->getSaveResultDir(pSubWndF, sRstCode, sDir)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// sDir为当前成果窗口目录
|
|
|
// 保存前先清空成果ID目录下的旧内容,避免旧RstWnd目录或残留文件继续被加载
|
|
|
QString sResultRootPath = QFileInfo(sDir).dir().absolutePath();
|
|
|
if(!clearDirectoryContents(sResultRootPath)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString sResultPath = sDir + "/Results";
|
|
|
this->ensureDirectoryExists(sResultPath);
|
|
|
// 将数据写入Json文件
|
|
|
this->WriteProjectData(sResultPath + "/Numerical_Parameters.json");
|
|
|
|
|
|
// --- 保存所有井的历史数据到独立目录 /WellHistory ---
|
|
|
QString sWellHistoryDataPath = sDir + "/WellHistory";
|
|
|
this->ensureDirectoryExists(sWellHistoryDataPath);
|
|
|
|
|
|
QVector<nmDataWellBase*> vecAllWells = nmDataAnalyzeManager::getCurrentInstance()->getWellDataList(); // 获取所有井
|
|
|
|
|
|
// 遍历所有井,保存历史数据
|
|
|
for(int wellIdx = 0; wellIdx < vecAllWells.size(); ++wellIdx) {
|
|
|
nmDataWellBase* pWellData = vecAllWells[wellIdx];
|
|
|
if(pWellData) {
|
|
|
this->saveWellHistoryData(sWellHistoryDataPath, pWellData);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 保存非结构化网格数据
|
|
|
QString sGridPath = sDir + "/Grid";
|
|
|
|
|
|
if(!m_pVtkUnstructuredGrid) {
|
|
|
// 如果没有网格对象,说明没有生成网格,直接返回
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
this->ensureDirectoryExists(sGridPath);
|
|
|
|
|
|
// 将实时划分出来的网格写入文件
|
|
|
this->writeUnstructuredGridToFile(m_pVtkUnstructuredGrid, sGridPath + "/CurrentGrid.vtu");
|
|
|
|
|
|
// 保存结果里的基础网格
|
|
|
if(!m_pResultBaseGrid) {
|
|
|
// 无基础网格对象,说明没有进行计算,返回
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 保存场图里的基础网格
|
|
|
this->writeUnstructuredGridToFile(m_pResultBaseGrid, sGridPath + "/ResultGrid.vtu");
|
|
|
|
|
|
// 保存场图中的井位置相关信息
|
|
|
this->saveWellLocations(sGridPath + "/ResultWellLocations.bin");
|
|
|
|
|
|
// --- 保存时间步压力数据 (m_mapTimeStepDataP) ---
|
|
|
QString sTimeStepDataFilePath = sDir + "/TimeStepData/PressureTimeSteps.bin"; // 单个二进制文件路径
|
|
|
QString sTimeStepDataDirPath = sDir + "/TimeStepData"; // 确保目录存在
|
|
|
this->ensureDirectoryExists(sTimeStepDataDirPath);
|
|
|
|
|
|
// 将时间步数据写入二进制文件中
|
|
|
if(!writeTimeStepDataMapToBinaryFile(sTimeStepDataFilePath)) {
|
|
|
qDebug() << QString("Failed to save all time step data map to binary file: %1").arg(sTimeStepDataFilePath);
|
|
|
return false; // 返回失败
|
|
|
}
|
|
|
|
|
|
// 保存参与计算井的结果数据
|
|
|
QString sWellRstDataPath = sDir + "/WellRst";
|
|
|
this->ensureDirectoryExists(sWellRstDataPath);
|
|
|
QVector<QPair<NM_WELL_MODEL, QString>> vecWells = nmDataAnalyzeManager::getCurrentInstance()->getCalculationWells();
|
|
|
|
|
|
// 遍历每口井,保存里面计算出来的数据
|
|
|
for(int wellIdx = 0; wellIdx < vecWells.size(); ++wellIdx) {
|
|
|
NM_WELL_MODEL wellType = vecWells[wellIdx].first; // 获取井的类型
|
|
|
QString wellName = vecWells[wellIdx].second; // 获取井的名称
|
|
|
|
|
|
// 跳过裂缝(或未知井类型)
|
|
|
if(wellType == NM_WELL_MODEL::Unknow_Well) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
nmDataWellBase* pWellData = nmDataAnalyzeManager::getCurrentInstance()->findWellByName(wellName);
|
|
|
|
|
|
if(pWellData) {
|
|
|
this->saveWellCalRstData(sWellRstDataPath, pWellData);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::loadNmResult(QString sLoadAnalDir)
|
|
|
{
|
|
|
// 将Json文件内容读取出来
|
|
|
QString sResultPath = sLoadAnalDir + "/Results/Numerical_Parameters.json";
|
|
|
this->ReadProjectData(sResultPath);
|
|
|
|
|
|
// 读取当前网格文件
|
|
|
QString sCurrentGridPath = sLoadAnalDir + "/Grid/CurrentGrid.vtu";
|
|
|
this->readUnstructuredGridFromFile(m_pVtkUnstructuredGrid, sCurrentGridPath);
|
|
|
|
|
|
// 读取结果基础网格文件
|
|
|
QString sResultGridPath = sLoadAnalDir + "/Grid/ResultGrid.vtu";
|
|
|
this->readUnstructuredGridFromFile(m_pResultBaseGrid, sResultGridPath);
|
|
|
|
|
|
// 加载场图中的井位置相关信息
|
|
|
QString sResultWellLocationPath = sLoadAnalDir + "/Grid/ResultWellLocations.bin";
|
|
|
this->loadWellLocations(sResultWellLocationPath);
|
|
|
|
|
|
// --- 加载时间步压力数据 (m_mapTimeStepDataP) ---
|
|
|
QString sTimeStepDataFilePath = sLoadAnalDir + "/TimeStepData/PressureTimeSteps.bin";
|
|
|
|
|
|
// 读取时间步数据
|
|
|
if(!readTimeStepDataMapFromBinaryFile(sTimeStepDataFilePath)) {
|
|
|
qDebug() << QString("Failed to load all time step data map from binary file: %1").arg(sTimeStepDataFilePath);
|
|
|
}
|
|
|
|
|
|
// --- 加载所有井的历史数据从独立目录 /WellHistory ---
|
|
|
QString sWellHistoryDataPath = sLoadAnalDir + "/WellHistory";
|
|
|
this->ensureDirectoryExists(sWellHistoryDataPath);
|
|
|
|
|
|
// 遍历所有井,尝试加载历史数据
|
|
|
for(int i = 0; i < m_vWellData.size(); i++) {
|
|
|
this->loadWellHistoryData(sWellHistoryDataPath, m_vWellData[i]);
|
|
|
}
|
|
|
|
|
|
// 获取参与计算井的结果数据
|
|
|
QString sWellRstDataPath = sLoadAnalDir + "/WellRst";
|
|
|
this->ensureDirectoryExists(sWellRstDataPath);
|
|
|
|
|
|
for(int i = 0; i < m_vWellData.size(); i++) {
|
|
|
this->loadWellCalRstData(sWellRstDataPath, m_vWellData[i]);
|
|
|
}
|
|
|
|
|
|
// 读完后加载井的压力、流量数据
|
|
|
this->loadWellPreAndFlow();
|
|
|
|
|
|
if (m_pVtkUnstructuredGrid != nullptr)
|
|
|
m_bIsLoadData = true;
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::ensureDirectoryExists(const QString & dirPath)
|
|
|
{
|
|
|
QDir dir(dirPath);
|
|
|
|
|
|
if(!dir.exists()) {
|
|
|
qDebug() << QString("Directory does not exist, attempting to create: %1").arg(dirPath);
|
|
|
|
|
|
if(!dir.mkpath(dirPath)) {
|
|
|
qDebug() << QString("Failed to create directory: %1").arg(dirPath);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
qDebug() << QString("Directory created successfully: %1").arg(dirPath);
|
|
|
} else {
|
|
|
qDebug() << QString("Directory already exists: %1").arg(dirPath);
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::loadWellPreAndFlow()
|
|
|
{
|
|
|
// 获取当前工区里所有的ZxDataWell井
|
|
|
if(zxCurProject == nullptr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
ZxDataObjectList wellList = zxCurProject->getChildren(iDataModelType::sTypeWell);
|
|
|
|
|
|
foreach(nmDataWellBase* pWell, m_vWellData) {
|
|
|
if(pWell == nullptr) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
QString sWellName = pWell->getWellName();
|
|
|
|
|
|
ZxDataWell* pWellData = nullptr;
|
|
|
|
|
|
for(int i = 0; i < wellList.size(); i++) {
|
|
|
ZxDataWell* pCandidateWell = dynamic_cast<ZxDataWell*>(wellList[i]);
|
|
|
|
|
|
if(pCandidateWell != nullptr && pCandidateWell->getName() == sWellName) {
|
|
|
pWellData = pCandidateWell;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 拿到了井的数据
|
|
|
if(pWellData) {
|
|
|
// 获取当前井的压力、流量数据
|
|
|
ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP);
|
|
|
ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF);
|
|
|
|
|
|
ZxDataGaugeP* pGaugeP = nullptr;
|
|
|
ZxDataGaugeF* pGaugeF = nullptr;
|
|
|
|
|
|
// 遍历压力数据列表
|
|
|
for(int i = 0; i < m_listGaugeP.size(); ++i) {
|
|
|
if(pGaugeP = dynamic_cast<ZxDataGaugeP * >(m_listGaugeP[i])) { // 拿到第一条压力数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 遍历流量数据列表
|
|
|
for(int i = 0; i < m_listGaugeF.size(); ++i) {
|
|
|
if(pGaugeF = dynamic_cast<ZxDataGaugeF * >(m_listGaugeF[i])) { // 拿到第一条流量数据
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取的压力、流量数据
|
|
|
QVector<QPointF> vecPtsP, vecPtsF;
|
|
|
// 临时存储x,y坐标
|
|
|
VecDouble vecX, vecY;
|
|
|
|
|
|
if(pGaugeP != nullptr) {
|
|
|
// 获取压力数据
|
|
|
if(pGaugeP->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsP.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(pGaugeF != nullptr) {
|
|
|
vecX.clear();
|
|
|
vecY.clear();
|
|
|
|
|
|
// 获取流量数据
|
|
|
if(pGaugeF->getDataVecXY(vecX, vecY)) {
|
|
|
int pointCount = vecX.size();
|
|
|
if(pointCount > vecY.size()) {
|
|
|
pointCount = vecY.size();
|
|
|
}
|
|
|
for(int i = 0; i < pointCount; ++i) {
|
|
|
QPointF pt(vecX[i], vecY[i]);
|
|
|
vecPtsF.append(pt);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 设置井的压力数据、流量数据
|
|
|
pWell->setPressurePoints(vecPtsP);
|
|
|
pWell->setFlowPoints(vecPtsF);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> nmDataAnalyzeManager::getUnstructuredGrid() const
|
|
|
{
|
|
|
return m_pVtkUnstructuredGrid;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setUnstructuredGrid(vtkSmartPointer<vtkUnstructuredGrid> grid)
|
|
|
{
|
|
|
m_pVtkUnstructuredGrid = grid;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::clearUnstructuredGrid()
|
|
|
{
|
|
|
// 释放当前分析持有的实时VTK网格对象,关闭网格窗口后不再保留旧网格。
|
|
|
m_pVtkUnstructuredGrid = nullptr;
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> nmDataAnalyzeManager::getUnstructuredGridCopy() const
|
|
|
{
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> pCopyGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
|
|
|
|
|
|
if(m_pVtkUnstructuredGrid) {
|
|
|
// 执行深拷贝:复制网格的所有几何和拓扑信息
|
|
|
pCopyGrid->DeepCopy(m_pVtkUnstructuredGrid);
|
|
|
}
|
|
|
|
|
|
return pCopyGrid;
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> nmDataAnalyzeManager::getResultBaseGrid() const
|
|
|
{
|
|
|
return m_pResultBaseGrid;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setResultBaseGrid(vtkSmartPointer<vtkUnstructuredGrid> grid)
|
|
|
{
|
|
|
m_pResultBaseGrid = grid;
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> nmDataAnalyzeManager::getResultBaseGridCopy() const
|
|
|
{
|
|
|
vtkSmartPointer<vtkUnstructuredGrid> pCopyGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
|
|
|
|
|
|
if(m_pResultBaseGrid) {
|
|
|
// 执行深拷贝:复制网格的所有几何和拓扑信息
|
|
|
pCopyGrid->DeepCopy(m_pResultBaseGrid);
|
|
|
}
|
|
|
|
|
|
return pCopyGrid;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::writeUnstructuredGridToFile(vtkSmartPointer<vtkUnstructuredGrid> grid, const QString& filePath)
|
|
|
{
|
|
|
// 检查是否存在有效的网格数据
|
|
|
if(!grid) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 根据文件扩展名决定使用哪种格式
|
|
|
if(filePath.endsWith(".vtu", Qt::CaseInsensitive)) {
|
|
|
// 使用XML格式(推荐格式)
|
|
|
vtkNew<vtkXMLUnstructuredGridWriter> writer;
|
|
|
writer->SetInputData(grid); // 设置输入数据
|
|
|
writer->SetFileName(filePath.toStdString().c_str()); // 设置输出文件名
|
|
|
writer->SetDataModeToBinary(); // 设置为二进制模式,也可以用SetDataModeToAscii()设为文本模式
|
|
|
writer->Write(); // 执行写入操作
|
|
|
} else if(filePath.endsWith(".vtk", Qt::CaseInsensitive)) {
|
|
|
// 使用传统的VTK格式
|
|
|
vtkNew<vtkUnstructuredGridWriter> writer;
|
|
|
writer->SetInputData(grid); // 设置输入数据
|
|
|
writer->SetFileName(filePath.toStdString().c_str()); // 设置输出文件名
|
|
|
writer->SetFileTypeToBinary(); // 设置为二进制模式,也可以用SetFileTypeToASCII()设为文本模式
|
|
|
writer->Write(); // 执行写入操作
|
|
|
} else {
|
|
|
return false; // 不支持的文件扩展名
|
|
|
}
|
|
|
|
|
|
return true; // 写入成功
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::readUnstructuredGridFromFile(vtkSmartPointer<vtkUnstructuredGrid>& grid, const QString& filePath)
|
|
|
{
|
|
|
// 检查文件是否存在
|
|
|
if(!QFile::exists(filePath)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 根据文件扩展名选择不同的读取器
|
|
|
if(filePath.endsWith(".vtu", Qt::CaseInsensitive)) {
|
|
|
// 使用XML格式读取器
|
|
|
vtkNew<vtkXMLUnstructuredGridReader> reader;
|
|
|
reader->SetFileName(filePath.toStdString().c_str()); // 设置输入文件名
|
|
|
reader->Update(); // 执行读取操作
|
|
|
grid = reader->GetOutput(); // 获取读取的数据
|
|
|
} else if(filePath.endsWith(".vtk", Qt::CaseInsensitive)) {
|
|
|
// 使用传统VTK格式读取器
|
|
|
vtkNew<vtkUnstructuredGridReader> reader;
|
|
|
reader->SetFileName(filePath.toStdString().c_str()); // 设置输入文件名
|
|
|
reader->Update(); // 执行读取操作
|
|
|
grid = reader->GetOutput(); // 获取读取的数据
|
|
|
} else {
|
|
|
return false; // 不支持的文件扩展名
|
|
|
}
|
|
|
|
|
|
// 检查是否成功读取了有效的网格数据
|
|
|
if(grid && grid->GetNumberOfPoints() > 0) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false; // 读取失败
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::addTimeStep(double time, vtkSmartPointer<vtkDoubleArray> data)
|
|
|
{
|
|
|
if(!data || data->GetNumberOfTuples() == 0) return;
|
|
|
|
|
|
m_mapTimeStepDataP.insert(time, data);
|
|
|
}
|
|
|
|
|
|
vtkSmartPointer<vtkDoubleArray> nmDataAnalyzeManager::getTimeStepData(double time) const
|
|
|
{
|
|
|
if(m_mapTimeStepDataP.contains(time)) {
|
|
|
return m_mapTimeStepDataP.value(time);
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
QList<double> nmDataAnalyzeManager::getTimeStepKeys()
|
|
|
{
|
|
|
return m_mapTimeStepDataP.keys();
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::isTimeStepDataEmpty()
|
|
|
{
|
|
|
return m_mapTimeStepDataP.isEmpty();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 辅助函数:将整个时间步数据QMap保存到单个二进制文件。
|
|
|
* 文件中依次存储:QMap大小、每个时间键、每个vtkDoubleArray的大小、每个vtkDoubleArray的数据。
|
|
|
* @param filePath 文件保存的完整路径。
|
|
|
* @return 写入成功返回true,否则返回false。
|
|
|
*/
|
|
|
bool nmDataAnalyzeManager::writeTimeStepDataMapToBinaryFile(const QString& filePath)
|
|
|
{
|
|
|
QFile file(filePath);
|
|
|
|
|
|
// 使用 Truncate 模式确保如果文件已存在,会被清空并覆盖
|
|
|
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
|
|
qDebug() << QString("Failed to open file for writing (TimeStepDataMap): %1").arg(filePath);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream out(&file);
|
|
|
out.setVersion(QDataStream::Qt_4_8); // 当前项目Qt版本
|
|
|
|
|
|
// 1. 写入 QMap 的元素数量
|
|
|
out << (qint32)m_mapTimeStepDataP.size();
|
|
|
|
|
|
// 2. 遍历 QMap,依次写入每个时间键和对应的 vtkDoubleArray 数据
|
|
|
for(auto it = m_mapTimeStepDataP.constBegin(); it != m_mapTimeStepDataP.constEnd(); ++it) {
|
|
|
double time = it.key();
|
|
|
vtkSmartPointer<vtkDoubleArray> data = it.value();
|
|
|
|
|
|
// 写入时间键
|
|
|
out << time;
|
|
|
|
|
|
// 写入 vtkDoubleArray 的元素数量
|
|
|
qint64 numberOfTuples = data ? data->GetNumberOfTuples() : 0;
|
|
|
out << numberOfTuples;
|
|
|
|
|
|
// 写入 vtkDoubleArray 的数据
|
|
|
if(data && numberOfTuples > 0) {
|
|
|
for(qint64 i = 0; i < numberOfTuples; ++i) {
|
|
|
out << data->GetValue(i);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 辅助函数:从单个二进制文件加载整个时间步数据QMap。
|
|
|
* @param filePath 文件所在的完整路径。
|
|
|
* @return 加载成功返回true,否则返回false。
|
|
|
*/
|
|
|
bool nmDataAnalyzeManager::readTimeStepDataMapFromBinaryFile(const QString& filePath)
|
|
|
{
|
|
|
m_mapTimeStepDataP.clear(); // 清空现有数据,准备加载新数据
|
|
|
|
|
|
m_dScalarRangeP[0] = DBL_MAX; // 初始化最小值为最大浮点数
|
|
|
m_dScalarRangeP[1] = -DBL_MAX; // 初始化最大值为最小浮点数
|
|
|
|
|
|
QFile file(filePath);
|
|
|
|
|
|
if(!file.open(QIODevice::ReadOnly)) {
|
|
|
qDebug() << QString("Failed to open file for reading (TimeStepDataMap): %1").arg(filePath);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream in(&file);
|
|
|
in.setVersion(QDataStream::Qt_4_8); // 必须与写入时的版本一致
|
|
|
|
|
|
// 1. 读取 QMap 的元素数量
|
|
|
qint32 mapSize;
|
|
|
in >> mapSize;
|
|
|
|
|
|
if(mapSize < 0) { // 简单校验
|
|
|
qDebug() << QString("Invalid map size read from binary file: %1").arg(filePath);
|
|
|
file.close();
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 2. 循环读取每个时间键和对应的 vtkDoubleArray 数据
|
|
|
for(qint32 k = 0; k < mapSize; ++k) {
|
|
|
double time;
|
|
|
in >> time; // 读取时间键
|
|
|
|
|
|
qint64 numberOfTuples;
|
|
|
in >> numberOfTuples; // 读取 vtkDoubleArray 的元素数量
|
|
|
|
|
|
vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New();
|
|
|
data->SetNumberOfComponents(1); // 假设是单分量数组
|
|
|
data->SetNumberOfTuples(numberOfTuples); // 设置数组大小
|
|
|
|
|
|
// 设置数组名称
|
|
|
data->SetName("p");
|
|
|
|
|
|
if(numberOfTuples > 0) {
|
|
|
double currentMin = DBL_MAX;
|
|
|
double currentMax = -DBL_MAX;
|
|
|
|
|
|
for(qint64 i = 0; i < numberOfTuples; ++i) {
|
|
|
double value;
|
|
|
in >> value;
|
|
|
data->SetValue(i, value);
|
|
|
|
|
|
// 更新当前时间步的范围
|
|
|
currentMin = qMin(currentMin, value);
|
|
|
currentMax = qMax(currentMax, value);
|
|
|
}
|
|
|
|
|
|
// 更新全局范围
|
|
|
m_dScalarRangeP[0] = qMin(m_dScalarRangeP[0], currentMin);
|
|
|
m_dScalarRangeP[1] = qMax(m_dScalarRangeP[1], currentMax);
|
|
|
}
|
|
|
|
|
|
m_mapTimeStepDataP.insert(time, data);
|
|
|
}
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::saveWellHistoryData(QString sDir, nmDataWellBase* pWellData)
|
|
|
{
|
|
|
Q_ASSERT(nullptr != pWellData);
|
|
|
if(nullptr == pWellData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 构建文件路径,文件名为:[WellName]_History.bin
|
|
|
QString wellName = pWellData->getWellName();
|
|
|
if(wellName.isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
|
QString filePath = sDir + "/" + wellName + "_History.bin";
|
|
|
|
|
|
QFile file(filePath);
|
|
|
if(!file.open(QIODevice::WriteOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream out(&file);
|
|
|
out.setVersion(QDataStream::Qt_4_8);
|
|
|
|
|
|
// 只写入历史数据
|
|
|
out << pWellData->getHistoryPressure();
|
|
|
out << pWellData->getHistoryLogLog();
|
|
|
out << pWellData->getHistorySemiLog();
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::loadWellHistoryData(QString sDir, nmDataWellBase* pWellData)
|
|
|
{
|
|
|
Q_ASSERT(nullptr != pWellData);
|
|
|
|
|
|
if(nullptr == pWellData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString sWellName = pWellData->getWellName();
|
|
|
if(sWellName.isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 文件名为:[WellName]_History.bin
|
|
|
QString filePath = sDir + "/" + sWellName + "_History.bin";
|
|
|
|
|
|
QFile file(filePath);
|
|
|
if(!file.open(QIODevice::ReadOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream in(&file);
|
|
|
in.setVersion(QDataStream::Qt_4_8);
|
|
|
|
|
|
// 只需要读取历史数据
|
|
|
QVector<QVector<double>> historyPressureData;
|
|
|
QVector<QVector<double>> historyLoglogData;
|
|
|
QVector<QVector<double>> historySemiLogData;
|
|
|
|
|
|
// 只读取历史数据
|
|
|
in >> historyPressureData;
|
|
|
in >> historyLoglogData;
|
|
|
in >> historySemiLogData;
|
|
|
|
|
|
pWellData->setHistoryPressure(historyPressureData);
|
|
|
pWellData->setHistoryLogLog(historyLoglogData);
|
|
|
pWellData->setHistorySemiLog(historySemiLogData);
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::saveWellCalRstData(QString sDir, nmDataWellBase* pWellData)
|
|
|
{
|
|
|
Q_ASSERT(nullptr != pWellData);
|
|
|
|
|
|
if(nullptr == pWellData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 构建文件路径,为每口井的结果创建一个独立文件
|
|
|
QString wellName = pWellData->getWellName();
|
|
|
|
|
|
if(wellName.isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString filePath = sDir + "/" + wellName + "_Results.bin"; //
|
|
|
|
|
|
QFile file(filePath);
|
|
|
|
|
|
if(!file.open(QIODevice::WriteOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream out(&file);
|
|
|
out.setVersion(QDataStream::Qt_4_8); // 设置数据流版本,保证未来兼容性
|
|
|
|
|
|
// 写入数据
|
|
|
// QDataStream 可以直接序列化 QVector<QVector<double>>
|
|
|
out << pWellData->getResultPressure();
|
|
|
out << pWellData->getResultLogLog();
|
|
|
out << pWellData->getResultSemiLog();
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::loadWellCalRstData(QString sDir, nmDataWellBase* pWellData)
|
|
|
{
|
|
|
Q_ASSERT(nullptr != pWellData);
|
|
|
|
|
|
if(nullptr == pWellData) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString sWellName = pWellData->getWellName();
|
|
|
|
|
|
if(sWellName.isEmpty()) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QString filePath = sDir + "/" + sWellName + "_Results.bin";
|
|
|
|
|
|
QFile file(filePath);
|
|
|
|
|
|
if(!file.open(QIODevice::ReadOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream in(&file);
|
|
|
in.setVersion(QDataStream::Qt_4_8); // 确保与写入时版本一致
|
|
|
|
|
|
// 读取数据到 pWellData 的成员变量
|
|
|
QVector<QVector<double>> pressureData;
|
|
|
QVector<QVector<double>> loglogData;
|
|
|
QVector<QVector<double>> semiLogData;
|
|
|
|
|
|
in >> pressureData;
|
|
|
in >> loglogData;
|
|
|
in >> semiLogData;
|
|
|
|
|
|
pWellData->setResultPressure(pressureData);
|
|
|
pWellData->setResultLogLog(loglogData);
|
|
|
pWellData->setResultSemiLog(semiLogData);
|
|
|
|
|
|
//// 存储当前井名称和二维位置到映射
|
|
|
//QPointF ptWellCoords(pWellData->getX().getValue().toDouble(), pWellData->getY().getValue().toDouble());
|
|
|
//addWellLocation(sWellName, ptWellCoords);
|
|
|
|
|
|
// 将当前井添加到参与计算井列表中
|
|
|
this->appendCalculationWell(QPair<NM_WELL_MODEL, QString>(pWellData->getWellType(), pWellData->getWellName()));
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::getScalarRangeP(double range[2]) const
|
|
|
{
|
|
|
range[0] = m_dScalarRangeP[0];
|
|
|
range[1] = m_dScalarRangeP[1];
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::setScalarRangeP(double min, double max)
|
|
|
{
|
|
|
m_dScalarRangeP[0] = min;
|
|
|
m_dScalarRangeP[1] = max;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::addWellLocation(const QString& wellName, const QPointF& location)
|
|
|
{
|
|
|
m_mapWellLocations.insert(wellName, location);
|
|
|
}
|
|
|
|
|
|
QPointF nmDataAnalyzeManager::getWellLocation(const QString& wellName) const
|
|
|
{
|
|
|
return m_mapWellLocations.value(wellName, QPointF()); // 如果未找到,返回默认的QPointF(0,0)
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::removeWellLocation(const QString& wellName)
|
|
|
{
|
|
|
return m_mapWellLocations.remove(wellName) > 0;
|
|
|
}
|
|
|
|
|
|
void nmDataAnalyzeManager::clearWellLocations()
|
|
|
{
|
|
|
m_mapWellLocations.clear();
|
|
|
}
|
|
|
|
|
|
QMap<QString, QPointF> nmDataAnalyzeManager::getAllWellLocations() const
|
|
|
{
|
|
|
return m_mapWellLocations;
|
|
|
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::saveWellLocations(const QString& filePath)
|
|
|
{
|
|
|
QFile file(filePath);
|
|
|
|
|
|
if(!file.open(QIODevice::WriteOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream out(&file);
|
|
|
out.setVersion(QDataStream::Qt_4_8);
|
|
|
|
|
|
qDebug() << "Map size before writting:" << m_mapWellLocations.size();
|
|
|
|
|
|
out << m_mapWellLocations;
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool nmDataAnalyzeManager::loadWellLocations(const QString& filePath)
|
|
|
{
|
|
|
QFile file(filePath);
|
|
|
|
|
|
if(!file.open(QIODevice::ReadOnly)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
QDataStream in(&file);
|
|
|
in.setVersion(QDataStream::Qt_4_8);
|
|
|
|
|
|
in >> m_mapWellLocations;
|
|
|
|
|
|
qDebug() << "Map size after reading:" << m_mapWellLocations.size();
|
|
|
|
|
|
file.close();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
//void nmDataAnalyzeManager::createTimeStep()
|
|
|
//{
|
|
|
// if (m_pTimeStep != nullptr)
|
|
|
// {
|
|
|
// delete m_pTimeStep;
|
|
|
// m_pTimeStep = nullptr;
|
|
|
// }
|
|
|
//
|
|
|
// // 获取当前井下流量的时间范围
|
|
|
// QVector<QPointF> vecFlowPoints;
|
|
|
// if (m_pCurDataWell){
|
|
|
// vecFlowPoints = m_pCurDataWell->getFlowPoints();
|
|
|
// }
|
|
|
//
|
|
|
// // 计算起始时间和终止时间
|
|
|
// // 检查坐标数组是否为空,以防止访问越界
|
|
|
// if (!vecFlowPoints.isEmpty()) {
|
|
|
// // 起始时间就是第一个点的横坐标
|
|
|
// double dStartTime = vecFlowPoints.first().x();
|
|
|
//
|
|
|
// // 终止时间是所有点的横坐标之和
|
|
|
// double dEndTime = 0.0;
|
|
|
// foreach (const QPointF& point, vecFlowPoints) {
|
|
|
// dEndTime += point.x();
|
|
|
// }
|
|
|
//
|
|
|
// m_pTimeStep = new nmDataTimeStepSetting(dStartTime,dEndTime);
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
nmDataTimeStepSetting* nmDataAnalyzeManager::createTimeStep()
|
|
|
{
|
|
|
if (m_pTimeStep != nullptr)
|
|
|
{
|
|
|
delete m_pTimeStep;
|
|
|
m_pTimeStep = nullptr;
|
|
|
}
|
|
|
|
|
|
m_pTimeStep = new nmDataTimeStepSetting;
|
|
|
return m_pTimeStep;
|
|
|
}
|
|
|
|
|
|
nmDataTimeStepSetting* nmDataAnalyzeManager::getTimeStep()
|
|
|
{
|
|
|
return m_pTimeStep;
|
|
|
}
|
|
|
|
|
|
// 获取许可证路径
|
|
|
void nmDataAnalyzeManager::setLicensePath(const QString& licensePath)
|
|
|
{
|
|
|
m_licensePath = licensePath;
|
|
|
}
|
|
|
|
|
|
QString nmDataAnalyzeManager::getLicensePath() const
|
|
|
{
|
|
|
return m_licensePath;
|
|
|
}
|