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

View File

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

View File

@ -25,9 +25,13 @@
#include "RiaApplication.h"
#include "RiaRftDefines.h"
#include "RifReaderEclipseRft.h"
#include "RifReaderOpmRft.h"
#include "RigWellLogCurveData.h"
#include "RimRftCase.h"
#include "RimRftTopologyCurve.h"
#include "RimSummaryCase.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogPlot.h"
@ -63,26 +67,32 @@ void RicNewRftSegmentWellLogPlotFeature::onActionTriggered( bool isChecked )
RimSummaryCase* summaryCase = nullptr;
rftCase->firstAncestorOfType( summaryCase );
if ( !summaryCase ) return;
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";
{
auto branchType = RiaDefines::RftBranchType::RFT_TUBING;
std::vector<RiaDefines::RftBranchType> branchTypes{ RiaDefines::RftBranchType::RFT_ANNULUS,
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, branchType, summaryCase );
appendTrackAndCurveForBranchType( plot, resultName, wellName, branchType, summaryCase );
}
{
auto branchType = RiaDefines::RftBranchType::RFT_ANNULUS;
appendTrackAndCurveForBranchType( plot, resultName, branchType, summaryCase );
}
appendTopologyTrack( plot, wellName, summaryCase );
plot->loadDataAndUpdate();
RiuPlotMainWindowTools::onObjectAppended( plot );
}
@ -92,6 +102,7 @@ void RicNewRftSegmentWellLogPlotFeature::onActionTriggered( bool isChecked )
//--------------------------------------------------------------------------------------------------
void RicNewRftSegmentWellLogPlotFeature::appendTrackAndCurveForBranchType( RimWellLogPlot* plot,
const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType,
RimSummaryCase* summaryCase )
{
@ -101,13 +112,50 @@ void RicNewRftSegmentWellLogPlotFeature::appendTrackAndCurveForBranchType( RimWe
plot->loadDataAndUpdate();
auto curve = RicWellLogTools::addSummaryRftSegmentCurve( plotTrack, resultName, branchType, summaryCase );
auto curve = RicWellLogTools::addSummaryRftSegmentCurve( plotTrack, resultName, wellName, branchType, summaryCase );
curve->loadDataAndUpdate( true );
curve->updateAllRequiredEditors();
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,
const QString& resultName,
const QString& wellName,
RiaDefines::RftBranchType branchType,
RimSummaryCase* summaryCase );
void appendTopologyTrack( RimWellLogPlot* plot, const QString& wellName, RimSummaryCase* summaryCase );
};

View File

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

View File

