#include "nmReservoirParameterCatalog.h" #include "nmReservoirPropertiesDataSource.h" #include "nmAttrRegistry.h" #include "nmDataAttribute.h" #include "nmDataPerforation.h" #include namespace { /* * Qt 4.8的lupdate无法跟踪editorText()的间接参数,以下标记只用于 * 收集中英文资源;运行时仍由同一翻译上下文返回文字。 */ static const char* const s_pCatalogTranslationMarkers[] = { QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Reservoir type"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Homogeneous"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Dual porosity pseudo steady state"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Fault flow model"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Region flow model"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Leaky"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Composite limit"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Fracture flow model"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Finite conductivity"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Infinite conductivity"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Position and wellbore"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Storage and fracture"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Basic properties"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Fluid parameters"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Compression and saturation"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Reservoir parameters"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Vertical well"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Vertical fractured well"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Horizontal fractured well"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Dual-medium parameters"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Geometry"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Flow properties"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Conductivity properties"), QT_TRANSLATE_NOOP("nmWxReservoirPropertiesEditor", "Region properties") }; /** @brief 返回当前语言下的界面文字。 */ QString editorText(const char* pText) { Q_UNUSED(s_pCatalogTranslationMarkers); return QCoreApplication::translate("nmWxReservoirPropertiesEditor", pText); } /** @brief 创建一个稳定枚举选项。 */ nmReservoirEnumOption enumOption(const QString& sCode, const char* pText) { nmReservoirEnumOption oOption; oOption.m_sCode = sCode; oOption.m_sText = editorText(pText); return oOption; } /** @brief 创建一个数值字段描述。 */ nmReservoirParameterFieldInfo numericField( const QString& sParameterId, const QString& sBaseParameterId, nmReservoirParameterEditorType eEditorType) { nmReservoirParameterFieldInfo oField; oField.m_sParameterId = sParameterId; oField.m_sBaseParameterId = sBaseParameterId; oField.m_eEditorType = eEditorType; oField.m_bUnitEnabled = true; return oField; } /** @brief 创建一个浮点数字段描述。 */ nmReservoirParameterFieldInfo numericField( const QString& sParameterId, const QString& sBaseParameterId) { return numericField(sParameterId, sBaseParameterId, NM_RESERVOIR_EDITOR_NUMBER); } /** @brief 创建一个明确不显示单位的浮点数字段。 */ nmReservoirParameterFieldInfo unitlessNumericField( const QString& sParameterId, const QString& sBaseParameterId) { nmReservoirParameterFieldInfo oField = numericField(sParameterId, sBaseParameterId); oField.m_bUnitEnabled = false; return oField; } /** @brief 创建储层类型字段。 */ nmReservoirParameterFieldInfo reservoirModelField( const QString& sParameterId) { nmReservoirParameterFieldInfo oField; oField.m_sParameterId = sParameterId; oField.m_sLabel = editorText("Reservoir type"); oField.m_eEditorType = NM_RESERVOIR_EDITOR_ENUM; oField.m_bUnitEnabled = false; oField.m_listOptions.append(enumOption("homogeneous", "Homogeneous")); oField.m_listOptions.append(enumOption( "dual_porosity_pss", "Dual porosity pseudo steady state")); return oField; } /** @brief 创建断层或复合区流动模型字段。 */ nmReservoirParameterFieldInfo leakageModelField( const QString& sParameterId, const char* pLabel) { nmReservoirParameterFieldInfo oField; oField.m_sParameterId = sParameterId; oField.m_sLabel = editorText(pLabel); oField.m_eEditorType = NM_RESERVOIR_EDITOR_ENUM; oField.m_bUnitEnabled = false; oField.m_listOptions.append(enumOption("leaky", "Leaky")); oField.m_listOptions.append(enumOption( "composite_limit", "Composite limit")); return oField; } /** @brief 创建裂缝导流模型字段。 */ nmReservoirParameterFieldInfo fractureModelField( const QString& sParameterId) { nmReservoirParameterFieldInfo oField; oField.m_sParameterId = sParameterId; oField.m_sLabel = editorText("Fracture flow model"); oField.m_eEditorType = NM_RESERVOIR_EDITOR_ENUM; oField.m_bUnitEnabled = false; oField.m_listOptions.append(enumOption( "finite_conductivity", "Finite conductivity")); oField.m_listOptions.append(enumOption( "infinite_conductivity", "Infinite conductivity")); return oField; } /** @brief 创建页面上的一个参数分组。 */ nmReservoirParameterGroupInfo parameterGroup( const char* pTitle, int nRow, int nColumn, int nColumnSpan) { nmReservoirParameterGroupInfo oGroup; oGroup.m_sTitle = editorText(pTitle); oGroup.m_nRow = nRow; oGroup.m_nColumn = nColumn; oGroup.m_nRowSpan = 1; oGroup.m_nColumnSpan = nColumnSpan; oGroup.m_bValueRightAligned = false; return oGroup; } /** @brief 为参数ID添加对象编码前缀。 */ QString prefixed(const QString& sObjectCode, const char* pParameterId) { return sObjectCode + "_" + QString::fromLatin1(pParameterId); } /** @brief 生成无井编码时的会话编码。 */ QString wellCode(const nmDataWellBase& oWell, const QString& sFallbackPrefix, int nIndex) { QString sCode = oWell.getWellCode(); if (sCode.isEmpty()) { sCode = QString("%1%2").arg(sFallbackPrefix) .arg(nIndex + 1, 4, 10, QChar('0')); } return sCode; } /** @brief 创建井对象的分组描述。 */ void createWellGroups(nmReservoirPropertyObjectInfo& oInfo, NM_WELL_MODEL eWellType, bool bHasPerforation) { nmReservoirParameterGroupInfo oPosition = parameterGroup("Position and wellbore", 0, 0, 1); oPosition.m_listFields << numericField(prefixed(oInfo.m_sObjectCode, "W_X"), "W_X") << numericField(prefixed(oInfo.m_sObjectCode, "W_Y"), "W_Y") << numericField(prefixed(oInfo.m_sObjectCode, "W_Rw"), "W_Rw"); if (bHasPerforation) { oPosition.m_listFields.append(numericField( prefixed(oInfo.m_sObjectCode, "W_Skin"), "W_Skin")); } nmReservoirParameterGroupInfo oStorage = parameterGroup("Storage and fracture", 0, 1, 1); oStorage.m_listFields.append(numericField( prefixed(oInfo.m_sObjectCode, "W_C"), "W_C")); if (eWellType == Vertical_Fractured_Well) { oStorage.m_listFields << numericField(prefixed(oInfo.m_sObjectCode, "W_FractureHalfLength"), "W_FractureHalfLength") << numericField(prefixed(oInfo.m_sObjectCode, "W_FractureAngle"), "W_FractureAngle") << numericField(prefixed(oInfo.m_sObjectCode, "W_Dfc"), "W_Dfc"); } else if (eWellType == Horizontal_Fractured_Well) { oStorage.m_listFields << numericField(prefixed(oInfo.m_sObjectCode, "W_WellLength"), "W_WellLength") << numericField(prefixed(oInfo.m_sObjectCode, "W_DrainAngle"), "W_DrainAngle") << numericField(prefixed(oInfo.m_sObjectCode, "W_NumberOfFractures"), "W_NumberOfFractures", NM_RESERVOIR_EDITOR_INTEGER) << numericField(prefixed(oInfo.m_sObjectCode, "W_FractureHalfLength"), "W_FractureHalfLength") << numericField(prefixed(oInfo.m_sObjectCode, "W_FractureAngle"), "W_FractureAngle") << numericField(prefixed(oInfo.m_sObjectCode, "W_Dfc"), "W_Dfc"); } oInfo.m_listGroups << oPosition << oStorage; } /** @brief 注册一口井的全部可编辑数值属性。 */ void registerWell(nmAttrRegistry* pRegistry, nmDataWellBase& oWell, const QString& sCode) { pRegistry->regAttr(prefixed(sCode, "W_X"), &oWell.getX()); pRegistry->regAttr(prefixed(sCode, "W_Y"), &oWell.getY()); pRegistry->regAttr(prefixed(sCode, "W_Rw"), &oWell.getRadius()); pRegistry->regAttr(prefixed(sCode, "W_C"), &oWell.getWellboreStorage()); if (oWell.getPerforationCount() > 0 && oWell.getPerforation(0) != nullptr) { pRegistry->regAttr(prefixed(sCode, "W_Skin"), &oWell.getPerforation(0)->getSkin()); } } /** @brief 判断对象描述中是否包含指定枚举字段。 */ bool containsEnumField(const nmReservoirPropertyObjectInfo& oInfo, const QString& sParameterId) { for (int nGroupIndex = 0; nGroupIndex < oInfo.m_listGroups.size(); ++nGroupIndex) { const nmReservoirParameterGroupInfo& oGroup = oInfo.m_listGroups[nGroupIndex]; for (int nFieldIndex = 0; nFieldIndex < oGroup.m_listFields.size(); ++nFieldIndex) { const nmReservoirParameterFieldInfo& oField = oGroup.m_listFields[nFieldIndex]; if (oField.m_eEditorType == NM_RESERVOIR_EDITOR_ENUM && oField.m_sParameterId == sParameterId) { return true; } } } return false; } } void nmReservoirParameterCatalog::registerSnapshot( nmAttrRegistry* pRegistry, nmReservoirPropertiesSnapshot& oSnapshot) { if (pRegistry == nullptr) { return; } // 第一步:重新建立编辑会话独占的注册表,杜绝与实时数据交叉连接。 pRegistry->clear(); pRegistry->regAttr("h", &oSnapshot.m_oReservoir.getThickness()); pRegistry->regAttr("Pi", &oSnapshot.m_oReservoir.getInitialPressure()); pRegistry->regAttr("K", &oSnapshot.m_oReservoir.getPermeability()); pRegistry->regAttr("phi", &oSnapshot.m_oReservoir.getPorosity()); pRegistry->regAttr("Cti", &oSnapshot.m_oReservoir.getCt()); pRegistry->regAttr("Cf", &oSnapshot.m_oReservoir.getCf()); pRegistry->regAttr("Soi", &oSnapshot.m_oReservoir.getSoi()); pRegistry->regAttr("Swi", &oSnapshot.m_oReservoir.getSwi()); pRegistry->regAttr("Bo", &oSnapshot.m_oReservoir.getBo()); pRegistry->regAttr("Miuo", &oSnapshot.m_oReservoir.getMiuo()); pRegistry->regAttr("KxKy", &oSnapshot.m_oReservoir.getKxKy()); // 第二步:注册求解器支持的三类井及其压裂参数。 for (int nIndex = 0; nIndex < oSnapshot.m_vecVerticalWells.size(); ++nIndex) { nmDataVerticalWell& oWell = oSnapshot.m_vecVerticalWells[nIndex]; registerWell(pRegistry, oWell, wellCode(oWell, "VWELL", nIndex)); } for (int nIndex = 0; nIndex < oSnapshot.m_vecVerticalFracturedWells.size(); ++nIndex) { nmDataVerticalFracturedWell& oWell = oSnapshot.m_vecVerticalFracturedWells[nIndex]; QString sCode = wellCode(oWell, "VFWELL", nIndex); registerWell(pRegistry, oWell, sCode); pRegistry->regAttr(prefixed(sCode, "W_FractureHalfLength"), &oWell.getFractureHalfLength()); pRegistry->regAttr(prefixed(sCode, "W_FractureAngle"), &oWell.getFractureAngle()); pRegistry->regAttr(prefixed(sCode, "W_Dfc"), &oWell.getDfc()); } for (int nIndex = 0; nIndex < oSnapshot.m_vecHorizontalFracturedWells.size(); ++nIndex) { nmDataHorizontalFracturedWell& oWell = oSnapshot.m_vecHorizontalFracturedWells[nIndex]; QString sCode = wellCode(oWell, "HFWELL", nIndex); registerWell(pRegistry, oWell, sCode); pRegistry->regAttr(prefixed(sCode, "W_WellLength"), &oWell.getWellLength()); pRegistry->regAttr(prefixed(sCode, "W_DrainAngle"), &oWell.getDrainAngle()); pRegistry->regAttr(prefixed(sCode, "W_NumberOfFractures"), &oWell.getNumberOfFractures()); pRegistry->regAttr(prefixed(sCode, "W_FractureHalfLength"), &oWell.getFractureHalfLength()); pRegistry->regAttr(prefixed(sCode, "W_FractureAngle"), &oWell.getFractureAngle()); pRegistry->regAttr(prefixed(sCode, "W_Dfc"), &oWell.getDfc()); } // 第三步:注册区域标记和复合区数值参数。 for (int nIndex = 0; nIndex < oSnapshot.m_vecRegionMarks.size(); ++nIndex) { QString sCode = QString("RMARK%1") .arg(nIndex + 1, 4, 10, QChar('0')); nmDataRegionMark& oMark = oSnapshot.m_vecRegionMarks[nIndex]; pRegistry->regAttr(prefixed(sCode, "RM_ComW"), &oMark.getComW()); pRegistry->regAttr(prefixed(sCode, "RM_ComKr"), &oMark.getComKr()); pRegistry->regAttr(prefixed(sCode, "RM_NetToGross"), &oMark.getNetToGross()); } for (int nIndex = 0; nIndex < oSnapshot.m_vecRegions.size(); ++nIndex) { QString sCode = QString("REGION%1") .arg(nIndex + 1, 4, 10, QChar('0')); pRegistry->regAttr(prefixed(sCode, "R_Leakage"), &oSnapshot.m_vecRegions[nIndex] .getRegionLeakage()); } // 第四步:注册断层和普通裂缝;DFN由专用功能维护。 for (int nIndex = 0; nIndex < oSnapshot.m_vecFaults.size(); ++nIndex) { QString sCode = QString("FAULT%1") .arg(nIndex + 1, 4, 10, QChar('0')); nmDataFault& oFault = oSnapshot.m_vecFaults[nIndex]; pRegistry->regAttr(prefixed(sCode, "FT_X0"), &oFault.getStartX()); pRegistry->regAttr(prefixed(sCode, "FT_Y0"), &oFault.getStartY()); pRegistry->regAttr(prefixed(sCode, "FT_X1"), &oFault.getEndX()); pRegistry->regAttr(prefixed(sCode, "FT_Y1"), &oFault.getEndY()); pRegistry->regAttr(prefixed(sCode, "FT_Leakage"), &oFault.getFaultLeakage()); } int nVisibleFracture = 0; for (int nIndex = 0; nIndex < oSnapshot.m_vecFractures.size(); ++nIndex) { nmDataFracture& oFracture = oSnapshot.m_vecFractures[nIndex]; if (oFracture.getFractureType().getValue().toString() == "DFN") { continue; } QString sCode = QString("FRAC%1") .arg(++nVisibleFracture, 4, 10, QChar('0')); pRegistry->regAttr(prefixed(sCode, "F_X0"), &oFracture.getStartX()); pRegistry->regAttr(prefixed(sCode, "F_Y0"), &oFracture.getStartY()); pRegistry->regAttr(prefixed(sCode, "F_X1"), &oFracture.getEndX()); pRegistry->regAttr(prefixed(sCode, "F_Y1"), &oFracture.getEndY()); pRegistry->regAttr(prefixed(sCode, "F_FC"), &oFracture.getFractureDfc()); pRegistry->regAttr(prefixed(sCode, "F_DW"), &oFracture.getFractureDw()); } } QList nmReservoirParameterCatalog::createObjectInfos( nmReservoirPropertiesCategory eCategory, nmReservoirPropertiesSnapshot& oSnapshot) { QList listInfos; if (eCategory == NM_RESERVOIR_PAGE_RESERVOIR) { nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_RESERVOIR; oInfo.m_nSourceIndex = 0; oInfo.m_sObjectCode = "RESERVOIR"; oInfo.m_sDisplayName = editorText("Reservoir parameters"); nmReservoirParameterGroupInfo oBasic = parameterGroup("Basic properties", 0, 0, 1); oBasic.m_nRowSpan = 2; oBasic.m_bValueRightAligned = true; oBasic.m_listFields << numericField("Pi", "Pi") << numericField("K", "K") << numericField("h", "h") << numericField("phi", "phi"); nmReservoirParameterGroupInfo oFluid = parameterGroup("Fluid parameters", 0, 1, 1); oFluid.m_listFields << reservoirModelField("ReservoirType") << numericField("Miuo", "Miuo") << unitlessNumericField("Bo", "Bo") << numericField("KxKy", "KxKy"); nmReservoirParameterGroupInfo oCompression = parameterGroup("Compression and saturation", 1, 1, 1); oCompression.m_listFields << numericField("Cti", "Cti") << numericField("Cf", "Cf") << numericField("Soi", "Soi") << numericField("Swi", "Swi"); oInfo.m_listGroups << oBasic << oFluid << oCompression; listInfos.append(oInfo); return listInfos; } if (eCategory == NM_RESERVOIR_PAGE_WELL) { for (int nIndex = 0; nIndex < oSnapshot.m_vecVerticalWells.size(); ++nIndex) { nmDataVerticalWell& oWell = oSnapshot.m_vecVerticalWells[nIndex]; nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_VERTICAL_WELL; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = wellCode(oWell, "VWELL", nIndex); oInfo.m_sDisplayName = oWell.getWellName() + " - " + editorText("Vertical well"); createWellGroups(oInfo, Vertical_Well, oWell.getPerforationCount() > 0); listInfos.append(oInfo); } for (int nIndex = 0; nIndex < oSnapshot.m_vecVerticalFracturedWells.size(); ++nIndex) { nmDataVerticalFracturedWell& oWell = oSnapshot.m_vecVerticalFracturedWells[nIndex]; nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_VERTICAL_FRAC_WELL; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = wellCode(oWell, "VFWELL", nIndex); oInfo.m_sDisplayName = oWell.getWellName() + " - " + editorText("Vertical fractured well"); createWellGroups(oInfo, Vertical_Fractured_Well, oWell.getPerforationCount() > 0); listInfos.append(oInfo); } for (int nIndex = 0; nIndex < oSnapshot.m_vecHorizontalFracturedWells.size(); ++nIndex) { nmDataHorizontalFracturedWell& oWell = oSnapshot.m_vecHorizontalFracturedWells[nIndex]; nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_HORIZONTAL_FRAC_WELL; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = wellCode(oWell, "HFWELL", nIndex); oInfo.m_sDisplayName = oWell.getWellName() + " - " + editorText("Horizontal fractured well"); createWellGroups(oInfo, Horizontal_Fractured_Well, oWell.getPerforationCount() > 0); listInfos.append(oInfo); } return listInfos; } if (eCategory == NM_RESERVOIR_PAGE_REGION_MARK) { for (int nIndex = 0; nIndex < oSnapshot.m_vecRegionMarks.size(); ++nIndex) { nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_REGION_MARK; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = QString("RMARK%1") .arg(nIndex + 1, 4, 10, QChar('0')); oInfo.m_sDisplayName = oSnapshot.m_vecRegionMarks[nIndex].getRegionMarkName(); nmReservoirParameterGroupInfo oDual = parameterGroup("Dual-medium parameters", 0, 0, 2); oDual.m_listFields << reservoirModelField(prefixed( oInfo.m_sObjectCode, "RM_ReservoirType")) << numericField(prefixed( oInfo.m_sObjectCode, "RM_ComW"), "RM_ComW") << numericField(prefixed( oInfo.m_sObjectCode, "RM_ComKr"), "RM_ComKr") << numericField(prefixed( oInfo.m_sObjectCode, "RM_NetToGross"), "RM_NetToGross"); oInfo.m_listGroups.append(oDual); listInfos.append(oInfo); } return listInfos; } if (eCategory == NM_RESERVOIR_PAGE_FAULT) { for (int nIndex = 0; nIndex < oSnapshot.m_vecFaults.size(); ++nIndex) { nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_FAULT; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = QString("FAULT%1") .arg(nIndex + 1, 4, 10, QChar('0')); oInfo.m_sDisplayName = oSnapshot.m_vecFaults[nIndex].getFaultName(); nmReservoirParameterGroupInfo oGeometry = parameterGroup("Geometry", 0, 0, 1); oGeometry.m_listFields << numericField(prefixed( oInfo.m_sObjectCode, "FT_X0"), "FT_X0") << numericField(prefixed( oInfo.m_sObjectCode, "FT_Y0"), "FT_Y0") << numericField(prefixed( oInfo.m_sObjectCode, "FT_X1"), "FT_X1") << numericField(prefixed( oInfo.m_sObjectCode, "FT_Y1"), "FT_Y1"); nmReservoirParameterGroupInfo oFlow = parameterGroup("Flow properties", 0, 1, 1); oFlow.m_listFields << leakageModelField(prefixed( oInfo.m_sObjectCode, "FT_FlowModel"), "Fault flow model") << numericField(prefixed( oInfo.m_sObjectCode, "FT_Leakage"), "FT_Leakage"); oInfo.m_listGroups << oGeometry << oFlow; listInfos.append(oInfo); } return listInfos; } if (eCategory == NM_RESERVOIR_PAGE_FRACTURE) { int nVisibleFracture = 0; for (int nIndex = 0; nIndex < oSnapshot.m_vecFractures.size(); ++nIndex) { nmDataFracture& oFracture = oSnapshot.m_vecFractures[nIndex]; if (oFracture.getFractureType().getValue().toString() == "DFN") { continue; } nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_FRACTURE; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = QString("FRAC%1") .arg(++nVisibleFracture, 4, 10, QChar('0')); oInfo.m_sDisplayName = oFracture.getFractureName(); nmReservoirParameterGroupInfo oGeometry = parameterGroup("Geometry", 0, 0, 1); oGeometry.m_listFields << numericField(prefixed( oInfo.m_sObjectCode, "F_X0"), "F_X0") << numericField(prefixed( oInfo.m_sObjectCode, "F_Y0"), "F_Y0") << numericField(prefixed( oInfo.m_sObjectCode, "F_X1"), "F_X1") << numericField(prefixed( oInfo.m_sObjectCode, "F_Y1"), "F_Y1"); nmReservoirParameterGroupInfo oFlow = parameterGroup("Conductivity properties", 0, 1, 1); oFlow.m_listFields << fractureModelField(prefixed( oInfo.m_sObjectCode, "F_FlowModel")) << numericField(prefixed( oInfo.m_sObjectCode, "F_FC"), "F_FC") << numericField(prefixed( oInfo.m_sObjectCode, "F_DW"), "F_DW"); oInfo.m_listGroups << oGeometry << oFlow; listInfos.append(oInfo); } return listInfos; } if (eCategory == NM_RESERVOIR_PAGE_COMPOSITE_REGION) { for (int nIndex = 0; nIndex < oSnapshot.m_vecRegions.size(); ++nIndex) { nmReservoirPropertyObjectInfo oInfo; oInfo.m_eCategory = eCategory; oInfo.m_eObjectType = NM_RESERVOIR_OBJECT_REGION; oInfo.m_nSourceIndex = nIndex; oInfo.m_sObjectCode = QString("REGION%1") .arg(nIndex + 1, 4, 10, QChar('0')); oInfo.m_sDisplayName = oSnapshot.m_vecRegions[nIndex].getRegoinName(); nmReservoirParameterGroupInfo oRegion = parameterGroup("Region properties", 0, 0, 2); oRegion.m_listFields << leakageModelField(prefixed( oInfo.m_sObjectCode, "R_FlowModel"), "Region flow model") << numericField(prefixed( oInfo.m_sObjectCode, "R_Leakage"), "R_Leakage"); oInfo.m_listGroups.append(oRegion); listInfos.append(oInfo); } } return listInfos; } QString nmReservoirParameterCatalog::enumCodeFromStoredValue( const QString& sParameterId, const QString& sStoredValue) { QString sValue = sStoredValue.trimmed().toLower(); if (sParameterId.endsWith("ReservoirType")) { return sValue.contains("dual") ? "dual_porosity_pss" : "homogeneous"; } if (sParameterId.endsWith("F_FlowModel")) { return sValue.contains("infinite") ? "infinite_conductivity" : "finite_conductivity"; } if (sParameterId.endsWith("FlowModel")) { return sValue.contains("leaky") ? "leaky" : "composite_limit"; } return QString(); } QString nmReservoirParameterCatalog::storedValueFromEnumCode( const QString& sParameterId, const QString& sCode) { if (sParameterId.endsWith("ReservoirType")) { return sCode == "dual_porosity_pss" ? "Dual porosity pseudo steady state" : "Homogeneous"; } if (sParameterId.endsWith("F_FlowModel")) { return sCode == "infinite_conductivity" ? "Infinite Conductivity" : "Finite Conductivity"; } if (sParameterId.endsWith("FlowModel")) { return sCode == "leaky" ? "Leaky" : "Composite limit"; } return QString(); } QString nmReservoirParameterCatalog::enumCode( const nmReservoirPropertiesSnapshot& oSnapshot, const QString& sParameterId) { if (sParameterId == "ReservoirType") { nmDataReservoir& oReservoir = const_cast(oSnapshot.m_oReservoir); return enumCodeFromStoredValue( sParameterId, oReservoir.getReservoirType().getValue().toString()); } QList listAll; nmReservoirPropertiesSnapshot& oWritable = const_cast(oSnapshot); listAll << createObjectInfos(NM_RESERVOIR_PAGE_FAULT, oWritable) << createObjectInfos(NM_RESERVOIR_PAGE_FRACTURE, oWritable) << createObjectInfos(NM_RESERVOIR_PAGE_COMPOSITE_REGION, oWritable) << createObjectInfos(NM_RESERVOIR_PAGE_REGION_MARK, oWritable); for (int nInfoIndex = 0; nInfoIndex < listAll.size(); ++nInfoIndex) { const nmReservoirPropertyObjectInfo& oInfo = listAll[nInfoIndex]; if (!containsEnumField(oInfo, sParameterId)) { continue; } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_REGION_MARK) { nmDataRegionMark& oMark = oWritable.m_vecRegionMarks[oInfo.m_nSourceIndex]; return enumCodeFromStoredValue( sParameterId, oMark.getReservoirType().getValue().toString()); } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_FAULT) { nmDataFault& oFault = oWritable.m_vecFaults[oInfo.m_nSourceIndex]; return enumCodeFromStoredValue( sParameterId, oFault.getFaultFlowModel().getValue().toString()); } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_FRACTURE) { nmDataFracture& oFracture = oWritable.m_vecFractures[oInfo.m_nSourceIndex]; return enumCodeFromStoredValue( sParameterId, oFracture.getFractureFlowModel() .getValue().toString()); } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_REGION) { nmDataRegion& oRegion = oWritable.m_vecRegions[oInfo.m_nSourceIndex]; return enumCodeFromStoredValue( sParameterId, oRegion.getRegionFlowModel().getValue().toString()); } } return QString(); } bool nmReservoirParameterCatalog::setEnumCode( nmReservoirPropertiesSnapshot& oSnapshot, const QString& sParameterId, const QString& sCode) { QString sStoredValue = storedValueFromEnumCode(sParameterId, sCode); if (sStoredValue.isEmpty()) { return false; } if (sParameterId == "ReservoirType") { oSnapshot.m_oReservoir.getReservoirType() .setValue(sStoredValue); return true; } QList listAll; listAll << createObjectInfos(NM_RESERVOIR_PAGE_FAULT, oSnapshot) << createObjectInfos(NM_RESERVOIR_PAGE_FRACTURE, oSnapshot) << createObjectInfos(NM_RESERVOIR_PAGE_COMPOSITE_REGION, oSnapshot) << createObjectInfos(NM_RESERVOIR_PAGE_REGION_MARK, oSnapshot); for (int nInfoIndex = 0; nInfoIndex < listAll.size(); ++nInfoIndex) { const nmReservoirPropertyObjectInfo& oInfo = listAll[nInfoIndex]; if (!containsEnumField(oInfo, sParameterId)) { continue; } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_REGION_MARK) { oSnapshot.m_vecRegionMarks[oInfo.m_nSourceIndex] .getReservoirType().setValue(sStoredValue); return true; } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_FAULT) { oSnapshot.m_vecFaults[oInfo.m_nSourceIndex] .getFaultFlowModel().setValue(sStoredValue); return true; } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_FRACTURE) { oSnapshot.m_vecFractures[oInfo.m_nSourceIndex] .getFractureFlowModel().setValue(sStoredValue); return true; } if (oInfo.m_eObjectType == NM_RESERVOIR_OBJECT_REGION) { oSnapshot.m_vecRegions[oInfo.m_nSourceIndex] .getRegionFlowModel().setValue(sStoredValue); return true; } } return false; }