#4799 WBS: Make PP go up to seabed and ensure sources are kept valid when source stepping.

This commit is contained in:
Gaute Lindkvist 2019-09-30 15:34:47 +02:00
parent 62c48d3cdb
commit 2d2a5201d0
4 changed files with 292 additions and 258 deletions

View File

@ -68,12 +68,16 @@ RimWellBoreStabilityPlot::RimWellBoreStabilityPlot()
"" );
CAF_PDM_InitFieldNoDefault( &m_ucsSource, "UcsSource", "Uniaxial Compressive Strength", "", "Data source for UCS", "" );
CAF_PDM_InitField( &m_userDefinedPoissionRatio, "UserPoissionRatio", 0.25, "", "", "User defined Poisson Ratio", "" );
m_userDefinedPoissionRatio.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
CAF_PDM_InitField( &m_userDefinedPoissionRatio,
"UserPoissionRatio",
0.25,
"User defined Poisson Ratio",
"",
"User defined Poisson Ratio",
"" );
// Typical UCS: http://ceae.colorado.edu/~amadei/CVEN5768/PDF/NOTES8.pdf
// Typical UCS for Shale is 5 - 100 MPa -> 50 - 1000 bar.
CAF_PDM_InitField( &m_userDefinedUcs, "UserUcs", 100.0, "", "", "User defined UCS [bar]", "" );
m_userDefinedUcs.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
CAF_PDM_InitField( &m_userDefinedUcs, "UserUcs", 100.0, "User defined UCS [bar]", "", "User defined UCS [bar]", "" );
}
//--------------------------------------------------------------------------------------------------
@ -126,13 +130,9 @@ void RimWellBoreStabilityPlot::defineUiOrdering( QString uiConfigName, caf::PdmU
caf::PdmUiGroup* parameterSources = uiOrdering.addNewGroup( "Parameter Sources" );
parameterSources->add( &m_porePressureSource );
parameterSources->add( &m_poissonRatioSource );
parameterSources->add( &m_userDefinedPoissionRatio, {false, 1, 1} );
parameterSources->add( &m_userDefinedPoissionRatio );
parameterSources->add( &m_ucsSource );
parameterSources->add( &m_userDefinedUcs, {false, 1, 1} );
m_userDefinedPoissionRatio.uiCapability()->setUiReadOnly( m_poissonRatioSource() !=
RigGeoMechWellLogExtractor::USER_DEFINED );
m_userDefinedUcs.uiCapability()->setUiReadOnly( m_ucsSource() != RigGeoMechWellLogExtractor::USER_DEFINED );
parameterSources->add( &m_userDefinedUcs );
uiOrderingForDepthAxis( uiOrdering );
uiOrderingForPlotSettings( uiOrdering );
@ -148,91 +148,27 @@ QList<caf::PdmOptionItemInfo>
{
QList<caf::PdmOptionItemInfo> options = RimWellLogPlot::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
RimWellPath* wellPath = m_commonDataSource->wellPathToApply();
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( m_commonDataSource->caseToApply() );
int timeStep = m_commonDataSource->timeStepToApply();
RigFemPartResultsCollection* femPartResults = nullptr;
if ( geoMechCase )
{
femPartResults = geoMechCase->geoMechData()->femPartResults();
}
if ( fieldNeedingOptions == &m_porePressureSource )
{
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForPorePressure() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "PP" ).empty() )
for ( auto source : supportedSourcesForPorePressure() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "POR", "" );
if ( timeStep > 0 && femPartResults && !femPartResults->resultValues( resAddr, 0, timeStep ).empty() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
}
else if ( fieldNeedingOptions == &m_poissonRatioSource )
{
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForPoissonRatio() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "POISSON_RATIO" ).empty() )
for ( auto source : supportedSourcesForPoisson() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "RATIO", "" );
if ( timeStep > 0 && femPartResults && !femPartResults->resultValues( resAddr, 0, timeStep ).empty() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
}
else if ( fieldNeedingOptions == &m_ucsSource )
{
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForUcs() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "UCS" ).empty() )
for ( auto source : supportedSourcesForUcs() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "UCS", "" );
if ( timeStep > 0 && femPartResults && !femPartResults->resultValues( resAddr, 0, timeStep ).empty() )
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
else
{
options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) );
}
}
}
return options;
}
@ -251,3 +187,155 @@ void RimWellBoreStabilityPlot::fieldChangedByUi( const caf::PdmFieldHandle* chan
this->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellBoreStabilityPlot::onLoadDataAndUpdate()
{
if ( !supportedSourcesForPorePressure().count( m_porePressureSource() ) )
{
m_porePressureSource = RigGeoMechWellLogExtractor::AUTO;
}
if ( !supportedSourcesForPoisson().count( m_poissonRatioSource() ) )
{
m_poissonRatioSource = RigGeoMechWellLogExtractor::AUTO;
}
if ( !supportedSourcesForUcs().count( m_ucsSource() ) )
{
m_ucsSource = RigGeoMechWellLogExtractor::AUTO;
}
RimWellLogPlot::onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellBoreStabilityPlot::hasLasFileWithChannel( const QString& channel ) const
{
RimWellPath* wellPath = m_commonDataSource->wellPathToApply();
if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, channel ).empty() )
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellBoreStabilityPlot::hasElementPropertyEntry( const RigFemResultAddress& resAddr ) const
{
int timeStep = m_commonDataSource->timeStepToApply();
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( m_commonDataSource->caseToApply() );
RigFemPartResultsCollection* femPartResults = nullptr;
if ( geoMechCase && timeStep > 0 )
{
femPartResults = geoMechCase->geoMechData()->femPartResults();
if ( femPartResults )
{
return !femPartResults->resultValues( resAddr, 0, timeStep ).empty();
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RimWellBoreStabilityPlot::supportedSourcesForPorePressure() const
{
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> sources;
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForPorePressure() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( hasLasFileWithChannel( "PP" ) )
{
sources.insert( source );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "POR", "" );
if ( hasElementPropertyEntry( resAddr ) )
{
sources.insert( source );
}
}
else
{
sources.insert( source );
}
}
return sources;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RimWellBoreStabilityPlot::supportedSourcesForPoisson() const
{
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> sources;
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForPoissonRatio() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( hasLasFileWithChannel( "POISSON_RATIO" ) )
{
sources.insert( source );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "RATIO", "" );
if ( hasElementPropertyEntry( resAddr ) )
{
sources.insert( source );
}
}
else
{
sources.insert( source );
}
}
return sources;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RimWellBoreStabilityPlot::supportedSourcesForUcs() const
{
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> sources;
for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForUcs() )
{
if ( source == RigGeoMechWellLogExtractor::LAS_FILE )
{
if ( hasLasFileWithChannel( "UCS" ) )
{
sources.insert( source );
}
}
else if ( source == RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE )
{
RigFemResultAddress resAddr( RIG_ELEMENT, "UCS", "" );
if ( hasElementPropertyEntry( resAddr ) )
{
sources.insert( source );
}
}
else
{
sources.insert( source );
}
}
return sources;
}

View File

@ -57,6 +57,15 @@ protected:
const QVariant& oldValue,
const QVariant& newValue ) override;
void onLoadDataAndUpdate() override;
bool hasLasFileWithChannel( const QString& channel ) const;
bool hasElementPropertyEntry( const RigFemResultAddress& resAddr ) const;
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> supportedSourcesForPorePressure() const;
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> supportedSourcesForPoisson() const;
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> supportedSourcesForUcs() const;
private:
caf::PdmField<ParameterSourceEnum> m_porePressureSource;
caf::PdmField<ParameterSourceEnum> m_poissonRatioSource;

