Merge pull request #4689 from OPM/feature-WBS-class

#4665 Implement a Well Bore Stability Plot class
This commit is contained in:
Gaute Lindkvist
2019-09-10 09:48:28 +02:00
committed by GitHub
12 changed files with 566 additions and 88 deletions

View File

@@ -30,11 +30,11 @@
#include "RimGeoMechCase.h"
#include "RimGeoMechView.h"
#include "RimProject.h"
#include "RimWellBoreStabilityPlot.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFile.h"
#include "RimWellLogFileChannel.h"
#include "RimWellLogFileCurve.h"
#include "RimWellLogPlot.h"
#include "RimWellLogPlotCollection.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
@@ -104,8 +104,9 @@ void RicNewWellBoreStabilityPlotFeature::onActionTriggered( bool isChecked )
caf::ProgressInfo progInfo( 100, "Creating Well Bore Stability Plot" );
RimGeoMechCase* geoMechCase = geoMechView->geoMechCase();
RimWellLogPlot* plot = RicNewWellLogPlotFeatureImpl::createWellLogPlot( false, "Well Bore Stability" );
RimGeoMechCase* geoMechCase = geoMechView->geoMechCase();
RimWellBoreStabilityPlot* plot = RicNewWellLogPlotFeatureImpl::createWellBoreStabilityPlot( false,
"Well Bore Stability" );
{
auto task = progInfo.task( "Creating formation track", 2 );
@@ -158,9 +159,9 @@ void RicNewWellBoreStabilityPlotFeature::setupActionLook( QAction* actionToSetup
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellBoreStabilityPlotFeature::createFormationTrack( RimWellLogPlot* plot,
RimWellPath* wellPath,
RimGeoMechCase* geoMechCase )
void RicNewWellBoreStabilityPlotFeature::createFormationTrack( RimWellBoreStabilityPlot* plot,
RimWellPath* wellPath,
RimGeoMechCase* geoMechCase )
{
RimWellLogTrack* formationTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Formations", plot );
formationTrack->setFormationWellPath( wellPath );
@@ -173,9 +174,9 @@ void RicNewWellBoreStabilityPlotFeature::createFormationTrack( RimWellLogPlot* p
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellBoreStabilityPlotFeature::createCasingShoeTrack( RimWellLogPlot* plot,
RimWellPath* wellPath,
RimGeoMechCase* geoMechCase )
void RicNewWellBoreStabilityPlotFeature::createCasingShoeTrack( RimWellBoreStabilityPlot* plot,
RimWellPath* wellPath,
RimGeoMechCase* geoMechCase )
{
RimWellLogTrack* casingShoeTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Well Design", plot );
casingShoeTrack->setWidthScaleFactor( RimWellLogTrack::NARROW_TRACK );
@@ -193,9 +194,9 @@ void RicNewWellBoreStabilityPlotFeature::createCasingShoeTrack( RimWellLogPlot*
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellLogPlot* plot,
RimWellPath* wellPath,
RimGeoMechView* geoMechView )
void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBoreStabilityPlot* plot,
RimWellPath* wellPath,
RimGeoMechView* geoMechView )
{
RimWellLogTrack* stabilityCurvesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false,
"Stability Curves",
@@ -242,9 +243,9 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellLogP
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellLogPlot* plot,
RimWellPath* wellPath,
RimGeoMechView* geoMechView )
void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellBoreStabilityPlot* plot,
RimWellPath* wellPath,
RimGeoMechView* geoMechView )
{
RimWellLogTrack* wellPathAnglesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false,
"Well Path Angles",

View File

@@ -22,7 +22,7 @@
class RimGeoMechCase;
class RimGeoMechView;
class RimWellLogPlot;
class RimWellBoreStabilityPlot;
class RimWellPath;
//==================================================================================================
@@ -39,8 +39,8 @@ protected:
void setupActionLook( QAction* actionToSetup ) override;
private:
void createFormationTrack( RimWellLogPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase );
void createCasingShoeTrack( RimWellLogPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase );
void createStabilityCurvesTrack( RimWellLogPlot* plot, RimWellPath* wellPath, RimGeoMechView* geoMechCase );
void createAnglesTrack( RimWellLogPlot* plot, RimWellPath* wellPath, RimGeoMechView* geoMechView );
void createFormationTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase );
void createCasingShoeTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase );
void createStabilityCurvesTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechView* geoMechCase );
void createAnglesTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechView* geoMechView );
};