@ -81,7 +81,8 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
{
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 )
{
CAF_ASSERT( i < data.size() );
@ -145,8 +146,8 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
}
else
{
auto indices =
segment.indicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() );
auto indices = segment.segmentIndicesForBranchIndex( rftAddress.segmentBranchIndex(),
rftAddress.segmentBranchType() );
for ( const auto& i : indices )
{
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 m = timeStep.date().month();
@ -299,7 +302,25 @@ std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString&
if ( m_rftWellDateSegments.count( key ) > 0 )
{
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 {};
@ -310,15 +331,26 @@ std::map<int, int> RifReaderOpmRft::branchIdsAndOneBasedIndices( const QString&
//--------------------------------------------------------------------------------------------------
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() )
{
QString text = QString( "Imported segment data from %1\n" ).arg( QString::fromStdString( filePath ) );
text += QString( "Number of wells: %1\n" ).arg( m_wseglink.size() );
text += "Imported WSEGLINK data from well(s):\n";
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 );
}
int oneBasedBranchIndex = 1;
if ( !seglenenValues.empty() && !seglenstValues.empty() )
{
// Find tubing and annulus branch types
identifyTubingCandidateBranches( segmentRef, wellName, seglenstValues, seglenenValues );
identifyAnnulusBranches( segmentRef, seglenstValues );
auto branchIds = segmentRef.branchIds();
for ( auto id : branchIds )
{
double minimumMD = std::numeric_limits<double>::max();
double maximumMD = std::numeric_limits<double>::min();
// The tubing branches are given increasing branch indices. If a tubing branch is categorized as an annulus
// branch, the index values must be reassigned. Each triplet of tubing/device/annulus has a unique branch index.
reassignBranchIndices( segmentRef );
std::vector<int> segmentNumbers;
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 );
}
}
}
}
identifyDeviceBranches( segmentRef, seglenstValues );
// Assign branch index to annulus branches
auto branchIds = segmentRef.branchIds();
for ( auto branchId : branchIds )
{
auto branchType = segmentRef.branchType( branchId );
if ( branchType == RiaDefines::RftBranchType::RFT_ANNULUS )
{
auto segmentIndices = segmentRef.indicesForBranchNumber( branchId );
auto segmentIndices = segmentRef.segmentIndicesForBranchNumber( branchId );
if ( segmentIndices.empty() ) continue;
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;
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:
// Segment data
@ -68,6 +72,13 @@ private:
bool isOpen() const;
void importWellNames();
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;

View File

@ -21,6 +21,8 @@
#include <algorithm>
#include <unordered_set>
#include "cvfAssert.h"
//--------------------------------------------------------------------------------------------------
/// segnxt : Int ID for the next segment
/// 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 )
{
if ( segData.segNo() < deviceBranchFirstSegmentNumber ) continue;
@ -192,6 +219,13 @@ void RifRftSegment::createDeviceBranch( int deviceBranchFirstSegmentNumber, int
auto branchNumber = segData.segBrno();
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 );
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;
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;
for ( size_t i = 0; i < m_topology.size(); i++ )
@ -287,7 +321,7 @@ std::vector<int> RifRftSegment::segmentNumbersForBranchIndex( int
{
std::vector<int> v;
auto indices = indicesForBranchIndex( oneBasedBranchIndex, branchType );
auto indices = segmentIndicesForBranchIndex( oneBasedBranchIndex, branchType );
for ( auto index : indices )
{
v.push_back( m_topology[index].segNo() );
@ -295,3 +329,33 @@ std::vector<int> RifRftSegment::segmentNumbersForBranchIndex( int
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> branchIds() 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* 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 setBranchType( int branchId, RiaDefines::RftBranchType branchType );
@ -70,11 +73,16 @@ public:
RiaDefines::RftBranchType branchType( int branchId ) const;
std::vector<size_t> indicesForBranchNumber( int branchNumber ) const;
std::vector<size_t> indicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const;
std::vector<size_t> segmentIndicesForBranchNumber( int branchNumber ) const;
std::vector<size_t> segmentIndicesForBranchIndex( int branchIndex, 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:
std::vector<RifRftSegmentData> m_topology;
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/Parser/ParseContext.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/W.hpp"
@ -131,8 +132,10 @@ std::map<std::string, std::vector<std::pair<int, int>>> RiaOpmParserTools::extra
Opm::Parser parser( false );
const Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::INCLUDE kw2;
parser.addParserKeyword( kw1 );
parser.addParserKeyword( kw2 );
std::stringstream ss;
Opm::ParseContext parseContext( Opm::InputError::Action::WARN );

View File

@ -139,12 +139,43 @@ void RimFileSummaryCase::createRftReaderInterface()
QFileInfo fileInfo( summaryHeaderFilename() );
QString folder = fileInfo.absolutePath();
QString rftFileName = folder + "/" + fileInfo.completeBaseName() + ".RFT";
QFileInfo rftFileInfo( rftFileName );
if ( rftFileInfo.exists() )
QString rftFileName = folder + "/" + fileInfo.completeBaseName() + ".RFT";
{
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 =

View File

@ -24,6 +24,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimWellLogRftCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimWellLogWbsCurve.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.h
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -52,6 +53,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatistics.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleWellLogStatisticsCurve.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftTopologyCurve.cpp
)
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,
const QString& wellName,
const QDateTime& timeStep )
QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderRftInterface* readerRft,
const QString& wellName,
const QDateTime& timeStep,
RiaDefines::RftBranchType branchType )
{
auto opmReader = dynamic_cast<RifReaderOpmRft*>( readerRft );
if ( opmReader )
@ -151,7 +152,7 @@ QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderR
QList<caf::PdmOptionItemInfo> options;
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;
for ( auto b : branchIdIndex )
@ -169,7 +170,7 @@ QList<caf::PdmOptionItemInfo> RimRftTools::segmentBranchIndexOptions( RifReaderR
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 ) );
}

View File

@ -18,6 +18,7 @@
#pragma once
#include "RiaRftDefines.h"
#include "RifEclipseRftAddress.h"
#include <QList>
@ -40,7 +41,9 @@ public:
static QList<caf::PdmOptionItemInfo> segmentTimeStepOptions( RifReaderRftInterface* readerRft, const QString& wellName );
static QList<caf::PdmOptionItemInfo>
segmentResultNameOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep );
static QList<caf::PdmOptionItemInfo>
segmentBranchIndexOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep );
segmentResultNameOptions( RifReaderRftInterface* readerRft, const QString& wellName, const QDateTime& timeStep );
static QList<caf::PdmOptionItemInfo> segmentBranchIndexOptions( RifReaderRftInterface* readerRft,
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 "RimProject.h"
#include "RimRftTools.h"
#include "RimRftTopologyCurve.h"
#include "RimSummaryCase.h"
#include "RimTools.h"
#include "RimWellFlowRateCurve.h"
@ -108,7 +109,7 @@ RimWellLogCurveCommonDataSource::RimWellLogCurveCommonDataSource()
CAF_PDM_InitFieldNoDefault( &m_rftTimeStep, "RftTimeStep", "RFT Time Step" );
CAF_PDM_InitFieldNoDefault( &m_rftWellName, "RftWellName", "RFT Well Name" );
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_wellPath = nullptr;
@ -531,6 +532,7 @@ void RimWellLogCurveCommonDataSource::applyDataSourceChanges( const std::vector<
auto* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve );
auto* measurementCurve = dynamic_cast<RimWellMeasurementCurve*>( curve );
auto* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve );
auto* topologyCurve = dynamic_cast<RimRftTopologyCurve*>( curve );
if ( fileCurve )
{
if ( wellPathToApply() != nullptr )
@ -638,6 +640,10 @@ void RimWellLogCurveCommonDataSource::applyDataSourceChanges( const std::vector<
rftCurve->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot );
}
else if ( topologyCurve )
{
topologyCurve->setDataSource( m_summaryCase, m_rftTimeStep, m_rftWellName, m_rftSegmentBranchIndex );
}
curve->updateConnectedEditors();
}
@ -1002,7 +1008,8 @@ QList<caf::PdmOptionItemInfo>
}
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;
@ -1062,8 +1069,8 @@ void RimWellLogCurveCommonDataSource::defineUiOrdering( QString uiConfigName, ca
if ( !m_uniqueRftTimeSteps.empty() ) group->add( &m_rftTimeStep );
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_uniqueRftBranchIndices.empty() ) group->add( &m_rftSegmentBranchIndex );
uiOrdering.skipRemainingFields( true );
}

