Merge pull request #4804 from OPM/feature-minor-wbs-changes

Minor wbs changes
This commit is contained in:
Gaute Lindkvist
2019-10-02 17:56:09 +02:00
committed by GitHub
12 changed files with 356 additions and 286 deletions

View File

@@ -68,6 +68,12 @@ void RicExportToLasFileFeature::onActionTriggered( bool isChecked )
RicExportToLasFileResampleUi featureUi;
featureUi.exportFolder = defaultDir;
if ( RicWellLogPlotCurveFeatureImpl::parentWellBoreStabilityPlot() )
{
featureUi.filePrefix = "WBS_";
featureUi.capitalizeFileName = true;
}
{
std::vector<QString> wellNames;
std::vector<double> rkbDiffs;
@@ -101,7 +107,7 @@ void RicExportToLasFileFeature::onActionTriggered( bool isChecked )
lasExporter.setRkbDiffs( wellNames, userDefRkbDiff );
}
lasExporter.writeToFolder( featureUi.exportFolder() );
lasExporter.writeToFolder( featureUi.exportFolder(), featureUi.filePrefix(), featureUi.capitalizeFileName() );
// Remember the path to next time
RiaApplication::instance()->setLastUsedDialogDirectory( "WELL_LOGS_DIR", featureUi.exportFolder() );

View File

@@ -47,6 +47,8 @@ RicExportToLasFileResampleUi::RicExportToLasFileResampleUi( void )
CAF_PDM_InitField( &exportFolder, "ExportFolder", QString(), "Export Folder", "", "", "" );
exportFolder.uiCapability()->setUiEditorTypeName( caf::PdmUiFilePathEditor::uiEditorTypeName() );
CAF_PDM_InitField( &filePrefix, "FilePrefix", QString( "" ), "File Prefix", "", "", "" );
CAF_PDM_InitField( &capitalizeFileName, "CapitalizeFileName", false, "Capitalize File Name", "", "", "" );
CAF_PDM_InitField( &activateResample, "ActivateResample", false, "Resample Curve Data", "", "", "" );
activateResample.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
@@ -168,7 +170,8 @@ void RicExportToLasFileResampleUi::updateFieldVisibility()
void RicExportToLasFileResampleUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &exportFolder );
uiOrdering.add( &filePrefix );
uiOrdering.add( &capitalizeFileName );
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Resampling" );

View File

@@ -47,6 +47,8 @@ public:
~RicExportToLasFileResampleUi() override;
caf::PdmField<QString> exportFolder;
caf::PdmField<QString> filePrefix;
caf::PdmField<bool> capitalizeFileName;
caf::PdmField<bool> activateResample;
caf::PdmField<double> resampleInterval;

View File

@@ -208,22 +208,16 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore
stabilityCurvesTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR );
stabilityCurvesTrack->setFormationWellPath( wellPath );
stabilityCurvesTrack->setFormationCase( geoMechView->geoMechCase() );
stabilityCurvesTrack->setAnnotationType( RiuPlotAnnotationTool::CURVE_ANNOTATIONS );
stabilityCurvesTrack->setAnnotationType( RiuPlotAnnotationTool::NO_ANNOTATIONS );
stabilityCurvesTrack->setShowRegionLabels( true );
std::vector<QString> resultNames = RiaDefines::wellPathStabilityResultNames();
std::vector<cvf::Color3f> colors = {cvf::Color3f::RED,
std::vector<cvf::Color3f> colors = {cvf::Color3f::BLUE,
cvf::Color3f::BROWN,
cvf::Color3f::RED,
cvf::Color3f::PURPLE,
cvf::Color3f::GREEN,
cvf::Color3f::BLUE,
cvf::Color3f::ORANGE};
std::vector<RiuQwtPlotCurve::LineStyleEnum> lineStyles = {RiuQwtPlotCurve::STYLE_SOLID,
RiuQwtPlotCurve::STYLE_DASH,
RiuQwtPlotCurve::STYLE_DASH_DOT,
RiuQwtPlotCurve::STYLE_SOLID,
RiuQwtPlotCurve::STYLE_DASH};
cvf::Color3f::DARK_GREEN};
for ( size_t i = 0; i < resultNames.size(); ++i )
{
@@ -240,7 +234,6 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore
curve->setCurrentTimeStep( geoMechView->currentTimeStep() );
curve->setCustomName( resultName );
curve->setColor( colors[i % colors.size()] );
curve->setLineStyle( lineStyles[i % lineStyles.size()] );
curve->setLineThickness( 2 );
curve->loadDataAndUpdate( false );
}
@@ -261,7 +254,7 @@ void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellBoreStability
const double angleIncrement = 90.0;
std::vector<QString> resultNames = RiaDefines::wellPathAngleResultNames();
std::vector<cvf::Color3f> colors = {cvf::Color3f::DARK_RED, cvf::Color3f::BLUE};
std::vector<cvf::Color3f> colors = {cvf::Color3f::GREEN, cvf::Color3f::ORANGE};
std::vector<RiuQwtPlotCurve::LineStyleEnum> lineStyles = {RiuQwtPlotCurve::STYLE_SOLID, RiuQwtPlotCurve::STYLE_DASH};

View File