View File

@ -109,23 +109,23 @@ void RigGeoMechWellLogExtractor::curveData( const RigFemResultAddress& resAddr,
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t intersectionIdx,
float averageSegmentPorePressureBar,
double hydroStaticPorePressureBar,
std::pair<float, RigGeoMechWellLogExtractor::WbsParameterSource> RigGeoMechWellLogExtractor::calculatePorePressureInSegment(
int64_t intersectionIdx,
double effectiveDepthMeters,
const std::vector<float>& interpolatedInterfacePorePressuresBar,
const std::vector<float>& poreElementPressuresPascal ) const
{
// Priority 4: Assign a default of hydrostatic pore pressure
double porePressure = hydroStaticPorePressureBar;
// Priority 3: Try element property tables
if ( m_porePressureSource == AUTO || m_porePressureSource == ELEMENT_PROPERTY_TABLE )
// Priority 1: Try pore pressure from the grid
if ( m_porePressureSource == AUTO || m_porePressureSource == GRID )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poreElementPressuresPascal.size() )
float averagePorePressureBar = std::numeric_limits<float>::infinity();
bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx,
interpolatedInterfacePorePressuresBar,
std::numeric_limits<float>::infinity(),
&averagePorePressureBar );
if ( validGridPorePressure )
{
// Pore pressure from element property tables are in pascal.
porePressure = pascalToBar( poreElementPressuresPascal[elmIdx] );
return std::make_pair( averagePorePressureBar, GRID );
}
}
@ -137,43 +137,32 @@ float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t inters
{
double specificMudWeightNPerM3 = lasMudWeightKgPerM3 * 9.81;
double porePressurePascal = specificMudWeightNPerM3 * effectiveDepthMeters;
porePressure = pascalToBar( porePressurePascal );
double porePressureBar = pascalToBar( porePressurePascal );
return std::make_pair( (float)porePressureBar, LAS_FILE );
}
}
// Priority 1: Try pore pressure from the grid
if ( m_porePressureSource == AUTO || m_porePressureSource == GRID )
// Priority 3: Try element property tables
if ( m_porePressureSource == AUTO || m_porePressureSource == ELEMENT_PROPERTY_TABLE )
{
if ( averageSegmentPorePressureBar != std::numeric_limits<double>::infinity() &&
averageSegmentPorePressureBar > 0.0 )
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poreElementPressuresPascal.size() )
{
porePressure = averageSegmentPorePressureBar;
float porePressureBar = pascalToBar( poreElementPressuresPascal[elmIdx] );
return std::make_pair( porePressureBar, ELEMENT_PROPERTY_TABLE );
}
}
CVF_ASSERT( porePressure >= 0.0 );
return porePressure;
return std::make_pair( std::numeric_limits<float>::infinity(), INVALID );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RigGeoMechWellLogExtractor::calculatePoissonRatio( int64_t intersectionIdx,
std::pair<float, RigGeoMechWellLogExtractor::WbsParameterSource>
RigGeoMechWellLogExtractor::calculatePoissonRatioInSegment( int64_t intersectionIdx,
const std::vector<float>& poissonRatios ) const
{
// Priority 3: User defined poisson ratio
double poissonRatio = m_userDefinedPoissonRatio;
// Priority 2: Element property table ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poissonRatios.size() )
{
poissonRatio = poissonRatios[elmIdx];
}
}
// Priority 1: Las-file poisson ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == LAS_FILE )
{
@ -182,33 +171,32 @@ float RigGeoMechWellLogExtractor::calculatePoissonRatio( int64_t
double lasPoissionRatio = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndPoissonRatios );
if ( lasPoissionRatio != std::numeric_limits<double>::infinity() )
{
poissonRatio = lasPoissionRatio;
return std::make_pair( lasPoissionRatio, LAS_FILE );
}
}
}
return poissonRatio;
// Priority 2: Element property table ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poissonRatios.size() )
{
return std::make_pair( poissonRatios[elmIdx], ELEMENT_PROPERTY_TABLE );
}
}
// Priority 3: User defined poisson ratio
return std::make_pair( (float)m_userDefinedPoissonRatio, USER_DEFINED );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RigGeoMechWellLogExtractor::calculateUcs( int64_t intersectionIdx, const std::vector<float>& ucsValuesPascal ) const
std::pair<float, RigGeoMechWellLogExtractor::WbsParameterSource>
RigGeoMechWellLogExtractor::calculateUcsInSegment( int64_t intersectionIdx,
const std::vector<float>& ucsValuesPascal ) const
{
// Priority 3: User defined UCS
double uniaxialStrengthInBar = m_userDefinedUcs;
// Priority 2: From element property table
if ( m_ucsSource == AUTO || m_ucsSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < ucsValuesPascal.size() )
{
// Read UCS from element table in Pascal
uniaxialStrengthInBar = pascalToBar( ucsValuesPascal[elmIdx] );
}
}
if ( m_ucsSource == AUTO || m_ucsSource == LAS_FILE )
{
if ( !m_wellLogMdAndUcsBar.empty() )
@ -216,12 +204,23 @@ float RigGeoMechWellLogExtractor::calculateUcs( int64_t intersectionIdx, const s
double lasUniaxialStrengthInBar = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndUcsBar );
if ( lasUniaxialStrengthInBar != std::numeric_limits<double>::infinity() )
{
uniaxialStrengthInBar = lasUniaxialStrengthInBar;
return std::make_pair( lasUniaxialStrengthInBar, LAS_FILE );
}
}
}
return uniaxialStrengthInBar;
// Priority 2: From element property table
if ( m_ucsSource == AUTO || m_ucsSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < ucsValuesPascal.size() )
{
// Read UCS from element table in Pascal
float uniaxialStrengthInBar = pascalToBar( ucsValuesPascal[elmIdx] );
return std::make_pair( uniaxialStrengthInBar, ELEMENT_PROPERTY_TABLE );
}
}
// Priority 3: User defined UCS (in bar)
return std::make_pair( m_userDefinedUcs, USER_DEFINED );
}
//--------------------------------------------------------------------------------------------------
@ -348,19 +347,21 @@ void RigGeoMechWellLogExtractor::wellPathScaledCurveData( const RigFemResultAddr
double hydroStaticPorePressureBar = pascalToBar( effectiveDepthMeters * UNIT_WEIGHT_OF_WATER );
float averageUnscaledValue = std::numeric_limits<float>::infinity();
bool validAverage = averageIntersectionValuesToSegmentValue( intersectionIdx,
interpolatedInterfaceValues,
std::numeric_limits<float>::infinity(),
&averageUnscaledValue );
if ( resAddr.fieldName == "PP" && validAverage )
if ( resAddr.fieldName == "PP" )
{
double segmentPorePressureFromGrid = averageUnscaledValue;
averageUnscaledValue = calculatePorePressureInSegment( intersectionIdx,
segmentPorePressureFromGrid,
hydroStaticPorePressureBar,
auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx,
effectiveDepthMeters,
interpolatedInterfaceValues,
poreElementPressuresPascal );
if ( ppSourcePair.second == INVALID )
{
averageUnscaledValue = hydroStaticPorePressureBar;
}
else
{
averageUnscaledValue = ppSourcePair.first;
}
}
( *values )[intersectionIdx] = static_cast<double>( averageUnscaledValue ) / hydroStaticPorePressureBar;
@ -404,8 +405,8 @@ void RigGeoMechWellLogExtractor::wellBoreWallCurveData( const RigFemResultAddres
std::vector<float> poissonRatios = resultCollection->resultValues( poissonResAddr, 0, frameIndex );
std::vector<float> ucsValuesPascal = resultCollection->resultValues( ucsResAddr, 0, frameIndex );
std::vector<float> interpolatedInterfacePorePressureBar;
interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits<double>::infinity() );
std::vector<float> interpolatedInterfacePorePressuresBar;
interpolatedInterfacePorePressuresBar.resize( m_intersections.size(), std::numeric_limits<double>::infinity() );
std::vector<caf::Ten3d> interpolatedInterfaceStressBar;
interpolatedInterfaceStressBar.resize( m_intersections.size() );
@ -416,7 +417,7 @@ void RigGeoMechWellLogExtractor::wellBoreWallCurveData( const RigFemResultAddres
RigElementType elmType = femPart->elementType( elmIdx );
if ( !( elmType == HEX8 || elmType == HEX8P ) ) continue;
interpolatedInterfacePorePressureBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType,
interpolatedInterfacePorePressuresBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType,
porePressures,
intersectionIdx,
false );
@ -442,20 +443,22 @@ void RigGeoMechWellLogExtractor::wellBoreWallCurveData( const RigFemResultAddres
double effectiveDepthMeters = trueVerticalDepth + m_rkbDiff;
double hydroStaticPorePressureBar = pascalToBar( effectiveDepthMeters * UNIT_WEIGHT_OF_WATER );
float averagePorePressureBar = std::numeric_limits<float>::infinity();
bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx,
interpolatedInterfacePorePressureBar,
std::numeric_limits<float>::infinity(),
&averagePorePressureBar );
bool isFGregion = validGridPorePressure; // FG is for sands, SFG for shale. Sands has PP, shale does not.
double porePressureBar = calculatePorePressureInSegment( intersectionIdx,
averagePorePressureBar,
hydroStaticPorePressureBar,
auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx,
effectiveDepthMeters,
interpolatedInterfacePorePressuresBar,
poreElementPressuresPascal );
double poissonRatio = calculatePoissonRatio( intersectionIdx, poissonRatios );
double ucsBar = calculateUcs( intersectionIdx, ucsValuesPascal );
double porePressureBar = ppSourcePair.first;
// FG is for sands, SFG for shale. Sands has valid PP, shale does not.
bool isFGregion = ppSourcePair.second != INVALID;
if ( ppSourcePair.second == INVALID )
{
porePressureBar = hydroStaticPorePressureBar;
}
double poissonRatio = calculatePoissonRatioInSegment( intersectionIdx, poissonRatios ).first;
double ucsBar = calculateUcsInSegment( intersectionIdx, ucsValuesPascal ).first;
caf::Ten3d segmentStress;
bool validSegmentStress = averageIntersectionValuesToSegmentValue( intersectionIdx,
@ -592,7 +595,7 @@ std::vector<double> RigGeoMechWellLogExtractor::porePressureIntervals( int frame
std::vector<float> poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr, 0, frameIndex );
std::vector<float> interpolatedInterfacePorePressureBar;
interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits<double>::infinity() );
interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits<float>::infinity() );
#pragma omp parallel for
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
@ -610,41 +613,17 @@ std::vector<double> RigGeoMechWellLogExtractor::porePressureIntervals( int frame
#pragma omp parallel for
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
{
// Priority 4: Hydrostatic pore pressure
ppValues[intersectionIdx] = static_cast<double>( HYDROSTATIC_PP );
// Priority 3: Try element property tables
if ( m_porePressureSource == AUTO || m_porePressureSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poreElementPressuresPascal.size() )
{
ppValues[intersectionIdx] = static_cast<double>( ELEMENT_PROPERTY_TABLE );
}
}
// Priority 2: Try LAS-file
if ( m_porePressureSource == AUTO || m_porePressureSource == LAS_FILE )
{
double lasMudWeightKgPerM3 = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndMudWeightKgPerM3 );
if ( lasMudWeightKgPerM3 != std::numeric_limits<double>::infinity() )
{
ppValues[intersectionIdx] = static_cast<double>( LAS_FILE );
}
}
// Priority 1: Try pore pressure from the grid
if ( m_porePressureSource == AUTO || m_porePressureSource == GRID )
{
float averagePorePressureBar = std::numeric_limits<float>::infinity();
bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx,
auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx,
0.0,
interpolatedInterfacePorePressureBar,
std::numeric_limits<float>::infinity(),
&averagePorePressureBar );
if ( validGridPorePressure )
poreElementPressuresPascal );
if ( ppSourcePair.second == INVALID )
{
ppValues[intersectionIdx] = static_cast<double>( GRID );
ppValues[intersectionIdx] = static_cast<double>( HYDROSTATIC_PP );
}
else
{
ppValues[intersectionIdx] = static_cast<double>( ppSourcePair.second );
}
}
return ppValues;
@ -665,31 +644,8 @@ std::vector<double> RigGeoMechWellLogExtractor::poissonIntervals( int frameIndex
#pragma omp parallel for
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
{
// Priority 3: User defined Poisson ratio
poissonValues[intersectionIdx] = static_cast<double>( USER_DEFINED );
// Priority 2: Element property table ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poissonRatios.size() )
{
poissonValues[intersectionIdx] = static_cast<double>( ELEMENT_PROPERTY_TABLE );
}
}
// Priority 1: Las-file poisson ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == LAS_FILE )
{
if ( !m_wellLogMdAndPoissonRatios.empty() )
{
double lasPoissionRatio = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndPoissonRatios );
if ( lasPoissionRatio != std::numeric_limits<double>::infinity() )
{
poissonValues[intersectionIdx] = static_cast<double>( LAS_FILE );
}
}
}
auto poissonSourcePair = calculatePoissonRatioInSegment( intersectionIdx, poissonRatios );
poissonValues[intersectionIdx] = static_cast<double>( poissonSourcePair.second );
}
return poissonValues;
}
@ -710,30 +666,8 @@ std::vector<double> RigGeoMechWellLogExtractor::ucsIntervals( int frameIndex )
#pragma omp parallel for
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
{
// Priority 3: User defined Poisson ratio
ucsValues[intersectionIdx] = static_cast<double>( USER_DEFINED );
// Priority 2: From element property table
if ( m_ucsSource == AUTO || m_ucsSource == ELEMENT_PROPERTY_TABLE )
{
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < ucsValuesPascal.size() )
{
ucsValues[intersectionIdx] = static_cast<double>( ELEMENT_PROPERTY_TABLE );
}
}
// Priority 1: Las-file
if ( m_ucsSource == AUTO || m_ucsSource == LAS_FILE )
{
if ( !m_wellLogMdAndUcsBar.empty() )
{
double lasUniaxialStrengthInBar = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndUcsBar );
if ( lasUniaxialStrengthInBar != std::numeric_limits<double>::infinity() )
{
ucsValues[intersectionIdx] = static_cast<double>( LAS_FILE );
}
}
}
auto ucsSourcePair = calculateUcsInSegment( intersectionIdx, ucsValuesPascal );
ucsValues[intersectionIdx] = static_cast<double>( ucsSourcePair.second );
}
return ucsValues;
}

