#3224 Non-Darcy longitudinal : Use geometric mean for B-factor

This commit is contained in:
Magne Sjaastad 2018-09-24 15:10:46 +02:00
parent 0f99ecf9e6
commit e96cc60ee7
8 changed files with 182 additions and 33 deletions

View File

@ -228,10 +228,10 @@ void RimEllipseFractureTemplate::createFractureGridAndAssignConductivities()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FractureWidthAndConductivity
RimEllipseFractureTemplate::widthAndConductivityAtWellPathIntersection(const RimFracture* fractureInstance) const
WellFractureIntersectionData
RimEllipseFractureTemplate::wellFractureIntersectionData(const RimFracture* fractureInstance) const
{
FractureWidthAndConductivity values;
WellFractureIntersectionData values;
values.m_width = m_width;
values.m_permeability = m_permeability;

View File

@ -76,7 +76,7 @@ private:
void createFractureGridAndAssignConductivities();
std::vector<cvf::Vec3f> fractureBorderPolygon() const;
FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection(const RimFracture* fractureInstance) const override;
WellFractureIntersectionData wellFractureIntersectionData(const RimFracture* fractureInstance) const override;
private:
cvf::ref<RigFractureGrid> m_fractureGrid;

View File

@ -269,6 +269,7 @@ void RimFracture::ensureValidNonDarcyProperties()
props.dFactor = m_fractureTemplate->computeDFactor(this);
props.effectivePermeability = m_fractureTemplate->computeEffectivePermeability(this);
props.eqWellRadius = m_fractureTemplate->computeWellRadiusForDFactorCalculation(this);
props.betaFactor = m_fractureTemplate->getOrComputeBetaFactor(this);
props.isDataDirty = false;
}

View File

@ -50,6 +50,7 @@ public:
, effectivePermeability(std::numeric_limits<double>::infinity())
, dFactor(std::numeric_limits<double>::infinity())
, eqWellRadius(std::numeric_limits<double>::infinity())
, betaFactor(std::numeric_limits<double>::infinity())
, isDataDirty(true)
{
}
@ -64,6 +65,7 @@ public:
double conductivity;
double effectivePermeability;
double dFactor;
double betaFactor;
bool isDataDirty;
};

View File

