#include "nmPebiExampleCalculator.h" #include "pch.h" #include "nmDataAnalyzeManager.h" #include "nmDataPvtParaForPebi.h" #include #include #include #include #include #include #include #include #include #include #include #include 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(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& pressure, const QVector& volumeFactor, const QVector& compressibility, const QVector& 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& 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(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(dllPath.utf16())); if(dll == NULL) { error = QString::fromLocal8Bit("加载PEBI求解器失败,错误码:%1").arg(GetLastError()); return false; } HX_NWTM_GRID_Func gridFunction = reinterpret_cast( GetProcAddress(dll, "HX_NWTM_GRID")); HX_NWTM_MODEL_Func modelFunction = reinterpret_cast( 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)); }