View File

@ -50,7 +50,8 @@ class RigGeoMechWellLogExtractor : public RigWellLogExtractor
public:
enum WbsParameterSource
{
AUTO,
INVALID = -1,
AUTO = 0,
GRID, // Only relevant for Pore Pressure
LAS_FILE,
ELEMENT_PROPERTY_TABLE,
@ -92,14 +93,16 @@ private:
TangentConstantWithinCell
};
float calculatePorePressureInSegment( int64_t intersectionIdx,
float averageSegmentPorePressureBar,
double hydroStaticPorePressureBar,
std::pair<float, WbsParameterSource>
calculatePorePressureInSegment( int64_t intersectionIdx,
double effectiveDepthMeters,
const std::vector<float>& interpolatedInterfacePorePressuresBar,
const std::vector<float>& poreElementPressuresPascal ) const;
float calculatePoissonRatio( int64_t intersectionIdx, const std::vector<float>& poissonRatios ) const;
float calculateUcs( int64_t intersectionIdx, const std::vector<float>& ucsValuesPascal ) const;
std::pair<float, WbsParameterSource> calculatePoissonRatioInSegment( int64_t intersectionIdx,
const std::vector<float>& poissonRatios ) const;
std::pair<float, WbsParameterSource> calculateUcsInSegment( int64_t intersectionIdx,
const std::vector<float>& ucsValuesPascal ) const;
void wellPathAngles( const RigFemResultAddress& resAddr, std::vector<double>* values );
void wellPathScaledCurveData( const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values );