diff --git a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp index 769a50d2f4..b91d27a3bf 100644 --- a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.cpp @@ -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,89 +148,25 @@ QList { QList options = RimWellLogPlot::calculateValueOptions( fieldNeedingOptions, useOptionsOnly ); - RimWellPath* wellPath = m_commonDataSource->wellPathToApply(); - RimGeoMechCase* geoMechCase = dynamic_cast( 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() ) + for ( auto source : supportedSourcesForPorePressure() ) { - if ( source == RigGeoMechWellLogExtractor::LAS_FILE ) - { - if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "PP" ).empty() ) - { - 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 ) ); - } + options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) ); } } else if ( fieldNeedingOptions == &m_poissonRatioSource ) { - for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForPoissonRatio() ) + for ( auto source : supportedSourcesForPoisson() ) { - if ( source == RigGeoMechWellLogExtractor::LAS_FILE ) - { - if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "POISSON_RATIO" ).empty() ) - { - 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 ) ); - } + options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( source ), source ) ); } } else if ( fieldNeedingOptions == &m_ucsSource ) { - for ( auto source : RigGeoMechWellLogExtractor::supportedSourcesForUcs() ) + for ( auto source : supportedSourcesForUcs() ) { - if ( source == RigGeoMechWellLogExtractor::LAS_FILE ) - { - if ( wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, "UCS" ).empty() ) - { - 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 ) ); - } + 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( 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 RimWellBoreStabilityPlot::supportedSourcesForPorePressure() const +{ + std::set 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 RimWellBoreStabilityPlot::supportedSourcesForPoisson() const +{ + std::set 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 RimWellBoreStabilityPlot::supportedSourcesForUcs() const +{ + std::set 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; +} diff --git a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.h b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.h index 0b9b510c0c..82736f2269 100644 --- a/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.h +++ b/ApplicationCode/ProjectDataModel/RimWellBoreStabilityPlot.h @@ -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 supportedSourcesForPorePressure() const; + std::set supportedSourcesForPoisson() const; + std::set supportedSourcesForUcs() const; + private: caf::PdmField m_porePressureSource; caf::PdmField m_poissonRatioSource; diff --git a/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.cpp b/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.cpp index 36a1a4203f..19c8231e2b 100644 --- a/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.cpp @@ -109,23 +109,23 @@ void RigGeoMechWellLogExtractor::curveData( const RigFemResultAddress& resAddr, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t intersectionIdx, - float averageSegmentPorePressureBar, - double hydroStaticPorePressureBar, - double effectiveDepthMeters, - const std::vector& poreElementPressuresPascal ) const +std::pair RigGeoMechWellLogExtractor::calculatePorePressureInSegment( + int64_t intersectionIdx, + double effectiveDepthMeters, + const std::vector& interpolatedInterfacePorePressuresBar, + const std::vector& 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::infinity(); + bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx, + interpolatedInterfacePorePressuresBar, + std::numeric_limits::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::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::infinity(), INVALID ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -float RigGeoMechWellLogExtractor::calculatePoissonRatio( int64_t intersectionIdx, - const std::vector& poissonRatios ) const +std::pair + RigGeoMechWellLogExtractor::calculatePoissonRatioInSegment( int64_t intersectionIdx, + const std::vector& 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::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& ucsValuesPascal ) const +std::pair + RigGeoMechWellLogExtractor::calculateUcsInSegment( int64_t intersectionIdx, + const std::vector& 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::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::infinity(); - bool validAverage = averageIntersectionValuesToSegmentValue( intersectionIdx, - interpolatedInterfaceValues, - std::numeric_limits::infinity(), - &averageUnscaledValue ); - if ( resAddr.fieldName == "PP" && validAverage ) + if ( resAddr.fieldName == "PP" ) { - double segmentPorePressureFromGrid = averageUnscaledValue; - averageUnscaledValue = calculatePorePressureInSegment( intersectionIdx, - segmentPorePressureFromGrid, - hydroStaticPorePressureBar, - effectiveDepthMeters, - poreElementPressuresPascal ); + auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx, + effectiveDepthMeters, + interpolatedInterfaceValues, + poreElementPressuresPascal ); + if ( ppSourcePair.second == INVALID ) + { + averageUnscaledValue = hydroStaticPorePressureBar; + } + else + { + averageUnscaledValue = ppSourcePair.first; + } } ( *values )[intersectionIdx] = static_cast( averageUnscaledValue ) / hydroStaticPorePressureBar; @@ -404,8 +405,8 @@ void RigGeoMechWellLogExtractor::wellBoreWallCurveData( const RigFemResultAddres std::vector poissonRatios = resultCollection->resultValues( poissonResAddr, 0, frameIndex ); std::vector ucsValuesPascal = resultCollection->resultValues( ucsResAddr, 0, frameIndex ); - std::vector interpolatedInterfacePorePressureBar; - interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits::infinity() ); + std::vector interpolatedInterfacePorePressuresBar; + interpolatedInterfacePorePressuresBar.resize( m_intersections.size(), std::numeric_limits::infinity() ); std::vector interpolatedInterfaceStressBar; interpolatedInterfaceStressBar.resize( m_intersections.size() ); @@ -416,11 +417,11 @@ void RigGeoMechWellLogExtractor::wellBoreWallCurveData( const RigFemResultAddres RigElementType elmType = femPart->elementType( elmIdx ); if ( !( elmType == HEX8 || elmType == HEX8P ) ) continue; - interpolatedInterfacePorePressureBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType, - porePressures, - intersectionIdx, - false ); - interpolatedInterfaceStressBar[intersectionIdx] = interpolateGridResultValue( stressResAddr.resultPosType, + interpolatedInterfacePorePressuresBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType, + porePressures, + intersectionIdx, + false ); + interpolatedInterfaceStressBar[intersectionIdx] = interpolateGridResultValue( stressResAddr.resultPosType, vertexStresses, 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::infinity(); - bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx, - interpolatedInterfacePorePressureBar, - std::numeric_limits::infinity(), - &averagePorePressureBar ); - bool isFGregion = validGridPorePressure; // FG is for sands, SFG for shale. Sands has PP, shale does not. + auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx, + effectiveDepthMeters, + interpolatedInterfacePorePressuresBar, + poreElementPressuresPascal ); + double porePressureBar = ppSourcePair.first; - double porePressureBar = calculatePorePressureInSegment( intersectionIdx, - averagePorePressureBar, - hydroStaticPorePressureBar, - effectiveDepthMeters, - poreElementPressuresPascal ); - double poissonRatio = calculatePoissonRatio( intersectionIdx, poissonRatios ); - double ucsBar = calculateUcs( intersectionIdx, ucsValuesPascal ); + // 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 RigGeoMechWellLogExtractor::porePressureIntervals( int frame std::vector poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr, 0, frameIndex ); std::vector interpolatedInterfacePorePressureBar; - interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits::infinity() ); + interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits::infinity() ); #pragma omp parallel for for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx ) @@ -610,41 +613,17 @@ std::vector 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( HYDROSTATIC_PP ); - - // Priority 3: Try element property tables - if ( m_porePressureSource == AUTO || m_porePressureSource == ELEMENT_PROPERTY_TABLE ) + auto ppSourcePair = calculatePorePressureInSegment( intersectionIdx, + 0.0, + interpolatedInterfacePorePressureBar, + poreElementPressuresPascal ); + if ( ppSourcePair.second == INVALID ) { - size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx]; - if ( elmIdx < poreElementPressuresPascal.size() ) - { - ppValues[intersectionIdx] = static_cast( ELEMENT_PROPERTY_TABLE ); - } + ppValues[intersectionIdx] = static_cast( HYDROSTATIC_PP ); } - - // Priority 2: Try LAS-file - if ( m_porePressureSource == AUTO || m_porePressureSource == LAS_FILE ) + else { - double lasMudWeightKgPerM3 = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndMudWeightKgPerM3 ); - if ( lasMudWeightKgPerM3 != std::numeric_limits::infinity() ) - { - ppValues[intersectionIdx] = static_cast( LAS_FILE ); - } - } - - // Priority 1: Try pore pressure from the grid - if ( m_porePressureSource == AUTO || m_porePressureSource == GRID ) - { - float averagePorePressureBar = std::numeric_limits::infinity(); - bool validGridPorePressure = averageIntersectionValuesToSegmentValue( intersectionIdx, - interpolatedInterfacePorePressureBar, - std::numeric_limits::infinity(), - &averagePorePressureBar ); - if ( validGridPorePressure ) - { - ppValues[intersectionIdx] = static_cast( GRID ); - } + ppValues[intersectionIdx] = static_cast( ppSourcePair.second ); } } return ppValues; @@ -665,31 +644,8 @@ std::vector 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( 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( 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::infinity() ) - { - poissonValues[intersectionIdx] = static_cast( LAS_FILE ); - } - } - } + auto poissonSourcePair = calculatePoissonRatioInSegment( intersectionIdx, poissonRatios ); + poissonValues[intersectionIdx] = static_cast( poissonSourcePair.second ); } return poissonValues; } @@ -710,30 +666,8 @@ std::vector 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( 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( 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::infinity() ) - { - ucsValues[intersectionIdx] = static_cast( LAS_FILE ); - } - } - } + auto ucsSourcePair = calculateUcsInSegment( intersectionIdx, ucsValuesPascal ); + ucsValues[intersectionIdx] = static_cast( ucsSourcePair.second ); } return ucsValues; } diff --git a/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.h b/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.h index f1bf8d59aa..5add11a4ed 100644 --- a/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.h +++ b/ApplicationCode/ReservoirDataModel/RigGeoMechWellLogExtractor.h @@ -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, - double effectiveDepthMeters, - const std::vector& poreElementPressuresPascal ) const; + std::pair + calculatePorePressureInSegment( int64_t intersectionIdx, + double effectiveDepthMeters, + const std::vector& interpolatedInterfacePorePressuresBar, + const std::vector& poreElementPressuresPascal ) const; - float calculatePoissonRatio( int64_t intersectionIdx, const std::vector& poissonRatios ) const; - float calculateUcs( int64_t intersectionIdx, const std::vector& ucsValuesPascal ) const; + std::pair calculatePoissonRatioInSegment( int64_t intersectionIdx, + const std::vector& poissonRatios ) const; + std::pair calculateUcsInSegment( int64_t intersectionIdx, + const std::vector& ucsValuesPascal ) const; void wellPathAngles( const RigFemResultAddress& resAddr, std::vector* values ); void wellPathScaledCurveData( const RigFemResultAddress& resAddr, int frameIndex, std::vector* values );