mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#3224 Non-Darcy longitudinal : Use geometric mean for B-factor
This commit is contained in:
parent
0f99ecf9e6
commit
e96cc60ee7
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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 (β)</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(β-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("α : %1").arg(alpha));
|
||||
|
||||
auto beta = m_inertialCoefficient;
|
||||
auto beta = getOrComputeBetaFactor(f);
|
||||
text += indentedText(QString("β : %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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user