@@ -22,6 +22,7 @@
#include "RiaColorTables.h"
#include "RimWellAllocationPlot.h"
#include "RimWellBoreStabilityPlot.h"
#include "RimWellLogCurve.h"
#include "RimWellRftPlot.h"
@@ -42,7 +43,10 @@ cvf::Color3f RicWellLogPlotCurveFeatureImpl::curveColorFromTable( size_t index )
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogCurve*> RicWellLogPlotCurveFeatureImpl::selectedWellLogCurves()
{
std::set<RimWellLogCurve*> curveSet;
// Use std::set to determine uniqueness but a vector for inserting curves.
// This is to retain deterministic order.
std::vector<RimWellLogCurve*> allCurves;
std::set<RimWellLogCurve*> uniqueCurves;
{
std::vector<caf::PdmUiItem*> selectedItems;
@@ -58,17 +62,21 @@ std::vector<RimWellLogCurve*> RicWellLogPlotCurveFeatureImpl::selectedWellLogCur
for ( RimWellLogCurve* curve : childCurves )
{
curveSet.insert( curve );
if ( !uniqueCurves.count( curve ) )
{
uniqueCurves.insert( curve );
allCurves.push_back( curve );
}
}
}
}
}
std::vector<RimWellLogCurve*> allCurves;
for ( RimWellLogCurve* curve : curveSet )
{
allCurves.push_back( curve );
}
// Sort by curve name in a way that retains the original order of equivalent items
// This way we have a completely deterministic order
std::stable_sort( allCurves.begin(), allCurves.end(), []( const RimWellLogCurve* lhs, const RimWellLogCurve* rhs ) {
return lhs->curveName() < rhs->curveName();
} );
return allCurves;
}
@@ -102,3 +110,18 @@ RimWellRftPlot* RicWellLogPlotCurveFeatureImpl::parentWellRftPlot()
return wellRftPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellBoreStabilityPlot* RicWellLogPlotCurveFeatureImpl::parentWellBoreStabilityPlot()
{
caf::PdmObjectHandle* destinationObject = dynamic_cast<caf::PdmObjectHandle*>(
caf::SelectionManager::instance()->selectedItem() );
if ( !destinationObject ) return nullptr;
RimWellBoreStabilityPlot* wbsPlot = nullptr;
destinationObject->firstAncestorOrThisOfType( wbsPlot );
return wbsPlot;
}

View File

@@ -21,6 +21,7 @@
#include "cafPdmFieldCvfColor.h"
class RimWellBoreStabilityPlot;
class RimWellLogCurve;
class RimWellAllocationPlot;
class RimWellRftPlot;
@@ -35,4 +36,5 @@ public:
static std::vector<RimWellLogCurve*> selectedWellLogCurves();
static RimWellAllocationPlot* parentWellAllocationPlot();
static RimWellRftPlot* parentWellRftPlot();
static RimWellBoreStabilityPlot* parentWellBoreStabilityPlot();
};

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,89 +148,25 @@ 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() )
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<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,
double effectiveDepthMeters,
const std::vector<float>& poreElementPressuresPascal ) const
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,
const std::vector<float>& poissonRatios ) const
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,
effectiveDepthMeters,
poreElementPressuresPascal );
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,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<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.
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<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 )
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<double>( ELEMENT_PROPERTY_TABLE );
}
ppValues[intersectionIdx] = static_cast<double>( 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<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,
interpolatedInterfacePorePressureBar,
std::numeric_limits<float>::infinity(),
&averagePorePressureBar );
if ( validGridPorePressure )
{
ppValues[intersectionIdx] = static_cast<double>( GRID );
}
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,
double effectiveDepthMeters,
const std::vector<float>& poreElementPressuresPascal ) const;
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 );

View File

@@ -374,7 +374,9 @@ void RigLasFileExporter::setRkbDiffs( const std::vector<QString>& wellNames, con
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigLasFileExporter::writeToFolder( const QString& exportFolder )
bool RigLasFileExporter::writeToFolder( const QString& exportFolder,
const QString& filePrefix /*= ""*/,
bool capitalizeFileName /*= false*/ )
{
std::vector<SingleLasFileMetaData> lasFileDescriptions = createLasFileDescriptions( m_curves );
@@ -392,10 +394,15 @@ bool RigLasFileExporter::writeToFolder( const QString& exportFolder )
}
QDir dir( exportFolder );
QString fileName = dir.absoluteFilePath( QString::fromStdString( lasFileDescr.generateFilename() ) );
if ( caf::Utils::fileExists( fileName ) )
QString fileName = filePrefix + QString::fromStdString( lasFileDescr.generateFilename() );
if ( capitalizeFileName )
{
QString txt = QString( "File %1 exists.\n\nDo you want to overwrite the file?" ).arg( fileName );
fileName = fileName.toUpper();
}
QString fullPathName = dir.absoluteFilePath( fileName );
if ( caf::Utils::fileExists( fullPathName ) )
{
QString txt = QString( "File %1 exists.\n\nDo you want to overwrite the file?" ).arg( fullPathName );
int ret = QMessageBox::question( nullptr,
"LAS File Export",
txt,
@@ -406,7 +413,7 @@ bool RigLasFileExporter::writeToFolder( const QString& exportFolder )
}
std::vector<std::string> commentHeader;
lasFile.WriteToFile( fileName.toStdString(), commentHeader );
lasFile.WriteToFile( fullPathName.toStdString(), commentHeader );
}
return true;

View File

@@ -38,7 +38,7 @@ public:
void wellPathsAndRkbDiff( std::vector<QString>* wellNames, std::vector<double>* rkbDiffs );
void setRkbDiffs( const std::vector<QString>& wellNames, const std::vector<double>& rkbDiffs );
bool writeToFolder( const QString& exportFolder );
bool writeToFolder( const QString& exportFolder, const QString& filePrefix = "", bool capitalizeFileName = false );
private:
std::vector<SingleLasFileMetaData> createLasFileDescriptions( const std::vector<RimWellLogCurve*>& curves );