You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWnd/nmPebiExampleCalculator.cpp

701 lines
25 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmPebiExampleCalculator.h"
#include "pch.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataPvtParaForPebi.h"
#include <QApplication>
#include <QCoreApplication>
#include <QDateTime>
#include <QDesktopServices>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QInputDialog>
#include <QMessageBox>
#include <QStringList>
#include <QTextStream>
#include <exception>
namespace
{
typedef void (*HX_NWTM_GRID_Func)(HX_NWTM_GRID_OUTPUT1&,
HX_NWTM_GRID_OUTPUT2&,
const HX_NWTM_GRID_INPUT&,
std::string);
typedef void (*HX_NWTM_MODEL_Func)(HX_NWTM_MODEL_OUTPUT&,
const HX_NWTM_MODEL_INPUT&,
std::string);
QStringList exampleNames()
{
QStringList names;
names << QString::fromLocal8Bit("1. 油单相常数PVT一口多段压裂水平井")
<< QString::fromLocal8Bit("2. 油单相常数PVT五口混合井")
<< QString::fromLocal8Bit("3. 油单相常数PVT五十口直井")
<< QString::fromLocal8Bit("4. 油单相变化PVT一口多段压裂水平井")
<< QString::fromLocal8Bit("5. 水单相常数PVT一口多段压裂水平井")
<< QString::fromLocal8Bit("6. 水单相变化PVT一口多段压裂水平井")
<< QString::fromLocal8Bit("7. 气单相变化PVT一口多段压裂水平井")
<< QString::fromLocal8Bit("8. 气单相拟压力(一口多段压裂水平井)")
<< QString::fromLocal8Bit("9. 油水两相(一口多段压裂水平井)");
return names;
}
dVec1 makePoint(double x, double y, double value)
{
dVec1 point(3);
point[0] = x;
point[1] = y;
point[2] = value;
return point;
}
dVec1 makeLine(double x0, double y0, double x1, double y1)
{
dVec1 line(4);
line[0] = x0;
line[1] = y0;
line[2] = x1;
line[3] = y1;
return line;
}
dVec1 makeFracture(double x0, double y0, double x1, double y1,
double halfWidth, double conductivity)
{
dVec1 fracture(6);
fracture[0] = x0;
fracture[1] = y0;
fracture[2] = x1;
fracture[3] = y1;
fracture[4] = halfWidth;
fracture[5] = conductivity;
return fracture;
}
void initializeGridInput(HX_NWTM_GRID_INPUT& input, double halfSize)
{
// 构造函数带有默认井数据,算例计算前必须全部清空后重新组装。
input.Boundary.clear();
input.VerticalWell.clear();
input.HorizontalWell.clear();
input.FractureVerticalWell.clear();
input.MultistageFracturedHorizontalWell.clear();
input.InclinedWell.clear();
input.Fault.clear();
input.Boundary.push_back(makeLine(-halfSize, -halfSize, -halfSize, halfSize));
input.Boundary.push_back(makeLine(-halfSize, halfSize, halfSize, halfSize));
input.Boundary.push_back(makeLine(halfSize, halfSize, halfSize, -halfSize));
input.Boundary.push_back(makeLine(halfSize, -halfSize, -halfSize, -halfSize));
input.GridControl = 150.0;
input.D = 2;
}
void setupSingleWellGrid(HX_NWTM_GRID_INPUT& input)
{
initializeGridInput(input, 1500.0);
// 使用main.cpp中单口多段压裂水平井的五条裂缝参数。
dVec2 fractures;
fractures.push_back(makeFracture(-400.0, -200.0, -400.0, 200.0, 0.05, 100.0));
fractures.push_back(makeFracture(-200.0, -200.0, -200.0, 200.0, 0.05, 100.0));
fractures.push_back(makeFracture(0.0, -200.0, 0.0, 200.0, 0.05, 100.0));
fractures.push_back(makeFracture(200.0, -200.0, 200.0, 200.0, 0.05, 100.0));
fractures.push_back(makeFracture(400.0, -200.0, 400.0, 200.0, 0.05, 100.0));
input.MultistageFracturedHorizontalWell.push_back(fractures);
}
void setupFiveWellGrid(HX_NWTM_GRID_INPUT& input)
{
initializeGridInput(input, 1500.0);
input.VerticalWell.push_back(makePoint(0.0, 0.0, 0.1));
input.VerticalWell.push_back(makePoint(1000.0, 1000.0, 0.1));
input.VerticalWell.push_back(makePoint(-1000.0, -1000.0, 0.1));
input.FractureVerticalWell.push_back(
makeFracture(-200.0, -200.0, 200.0, -200.0, 0.05, 0.0));
dVec2 fractures;
fractures.push_back(makeFracture(-600.0, 600.0, -400.0, 600.0, 0.1, 0.0));
fractures.push_back(makeFracture(-600.0, 400.0, -400.0, 400.0, 0.1, 0.0));
fractures.push_back(makeFracture(-600.0, 200.0, -400.0, 200.0, 0.1, 0.0));
input.MultistageFracturedHorizontalWell.push_back(fractures);
input.Fault.push_back(makeLine(-500.0, 1000.0, 500.0, 500.0));
}
void setupFiftyWellGrid(HX_NWTM_GRID_INPUT& input)
{
initializeGridInput(input, 1000.0);
static const double wells[50][2] = {
{766.32207856101854, -408.4253100821785},
{-359.11086885711029, -242.17185988435722},
{-396.28113134064483, 618.18974488936828},
{-844.38929572547772, 859.25724767620932},
{-631.69279373636357, 620.26791301684102},
{-858.84439780240791, 333.48071142559911},
{-844.38929572547772, 609.87707237947734},
{-639.95285206603785, 867.56992018610026},
{764.25706397860017, -190.2176566975379},
{-410.73623341757479, 867.56992018610026},
{-121.63419187897284, 98.647713021176514},
{-152.6094106152517, 364.65323333769061},
{-152.6094106152517, 620.26791301684102},
{-361.17588343952877, 102.80404927612199},
{-844.38929572547772, -231.78101924699342},
{-156.73943978008879, 875.88259269599121},
{138.55764550576896, 890.42976958830059},
{446.24481828613784, -439.59783199426988},
{-846.45431030789632, 61.240686726666581},
{-142.28433770315883, -223.46834673710214},
{-375.63098551645885, -472.84852203383423},
{-602.78258958250342, 354.2623927003267},
{431.78971620920788, 624.42424927178672},
{-834.06422281338484, -474.92669016130685},
{-836.12923739580344, -747.16671486023938},
{813.81741395664631, -693.13434354594744},
{458.63490578064966, -718.07236107562062},
{409.07455580260353, 873.80442456851847},
{124.10254342883854, -454.14500888657915},
{138.55764550576896, 96.569544893703778},
{101.38738302223419, 611.95524050694985},
{-373.56597093404037, 360.49689708274514},
{-604.8476041649219, 79.944199873921661},
{-611.0426479121777, -219.31201048215667},
{448.30983286855667, -202.68666546237455},
{735.34685982474002, 880.03892895093713},
{107.58242676948976, -724.30686545803894},
{150.94773300028032, -196.45216107995623},
{762.19204939618135, 113.19488991348589},
{-125.76422104381015, -470.77035390636138},
{452.43986203339387, 366.73140146516357},
{-350.85081052743578, -751.32305111518485},
{122.03752884641995, 354.2623927003267},
{-608.9776333297591, -447.91050450416094},
{407.0095412201847, 113.19488991348589},
{731.21683065990283, 636.89325803662314},
{-121.63419187897284, -724.30686545803894},
{289.3037100223255, -925.88917382289742},
{737.41187440715862, 366.73140146516357},
{-611.0426479121777, -730.54136984045726}
};
for(int i = 0; i < 50; ++i) {
input.VerticalWell.push_back(makePoint(wells[i][0], wells[i][1], 0.108));
}
}
void setupGridForExample(int exampleIndex, HX_NWTM_GRID_INPUT& input)
{
if(exampleIndex == 2) {
setupFiveWellGrid(input);
} else if(exampleIndex == 3) {
setupFiftyWellGrid(input);
} else {
setupSingleWellGrid(input);
}
}
void resetWellData(HX_NWTM_MODEL_INPUT& input, int wellCount)
{
// 所有相态统一按实际井数重建外层数组,避免沿用接口构造函数中的五井默认值。
input.Rate.t.assign(wellCount, dVec1());
input.Rate.qo.assign(wellCount, dVec1());
input.Rate.qg.assign(wellCount, dVec1());
input.Rate.qw.assign(wellCount, dVec1());
input.Pressure.t.clear();
input.Pressure.p.clear();
input.CS.C.assign(wellCount, 0.0);
input.CS.S.assign(wellCount, 0.0);
}
void resizeRateStep(HX_NWTM_MODEL_INPUT& input, int wellIndex, int stepCount)
{
input.Rate.t[wellIndex].assign(stepCount, 0.0);
input.Rate.qo[wellIndex].assign(stepCount, 0.0);
input.Rate.qg[wellIndex].assign(stepCount, 0.0);
input.Rate.qw[wellIndex].assign(stepCount, 0.0);
}
void setPressureAxis(HX_NWTM_MODEL_INPUT& input)
{
input.PVT.p.assign(200, 0.0);
for(int i = 0; i < 200; ++i) {
input.PVT.p[i] = i + 1.0;
}
}
void setBase(HX_NWTM_MODEL_INPUT& input, int cellCount,
double permeability, double porosity, double thickness)
{
input.Base.k.assign(cellCount, permeability);
input.Base.phi.assign(cellCount, porosity);
input.Base.h.assign(cellCount, thickness);
input.Base.d = 1.05;
input.Base.dt_Min = 0.0025;
input.Base.dt_Max = 12.5;
}
void setupExample1(HX_NWTM_MODEL_INPUT& input, int cellCount)
{
input.T = 1;
resetWellData(input, 1);
resizeRateStep(input, 0, 2);
input.Rate.t[0][0] = 2000.0;
input.Rate.t[0][1] = 500.0;
input.Rate.qo[0][0] = 20.0;
input.PVT.Bo.assign(200, 1.2);
input.PVT.miuo.assign(200, 0.5);
setPressureAxis(input);
input.Base.Pi = 40.0;
input.Base.Cti = 1e-3;
setBase(input, cellCount, 0.001, 0.1, 10.0);
}
void setupExample2(HX_NWTM_MODEL_INPUT& input, int cellCount)
{
input.T = 1;
resetWellData(input, 5);
resizeRateStep(input, 0, 2);
input.Rate.t[0][0] = 2000.0;
input.Rate.t[0][1] = 500.0;
input.Rate.qo[0][0] = 10.0;
resizeRateStep(input, 1, 0);
resizeRateStep(input, 2, 3);
input.Rate.t[2][0] = 1000.0;
input.Rate.t[2][1] = 1000.0;
input.Rate.t[2][2] = 500.0;
input.Rate.qo[2][0] = 30.0;
input.Rate.qo[2][1] = 40.0;
input.Rate.qo[2][2] = 20.0;
resizeRateStep(input, 3, 2);
input.Rate.t[3][0] = 1500.0;
input.Rate.t[3][1] = 1000.0;
input.Rate.qo[3][0] = 30.0;
input.Rate.qo[3][1] = 20.0;
resizeRateStep(input, 4, 2);
input.Rate.t[4][0] = 1000.0;
input.Rate.t[4][1] = 1500.0;
input.Rate.qo[4][0] = -50.0;
input.Rate.qo[4][1] = -60.0;
input.CS.C.assign(5, 0.1);
input.CS.S.assign(5, 0.1);
setPressureAxis(input);
input.PVT.Bo.assign(200, 1.2);
input.PVT.miuo.assign(200, 0.5);
input.Base.Pi = 40.0;
input.Base.Cti = 1e-3;
setBase(input, cellCount, 0.001, 0.1, 10.0);
}
void setupExample3(HX_NWTM_MODEL_INPUT& input, int cellCount)
{
input.T = 1;
resetWellData(input, 50);
for(int wellIndex = 0; wellIndex < 50; ++wellIndex) {
resizeRateStep(input, wellIndex, 5);
input.Rate.t[wellIndex][0] = 12.0;
input.Rate.t[wellIndex][1] = 12.0;
input.Rate.t[wellIndex][2] = 12.0;
input.Rate.t[wellIndex][3] = 48.0;
input.Rate.t[wellIndex][4] = 72.0;
input.Rate.qo[wellIndex][0] = 158.98699999999999;
input.Rate.qo[wellIndex][1] = 190.785;
input.Rate.qo[wellIndex][2] = 222.58199999999999;
input.Rate.qo[wellIndex][3] = 238.48099999999999;
}
input.CS.C.assign(50, 0.01);
input.CS.S.assign(50, 0.0);
setPressureAxis(input);
input.PVT.Bo.assign(200, 1.07);
input.PVT.miuo.assign(200, 0.79);
input.Base.Pi = 40.0;
input.Base.Cti = 0.43e-3;
setBase(input, cellCount, 0.025, 0.1, 10.0);
}
void setupSinglePhaseExample(HX_NWTM_MODEL_INPUT& input, int exampleIndex,
int cellCount)
{
resetWellData(input, 1);
resizeRateStep(input, 0, 2);
input.Rate.t[0][0] = 2000.0;
input.Rate.t[0][1] = 500.0;
input.CS.C[0] = 0.1;
input.CS.S[0] = 0.1;
if(exampleIndex == 4) {
input.T = 2;
input.Rate.qo[0][0] = 10.0;
} else if(exampleIndex == 5 || exampleIndex == 6) {
input.T = exampleIndex == 5 ? 3 : 4;
input.Rate.qw[0][0] = -10.0;
if(exampleIndex == 5) {
setPressureAxis(input);
input.PVT.Bw.assign(200, 1.05);
input.PVT.miuw.assign(200, 0.8);
}
} else {
input.T = exampleIndex == 7 ? 5 : 6;
input.Rate.qg[0][0] = 50000.0;
}
input.Base.Pi = 40.0;
input.Base.Cf = 1e-3;
if(exampleIndex == 5) {
input.Base.Cti = 1e-3;
}
setBase(input, cellCount, 0.001, 0.1, 10.0);
}
void setupExample9(HX_NWTM_MODEL_INPUT& input, int cellCount)
{
input.T = 8;
resetWellData(input, 1);
resizeRateStep(input, 0, 2);
input.Rate.t[0][0] = 2000.0;
input.Rate.t[0][1] = 500.0;
input.Rate.qo[0][0] = 20.0;
input.CS.C[0] = 0.1;
input.CS.S[0] = 0.1;
input.Base.Pi = 40.0;
input.Base.Cf = 1e-4;
input.Base.Swi = 0.2;
setBase(input, cellCount, 0.001, 0.1, 10.0);
}
void setupModelForExample(int exampleIndex, const HX_NWTM_GRID_OUTPUT2& grid,
HX_NWTM_MODEL_INPUT& input)
{
const int cellCount = static_cast<int>(grid.Trinodexy.size());
if(exampleIndex == 1) {
setupExample1(input, cellCount);
} else if(exampleIndex == 2) {
setupExample2(input, cellCount);
} else if(exampleIndex == 3) {
setupExample3(input, cellCount);
} else if(exampleIndex >= 4 && exampleIndex <= 8) {
setupSinglePhaseExample(input, exampleIndex, cellCount);
} else {
setupExample9(input, cellCount);
}
}
bool hasPhasePvt(const QVector<double>& pressure,
const QVector<double>& volumeFactor,
const QVector<double>& compressibility,
const QVector<double>& viscosity)
{
return !pressure.isEmpty()
&& pressure.size() == volumeFactor.size()
&& pressure.size() == compressibility.size()
&& pressure.size() == viscosity.size();
}
bool loadFrameworkPvt(int exampleIndex,
HX_NWTM_MODEL_INPUT& input,
QString& error)
{
// 常数PVT算例继续使用main.cpp中的固定数据。
if(exampleIndex == 1 || exampleIndex == 2
|| exampleIndex == 3 || exampleIndex == 5) {
return true;
}
nmDataAnalyzeManager* dataManager = nmDataAnalyzeManager::getCurrentInstance();
nmDataPvtParaForPebi* pvt = dataManager == NULL
? NULL : dataManager->getPebiPvtPara();
if(pvt == NULL) {
error = QString::fromLocal8Bit("当前分析中没有可用的PVT数据。");
return false;
}
const QVector<double>& pressure = pvt->getPressure();
if(exampleIndex == 4) {
if(!hasPhasePvt(pressure, pvt->getBo(), pvt->getCo(), pvt->getMiuo())) {
error = QString::fromLocal8Bit("当前分析中的油相变化PVT数据不完整。");
return false;
}
input.PVT.p = pressure.toStdVector();
input.PVT.Bo = pvt->getBo().toStdVector();
input.PVT.Co = pvt->getCo().toStdVector();
input.PVT.miuo = pvt->getMiuo().toStdVector();
} else if(exampleIndex == 6) {
if(!hasPhasePvt(pressure, pvt->getBw(), pvt->getCw(), pvt->getMiuw())) {
error = QString::fromLocal8Bit("当前分析中的水相变化PVT数据不完整。");
return false;
}
input.PVT.p = pressure.toStdVector();
input.PVT.Bw = pvt->getBw().toStdVector();
input.PVT.Cw = pvt->getCw().toStdVector();
input.PVT.miuw = pvt->getMiuw().toStdVector();
} else if(exampleIndex == 7 || exampleIndex == 8) {
if(!hasPhasePvt(pressure, pvt->getBg(), pvt->getCg(), pvt->getMiug())) {
error = QString::fromLocal8Bit("当前分析中的气相变化PVT数据不完整。");
return false;
}
input.PVT.p = pressure.toStdVector();
input.PVT.Bg = pvt->getBg().toStdVector();
input.PVT.Cg = pvt->getCg().toStdVector();
input.PVT.miug = pvt->getMiug().toStdVector();
} else if(exampleIndex == 9) {
const bool oilWaterPvtValid = !pressure.isEmpty()
&& pressure.size() == pvt->getBo().size()
&& pressure.size() == pvt->getMiuo().size()
&& pressure.size() == pvt->getBw().size()
&& pressure.size() == pvt->getMiuw().size();
const bool relativePermeabilityValid = !pvt->getSo().isEmpty()
&& pvt->getSo().size() == pvt->getKro().size()
&& pvt->getSo().size() == pvt->getKrw().size();
if(!oilWaterPvtValid || !relativePermeabilityValid) {
error = QString::fromLocal8Bit("当前分析中的油水两相PVT或相渗数据不完整。");
return false;
}
input.PVT.p = pressure.toStdVector();
input.PVT.Bo = pvt->getBo().toStdVector();
input.PVT.miuo = pvt->getMiuo().toStdVector();
input.PVT.Bw = pvt->getBw().toStdVector();
input.PVT.miuw = pvt->getMiuw().toStdVector();
input.PVT.So = pvt->getSo().toStdVector();
input.PVT.Kro = pvt->getKro().toStdVector();
input.PVT.Krw = pvt->getKrw().toStdVector();
}
return true;
}
QString numberText(double value)
{
return QString::number(value, 'g', 16);
}
bool writePressureFile(const QString& filePath,
const HX_NWTM_MODEL_OUTPUT& output,
size_t wellIndex,
QString& error)
{
QFile file(filePath);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
error = QString::fromLocal8Bit("无法创建压力文件:%1").arg(filePath);
return false;
}
QTextStream stream(&file);
stream.setCodec("UTF-8");
for(size_t timeIndex = 0; timeIndex < output.t.size(); ++timeIndex) {
stream << numberText(output.t[timeIndex]) << " ";
if(timeIndex < output.pw[wellIndex].size()) {
stream << numberText(output.pw[wellIndex][timeIndex]);
}
stream << "\n";
}
return true;
}
bool writeFlowFile(const QString& filePath,
const HX_NWTM_MODEL_INPUT& input,
int exampleIndex,
size_t wellIndex,
QString& error)
{
QFile file(filePath);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
error = QString::fromLocal8Bit("无法创建流量文件:%1").arg(filePath);
return false;
}
QTextStream stream(&file);
stream.setCodec("UTF-8");
stream << "0 0\n";
// 按算例相态选择实际使用的油、气或水流量数组。
const dVec1* rates = &input.Rate.qo[wellIndex];
if(exampleIndex == 5 || exampleIndex == 6) {
rates = &input.Rate.qw[wellIndex];
} else if(exampleIndex == 7 || exampleIndex == 8) {
rates = &input.Rate.qg[wellIndex];
}
for(size_t stepIndex = 0; stepIndex < input.Rate.t[wellIndex].size(); ++stepIndex) {
stream << numberText(input.Rate.t[wellIndex][stepIndex]) << " ";
if(stepIndex < rates->size()) {
stream << numberText((*rates)[stepIndex]);
}
stream << "\n";
}
return true;
}
bool saveResults(int exampleIndex,
const HX_NWTM_MODEL_INPUT& input,
const HX_NWTM_MODEL_OUTPUT& output,
int& savedWellCount,
QString& error)
{
QString desktopPath = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
if(desktopPath.isEmpty()) {
desktopPath = QDir::home().filePath("Desktop");
}
if(!QDir(desktopPath).exists()) {
error = QString::fromLocal8Bit("桌面目录不存在:%1").arg(desktopPath);
return false;
}
if(output.pw.size() != input.Rate.t.size()) {
error = QString::fromLocal8Bit("求解器返回的压力井数与输入井数不一致。");
return false;
}
const QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
QStringList createdFiles;
savedWellCount = static_cast<int>(input.Rate.t.size());
for(int wellIndex = 0; wellIndex < savedWellCount; ++wellIndex) {
const QString pressurePath = QDir(desktopPath).filePath(
QString("PEBI_Model_%1_Well_%2_Pressure_%3.txt")
.arg(exampleIndex).arg(wellIndex + 1).arg(timestamp));
const QString flowPath = QDir(desktopPath).filePath(
QString("PEBI_Model_%1_Well_%2_Flow_%3.txt")
.arg(exampleIndex).arg(wellIndex + 1).arg(timestamp));
if(!writePressureFile(pressurePath, output, wellIndex, error)) {
break;
}
createdFiles.append(pressurePath);
if(!writeFlowFile(flowPath, input, exampleIndex, wellIndex, error)) {
break;
}
createdFiles.append(flowPath);
}
if(!error.isEmpty()) {
for(int fileIndex = 0; fileIndex < createdFiles.size(); ++fileIndex) {
QFile::remove(createdFiles[fileIndex]);
}
savedWellCount = 0;
return false;
}
return true;
}
bool calculateExample(int exampleIndex,
int& savedWellCount,
QString& error)
{
const QString dllPath = QDir(QCoreApplication::applicationDirPath()).filePath("HX_NWTM.dll");
if(!QFileInfo(dllPath).exists()) {
error = QString::fromLocal8Bit("未找到PEBI求解器%1").arg(dllPath);
return false;
}
HMODULE dll = LoadLibraryW(reinterpret_cast<const wchar_t*>(dllPath.utf16()));
if(dll == NULL) {
error = QString::fromLocal8Bit("加载PEBI求解器失败错误码%1").arg(GetLastError());
return false;
}
HX_NWTM_GRID_Func gridFunction = reinterpret_cast<HX_NWTM_GRID_Func>(
GetProcAddress(dll, "HX_NWTM_GRID"));
HX_NWTM_MODEL_Func modelFunction = reinterpret_cast<HX_NWTM_MODEL_Func>(
GetProcAddress(dll, "HX_NWTM_MODEL"));
if(gridFunction == NULL || modelFunction == NULL) {
error = QString::fromLocal8Bit("PEBI求解器缺少网格或模型计算接口。");
FreeLibrary(dll);
return false;
}
const QString licensePath = QDir::cleanPath(
QDir(QCoreApplication::applicationDirPath()).filePath("../Res/license/HXNWTM_license.dat"));
if(!QFileInfo(licensePath).exists()) {
error = QString::fromLocal8Bit("未找到PEBI许可证%1").arg(licensePath);
FreeLibrary(dll);
return false;
}
try {
// 必须先由所选算例的井和边界生成网格,再用网格输出构造模型输入。
HX_NWTM_GRID_INPUT gridInput;
HX_NWTM_GRID_OUTPUT1 gridOutput1;
HX_NWTM_GRID_OUTPUT2 gridOutput2;
setupGridForExample(exampleIndex, gridInput);
gridFunction(gridOutput1, gridOutput2, gridInput, licensePath.toStdString());
if(gridOutput2.Trinodexy.empty()) {
error = QString::fromLocal8Bit("PEBI网格生成失败未返回有效网格单元。");
FreeLibrary(dll);
return false;
}
HX_NWTM_MODEL_INPUT modelInput(gridOutput2);
HX_NWTM_MODEL_OUTPUT modelOutput;
setupModelForExample(exampleIndex, gridOutput2, modelInput);
if(!loadFrameworkPvt(exampleIndex, modelInput, error)) {
FreeLibrary(dll);
return false;
}
modelFunction(modelOutput, modelInput, licensePath.toStdString());
if(modelOutput.t.empty() || modelOutput.pw.empty()) {
error = QString::fromLocal8Bit("PEBI模型计算失败未返回压力数据。");
FreeLibrary(dll);
return false;
}
const bool saved = saveResults(exampleIndex, modelInput, modelOutput,
savedWellCount, error);
FreeLibrary(dll);
return saved;
} catch(const std::exception& exception) {
error = QString::fromLocal8Bit("PEBI算例计算异常%1")
.arg(QString::fromLocal8Bit(exception.what()));
} catch(...) {
error = QString::fromLocal8Bit("PEBI算例计算发生未知异常。");
}
FreeLibrary(dll);
return false;
}
}
nmPebiExampleCalculator::nmPebiExampleCalculator(QWidget* pParent)
: m_pParent(pParent)
{
}
void nmPebiExampleCalculator::run()
{
bool accepted = false;
const QString selected = QInputDialog::getItem(
m_pParent,
QString::fromLocal8Bit("PEBI算例计算"),
QString::fromLocal8Bit("请选择计算模型:"),
exampleNames(), 0, false, &accepted);
if(!accepted || selected.isEmpty()) {
return;
}
const int exampleIndex = exampleNames().indexOf(selected) + 1;
if(exampleIndex < 1 || exampleIndex > 9) {
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
int savedWellCount = 0;
QString error;
const bool success = calculateExample(exampleIndex, savedWellCount, error);
QApplication::restoreOverrideCursor();
if(!success) {
QMessageBox::warning(m_pParent, QString::fromLocal8Bit("PEBI算例计算"), error);
return;
}
QMessageBox::information(
m_pParent,
QString::fromLocal8Bit("PEBI算例计算"),
QString::fromLocal8Bit("计算完成,已按井保存到桌面,共%1口井、%2个文件。")
.arg(savedWellCount).arg(savedWellCount * 2));
}