@ -85,6 +85,16 @@ namespace caf
setDefault(RimFractureTemplate::NON_DARCY_NONE);
}
template<>
void caf::AppEnum< RimFractureTemplate::BetaFactorEnum>::setUp()
{
addItem(RimFractureTemplate::USER_DEFINED_BETA_FACTOR, "UserDefinedBetaFactor", "User Defined");
addItem(RimFractureTemplate::BETA_FACTOR_FROM_FRACTURE, "FractureBetaFactor", "Use Fracture Beta Factor");
setDefault(RimFractureTemplate::USER_DEFINED_BETA_FACTOR);
}
}
// TODO Move to cafPdmObject.h
@ -138,6 +148,7 @@ RimFractureTemplate::RimFractureTemplate()
CAF_PDM_InitFieldNoDefault(&m_fractureWidthType, "FractureWidthType", "Type", "", "", "");
CAF_PDM_InitField_Basic(&m_fractureWidth, "FractureWidth", 0.01, "Fracture Width (h)");
CAF_PDM_InitFieldNoDefault(&m_betaFactorType, "BetaFactorType", "Type", "", "", "");
CAF_PDM_InitField_Basic(&m_inertialCoefficient, "InertialCoefficient", 0.006083236, "<html>Inertial Coefficient (&beta;)</html> [Forch. unit]");
CAF_PDM_InitFieldNoDefault(&m_permeabilityType, "PermeabilityType", "Type", "", "", "");
@ -336,7 +347,11 @@ void RimFractureTemplate::defineUiOrdering(QString uiConfigName, caf::PdmUiOrder
if (m_nonDarcyFlowType == RimFractureTemplate::NON_DARCY_COMPUTED)
{
nonDarcyFlowGroup->add(&m_inertialCoefficient);
{
auto group = nonDarcyFlowGroup->addNewGroup("<html>Inertial Coefficient(&beta;-factor)</html>");
group->add(&m_betaFactorType);
group->add(&m_inertialCoefficient);
}
{
auto group = nonDarcyFlowGroup->addNewGroup("Effective Permeability");
@ -424,6 +439,18 @@ QList<caf::PdmOptionItemInfo> RimFractureTemplate::calculateValueOptions(const c
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum<WidthEnum>::uiText(WIDTH_FROM_FRACTURE), WIDTH_FROM_FRACTURE));
}
if (fieldNeedingOptions == &m_betaFactorType)
{
options.push_back(
caf::PdmOptionItemInfo(caf::AppEnum<BetaFactorEnum>::uiText(USER_DEFINED_BETA_FACTOR), USER_DEFINED_BETA_FACTOR));
if (isBetaFactorAvailableOnFile())
{
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum<BetaFactorEnum>::uiText(BETA_FACTOR_FROM_FRACTURE),
BETA_FACTOR_FROM_FRACTURE));
}
}
return options;
}
@ -477,13 +504,24 @@ void RimFractureTemplate::prepareFieldsForUiDisplay()
// Non Darcy Flow
if (m_fractureWidthType == RimFractureTemplate::USER_DEFINED_WIDTH)
{
m_fractureWidth.uiCapability()->setUiReadOnly(false);
}
else
{
m_fractureWidth.uiCapability()->setUiReadOnly(true);
if (m_fractureWidthType == RimFractureTemplate::USER_DEFINED_WIDTH)
{
m_fractureWidth.uiCapability()->setUiReadOnly(false);
}
else
{
m_fractureWidth.uiCapability()->setUiReadOnly(true);
}
if (m_betaFactorType == RimFractureTemplate::USER_DEFINED_BETA_FACTOR)
{
m_inertialCoefficient.uiCapability()->setUiReadOnly(false);
}
else
{
m_inertialCoefficient.uiCapability()->setUiReadOnly(true);
}
}
if (m_permeabilityType == RimFractureTemplate::USER_DEFINED_PERMEABILITY)
@ -545,7 +583,7 @@ QString RimFractureTemplate::dFactorSummary() const
auto alpha = RiaDefines::nonDarcyFlowAlpha(m_fractureTemplateUnit());
text += indentedText(QString("&alpha; : %1").arg(alpha));
auto beta = m_inertialCoefficient;
auto beta = getOrComputeBetaFactor(f);
text += indentedText(QString("&beta; : %1").arg(beta));
double effPerm = f->nonDarcyProperties().effectivePermeability;
@ -596,7 +634,7 @@ double RimFractureTemplate::computeEffectivePermeability(const RimFracture* frac
else
{
double fracPermeability = 0.0;
auto values = widthAndConductivityAtWellPathIntersection(fractureInstance);
auto values = wellFractureIntersectionData(fractureInstance);
if (values.isWidthAndPermeabilityDefined())
{
fracPermeability = values.m_permeability;
@ -606,7 +644,7 @@ double RimFractureTemplate::computeEffectivePermeability(const RimFracture* frac
auto conductivity = values.m_conductivity;
auto width = computeFractureWidth(fractureInstance);
if (fabs(width) < 1e-10) return HUGE_VAL;
if (fabs(width) < 1e-10) return std::numeric_limits<double>::infinity();
fracPermeability = conductivity / width;
}
@ -651,7 +689,7 @@ double RimFractureTemplate::computeDFactor(const RimFracture* fractureInstance)
{
double radius = computeWellRadiusForDFactorCalculation(fractureInstance);
double alpha = RiaDefines::nonDarcyFlowAlpha(m_fractureTemplateUnit());
double beta = m_inertialCoefficient;
double beta = getOrComputeBetaFactor(fractureInstance);
double effPerm = computeEffectivePermeability(fractureInstance);
double gamma = m_relativeGasDensity;
@ -661,7 +699,7 @@ double RimFractureTemplate::computeDFactor(const RimFracture* fractureInstance)
double numerator = alpha * beta * effPerm * gamma;
double denumerator = h * radius * mu;
if (denumerator < 1e-10) return HUGE_VAL;
if (denumerator < 1e-10) return std::numeric_limits<double>::infinity();
d = numerator / denumerator;
@ -685,7 +723,7 @@ double RimFractureTemplate::computeKh(const RimFracture* fractureInstance) const
// kh = permeability * h
// conductivity = permeability * h
auto values = widthAndConductivityAtWellPathIntersection(fractureInstance);
auto values = wellFractureIntersectionData(fractureInstance);
if (values.isConductivityDefined())
{
// If conductivity is found in stim plan file, use this directly
@ -804,7 +842,7 @@ double RimFractureTemplate::computeFractureWidth(const RimFracture* fractureInst
{
if (m_fractureWidthType == RimFractureTemplate::WIDTH_FROM_FRACTURE)
{
auto values = widthAndConductivityAtWellPathIntersection(fractureInstance);
auto values = wellFractureIntersectionData(fractureInstance);
return values.m_width;
}
@ -812,6 +850,21 @@ double RimFractureTemplate::computeFractureWidth(const RimFracture* fractureInst
return m_fractureWidth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureTemplate::getOrComputeBetaFactor(const RimFracture* fractureInstance) const
{
if (m_betaFactorType == RimFractureTemplate::BETA_FACTOR_FROM_FRACTURE)
{
auto values = wellFractureIntersectionData(fractureInstance);
return values.m_betaFactorInForcheimerUnits;
}
return m_inertialCoefficient;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -831,6 +884,14 @@ std::vector<RimFracture*> RimFractureTemplate::fracturesUsingThisTemplate() cons
return fractures;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFractureTemplate::isBetaFactorAvailableOnFile() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -32,7 +32,7 @@
#include "cvfVector3.h"
#include <vector>
#include <cmath>
#include <limits>
class RigFractureGrid;
class RimFractureContainment;
@ -40,13 +40,14 @@ class MinMaxAccumulator;
class PosNegAccumulator;
class RimFracture;
class FractureWidthAndConductivity
class WellFractureIntersectionData
{
public:
FractureWidthAndConductivity()
WellFractureIntersectionData()
: m_width(0.0)
, m_permeability(0.0)
, m_conductivity(HUGE_VAL)
, m_conductivity(std::numeric_limits<double>::infinity())
, m_betaFactorInForcheimerUnits(std::numeric_limits<double>::infinity())
{
}
@ -60,7 +61,7 @@ public:
bool isConductivityDefined() const
{
return (m_conductivity != HUGE_VAL);
return (m_conductivity != std::numeric_limits<double>::infinity());
}
// Unit : meter or feet
@ -70,6 +71,9 @@ public:
double m_permeability;
double m_conductivity;
// Unit : Forcheimer unit
double m_betaFactorInForcheimerUnits;
};
//==================================================================================================
@ -106,6 +110,12 @@ public:
WIDTH_FROM_FRACTURE,
};
enum BetaFactorEnum
{
USER_DEFINED_BETA_FACTOR,
BETA_FACTOR_FROM_FRACTURE,
};
enum NonDarcyFlowEnum
{
NON_DARCY_NONE,
@ -165,6 +175,7 @@ public:
double computeEffectivePermeability(const RimFracture* fractureInstance) const;
double computeWellRadiusForDFactorCalculation(const RimFracture* fractureInstance) const;
double computeFractureWidth(const RimFracture* fractureInstance) const;
double getOrComputeBetaFactor(const RimFracture* fractureInstance) const;
void loadDataAndUpdateGeometryHasChanged();
@ -178,9 +189,11 @@ protected:
std::vector<RimFracture*> fracturesUsingThisTemplate() const;
virtual void onLoadDataAndUpdateGeometryHasChanged() = 0;
virtual bool isBetaFactorAvailableOnFile() const;
private:
void prepareFieldsForUiDisplay();
virtual FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection(const RimFracture* fractureInstance) const = 0;
virtual WellFractureIntersectionData wellFractureIntersectionData(const RimFracture* fractureInstance) const = 0;
QString dFactorSummary() const;
double dFactorForTemplate() const;
@ -205,6 +218,8 @@ protected:
caf::PdmField<caf::AppEnum<WidthEnum>> m_fractureWidthType;
caf::PdmField<double> m_fractureWidth;
caf::PdmField<caf::AppEnum<BetaFactorEnum>> m_betaFactorType;
caf::PdmField<double> m_inertialCoefficient;
caf::PdmField<caf::AppEnum<PermeabilityEnum>> m_permeabilityType;

View File

@ -22,6 +22,7 @@
#include "RiaCompletionTypeCalculationScheduler.h"
#include "RiaFractureDefines.h"
#include "RiaLogging.h"
#include "RiaWeightedGeometricMeanCalculator.h"
#include "RiaWeightedMeanCalculator.h"
#include "RifStimPlanXmlReader.h"
@ -439,10 +440,9 @@ std::vector<double>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
FractureWidthAndConductivity
RimStimPlanFractureTemplate::widthAndConductivityAtWellPathIntersection(const RimFracture* fractureInstance) const
WellFractureIntersectionData RimStimPlanFractureTemplate::wellFractureIntersectionData(const RimFracture* fractureInstance) const
{
FractureWidthAndConductivity values;
WellFractureIntersectionData values;
if (m_fractureGrid.notNull())
{
@ -455,9 +455,11 @@ FractureWidthAndConductivity
if (rimWellPath && rimWellPath->wellPathGeometry())
{
double totalLength = 0.0;
double weightedConductivity = 0.0;
double weightedWidth = 0.0;
double totalLength = 0.0;
double weightedConductivity = 0.0;
double weightedWidth = 0.0;
double weightedBetaFactorOnFile = 0.0;
double conversionFactorForBeta = 1.0;
{
std::vector<double> widthResultValues;
@ -474,8 +476,30 @@ FractureWidthAndConductivity
nameUnit.first, nameUnit.second, m_activeTimeStepIndex, fractureTemplateUnit());
}
RiaWeightedMeanCalculator<double> widthCalc;
RiaWeightedMeanCalculator<double> conductivityCalc;
std::vector<double> betaFactorResultValues;
{
auto nameUnit = betaFactorParameterNameAndUnit();
betaFactorResultValues = m_stimPlanFractureDefinitionData->fractureGridResults(
nameUnit.first, nameUnit.second, m_activeTimeStepIndex);
QString trimmedUnit = nameUnit.second.trimmed().toLower();
if (trimmedUnit == "/m")
{
conversionFactorForBeta = 1.01325E+08;
}
else if (trimmedUnit == "/cm")
{
conversionFactorForBeta = 1.01325E+06;
}
else if (trimmedUnit == "/ft")
{
conversionFactorForBeta = 3.088386E+07;
}
}
RiaWeightedMeanCalculator<double> widthCalc;
RiaWeightedMeanCalculator<double> conductivityCalc;
RiaWeightedGeometricMeanCalculator betaFactorCalc;
RigWellPathStimplanIntersector intersector(rimWellPath->wellPathGeometry(), fractureInstance);
for (const auto& v : intersector.intersections())
@ -493,6 +517,11 @@ FractureWidthAndConductivity
conductivityCalc.addValueAndWeight(conductivityResultValues[fractureGlobalCellIndex],
intersectionLength);
}
if (fractureGlobalCellIndex < betaFactorResultValues.size())
{
betaFactorCalc.addValueAndWeight(betaFactorResultValues[fractureGlobalCellIndex], intersectionLength);
}
}
if (conductivityCalc.validAggregatedWeight())
{
@ -503,12 +532,19 @@ FractureWidthAndConductivity
weightedWidth = widthCalc.weightedMean();
totalLength = widthCalc.aggregatedWeight();
}
if (betaFactorCalc.validAggregatedWeight())
{
weightedBetaFactorOnFile = betaFactorCalc.weightedMean();
}
}
if (totalLength > 1e-7)
{
values.m_width = weightedWidth;
values.m_conductivity = weightedConductivity;
double betaFactorForcheimer = weightedBetaFactorOnFile / conversionFactorForBeta;
values.m_betaFactorInForcheimerUnits = betaFactorForcheimer;
}
if (weightedWidth > 1e-7)
@ -601,6 +637,38 @@ std::pair<QString, QString> RimStimPlanFractureTemplate::conductivityParameterNa
return std::pair<QString, QString>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<QString, QString> RimStimPlanFractureTemplate::betaFactorParameterNameAndUnit() const
{
if (m_stimPlanFractureDefinitionData.notNull())
{
std::vector<std::pair<QString, QString>> propertyNamesUnitsOnFile =
m_stimPlanFractureDefinitionData->getStimPlanPropertyNamesUnits();
for (const auto& nameUnit : propertyNamesUnitsOnFile)
{
if (nameUnit.first.contains("beta", Qt::CaseInsensitive))
{
return nameUnit;
}
}
}
return std::pair<QString, QString>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimStimPlanFractureTemplate::isBetaFactorAvailableOnFile() const
{
auto nameAndUnit = betaFactorParameterNameAndUnit();
return !nameAndUnit.first.isEmpty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -108,10 +108,12 @@ private:
std::vector<double> fractureGridResultsForUnitSystem(const QString& resultName, const QString& unitName, size_t timeStepIndex, RiaEclipseUnitTools::UnitSystem requiredUnitSystem) const;
virtual FractureWidthAndConductivity widthAndConductivityAtWellPathIntersection(const RimFracture* fractureInstance) const override;
virtual WellFractureIntersectionData wellFractureIntersectionData(const RimFracture* fractureInstance) const override;
std::pair<QString, QString> widthParameterNameAndUnit() const;
std::pair<QString, QString> conductivityParameterNameAndUnit() const;
std::pair<QString, QString> betaFactorParameterNameAndUnit() const;
bool isBetaFactorAvailableOnFile() const override;
private:
caf::PdmField<int> m_activeTimeStepIndex;