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/nmData/nmDataAutomaticFitting.cpp

367 lines
19 KiB
C++

#include "nmDataAutomaticFitting.h"
#include <QCoreApplication>
#include <QtCore/qnumeric.h>
nmDataAutomaticFitting::nmDataAutomaticFitting()
{
// 初始化参数选择标志
m_permeabilitySelected = true; // 默认选中
m_skinSelected = true; // 默认选中
m_wellboreStorageSelected = true; // 默认选中
m_porositySelected = true; // 默认选中
m_fractureConductivitySelected = false; // 仅压裂井可用,默认不选中
m_fractureHalfLengthSelected = false; // 仅压裂井可用,默认不选中
// 拟合上下界不再使用固定默认值,由自动拟合窗口按数据对象初值和物理边界生成。
m_permeabilityMax = nmDataAttribute("Permeability Max", QVariant(), "mD");
m_skinMax = nmDataAttribute("Skin Max", QVariant(), "");
m_wellboreStorageMax = nmDataAttribute("Wellbore Storage Max", QVariant(), "m^3/MPa");
m_porosityMax = nmDataAttribute("Porosity Max", QVariant(), "");
m_fractureConductivityMax = nmDataAttribute("Fracture Conductivity Max", QVariant(), "md.m");
m_fractureHalfLengthMax = nmDataAttribute("Fracture Half Length Max", QVariant(), "m");
m_permeabilityMin = nmDataAttribute("Permeability Min", QVariant(), "mD");
m_skinMin = nmDataAttribute("Skin Min", QVariant(), "");
m_wellboreStorageMin = nmDataAttribute("Wellbore Storage Min", QVariant(), "m^3/MPa");
m_porosityMin = nmDataAttribute("Porosity Min", QVariant(), "");
m_fractureConductivityMin = nmDataAttribute("Fracture Conductivity Min", QVariant(), "mD.m");
m_fractureHalfLengthMin = nmDataAttribute("Fracture Half Length Min", QVariant(), "m");
// 初始化迭代参数
m_iterationCount = nmDataAttribute("Iteration Count", 20, "");
m_errorTolerance = nmDataAttribute("Error Tolerance", 0.02, "");
m_algorithmName = QString(tr("PSO (Particle Swarm Optimization)"));
m_surrogateScreeningEnabled = false;
}
nmDataAutomaticFitting::~nmDataAutomaticFitting()
{
}
nmDataAutomaticFitting::nmDataAutomaticFitting(const nmDataAutomaticFitting& other)
{
*this = other;
}
nmDataAutomaticFitting& nmDataAutomaticFitting::operator=(const nmDataAutomaticFitting& other)
{
if (this != &other) {
// 复制多井参数及原单井配置
m_modelParameters = other.m_modelParameters;
m_permeabilitySelected = other.m_permeabilitySelected;
m_skinSelected = other.m_skinSelected;
m_wellboreStorageSelected = other.m_wellboreStorageSelected;
m_porositySelected = other.m_porositySelected;
m_fractureConductivitySelected = other.m_fractureConductivitySelected;
m_fractureHalfLengthSelected = other.m_fractureHalfLengthSelected;
// 复制参数最大值
m_permeabilityMax = other.m_permeabilityMax;
m_skinMax = other.m_skinMax;
m_wellboreStorageMax = other.m_wellboreStorageMax;
m_porosityMax = other.m_porosityMax;
m_fractureConductivityMax = other.m_fractureConductivityMax;
m_fractureHalfLengthMax = other.m_fractureHalfLengthMax;
// 复制参数最小值
m_permeabilityMin = other.m_permeabilityMin;
m_skinMin = other.m_skinMin;
m_wellboreStorageMin = other.m_wellboreStorageMin;
m_porosityMin = other.m_porosityMin;
m_fractureConductivityMin = other.m_fractureConductivityMin;
m_fractureHalfLengthMin = other.m_fractureHalfLengthMin;
// 复制迭代参数
m_iterationCount = other.m_iterationCount;
m_errorTolerance = other.m_errorTolerance;
m_algorithmName = other.m_algorithmName;
m_surrogateScreeningEnabled = other.m_surrogateScreeningEnabled;
}
return *this;
}
rapidjson::Value nmDataAutomaticFitting::ToJsonValue(rapidjson::Document::AllocatorType& allocator) const
{
rapidjson::Value fittingObject(rapidjson::kObjectType);
// 序列化参数选择标志
fittingObject.AddMember("PermeabilitySelected", m_permeabilitySelected, allocator);
fittingObject.AddMember("SkinSelected", m_skinSelected, allocator);
fittingObject.AddMember("WellboreStorageSelected", m_wellboreStorageSelected, allocator);
fittingObject.AddMember("PorositySelected", m_porositySelected, allocator);
fittingObject.AddMember("FractureConductivitySelected", m_fractureConductivitySelected, allocator);
fittingObject.AddMember("FractureHalfLengthSelected", m_fractureHalfLengthSelected, allocator);
// 序列化参数最大值
fittingObject.AddMember("PermeabilityMax", m_permeabilityMax.ToJsonValue(allocator), allocator);
fittingObject.AddMember("SkinMax", m_skinMax.ToJsonValue(allocator), allocator);
fittingObject.AddMember("WellboreStorageMax", m_wellboreStorageMax.ToJsonValue(allocator), allocator);
fittingObject.AddMember("PorosityMax", m_porosityMax.ToJsonValue(allocator), allocator);
fittingObject.AddMember("FractureConductivityMax", m_fractureConductivityMax.ToJsonValue(allocator), allocator);
fittingObject.AddMember("FractureHalfLengthMax", m_fractureHalfLengthMax.ToJsonValue(allocator), allocator);
// 序列化参数最小值
fittingObject.AddMember("PermeabilityMin", m_permeabilityMin.ToJsonValue(allocator), allocator);
fittingObject.AddMember("SkinMin", m_skinMin.ToJsonValue(allocator), allocator);
fittingObject.AddMember("WellboreStorageMin", m_wellboreStorageMin.ToJsonValue(allocator), allocator);
fittingObject.AddMember("PorosityMin", m_porosityMin.ToJsonValue(allocator), allocator);
fittingObject.AddMember("FractureConductivityMin", m_fractureConductivityMin.ToJsonValue(allocator), allocator);
fittingObject.AddMember("FractureHalfLengthMin", m_fractureHalfLengthMin.ToJsonValue(allocator), allocator);
// 序列化迭代参数
fittingObject.AddMember("IterationCount", m_iterationCount.ToJsonValue(allocator), allocator);
fittingObject.AddMember("ErrorTolerance", m_errorTolerance.ToJsonValue(allocator), allocator);
fittingObject.AddMember("AlgorithmName", rapidjson::Value(m_algorithmName.toStdString().c_str(), allocator).Move(), allocator);
fittingObject.AddMember("SurrogateScreeningEnabled", m_surrogateScreeningEnabled, allocator);
// 多井配置仍存放在原自动拟合节点中,敏感性配置复用同一序列化。
rapidjson::Value parameters(rapidjson::kArrayType);
for(int i = 0; i < m_modelParameters.size(); ++i) {
const nmFitParameter& p = m_modelParameters[i];
rapidjson::Value item(rapidjson::kObjectType);
item.AddMember("WellCode", rapidjson::Value(p.wellCode.toUtf8().constData(), allocator).Move(), allocator);
item.AddMember("WellName", rapidjson::Value(p.wellName.toUtf8().constData(), allocator).Move(), allocator);
item.AddMember("Type", p.type, allocator);
item.AddMember("Selected", p.selected, allocator);
item.AddMember("Initial", p.initial, allocator);
item.AddMember("Lower", p.lower, allocator);
item.AddMember("Upper", p.upper, allocator);
parameters.PushBack(item, allocator);
}
fittingObject.AddMember("ModelParameters", parameters, allocator);
return fittingObject;
}
void nmDataAutomaticFitting::FromJsonValue(const rapidjson::Value& jsonValue)
{
// 缺失列表表示旧版单井设置;非法项不进入优化向量。
m_modelParameters.clear();
if(jsonValue.HasMember("ModelParameters") && jsonValue["ModelParameters"].IsArray()) {
const rapidjson::Value& items = jsonValue["ModelParameters"];
for(rapidjson::SizeType i = 0; i < items.Size(); ++i) {
const rapidjson::Value& item = items[i];
if(!item.IsObject() || !item.HasMember("Type") || !item["Type"].IsInt() ||
item["Type"].GetInt() < 0 || item["Type"].GetInt() > 5 ||
!item.HasMember("Initial") || !item["Initial"].IsNumber() ||
!item.HasMember("Lower") || !item["Lower"].IsNumber() ||
!item.HasMember("Upper") || !item["Upper"].IsNumber()) continue;
nmFitParameter p;
p.type = item["Type"].GetInt();
if(item.HasMember("WellCode") && item["WellCode"].IsString()) p.wellCode = QString::fromUtf8(item["WellCode"].GetString());
if(item.HasMember("WellName") && item["WellName"].IsString()) p.wellName = QString::fromUtf8(item["WellName"].GetString());
p.initial = item["Initial"].GetDouble();
p.lower = item["Lower"].GetDouble();
p.upper = item["Upper"].GetDouble();
if(!qIsFinite(p.initial) || !qIsFinite(p.lower) || !qIsFinite(p.upper) || p.lower > p.upper) continue;
p.selected = item.HasMember("Selected") && item["Selected"].IsBool() && item["Selected"].GetBool();
m_modelParameters.append(p);
}
}
// 反序列化参数选择标志
if (jsonValue.HasMember("PermeabilitySelected") && jsonValue["PermeabilitySelected"].IsBool()) {
m_permeabilitySelected = jsonValue["PermeabilitySelected"].GetBool();
}
if (jsonValue.HasMember("SkinSelected") && jsonValue["SkinSelected"].IsBool()) {
m_skinSelected = jsonValue["SkinSelected"].GetBool();
}
if (jsonValue.HasMember("WellboreStorageSelected") && jsonValue["WellboreStorageSelected"].IsBool()) {
m_wellboreStorageSelected = jsonValue["WellboreStorageSelected"].GetBool();
}
if (jsonValue.HasMember("PorositySelected") && jsonValue["PorositySelected"].IsBool()) {
m_porositySelected = jsonValue["PorositySelected"].GetBool();
}
if (jsonValue.HasMember("FractureConductivitySelected") && jsonValue["FractureConductivitySelected"].IsBool()) {
m_fractureConductivitySelected = jsonValue["FractureConductivitySelected"].GetBool();
}
if (jsonValue.HasMember("FractureHalfLengthSelected") && jsonValue["FractureHalfLengthSelected"].IsBool()) {
m_fractureHalfLengthSelected = jsonValue["FractureHalfLengthSelected"].GetBool();
}
// 反序列化参数最大值
if (jsonValue.HasMember("PermeabilityMax") && jsonValue["PermeabilityMax"].IsObject()) {
m_permeabilityMax.FromJsonValue(jsonValue["PermeabilityMax"]);
// 自动拟合上下限统一按数据层基准单位mD解释,不兼容旧JSON的D数值。
m_permeabilityMax.setUnit("mD");
}
if (jsonValue.HasMember("SkinMax") && jsonValue["SkinMax"].IsObject()) {
m_skinMax.FromJsonValue(jsonValue["SkinMax"]);
}
if (jsonValue.HasMember("WellboreStorageMax") && jsonValue["WellboreStorageMax"].IsObject()) {
m_wellboreStorageMax.FromJsonValue(jsonValue["WellboreStorageMax"]);
}
if (jsonValue.HasMember("PorosityMax") && jsonValue["PorosityMax"].IsObject()) {
m_porosityMax.FromJsonValue(jsonValue["PorosityMax"]);
}
if (jsonValue.HasMember("FractureConductivityMax") && jsonValue["FractureConductivityMax"].IsObject()) {
m_fractureConductivityMax.FromJsonValue(jsonValue["FractureConductivityMax"]);
}
if (jsonValue.HasMember("FractureHalfLengthMax") && jsonValue["FractureHalfLengthMax"].IsObject()) {
m_fractureHalfLengthMax.FromJsonValue(jsonValue["FractureHalfLengthMax"]);
}
// 反序列化参数最小值
if (jsonValue.HasMember("PermeabilityMin") && jsonValue["PermeabilityMin"].IsObject()) {
m_permeabilityMin.FromJsonValue(jsonValue["PermeabilityMin"]);
m_permeabilityMin.setUnit("mD");
}
if (jsonValue.HasMember("SkinMin") && jsonValue["SkinMin"].IsObject()) {
m_skinMin.FromJsonValue(jsonValue["SkinMin"]);
}
if (jsonValue.HasMember("WellboreStorageMin") && jsonValue["WellboreStorageMin"].IsObject()) {
m_wellboreStorageMin.FromJsonValue(jsonValue["WellboreStorageMin"]);
}
if (jsonValue.HasMember("PorosityMin") && jsonValue["PorosityMin"].IsObject()) {
m_porosityMin.FromJsonValue(jsonValue["PorosityMin"]);
}
if (jsonValue.HasMember("FractureConductivityMin") && jsonValue["FractureConductivityMin"].IsObject()) {
m_fractureConductivityMin.FromJsonValue(jsonValue["FractureConductivityMin"]);
}
if (jsonValue.HasMember("FractureHalfLengthMin") && jsonValue["FractureHalfLengthMin"].IsObject()) {
m_fractureHalfLengthMin.FromJsonValue(jsonValue["FractureHalfLengthMin"]);
}
// 反序列化迭代参数
if (jsonValue.HasMember("IterationCount") && jsonValue["IterationCount"].IsObject()) {
m_iterationCount.FromJsonValue(jsonValue["IterationCount"]);
}
if (jsonValue.HasMember("ErrorTolerance") && jsonValue["ErrorTolerance"].IsObject()) {
m_errorTolerance.FromJsonValue(jsonValue["ErrorTolerance"]);
}
if (jsonValue.HasMember("AlgorithmName") && jsonValue["AlgorithmName"].IsString()) {
m_algorithmName = QString::fromUtf8(jsonValue["AlgorithmName"].GetString());
}
if (jsonValue.HasMember("SurrogateScreeningEnabled") && jsonValue["SurrogateScreeningEnabled"].IsBool()) {
m_surrogateScreeningEnabled = jsonValue["SurrogateScreeningEnabled"].GetBool();
}
}
// Getter and Setter implementations for parameter selection flags
bool nmDataAutomaticFitting::getPermeabilitySelected() const { return m_permeabilitySelected; }
void nmDataAutomaticFitting::setPermeabilitySelected(bool selected) { m_permeabilitySelected = selected; }
bool nmDataAutomaticFitting::getSkinSelected() const { return m_skinSelected; }
void nmDataAutomaticFitting::setSkinSelected(bool selected) { m_skinSelected = selected; }
bool nmDataAutomaticFitting::getWellboreStorageSelected() const { return m_wellboreStorageSelected; }
void nmDataAutomaticFitting::setWellboreStorageSelected(bool selected) { m_wellboreStorageSelected = selected; }
bool nmDataAutomaticFitting::getPorositySelected() const { return m_porositySelected; }
void nmDataAutomaticFitting::setPorositySelected(bool selected) { m_porositySelected = selected; }
bool nmDataAutomaticFitting::getFractureConductivitySelected() const { return m_fractureConductivitySelected; }
void nmDataAutomaticFitting::setFractureConductivitySelected(bool selected) { m_fractureConductivitySelected = selected; }
bool nmDataAutomaticFitting::getFractureHalfLengthSelected() const { return m_fractureHalfLengthSelected; }
void nmDataAutomaticFitting::setFractureHalfLengthSelected(bool selected) { m_fractureHalfLengthSelected = selected; }
// Getter and Setter implementations for Max values
nmDataAttribute& nmDataAutomaticFitting::getPermeabilityMax() { return m_permeabilityMax; }
void nmDataAutomaticFitting::setPermeabilityMax(const nmDataAttribute& permeabilityMax) { m_permeabilityMax = permeabilityMax; }
nmDataAttribute& nmDataAutomaticFitting::getSkinMax() { return m_skinMax; }
void nmDataAutomaticFitting::setSkinMax(const nmDataAttribute& skinMax) { m_skinMax = skinMax; }
nmDataAttribute& nmDataAutomaticFitting::getWellboreStorageMax() { return m_wellboreStorageMax; }
void nmDataAutomaticFitting::setWellboreStorageMax(const nmDataAttribute& wellboreStorageMax) { m_wellboreStorageMax = wellboreStorageMax; }
nmDataAttribute& nmDataAutomaticFitting::getPorosityMax() { return m_porosityMax; }
void nmDataAutomaticFitting::setPorosityMax(const nmDataAttribute& porosityMax) { m_porosityMax = porosityMax; }
nmDataAttribute& nmDataAutomaticFitting::getFractureConductivityMax() { return m_fractureConductivityMax; }
void nmDataAutomaticFitting::setFractureConductivityMax(const nmDataAttribute& fractureConductivityMax) { m_fractureConductivityMax = fractureConductivityMax; }
nmDataAttribute& nmDataAutomaticFitting::getFractureHalfLengthMax() { return m_fractureHalfLengthMax; }
void nmDataAutomaticFitting::setFractureHalfLengthMax(const nmDataAttribute& fractureHalfLengthMax) { m_fractureHalfLengthMax = fractureHalfLengthMax; }
// Getter and Setter implementations for Min values
nmDataAttribute& nmDataAutomaticFitting::getPermeabilityMin() { return m_permeabilityMin; }
void nmDataAutomaticFitting::setPermeabilityMin(const nmDataAttribute& permeabilityMin) { m_permeabilityMin = permeabilityMin; }
nmDataAttribute& nmDataAutomaticFitting::getSkinMin() { return m_skinMin; }
void nmDataAutomaticFitting::setSkinMin(const nmDataAttribute& skinMin) { m_skinMin = skinMin; }
nmDataAttribute& nmDataAutomaticFitting::getWellboreStorageMin() { return m_wellboreStorageMin; }
void nmDataAutomaticFitting::setWellboreStorageMin(const nmDataAttribute& wellboreStorageMin) { m_wellboreStorageMin = wellboreStorageMin; }
nmDataAttribute& nmDataAutomaticFitting::getPorosityMin() { return m_porosityMin; }
void nmDataAutomaticFitting::setPorosityMin(const nmDataAttribute& porosityMin) { m_porosityMin = porosityMin; }
nmDataAttribute& nmDataAutomaticFitting::getFractureConductivityMin() { return m_fractureConductivityMin; }
void nmDataAutomaticFitting::setFractureConductivityMin(const nmDataAttribute& fractureConductivityMin) { m_fractureConductivityMin = fractureConductivityMin; }
nmDataAttribute& nmDataAutomaticFitting::getFractureHalfLengthMin() { return m_fractureHalfLengthMin; }
void nmDataAutomaticFitting::setFractureHalfLengthMin(const nmDataAttribute& fractureHalfLengthMin) { m_fractureHalfLengthMin = fractureHalfLengthMin; }
// Getter and Setter implementations for iteration parameters
nmDataAttribute& nmDataAutomaticFitting::getIterationCount() { return m_iterationCount; }
void nmDataAutomaticFitting::setIterationCount(const nmDataAttribute& iterationCount) { m_iterationCount = iterationCount; }
nmDataAttribute& nmDataAutomaticFitting::getErrorTolerance() { return m_errorTolerance; }
void nmDataAutomaticFitting::setErrorTolerance(const nmDataAttribute& errorTolerance) { m_errorTolerance = errorTolerance; }
QString nmDataAutomaticFitting::getAlgorithmName() const { return m_algorithmName; }
void nmDataAutomaticFitting::setAlgorithmName(const QString& algorithmName) { m_algorithmName = algorithmName; }
bool nmDataAutomaticFitting::getSurrogateScreeningEnabled() const { return m_surrogateScreeningEnabled; }
void nmDataAutomaticFitting::setSurrogateScreeningEnabled(bool enabled) { m_surrogateScreeningEnabled = enabled; }
QString nmFitParameter::name() const
{
// 井参数携带井名,共用参数保持原名称和翻译。
const char* names[] = {"Permeability", "Skin", "Wellbore storage", "Porosity", "Fracture conductivity", "Fracture half length"};
const QString label = QCoreApplication::translate("nmWxAutomaticFitting", names[type]);
return wellCode.isEmpty() ? label : wellName + " / " + label;
}
QString nmFitParameter::code() const
{
// 结果面板继续使用已有 XML 参数编码。
const char* codes[] = {"K", "Skin", "C", "phi", "Dfc", "FractureHalfLength"};
return codes[type];
}
QString nmFitParameter::unit() const
{
// 与既有六参数的基准单位一致。
const char* units[] = {"mD", "", "m^3/MPa", "", "mD.m", "m"};
return units[type];
}
QString nmFitParameter::samplingKey() const
{
// 同井同参数才与敏感性采样互斥。
const QString names[] = {"k", "Skin", "C", QString(QChar(0x03c6)), "Dfc", "FractureHalfLength"};
return wellCode.isEmpty() ? names[type] : wellCode + "/" + names[type];
}
QVector<nmFitParameter>& nmDataAutomaticFitting::getModelParameters()
{
// 窗口在自己的配置副本上编辑。
return m_modelParameters;
}
const QVector<nmFitParameter>& nmDataAutomaticFitting::getModelParameters() const
{
// 后台计算只读取启动前冻结的设置。
return m_modelParameters;
}
bool nmDataAutomaticFitting::hasSelectedParameters() const
{
// 新配置检查完整多井列表,旧配置兼容原六个勾选标志。
if(!m_modelParameters.isEmpty()) {
for(int i = 0; i < m_modelParameters.size(); ++i)
if(m_modelParameters[i].selected) return true;
return false;
}
return m_permeabilitySelected || m_skinSelected || m_wellboreStorageSelected ||
m_porositySelected || m_fractureConductivitySelected || m_fractureHalfLengthSelected;
}