mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-08 23:23:01 -06:00
* Initial WIP * Identical results with spreadsheet * Improved and more robust smoothing by filtering points first * Improved smoothing and more GUI * Include mixed-label for smoothing threshold
This commit is contained in:
parent
1e2e02c9ac
commit
55f0cac713
@ -32,6 +32,7 @@
|
||||
#include "RimWellLogFileCurve.h"
|
||||
#include "RimWellLogRftCurve.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellLogWbsCurve.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "RifReaderEclipseRft.h"
|
||||
@ -166,16 +167,17 @@ RimWellPath* RicWellLogTools::findWellPathWithLogFileFromSelection()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogExtractionCurve* RicWellLogTools::addExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow )
|
||||
template <typename ExtractionCurveType>
|
||||
ExtractionCurveType* RicWellLogTools::addExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow )
|
||||
{
|
||||
CVF_ASSERT( plotTrack );
|
||||
RimWellLogExtractionCurve* curve = new RimWellLogExtractionCurve();
|
||||
ExtractionCurveType* curve = new ExtractionCurveType();
|
||||
|
||||
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable( plotTrack->curveCount() );
|
||||
curve->setColor( curveColor );
|
||||
@ -363,3 +365,43 @@ RimWellLogFileCurve* RicWellLogTools::addFileCurve( RimWellLogTrack* plotTrack,
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogExtractionCurve* RicWellLogTools::addWellLogExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow /*= true */ )
|
||||
{
|
||||
return addExtractionCurve<RimWellLogExtractionCurve>( plotTrack,
|
||||
view,
|
||||
wellPath,
|
||||
simWell,
|
||||
branchIndex,
|
||||
useBranchDetection,
|
||||
showPlotWindow );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogWbsCurve* RicWellLogTools::addWellLogWbsCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow /*= true */ )
|
||||
{
|
||||
return addExtractionCurve<RimWellLogWbsCurve>( plotTrack,
|
||||
view,
|
||||
wellPath,
|
||||
simWell,
|
||||
branchIndex,
|
||||
useBranchDetection,
|
||||
showPlotWindow );
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ class RimWellLogFileChannel;
|
||||
class RimWellLogFileCurve;
|
||||
class RimWellLogRftCurve;
|
||||
class RimWellLogTrack;
|
||||
class RimWellLogWbsCurve;
|
||||
class RimWellPath;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -38,21 +39,39 @@ class RimWellPath;
|
||||
class RicWellLogTools
|
||||
{
|
||||
public:
|
||||
static RimSimWellInView* selectedSimulationWell( int* branchIndex );
|
||||
static bool wellHasRftData( const QString& wellName );
|
||||
static bool isWellPathOrSimWellSelectedInView();
|
||||
static void addWellLogChannelsToPlotTrack( RimWellLogTrack* plotTrack,
|
||||
const std::vector<RimWellLogFileChannel*>& wellLogFileChannels );
|
||||
static RimWellPath* selectedWellPathWithLogFile();
|
||||
static RimWellPath* findWellPathWithLogFileFromSelection();
|
||||
static RimWellLogExtractionCurve* addExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
static RimSimWellInView* selectedSimulationWell( int* branchIndex );
|
||||
static bool wellHasRftData( const QString& wellName );
|
||||
static bool isWellPathOrSimWellSelectedInView();
|
||||
static void addWellLogChannelsToPlotTrack( RimWellLogTrack* plotTrack,
|
||||
const std::vector<RimWellLogFileChannel*>& wellLogFileChannels );
|
||||
static RimWellPath* selectedWellPathWithLogFile();
|
||||
static RimWellPath* findWellPathWithLogFileFromSelection();
|
||||
static RimWellLogRftCurve*
|
||||
addRftCurve( RimWellLogTrack* plotTrack, const RimSimWellInView* simWell, bool showPlotWindow = true );
|
||||
static RimWellLogFileCurve* addFileCurve( RimWellLogTrack* plotTrack, bool showPlotWindow = true );
|
||||
|
||||
static RimWellLogExtractionCurve* addWellLogExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow = true );
|
||||
static RimWellLogWbsCurve* addWellLogWbsCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow = true );
|
||||
static RimWellLogRftCurve*
|
||||
addRftCurve( RimWellLogTrack* plotTrack, const RimSimWellInView* simWell, bool showPlotWindow = true );
|
||||
static RimWellLogFileCurve* addFileCurve( RimWellLogTrack* plotTrack, bool showPlotWindow = true );
|
||||
|
||||
private:
|
||||
template <typename ExtractionCurveType>
|
||||
static ExtractionCurveType* addExtractionCurve( RimWellLogTrack* plotTrack,
|
||||
Rim3dView* view,
|
||||
RimWellPath* wellPath,
|
||||
const RimSimWellInView* simWell,
|
||||
int branchIndex,
|
||||
bool useBranchDetection,
|
||||
bool showPlotWindow );
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "RimWellLogFileCurve.h"
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellLogWbsCurve.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "RicWellLogTools.h"
|
||||
@ -221,21 +222,23 @@ void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBore
|
||||
|
||||
for ( size_t i = 0; i < resultNames.size(); ++i )
|
||||
{
|
||||
const QString& resultName = resultNames[i];
|
||||
RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, resultName.toStdString(), "" );
|
||||
RimWellLogExtractionCurve* curve = RicWellLogTools::addExtractionCurve( stabilityCurvesTrack,
|
||||
geoMechView,
|
||||
wellPath,
|
||||
nullptr,
|
||||
-1,
|
||||
false,
|
||||
false );
|
||||
const QString& resultName = resultNames[i];
|
||||
RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, resultName.toStdString(), "" );
|
||||
RimWellLogWbsCurve* curve = RicWellLogTools::addWellLogWbsCurve( stabilityCurvesTrack,
|
||||
geoMechView,
|
||||
wellPath,
|
||||
nullptr,
|
||||
-1,
|
||||
false,
|
||||
false );
|
||||
curve->setGeoMechResultAddress( resAddr );
|
||||
curve->setCurrentTimeStep( geoMechView->currentTimeStep() );
|
||||
curve->setCustomName( resultName );
|
||||
curve->setColor( colors[i % colors.size()] );
|
||||
curve->setLineThickness( 2 );
|
||||
curve->loadDataAndUpdate( false );
|
||||
curve->setSmoothCurve( true );
|
||||
curve->setSmoothingThreshold( 0.002 );
|
||||
}
|
||||
stabilityCurvesTrack->calculateXZoomRangeAndUpdateQwt();
|
||||
}
|
||||
@ -262,8 +265,13 @@ void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellBoreStability
|
||||
{
|
||||
const QString& resultName = resultNames[i];
|
||||
RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, resultName.toStdString(), "" );
|
||||
RimWellLogExtractionCurve* curve =
|
||||
RicWellLogTools::addExtractionCurve( wellPathAnglesTrack, geoMechView, wellPath, nullptr, -1, false, false );
|
||||
RimWellLogExtractionCurve* curve = RicWellLogTools::addWellLogExtractionCurve( wellPathAnglesTrack,
|
||||
geoMechView,
|
||||
wellPath,
|
||||
nullptr,
|
||||
-1,
|
||||
false,
|
||||
false );
|
||||
curve->setGeoMechResultAddress( resAddr );
|
||||
curve->setCurrentTimeStep( geoMechView->currentTimeStep() );
|
||||
curve->setCustomName( resultName );
|
||||
|
@ -74,7 +74,7 @@ void RicNewWellLogCurveExtractionFeature::onActionTriggered( bool isChecked )
|
||||
RimWellLogTrack* wellLogPlotTrack = caf::SelectionManager::instance()->selectedItemOfType<RimWellLogTrack>();
|
||||
if ( wellLogPlotTrack )
|
||||
{
|
||||
RicWellLogTools::addExtractionCurve( wellLogPlotTrack, nullptr, nullptr, nullptr, -1, true );
|
||||
RicWellLogTools::addWellLogExtractionCurve( wellLogPlotTrack, nullptr, nullptr, nullptr, -1, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -113,12 +113,12 @@ void RicNewWellLogCurveExtractionFeature::onActionTriggered( bool isChecked )
|
||||
newWellLogPlotTrack->setFormationCase( view->ownerCase() );
|
||||
}
|
||||
|
||||
RimWellLogExtractionCurve* plotCurve = RicWellLogTools::addExtractionCurve( newWellLogPlotTrack,
|
||||
view,
|
||||
wellPath,
|
||||
simWell,
|
||||
branchIndex,
|
||||
useBranchDetection );
|
||||
RimWellLogExtractionCurve* plotCurve = RicWellLogTools::addWellLogExtractionCurve( newWellLogPlotTrack,
|
||||
view,
|
||||
wellPath,
|
||||
simWell,
|
||||
branchIndex,
|
||||
useBranchDetection );
|
||||
|
||||
plotCurve->loadDataAndUpdate( true );
|
||||
|
||||
|
@ -53,7 +53,12 @@ bool RicNewWellLogPlotFeature::isCommandEnabled()
|
||||
void RicNewWellLogPlotFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack();
|
||||
RimWellLogExtractionCurve* curve = RicWellLogTools::addExtractionCurve( plotTrack, nullptr, nullptr, nullptr, -1, true );
|
||||
RimWellLogExtractionCurve* curve = RicWellLogTools::addWellLogExtractionCurve( plotTrack,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
-1,
|
||||
true );
|
||||
curve->loadDataAndUpdate( true );
|
||||
RimWellLogPlot* plot = nullptr;
|
||||
plotTrack->firstAncestorOrThisOfTypeAsserted( plot );
|
||||
|
@ -66,7 +66,7 @@ void RicNewWellLogPlotTrackFeature::onActionTriggered( bool isChecked )
|
||||
plotTrack->setDescription( QString( "Track %1" ).arg( wellLogPlot->trackCount() ) );
|
||||
RiuPlotMainWindow* plotWindow = RiaGuiApplication::instance()->getOrCreateMainPlotWindow();
|
||||
RiuWellLogPlot* viewWidget = dynamic_cast<RiuWellLogPlot*>( wellLogPlot->viewWidget() );
|
||||
RicWellLogTools::addExtractionCurve( plotTrack, nullptr, nullptr, nullptr, -1, true );
|
||||
RicWellLogTools::addWellLogExtractionCurve( plotTrack, nullptr, nullptr, nullptr, -1, true );
|
||||
|
||||
plotWindow->setWidthOfMdiWindow( viewWidget, viewWidget->preferredSize().width() );
|
||||
wellLogPlot->updateConnectedEditors();
|
||||
|
@ -83,6 +83,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellLogFile.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogFileChannel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogFileCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogRftCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimIntersection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimIntersectionCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimContextCommandBuilder.h
|
||||
@ -221,6 +222,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellLogFile.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogFileChannel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogFileCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogRftCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimIntersection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimIntersectionCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimContextCommandBuilder.cpp
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "RimCase.h"
|
||||
#include "RimDataSourceSteppingTools.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimGeoMechCase.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimTools.h"
|
||||
@ -29,6 +30,7 @@
|
||||
#include "RimWellLogPlot.h"
|
||||
#include "RimWellLogPlotCollection.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellLogWbsCurve.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
@ -37,9 +39,29 @@
|
||||
|
||||
#include "cafPdmUiCheckBoxTristateEditor.h"
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellLogCurveCommonDataSource, "ChangeDataSourceFeatureUi" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogCurveCommonDataSource::DoubleComparator::DoubleComparator( double eps /*= 1.0e-8 */ )
|
||||
: m_eps( eps )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogCurveCommonDataSource::DoubleComparator::operator()( const double& lhs, const double& rhs ) const
|
||||
{
|
||||
double diff = lhs - rhs;
|
||||
return diff < -m_eps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -65,6 +87,12 @@ RimWellLogCurveCommonDataSource::RimWellLogCurveCommonDataSource()
|
||||
|
||||
CAF_PDM_InitField( &m_timeStep, "CurveTimeStep", -1, "Time Step", "", "", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_wbsSmoothing, "WBSSmoothing", "Smooth Curves", "", "", "" );
|
||||
m_wbsSmoothing.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
|
||||
m_wbsSmoothing.v() = caf::Tristate::State::PartiallyTrue;
|
||||
|
||||
CAF_PDM_InitField( &m_wbsSmoothingThreshold, "WBSSmoothingThreshold", -1.0, "Smoothing Threshold", "", "", "" );
|
||||
|
||||
m_case = nullptr;
|
||||
m_wellPath = nullptr;
|
||||
}
|
||||
@ -149,6 +177,38 @@ void RimWellLogCurveCommonDataSource::setBranchDetectionToApply( caf::Tristate::
|
||||
m_branchDetection.v() = val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::Tristate RimWellLogCurveCommonDataSource::wbsSmoothingToApply() const
|
||||
{
|
||||
return m_wbsSmoothing();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogCurveCommonDataSource::setWbsSmoothingToApply( caf::Tristate::State val )
|
||||
{
|
||||
m_wbsSmoothing.v() = val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellLogCurveCommonDataSource::wbsSmoothingThreshold() const
|
||||
{
|
||||
return m_wbsSmoothingThreshold;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogCurveCommonDataSource::setWbsSmoothingThreshold( double smoothingThreshold )
|
||||
{
|
||||
m_wbsSmoothingThreshold = smoothingThreshold;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -193,6 +253,8 @@ void RimWellLogCurveCommonDataSource::resetDefaultOptions()
|
||||
setBranchDetectionToApply( caf::Tristate::State::PartiallyTrue );
|
||||
setSimWellNameToApply( QString( "" ) );
|
||||
setTimeStepToApply( -1 );
|
||||
setWbsSmoothingToApply( caf::Tristate::State::PartiallyTrue );
|
||||
setWbsSmoothingThreshold( -1.0 );
|
||||
|
||||
m_uniqueCases.clear();
|
||||
m_uniqueTrajectoryTypes.clear();
|
||||
@ -201,6 +263,8 @@ void RimWellLogCurveCommonDataSource::resetDefaultOptions()
|
||||
m_uniqueTimeSteps.clear();
|
||||
m_uniqueBranchIndices.clear();
|
||||
m_uniqueBranchDetection.clear();
|
||||
m_uniqueWbsSmoothing.clear();
|
||||
m_uniqueWbsSmoothingThreshold.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -223,6 +287,12 @@ void RimWellLogCurveCommonDataSource::updateDefaultOptions( const std::vector<Ri
|
||||
RimWellLogFileCurve* fileCurve = dynamic_cast<RimWellLogFileCurve*>( curve );
|
||||
if ( extractionCurve )
|
||||
{
|
||||
RimWellLogWbsCurve* wbsCurve = dynamic_cast<RimWellLogWbsCurve*>( extractionCurve );
|
||||
if ( wbsCurve )
|
||||
{
|
||||
m_uniqueWbsSmoothing.insert( wbsCurve->smoothCurve() );
|
||||
m_uniqueWbsSmoothingThreshold.insert( wbsCurve->smoothingThreshold() );
|
||||
}
|
||||
if ( extractionCurve->rimCase() )
|
||||
{
|
||||
m_uniqueCases.insert( extractionCurve->rimCase() );
|
||||
@ -311,6 +381,17 @@ void RimWellLogCurveCommonDataSource::updateDefaultOptions( const std::vector<Ri
|
||||
{
|
||||
setTimeStepToApply( *m_uniqueTimeSteps.begin() );
|
||||
}
|
||||
|
||||
if ( m_uniqueWbsSmoothing.size() == 1u )
|
||||
{
|
||||
setWbsSmoothingToApply( *m_uniqueWbsSmoothing.begin() == true ? caf::Tristate::State::True
|
||||
: caf::Tristate::State::False );
|
||||
}
|
||||
|
||||
if ( m_uniqueWbsSmoothingThreshold.size() == 1u )
|
||||
{
|
||||
setWbsSmoothingThreshold( *m_uniqueWbsSmoothingThreshold.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -411,6 +492,21 @@ void RimWellLogCurveCommonDataSource::updateCurvesAndTracks( std::vector<RimWell
|
||||
updatedSomething = true;
|
||||
}
|
||||
|
||||
RimWellLogWbsCurve* wbsCurve = dynamic_cast<RimWellLogWbsCurve*>( extractionCurve );
|
||||
if ( wbsCurve )
|
||||
{
|
||||
if ( !wbsSmoothingToApply().isPartiallyTrue() )
|
||||
{
|
||||
wbsCurve->setSmoothCurve( wbsSmoothingToApply().isTrue() );
|
||||
updatedSomething = true;
|
||||
}
|
||||
|
||||
if ( wbsSmoothingThreshold() != 1.0 )
|
||||
{
|
||||
wbsCurve->setSmoothingThreshold( wbsSmoothingThreshold() );
|
||||
updatedSomething = true;
|
||||
}
|
||||
}
|
||||
if ( updatedSomething )
|
||||
{
|
||||
RimWellLogPlot* parentPlot = nullptr;
|
||||
@ -603,6 +699,13 @@ void RimWellLogCurveCommonDataSource::fieldChangedByUi( const caf::PdmFieldHandl
|
||||
m_branchDetection.v() = caf::Tristate::State::True;
|
||||
}
|
||||
}
|
||||
if ( changedField == &m_wbsSmoothing )
|
||||
{
|
||||
if ( m_wbsSmoothing().isPartiallyTrue() )
|
||||
{
|
||||
m_wbsSmoothing.v() = caf::Tristate::State::True;
|
||||
}
|
||||
}
|
||||
|
||||
this->updateCurvesAndTracks();
|
||||
}
|
||||
@ -791,6 +894,13 @@ void RimWellLogCurveCommonDataSource::defineUiOrdering( QString uiConfigName, ca
|
||||
group->add( &m_wellPath );
|
||||
}
|
||||
group->add( &m_timeStep );
|
||||
|
||||
if ( dynamic_cast<RimGeoMechCase*>( m_case() ) )
|
||||
{
|
||||
group->add( &m_wbsSmoothing );
|
||||
group->add( &m_wbsSmoothingThreshold );
|
||||
}
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
@ -830,6 +940,21 @@ void RimWellLogCurveCommonDataSource::defineEditorAttribute( const caf::PdmField
|
||||
myAttr->prevButtonText = "Previous " + modifierText + "PgUp)";
|
||||
}
|
||||
}
|
||||
caf::PdmUiLineEditorAttributeUiDisplayString* uiDisplayStringAttr =
|
||||
dynamic_cast<caf::PdmUiLineEditorAttributeUiDisplayString*>( attribute );
|
||||
if ( uiDisplayStringAttr && wbsSmoothingThreshold() == -1.0 )
|
||||
{
|
||||
QString displayString = "Mixed";
|
||||
|
||||
if ( m_uniqueWbsSmoothingThreshold.size() > 1u )
|
||||
{
|
||||
auto minmax_it = std::minmax_element( m_uniqueWbsSmoothingThreshold.begin(),
|
||||
m_uniqueWbsSmoothingThreshold.end() );
|
||||
displayString += QString( " [%1, %2]" ).arg( *( minmax_it.first ) ).arg( *( minmax_it.second ) );
|
||||
}
|
||||
|
||||
uiDisplayStringAttr->m_displayString = displayString;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -40,6 +40,16 @@ class RimWellLogCurveCommonDataSource : public caf::PdmObject
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
class DoubleComparator
|
||||
{
|
||||
public:
|
||||
DoubleComparator( double eps = 1.0e-6 );
|
||||
bool operator()( const double& lhs, const double& rhs ) const;
|
||||
|
||||
private:
|
||||
double m_eps;
|
||||
};
|
||||
|
||||
RimWellLogCurveCommonDataSource();
|
||||
|
||||
RimCase* caseToApply() const;
|
||||
@ -52,6 +62,10 @@ public:
|
||||
void setBranchIndexToApply( int val );
|
||||
caf::Tristate branchDetectionToApply() const;
|
||||
void setBranchDetectionToApply( caf::Tristate::State val );
|
||||
caf::Tristate wbsSmoothingToApply() const;
|
||||
void setWbsSmoothingToApply( caf::Tristate::State val );
|
||||
double wbsSmoothingThreshold() const;
|
||||
void setWbsSmoothingThreshold( double smoothingThreshold );
|
||||
|
||||
QString simWellNameToApply() const;
|
||||
void setSimWellNameToApply( const QString& val );
|
||||
@ -93,12 +107,16 @@ private:
|
||||
caf::PdmField<int> m_branchIndex;
|
||||
caf::PdmField<caf::Tristate> m_branchDetection;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
caf::PdmField<caf::Tristate> m_wbsSmoothing;
|
||||
caf::PdmField<double> m_wbsSmoothingThreshold;
|
||||
|
||||
std::set<RimCase*> m_uniqueCases;
|
||||
std::set<int> m_uniqueTrajectoryTypes;
|
||||
std::set<RimWellPath*> m_uniqueWellPaths;
|
||||
std::set<QString> m_uniqueWellNames;
|
||||
std::set<int> m_uniqueTimeSteps;
|
||||
std::set<bool> m_uniqueBranchDetection;
|
||||
std::set<int> m_uniqueBranchIndices;
|
||||
std::set<RimCase*> m_uniqueCases;
|
||||
std::set<int> m_uniqueTrajectoryTypes;
|
||||
std::set<RimWellPath*> m_uniqueWellPaths;
|
||||
std::set<QString> m_uniqueWellNames;
|
||||
std::set<int> m_uniqueTimeSteps;
|
||||
std::set<bool> m_uniqueBranchDetection;
|
||||
std::set<int> m_uniqueBranchIndices;
|
||||
std::set<bool> m_uniqueWbsSmoothing;
|
||||
std::set<double, DoubleComparator> m_uniqueWbsSmoothingThreshold;
|
||||
};
|
||||
|
@ -336,7 +336,7 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
if ( isCurveVisible() )
|
||||
{
|
||||
bool isUsingPseudoLength = false;
|
||||
extractData( &isUsingPseudoLength );
|
||||
performDataExtraction( &isUsingPseudoLength );
|
||||
|
||||
RiaDefines::DepthUnitType displayUnit = RiaDefines::UNIT_METER;
|
||||
|
||||
@ -395,7 +395,15 @@ void RimWellLogExtractionCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength )
|
||||
void RimWellLogExtractionCurve::performDataExtraction( bool* isUsingPseudoLength )
|
||||
{
|
||||
extractData( isUsingPseudoLength );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength, bool smoothData, double smoothingThreshold )
|
||||
{
|
||||
CAF_ASSERT( isUsingPseudoLength );
|
||||
|
||||
@ -495,17 +503,21 @@ void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength )
|
||||
|
||||
m_geomResultDefinition->loadResult();
|
||||
geomExtractor->curveData( m_geomResultDefinition->resultAddress(), m_timeStep, &values );
|
||||
if ( smoothData )
|
||||
{
|
||||
geomExtractor->smoothCurveData( m_timeStep, &measuredDepthValues, &tvDepthValues, &values, smoothingThreshold );
|
||||
}
|
||||
}
|
||||
|
||||
if ( values.size() && measuredDepthValues.size() )
|
||||
{
|
||||
if ( !tvDepthValues.size() )
|
||||
{
|
||||
this->setValuesAndMD( values, measuredDepthValues, depthUnit, true );
|
||||
this->setValuesAndMD( values, measuredDepthValues, depthUnit, !smoothData );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setValuesWithTVD( values, measuredDepthValues, tvDepthValues, depthUnit, true );
|
||||
this->setValuesWithTVD( values, measuredDepthValues, tvDepthValues, depthUnit, !smoothData );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -649,7 +661,7 @@ void RimWellLogExtractionCurve::defineUiOrdering( QString uiConfigName, caf::Pdm
|
||||
{
|
||||
RimPlotCurve::updateOptionSensitivity();
|
||||
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Curve Data" );
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroupWithKeyword( "Curve Data", "CurveData" );
|
||||
|
||||
curveDataGroup->add( &m_case );
|
||||
|
||||
@ -677,7 +689,6 @@ void RimWellLogExtractionCurve::defineUiOrdering( QString uiConfigName, caf::Pdm
|
||||
else if ( geomCase )
|
||||
{
|
||||
curveDataGroup->add( &m_wellPath );
|
||||
m_geomResultDefinition->uiOrdering( uiConfigName, *curveDataGroup );
|
||||
}
|
||||
|
||||
if ( ( eclipseCase && m_eclipseResultDefinition->hasDynamicResult() ) || geomCase )
|
||||
|
@ -87,9 +87,10 @@ public:
|
||||
RigGeoMechWellLogExtractor* geomExtractor );
|
||||
|
||||
protected:
|
||||
QString createCurveAutoName() override;
|
||||
void onLoadDataAndUpdate( bool updateParentPlot ) override;
|
||||
void extractData( bool* isUsingPseudoLength );
|
||||
QString createCurveAutoName() override;
|
||||
void onLoadDataAndUpdate( bool updateParentPlot ) override;
|
||||
virtual void performDataExtraction( bool* isUsingPseudoLength );
|
||||
void extractData( bool* isUsingPseudoLength, bool smoothData = false, double smoothingThreshold = -1.0 );
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
|
86
ApplicationCode/ProjectDataModel/RimWellLogWbsCurve.cpp
Normal file
86
ApplicationCode/ProjectDataModel/RimWellLogWbsCurve.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "RimWellLogWbsCurve.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellLogWbsCurve, "RimWellLogWbsCurve" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogWbsCurve::RimWellLogWbsCurve()
|
||||
{
|
||||
CAF_PDM_InitObject( "Well Bore Stability Curve", "", "", "" );
|
||||
|
||||
CAF_PDM_InitField( &m_smoothCurve, "SmoothCurve", false, "Smooth Curve", "", "", "" );
|
||||
CAF_PDM_InitField( &m_smoothingThreshold, "SmoothingThreshold", 0.002, "Smoothing Threshold", "", "", "" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogWbsCurve::smoothCurve() const
|
||||
{
|
||||
return m_smoothCurve;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellLogWbsCurve::smoothingThreshold() const
|
||||
{
|
||||
return m_smoothingThreshold;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogWbsCurve::setSmoothCurve( bool smooth )
|
||||
{
|
||||
m_smoothCurve = smooth;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogWbsCurve::setSmoothingThreshold( double threshold )
|
||||
{
|
||||
m_smoothingThreshold = threshold;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogWbsCurve::performDataExtraction( bool* isUsingPseudoLength )
|
||||
{
|
||||
extractData( isUsingPseudoLength, m_smoothCurve(), m_smoothingThreshold() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogWbsCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellLogExtractionCurve::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
caf::PdmUiGroup* dataGroup = uiOrdering.findGroup( "CurveData" );
|
||||
dataGroup->add( &m_smoothCurve );
|
||||
dataGroup->add( &m_smoothingThreshold );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogWbsCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
RimWellLogExtractionCurve::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
|
||||
if ( changedField == &m_smoothCurve || changedField == &m_smoothingThreshold )
|
||||
{
|
||||
this->loadDataAndUpdate( true );
|
||||
}
|
||||
}
|
49
ApplicationCode/ProjectDataModel/RimWellLogWbsCurve.h
Normal file
49
ApplicationCode/ProjectDataModel/RimWellLogWbsCurve.h
Normal file
@ -0,0 +1,49 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RimWellLogExtractionCurve.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellLogWbsCurve : public RimWellLogExtractionCurve
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimWellLogWbsCurve();
|
||||
|
||||
bool smoothCurve() const;
|
||||
double smoothingThreshold() const;
|
||||
|
||||
void setSmoothCurve( bool smooth );
|
||||
void setSmoothingThreshold( double threshold );
|
||||
|
||||
protected:
|
||||
void performDataExtraction( bool* isUsingPseudoLength ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue ) override;
|
||||
|
||||
protected:
|
||||
caf::PdmField<bool> m_smoothCurve;
|
||||
caf::PdmField<double> m_smoothingThreshold;
|
||||
};
|
@ -33,12 +33,15 @@
|
||||
|
||||
#include "RigWellLogExtractionTools.h"
|
||||
#include "RigWellPath.h"
|
||||
#include "RigWellPathGeometryTools.h"
|
||||
#include "RigWellPathIntersectionTools.h"
|
||||
|
||||
#include "cafTensor3.h"
|
||||
#include "cvfGeometryTools.h"
|
||||
#include "cvfMath.h"
|
||||
|
||||
#include <QPolygonF>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
const double RigGeoMechWellLogExtractor::UNIT_WEIGHT_OF_WATER = 9.81 * 1000.0; // N / m^3
|
||||
@ -55,6 +58,53 @@ RigGeoMechWellLogExtractor::RigGeoMechWellLogExtractor( RigGeoMechCaseData* aCas
|
||||
calculateIntersection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::smoothCurveData( int frameIndex,
|
||||
std::vector<double>* mds,
|
||||
std::vector<double>* tvds,
|
||||
std::vector<double>* values,
|
||||
const double smoothingTreshold )
|
||||
{
|
||||
CVF_ASSERT( mds && tvds && values );
|
||||
|
||||
RigFemPartResultsCollection* resultCollection = m_caseData->femPartResults();
|
||||
|
||||
RigFemResultAddress shAddr( RIG_ELEMENT_NODAL, "ST", "S3" );
|
||||
RigFemResultAddress porBarResAddr( RIG_ELEMENT_NODAL, "POR-Bar", "" );
|
||||
|
||||
const std::vector<float>& unscaledShValues = resultCollection->resultValues( shAddr, 0, frameIndex );
|
||||
const std::vector<float>& porePressures = resultCollection->resultValues( porBarResAddr, 0, frameIndex );
|
||||
|
||||
std::vector<float> interfaceShValues = interpolateInterfaceValues( shAddr, unscaledShValues );
|
||||
std::vector<float> interfacePorePressures = interpolateInterfaceValues( porBarResAddr, porePressures );
|
||||
|
||||
std::vector<double> interfaceShValuesDbl( interfaceShValues.size(), std::numeric_limits<double>::infinity() );
|
||||
std::vector<double> interfacePorePressuresDbl( interfacePorePressures.size(),
|
||||
std::numeric_limits<double>::infinity() );
|
||||
#pragma omp parallel for
|
||||
for ( int64_t i = 0; i < int64_t( m_intersections.size() ); ++i )
|
||||
{
|
||||
cvf::Vec3f centroid = cellCentroid( i );
|
||||
|
||||
double trueVerticalDepth = -centroid.z();
|
||||
|
||||
double effectiveDepthMeters = trueVerticalDepth + m_rkbDiff;
|
||||
double hydroStaticPorePressureBar = pascalToBar( effectiveDepthMeters * UNIT_WEIGHT_OF_WATER );
|
||||
interfaceShValuesDbl[i] = interfaceShValues[i] / hydroStaticPorePressureBar;
|
||||
interfacePorePressuresDbl[i] = interfacePorePressures[i];
|
||||
}
|
||||
|
||||
std::vector<std::vector<double>*> dependentValues = {tvds, &interfaceShValuesDbl, &interfacePorePressuresDbl};
|
||||
|
||||
std::vector<unsigned char> smoothOrFilterSegments = determineFilteringOrSmoothing( interfacePorePressuresDbl );
|
||||
filterShortSegments( mds, values, &smoothOrFilterSegments, dependentValues );
|
||||
filterColinearSegments( mds, values, &smoothOrFilterSegments, dependentValues );
|
||||
|
||||
smoothSegments( mds, tvds, values, interfaceShValuesDbl, smoothOrFilterSegments, smoothingTreshold );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -102,7 +152,7 @@ void RigGeoMechWellLogExtractor::curveData( const RigFemResultAddress& resAddr,
|
||||
for ( size_t intersectionIdx = 0; intersectionIdx < m_intersections.size(); ++intersectionIdx )
|
||||
{
|
||||
( *values )[intersectionIdx] = static_cast<double>(
|
||||
interpolateGridResultValue<float>( convResAddr.resultPosType, resultValues, intersectionIdx, false ) );
|
||||
interpolateGridResultValue<float>( convResAddr.resultPosType, resultValues, intersectionIdx ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,24 +357,12 @@ void RigGeoMechWellLogExtractor::wellPathScaledCurveData( const RigFemResultAddr
|
||||
RigFemResultAddress nativeAddr( RIG_ELEMENT_NODAL, nativeFieldName, nativeCompName );
|
||||
RigFemResultAddress porElementResAddr( RIG_ELEMENT, "POR", "" );
|
||||
|
||||
std::vector<float> unscaledResultValues = resultCollection->resultValues( nativeAddr, 0, frameIndex );
|
||||
std::vector<float> poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr, 0, frameIndex );
|
||||
const std::vector<float>& unscaledResultValues = resultCollection->resultValues( nativeAddr, 0, frameIndex );
|
||||
const std::vector<float>& poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr,
|
||||
0,
|
||||
frameIndex );
|
||||
|
||||
std::vector<float> interpolatedInterfaceValues;
|
||||
interpolatedInterfaceValues.resize( m_intersections.size(), std::numeric_limits<double>::infinity() );
|
||||
|
||||
#pragma omp parallel for
|
||||
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
|
||||
{
|
||||
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
|
||||
RigElementType elmType = femPart->elementType( elmIdx );
|
||||
if ( !( elmType == HEX8 || elmType == HEX8P ) ) continue;
|
||||
|
||||
interpolatedInterfaceValues[intersectionIdx] = interpolateGridResultValue<float>( nativeAddr.resultPosType,
|
||||
unscaledResultValues,
|
||||
intersectionIdx,
|
||||
false );
|
||||
}
|
||||
std::vector<float> interpolatedInterfaceValues = interpolateInterfaceValues( nativeAddr, unscaledResultValues );
|
||||
|
||||
values->resize( m_intersections.size(), 0.0f );
|
||||
|
||||
@ -366,6 +404,11 @@ void RigGeoMechWellLogExtractor::wellPathScaledCurveData( const RigFemResultAddr
|
||||
|
||||
( *values )[intersectionIdx] = static_cast<double>( averageUnscaledValue ) / hydroStaticPorePressureBar;
|
||||
}
|
||||
|
||||
#pragma omp parallel for
|
||||
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -405,27 +448,11 @@ 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> interpolatedInterfacePorePressuresBar;
|
||||
interpolatedInterfacePorePressuresBar.resize( m_intersections.size(), std::numeric_limits<double>::infinity() );
|
||||
std::vector<float> interpolatedInterfacePorePressuresBar = interpolateInterfaceValues<float>( porBarResAddr,
|
||||
porePressures );
|
||||
|
||||
std::vector<caf::Ten3d> interpolatedInterfaceStressBar;
|
||||
interpolatedInterfaceStressBar.resize( m_intersections.size() );
|
||||
#pragma omp parallel for
|
||||
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
|
||||
{
|
||||
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
|
||||
RigElementType elmType = femPart->elementType( elmIdx );
|
||||
if ( !( elmType == HEX8 || elmType == HEX8P ) ) continue;
|
||||
|
||||
interpolatedInterfacePorePressuresBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType,
|
||||
porePressures,
|
||||
intersectionIdx,
|
||||
false );
|
||||
interpolatedInterfaceStressBar[intersectionIdx] = interpolateGridResultValue( stressResAddr.resultPosType,
|
||||
vertexStresses,
|
||||
intersectionIdx,
|
||||
false );
|
||||
}
|
||||
std::vector<caf::Ten3d> interpolatedInterfaceStressBar = interpolateInterfaceValues<caf::Ten3d>( stressResAddr,
|
||||
vertexStresses );
|
||||
|
||||
values->resize( m_intersections.size(), 0.0f );
|
||||
|
||||
@ -591,8 +618,10 @@ std::vector<double> RigGeoMechWellLogExtractor::porePressureIntervals( int frame
|
||||
const RigFemPart* femPart = m_caseData->femParts()->part( 0 );
|
||||
RigFemPartResultsCollection* resultCollection = m_caseData->femPartResults();
|
||||
|
||||
std::vector<float> porePressures = resultCollection->resultValues( porBarResAddr, 0, frameIndex );
|
||||
std::vector<float> poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr, 0, frameIndex );
|
||||
const std::vector<float>& porePressures = resultCollection->resultValues( porBarResAddr, 0, frameIndex );
|
||||
const std::vector<float>& poreElementPressuresPascal = resultCollection->resultValues( porElementResAddr,
|
||||
0,
|
||||
frameIndex );
|
||||
|
||||
std::vector<float> interpolatedInterfacePorePressureBar;
|
||||
interpolatedInterfacePorePressureBar.resize( m_intersections.size(), std::numeric_limits<float>::infinity() );
|
||||
@ -606,8 +635,7 @@ std::vector<double> RigGeoMechWellLogExtractor::porePressureIntervals( int frame
|
||||
|
||||
interpolatedInterfacePorePressureBar[intersectionIdx] = interpolateGridResultValue( porBarResAddr.resultPosType,
|
||||
porePressures,
|
||||
intersectionIdx,
|
||||
false );
|
||||
intersectionIdx );
|
||||
}
|
||||
|
||||
#pragma omp parallel for
|
||||
@ -678,8 +706,7 @@ std::vector<double> RigGeoMechWellLogExtractor::ucsIntervals( int frameIndex )
|
||||
template <typename T>
|
||||
T RigGeoMechWellLogExtractor::interpolateGridResultValue( RigFemResultPosEnum resultPosType,
|
||||
const std::vector<T>& gridResultValues,
|
||||
int64_t intersectionIdx,
|
||||
bool averageNodeElementResults ) const
|
||||
int64_t intersectionIdx ) const
|
||||
{
|
||||
const RigFemPart* femPart = m_caseData->femParts()->part( 0 );
|
||||
const std::vector<cvf::Vec3f>& nodeCoords = femPart->nodes().coordinates;
|
||||
@ -748,38 +775,10 @@ T RigGeoMechWellLogExtractor::interpolateGridResultValue( RigFemResultPosEnum
|
||||
|
||||
std::vector<T> nodeResultValues;
|
||||
nodeResultValues.reserve( 4 );
|
||||
if ( resultPosType == RIG_ELEMENT_NODAL && averageNodeElementResults )
|
||||
for ( size_t i = 0; i < nodeResIdx.size(); ++i )
|
||||
{
|
||||
// Estimate nodal values as the average of the node values from each connected element.
|
||||
for ( size_t i = 0; i < nodeResIdx.size(); ++i )
|
||||
{
|
||||
int nodeIndex = femPart->nodeIdxFromElementNodeResultIdx( nodeResIdx[i] );
|
||||
const std::vector<int>& elements = femPart->elementsUsingNode( nodeIndex );
|
||||
const std::vector<unsigned char>& localIndices = femPart->elementLocalIndicesForNode( nodeIndex );
|
||||
size_t otherGridResultValueIdx = femPart->resultValueIdxFromResultPosType( resultPosType,
|
||||
elements[0],
|
||||
static_cast<int>(
|
||||
localIndices[0] ) );
|
||||
T nodeResultValue = gridResultValues[otherGridResultValueIdx];
|
||||
for ( size_t j = 1; j < elements.size(); ++j )
|
||||
{
|
||||
otherGridResultValueIdx = femPart->resultValueIdxFromResultPosType( resultPosType,
|
||||
elements[j],
|
||||
static_cast<int>( localIndices[j] ) );
|
||||
nodeResultValue = nodeResultValue + gridResultValues[otherGridResultValueIdx];
|
||||
}
|
||||
nodeResultValue = nodeResultValue * ( 1.0 / elements.size() );
|
||||
nodeResultValues.push_back( nodeResultValue );
|
||||
}
|
||||
nodeResultValues.push_back( gridResultValues[nodeResIdx[i]] );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( size_t i = 0; i < nodeResIdx.size(); ++i )
|
||||
{
|
||||
nodeResultValues.push_back( gridResultValues[nodeResIdx[i]] );
|
||||
}
|
||||
}
|
||||
|
||||
T interpolatedValue = cvf::GeometryTools::interpolateQuad<T>( v0,
|
||||
nodeResultValues[0],
|
||||
v1,
|
||||
@ -1070,3 +1069,239 @@ bool RigGeoMechWellLogExtractor::averageIntersectionValuesToSegmentValue( size_t
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
std::vector<T> RigGeoMechWellLogExtractor::interpolateInterfaceValues( RigFemResultAddress nativeAddr,
|
||||
const std::vector<T>& unscaledResultValues ) const
|
||||
{
|
||||
std::vector<T> interpolatedInterfaceValues;
|
||||
initializeResultValues( interpolatedInterfaceValues, m_intersections.size() );
|
||||
|
||||
const RigFemPart* femPart = m_caseData->femParts()->part( 0 );
|
||||
|
||||
#pragma omp parallel for
|
||||
for ( int64_t intersectionIdx = 0; intersectionIdx < (int64_t)m_intersections.size(); ++intersectionIdx )
|
||||
{
|
||||
size_t elmIdx = m_intersectedCellsGlobIdx[intersectionIdx];
|
||||
RigElementType elmType = femPart->elementType( elmIdx );
|
||||
if ( !( elmType == HEX8 || elmType == HEX8P ) ) continue;
|
||||
|
||||
interpolatedInterfaceValues[intersectionIdx] = interpolateGridResultValue<T>( nativeAddr.resultPosType,
|
||||
unscaledResultValues,
|
||||
intersectionIdx );
|
||||
}
|
||||
return interpolatedInterfaceValues;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::initializeResultValues( std::vector<float>& resultValues, size_t resultCount )
|
||||
{
|
||||
resultValues.resize( resultCount, std::numeric_limits<float>::infinity() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::initializeResultValues( std::vector<caf::Ten3d>& resultValues, size_t resultCount )
|
||||
{
|
||||
resultValues.resize( resultCount );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::filterShortSegments( std::vector<double>* xValues,
|
||||
std::vector<double>* yValues,
|
||||
std::vector<unsigned char>* filterSegments,
|
||||
std::vector<std::vector<double>*>& vectorOfDependentValues )
|
||||
{
|
||||
std::vector<double> simplerXValues;
|
||||
std::vector<double> simplerYValues;
|
||||
std::vector<unsigned char> simpledFilterSegments;
|
||||
std::vector<std::vector<double>> simplerDependentValues( vectorOfDependentValues.size() );
|
||||
|
||||
simplerXValues.push_back( xValues->front() );
|
||||
simplerYValues.push_back( yValues->front() );
|
||||
simpledFilterSegments.push_back( filterSegments->front() );
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
simplerDependentValues[n].push_back( vectorOfDependentValues[n]->front() );
|
||||
}
|
||||
for ( int64_t i = 1; i < int64_t( xValues->size() - 1 ); ++i )
|
||||
{
|
||||
cvf::Vec2d vecIn( ( ( *xValues )[i] - simplerXValues.back() ) / std::max( 1.0, simplerXValues.back() ),
|
||||
( ( *yValues )[i] - simplerYValues.back() ) / std::max( 1.0, simplerYValues.back() ) );
|
||||
if ( ( *filterSegments )[i] == 0u || vecIn.length() > 1.0e-3 )
|
||||
{
|
||||
simplerXValues.push_back( ( *xValues )[i] );
|
||||
simplerYValues.push_back( ( *yValues )[i] );
|
||||
simpledFilterSegments.push_back( ( *filterSegments )[i] );
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
simplerDependentValues[n].push_back( ( *vectorOfDependentValues[n] )[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
simplerXValues.push_back( xValues->back() );
|
||||
simplerYValues.push_back( yValues->back() );
|
||||
simpledFilterSegments.push_back( filterSegments->back() );
|
||||
for ( size_t i = 0; i < vectorOfDependentValues.size(); ++i )
|
||||
{
|
||||
simplerDependentValues[i].push_back( vectorOfDependentValues[i]->back() );
|
||||
}
|
||||
|
||||
xValues->swap( simplerXValues );
|
||||
yValues->swap( simplerYValues );
|
||||
filterSegments->swap( simpledFilterSegments );
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
vectorOfDependentValues[n]->swap( simplerDependentValues[n] );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::filterColinearSegments( std::vector<double>* xValues,
|
||||
std::vector<double>* yValues,
|
||||
std::vector<unsigned char>* filterSegments,
|
||||
std::vector<std::vector<double>*>& vectorOfDependentValues )
|
||||
{
|
||||
std::vector<double> simplerXValues;
|
||||
std::vector<double> simplerYValues;
|
||||
std::vector<unsigned char> simpledFilterSegments;
|
||||
std::vector<std::vector<double>> simplerDependentValues( vectorOfDependentValues.size() );
|
||||
|
||||
simplerXValues.push_back( xValues->front() );
|
||||
simplerYValues.push_back( yValues->front() );
|
||||
simpledFilterSegments.push_back( filterSegments->front() );
|
||||
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
simplerDependentValues[n].push_back( vectorOfDependentValues[n]->front() );
|
||||
}
|
||||
for ( int64_t i = 1; i < int64_t( xValues->size() - 1 ); ++i )
|
||||
{
|
||||
cvf::Vec2d vecIn( ( ( *xValues )[i] - simplerXValues.back() ) / std::max( 1.0, simplerXValues.back() ),
|
||||
( ( *yValues )[i] - simplerYValues.back() ) / std::max( 1.0, simplerYValues.back() ) );
|
||||
cvf::Vec2d vecOut( ( ( *xValues )[i + 1] - ( *xValues )[i] ) / std::max( 1.0, ( *xValues )[i] ),
|
||||
( ( *yValues )[i + 1] - ( *yValues )[i] ) / std::max( 1.0, ( *yValues )[i] ) );
|
||||
vecIn.normalize();
|
||||
vecOut.normalize();
|
||||
double dotProduct = std::abs( vecIn * vecOut );
|
||||
|
||||
if ( ( *filterSegments )[i] == 0u || std::fabs( 1.0 - dotProduct ) > 1.0e-3 )
|
||||
{
|
||||
simplerXValues.push_back( ( *xValues )[i] );
|
||||
simplerYValues.push_back( ( *yValues )[i] );
|
||||
simpledFilterSegments.push_back( ( *filterSegments )[i] );
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
simplerDependentValues[n].push_back( ( *vectorOfDependentValues[n] )[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
simplerXValues.push_back( xValues->back() );
|
||||
simplerYValues.push_back( yValues->back() );
|
||||
simpledFilterSegments.push_back( filterSegments->back() );
|
||||
|
||||
for ( size_t i = 0; i < vectorOfDependentValues.size(); ++i )
|
||||
{
|
||||
simplerDependentValues[i].push_back( vectorOfDependentValues[i]->back() );
|
||||
}
|
||||
|
||||
xValues->swap( simplerXValues );
|
||||
yValues->swap( simplerYValues );
|
||||
filterSegments->swap( simpledFilterSegments );
|
||||
for ( size_t n = 0; n < vectorOfDependentValues.size(); ++n )
|
||||
{
|
||||
vectorOfDependentValues[n]->swap( simplerDependentValues[n] );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigGeoMechWellLogExtractor::smoothSegments( std::vector<double>* mds,
|
||||
std::vector<double>* tvds,
|
||||
std::vector<double>* values,
|
||||
const std::vector<double>& interfaceShValues,
|
||||
const std::vector<unsigned char>& smoothSegments,
|
||||
const double smoothingThreshold )
|
||||
{
|
||||
const double eps = 1.0e-6;
|
||||
|
||||
double maxOriginalMd = ( *mds )[0];
|
||||
double maxOriginalTvd = ( !tvds->empty() ) ? ( *tvds )[0] : 0.0;
|
||||
for ( int64_t i = 1; i < int64_t( mds->size() - 1 ); ++i )
|
||||
{
|
||||
double originalMD = ( *mds )[i];
|
||||
double originalTVD = ( !tvds->empty() ) ? ( *tvds )[i] : 0.0;
|
||||
|
||||
bool smoothSegment = smoothSegments[i] != 0u;
|
||||
|
||||
double diffMd = std::fabs( ( *mds )[i + 1] - ( *mds )[i] ) / std::max( eps, ( *mds )[i] );
|
||||
double diffSh = std::fabs( interfaceShValues[i + 1] - interfaceShValues[i] ) /
|
||||
std::max( eps, interfaceShValues[i] );
|
||||
|
||||
bool leapSh = diffSh > smoothingThreshold && diffMd < eps;
|
||||
if ( smoothSegment )
|
||||
{
|
||||
if ( leapSh )
|
||||
{
|
||||
// Update depth of current
|
||||
( *mds )[i] = 0.5 * ( ( *mds )[i] + maxOriginalMd );
|
||||
|
||||
if ( !tvds->empty() )
|
||||
{
|
||||
( *tvds )[i] = 0.5 * ( ( *tvds )[i] + maxOriginalTvd );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update depth of current
|
||||
( *mds )[i] = ( *mds )[i - 1];
|
||||
|
||||
if ( !tvds->empty() )
|
||||
{
|
||||
( *tvds )[i] = ( *tvds )[i - 1];
|
||||
}
|
||||
}
|
||||
double diffMd_m1 = std::fabs( ( *mds )[i] - ( *mds )[i - 1] );
|
||||
if ( diffMd_m1 < ( *mds )[i] * eps && ( *values )[i - 1] != std::numeric_limits<double>::infinity() )
|
||||
{
|
||||
( *values )[i] = ( *values )[i - 1];
|
||||
}
|
||||
}
|
||||
if ( leapSh )
|
||||
{
|
||||
maxOriginalMd = std::max( maxOriginalMd, originalMD );
|
||||
maxOriginalTvd = std::max( maxOriginalTvd, originalTVD );
|
||||
}
|
||||
}
|
||||
( *values )[0] = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Note that this is unsigned char because std::vector<bool> is not thread safe
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<unsigned char>
|
||||
RigGeoMechWellLogExtractor::determineFilteringOrSmoothing( const std::vector<double>& porePressures )
|
||||
{
|
||||
std::vector<unsigned char> smoothOrFilterSegments( porePressures.size(), false );
|
||||
#pragma omp parallel for
|
||||
for ( int64_t i = 1; i < int64_t( porePressures.size() - 1 ); ++i )
|
||||
{
|
||||
bool validPP_im1 = porePressures[i - 1] >= 0.0 && porePressures[i - 1] != std::numeric_limits<double>::infinity();
|
||||
bool validPP_i = porePressures[i] >= 0.0 && porePressures[i] != std::numeric_limits<double>::infinity();
|
||||
bool validPP_ip1 = porePressures[i + 1] >= 0.0 && porePressures[i + 1] != std::numeric_limits<double>::infinity();
|
||||
bool anyValidPP = validPP_im1 || validPP_i || validPP_ip1;
|
||||
smoothOrFilterSegments[i] = !anyValidPP;
|
||||
}
|
||||
return smoothOrFilterSegments;
|
||||
}
|
||||
|
@ -64,6 +64,12 @@ public:
|
||||
const RigWellPath* wellpath,
|
||||
const std::string& wellCaseErrorMsgName );
|
||||
|
||||
void smoothCurveData( int frameIndex,
|
||||
std::vector<double>* mds,
|
||||
std::vector<double>* tvds,
|
||||
std::vector<double>* values,
|
||||
const double smoothingTreshold );
|
||||
|
||||
void curveData( const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values );
|
||||
const RigGeoMechCaseData* caseData();
|
||||
void setRkbDiff( double rkbDiff );
|
||||
@ -106,14 +112,12 @@ private:
|
||||
|
||||
void wellPathAngles( const RigFemResultAddress& resAddr, std::vector<double>* values );
|
||||
void wellPathScaledCurveData( const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values );
|
||||
|
||||
void wellBoreWallCurveData( const RigFemResultAddress& resAddr, int frameIndex, std::vector<double>* values );
|
||||
|
||||
template <typename T>
|
||||
T interpolateGridResultValue( RigFemResultPosEnum resultPosType,
|
||||
const std::vector<T>& gridResultValues,
|
||||
int64_t intersectionIdx,
|
||||
bool averageNodeElementResults ) const;
|
||||
int64_t intersectionIdx ) const;
|
||||
size_t gridResultIndexFace( size_t elementIdx, cvf::StructGridInterface::FaceType cellFace, int faceLocalNodeIdx ) const;
|
||||
void calculateIntersection();
|
||||
std::vector<size_t> findCloseCells( const cvf::BoundingBox& bb );
|
||||
@ -135,6 +139,30 @@ private:
|
||||
T* averagedSegmentValue ) const;
|
||||
static double pascalToBar( double pascalValue );
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> interpolateInterfaceValues( RigFemResultAddress nativeAddr,
|
||||
const std::vector<T>& unscaledResultValues ) const;
|
||||
|
||||
static void initializeResultValues( std::vector<float>& resultValues, size_t resultCount );
|
||||
static void initializeResultValues( std::vector<caf::Ten3d>& resultValues, size_t resultCount );
|
||||
|
||||
void filterShortSegments( std::vector<double>* xValues,
|
||||
std::vector<double>* yValues,
|
||||
std::vector<unsigned char>* filterSegments,
|
||||
std::vector<std::vector<double>*>& vectorOfDependentValues );
|
||||
void filterColinearSegments( std::vector<double>* xValues,
|
||||
std::vector<double>* yValues,
|
||||
std::vector<unsigned char>* filterSegments,
|
||||
std::vector<std::vector<double>*>& vectorOfDependentValues );
|
||||
void smoothSegments( std::vector<double>* mds,
|
||||
std::vector<double>* tvds,
|
||||
std::vector<double>* values,
|
||||
const std::vector<double>& interfaceShValues,
|
||||
const std::vector<unsigned char>& smoothSegments,
|
||||
const double smoothingThreshold );
|
||||
|
||||
std::vector<unsigned char> determineFilteringOrSmoothing( const std::vector<double>& porePressures );
|
||||
|
||||
private:
|
||||
cvf::ref<RigGeoMechCaseData> m_caseData;
|
||||
double m_rkbDiff;
|
||||
|
Loading…
Reference in New Issue
Block a user