View File

@@ -21,6 +21,7 @@
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimWellBoreStabilityPlot.h"
#include "RimWellLogPlot.h"
#include "RimWellLogPlotCollection.h"
#include "RimWellLogTrack.h"
@@ -31,6 +32,42 @@
#include <QString>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellBoreStabilityPlot*
RicNewWellLogPlotFeatureImpl::createWellBoreStabilityPlot( bool showAfterCreation /*= true*/,
const QString& plotDescription /*= QString("")*/ )
{
RimWellLogPlotCollection* wellLogPlotColl = wellLogPlotCollection();
CVF_ASSERT( wellLogPlotColl );
// Make sure the summary plot window is created
RiaGuiApplication::instance()->getOrCreateMainPlotWindow();
RimWellBoreStabilityPlot* plot = new RimWellBoreStabilityPlot();
plot->setAsPlotMdiWindow();
wellLogPlotColl->wellLogPlots().push_back( plot );
if ( !plotDescription.isEmpty() )
{
plot->setDescription( plotDescription );
}
else
{
plot->setDescription(
QString( "Well Bore Stability Plot %1" ).arg( wellLogPlotCollection()->wellLogPlots.size() ) );
}
if ( showAfterCreation )
{
RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow();
}
return plot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -21,6 +21,7 @@
#include <QString>
class RimWellBoreStabilityPlot;
class RimWellLogPlotCollection;
class RimWellLogPlot;
class RimWellLogTrack;
@@ -31,12 +32,14 @@ class RimWellLogTrack;
class RicNewWellLogPlotFeatureImpl
{
public:
static RimWellLogPlot* createWellLogPlot( bool showAfterCreation = true,
const QString& plotDescription = QString( "" ) );
static RimWellLogTrack* createWellLogPlotTrack( bool updateAfterCreation = true,
const QString& trackDescription = QString( "" ),
RimWellLogPlot* existingPlot = nullptr );
static void updateAfterCreation( RimWellLogPlot* plot );
static RimWellBoreStabilityPlot* createWellBoreStabilityPlot( bool showAfterCreation = true,
const QString& plotDescription = QString( "" ) );
static RimWellLogPlot* createWellLogPlot( bool showAfterCreation = true,
const QString& plotDescription = QString( "" ) );
static RimWellLogTrack* createWellLogPlotTrack( bool updateAfterCreation = true,
const QString& trackDescription = QString( "" ),
RimWellLogPlot* existingPlot = nullptr );
static void updateAfterCreation( RimWellLogPlot* plot );
private:
static RimWellLogPlotCollection* wellLogPlotCollection();

View File

@@ -75,6 +75,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimPltPlotCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogTrack.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimWellBoreStabilityPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimViewLinker.h
${CMAKE_CURRENT_LIST_DIR}/RimViewLinkerCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogExtractionCurve.h
@@ -210,6 +211,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlotCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftPlotCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPltPlotCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellLogPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellBoreStabilityPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellLogTrack.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimViewLinker.cpp

View File

@@ -24,6 +24,7 @@
#include "RimCase.h"
#include "RimEclipseCase.h"
#include "RimGeoMechCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimWellLogFile.h"
@@ -333,6 +334,31 @@ void RimTools::eclipseCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTools::geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
RimProject* proj = RiaApplication::instance()->project();
if ( proj )
{
std::vector<RimCase*> cases;
proj->allCases( cases );
for ( RimCase* c : cases )
{
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( c );
if ( geoMechCase )
{
options->push_back( caf::PdmOptionItemInfo( c->caseUserDescription(), c, false, c->uiIconProvider() ) );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -55,5 +55,6 @@ public:
static void wellPathWithFormations( std::vector<RimWellPath*>* wellPaths );
static void caseOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void eclipseCaseOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options );
static RimWellPathCollection* wellPathCollection();
};

View File

@@ -0,0 +1,238 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimWellBoreStabilityPlot.h"
#include "RigFemPartResultsCollection.h"
#include "RigFemResultAddress.h"
#include "RigGeoMechCaseData.h"
#include "RimGeoMechCase.h"
#include "RimTools.h"
#include "RimWellLogCurveCommonDataSource.h"
#include "RimWellLogFile.h"
#include "cafPdmBase.h"
#include "cafPdmObject.h"
#include "cafPdmUiGroup.h"
namespace caf
{
template<>
void RimWellBoreStabilityPlot::ParameterSourceEnum::setUp()
{
addItem(RigGeoMechWellLogExtractor::AUTO, "AUTO", "Automatic");
addItem(RigGeoMechWellLogExtractor::GRID, "GRID", "Grid");
addItem(RigGeoMechWellLogExtractor::LAS_FILE, "LAS_FILE", "LAS File");
addItem(RigGeoMechWellLogExtractor::ELEMENT_PROPERTY_TABLE, "ELEMENT_PROPERTY_TABLE", "Element Property Table");
addItem(RigGeoMechWellLogExtractor::USER_DEFINED, "USER_DEFINED", "User Defined");
addItem(RigGeoMechWellLogExtractor::HYDROSTATIC_PP, "HYDROSTATIC_PP", "Hydrostatic");
setDefault(RigGeoMechWellLogExtractor::AUTO);
}
} // End namespace caf
CAF_PDM_SOURCE_INIT(RimWellBoreStabilityPlot, "WellBoreStabilityPlot");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellBoreStabilityPlot::RimWellBoreStabilityPlot()
{
CAF_PDM_InitObject("Well Bore Stability Plot", ":/WellLogPlot16x16.png", "", "");
CAF_PDM_InitFieldNoDefault(
&m_porePressureSource, "PorePressureSource", "Pore Pressure", "", "Data source for Pore Pressure", "");
CAF_PDM_InitFieldNoDefault(
&m_poissonRatioSource, "PoissionRatioSource", "Poisson Ratio", "", "Data source for Poisson Ratio", "");
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);
// 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);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechWellLogExtractor::WbsParameterSource RimWellBoreStabilityPlot::porePressureSource() const
{
return m_porePressureSource();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechWellLogExtractor::WbsParameterSource RimWellBoreStabilityPlot::poissonRatioSource() const
{
return m_poissonRatioSource();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechWellLogExtractor::WbsParameterSource RimWellBoreStabilityPlot::ucsSource() const
{
return m_ucsSource();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellBoreStabilityPlot::userDefinedPoissonRatio() const
{
return m_userDefinedPoissionRatio();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellBoreStabilityPlot::userDefinedUcs() const
{
return m_userDefinedUcs();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellBoreStabilityPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
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_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);
RimWellLogPlot::defineUiOrdering(uiConfigName, uiOrdering);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellBoreStabilityPlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
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())
{
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())
{
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())
{
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;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellBoreStabilityPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue)
{
RimWellLogPlot::fieldChangedByUi(changedField, oldValue, newValue);
if (changedField == &m_porePressureSource || changedField == &m_poissonRatioSource || changedField == &m_ucsSource ||
changedField == &m_userDefinedPoissionRatio || changedField == &m_userDefinedUcs)
{
this->loadDataAndUpdate();
}
}

View File

@@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimWellLogPlot.h"
#include "RigGeoMechWellLogExtractor.h"
#include "cafAppEnum.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
#include <set>
class RimGeoMechCase;
class RimWellPath;
class RimWellBoreStabilityPlot : public RimWellLogPlot
{
CAF_PDM_HEADER_INIT;
public:
typedef caf::AppEnum<RigGeoMechWellLogExtractor::WbsParameterSource> ParameterSourceEnum;
public:
RimWellBoreStabilityPlot();
RigGeoMechWellLogExtractor::WbsParameterSource porePressureSource() const;
RigGeoMechWellLogExtractor::WbsParameterSource poissonRatioSource() const;
RigGeoMechWellLogExtractor::WbsParameterSource ucsSource() const;
double userDefinedPoissonRatio() const;
double userDefinedUcs() const;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue ) override;
private:
caf::PdmField<ParameterSourceEnum> m_porePressureSource;
caf::PdmField<ParameterSourceEnum> m_poissonRatioSource;
caf::PdmField<ParameterSourceEnum> m_ucsSource;
caf::PdmField<double> m_userDefinedPoissionRatio;
caf::PdmField<double> m_userDefinedUcs;
};

View File

@@ -46,6 +46,7 @@
#include "RimOilField.h"
#include "RimProject.h"
#include "RimTools.h"
#include "RimWellBoreStabilityPlot.h"
#include "RimWellLogCurve.h"
#include "RimWellLogFile.h"
#include "RimWellLogFileChannel.h"
@@ -408,6 +409,16 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate( bool updateParentPlot )
tvDepthValues = geomExtractor->cellIntersectionTVDs();
findAndLoadWbsParametersFromLasFiles( m_wellPath(), geomExtractor.p() );
RimWellBoreStabilityPlot* wbsPlot;
this->firstAncestorOrThisOfType( wbsPlot );
if ( wbsPlot )
{
geomExtractor->setWbsParameters( wbsPlot->porePressureSource(),
wbsPlot->poissonRatioSource(),
wbsPlot->ucsSource(),
wbsPlot->userDefinedPoissonRatio(),
wbsPlot->userDefinedUcs() );
}
geomExtractor->setRkbDiff( rkbDiff() );

View File

@@ -115,17 +115,22 @@ float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t inters
double effectiveDepthMeters,
const std::vector<float>& poreElementPressuresPascal ) const
{
// Priority 4: Assign a default of hydrostatic pore pressure
double porePressure = hydroStaticPorePressureBar;
// 1: Try pore pressure from the grid
if ( porePressure == hydroStaticPorePressureBar &&
averageSegmentPorePressureBar != std::numeric_limits<double>::infinity() && averageSegmentPorePressureBar > 0.0 )
// Priority 3: Try element property tables
if ( m_porePressureSource == AUTO || m_porePressureSource == ELEMENT_PROPERTY_TABLE )
{
porePressure = averageSegmentPorePressureBar;
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poreElementPressuresPascal.size() )
{
// Pore pressure from element property tables are in pascal.
porePressure = pascalToBar( poreElementPressuresPascal[elmIdx] );
}
}
// 2: Try mud weight from LAS-file to generate pore pressure
if ( porePressure == hydroStaticPorePressureBar && !m_wellLogMdAndMudWeightKgPerM3.empty() )
// 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() )
@@ -135,14 +140,16 @@ float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t inters
porePressure = pascalToBar( porePressurePascal );
}
}
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
// 3: Try pore pressure from element property tables
if ( porePressure == hydroStaticPorePressureBar && elmIdx < poreElementPressuresPascal.size() )
// Priority 1: Try pore pressure from the grid
if ( m_porePressureSource == AUTO || m_porePressureSource == GRID )
{
// Pore pressure from element property tables are in pascal.
porePressure = pascalToBar( poreElementPressuresPascal[elmIdx] );
if ( averageSegmentPorePressureBar != std::numeric_limits<double>::infinity() &&
averageSegmentPorePressureBar > 0.0 )
{
porePressure = averageSegmentPorePressureBar;
}
}
// 4: If no pore-pressure was found, the default value of hydrostatic pore pressure is used.
CVF_ASSERT( porePressure >= 0.0 );
return porePressure;
@@ -154,24 +161,32 @@ float RigGeoMechWellLogExtractor::calculatePorePressureInSegment( int64_t inters
float RigGeoMechWellLogExtractor::calculatePoissonRatio( int64_t intersectionIdx,
const std::vector<float>& poissonRatios ) const
{
const double defaultPoissonRatio = 0.25;
// Priority 3: User defined poisson ratio
double poissonRatio = m_userDefinedPoissonRatio;
double poissonRatio = defaultPoissonRatio;
if ( !m_wellLogMdAndPoissonRatios.empty() )
// Priority 2: Element property table ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == ELEMENT_PROPERTY_TABLE )
{
double lasPoissionRatio = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndPoissonRatios );
if ( lasPoissionRatio != std::numeric_limits<double>::infinity() )
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < poissonRatios.size() )
{
poissonRatio = lasPoissionRatio;
poissonRatio = poissonRatios[elmIdx];
}
}
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( poissonRatio == defaultPoissonRatio && elmIdx < poissonRatios.size() )
// Priority 1: Las-file poisson ratio
if ( m_poissonRatioSource == AUTO || m_poissonRatioSource == LAS_FILE )
{
poissonRatio = poissonRatios[elmIdx];
if ( !m_wellLogMdAndPoissonRatios.empty() )
{
double lasPoissionRatio = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndPoissonRatios );
if ( lasPoissionRatio != std::numeric_limits<double>::infinity() )
{
poissonRatio = lasPoissionRatio;
}
}
}
return poissonRatio;
}
@@ -180,26 +195,32 @@ float RigGeoMechWellLogExtractor::calculatePoissonRatio( int64_t
//--------------------------------------------------------------------------------------------------
float RigGeoMechWellLogExtractor::calculateUcs( int64_t intersectionIdx, const std::vector<float>& ucsValuesPascal ) const
{
// Typical UCS: http://ceae.colorado.edu/~amadei/CVEN5768/PDF/NOTES8.pdf
// Typical UCS for Shale is 5 - 100 MPa -> 50 - 1000 bar.
const double defaultUniaxialStrengthInBar = 100.0;
// Priority 3: User defined UCS
double uniaxialStrengthInBar = m_userDefinedUcs;
double uniaxialStrengthInBar = defaultUniaxialStrengthInBar;
if ( !m_wellLogMdAndUcsBar.empty() )
// Priority 2: From element property table
if ( m_ucsSource == AUTO || m_ucsSource == ELEMENT_PROPERTY_TABLE )
{
double lasUniaxialStrengthInBar = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndUcsBar );
if ( lasUniaxialStrengthInBar != std::numeric_limits<double>::infinity() )
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( elmIdx < ucsValuesPascal.size() )
{
uniaxialStrengthInBar = lasUniaxialStrengthInBar;
// Read UCS from element table in Pascal
uniaxialStrengthInBar = pascalToBar( ucsValuesPascal[elmIdx] );
}
}
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
if ( uniaxialStrengthInBar == defaultUniaxialStrengthInBar && elmIdx < ucsValuesPascal.size() )
if ( m_ucsSource == AUTO || m_ucsSource == LAS_FILE )
{
// Read UCS from element table in Pascal
uniaxialStrengthInBar = pascalToBar( ucsValuesPascal[elmIdx] );
if ( !m_wellLogMdAndUcsBar.empty() )
{
double lasUniaxialStrengthInBar = getWellLogSegmentValue( intersectionIdx, m_wellLogMdAndUcsBar );
if ( lasUniaxialStrengthInBar != std::numeric_limits<double>::infinity() )
{
uniaxialStrengthInBar = lasUniaxialStrengthInBar;
}
}
}
return uniaxialStrengthInBar;
}
@@ -514,6 +535,46 @@ void RigGeoMechWellLogExtractor::setWellLogMdAndPoissonRatio( const std::vector<
m_wellLogMdAndPoissonRatios = poissonRatios;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RigGeoMechWellLogExtractor::supportedSourcesForPorePressure()
{
return {AUTO, GRID, LAS_FILE, ELEMENT_PROPERTY_TABLE, HYDROSTATIC_PP};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RigGeoMechWellLogExtractor::supportedSourcesForPoissonRatio()
{
return {AUTO, LAS_FILE, ELEMENT_PROPERTY_TABLE, USER_DEFINED};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigGeoMechWellLogExtractor::WbsParameterSource> RigGeoMechWellLogExtractor::supportedSourcesForUcs()
{
return {AUTO, LAS_FILE, ELEMENT_PROPERTY_TABLE, USER_DEFINED};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGeoMechWellLogExtractor::setWbsParameters( WbsParameterSource porePressureSource,
WbsParameterSource poissonRatioSource,
WbsParameterSource ucsSource,
double userDefinedPoissonRatio,
double userDefinedUcs )
{
m_porePressureSource = porePressureSource;
m_poissonRatioSource = poissonRatioSource;
m_ucsSource = ucsSource;
m_userDefinedPoissonRatio = userDefinedPoissonRatio;
m_userDefinedUcs = userDefinedUcs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -688,7 +749,8 @@ void RigGeoMechWellLogExtractor::calculateIntersection()
hexCorners[6] = cvf::Vec3d( nodeCoords[cornerIndices[6]] );
hexCorners[7] = cvf::Vec3d( nodeCoords[cornerIndices[7]] );
// int intersectionCount = RigHexIntersector::lineHexCellIntersection(p1, p2, hexCorners, closeCells[ccIdx], &intersections);
// int intersectionCount = RigHexIntersector::lineHexCellIntersection(p1, p2, hexCorners, closeCells[ccIdx],
// &intersections);
RigHexIntersectionTools::lineHexCellIntersection( p1, p2, hexCorners, closeCells[ccIdx], &intersections );
}
@@ -818,39 +880,41 @@ cvf::Vec3f RigGeoMechWellLogExtractor::cellCentroid( size_t intersectionIdx ) co
double RigGeoMechWellLogExtractor::getWellLogSegmentValue( size_t intersectionIdx,
const std::vector<std::pair<double, double>>& wellLogValues ) const
{
double startMD, endMD;
if ( intersectionIdx % 2 == 0 )
if ( !wellLogValues.empty() )
{
startMD = m_intersectionMeasuredDepths[intersectionIdx];
endMD = m_intersectionMeasuredDepths[intersectionIdx + 1];
}
else
{
startMD = m_intersectionMeasuredDepths[intersectionIdx - 1];
endMD = m_intersectionMeasuredDepths[intersectionIdx];
}
RiaWeightedMeanCalculator<double> averageCalc;
for ( auto& depthAndValue : wellLogValues )
{
if ( cvf::Math::valueInRange( depthAndValue.first, startMD, endMD ) )
double startMD, endMD;
if ( intersectionIdx % 2 == 0 )
{
cvf::Vec3d position = m_wellPath->interpolatedPointAlongWellPath( depthAndValue.first );
cvf::Vec3d centroid( cellCentroid( intersectionIdx ) );
double weight = 1.0;
double dist = ( position - centroid ).length();
if ( dist > 1.0 )
startMD = m_intersectionMeasuredDepths[intersectionIdx];
endMD = m_intersectionMeasuredDepths[intersectionIdx + 1];
}
else
{
startMD = m_intersectionMeasuredDepths[intersectionIdx - 1];
endMD = m_intersectionMeasuredDepths[intersectionIdx];
}
RiaWeightedMeanCalculator<double> averageCalc;
for ( auto& depthAndValue : wellLogValues )
{
if ( cvf::Math::valueInRange( depthAndValue.first, startMD, endMD ) )
{
weight = 1.0 / dist;
cvf::Vec3d position = m_wellPath->interpolatedPointAlongWellPath( depthAndValue.first );
cvf::Vec3d centroid( cellCentroid( intersectionIdx ) );
double weight = 1.0;
double dist = ( position - centroid ).length();
if ( dist > 1.0 )
{
weight = 1.0 / dist;
}
averageCalc.addValueAndWeight( depthAndValue.second, weight );
}
averageCalc.addValueAndWeight( depthAndValue.second, weight );
}
if ( averageCalc.validAggregatedWeight() )
{
return averageCalc.weightedMean();
}
}
if ( averageCalc.validAggregatedWeight() )
{
return averageCalc.weightedMean();
}
return std::numeric_limits<double>::infinity();
}

View File

@@ -47,6 +47,17 @@ class BoundingBox;
//==================================================================================================
class RigGeoMechWellLogExtractor : public RigWellLogExtractor
{
public:
enum WbsParameterSource
{
AUTO,
GRID, // Only relevant for Pore Pressure
LAS_FILE,
ELEMENT_PROPERTY_TABLE,
USER_DEFINED, // Not relevant for Pore Pressure
HYDROSTATIC_PP // Only relevant for Pore Pressure
};
public:
RigGeoMechWellLogExtractor( RigGeoMechCaseData* aCase,
const RigWellPath* wellpath,
@@ -60,6 +71,16 @@ public:
void setWellLogMdAndUcsBar( const std::vector<std::pair<double, double>>& ucsValues );
void setWellLogMdAndPoissonRatio( const std::vector<std::pair<double, double>>& poissonRatio );
static std::set<WbsParameterSource> supportedSourcesForPorePressure();
static std::set<WbsParameterSource> supportedSourcesForPoissonRatio();
static std::set<WbsParameterSource> supportedSourcesForUcs();
void setWbsParameters( WbsParameterSource porePressureSource,
WbsParameterSource poissonRatioSource,
WbsParameterSource ucsSource,
double userDefinedPoissonRatio,
double userDefinedUcs );
private:
enum WellPathTangentCalculation
{
@@ -72,6 +93,7 @@ private:
double hydroStaticPorePressureBar,
double effectiveDepthMeters,
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;
@@ -113,5 +135,11 @@ private:
std::vector<std::pair<double, double>> m_wellLogMdAndUcsBar;
std::vector<std::pair<double, double>> m_wellLogMdAndPoissonRatios;
WbsParameterSource m_porePressureSource;
WbsParameterSource m_poissonRatioSource;
WbsParameterSource m_ucsSource;
double m_userDefinedPoissonRatio;
double m_userDefinedUcs;
static const double UNIT_WEIGHT_OF_WATER;
};