#7452 Use pressure gradient from equilibrium region for stress gradient

This commit is contained in:
Kristian Bendiksen 2021-03-08 14:57:52 +01:00
parent 915b16dd78
commit 8542643963
6 changed files with 154 additions and 37 deletions

View File

@ -56,6 +56,7 @@ void AppEnum<RiaDefines::CurveProperty>::setUp()
addItem( RiaDefines::CurveProperty::NET_TO_GROSS, "NET_TO_GROSS", "Net-To-Gross" ); addItem( RiaDefines::CurveProperty::NET_TO_GROSS, "NET_TO_GROSS", "Net-To-Gross" );
addItem( RiaDefines::CurveProperty::POROSITY_UNSCALED, "POROSITY_UNSCALED", "Porosity (Unscaled)" ); addItem( RiaDefines::CurveProperty::POROSITY_UNSCALED, "POROSITY_UNSCALED", "Porosity (Unscaled)" );
addItem( RiaDefines::CurveProperty::EQLNUM, "EQLNUM", "Equilibration Number" ); addItem( RiaDefines::CurveProperty::EQLNUM, "EQLNUM", "Equilibration Number" );
addItem( RiaDefines::CurveProperty::PRESSURE_GRADIENT, "PRESSURE_GRADIENT", "Pressure Gradient" );
setDefault( RiaDefines::CurveProperty::UNDEFINED ); setDefault( RiaDefines::CurveProperty::UNDEFINED );
} }

View File

@ -51,6 +51,7 @@ enum class CurveProperty
NET_TO_GROSS, NET_TO_GROSS,
POROSITY_UNSCALED, POROSITY_UNSCALED,
EQLNUM, EQLNUM,
PRESSURE_GRADIENT,
}; };
double defaultPorosity(); double defaultPorosity();

View File

