Add topology curves and show in additional track

* Add topology curves and default plot
* Improve visual appearance
* Update sub module opm-common
* Add support for INCLUDE keyword to allow parsing of include files recursively
* Search for *.DATA with fallback to *.SCH to automatically import WESEGLINK data
* Find annulus branch based on MD diff on segment start
* Stop growing device branch if segment starts at a lower MD than previous
This commit is contained in:
Magne Sjaastad 2022-10-07 12:37:23 +02:00 committed by GitHub
parent f155da0179
commit 6d5e303361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 893 additions and 149 deletions

View File

@ -499,6 +499,7 @@ RimWellLogCurve* RicWellLogTools::addSummaryRftCurve( RimWellLogTrack* plotTrack
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RimWellLogCurve* RicWellLogTools::addSummaryRftSegmentCurve( RimWellLogTrack* plotTrack, RimWellLogCurve* RicWellLogTools::addSummaryRftSegmentCurve( RimWellLogTrack* plotTrack,
const QString& resultName, const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType, RiaDefines::RftBranchType branchType,
RimSummaryCase* rimCase ) RimSummaryCase* rimCase )
{ {
@ -507,10 +508,6 @@ RimWellLogCurve* RicWellLogTools::addSummaryRftSegmentCurve( RimWellLogTrack*
curve->setSummaryCase( rimCase ); curve->setSummaryCase( rimCase );
auto rftReader = rimCase->rftReader(); auto rftReader = rimCase->rftReader();
QString wellName;
auto wellNames = rftReader->wellNames();
if ( !wellNames.empty() ) wellName = *wellNames.begin();
QDateTime dateTime; QDateTime dateTime;
auto timeSteps = rftReader->availableTimeSteps( wellName ); auto timeSteps = rftReader->availableTimeSteps( wellName );
@ -519,6 +516,10 @@ RimWellLogCurve* RicWellLogTools::addSummaryRftSegmentCurve( RimWellLogTrack*
RifEclipseRftAddress adr = RifEclipseRftAddress adr =
RifEclipseRftAddress::createBranchSegmentAddress( wellName, dateTime, resultName, 1, branchType ); RifEclipseRftAddress::createBranchSegmentAddress( wellName, dateTime, resultName, 1, branchType );
curve->setRftAddress( adr ); curve->setRftAddress( adr );
curve->enableColorFromResultName( true );
curve->assignColorFromResultName( resultName );
curve->setLineThickness( 4 );
curve->setFillStyle( Qt::SolidPattern );
curve->setInterpolation( RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_STEP_LEFT ); curve->setInterpolation( RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_STEP_LEFT );

View File

@ -80,6 +80,7 @@ public:
static RimWellLogCurve* addSummaryRftCurve( RimWellLogTrack* plotTrack, RimSummaryCase* rimCase ); static RimWellLogCurve* addSummaryRftCurve( RimWellLogTrack* plotTrack, RimSummaryCase* rimCase );
static RimWellLogCurve* addSummaryRftSegmentCurve( RimWellLogTrack* plotTrack, static RimWellLogCurve* addSummaryRftSegmentCurve( RimWellLogTrack* plotTrack,
const QString& resultName, const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType, RiaDefines::RftBranchType branchType,
RimSummaryCase* rimCase ); RimSummaryCase* rimCase );

View File

@ -25,9 +25,13 @@
#include "RiaApplication.h" #include "RiaApplication.h"
#include "RiaRftDefines.h" #include "RiaRftDefines.h"
#include "RifReaderEclipseRft.h"
#include "RifReaderOpmRft.h"
#include "RigWellLogCurveData.h" #include "RigWellLogCurveData.h"
#include "RimRftCase.h" #include "RimRftCase.h"
#include "RimRftTopologyCurve.h"
#include "RimSummaryCase.h" #include "RimSummaryCase.h"
#include "RimWellLogExtractionCurve.h" #include "RimWellLogExtractionCurve.h"
#include "RimWellLogPlot.h" #include "RimWellLogPlot.h"
@ -63,26 +67,32 @@ void RicNewRftSegmentWellLogPlotFeature::onActionTriggered( bool isChecked )
RimSummaryCase* summaryCase = nullptr; RimSummaryCase* summaryCase = nullptr;
rftCase->firstAncestorOfType( summaryCase ); rftCase->firstAncestorOfType( summaryCase );
if ( !summaryCase ) return;
auto plot = RicNewWellLogPlotFeatureImpl::createHorizontalWellLogPlot(); auto plot = RicNewWellLogPlotFeatureImpl::createHorizontalWellLogPlot();
QString wellName = "Unknown";
auto rftReader = summaryCase->rftReader();
if ( rftReader )
{
auto wellNames = rftReader->wellNames();
if ( !wellNames.empty() ) wellName = *wellNames.begin();
}
QString resultName = "SEGGRAT"; QString resultName = "SEGGRAT";
{ std::vector<RiaDefines::RftBranchType> branchTypes{ RiaDefines::RftBranchType::RFT_ANNULUS,
auto branchType = RiaDefines::RftBranchType::RFT_TUBING; RiaDefines::RftBranchType::RFT_DEVICE,
RiaDefines::RftBranchType::RFT_TUBING };
appendTrackAndCurveForBranchType( plot, resultName, branchType, summaryCase ); for ( auto branchType : branchTypes )
}
{ {
auto branchType = RiaDefines::RftBranchType::RFT_DEVICE; appendTrackAndCurveForBranchType( plot, resultName, wellName, branchType, summaryCase );
appendTrackAndCurveForBranchType( plot, resultName, branchType, summaryCase );
} }
{
auto branchType = RiaDefines::RftBranchType::RFT_ANNULUS;
appendTrackAndCurveForBranchType( plot, resultName, branchType, summaryCase ); appendTopologyTrack( plot, wellName, summaryCase );
} plot->loadDataAndUpdate();
RiuPlotMainWindowTools::onObjectAppended( plot ); RiuPlotMainWindowTools::onObjectAppended( plot );
} }
@ -92,6 +102,7 @@ void RicNewRftSegmentWellLogPlotFeature::onActionTriggered( bool isChecked )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RicNewRftSegmentWellLogPlotFeature::appendTrackAndCurveForBranchType( RimWellLogPlot* plot, void RicNewRftSegmentWellLogPlotFeature::appendTrackAndCurveForBranchType( RimWellLogPlot* plot,
const QString& resultName, const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType, RiaDefines::RftBranchType branchType,
RimSummaryCase* summaryCase ) RimSummaryCase* summaryCase )
{ {
@ -101,13 +112,50 @@ void RicNewRftSegmentWellLogPlotFeature::appendTrackAndCurveForBranchType( RimWe
plot->loadDataAndUpdate(); plot->loadDataAndUpdate();
auto curve = RicWellLogTools::addSummaryRftSegmentCurve( plotTrack, resultName, branchType, summaryCase ); auto curve = RicWellLogTools::addSummaryRftSegmentCurve( plotTrack, resultName, wellName, branchType, summaryCase );
curve->loadDataAndUpdate( true ); curve->loadDataAndUpdate( true );
curve->updateAllRequiredEditors(); curve->updateAllRequiredEditors();
RiuPlotMainWindowTools::setExpanded( curve ); RiuPlotMainWindowTools::setExpanded( curve );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewRftSegmentWellLogPlotFeature::appendTopologyTrack( RimWellLogPlot* plot,
const QString& wellName,
RimSummaryCase* summaryCase )
{
QDateTime dateTime;
int branchIndex = 1;
auto rftReader = dynamic_cast<RifReaderOpmRft*>( summaryCase->rftReader() );
if ( rftReader )
{
auto timeSteps = rftReader->availableTimeSteps( wellName );
if ( !timeSteps.empty() ) dateTime = *timeSteps.rbegin();
}
auto track = new RimWellLogTrack();
track->setDescription( "Topology" );
plot->addPlot( track );
std::vector<RiaDefines::RftBranchType> branchTypes{ RiaDefines::RftBranchType::RFT_TUBING,
RiaDefines::RftBranchType::RFT_DEVICE,
RiaDefines::RftBranchType::RFT_ANNULUS };
for ( auto branchType : branchTypes )
{
auto curve = new RimRftTopologyCurve;
curve->setDataSource( summaryCase, dateTime, wellName, branchIndex, branchType );
curve->applyDefaultAppearance();
track->addCurve( curve );
}
track->updateAllRequiredEditors();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -40,6 +40,9 @@ private:
void appendTrackAndCurveForBranchType( RimWellLogPlot* plot, void appendTrackAndCurveForBranchType( RimWellLogPlot* plot,
const QString& resultName, const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType, RiaDefines::RftBranchType branchType,
RimSummaryCase* summaryCase ); RimSummaryCase* summaryCase );
void appendTopologyTrack( RimWellLogPlot* plot, const QString& wellName, RimSummaryCase* summaryCase );
}; };

View File

@ -89,6 +89,7 @@ RimWellLogPlot* RicNewWellLogPlotFeatureImpl::createHorizontalWellLogPlot()
{ {
auto plot = createWellLogPlot(); auto plot = createWellLogPlot();
plot->setDepthOrientation( RimDepthTrackPlot::DepthOrientation::HORIZONTAL ); plot->setDepthOrientation( RimDepthTrackPlot::DepthOrientation::HORIZONTAL );
plot->setLegendsHorizontal( true );
return plot; return plot;
} }

View File

@ -81,7 +81,8 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
{ {
auto data = segment.topology(); auto data = segment.topology();
auto indices = segment.indicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() ); auto indices =
segment.segmentIndicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() );
for ( const auto& i : indices ) for ( const auto& i : indices )
{ {
CAF_ASSERT( i < data.size() ); CAF_ASSERT( i < data.size() );
@ -145,8 +146,8 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
} }
else else
{ {
auto indices = auto indices = segment.segmentIndicesForBranchIndex( rftAddress.segmentBranchIndex(),
segment.indicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() ); rftAddress.segmentBranchType() );
for ( const auto& i : indices ) for ( const auto& i : indices )
{ {
CAF_ASSERT( i < data.size() ); CAF_ASSERT( i < data.size() );
@ -289,7 +290,9 @@ void RifReaderOpmRft::cellIndices( const RifEclipseRftAddress& rftAddress, std::
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString& wellName, const QDateTime& timeStep ) std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString& wellName,
const QDateTime& timeStep,
RiaDefines::RftBranchType branchType )
{ {
int y = timeStep.date().year(); int y = timeStep.date().year();
int m = timeStep.date().month(); int m = timeStep.date().month();
@ -299,7 +302,25 @@ std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString&
if ( m_rftWellDateSegments.count( key ) > 0 ) if ( m_rftWellDateSegments.count( key ) > 0 )
{ {
auto segment = m_rftWellDateSegments[key]; auto segment = m_rftWellDateSegments[key];
return segment.branchIdsAndOneBasedBranchIndices(); return segment.branchIdsAndOneBasedBranchIndices( branchType );
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifRftSegment RifReaderOpmRft::segmentForWell( const QString& wellName, const QDateTime& timeStep )
{
int y = timeStep.date().year();
int m = timeStep.date().month();
int d = timeStep.date().day();
auto key = std::make_pair( wellName.toStdString(), RftDate{ y, m, d } );
if ( m_rftWellDateSegments.count( key ) > 0 )
{
return m_rftWellDateSegments[key];
} }
return {}; return {};
@ -310,15 +331,26 @@ std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString&
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::readWseglink( const std::string& filePath ) void RifReaderOpmRft::readWseglink( const std::string& filePath )
{ {
m_wseglink = RiaOpmParserTools::extractWseglink( filePath ); if ( filePath.empty() ) return;
QString text = QString( "Scanning for WSEGLINK data in %1\n" ).arg( QString::fromStdString( filePath ) );
m_wseglink = RiaOpmParserTools::extractWseglink( filePath );
if ( !m_wseglink.empty() ) if ( !m_wseglink.empty() )
{ {
QString text = QString( "Imported segment data from %1\n" ).arg( QString::fromStdString( filePath ) ); text += "Imported WSEGLINK data from well(s):\n";
text += QString( "Number of wells: %1\n" ).arg( m_wseglink.size() );
RiaLogging::info( text ); for ( auto [wellName, links] : m_wseglink )
{
text += " " + QString::fromStdString( wellName ) + "\n";
}
} }
else
{
text += QString( " No WSEGLINK data found." );
}
RiaLogging::info( text );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -579,102 +611,25 @@ void RifReaderOpmRft::buildSegmentBranchTypes( const RftSegmentKey& segmentKey )
values( resultName, &seglenenValues ); values( resultName, &seglenenValues );
} }
int oneBasedBranchIndex = 1;
if ( !seglenenValues.empty() && !seglenstValues.empty() ) if ( !seglenenValues.empty() && !seglenstValues.empty() )
{ {
// Find tubing and annulus branch types identifyTubingCandidateBranches( segmentRef, wellName, seglenstValues, seglenenValues );
identifyAnnulusBranches( segmentRef, seglenstValues );
auto branchIds = segmentRef.branchIds(); // The tubing branches are given increasing branch indices. If a tubing branch is categorized as an annulus
for ( auto id : branchIds ) // branch, the index values must be reassigned. Each triplet of tubing/device/annulus has a unique branch index.
{ reassignBranchIndices( segmentRef );
double minimumMD = std::numeric_limits<double>::max();
double maximumMD = std::numeric_limits<double>::min();
std::vector<int> segmentNumbers; identifyDeviceBranches( segmentRef, seglenstValues );
auto indices = segmentRef.indicesForBranchNumber( id );
for ( auto i : indices )
{
minimumMD = std::min( minimumMD, seglenstValues[i] );
maximumMD = std::max( maximumMD, seglenenValues[i] );
segmentNumbers.push_back( segmentRef.topology()[i].segNo() );
}
double length = maximumMD - minimumMD;
segmentRef.setBranchLength( id, length );
RiaDefines::RftBranchType branchType = RiaDefines::RftBranchType::RFT_UNKNOWN;
bool hasFoundAnnulusBranch = false;
auto annulusSegments = annulusSegmentsForWell( wellName );
std::vector<int> matchingSegments;
std::set_intersection( segmentNumbers.begin(),
segmentNumbers.end(),
annulusSegments.begin(),
annulusSegments.end(),
std::inserter( matchingSegments, matchingSegments.end() ) );
if ( !matchingSegments.empty() )
{
{
branchType = RiaDefines::RftBranchType::RFT_ANNULUS;
// NOTE: Assign branch index after device branch is detected
hasFoundAnnulusBranch = true;
}
}
if ( !hasFoundAnnulusBranch )
{
const double tubingThreshold = 1.0;
if ( length > tubingThreshold )
{
branchType = RiaDefines::RftBranchType::RFT_TUBING;
segmentRef.setOneBasedBranchIndex( id, oneBasedBranchIndex++ );
}
}
segmentRef.setBranchType( id, branchType );
}
auto tubingBranchIds = segmentRef.tubingBranchIds();
for ( auto& segment : segmentRef.topology() )
{
auto segmentBranchId = segment.segBrno();
auto it = std::find( tubingBranchIds.begin(), tubingBranchIds.end(), segmentBranchId );
if ( it == tubingBranchIds.end() )
{
auto tubingSegmentNumber = segment.segNext();
auto tubingSegmentData = segmentRef.segmentData( tubingSegmentNumber );
if ( tubingSegmentData != nullptr )
{
auto it = std::find( tubingBranchIds.begin(), tubingBranchIds.end(), tubingSegmentData->segBrno() );
if ( it != tubingBranchIds.end() )
{
// Find all connected segments that is not assigned a branch type, and mark as device
// layer
auto tubingBranchIndex = segmentRef.oneBasedBranchIndexForBranchId( tubingSegmentData->segBrno() );
segmentRef.createDeviceBranch( segment.segNo(), tubingBranchIndex );
}
}
}
}
// Assign branch index to annulus branches // Assign branch index to annulus branches
auto branchIds = segmentRef.branchIds();
for ( auto branchId : branchIds ) for ( auto branchId : branchIds )
{ {
auto branchType = segmentRef.branchType( branchId ); auto branchType = segmentRef.branchType( branchId );
if ( branchType == RiaDefines::RftBranchType::RFT_ANNULUS ) if ( branchType == RiaDefines::RftBranchType::RFT_ANNULUS )
{ {
auto segmentIndices = segmentRef.indicesForBranchNumber( branchId ); auto segmentIndices = segmentRef.segmentIndicesForBranchNumber( branchId );
if ( segmentIndices.empty() ) continue; if ( segmentIndices.empty() ) continue;
auto firstSegmentIndex = segmentIndices.front(); auto firstSegmentIndex = segmentIndices.front();
@ -695,6 +650,191 @@ void RifReaderOpmRft::buildSegmentBranchTypes( const RftSegmentKey& segmentKey )
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::identifyTubingCandidateBranches( RifRftSegment& segmentRef,
const std::string& wellName,
const std::vector<double>& seglenstValues,
const std::vector<double>& seglenenValues )
{
int oneBasedBranchIndex = 1;
auto branchIds = segmentRef.branchIds();
for ( auto id : branchIds )
{
double minimumMD = std::numeric_limits<double>::max();
double maximumMD = std::numeric_limits<double>::min();
std::vector<int> segmentNumbers;
auto indices = segmentRef.segmentIndicesForBranchNumber( id );
for ( auto i : indices )
{
minimumMD = std::min( minimumMD, seglenstValues[i] );
maximumMD = std::max( maximumMD, seglenenValues[i] );
segmentNumbers.push_back( segmentRef.topology()[i].segNo() );
}
double length = maximumMD - minimumMD;
segmentRef.setBranchLength( id, length );
RiaDefines::RftBranchType branchType = RiaDefines::RftBranchType::RFT_UNKNOWN;
bool hasFoundAnnulusBranch = false;
// If WESEGLINK is imported, get annulus segments for well
auto annulusSegments = annulusSegmentsForWell( wellName );
std::vector<int> matchingSegments;
std::set_intersection( segmentNumbers.begin(),
segmentNumbers.end(),
annulusSegments.begin(),
annulusSegments.end(),
std::inserter( matchingSegments, matchingSegments.end() ) );
if ( !matchingSegments.empty() )
{
{
branchType = RiaDefines::RftBranchType::RFT_ANNULUS;
// NOTE: Assign branch index after device branch is detected
hasFoundAnnulusBranch = true;
}
}
if ( !hasFoundAnnulusBranch )
{
const double tubingThreshold = 1.0;
if ( length > tubingThreshold )
{
branchType = RiaDefines::RftBranchType::RFT_TUBING;
segmentRef.setOneBasedBranchIndex( id, oneBasedBranchIndex++ );
}
}
segmentRef.setBranchType( id, branchType );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::identifyAnnulusBranches( RifRftSegment& segmentRef, const std::vector<double>& seglenstValues )
{
// If no WESEGLINK data is present, compare the location of the last N segments of two tubing branches. If the
// difference is correct, mark candidate branch as annulus branch instead of tubing.
if ( m_wseglink.empty() )
{
auto tubingIds = segmentRef.tubingBranchIds();
std::map<size_t, std::vector<double>> seglenstForBranch;
for ( auto branchId : tubingIds )
{
std::vector<double> values;
auto indices = segmentRef.segmentIndicesForBranchNumber( branchId );
for ( auto i : indices )
{
values.push_back( seglenstValues[i] );
}
seglenstForBranch[branchId] = values;
}
std::set<size_t> annulusBranchIds;
for ( auto branchId : tubingIds )
{
if ( annulusBranchIds.count( branchId ) ) continue;
for ( auto candidateBranchId : tubingIds )
{
if ( candidateBranchId == branchId ) continue;
if ( annulusBranchIds.count( candidateBranchId ) ) continue;
auto branchValues = seglenstForBranch.at( branchId );
auto candidateValues = seglenstForBranch.at( candidateBranchId );
double lastBranchValue = branchValues.back();
double lastCandidateValue = candidateValues.back();
double diff = lastCandidateValue - lastBranchValue;
const double epsilon = 1e-3;
const double distanceTubingAnnulus = 0.1;
if ( std::fabs( ( std::fabs( diff ) - distanceTubingAnnulus ) ) < epsilon )
{
size_t annulusBranchId = ( diff > 0 ) ? candidateBranchId : branchId;
segmentRef.setBranchType( annulusBranchId, RiaDefines::RftBranchType::RFT_ANNULUS );
annulusBranchIds.insert( annulusBranchId );
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::reassignBranchIndices( RifRftSegment& segmentRef )
{
auto tubingBranchIds = segmentRef.tubingBranchIds();
size_t oneBasedBranchIndex = 1;
std::map<size_t, size_t> newOneBasedBranchIndex;
for ( auto branchId : tubingBranchIds )
{
auto previsousIndex = segmentRef.oneBasedBranchIndexForBranchId( branchId );
newOneBasedBranchIndex[previsousIndex] = oneBasedBranchIndex++;
}
for ( auto branchId : segmentRef.branchIds() )
{
auto branchIndex = segmentRef.oneBasedBranchIndexForBranchId( branchId );
if ( newOneBasedBranchIndex.count( branchIndex ) )
{
segmentRef.setOneBasedBranchIndex( branchId, newOneBasedBranchIndex.at( branchIndex ) );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::identifyDeviceBranches( RifRftSegment& segmentRef, const std::vector<double>& seglenstValues )
{
auto tubingBranchIds = segmentRef.tubingBranchIds();
for ( auto& segment : segmentRef.topology() )
{
auto segmentBranchId = segment.segBrno();
auto it = std::find( tubingBranchIds.begin(), tubingBranchIds.end(), segmentBranchId );
if ( it == tubingBranchIds.end() )
{
auto tubingSegmentNumber = segment.segNext();
auto tubingSegmentData = segmentRef.segmentData( tubingSegmentNumber );
if ( tubingSegmentData != nullptr )
{
auto it = std::find( tubingBranchIds.begin(), tubingBranchIds.end(), tubingSegmentData->segBrno() );
if ( it != tubingBranchIds.end() )
{
// Find all connected segments that is not assigned a branch type, and mark as device layer
auto tubingBranchIndex = segmentRef.oneBasedBranchIndexForBranchId( tubingSegmentData->segBrno() );
segmentRef.createDeviceBranch( segment.segNo(), tubingBranchIndex, seglenstValues );
}
}
}
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -53,7 +53,11 @@ public:
void cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices ) override; void cellIndices( const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices ) override;
std::map<int, int> branchIdsAndOneBasedIndices( const QString& wellName, const QDateTime& timeStep ); std::map<int, int> branchIdsAndOneBasedIndices( const QString& wellName,
const QDateTime& timeStep,
RiaDefines::RftBranchType branchType );
RifRftSegment segmentForWell( const QString& wellName, const QDateTime& timeStep );
private: private:
// Segment data // Segment data
@ -68,6 +72,13 @@ private:
bool isOpen() const; bool isOpen() const;
void importWellNames(); void importWellNames();
void buildSegmentBranchTypes( const RftSegmentKey& segmentKey ); void buildSegmentBranchTypes( const RftSegmentKey& segmentKey );
void identifyTubingCandidateBranches( RifRftSegment& segmentRef,
const std::string& wellName,
const std::vector<double>& seglenstValues,
const std::vector<double>& seglenenValues );
void identifyAnnulusBranches( RifRftSegment& segmentRef, const std::vector<double>& seglenstValues );
void reassignBranchIndices( RifRftSegment& segmentRef );
void identifyDeviceBranches( RifRftSegment& segmentRef, const std::vector<double>& seglenstValues );
std::vector<int> importWellData( const std::string& wellName, const std::string& propertyName, const RftDate& date ) const; std::vector<int> importWellData( const std::string& wellName, const std::string& propertyName, const RftDate& date ) const;

View File

@ -21,6 +21,8 @@
#include <algorithm> #include <algorithm>
#include <unordered_set> #include <unordered_set>
#include "cvfAssert.h"
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// segnxt : Int ID for the next segment /// segnxt : Int ID for the next segment
/// brno : Branch ID number /// brno : Branch ID number
@ -162,9 +164,21 @@ int RifRftSegment::oneBasedBranchIndexForBranchId( int branchId ) const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::map<int, int> RifRftSegment::branchIdsAndOneBasedBranchIndices() const std::map<int, int> RifRftSegment::branchIdsAndOneBasedBranchIndices( RiaDefines::RftBranchType branchType ) const
{ {
return m_oneBasedBranchIndexMap; std::map<int, int> mapForBranchType;
// find all branch ids for the given branch type
for ( const auto& [branchId, branchIndex] : m_oneBasedBranchIndexMap )
{
if ( branchType == RiaDefines::RftBranchType::RFT_UNKNOWN || this->branchType( branchId ) == branchType )
{
mapForBranchType[branchId] = branchIndex;
}
}
return mapForBranchType;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -183,8 +197,21 @@ const RifRftSegmentData* RifRftSegment::segmentData( int segmentNumber ) const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RifRftSegment::createDeviceBranch( int deviceBranchFirstSegmentNumber, int oneBasedBranchIndex ) const RifRftSegmentData* RifRftSegment::segmentDataByIndex( int segmentIndex ) const
{ {
CVF_ASSERT( segmentIndex < m_topology.size() );
return &( m_topology[segmentIndex] );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifRftSegment::createDeviceBranch( int deviceBranchFirstSegmentNumber,
int oneBasedBranchIndex,
const std::vector<double>& seglenstValues )
{
double lastAssignedDeviceBranchDepth = -1.0;
for ( auto& segData : m_topology ) for ( auto& segData : m_topology )
{ {
if ( segData.segNo() < deviceBranchFirstSegmentNumber ) continue; if ( segData.segNo() < deviceBranchFirstSegmentNumber ) continue;
@ -192,6 +219,13 @@ void RifRftSegment::createDeviceBranch( int deviceBranchFirstSegmentNumber, int
auto branchNumber = segData.segBrno(); auto branchNumber = segData.segBrno();
if ( branchType( branchNumber ) != RiaDefines::RftBranchType::RFT_UNKNOWN ) return; if ( branchType( branchNumber ) != RiaDefines::RftBranchType::RFT_UNKNOWN ) return;
auto segmentIndex = segmentIndexFromSegmentNumber( segData.segNo() );
if ( segmentIndex < 0 ) continue;
double candidateSegmentDepth = seglenstValues[segmentIndex];
if ( lastAssignedDeviceBranchDepth > -1.0 && lastAssignedDeviceBranchDepth > candidateSegmentDepth ) return;
lastAssignedDeviceBranchDepth = candidateSegmentDepth;
setOneBasedBranchIndex( segData.segBrno(), oneBasedBranchIndex ); setOneBasedBranchIndex( segData.segBrno(), oneBasedBranchIndex );
setBranchType( segData.segBrno(), RiaDefines::RftBranchType::RFT_DEVICE ); setBranchType( segData.segBrno(), RiaDefines::RftBranchType::RFT_DEVICE );
@ -235,7 +269,7 @@ RiaDefines::RftBranchType RifRftSegment::branchType( int branchId ) const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<size_t> RifRftSegment::indicesForBranchNumber( int branchNumber ) const std::vector<size_t> RifRftSegment::segmentIndicesForBranchNumber( int branchNumber ) const
{ {
std::vector<size_t> v; std::vector<size_t> v;
for ( size_t i = 0; i < m_topology.size(); i++ ) for ( size_t i = 0; i < m_topology.size(); i++ )
@ -253,7 +287,7 @@ std::vector<size_t> RifRftSegment::indicesForBranchNumber( int branchNumber ) co
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<size_t> RifRftSegment::indicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const std::vector<size_t> RifRftSegment::segmentIndicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const
{ {
std::vector<size_t> v; std::vector<size_t> v;
for ( size_t i = 0; i < m_topology.size(); i++ ) for ( size_t i = 0; i < m_topology.size(); i++ )
@ -287,7 +321,7 @@ std::vector<int> RifRftSegment::segmentNumbersForBranchIndex( int
{ {
std::vector<int> v; std::vector<int> v;
auto indices = indicesForBranchIndex( oneBasedBranchIndex, branchType ); auto indices = segmentIndicesForBranchIndex( oneBasedBranchIndex, branchType );
for ( auto index : indices ) for ( auto index : indices )
{ {
v.push_back( m_topology[index].segNo() ); v.push_back( m_topology[index].segNo() );
@ -295,3 +329,33 @@ std::vector<int> RifRftSegment::segmentNumbersForBranchIndex( int
return v; return v;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RifRftSegment::uniqueOneBasedBranchIndices( RiaDefines::RftBranchType branchType ) const
{
std::set<int> indices;
for ( const auto [branchId, branchIndex] : m_oneBasedBranchIndexMap )
{
indices.insert( branchIndex );
}
return indices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifRftSegment::segmentIndexFromSegmentNumber( int segmentNumber ) const
{
for ( size_t i = 0; i < m_topology.size(); i++ )
{
auto segment = m_topology[i];
if ( segment.segNo() == segmentNumber ) return i;
}
return -1;
}

View File

@ -58,11 +58,14 @@ public:
std::vector<int> tubingBranchIds() const; std::vector<int> tubingBranchIds() const;
std::vector<int> branchIds() const; std::vector<int> branchIds() const;
int oneBasedBranchIndexForBranchId( int branchId ) const; int oneBasedBranchIndexForBranchId( int branchId ) const;
std::map<int, int> branchIdsAndOneBasedBranchIndices() const; std::map<int, int> branchIdsAndOneBasedBranchIndices( RiaDefines::RftBranchType branchType ) const;
const RifRftSegmentData* segmentData( int segmentNumber ) const; const RifRftSegmentData* segmentData( int segmentNumber ) const;
const RifRftSegmentData* segmentDataByIndex( int segmentIndex ) const;
void createDeviceBranch( int deviceBranchFirstSegmentNumber, int oneBasedBranchIndex ); void createDeviceBranch( int deviceBranchFirstSegmentNumber,
int oneBasedBranchIndex,
const std::vector<double>& seglenstValues );
void setBranchLength( int branchId, double length ); void setBranchLength( int branchId, double length );
void setBranchType( int branchId, RiaDefines::RftBranchType branchType ); void setBranchType( int branchId, RiaDefines::RftBranchType branchType );
@ -70,11 +73,16 @@ public:
RiaDefines::RftBranchType branchType( int branchId ) const; RiaDefines::RftBranchType branchType( int branchId ) const;
std::vector<size_t> indicesForBranchNumber( int branchNumber ) const; std::vector<size_t> segmentIndicesForBranchNumber( int branchNumber ) const;
std::vector<size_t> indicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const; std::vector<size_t> segmentIndicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const;
std::vector<int> segmentNumbersForBranchIndex( int oneBasedBranchIndex, RiaDefines::RftBranchType branchType ) const; std::vector<int> segmentNumbersForBranchIndex( int oneBasedBranchIndex, RiaDefines::RftBranchType branchType ) const;
std::set<int> uniqueOneBasedBranchIndices( RiaDefines::RftBranchType branchType ) const;
private:
int segmentIndexFromSegmentNumber( int segmentNumber ) const;
private: private:
std::vector<RifRftSegmentData> m_topology; std::vector<RifRftSegmentData> m_topology;
std::vector<Opm::EclIO::EclFile::EclEntry> m_resultNameAndSize; std::vector<Opm::EclIO::EclFile::EclEntry> m_resultNameAndSize;

View File

@ -24,6 +24,7 @@
#include "opm/input/eclipse/Deck/Deck.hpp" #include "opm/input/eclipse/Deck/Deck.hpp"
#include "opm/input/eclipse/Parser/ParseContext.hpp" #include "opm/input/eclipse/Parser/ParseContext.hpp"
#include "opm/input/eclipse/Parser/Parser.hpp" #include "opm/input/eclipse/Parser/Parser.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/I.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/V.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/V.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
@ -131,8 +132,10 @@ std::map<std::string, std::vector<std::pair<int, int>>> RiaOpmParserTools::extra
Opm::Parser parser( false ); Opm::Parser parser( false );
const Opm::ParserKeywords::WSEGLINK kw1; const Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::INCLUDE kw2;
parser.addParserKeyword( kw1 ); parser.addParserKeyword( kw1 );
parser.addParserKeyword( kw2 );
std::stringstream ss; std::stringstream ss;
Opm::ParseContext parseContext( Opm::InputError::Action::WARN ); Opm::ParseContext parseContext( Opm::InputError::Action::WARN );

View File

@ -139,12 +139,43 @@ void RimFileSummaryCase::createRftReaderInterface()
QFileInfo fileInfo( summaryHeaderFilename() ); QFileInfo fileInfo( summaryHeaderFilename() );
QString folder = fileInfo.absolutePath(); QString folder = fileInfo.absolutePath();
QString rftFileName = folder + "/" + fileInfo.completeBaseName() + ".RFT"; QString rftFileName = folder + "/" + fileInfo.completeBaseName() + ".RFT";
QFileInfo rftFileInfo( rftFileName );
if ( rftFileInfo.exists() )
{ {
m_rftCase()->setRftFileName( rftFileName ); QFileInfo fi( rftFileName );
if ( fi.exists() )
{
m_rftCase()->setRftFileName( rftFileName );
}
}
if ( m_rftCase->dataDeckFilePath().isEmpty() )
{
// Search for *.DATA file in same folder as summary file. If not found, search for a schedule file.
QString validDataDeckFileName;
QString dataDeckFileName = folder + "/" + fileInfo.completeBaseName() + ".DATA";
QFileInfo fi( dataDeckFileName );
if ( fi.exists() )
{
validDataDeckFileName = dataDeckFileName;
}
else
{
QString scheduleFileName = folder + "/" + fileInfo.completeBaseName() + ".SCH";
QFileInfo fi( scheduleFileName );
if ( fi.exists() )
{
validDataDeckFileName = scheduleFileName;
}
}
if ( !validDataDeckFileName.isEmpty() )
{
m_rftCase->setDataDeckFileName( dataDeckFileName );
}
} }
m_summaryEclipseRftReader = m_summaryEclipseRftReader =

View File

@ -24,6 +24,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellLogRftCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogRftCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.h ${CMAKE_CURRENT_LIST_DIR}/RimRftTools.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@ -52,6 +53,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatistics.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatistics.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatisticsCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatisticsCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RimRftTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.cpp
) )
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -141,9 +141,10 @@ QList<caf::PdmOptionItemInfo> RimRftTools::segmentResultNameOptions( RifReaderRf
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderRftInterface* readerRft, QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderRftInterface* readerRft,
const QString& wellName, const QString& wellName,
const QDateTime& timeStep ) const QDateTime& timeStep,
RiaDefines::RftBranchType branchType )
{ {
auto opmReader = dynamic_cast<RifReaderOpmRft*>( readerRft ); auto opmReader = dynamic_cast<RifReaderOpmRft*>( readerRft );
if ( opmReader ) if ( opmReader )
@ -151,7 +152,7 @@ QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderR
QList<caf::PdmOptionItemInfo> options; QList<caf::PdmOptionItemInfo> options;
options.push_front( caf::PdmOptionItemInfo( RiaDefines::allBranches(), -1 ) ); options.push_front( caf::PdmOptionItemInfo( RiaDefines::allBranches(), -1 ) );
auto branchIdIndex = opmReader->branchIdsAndOneBasedIndices( wellName, timeStep ); auto branchIdIndex = opmReader->branchIdsAndOneBasedIndices( wellName, timeStep, branchType );
std::set<int> indices; std::set<int> indices;
for ( auto b : branchIdIndex ) for ( auto b : branchIdIndex )
@ -169,7 +170,7 @@ QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderR
auto minMax = std::minmax_element( branchIds.begin(), branchIds.end() ); auto minMax = std::minmax_element( branchIds.begin(), branchIds.end() );
auto txt = QString( "%1 (%2-%3)" ).arg( i ).arg( *minMax.first ).arg( *minMax.second ); auto txt = QString( "%1 (Branch Id %2-%3)" ).arg( i ).arg( *minMax.first ).arg( *minMax.second );
options.push_back( caf::PdmOptionItemInfo( txt, i ) ); options.push_back( caf::PdmOptionItemInfo( txt, i ) );
} }

View File

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "RiaRftDefines.h"
#include "RifEclipseRftAddress.h" #include "RifEclipseRftAddress.h"
#include <QList> #include <QList>
@ -40,7 +41,9 @@ public:
static QList<caf::PdmOptionItemInfo> segmentTimeStepOptions( RifReaderRftInterface* readerRft, const QString& wellName ); static QList<caf::PdmOptionItemInfo> segmentTimeStepOptions( RifReaderRftInterface* readerRft, const QString& wellName );
static QList<caf::PdmOptionItemInfo> static QList<caf::PdmOptionItemInfo>
segmentResultNameOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep ); segmentResultNameOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep );
static QList<caf::PdmOptionItemInfo> static QList<caf::PdmOptionItemInfo> segmentBranchIndexOptions( RifReaderRftInterface* readerRft,
segmentBranchIndexOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep ); const QString& wellName,
const QDateTime& timeStep,
RiaDefines::RftBranchType branchType );
}; };

View File

@ -0,0 +1,297 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimRftTopologyCurve.h"
#include "RiaColorTables.h"
#include "RiaSummaryTools.h"
#include "RifReaderOpmRft.h"
#include "RigWellLogCurveData.h"
#include "RimDepthTrackPlot.h"
#include "RimProject.h"
#include "RimRftTools.h"
#include "RimSummaryCase.h"
#include "RimWellLogPlot.h"
#include "RiuPlotCurve.h"
CAF_PDM_SOURCE_INIT( RimRftTopologyCurve, "RimRftTopologyCurve" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimRftTopologyCurve::RimRftTopologyCurve()
{
CAF_PDM_InitObject( "RFT Topology Curve" );
CAF_PDM_InitFieldNoDefault( &m_summaryCase, "SummaryCase", "Summary Case" );
m_summaryCase.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_timeStep, "TimeStep", "Time Step" );
CAF_PDM_InitFieldNoDefault( &m_wellName, "WellName", "Well Name" );
CAF_PDM_InitField( &m_segmentBranchIndex, "SegmentBranchIndex", -1, "Branch" );
CAF_PDM_InitFieldNoDefault( &m_segmentBranchType, "SegmentBranchType", "Completion" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::setDataSource( RimSummaryCase* summaryCase,
const QDateTime& timeStep,
const QString& wellName,
int segmentBranchIndex,
RiaDefines::RftBranchType branchType )
{
setDataSource( summaryCase, timeStep, wellName, segmentBranchIndex );
m_segmentBranchType = branchType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::setDataSource( RimSummaryCase* summaryCase,
const QDateTime& timeStep,
const QString& wellName,
int segmentBranchIndex )
{
m_summaryCase = summaryCase;
m_timeStep = timeStep;
m_wellName = wellName;
m_segmentBranchIndex = segmentBranchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimRftTopologyCurve::wellName() const
{
return "Topology curve";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimRftTopologyCurve::wellLogChannelUiName() const
{
return "Topology curve channel";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimRftTopologyCurve::wellLogChannelUnits() const
{
return "Topology curve units";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimRftTopologyCurve::createCurveAutoName()
{
QString text;
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_ANNULUS ) text += "Annulus";
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_DEVICE ) text += "Device";
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_TUBING ) text += "Tubing";
text += QString( " (%1)" ).arg( m_segmentBranchIndex() );
return text;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
RimPlotCurve::updateOptionSensitivity();
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Data Source" );
curveDataGroup->add( &m_summaryCase );
curveDataGroup->add( &m_wellName );
curveDataGroup->add( &m_timeStep );
curveDataGroup->add( &m_segmentBranchIndex );
curveDataGroup->add( &m_segmentBranchType );
caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" );
RimStackablePlotCurve::stackingUiOrdering( *stackingGroup );
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" );
RimPlotCurve::appearanceUiOrdering( *appearanceGroup );
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "Curve Name" );
nameGroup->setCollapsedByDefault();
nameGroup->add( &m_showLegend );
RimPlotCurve::curveNameUiOrdering( *nameGroup );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimRftTopologyCurve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
if ( !m_summaryCase ) return {};
QList<caf::PdmOptionItemInfo> options;
auto reader = m_summaryCase->rftReader();
if ( fieldNeedingOptions == &m_summaryCase )
{
options = RiaSummaryTools::optionsForSummaryCases( RimProject::current()->allSummaryCases() );
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
else if ( fieldNeedingOptions == &m_wellName )
{
options = RimRftTools::wellNameOptions( reader );
}
else if ( fieldNeedingOptions == &m_timeStep )
{
options = RimRftTools::segmentTimeStepOptions( reader, m_wellName );
}
else if ( fieldNeedingOptions == &m_segmentBranchIndex )
{
options = RimRftTools::segmentBranchIndexOptions( reader,
m_wellName(),
m_timeStep(),
RiaDefines::RftBranchType::RFT_UNKNOWN );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimWellLogCurve::fieldChangedByUi( changedField, oldValue, newValue );
this->loadDataAndUpdate( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::onLoadDataAndUpdate( bool updateParentPlot )
{
this->RimPlotCurve::updateCurvePresentation( updateParentPlot );
if ( m_summaryCase )
{
auto rftReader = dynamic_cast<RifReaderOpmRft*>( m_summaryCase->rftReader() );
// Update well path attributes, packers and casing based on RFT data
if ( rftReader )
{
std::vector<double> seglenstValues;
std::vector<double> seglenenValues;
auto resultNameSeglenst = RifEclipseRftAddress::createSegmentAddress( m_wellName, m_timeStep, "SEGLENST" );
rftReader->values( resultNameSeglenst, &seglenstValues );
auto resultNameSeglenen = RifEclipseRftAddress::createSegmentAddress( m_wellName, m_timeStep, "SEGLENEN" );
rftReader->values( resultNameSeglenen, &seglenenValues );
auto segment = rftReader->segmentForWell( m_wellName, m_timeStep );
auto segmentIndices = segment.segmentIndicesForBranchIndex( m_segmentBranchIndex(), m_segmentBranchType() );
if ( !segmentIndices.empty() )
{
std::vector<double> depths;
std::vector<double> propertyValues;
// Assign a static property value to each type of curve to make sure they all are separated and easily
// visible
double curveValue = 1.0;
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_TUBING ) curveValue = 2.0;
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_DEVICE ) curveValue = 3.0;
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_ANNULUS ) curveValue = 4.0;
// Adjust the location of each branch if multiple branches are visible at the same time
curveValue += m_segmentBranchIndex() * 0.2;
for ( auto segmentIndex : segmentIndices )
{
depths.push_back( seglenstValues[segmentIndex] );
depths.push_back( seglenenValues[segmentIndex] );
propertyValues.push_back( curveValue );
propertyValues.push_back( curveValue );
}
RimDepthTrackPlot* wellLogPlot;
firstAncestorOrThisOfTypeAsserted( wellLogPlot );
RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType();
RiaDefines::DepthUnitType displayUnit = wellLogPlot->depthUnit();
bool isExtractionCurve = false;
bool useLogarithmicScale = false;
setPropertyValuesAndDepths( propertyValues, depths, depthType, 0.0, displayUnit, isExtractionCurve, useLogarithmicScale );
// Assign curve values based on horizontal or vertical plot
setPropertyAndDepthValuesToPlotCurve( propertyValues, depths );
if ( updateParentPlot )
{
updateZoomInParentPlot();
}
if ( m_parentPlot )
{
m_parentPlot->replot();
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimRftTopologyCurve::applyDefaultAppearance()
{
cvf::Color3f color = cvf::Color3f::BLUE;
if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_TUBING )
{
color = RiaColorTables::wellLogPlotPaletteColors().cycledColor3f( 0 );
}
else if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_DEVICE )
{
color = RiaColorTables::wellLogPlotPaletteColors().cycledColor3f( 1 );
setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_NONE );
}
else if ( m_segmentBranchType() == RiaDefines::RftBranchType::RFT_ANNULUS )
{
color = RiaColorTables::wellLogPlotPaletteColors().cycledColor3f( 2 );
setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_NONE );
}
setColor( color );
setLineThickness( 5.0 );
setSymbol( RiuPlotCurveSymbol::PointSymbolEnum::SYMBOL_ELLIPSE );
}

View File

@ -0,0 +1,70 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2022 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 "RimWellLogCurve.h"
#include "cafPdmPtrField.h"
#include "RiaRftDefines.h"
#include <QDateTime>
class RimSummaryCase;
//==================================================================================================
///
///
//==================================================================================================
class RimRftTopologyCurve : public RimWellLogCurve
{
CAF_PDM_HEADER_INIT;
public:
RimRftTopologyCurve();
void setDataSource( RimSummaryCase* summaryCase,
const QDateTime& timeStep,
const QString& wellName,
int segmentBranchIndex,
RiaDefines::RftBranchType branchType );
void setDataSource( RimSummaryCase* summaryCase, const QDateTime& timeStep, const QString& wellName, int segmentBranchIndex );
void applyDefaultAppearance();
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelUnits() const override;
protected:
QString createCurveAutoName() override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void onLoadDataAndUpdate( bool updateParentPlot ) override;
private:
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmField<QDateTime> m_timeStep;
caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_segmentBranchIndex;
caf::PdmField<caf::AppEnum<RiaDefines::RftBranchType>> m_segmentBranchType;
};

View File

@ -29,6 +29,7 @@
#include "RimOilField.h" #include "RimOilField.h"
#include "RimProject.h" #include "RimProject.h"
#include "RimRftTools.h" #include "RimRftTools.h"
#include "RimRftTopologyCurve.h"
#include "RimSummaryCase.h" #include "RimSummaryCase.h"
#include "RimTools.h" #include "RimTools.h"
#include "RimWellFlowRateCurve.h" #include "RimWellFlowRateCurve.h"
@ -108,7 +109,7 @@ RimWellLogCurveCommonDataSource::RimWellLogCurveCommonDataSource()
CAF_PDM_InitFieldNoDefault( &m_rftTimeStep, "RftTimeStep", "RFT Time Step" ); CAF_PDM_InitFieldNoDefault( &m_rftTimeStep, "RftTimeStep", "RFT Time Step" );
CAF_PDM_InitFieldNoDefault( &m_rftWellName, "RftWellName", "RFT Well Name" ); CAF_PDM_InitFieldNoDefault( &m_rftWellName, "RftWellName", "RFT Well Name" );
CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchIndex, "SegmentBranchIndex", "RFT Branch" ); CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchIndex, "SegmentBranchIndex", "RFT Branch" );
CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchType, "SegmentBranchType", "RFT Branch Type" ); CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchType, "SegmentBranchType", "RFT Completion" );
m_case = nullptr; m_case = nullptr;
m_wellPath = nullptr; m_wellPath = nullptr;
@ -531,6 +532,7 @@ void RimWellLogCurveCommonDataSource::applyDataSourceChanges( const std::vector<
auto* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve ); auto* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve );
auto* measurementCurve = dynamic_cast<RimWellMeasurementCurve*>( curve ); auto* measurementCurve = dynamic_cast<RimWellMeasurementCurve*>( curve );
auto* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve ); auto* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve );
auto* topologyCurve = dynamic_cast<RimRftTopologyCurve*>( curve );
if ( fileCurve ) if ( fileCurve )
{ {
if ( wellPathToApply() != nullptr ) if ( wellPathToApply() != nullptr )
@ -638,6 +640,10 @@ void RimWellLogCurveCommonDataSource::applyDataSourceChanges( const std::vector<
rftCurve->firstAncestorOrThisOfTypeAsserted( parentPlot ); rftCurve->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot ); plots.insert( parentPlot );
} }
else if ( topologyCurve )
{
topologyCurve->setDataSource( m_summaryCase, m_rftTimeStep, m_rftWellName, m_rftSegmentBranchIndex );
}
curve->updateConnectedEditors(); curve->updateConnectedEditors();
} }
@ -1002,7 +1008,8 @@ QList<caf::PdmOptionItemInfo>
} }
else if ( fieldNeedingOptions == &m_rftSegmentBranchIndex ) else if ( fieldNeedingOptions == &m_rftSegmentBranchIndex )
{ {
options = RimRftTools::segmentBranchIndexOptions( rftReader(), m_rftWellName(), m_rftTimeStep() ); options =
RimRftTools::segmentBranchIndexOptions( rftReader(), m_rftWellName(), m_rftTimeStep(), m_rftSegmentBranchType() );
} }
return options; return options;
@ -1062,8 +1069,8 @@ void RimWellLogCurveCommonDataSource::defineUiOrdering( QString uiConfigName, ca
if ( !m_uniqueRftTimeSteps.empty() ) group->add( &m_rftTimeStep ); if ( !m_uniqueRftTimeSteps.empty() ) group->add( &m_rftTimeStep );
if ( !m_uniqueRftWellNames.empty() ) group->add( &m_rftWellName ); if ( !m_uniqueRftWellNames.empty() ) group->add( &m_rftWellName );
if ( !m_uniqueRftBranchIndices.empty() ) group->add( &m_rftSegmentBranchIndex );
if ( !m_uniqueRftBranchTypes.empty() ) group->add( &m_rftSegmentBranchType ); if ( !m_uniqueRftBranchTypes.empty() ) group->add( &m_rftSegmentBranchType );
if ( !m_uniqueRftBranchIndices.empty() ) group->add( &m_rftSegmentBranchIndex );
uiOrdering.skipRemainingFields( true ); uiOrdering.skipRemainingFields( true );
} }

View File

@ -18,6 +18,8 @@
#include "RimWellLogRftCurve.h" #include "RimWellLogRftCurve.h"
#include "RiaColorTables.h"
#include "RiaColorTools.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaEclipseUnitTools.h" #include "RiaEclipseUnitTools.h"
#include "RiaQDateTimeTools.h" #include "RiaQDateTimeTools.h"
@ -175,7 +177,9 @@ RimWellLogRftCurve::RimWellLogRftCurve()
CAF_PDM_InitField( &m_segmentResultName, "SegmentResultName", RiaResultNames::undefinedResultName(), "Result Name" ); CAF_PDM_InitField( &m_segmentResultName, "SegmentResultName", RiaResultNames::undefinedResultName(), "Result Name" );
CAF_PDM_InitField( &m_segmentBranchIndex, "SegmentBranchIndex", -1, "Branch" ); CAF_PDM_InitField( &m_segmentBranchIndex, "SegmentBranchIndex", -1, "Branch" );
CAF_PDM_InitFieldNoDefault( &m_segmentBranchType, "SegmentBranchType", "Branch Type" ); CAF_PDM_InitFieldNoDefault( &m_segmentBranchType, "SegmentBranchType", "Completion" );
CAF_PDM_InitField( &m_curveColorByPhase, "CurveColorByPhase", false, "Color by Phase" );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -438,6 +442,43 @@ void RimWellLogRftCurve::setSimWellBranchData( bool branchDetection, int branchI
m_branchIndex = branchIndex; m_branchIndex = branchIndex;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::enableColorFromResultName( bool enable )
{
m_curveColorByPhase = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::assignColorFromResultName( const QString& resultName )
{
cvf::Color3f color = cvf::Color3f::BLACK;
if ( resultName.startsWith( "SEGO" ) || resultName.startsWith( "CONO" ) )
{
color = RiaColorTables::summaryCurveGreenPaletteColors().cycledColor3f( 0 );
}
else if ( resultName.startsWith( "SEGW" ) || resultName.startsWith( "CONW" ) )
{
color = RiaColorTables::summaryCurveBluePaletteColors().cycledColor3f( 0 );
}
else if ( resultName.startsWith( "SEGG" ) || resultName.startsWith( "CONG" ) )
{
color = RiaColorTables::summaryCurveRedPaletteColors().cycledColor3f( 0 );
}
// Do nothing if not phase is identified
if ( color == cvf::Color3f::BLACK ) return;
float scalingFactor = 0.5;
auto fillColor = RiaColorTools::makeLighter( color, scalingFactor );
setColor( color );
setFillColor( fillColor );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -503,6 +544,11 @@ QString RimWellLogRftCurve::createCurveAutoName()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot ) void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot )
{ {
if ( m_curveColorByPhase && m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA )
{
assignColorFromResultName( m_segmentResultName );
}
this->RimPlotCurve::updateCurvePresentation( updateParentPlot ); this->RimPlotCurve::updateCurvePresentation( updateParentPlot );
DerivedMDSource derivedMDSource = DerivedMDSource::NO_SOURCE; DerivedMDSource derivedMDSource = DerivedMDSource::NO_SOURCE;
@ -710,8 +756,9 @@ void RimWellLogRftCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
else else
{ {
curveDataGroup->add( &m_segmentResultName ); curveDataGroup->add( &m_segmentResultName );
curveDataGroup->add( &m_segmentBranchIndex );
curveDataGroup->add( &m_segmentBranchType ); curveDataGroup->add( &m_segmentBranchType );
curveDataGroup->add( &m_segmentBranchIndex );
curveDataGroup->add( &m_curveColorByPhase );
} }
caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" ); caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" );
@ -778,7 +825,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions( const c
} }
else if ( fieldNeedingOptions == &m_segmentBranchIndex ) else if ( fieldNeedingOptions == &m_segmentBranchIndex )
{ {
options = RimRftTools::segmentBranchIndexOptions( reader, m_wellName(), m_timeStep() ); options = RimRftTools::segmentBranchIndexOptions( reader, m_wellName(), m_timeStep(), m_segmentBranchType() );
} }
return options; return options;

View File

@ -98,6 +98,9 @@ public:
void setSimWellBranchData( bool branchDetection, int branchIndex ); void setSimWellBranchData( bool branchDetection, int branchIndex );
void enableColorFromResultName( bool enable );
void assignColorFromResultName( const QString& resultName );
protected: protected:
// Overrides from RimWellLogPlotCurve // Overrides from RimWellLogPlotCurve
QString createCurveAutoName() override; QString createCurveAutoName() override;
@ -142,6 +145,7 @@ private:
caf::PdmField<QString> m_wellName; caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_branchIndex; caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection; caf::PdmField<bool> m_branchDetection;
caf::PdmField<bool> m_curveColorByPhase;
caf::PdmField<caf::AppEnum<RimWellLogRftCurve::RftDataType>> m_rftDataType; caf::PdmField<caf::AppEnum<RimWellLogRftCurve::RftDataType>> m_rftDataType;

View File

@ -11,6 +11,8 @@
#include <opm/input/eclipse/Parser/ParserKeywords/V.hpp> #include <opm/input/eclipse/Parser/ParserKeywords/V.hpp>
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/I.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/S.hpp"
#include "OpmTestDataDirectory.h" #include "OpmTestDataDirectory.h"
@ -87,22 +89,22 @@ TEST(OpmParserTest, ReadFromFile)
TEST(OpmParserTest, ReadAndParseWSEGLINK) TEST(OpmParserTest, ReadAndParseWSEGLINK)
{ {
Parser parser(false); Parser parser(false);
const ::Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::INCLUDE kw2;
parser.addParserKeyword(kw1); parser.addParserKeyword(kw1);
parser.addParserKeyword(kw2);
std::stringstream ss; std::string testFilePath = std::string(TEST_DATA_DIR) + "/test_wseglink.DATA";
ss << TEST_DATA_DIR << "/test_wseglink.DATA";
std::string testFile = ss.str(); Opm::ParseContext parseContext(Opm::InputError::Action::WARN);
auto deck = parser.parseFile(testFilePath, parseContext);
auto deck = parser.parseFile(testFile);
std::string myKeyword = "WSEGLINK"; std::string myKeyword = "WSEGLINK";
auto keywordList = deck.getKeywordList(myKeyword); auto keywordList = deck.getKeywordList(myKeyword);
for (auto kw : keywordList) for (auto kw : keywordList)
{ {
auto name = kw->name();
for (size_t i = 0; i < kw->size(); i++) for (size_t i = 0; i < kw->size(); i++)
{ {
auto deckRecord = kw->getRecord(i); auto deckRecord = kw->getRecord(i);

@ -1 +1 @@
Subproject commit 212cc35c4354e501570b4b07577d6f224418849b Subproject commit aa8e9c1f84a8ccfe829c3a89295c442e95bb2a09