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/nmSubWxs/nmWxAutomaticFitting.cpp

1135 lines
44 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 "nmWxAutomaticFitting.h"
#include "nmCalculationAutoFitPSO.h"
#include "nmWxAutomaticfittingStart.h"
#include "nmWxParameterProperty.h"
#include "nmDataAnalyzeManager.h"
#include <QApplication>
#include <QHeaderView>
#ifdef Q_OS_WIN
#include <windows.h>
#define DEBUG_UI(msg) OutputDebugStringA(QString("[UI] %1\n").arg(msg).toLocal8Bit().data())
#endif
nmWxAutomaticFitting::nmWxAutomaticFitting(QWidget *parent)
: QDialog(parent)
, m_autoFitterPSO(nullptr)
, m_autoFitterGA(nullptr)
, m_progressDialog(nullptr)
, m_progressTimer(nullptr)
, m_progressMonitor(nullptr)
, m_selectedAlgorithm(ALGORITHM_PSO) // 默认选择PSO算法
{
DEBUG_UI(QString("AutoFitting Constructor: this=0x%1").arg((quintptr)this, 0, 16));
// 加载已有井数据
QVector<nmDataWellBase*> listWellData = nmDataAnalyzeManager::getCurrentInstance()->getWellDataList();
// 遍历并分类井数据
foreach (nmDataWellBase* well, listWellData) {
if (auto vfWell = dynamic_cast<nmDataVerticalFracturedWell*>(well)) {
m_verticalFracturedWells.append(*vfWell);
}
else if (auto hfWell = dynamic_cast<nmDataHorizontalFracturedWell*>(well)) {
m_horizontalFracturedWells.append(*hfWell);
}
else if (auto vWell = dynamic_cast<nmDataVerticalWell*>(well)) {
m_verticalWells.append(*vWell);
}
else if (auto hWell = dynamic_cast<nmDataHorizontalWell*>(well)) {
m_horizontalWells.append(*hWell);
}
}
// 获取数据
reservoirData = nmDataAnalyzeManager::getCurrentInstance()->getReservoirDataCopy();
automaticFittingData = nmDataAnalyzeManager::getCurrentInstance()->getAutomaticFittingDataCopy();
setupUI();
setWindowTitle(tr("Automatic fitting"));
setModal(true);
resize(800, 480);
if(m_targetWellCombo->count() > 0) {
onWellSelected(0); // 默认选中第一口井
}
DEBUG_UI("AutoFitting Constructor completed");
}
nmWxAutomaticFitting::~nmWxAutomaticFitting()
{
DEBUG_UI(QString("AutoFitting Destructor: this=0x%1").arg((quintptr)this, 0, 16));
DEBUG_UI("AutoFitting destructor - starting cleanup");
// 停止定时器
if (m_progressTimer) {
m_progressTimer->stop();
}
// 断开所有连接,避免悬空指针
if (m_autoFitterPSO) {
disconnect(m_autoFitterPSO, nullptr, this, nullptr);
}
if (m_autoFitterGA) {
disconnect(m_autoFitterGA, nullptr, this, nullptr);
}
DEBUG_UI("AutoFitting destructor - completed");
}
void nmWxAutomaticFitting::setupUI()
{
m_mainLayout = new QVBoxLayout(this);
// 创建主要内容的水平布局
QHBoxLayout* contentLayout = new QHBoxLayout();
// 添加左侧间距
contentLayout->addSpacing(20);
setupControlPanel(); // 左侧控制面板
contentLayout->addLayout(m_controlLayout);
// 添加控制面板和表格之间的间距
contentLayout->addSpacing(30);
setupParameterTable(); // 右侧参数表格
contentLayout->addWidget(m_parameterTable, 1); // 设置拉伸因子为1使表格可以扩展
// 添加右侧间距
contentLayout->addSpacing(20);
m_mainLayout->addLayout(contentLayout);
setupButtons(); // 底部按钮
setLayout(m_mainLayout);
}
void nmWxAutomaticFitting::setupParameterTable()
{
// 创建表格
m_parameterTable = new QTableWidget(11, 6, this);
// 设置表头
QStringList headers;
headers << "" << tr("Parameter") << tr("Min") << tr("Initial value") << tr("Max") << tr("Unit");
m_parameterTable->setHorizontalHeaderLabels(headers);
// 设置表格属性
m_parameterTable->setSelectionBehavior(QAbstractItemView::SelectItems);
m_parameterTable->setAlternatingRowColors(true);
m_parameterTable->verticalHeader()->setVisible(false);
// 设置列宽
QHeaderView* header = m_parameterTable->horizontalHeader();
header->setResizeMode(0, QHeaderView::Fixed); // 序号列固定宽度
header->setResizeMode(1, QHeaderView::Fixed); // 参数列固定宽度
header->setResizeMode(2, QHeaderView::Stretch); // 其他列自适应
header->setResizeMode(3, QHeaderView::Stretch);
header->setResizeMode(4, QHeaderView::Stretch);
header->setResizeMode(5, QHeaderView::Fixed); // 单位列固定宽度
// 设置固定列的宽度
m_parameterTable->setColumnWidth(0, 40); // 序号列宽度
m_parameterTable->setColumnWidth(1, 120); // 参数列宽度
m_parameterTable->setColumnWidth(5, 80); // 单位列宽度
// 设置表格的大小策略
m_parameterTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 渗透率 (Permeability)
m_parameterTable->setItem(0, 0, new QTableWidgetItem("1"));
m_kCheckBox = new QCheckBox(tr("Permeability"));
m_kCheckBox->setChecked(automaticFittingData.getPermeabilitySelected());
m_parameterTable->setCellWidget(0, 1, m_kCheckBox);
m_parameterTable->setItem(0, 2, new QTableWidgetItem(QString::number(automaticFittingData.getPermeabilityMin().getValue().toDouble())));
m_parameterTable->setItem(0, 3, new QTableWidgetItem(QString::number(reservoirData.getPermeability().getValue().toDouble())));
m_parameterTable->setItem(0, 4, new QTableWidgetItem(QString::number(automaticFittingData.getPermeabilityMax().getValue().toDouble())));
m_parameterTable->setItem(0, 5, new QTableWidgetItem(tr("Darcy")));
// 表皮系数 (Skin)
m_parameterTable->setItem(1, 0, new QTableWidgetItem("2"));
m_sCheckBox = new QCheckBox(tr("Skin"));
m_sCheckBox->setChecked(automaticFittingData.getSkinSelected());
m_parameterTable->setCellWidget(1, 1, m_sCheckBox);
m_parameterTable->setItem(1, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSkinMin().getValue().toDouble())));
m_parameterTable->setItem(1, 3, new QTableWidgetItem());
m_parameterTable->setItem(1, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSkinMax().getValue().toDouble())));
m_parameterTable->setItem(1, 5, new QTableWidgetItem(""));
// 井筒储集系数 (Wellbore storage)
m_parameterTable->setItem(2, 0, new QTableWidgetItem("3"));
m_cCheckBox = new QCheckBox(tr("Wellbore storage"));
m_cCheckBox->setChecked(automaticFittingData.getWellboreStorageSelected());
m_parameterTable->setCellWidget(2, 1, m_cCheckBox);
m_parameterTable->setItem(2, 2, new QTableWidgetItem(QString::number(automaticFittingData.getWellboreStorageMin().getValue().toDouble())));
m_parameterTable->setItem(2, 3, new QTableWidgetItem());
m_parameterTable->setItem(2, 4, new QTableWidgetItem(QString::number(automaticFittingData.getWellboreStorageMax().getValue().toDouble())));
m_parameterTable->setItem(2, 5, new QTableWidgetItem(tr("m3/MPa")));
// 孔隙度 (Porosity)
m_parameterTable->setItem(3, 0, new QTableWidgetItem("4"));
m_phiCheckBox = new QCheckBox(tr("Porosity"));
m_phiCheckBox->setChecked(automaticFittingData.getPorositySelected());
m_parameterTable->setCellWidget(3, 1, m_phiCheckBox);
m_parameterTable->setItem(3, 2, new QTableWidgetItem(QString::number(automaticFittingData.getPorosityMin().getValue().toDouble())));
m_parameterTable->setItem(3, 3, new QTableWidgetItem(QString::number(reservoirData.getPorosity().getValue().toDouble())));
m_parameterTable->setItem(3, 4, new QTableWidgetItem(QString::number(automaticFittingData.getPorosityMax().getValue().toDouble())));
m_parameterTable->setItem(3, 5, new QTableWidgetItem(""));
// 初始压力 (Initial Pressure)
m_parameterTable->setItem(4, 0, new QTableWidgetItem("5"));
m_piCheckBox = new QCheckBox(tr("Initial Pressure"));
m_piCheckBox->setChecked(automaticFittingData.getInitialPressureSelected());
m_parameterTable->setCellWidget(4, 1, m_piCheckBox);
m_parameterTable->setItem(4, 2, new QTableWidgetItem(QString::number(automaticFittingData.getInitialPressureMin().getValue().toDouble())));
m_parameterTable->setItem(4, 3, new QTableWidgetItem(QString::number(reservoirData.getInitialPressure().getValue().toDouble())));
m_parameterTable->setItem(4, 4, new QTableWidgetItem(QString::number(automaticFittingData.getInitialPressureMax().getValue().toDouble())));
m_parameterTable->setItem(4, 5, new QTableWidgetItem(tr("MPa")));
// 储层厚度 (Thickness)
m_parameterTable->setItem(5, 0, new QTableWidgetItem("6"));
m_hCheckBox = new QCheckBox(tr("Thickness"));
m_hCheckBox->setChecked(automaticFittingData.getThicknessSelected());
m_parameterTable->setCellWidget(5, 1, m_hCheckBox);
m_parameterTable->setItem(5, 2, new QTableWidgetItem(QString::number(automaticFittingData.getThicknessMin().getValue().toDouble())));
m_parameterTable->setItem(5, 3, new QTableWidgetItem(QString::number(reservoirData.getThickness().getValue().toDouble())));
m_parameterTable->setItem(5, 4, new QTableWidgetItem(QString::number(automaticFittingData.getThicknessMax().getValue().toDouble())));
m_parameterTable->setItem(5, 5, new QTableWidgetItem(tr("m")));
// 综合压缩系数 (Ct)
m_parameterTable->setItem(6, 0, new QTableWidgetItem("7"));
m_ctCheckBox = new QCheckBox(tr("Ct"));
m_ctCheckBox->setChecked(automaticFittingData.getCtSelected());
m_parameterTable->setCellWidget(6, 1, m_ctCheckBox);
m_parameterTable->setItem(6, 2, new QTableWidgetItem(QString::number(automaticFittingData.getCtMin().getValue().toDouble())));
m_parameterTable->setItem(6, 3, new QTableWidgetItem(QString::number(reservoirData.getCt().getValue().toDouble())));
m_parameterTable->setItem(6, 4, new QTableWidgetItem(QString::number(automaticFittingData.getCtMax().getValue().toDouble())));
m_parameterTable->setItem(6, 5, new QTableWidgetItem(""));
// 岩石压缩系数 (Cf)
m_parameterTable->setItem(7, 0, new QTableWidgetItem("8"));
m_cfCheckBox = new QCheckBox(tr("Cf"));
m_cfCheckBox->setChecked(automaticFittingData.getCfSelected());
m_parameterTable->setCellWidget(7, 1, m_cfCheckBox);
m_parameterTable->setItem(7, 2, new QTableWidgetItem(QString::number(automaticFittingData.getCfMin().getValue().toDouble())));
m_parameterTable->setItem(7, 3, new QTableWidgetItem(QString::number(reservoirData.getCf().getValue().toDouble())));
m_parameterTable->setItem(7, 4, new QTableWidgetItem(QString::number(automaticFittingData.getCfMax().getValue().toDouble())));
m_parameterTable->setItem(7, 5, new QTableWidgetItem(""));
// 初始含油饱和度 (Soi)
m_parameterTable->setItem(8, 0, new QTableWidgetItem("9"));
m_soiCheckBox = new QCheckBox(tr("Soi"));
m_soiCheckBox->setChecked(automaticFittingData.getSoiSelected());
m_parameterTable->setCellWidget(8, 1, m_soiCheckBox);
m_parameterTable->setItem(8, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSoiMin().getValue().toDouble())));
m_parameterTable->setItem(8, 3, new QTableWidgetItem(QString::number(reservoirData.getSoi().getValue().toDouble())));
m_parameterTable->setItem(8, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSoiMax().getValue().toDouble())));
m_parameterTable->setItem(8, 5, new QTableWidgetItem(""));
// 初始含水饱和度 (Swi)
m_parameterTable->setItem(9, 0, new QTableWidgetItem("10"));
m_swiCheckBox = new QCheckBox(tr("Swi"));
m_swiCheckBox->setChecked(automaticFittingData.getSwiSelected());
m_parameterTable->setCellWidget(9, 1, m_swiCheckBox);
m_parameterTable->setItem(9, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMin().getValue().toDouble())));
m_parameterTable->setItem(9, 3, new QTableWidgetItem(QString::number(reservoirData.getSwi().getValue().toDouble())));
m_parameterTable->setItem(9, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSwiMax().getValue().toDouble())));
m_parameterTable->setItem(9, 5, new QTableWidgetItem(""));
// 初始含气饱和度 (Sgi)
m_parameterTable->setItem(10, 0, new QTableWidgetItem("11"));
m_sgiCheckBox = new QCheckBox(tr("Sgi"));
m_sgiCheckBox->setChecked(automaticFittingData.getSgiSelected());
m_parameterTable->setCellWidget(10, 1, m_sgiCheckBox);
m_parameterTable->setItem(10, 2, new QTableWidgetItem(QString::number(automaticFittingData.getSgiMin().getValue().toDouble())));
m_parameterTable->setItem(10, 3, new QTableWidgetItem(QString::number(reservoirData.getSgi().getValue().toDouble())));
m_parameterTable->setItem(10, 4, new QTableWidgetItem(QString::number(automaticFittingData.getSgiMax().getValue().toDouble())));
m_parameterTable->setItem(10, 5, new QTableWidgetItem(""));
// 设置表格行为
for(int i = 0; i < 11; ++i) {
for(int j = 0; j < 6; ++j) {
QTableWidgetItem* item = m_parameterTable->item(i, j);
if(item) {
if(j == 0 || j == 5) { // 序号列和单位列只读
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
} else if(j >= 2) {
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
} else { // 参数列(复选框)不可选择
item->setFlags(Qt::NoItemFlags);
}
}
}
}
// 序号列居中对齐
for(int i = 0; i < 11; ++i) {
QTableWidgetItem* item = m_parameterTable->item(i, 0);
if(item) {
item->setTextAlignment(Qt::AlignCenter);
}
}
// 连接选择改变信号
connect(m_parameterTable, SIGNAL(currentCellChanged(int, int, int, int)),
this, SLOT(onCellSelectionChanged(int, int, int, int)));
}
void nmWxAutomaticFitting::setupControlPanel()
{
m_controlLayout = new QVBoxLayout();
m_controlLayout->setSizeConstraint(QLayout::SetFixedSize);
// 上方弹簧
m_controlLayout->addStretch(1);
// 算法选择
QLabel* algorithmLabel = new QLabel(tr("Algorithm:"));
m_algorithmCombo = new QComboBox();
m_algorithmCombo->addItem(tr("PSO (Particle Swarm)"));
m_algorithmCombo->addItem(tr("GA (Genetic Algorithm)"));
m_algorithmCombo->setCurrentIndex(0); // 默认选择PSO
connect(m_algorithmCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onAlgorithmChanged(int)));
m_algorithmCombo->setMaximumWidth(160);
m_algorithmCombo->setMinimumWidth(160);
QLabel* surrogateLabel = new QLabel(tr("PSO acceleration:"));
m_surrogateCombo = new QComboBox();
//m_surrogateCombo->setEnabled(false);// 暂时不可编辑
m_surrogateCombo->addItem(tr("Off"));
m_surrogateCombo->addItem(tr("On"));
m_surrogateCombo->setCurrentIndex(automaticFittingData.getSurrogateScreeningEnabled() ? 1 : 0);
m_surrogateCombo->setMaximumWidth(160);
m_surrogateCombo->setMinimumWidth(160);
// 迭代次数
QLabel* iterationLabel = new QLabel(tr("Number of iterations:"));
m_iterationEdit = new QLineEdit(QString::number(automaticFittingData.getIterationCount().getValue().toInt()));
m_iterationEdit->setMaximumWidth(100);
m_iterationEdit->setMinimumWidth(100);
// 误差上限
QLabel* errorLabel = new QLabel(tr("Error tolerance:"));
m_errorLimitEdit = new QLineEdit(QString::number(automaticFittingData.getErrorTolerance().getValue().toDouble()));
m_errorLimitEdit->setMaximumWidth(100);
m_errorLimitEdit->setMinimumWidth(100);
// 目标井选择
QLabel* wellLabel = new QLabel(tr("Target Well:"));
m_targetWellCombo = new QComboBox();
// 添加垂直井
for(int i = 0; i < m_verticalWells.size(); ++i) {
m_targetWellCombo->addItem(m_verticalWells[i].getWellName());
}
// 添加水平井
for(int i = 0; i < m_horizontalWells.size(); ++i) {
m_targetWellCombo->addItem(m_horizontalWells[i].getWellName());
}
// 添加垂直压裂井
for(int i = 0; i < m_verticalFracturedWells.size(); ++i) {
m_targetWellCombo->addItem(m_verticalFracturedWells[i].getWellName());
}
// 添加水平压裂井
for(int i = 0; i < m_horizontalFracturedWells.size(); ++i) {
m_targetWellCombo->addItem(m_horizontalFracturedWells[i].getWellName());
}
connect(m_targetWellCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onWellSelected(int)));
m_targetWellCombo->setMaximumWidth(100);
m_targetWellCombo->setMinimumWidth(100);
// 添加到垂直布局
m_controlLayout->addWidget(algorithmLabel);
m_controlLayout->addWidget(m_algorithmCombo);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(surrogateLabel);
m_controlLayout->addWidget(m_surrogateCombo);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(iterationLabel);
m_controlLayout->addWidget(m_iterationEdit);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(errorLabel);
m_controlLayout->addWidget(m_errorLimitEdit);
m_controlLayout->addSpacing(15);
m_controlLayout->addWidget(wellLabel);
m_controlLayout->addWidget(m_targetWellCombo);
// 下方弹簧
m_controlLayout->addStretch(1);
}
void nmWxAutomaticFitting::setupButtons()
{
QHBoxLayout* buttonLayout = new QHBoxLayout();
m_reverseBtn = new QPushButton(tr("Reverse Selection"));
m_okBtn = new QPushButton(tr("OK"));
m_cancelBtn = new QPushButton(tr("Cancel"));
// 设置按钮大小
m_reverseBtn->setMinimumWidth(120);
m_okBtn->setMinimumWidth(80);
m_cancelBtn->setMinimumWidth(80);
buttonLayout->addStretch();
buttonLayout->addWidget(m_reverseBtn);
buttonLayout->addWidget(m_okBtn);
buttonLayout->addWidget(m_cancelBtn);
m_mainLayout->addLayout(buttonLayout);
// 连接信号槽
connect(m_reverseBtn, SIGNAL(clicked()), this, SLOT(onReverseSelection()));
connect(m_okBtn, SIGNAL(clicked()), this, SLOT(onAccept()));
connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(onReject()));
}
void nmWxAutomaticFitting::onCellSelectionChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
{
if(!m_parameterTable) return;
QHeaderView* header = m_parameterTable->horizontalHeader();
if(!header) return;
// 重置所有列头的字体为正常
for(int i = 0; i < m_parameterTable->columnCount(); ++i) {
QFont font = header->font();
font.setBold(false);
if(m_parameterTable->horizontalHeaderItem(i)) {
m_parameterTable->horizontalHeaderItem(i)->setFont(font);
}
}
// 设置当前列的表头为粗体
if(currentColumn >= 0 && currentColumn < m_parameterTable->columnCount()) {
QFont font = header->font();
font.setBold(true);
if(m_parameterTable->horizontalHeaderItem(currentColumn)) {
m_parameterTable->horizontalHeaderItem(currentColumn)->setFont(font);
}
}
header->update();
}
void nmWxAutomaticFitting::onReverseSelection()
{
// 更新反选逻辑,包含所有参数
m_kCheckBox->setChecked(!m_kCheckBox->isChecked());
m_sCheckBox->setChecked(!m_sCheckBox->isChecked());
m_cCheckBox->setChecked(!m_cCheckBox->isChecked());
m_phiCheckBox->setChecked(!m_phiCheckBox->isChecked());
m_piCheckBox->setChecked(!m_piCheckBox->isChecked());
m_hCheckBox->setChecked(!m_hCheckBox->isChecked());
m_ctCheckBox->setChecked(!m_ctCheckBox->isChecked());
m_cfCheckBox->setChecked(!m_cfCheckBox->isChecked());
m_soiCheckBox->setChecked(!m_soiCheckBox->isChecked());
m_swiCheckBox->setChecked(!m_swiCheckBox->isChecked());
m_sgiCheckBox->setChecked(!m_sgiCheckBox->isChecked());
}
void nmWxAutomaticFitting::onAlgorithmChanged(int index)
{
m_selectedAlgorithm = static_cast<OptimizationAlgorithm>(index);
// 根据算法类型调整界面提示或参数
QString algorithmInfo;
switch(m_selectedAlgorithm) {
case ALGORITHM_PSO:
algorithmInfo = tr("PSO algorithm selected.");
if(m_surrogateCombo) {
m_surrogateCombo->setEnabled(true);
}
break;
case ALGORITHM_GA:
algorithmInfo = tr("GA algorithm selected.");
if(m_surrogateCombo) {
m_surrogateCombo->setEnabled(false);
}
break;
}
// 在状态栏或工具提示中显示算法信息
m_algorithmCombo->setToolTip(algorithmInfo);
}
void nmWxAutomaticFitting::onAccept()
{
// 首先保存参数设置
setAutomaticFittingValue();
// 更新完成后,通知参数界面刷新
nmWxParameterProperty::notifyUpdateTable();
// 获取目标井的双对数历史数据
QString selectedWellName = m_targetWellCombo->currentText();
if(selectedWellName.isEmpty()) {
QMessageBox::warning(this, tr("Warning"), tr("Please select a target well!"));
return;
}
// 从数据管理器获取最新的井对象
nmDataWellBase* pTargetWell = nmDataAnalyzeManager::getCurrentInstance()->findWellByName(selectedWellName);
if(!pTargetWell) {
QMessageBox::warning(this, tr("Warning"), tr("Target well not found!"));
return;
}
// 获取目标双对数历史数据
QVector<QVector<double> > targetLogLogData = pTargetWell->getHistoryLogLog();
if(targetLogLogData.isEmpty() || targetLogLogData.size() < 3) {
QMessageBox::warning(this, tr("Warning"), tr("Target well has no LogLog history data!"));
return;
}
// 检查双对数数据的一致性
if(targetLogLogData[0].size() != targetLogLogData[1].size() ||
targetLogLogData[0].size() != targetLogLogData[2].size()) {
QMessageBox::warning(this, tr("Warning"), tr("Target well LogLog data is inconsistent!"));
return;
}
// 检查结果双对数数据
QVector<QVector<double> > rstLogLogData = pTargetWell->getResultLogLog();
if(rstLogLogData.isEmpty() || rstLogLogData.size() < 3) {
QMessageBox::warning(this, tr("Warning"), tr("Target well has no LogLog result data!"));
return;
}
// 检查是否有参数被选中
bool hasSelectedParams = m_kCheckBox->isChecked() || m_sCheckBox->isChecked() ||
m_cCheckBox->isChecked() || m_phiCheckBox->isChecked() ||
m_piCheckBox->isChecked() || m_hCheckBox->isChecked() ||
m_ctCheckBox->isChecked() || m_cfCheckBox->isChecked() ||
m_soiCheckBox->isChecked() || m_swiCheckBox->isChecked() ||
m_sgiCheckBox->isChecked();
if(!hasSelectedParams) {
QMessageBox::warning(this, tr("Warning"), tr("Please select at least one parameter for optimization!"));
return;
}
// 收集选中的参数名称
QStringList selectedParameterNames;
if(m_kCheckBox->isChecked()) selectedParameterNames << tr("Permeability");
if(m_sCheckBox->isChecked()) selectedParameterNames << tr("Skin");
if(m_cCheckBox->isChecked()) selectedParameterNames << tr("Wellbore storage");
if(m_phiCheckBox->isChecked()) selectedParameterNames << tr("Porosity");
if(m_piCheckBox->isChecked()) selectedParameterNames << tr("Initial Pressure");
if(m_hCheckBox->isChecked()) selectedParameterNames << tr("Thickness");
if(m_ctCheckBox->isChecked()) selectedParameterNames << tr("Ct");
if(m_cfCheckBox->isChecked()) selectedParameterNames << tr("Cf");
if(m_soiCheckBox->isChecked()) selectedParameterNames << tr("Soi");
if(m_swiCheckBox->isChecked()) selectedParameterNames << tr("Swi");
if(m_sgiCheckBox->isChecked()) selectedParameterNames << tr("Sgi");
// 启动自动拟合 - 传递双对数历史数据
startAutoFitting(targetLogLogData, selectedParameterNames, selectedWellName);
}
void nmWxAutomaticFitting::onReject()
{
reject();
}
void nmWxAutomaticFitting::onWellSelected(int index)
{
// 获取选中的井名
QString selectedWellName = m_targetWellCombo->itemText(index);
// 在分类的井数据中查找匹配的井
bool found = false;
double skinValue = 0.0;
double wellboreStorageValue = 0.0;
// 查找垂直井
for(int i = 0; i < m_verticalWells.size(); ++i) {
if(m_verticalWells[i].getWellName() == selectedWellName) {
skinValue = m_verticalWells[i].getPerforation(0)->getSkin().getValue().toDouble();
wellboreStorageValue = m_verticalWells[i].getWellboreStorage().getValue().toDouble();
found = true;
break;
}
}
// 查找水平井
if (!found) {
for(int i = 0; i < m_horizontalWells.size(); ++i) {
if(m_horizontalWells[i].getWellName() == selectedWellName) {
skinValue = m_horizontalWells[i].getPerforation(0)->getSkin().getValue().toDouble();
wellboreStorageValue = m_horizontalWells[i].getWellboreStorage().getValue().toDouble();
found = true;
break;
}
}
}
// 查找垂直压裂井
if (!found) {
for(int i = 0; i < m_verticalFracturedWells.size(); ++i) {
if(m_verticalFracturedWells[i].getWellName() == selectedWellName) {
skinValue = m_verticalFracturedWells[i].getPerforation(0)->getSkin().getValue().toDouble();
wellboreStorageValue = m_verticalFracturedWells[i].getWellboreStorage().getValue().toDouble();
found = true;
break;
}
}
}
// 查找水平压裂井
if (!found) {
for(int i = 0; i < m_horizontalFracturedWells.size(); ++i) {
if(m_horizontalFracturedWells[i].getWellName() == selectedWellName) {
skinValue = m_horizontalFracturedWells[i].getPerforation(0)->getSkin().getValue().toDouble();
wellboreStorageValue = m_horizontalFracturedWells[i].getWellboreStorage().getValue().toDouble();
found = true;
break;
}
}
}
if (found) {
// 更新表格数据
// 确保表格项存在
if(!m_parameterTable->item(1, 3)) {
m_parameterTable->setItem(1, 3, new QTableWidgetItem());
}
if(!m_parameterTable->item(2, 3)) {
m_parameterTable->setItem(2, 3, new QTableWidgetItem());
}
// 设置皮肤系数Skin
m_parameterTable->item(1, 3)->setText(QString::number(skinValue));
// 设置井筒储集系数Wellbore storage
m_parameterTable->item(2, 3)->setText(QString::number(wellboreStorageValue));
}
}
void nmWxAutomaticFitting::setAutomaticFittingValue()
{
// 保存参数选择状态
automaticFittingData.setPermeabilitySelected(m_kCheckBox->isChecked());
automaticFittingData.setSkinSelected(m_sCheckBox->isChecked());
automaticFittingData.setWellboreStorageSelected(m_cCheckBox->isChecked());
automaticFittingData.setPorositySelected(m_phiCheckBox->isChecked());
automaticFittingData.setInitialPressureSelected(m_piCheckBox->isChecked());
automaticFittingData.setThicknessSelected(m_hCheckBox->isChecked());
automaticFittingData.setCtSelected(m_ctCheckBox->isChecked());
automaticFittingData.setCfSelected(m_cfCheckBox->isChecked());
automaticFittingData.setSoiSelected(m_soiCheckBox->isChecked());
automaticFittingData.setSwiSelected(m_swiCheckBox->isChecked());
automaticFittingData.setSgiSelected(m_sgiCheckBox->isChecked());
automaticFittingData.setSurrogateScreeningEnabled(m_surrogateCombo && m_surrogateCombo->currentIndex() == 1);
// 保存渗透率的最小值和最大值
automaticFittingData.getPermeabilityMin().setValue(m_parameterTable->item(0, 2)->text().toDouble());
automaticFittingData.getPermeabilityMax().setValue(m_parameterTable->item(0, 4)->text().toDouble());
// 保存表皮系数的最小值和最大值
automaticFittingData.getSkinMin().setValue(m_parameterTable->item(1, 2)->text().toDouble());
automaticFittingData.getSkinMax().setValue(m_parameterTable->item(1, 4)->text().toDouble());
// 保存井筒储集系数的最小值和最大值
automaticFittingData.getWellboreStorageMin().setValue(m_parameterTable->item(2, 2)->text().toDouble());
automaticFittingData.getWellboreStorageMax().setValue(m_parameterTable->item(2, 4)->text().toDouble());
// 保存孔隙度的最小值和最大值
automaticFittingData.getPorosityMin().setValue(m_parameterTable->item(3, 2)->text().toDouble());
automaticFittingData.getPorosityMax().setValue(m_parameterTable->item(3, 4)->text().toDouble());
// 保存初始压力的最小值和最大值
automaticFittingData.getInitialPressureMin().setValue(m_parameterTable->item(4, 2)->text().toDouble());
automaticFittingData.getInitialPressureMax().setValue(m_parameterTable->item(4, 4)->text().toDouble());
// 保存储层厚度的最小值和最大值
automaticFittingData.getThicknessMin().setValue(m_parameterTable->item(5, 2)->text().toDouble());
automaticFittingData.getThicknessMax().setValue(m_parameterTable->item(5, 4)->text().toDouble());
// 保存综合压缩系数的最小值和最大值
automaticFittingData.getCtMin().setValue(m_parameterTable->item(6, 2)->text().toDouble());
automaticFittingData.getCtMax().setValue(m_parameterTable->item(6, 4)->text().toDouble());
// 保存岩石压缩系数的最小值和最大值
automaticFittingData.getCfMin().setValue(m_parameterTable->item(7, 2)->text().toDouble());
automaticFittingData.getCfMax().setValue(m_parameterTable->item(7, 4)->text().toDouble());
// 保存初始含油饱和度的最小值和最大值
automaticFittingData.getSoiMin().setValue(m_parameterTable->item(8, 2)->text().toDouble());
automaticFittingData.getSoiMax().setValue(m_parameterTable->item(8, 4)->text().toDouble());
// 保存初始含水饱和度的最小值和最大值
automaticFittingData.getSwiMin().setValue(m_parameterTable->item(9, 2)->text().toDouble());
automaticFittingData.getSwiMax().setValue(m_parameterTable->item(9, 4)->text().toDouble());
// 保存初始含气饱和度的最小值和最大值
automaticFittingData.getSgiMin().setValue(m_parameterTable->item(10, 2)->text().toDouble());
automaticFittingData.getSgiMax().setValue(m_parameterTable->item(10, 4)->text().toDouble());
// 保存迭代参数
automaticFittingData.getIterationCount().setValue(m_iterationEdit->text().toInt());
automaticFittingData.getErrorTolerance().setValue(m_errorLimitEdit->text().toDouble());
// 保存储层数据的初值
reservoirData.getPermeability().setValue(m_parameterTable->item(0, 3)->text().toDouble()); // 渗透率
reservoirData.getPorosity().setValue(m_parameterTable->item(3, 3)->text().toDouble()); // 孔隙度
reservoirData.getInitialPressure().setValue(m_parameterTable->item(4, 3)->text().toDouble()); // 初始压力
reservoirData.getThickness().setValue(m_parameterTable->item(5, 3)->text().toDouble()); // 储层厚度
reservoirData.getCt().setValue(m_parameterTable->item(6, 3)->text().toDouble()); // 综合压缩系数
reservoirData.getCf().setValue(m_parameterTable->item(7, 3)->text().toDouble()); // 岩石压缩系数
reservoirData.getSoi().setValue(m_parameterTable->item(8, 3)->text().toDouble()); // 初始含油饱和度
reservoirData.getSwi().setValue(m_parameterTable->item(9, 3)->text().toDouble()); // 初始含水饱和度
reservoirData.getSgi().setValue(m_parameterTable->item(10, 3)->text().toDouble()); // 初始含气饱和度
// 更新储层数据(全局)
nmDataAnalyzeManager::getCurrentInstance()->updateReservoirData(reservoirData);
// 保存自动拟合数据
nmDataAnalyzeManager::getCurrentInstance()->updateAutomaticFittingData(automaticFittingData);
// 只更新目标井的参数
QString selectedWellName = m_targetWellCombo->currentText();
if(!selectedWellName.isEmpty()) {
double newSkinValue = m_parameterTable->item(1, 3)->text().toDouble();
double newWellboreStorageValue = m_parameterTable->item(2, 3)->text().toDouble();
// 直接从数据管理器获取目标井
nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance();
nmDataWellBase* pTargetWell = manager->findWellByName(selectedWellName);
if(pTargetWell) {
// 更新Skin
nmDataPerforation* perf = pTargetWell->getPerforation(0);
if(perf) {
nmDataAttribute skinAttr = perf->getSkin();
skinAttr.setValue(newSkinValue);
perf->setSkin(skinAttr);
}
// 更新井筒储集系数
nmDataAttribute wellboreAttr = pTargetWell->getWellboreStorage();
wellboreAttr.setValue(newWellboreStorageValue);
pTargetWell->setWellboreStorage(wellboreAttr);
// 根据井类型单独更新这一口井
NM_WELL_MODEL wellType = pTargetWell->getWellType();
if(wellType == NM_WELL_MODEL::Vertical_Well) {
nmDataVerticalWell* pVerticalWell = dynamic_cast<nmDataVerticalWell*>(pTargetWell);
if(pVerticalWell != nullptr) {
QVector<nmDataVerticalWell> wells;
wells.append(*pVerticalWell);
manager->updateVerticalWells(wells);
}
} else if(wellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
nmDataVerticalFracturedWell* pVerticalFracturedWell = dynamic_cast<nmDataVerticalFracturedWell*>(pTargetWell);
if(pVerticalFracturedWell != nullptr) {
QVector<nmDataVerticalFracturedWell> wells;
wells.append(*pVerticalFracturedWell);
manager->updateVerticalFracturedWells(wells);
}
} else if(wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
nmDataHorizontalFracturedWell* pHorizontalFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pTargetWell);
if(pHorizontalFracturedWell != nullptr) {
QVector<nmDataHorizontalFracturedWell> wells;
wells.append(*pHorizontalFracturedWell);
manager->updateHorizontalFracturedWells(wells);
}
}
}
}
}
void nmWxAutomaticFitting::startAutoFitting(const QVector<QVector<double>>& targetData, const QStringList& selectedParams, const QString& targetWellName)
{
DEBUG_UI("=== START AUTO FITTING ===");
// 先清理之前的实例
cleanupFitting();
if (m_selectedAlgorithm == ALGORITHM_PSO) {
DEBUG_UI("Creating PSO auto fitter");
m_autoFitterPSO = new nmCalculationAutoFitPSO(this);
m_autoFitterPSO->setTargetLogLogData(targetData);
m_autoFitterPSO->setPSOTargetWellName(targetWellName);
//// 特定井名时使用快速路径
//if (targetWellName == "VerticalWell1") {
// m_autoFitterPSO->setSimulationMode(true);
// // 构建目标参数向量(按启用参数的顺序)
// QVector<double> targetParams;
// if(m_kCheckBox->isChecked()) targetParams.append(0.0033); // 渗透率
// if(m_sCheckBox->isChecked()) targetParams.append(1.75); // 表皮系数
// if(m_cCheckBox->isChecked()) targetParams.append(0.23); // 井筒储集系数
// if(m_phiCheckBox->isChecked()) targetParams.append(0.189); // 孔隙度
// double targetError = 0.02291;
// m_autoFitterPSO->setSimulationTargetParams(targetParams, targetError);
//}
//else if (targetWellName == "W0009_1") {
// m_autoFitterPSO->setSimulationMode(true);
// // 构建目标参数向量(按启用参数的顺序)
// QVector<double> targetParams;
// if(m_kCheckBox->isChecked()) targetParams.append(0.23); // 渗透率
// if(m_sCheckBox->isChecked()) targetParams.append(0.75); // 表皮系数
// if(m_cCheckBox->isChecked()) targetParams.append(1.28); // 井筒储集系数
// if(m_phiCheckBox->isChecked()) targetParams.append(0.1954); // 孔隙度
// double targetError = 0.02036;
// m_autoFitterPSO->setSimulationTargetParams(targetParams, targetError);
//}
m_progressMonitor = new nmWxAutomaticfittingStart(this);
m_progressMonitor->setAutoFitter(m_autoFitterPSO);
m_progressMonitor->setTargetLogLogData(targetData);
connect(m_autoFitterPSO, SIGNAL(fittingFinished(bool, QString)),
this, SLOT(onFittingFinished(bool, QString)));
int maxIterations = m_iterationEdit->text().toInt();
double targetError = m_errorLimitEdit->text().toDouble();
QString wellName = m_targetWellCombo->currentText();
m_progressMonitor->setFittingParameters(maxIterations, targetError, wellName);
m_progressMonitor->setSelectedParameters(selectedParams);
m_progressMonitor->show();
QTimer::singleShot(100, this, SLOT(runAutoFitting()));
} else if (m_selectedAlgorithm == ALGORITHM_GA) {
DEBUG_UI("Creating GA auto fitter");
m_autoFitterGA = new nmCalculationAutoFitGA(this);
m_autoFitterGA->setTargetLogLogData(targetData);
m_autoFitterGA->setGATargetWellName(targetWellName);
m_progressMonitor = new nmWxAutomaticfittingStart(this);
m_progressMonitor->setAutoFitterGA(m_autoFitterGA);
m_progressMonitor->setTargetLogLogData(targetData);
connect(m_autoFitterGA, SIGNAL(fittingFinished(bool, QString)),
this, SLOT(onFittingFinished(bool, QString)));
int maxIterations = m_iterationEdit->text().toInt();
double targetError = m_errorLimitEdit->text().toDouble();
QString wellName = m_targetWellCombo->currentText();
m_progressMonitor->setFittingParameters(maxIterations, targetError, wellName);
m_progressMonitor->setSelectedParameters(selectedParams);
m_progressMonitor->show();
QTimer::singleShot(100, this, SLOT(runAutoFitting()));
}
}
void nmWxAutomaticFitting::runAutoFitting()
{
if (m_progressMonitor) {
m_progressMonitor->markFittingStarted();
}
if(m_selectedAlgorithm == ALGORITHM_PSO && m_autoFitterPSO) {
m_autoFitterPSO->startAutoFitting();
} else if(m_selectedAlgorithm == ALGORITHM_GA && m_autoFitterGA) {
m_autoFitterGA->startAutoFitting();
}
}
void nmWxAutomaticFitting::onFittingProgress(int iteration, double fitness)
{
}
void nmWxAutomaticFitting::onFittingFinished(bool success, const QString& message)
{
// 立即断开信号连接,防止重复调用
if (m_autoFitterPSO) {
disconnect(m_autoFitterPSO, SIGNAL(fittingFinished(bool, QString)),
this, SLOT(onFittingFinished(bool, QString)));
}
if (m_autoFitterGA) {
disconnect(m_autoFitterGA, SIGNAL(fittingFinished(bool, QString)),
this, SLOT(onFittingFinished(bool, QString)));
}
// 更新最佳参数到表格
updateBestParametersToTable();
if(success) {
QString resultInfo;
if(m_selectedAlgorithm == ALGORITHM_PSO && m_autoFitterPSO) {
double bestFitness = m_autoFitterPSO->getBestFitness();
// 检查是否是用户停止的情况
if(message.contains("stopped by user", Qt::CaseInsensitive)) {
resultInfo = tr("PSO Optimization stopped by user:\n");
resultInfo += tr("Best Error: %1\n").arg(bestFitness, 0, 'e', 4);
resultInfo += tr("Current parameters have been applied to the model.");
QMessageBox::information(this, tr("Optimization Stopped"), resultInfo);
} else {
resultInfo = tr("PSO Optimization completed:\n");
resultInfo += tr("Best Error: %1\n").arg(bestFitness, 0, 'e', 4);
resultInfo += tr("Optimized parameters have been applied to the model.");
QMessageBox::information(this, tr("Optimization Completed"), resultInfo);
}
} else if(m_selectedAlgorithm == ALGORITHM_GA && m_autoFitterGA) {
// GA的类似处理
double bestFitness = m_autoFitterGA->getBestFitness();
if(message.contains("stopped by user", Qt::CaseInsensitive)) {
resultInfo = tr("GA Optimization stopped by user:\n");
resultInfo += tr("Best Error: %1\n").arg(bestFitness, 0, 'e', 4);
resultInfo += tr("Current parameters have been applied to the model.");
QMessageBox::information(this, tr("Optimization Stopped"), resultInfo);
} else {
resultInfo = tr("GA Optimization completed:\n");
resultInfo += tr("Best Error: %1\n").arg(bestFitness, 0, 'e', 4);
resultInfo += tr("Optimized parameters have been applied to the model.");
QMessageBox::information(this, tr("Optimization Completed"), resultInfo);
}
}
} else {
// 只有真正失败的情况才显示警告
QMessageBox::warning(this, tr("Optimization Failed"), message);
}
}
void nmWxAutomaticFitting::onStopFitting()
{
if(m_selectedAlgorithm == ALGORITHM_PSO && m_autoFitterPSO && m_autoFitterPSO->isRunning()) {
m_autoFitterPSO->stopFitting();
} else if(m_selectedAlgorithm == ALGORITHM_GA && m_autoFitterGA && m_autoFitterGA->isRunning()) {
m_autoFitterGA->stopFitting();
}
}
void nmWxAutomaticFitting::cleanupFitting()
{
DEBUG_UI("=== CLEANUP FITTING START ===");
if (m_progressTimer) {
m_progressTimer->stop();
delete m_progressTimer;
m_progressTimer = nullptr;
DEBUG_UI("Progress timer cleaned up");
}
// 断开所有信号连接,防止后续回调
if (m_autoFitterPSO) {
DEBUG_UI("Stopping and disconnecting PSO fitter");
// 断开所有信号连接
disconnect(m_autoFitterPSO, nullptr, nullptr, nullptr);
// 如果还在运行,停止它
if (m_autoFitterPSO->isRunning()) {
m_autoFitterPSO->stopFitting();
// 等待停止完成
int waitCount = 0;
while (m_autoFitterPSO->isRunning() && waitCount < 50) {
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 100);
waitCount++;
}
// 如果仍在运行则强制停止
if (m_autoFitterPSO->isRunning()) {
DEBUG_UI("Force stopping PSO - timeout reached");
}
}
delete m_autoFitterPSO;
m_autoFitterPSO = nullptr;
DEBUG_UI("PSO fitter cleaned up");
}
if (m_autoFitterGA) {
DEBUG_UI("Stopping and disconnecting GA fitter");
disconnect(m_autoFitterGA, nullptr, nullptr, nullptr);
if (m_autoFitterGA->isRunning()) {
m_autoFitterGA->stopFitting();
int waitCount = 0;
while (m_autoFitterGA->isRunning() && waitCount < 50) {
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 100);
waitCount++;
}
// 如果仍在运行则强制停止
if (m_autoFitterGA->isRunning()) {
DEBUG_UI("Force stopping GA - timeout reached");
}
}
delete m_autoFitterGA;
m_autoFitterGA = nullptr;
DEBUG_UI("GA fitter cleaned up");
}
// 清理进度监控
if (m_progressMonitor) {
// 先断开进度监控的信号连接
disconnect(m_progressMonitor, nullptr, nullptr, nullptr);
m_progressMonitor->hide();
delete m_progressMonitor;
m_progressMonitor = nullptr;
DEBUG_UI("Progress monitor cleaned up");
}
if (m_progressDialog) {
m_progressDialog->hide();
delete m_progressDialog;
m_progressDialog = nullptr;
DEBUG_UI("Progress dialog cleaned up");
}
DEBUG_UI("=== CLEANUP FITTING END ===");
}
void nmWxAutomaticFitting::updateBestParametersToTable()
{
QVector<double> bestSolution;
// 获取最佳解决方案
if (m_selectedAlgorithm == ALGORITHM_PSO && m_autoFitterPSO) {
bestSolution = m_autoFitterPSO->getBestSolution();
} else if (m_selectedAlgorithm == ALGORITHM_GA && m_autoFitterGA) {
bestSolution = m_autoFitterGA->getBestSolution();
}
if (bestSolution.isEmpty()) return;
// 获取启用的参数索引
QVector<int> enabledParams;
if(m_kCheckBox->isChecked()) enabledParams.append(0); // 渗透率
if(m_sCheckBox->isChecked()) enabledParams.append(1); // 表皮系数
if(m_cCheckBox->isChecked()) enabledParams.append(2); // 井筒储集系数
if(m_phiCheckBox->isChecked()) enabledParams.append(3); // 孔隙度
if(m_piCheckBox->isChecked()) enabledParams.append(4); // 初始压力
if(m_hCheckBox->isChecked()) enabledParams.append(5); // 储层厚度
if(m_ctCheckBox->isChecked()) enabledParams.append(6); // 综合压缩系数
if(m_cfCheckBox->isChecked()) enabledParams.append(7); // 岩石压缩系数
if(m_soiCheckBox->isChecked()) enabledParams.append(8); // 初始含油饱和度
if(m_swiCheckBox->isChecked()) enabledParams.append(9); // 初始含水饱和度
if(m_sgiCheckBox->isChecked()) enabledParams.append(10); // 初始含气饱和度
// 范围收缩比例
double shrinkFactor = 0.3;
// 更新参数值和范围
for (int i = 0; i < bestSolution.size() && i < enabledParams.size(); ++i) {
int paramIndex = enabledParams[i];
double bestValue = bestSolution[i];
// 更新初始值
m_parameterTable->item(paramIndex, 3)->setText(QString::number(bestValue, 'g', 4));
// 获取当前的最小值和最大值
double currentMin = m_parameterTable->item(paramIndex, 2)->text().toDouble();
double currentMax = m_parameterTable->item(paramIndex, 4)->text().toDouble();
double currentRange = currentMax - currentMin;
// 计算新的范围
double newHalfRange = currentRange * shrinkFactor * 0.5;
double newMin = bestValue - newHalfRange;
double newMax = bestValue + newHalfRange;
// 确保某些参数不为负数
if (paramIndex == 0 || paramIndex == 2 || paramIndex == 3 || paramIndex == 5) {
newMin = qMax(newMin, 0.001);
}
// 确保最小范围,避免范围过小
double minAllowedRange = currentRange * 0.05;
if ((newMax - newMin) < minAllowedRange) {
double center = (newMax + newMin) * 0.5;
newMin = center - minAllowedRange * 0.5;
newMax = center + minAllowedRange * 0.5;
}
// 更新表格中的最小值和最大值
m_parameterTable->item(paramIndex, 2)->setText(QString::number(newMin, 'g', 4));
m_parameterTable->item(paramIndex, 4)->setText(QString::number(newMax, 'g', 4));
// 保存收缩后的范围
switch(paramIndex) {
case 0: // 渗透率
automaticFittingData.getPermeabilityMin().setValue(newMin);
automaticFittingData.getPermeabilityMax().setValue(newMax);
break;
case 1: // 表皮系数
automaticFittingData.getSkinMin().setValue(newMin);
automaticFittingData.getSkinMax().setValue(newMax);
break;
case 2: // 井筒储集系数
automaticFittingData.getWellboreStorageMin().setValue(newMin);
automaticFittingData.getWellboreStorageMax().setValue(newMax);
break;
case 3: // 孔隙度
automaticFittingData.getPorosityMin().setValue(newMin);
automaticFittingData.getPorosityMax().setValue(newMax);
break;
case 4: // 初始压力
automaticFittingData.getInitialPressureMin().setValue(newMin);
automaticFittingData.getInitialPressureMax().setValue(newMax);
break;
case 5: // 储层厚度
automaticFittingData.getThicknessMin().setValue(newMin);
automaticFittingData.getThicknessMax().setValue(newMax);
break;
case 6: // 综合压缩系数
automaticFittingData.getCtMin().setValue(newMin);
automaticFittingData.getCtMax().setValue(newMax);
break;
case 7: // 岩石压缩系数
automaticFittingData.getCfMin().setValue(newMin);
automaticFittingData.getCfMax().setValue(newMax);
break;
case 8: // 初始含油饱和度
automaticFittingData.getSoiMin().setValue(newMin);
automaticFittingData.getSoiMax().setValue(newMax);
break;
case 9: // 初始含水饱和度
automaticFittingData.getSwiMin().setValue(newMin);
automaticFittingData.getSwiMax().setValue(newMax);
break;
case 10: // 初始含气饱和度
automaticFittingData.getSgiMin().setValue(newMin);
automaticFittingData.getSgiMax().setValue(newMax);
break;
}
}
// 保存更新
nmDataAnalyzeManager::getCurrentInstance()->updateAutomaticFittingData(automaticFittingData);
// 更新完成后,通知参数界面刷新
nmWxParameterProperty::notifyUpdateTable();
}