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++

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 "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;
}