diff --git a/ApplicationCode/Application/RiaFractureDefines.cpp b/ApplicationCode/Application/RiaFractureDefines.cpp index 6fdbd19253..74f3b87d49 100644 --- a/ApplicationCode/Application/RiaFractureDefines.cpp +++ b/ApplicationCode/Application/RiaFractureDefines.cpp @@ -38,3 +38,16 @@ QString RiaDefines::unitStringConductivity(RiaEclipseUnitTools::UnitSystem unitS default: return ""; } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaDefines::nonDarcyFlowAlpha(RiaEclipseUnitTools::UnitSystem unitSystem) +{ + switch (unitSystem) + { + case RiaEclipseUnitTools::UNITS_METRIC: return 2.24460e-10; + case RiaEclipseUnitTools::UNITS_FIELD: return 6.83352e-8; + default: return 0.0; + } +} diff --git a/ApplicationCode/Application/RiaFractureDefines.h b/ApplicationCode/Application/RiaFractureDefines.h index 7263302b2a..a87bbe5acf 100644 --- a/ApplicationCode/Application/RiaFractureDefines.h +++ b/ApplicationCode/Application/RiaFractureDefines.h @@ -26,4 +26,6 @@ namespace RiaDefines { QString conductivityResultName(); QString unitStringConductivity(RiaEclipseUnitTools::UnitSystem unitSystem); + +double nonDarcyFlowAlpha(RiaEclipseUnitTools::UnitSystem unitSystem); }; diff --git a/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.cpp index 0dbb68d214..9b5b2f46a4 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.cpp @@ -270,6 +270,18 @@ void RimEllipseFractureTemplate::setupFractureGridCells() m_fractureGrid->setJCellCount(numberOfCellsY); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +FractureWidthAndConductivity RimEllipseFractureTemplate::widthAndConductivityAtWellPathIntersection() const +{ + FractureWidthAndConductivity values; + values.m_width = m_width; + values.m_permeability = m_permeability; + + return values; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.h b/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.h index 842da494a6..6b400456b1 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.h +++ b/ApplicationCode/ProjectDataModel/Completions/RimEllipseFractureTemplate.h @@ -73,6 +73,9 @@ protected: private: void setupFractureGridCells(); + + virtual FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection() const override; + private: cvf::ref m_fractureGrid; diff --git a/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.cpp index bc907c7146..9806acf644 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.cpp @@ -18,6 +18,7 @@ #include "RimFractureTemplate.h" +#include "RiaFractureDefines.h" #include "RigTesselatorTools.h" #include "RimFracture.h" @@ -26,6 +27,7 @@ #include "cafPdmObject.h" #include "cafPdmUiDoubleSliderEditor.h" +#include "cafPdmUiTextEditor.h" #include "cvfVector3.h" @@ -52,6 +54,15 @@ namespace caf setDefault(RimFractureTemplate::INFINITE_CONDUCTIVITY); } + template<> + void caf::AppEnum< RimFractureTemplate::EffectivePermeabilityEnum>::setUp() + { + addItem(RimFractureTemplate::USER_DEFINED_PERMEABILITY, "UserDefinedPermeability", "User Defined"); + addItem(RimFractureTemplate::CONDUCTIVITY_FROM_FRACTURE, "FractureConductivity", "Use Fracture Conductivity"); + + setDefault(RimFractureTemplate::CONDUCTIVITY_FROM_FRACTURE); + } + } @@ -90,11 +101,24 @@ RimFractureTemplate::RimFractureTemplate() // Non-Darcy Flow options CAF_PDM_InitField_Basic(&m_useNonDarcyFlow, "UseNonDarcyFlow", false, "Use Non-Darcy Flow"); - CAF_PDM_InitField_Basic(&m_fractureWidth, "FractureWidth", 0.0, "Fracture Width"); - CAF_PDM_InitField_Basic(&m_inertialCoefficient, "InertialCoefficient", 0.0, "Inertial Coefficient (beta)"); - CAF_PDM_InitField_Basic(&m_effectivePermeability, "EffectivePermeability",0.0, "Effective Permeability"); - CAF_PDM_InitField_Basic(&m_specificGasGravity, "SpecificGasGravity", 0.0, "Specific Gas Gravity"); - CAF_PDM_InitField_Basic(&m_gasViscosity, "GasViscosity", 0.0, "Gas Viscosity"); + CAF_PDM_InitField_Basic(&m_inertialCoefficient, "InertialCoefficient", 0.006083236, "Inertial Coefficient"); + + CAF_PDM_InitFieldNoDefault(&m_permeabilityType, "PermeabilityType", "Type", "", "", ""); + CAF_PDM_InitField_Basic(&m_permeabilityScaleFactor,"EffectivePermeabilityScaleFactor", 1.0, "Scale Factor [0..1]"); + CAF_PDM_InitField(&m_permeability, "EffectivePermeability", 0.0, "Effective Permeability", "", "", ""); + + CAF_PDM_InitField(&m_relativeGasDensity, "RelativeGasDensity", 0.8, "Relative Gas Density", "", "Relative density of gas at surface conditions with respect to air at STP", ""); + CAF_PDM_InitField(&m_gasViscosity, "GasViscosity", 0.02, "Gas Viscosity", "", "Gas viscosity at bottom hole pressure", ""); + + CAF_PDM_InitFieldNoDefault(&m_dFactorDisplayField, "dFactorDisplayField", "D Factor", "", "", ""); + m_dFactorDisplayField.registerGetMethod(this, &RimFractureTemplate::computeDFactor); + m_dFactorDisplayField.uiCapability()->setUiReadOnly(true); + + CAF_PDM_InitFieldNoDefault(&m_dFactorSummaryText, "dFactorSummaryText", "D Factor Summary", "", "", ""); + m_dFactorSummaryText.registerGetMethod(this, &RimFractureTemplate::dFactorSummary); + m_dFactorSummaryText.uiCapability()->setUiReadOnly(true); + m_dFactorSummaryText.uiCapability()->setUiEditorTypeName(caf::PdmUiTextEditor::uiEditorTypeName()); + m_dFactorSummaryText.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::LabelPosType::TOP); } //-------------------------------------------------------------------------------------------------- @@ -241,11 +265,24 @@ void RimFractureTemplate::defineUiOrdering(QString uiConfigName, caf::PdmUiOrder auto group = uiOrdering.addNewGroup("Non-Darcy Flow"); group->setCollapsedByDefault(true); group->add(&m_useNonDarcyFlow); - group->add(&m_fractureWidth); group->add(&m_inertialCoefficient); - group->add(&m_effectivePermeability); - group->add(&m_specificGasGravity); + + { + auto permGroup = group->addNewGroup("Effective Permeability"); + permGroup->add(&m_permeabilityType); + permGroup->add(&m_permeabilityScaleFactor); + permGroup->add(&m_permeability); + } + + group->add(&m_relativeGasDensity); group->add(&m_gasViscosity); + group->add(&m_dFactorDisplayField); + + { + auto dFactorGroup = group->addNewGroup("D Factor Details"); + dFactorGroup->setCollapsedByDefault(true); + dFactorGroup->add(&m_dFactorSummaryText); + } uiOrdering.add(&m_fractureTemplateUnit); } @@ -264,8 +301,20 @@ void RimFractureTemplate::defineEditorAttribute(const caf::PdmFieldHandle* field myAttr->m_maximum = 1.0; } } -} + if (field == &m_dFactorSummaryText) + { + auto myAttr = dynamic_cast(attribute); + if (myAttr) + { + myAttr->wrapMode = caf::PdmUiTextEditorAttribute::NoWrap; + + QFont font("Monospace", 10); + myAttr->font = font; + myAttr->textMode = caf::PdmUiTextEditorAttribute::HTML; + } + } +} //-------------------------------------------------------------------------------------------------- /// @@ -314,19 +363,127 @@ void RimFractureTemplate::prepareFieldsForUiDisplay() } // Non Darcy Flow - m_fractureWidth.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); m_inertialCoefficient.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); - m_effectivePermeability.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); - m_specificGasGravity.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); + + m_permeabilityType.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); + m_permeabilityScaleFactor.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); + m_permeability.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); + + m_relativeGasDensity.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); m_gasViscosity.uiCapability()->setUiReadOnly(!m_useNonDarcyFlow); - if (m_orientationType == RimFractureTemplate::ALONG_WELL_PATH) + if (m_useNonDarcyFlow) { - m_fractureWidth.uiCapability()->setUiHidden(true); + if (m_permeabilityType == RimFractureTemplate::USER_DEFINED_PERMEABILITY) + { + m_permeabilityScaleFactor.uiCapability()->setUiHidden(true); + m_permeability.uiCapability()->setUiReadOnly(false); + } + else + { + m_permeabilityScaleFactor.uiCapability()->setUiHidden(false); + m_permeability.uiCapability()->setUiHidden(true); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFractureTemplate::dFactorSummary() const +{ + QString text; + + auto dFactor = computeDFactor(); + text += QString("D-factor : %1").arg(dFactor); + + text += "
"; + text += "
"; + auto alpha = RiaDefines::nonDarcyFlowAlpha(m_fractureTemplateUnit()); + text += QString("α : %1").arg(alpha); + + text += "
"; + auto beta = m_inertialCoefficient; + text += QString("β : %1").arg(beta); + + text += "
"; + double effPerm = effectivePermeability(); + text += QString("Ke : %1").arg(effPerm); + + text += "
"; + double gamma = m_relativeGasDensity; + text += QString("γ : %1").arg(gamma); + + text += "
"; + auto h = nonDarcyH(); + text += QString("h : %1").arg(h); + + text += "
"; + auto wellRadius = m_wellDiameter / 2.0; + text += QString("rw : %1").arg(wellRadius); + + text += "
"; + auto mu = m_gasViscosity; + text += QString("μ : %1").arg(mu); + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureTemplate::effectivePermeability() const +{ + if (m_permeabilityType() == RimFractureTemplate::USER_DEFINED_PERMEABILITY) + { + return m_permeability; } else { - m_fractureWidth.uiCapability()->setUiHidden(false); + auto values = widthAndConductivityAtWellPathIntersection(); + + auto fracPermeability = values.m_permeability; + + return fracPermeability * m_permeabilityScaleFactor; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureTemplate::computeDFactor() const +{ + auto alpha = RiaDefines::nonDarcyFlowAlpha(m_fractureTemplateUnit()); + auto beta = m_inertialCoefficient; + auto effPerm = effectivePermeability(); + auto gamma = m_relativeGasDensity; + + auto radius = m_wellDiameter / 2.0; + auto mu = m_gasViscosity; + auto h = nonDarcyH(); + + double numerator = alpha * beta * effPerm * gamma; + double denumerator = h * radius * mu; + + if (denumerator < 1e-10) return HUGE_VAL; + + return numerator / denumerator; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureTemplate::nonDarcyH() const +{ + if (m_orientationType() == RimFractureTemplate::ALONG_WELL_PATH) + { + return m_perforationLength(); + } + else + { + auto values = widthAndConductivityAtWellPathIntersection(); + + return values.m_width; } } diff --git a/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.h b/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.h index a12b897f8b..3e1f60e774 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.h +++ b/ApplicationCode/ProjectDataModel/Completions/RimFractureTemplate.h @@ -21,11 +21,12 @@ #include "RiaEclipseUnitTools.h" #include "cafAppEnum.h" +#include "cafPdmChildField.h" #include "cafPdmField.h" +#include "cafPdmFieldCvfVec3d.h" #include "cafPdmFieldHandle.h" #include "cafPdmObject.h" -#include "cafPdmChildField.h" -#include "cafPdmFieldCvfVec3d.h" +#include "cafPdmProxyValueField.h" #include "cvfBase.h" #include "cvfVector3.h" @@ -37,6 +38,19 @@ class RimFractureContainment; class MinMaxAccumulator; class PosNegAccumulator; +class FractureWidthAndConductivity +{ +public: + FractureWidthAndConductivity() + : m_width(0.0) + , m_permeability(0.0) + { + } + + double m_width; + double m_permeability; +}; + //================================================================================================== /// /// @@ -59,6 +73,12 @@ public: FINITE_CONDUCTIVITY, }; + enum EffectivePermeabilityEnum + { + USER_DEFINED_PERMEABILITY, + CONDUCTIVITY_FROM_FRACTURE, + }; + public: RimFractureTemplate(); virtual ~RimFractureTemplate(); @@ -99,6 +119,14 @@ protected: private: void prepareFieldsForUiDisplay(); + virtual FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection() const = 0; + + QString dFactorSummary() const; + double effectivePermeability() const; + + double computeDFactor() const; + double nonDarcyH() const; + protected: caf::PdmField m_name; @@ -113,9 +141,16 @@ protected: caf::PdmChildField m_fractureContainment; caf::PdmField m_useNonDarcyFlow; - caf::PdmField m_fractureWidth; caf::PdmField m_inertialCoefficient; - caf::PdmField m_effectivePermeability; - caf::PdmField m_specificGasGravity; + + caf::PdmField> + m_permeabilityType; + caf::PdmField m_permeabilityScaleFactor; + caf::PdmField m_permeability; + + caf::PdmField m_relativeGasDensity; caf::PdmField m_gasViscosity; + + caf::PdmProxyValueField m_dFactorDisplayField; + caf::PdmProxyValueField m_dFactorSummaryText; }; diff --git a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp index 50d31e665f..be3061b0b4 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp @@ -402,6 +402,42 @@ QString RimStimPlanFractureTemplate::getUnitForStimPlanParameter(QString paramet } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +FractureWidthAndConductivity RimStimPlanFractureTemplate::widthAndConductivityAtWellPathIntersection() const +{ + FractureWidthAndConductivity values; + + if (m_fractureGrid.notNull()) + { + std::pair wellCellIJ = m_fractureGrid->fractureCellAtWellCenter(); + size_t wellCellIndex = m_fractureGrid->getGlobalIndexFromIJ(wellCellIJ.first, wellCellIJ.second); + const RigFractureCell& wellCell = m_fractureGrid->cellFromIndex(wellCellIndex); + + double conductivity = wellCell.getConductivtyValue(); + + std::vector > propertyNamesUnitsOnFile = m_stimPlanFractureDefinitionData->getStimPlanPropertyNamesUnits(); + for (const auto& nameUnit : propertyNamesUnitsOnFile) + { + if (nameUnit.first.contains("Width", Qt::CaseInsensitive)) + { + auto data = m_stimPlanFractureDefinitionData->fractureGridResults(nameUnit.first, nameUnit.second, m_activeTimeStepIndex); + + double width = data[wellCellIndex]; + + if (fabs(width) > 1e-7) + { + values.m_width = width; + values.m_permeability = conductivity / width; + } + } + } + } + + return values; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h index 3d03ed2d86..f4e0cd4f6b 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h +++ b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h @@ -104,6 +104,9 @@ private: void setPerforationLength(); QString getUnitForStimPlanParameter(QString parameterName); + + virtual FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection() const override; + private: caf::PdmField m_activeTimeStepIndex; caf::PdmField m_conductivityResultNameOnFile;