@ -34,6 +34,8 @@
#include "RimStimPlanModelStressCalculator.h" #include "RimStimPlanModelStressCalculator.h"
#include "RimStimPlanModelWellLogCalculator.h" #include "RimStimPlanModelWellLogCalculator.h"
#include <cmath>
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -377,9 +379,12 @@ bool RimStimPlanModelCalculator::calculateStressWithGradients( std::vector<doubl
// Poissons ratio // Poissons ratio
std::vector<double> poissonsRatioData = extractValues( RiaDefines::CurveProperty::POISSONS_RATIO, timeStep ); std::vector<double> poissonsRatioData = extractValues( RiaDefines::CurveProperty::POISSONS_RATIO, timeStep );
// Pressure difference
std::vector<double> pressureDiffData = extractValues( RiaDefines::CurveProperty::PRESSURE_GRADIENT, timeStep );
// Check that we have data from all curves // Check that we have data from all curves
if ( biotData.empty() || k0Data.empty() || timeStepPressureData.empty() || initialPressureData.empty() || if ( biotData.empty() || k0Data.empty() || timeStepPressureData.empty() || initialPressureData.empty() ||
poissonsRatioData.empty() ) poissonsRatioData.empty() || pressureDiffData.empty() )
{ {
return false; return false;
} }
@ -387,15 +392,11 @@ bool RimStimPlanModelCalculator::calculateStressWithGradients( std::vector<doubl
if ( biotData.size() < layerBoundaryIndexes.size() || k0Data.size() < layerBoundaryIndexes.size() || if ( biotData.size() < layerBoundaryIndexes.size() || k0Data.size() < layerBoundaryIndexes.size() ||
timeStepPressureData.size() < layerBoundaryIndexes.size() || timeStepPressureData.size() < layerBoundaryIndexes.size() ||
initialPressureData.size() < layerBoundaryIndexes.size() || initialPressureData.size() < layerBoundaryIndexes.size() ||
poissonsRatioData.size() < layerBoundaryIndexes.size() ) poissonsRatioData.size() < layerBoundaryIndexes.size() || pressureDiffData.size() < layerBoundaryIndexes.size() )
{ {
return false; return false;
} }
std::vector<double> stressForGradients;
std::vector<double> pressureForGradients;
std::vector<double> depthForGradients;
// Calculate the stress // Calculate the stress
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ ) for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
{ {
@ -427,36 +428,38 @@ bool RimStimPlanModelCalculator::calculateStressWithGradients( std::vector<doubl
initialStress.push_back( RiaEclipseUnitTools::barToPsi( Sh_init ) ); initialStress.push_back( RiaEclipseUnitTools::barToPsi( Sh_init ) );
// Cache some results for the gradients calculation // Use the bottom of the last layer to compute gradient for last layer
stressForGradients.push_back( Sv ); double bottomInitialPressure = findValueAtBottomOfLayer( initialPressureData, layerBoundaryIndexes, i );
pressureForGradients.push_back( initialPressure );
depthForGradients.push_back( depthTopOfZone );
if ( i == layerBoundaryDepths.size() - 1 ) double bottomDepthDiff = depthBottomOfZone - stressDepthRef;
double bottomSv = verticalStressRef + verticalStressGradientRef * bottomDepthDiff;
double lengthOfLayer = depthBottomOfZone - depthTopOfZone;
double diffStressLayer = bottomSv - Sv;
double diffPressureLayer = bottomInitialPressure - initialPressure;
// The pressure difference result is only defined where there was no pressure data.
// Diff pressure is interpolated in the equilibration region.
double diffPressureEQLTop = findValueAtTopOfLayer( pressureDiffData, layerBoundaryIndexes, i );
double diffPressureEQLBottom = findValueAtBottomOfLayer( pressureDiffData, layerBoundaryIndexes, i );
if ( !std::isinf( diffPressureEQLTop ) )
{ {
// Use the bottom of the last layer to compute gradient for last layer lengthOfLayer = 2.0;
double bottomInitialPressure = findValueAtBottomOfLayer( initialPressureData, layerBoundaryIndexes, i ); diffPressureLayer = diffPressureEQLTop;
diffStressLayer =
double bottomDepthDiff = depthBottomOfZone - stressDepthRef; calculateStressAtDepth( depthTopOfZone - 1, stressDepthRef, verticalStressRef, verticalStressGradientRef ) -
double bottomSv = verticalStressRef + verticalStressGradientRef * bottomDepthDiff; calculateStressAtDepth( depthTopOfZone + 1, stressDepthRef, verticalStressRef, verticalStressGradientRef );
stressForGradients.push_back( bottomSv ); }
pressureForGradients.push_back( bottomInitialPressure ); else if ( !std::isinf( diffPressureEQLBottom ) )
depthForGradients.push_back( depthBottomOfZone ); {
lengthOfLayer = 2.0;
diffPressureLayer = diffPressureEQLBottom;
diffStressLayer =
calculateStressAtDepth( depthBottomOfZone - 1, stressDepthRef, verticalStressRef, verticalStressGradientRef ) -
calculateStressAtDepth( depthBottomOfZone + 1, stressDepthRef, verticalStressRef, verticalStressGradientRef );
} }
}
assert( stressForGradients.size() == layerBoundaryDepths.size() + 1 ); double stressGradient = ( diffStressLayer * k0 + diffPressureLayer * ( 1.0 - k0 ) ) / lengthOfLayer;
assert( pressureForGradients.size() == layerBoundaryDepths.size() + 1 );
assert( depthForGradients.size() == layerBoundaryDepths.size() + 1 );
// Second pass to calculate the stress gradients
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
{
double diffStress = stressForGradients[i + 1] - stressForGradients[i];
double diffPressure = pressureForGradients[i + 1] - pressureForGradients[i];
double diffDepth = depthForGradients[i + 1] - depthForGradients[i];
double k0 = findValueAtTopOfLayer( k0Data, layerBoundaryIndexes, i );
double stressGradient = ( diffStress * k0 + diffPressure * ( 1.0 - k0 ) ) / diffDepth;
stressGradients.push_back( RiaEclipseUnitTools::barPerMeterToPsiPerFeet( stressGradient ) ); stressGradients.push_back( RiaEclipseUnitTools::barPerMeterToPsiPerFeet( stressGradient ) );
} }
@ -621,3 +624,16 @@ std::vector<double> RimStimPlanModelCalculator::calculateThermalExpansionCoeffic
return coefficientFahrenheit; return coefficientFahrenheit;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimStimPlanModelCalculator::calculateStressAtDepth( double depth,
double stressDepthRef,
double verticalStressRef,
double verticalStressGradientRef )
{
double depthDiff = depth - stressDepthRef;
double stress = verticalStressRef + verticalStressGradientRef * depthDiff;
return stress;
}

View File

@ -93,6 +93,11 @@ protected:
const std::vector<double>& inputVector, const std::vector<double>& inputVector,
std::vector<double>& result ); std::vector<double>& result );
static double calculateStressAtDepth( double depth,
double stressDepthRef,
double verticalStressRef,
double verticalStressGradientRef );
private: private:
RimStimPlanModel* m_stimPlanModel; RimStimPlanModel* m_stimPlanModel;
std::vector<std::unique_ptr<RimStimPlanModelPropertyCalculator>> m_resultCalculators; std::vector<std::unique_ptr<RimStimPlanModelPropertyCalculator>> m_resultCalculators;