View File

@ -18,6 +18,8 @@
#include "RimWellLogRftCurve.h"
#include "RiaColorTables.h"
#include "RiaColorTools.h"
#include "RiaDefines.h"
#include "RiaEclipseUnitTools.h"
#include "RiaQDateTimeTools.h"
@ -175,7 +177,9 @@ RimWellLogRftCurve::RimWellLogRftCurve()
CAF_PDM_InitField( &m_segmentResultName, "SegmentResultName", RiaResultNames::undefinedResultName(), "Result Name" );
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;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 )
{
if ( m_curveColorByPhase && m_rftDataType() == RimWellLogRftCurve::RftDataType::RFT_SEGMENT_DATA )
{
assignColorFromResultName( m_segmentResultName );
}
this->RimPlotCurve::updateCurvePresentation( updateParentPlot );
DerivedMDSource derivedMDSource = DerivedMDSource::NO_SOURCE;
@ -710,8 +756,9 @@ void RimWellLogRftCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
else
{
curveDataGroup->add( &m_segmentResultName );
curveDataGroup->add( &m_segmentBranchIndex );
curveDataGroup->add( &m_segmentBranchType );
curveDataGroup->add( &m_segmentBranchIndex );
curveDataGroup->add( &m_curveColorByPhase );
}
caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" );
@ -778,7 +825,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions( const c
}
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;

View File

@ -98,6 +98,9 @@ public:
void setSimWellBranchData( bool branchDetection, int branchIndex );
void enableColorFromResultName( bool enable );
void assignColorFromResultName( const QString& resultName );
protected:
// Overrides from RimWellLogPlotCurve
QString createCurveAutoName() override;
@ -142,6 +145,7 @@ private:
caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection;
caf::PdmField<bool> m_curveColorByPhase;
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/W.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/I.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/S.hpp"
#include "OpmTestDataDirectory.h"
@ -87,22 +89,22 @@ TEST(OpmParserTest, ReadFromFile)
TEST(OpmParserTest, ReadAndParseWSEGLINK)
{
Parser parser(false);
const ::Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::WSEGLINK kw1;
const Opm::ParserKeywords::INCLUDE kw2;
parser.addParserKeyword(kw1);
parser.addParserKeyword(kw2);
std::stringstream ss;
ss << TEST_DATA_DIR << "/test_wseglink.DATA";
std::string testFile = ss.str();
auto deck = parser.parseFile(testFile);
std::string testFilePath = std::string(TEST_DATA_DIR) + "/test_wseglink.DATA";
Opm::ParseContext parseContext(Opm::InputError::Action::WARN);
auto deck = parser.parseFile(testFilePath, parseContext);
std::string myKeyword = "WSEGLINK";
auto keywordList = deck.getKeywordList(myKeyword);
for (auto kw : keywordList)
{
auto name = kw->name();
for (size_t i = 0; i < kw->size(); i++)
{
auto deckRecord = kw->getRecord(i);

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