View File

@ -58,6 +58,7 @@ bool RimStimPlanModelPressureCalculator::isMatching( RiaDefines::CurveProperty c
std::vector<RiaDefines::CurveProperty> matching = { std::vector<RiaDefines::CurveProperty> matching = {
RiaDefines::CurveProperty::INITIAL_PRESSURE, RiaDefines::CurveProperty::INITIAL_PRESSURE,
RiaDefines::CurveProperty::PRESSURE, RiaDefines::CurveProperty::PRESSURE,
RiaDefines::CurveProperty::PRESSURE_GRADIENT,
}; };
return std::find( matching.begin(), matching.end(), curveProperty ) != matching.end(); return std::find( matching.begin(), matching.end(), curveProperty ) != matching.end();
@ -134,9 +135,16 @@ bool RimStimPlanModelPressureCalculator::extractValuesForProperty( RiaDefines::C
} }
} }
if ( stimPlanModel->stimPlanModelTemplate()->usePressureTableForProperty( curveProperty ) ) RiaDefines::CurveProperty pressureCurveProperty = curveProperty;
if ( curveProperty == RiaDefines::CurveProperty::PRESSURE_GRADIENT )
{ {
if ( !extractPressureDataFromTable( curveProperty, stimPlanModel, values, measuredDepthValues, tvDepthValues ) ) // Use initial pressure for pressure diff
pressureCurveProperty = RiaDefines::CurveProperty::INITIAL_PRESSURE;
}
if ( stimPlanModel->stimPlanModelTemplate()->usePressureTableForProperty( pressureCurveProperty ) )
{
if ( !extractPressureDataFromTable( pressureCurveProperty, stimPlanModel, values, measuredDepthValues, tvDepthValues ) )
{ {
RiaLogging::error( "Unable to extract pressure data from table" ); RiaLogging::error( "Unable to extract pressure data from table" );
return false; return false;
@ -145,7 +153,7 @@ bool RimStimPlanModelPressureCalculator::extractValuesForProperty( RiaDefines::C
else else
{ {
// Extract the property we care about // Extract the property we care about
RimStimPlanModelWellLogCalculator::extractValuesForProperty( curveProperty, RimStimPlanModelWellLogCalculator::extractValuesForProperty( pressureCurveProperty,
stimPlanModel, stimPlanModel,
timeStep, timeStep,
values, values,
@ -227,7 +235,8 @@ bool RimStimPlanModelPressureCalculator::extractValuesForProperty( RiaDefines::C
values.end(); values.end();
if ( hasMissingValues ) if ( hasMissingValues )
{ {
if ( !interpolateInitialPressureByEquilibrationRegion( stimPlanModel, if ( !interpolateInitialPressureByEquilibrationRegion( curveProperty,
stimPlanModel,
timeStep, timeStep,
measuredDepthValues, measuredDepthValues,
tvDepthValues, tvDepthValues,
@ -237,6 +246,21 @@ bool RimStimPlanModelPressureCalculator::extractValuesForProperty( RiaDefines::C
} }
} }
} }
else if ( curveProperty == RiaDefines::CurveProperty::PRESSURE_GRADIENT )
{
std::vector<double> initialPressureValues = values;
values.clear();
if ( !interpolatePressureDifferenceByEquilibrationRegion( curveProperty,
stimPlanModel,
timeStep,
measuredDepthValues,
tvDepthValues,
initialPressureValues,
values ) )
{
RiaLogging::error( "Pressure interpolation by equilibration region failed." );
}
}
else if ( curveProperty == RiaDefines::CurveProperty::PRESSURE ) else if ( curveProperty == RiaDefines::CurveProperty::PRESSURE )
{ {
// Filter out the facies which does not have pressure depletion. // Filter out the facies which does not have pressure depletion.
@ -532,6 +556,7 @@ double RimStimPlanModelPressureCalculator::interpolatePressure( const DepthValue
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RimStimPlanModelPressureCalculator::interpolateInitialPressureByEquilibrationRegion( bool RimStimPlanModelPressureCalculator::interpolateInitialPressureByEquilibrationRegion(
RiaDefines::CurveProperty curveProperty,
const RimStimPlanModel* stimPlanModel, const RimStimPlanModel* stimPlanModel,
int timeStep, int timeStep,
const std::vector<double>& measuredDepthValues, const std::vector<double>& measuredDepthValues,
@ -581,3 +606,64 @@ bool RimStimPlanModelPressureCalculator::interpolateInitialPressureByEquilibrati
return true; return true;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimStimPlanModelPressureCalculator::interpolatePressureDifferenceByEquilibrationRegion(
RiaDefines::CurveProperty curveProperty,
const RimStimPlanModel* stimPlanModel,
int timeStep,
const std::vector<double>& measuredDepthValues,
const std::vector<double>& tvDepthValues,
const std::vector<double>& initialPressureValues,
std::vector<double>& values ) const
{
std::vector<double> eqlNumValues;
std::vector<double> eqlNumMeasuredDepthsValues;
std::vector<double> eqlNumTvDepthValues;
double rkbDiff = -1.0;
if ( !stimPlanModel->calculator()->extractCurveData( RiaDefines::CurveProperty::EQLNUM,
timeStep,
eqlNumValues,
eqlNumMeasuredDepthsValues,
eqlNumTvDepthValues,
rkbDiff ) )
{
RiaLogging::error( "Failed to extract EQLNUM data in pressure calculation" );
return false;
}
std::set<int> presentEqlNums = findUniqueValues( eqlNumValues );
RiaLogging::info( QString( "Found %1 EQLNUM values." ).arg( presentEqlNums.size() ) );
EqlNumToDepthValuePairMap valuesPerEqlNum;
if ( !buildPressureTablesPerEqlNum( stimPlanModel, valuesPerEqlNum, presentEqlNums ) )
{
RiaLogging::error( "Failed to build EQLNUM pressure data in pressure calculation" );
return false;
}
values.clear();
values.resize( initialPressureValues.size(), std::numeric_limits<double>::infinity() );
for ( size_t i = 0; i < values.size(); i++ )
{
if ( std::isinf( initialPressureValues[i] ) )
{
int eqlNum = static_cast<int>( eqlNumValues[i] );
DepthValuePairVector depthValuePairs = valuesPerEqlNum[eqlNum];
if ( !depthValuePairs.empty() )
{
double depth = tvDepthValues[i];
double p1 = interpolatePressure( depthValuePairs, depth - 1, eqlNum );
double p2 = interpolatePressure( depthValuePairs, depth + 1, eqlNum );
values[i] = p2 - p1;
RiaLogging::debug( QString( "INTERPOLATING PRESSURE DIFF: %1 %2 = %3" ).arg( p1 ).arg( p2 ).arg( p2 - p1 ) );
}
}
}
return true;
}

View File

@ -58,11 +58,19 @@ protected:
std::vector<double>& measuredDepthValues, std::vector<double>& measuredDepthValues,
std::vector<double>& tvDepthValues ) const; std::vector<double>& tvDepthValues ) const;
bool interpolateInitialPressureByEquilibrationRegion( const RimStimPlanModel* stimPlanModel, bool interpolateInitialPressureByEquilibrationRegion( RiaDefines::CurveProperty curveProperty,
const RimStimPlanModel* stimPlanModel,
int timeStep, int timeStep,
const std::vector<double>& measuredDepthValues, const std::vector<double>& measuredDepthValues,
const std::vector<double>& tvDepthValues, const std::vector<double>& tvDepthValues,
std::vector<double>& values ) const; std::vector<double>& values ) const;
bool interpolatePressureDifferenceByEquilibrationRegion( RiaDefines::CurveProperty curveProperty,
const RimStimPlanModel* stimPlanModel,
int timeStep,
const std::vector<double>& measuredDepthValues,
const std::vector<double>& tvDepthValues,
const std::vector<double>& initialPressureValues,
std::vector<double>& values ) const;
typedef std::pair<double, double> DepthValuePair; typedef std::pair<double, double> DepthValuePair;
typedef std::vector<DepthValuePair> DepthValuePairVector; typedef std::vector<DepthValuePair> DepthValuePairVector;