RFT: Support device and annulus branches (#9168)

* Add unit test used to read data from WSEGLINK
* Add segment branch type
* Add detection of device branches
* Add data source stepping on branch type
* parse wseglink data
* add RFT case as child of RimFileSummaryCase
This commit is contained in:
Magne Sjaastad
2022-08-16 12:40:25 +02:00
committed by GitHub
parent e6af123094
commit 1f2e9babe6
25 changed files with 952 additions and 261 deletions

View File

@@ -21,16 +21,18 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseRftAddress::RifEclipseRftAddress( const QString& wellName,
const QDateTime& timeStep,
RftWellLogChannelType wellLogChannelName,
const QString& segmentResultName,
int segmentBranchNumber )
RifEclipseRftAddress::RifEclipseRftAddress( const QString& wellName,
const QDateTime& timeStep,
RftWellLogChannelType wellLogChannelName,
const QString& segmentResultName,
int segmentBranchIndex,
RiaDefines::RftBranchType segmentBranchType )
: m_wellName( wellName )
, m_timeStep( timeStep )
, m_wellLogChannel( wellLogChannelName )
, m_segmentResultName( segmentResultName )
, m_segmentBranchNumber( segmentBranchNumber )
, m_segmentBranchIndex( segmentBranchIndex )
, m_segmentBranchType( segmentBranchType )
{
}
@@ -43,7 +45,31 @@ RifEclipseRftAddress RifEclipseRftAddress::createAddress( const QString&
{
auto segmentResultName = "";
auto segmentBranchNumber = -1;
auto adr = RifEclipseRftAddress( wellName, timeStep, wellLogChannel, segmentResultName, segmentBranchNumber );
auto adr = RifEclipseRftAddress( wellName,
timeStep,
wellLogChannel,
segmentResultName,
segmentBranchNumber,
RiaDefines::RftBranchType::RFT_UNKNOWN );
return adr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseRftAddress RifEclipseRftAddress::createBranchSegmentAddress( const QString& wellName,
const QDateTime& dateTime,
const QString& resultName,
int segmentBranchIndex,
RiaDefines::RftBranchType segmentBranchType )
{
auto adr = RifEclipseRftAddress( wellName,
dateTime,
RifEclipseRftAddress::RftWellLogChannelType::SEGMENT_VALUES,
resultName,
segmentBranchIndex,
segmentBranchType );
return adr;
}
@@ -53,14 +79,14 @@ RifEclipseRftAddress RifEclipseRftAddress::createAddress( const QString&
//--------------------------------------------------------------------------------------------------
RifEclipseRftAddress RifEclipseRftAddress::createSegmentAddress( const QString& wellName,
const QDateTime& dateTime,
const QString& resultName,
int segmentBranchNumber )
const QString& resultName )
{
auto adr = RifEclipseRftAddress( wellName,
dateTime,
RifEclipseRftAddress::RftWellLogChannelType::SEGMENT_VALUES,
resultName,
segmentBranchNumber );
-1,
RiaDefines::RftBranchType::RFT_UNKNOWN );
return adr;
}
@@ -76,9 +102,17 @@ QString RifEclipseRftAddress::segmentResultName() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifEclipseRftAddress::segmentBranchNumber() const
int RifEclipseRftAddress::segmentBranchIndex() const
{
return m_segmentBranchNumber;
return m_segmentBranchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RftBranchType RifEclipseRftAddress::segmentBranchType() const
{
return m_segmentBranchType;
}
//--------------------------------------------------------------------------------------------------
@@ -137,7 +171,7 @@ bool operator==( const RifEclipseRftAddress& first, const RifEclipseRftAddress&
if ( first.timeStep() != second.timeStep() ) return false;
if ( first.wellLogChannel() != second.wellLogChannel() ) return false;
if ( first.segmentResultName() != second.segmentResultName() ) return false;
if ( first.segmentBranchNumber() != second.segmentBranchNumber() ) return false;
if ( first.segmentBranchIndex() != second.segmentBranchIndex() ) return false;
return true;
}
@@ -153,8 +187,8 @@ bool operator<( const RifEclipseRftAddress& first, const RifEclipseRftAddress& s
return ( first.wellLogChannel() < second.wellLogChannel() );
if ( first.segmentResultName() != second.segmentResultName() )
return first.segmentResultName() < second.segmentResultName();
if ( first.segmentBranchNumber() != second.segmentBranchNumber() )
return first.segmentBranchNumber() < second.segmentBranchNumber();
if ( first.segmentBranchIndex() != second.segmentBranchIndex() )
return first.segmentBranchIndex() < second.segmentBranchIndex();
return false;
}

View File

@@ -18,6 +18,8 @@
#pragma once
#include "RiaRftDefines.h"
#include <set>
#include <string>
#include <vector>
@@ -55,13 +57,18 @@ public:
static RifEclipseRftAddress
createAddress( const QString& wellName, const QDateTime& timeStep, RftWellLogChannelType wellLogChannel );
static RifEclipseRftAddress createSegmentAddress( const QString& wellName,
const QDateTime& dateTime,
const QString& resultName,
int segmentBranchNumber );
static RifEclipseRftAddress
createSegmentAddress( const QString& wellName, const QDateTime& dateTime, const QString& resultName );
QString segmentResultName() const;
int segmentBranchNumber() const;
static RifEclipseRftAddress createBranchSegmentAddress( const QString& wellName,
const QDateTime& dateTime,
const QString& resultName,
int segmentBranchIndex,
RiaDefines::RftBranchType segmentBranchType );
QString segmentResultName() const;
int segmentBranchIndex() const;
RiaDefines::RftBranchType segmentBranchType() const;
const QString& wellName() const;
QDateTime timeStep() const;
@@ -71,19 +78,21 @@ public:
static std::set<RftWellLogChannelType> pltPlotChannelTypes();
private:
RifEclipseRftAddress( const QString& wellName,
const QDateTime& timeStep,
RftWellLogChannelType wellLogChannel,
const QString& segmentResultName,
int segmentBranchNumber );
RifEclipseRftAddress( const QString& wellName,
const QDateTime& timeStep,
RftWellLogChannelType wellLogChannel,
const QString& segmentResultName,
int segmentBranchIndex,
RiaDefines::RftBranchType segmentBranchType );
private:
QString m_wellName;
QDateTime m_timeStep;
RftWellLogChannelType m_wellLogChannel;
QString m_segmentResultName;
int m_segmentBranchNumber;
QString m_segmentResultName;
int m_segmentBranchIndex;
RiaDefines::RftBranchType m_segmentBranchType;
};
bool operator==( const RifEclipseRftAddress& first, const RifEclipseRftAddress& second );

View File

@@ -23,6 +23,10 @@
#include "RiaRftDefines.h"
#include "RiaStdStringTools.h"
#include "RiaOpmParserTools.h"
#include "opm/input/eclipse/Parser/Parser.hpp"
#include "opm/input/eclipse/Parser/ParserKeywords/W.hpp"
#include "opm/io/eclipse/ERft.hpp"
#include "cafAssert.h"
@@ -31,25 +35,20 @@
#include <iomanip>
#include <iostream>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderOpmRft::RifReaderOpmRft( const QString& fileName, const QString& dataDeckFileName )
{
openFiles( fileName, dataDeckFileName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderOpmRft::RifReaderOpmRft( const QString& fileName )
{
try
{
m_opm_rft = std::make_unique<Opm::EclIO::ERft>( fileName.toStdString() );
buildMetaData();
}
catch ( const std::exception& e )
{
RiaLogging::error( QString( "Failed to open RFT file %1\n%2" ).arg( fileName ).arg( e.what() ) );
}
catch ( ... )
{
RiaLogging::error( QString( "Failed to open RFT file %1" ).arg( fileName ) );
}
openFiles( fileName, "" );
}
//--------------------------------------------------------------------------------------------------
@@ -82,12 +81,13 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
{
auto data = segment.topology();
auto indices = segment.indicesForBranchNumber( rftAddress.segmentBranchNumber() );
auto indices = segment.indicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() );
for ( const auto& i : indices )
{
CAF_ASSERT( i < data.size() );
values->push_back( data[i].segNo() );
}
return;
}
else if ( rftAddress.segmentResultName() == RiaDefines::segmentBranchNumberResultName() )
{
@@ -96,6 +96,16 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
{
values->push_back( branchNumber );
}
return;
}
else if ( rftAddress.segmentResultName() == RiaDefines::segmentOneBasedBranchIndexResultName() )
{
auto branchIndices = segment.oneBasedBranchIndices();
for ( const auto& branchNumber : branchIndices )
{
values->push_back( branchNumber );
}
return;
}
}
@@ -114,7 +124,8 @@ void RifReaderOpmRft::values( const RifEclipseRftAddress& rftAddress, std::vecto
auto key = std::make_pair( wellName, RftDate{ y, m, d } );
auto segment = m_rftWellDateSegments[key];
auto indices = segment.indicesForBranchNumber( rftAddress.segmentBranchNumber() );
auto indices =
segment.indicesForBranchIndex( rftAddress.segmentBranchIndex(), rftAddress.segmentBranchType() );
for ( const auto& i : indices )
{
CAF_ASSERT( i < data.size() );
@@ -253,6 +264,37 @@ void RifReaderOpmRft::cellIndices( const RifEclipseRftAddress& rftAddress, std::
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::readWseglink( const std::string& filePath )
{
m_wseglink = RiaOpmParserTools::extractWseglink( filePath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::openFiles( const QString& fileName, const QString& dataDeckFileName )
{
try
{
m_opm_rft = std::make_unique<Opm::EclIO::ERft>( fileName.toStdString() );
readWseglink( dataDeckFileName.toStdString() );
buildMetaData();
}
catch ( const std::exception& e )
{
RiaLogging::error( QString( "Failed to open RFT file %1\n%2" ).arg( fileName ).arg( e.what() ) );
}
catch ( ... )
{
RiaLogging::error( QString( "Failed to open RFT file %1" ).arg( fileName ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -317,16 +359,14 @@ void RifReaderOpmRft::buildMetaData()
auto resultName = std::get<0>( resultNameAndSize );
auto adr = RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ),
dt,
QString::fromStdString( resultName ),
-1 );
QString::fromStdString( resultName ) );
m_addresses.insert( adr );
}
auto adr = RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ),
dt,
RiaDefines::segmentNumberResultName(),
-1 );
RiaDefines::segmentNumberResultName() );
m_addresses.insert( adr );
}
@@ -456,6 +496,17 @@ void RifReaderOpmRft::importWellNames()
//--------------------------------------------------------------------------------------------------
void RifReaderOpmRft::buildSegmentBranchTypes( const RftSegmentKey& segmentKey )
{
// A branch can have up to three layers of branches
// Tubing branch
// The inner most branch representing the tubing pipe
//
// Device branch
// Layer between tubing branch and annulus branch or reservoir
// The device segment is connected to a segment on the tubing branch
//
// Annulus branch
// Layer between device branch and reservoir. The segment connection data is imported from WSEGLINK in the data deck
auto wellName = segmentKey.first;
auto date = segmentKey.second;
RifRftSegment& segmentRef = m_rftWellDateSegments[segmentKey];
@@ -469,8 +520,7 @@ void RifReaderOpmRft::buildSegmentBranchTypes( const RftSegmentKey& segmentKey )
std::vector<double> seglenstValues;
std::vector<double> seglenenValues;
{
auto resultName =
RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ), dt, "SEGLENST", -1 );
auto resultName = RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ), dt, "SEGLENST" );
values( resultName, &seglenstValues );
@@ -480,37 +530,124 @@ void RifReaderOpmRft::buildSegmentBranchTypes( const RftSegmentKey& segmentKey )
}
}
{
auto resultName =
RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ), dt, "SEGLENEN", -1 );
auto resultName = RifEclipseRftAddress::createSegmentAddress( QString::fromStdString( wellName ), dt, "SEGLENEN" );
values( resultName, &seglenenValues );
}
int oneBasedBranchIndex = 1;
if ( !seglenenValues.empty() && !seglenstValues.empty() )
{
// Find tubing and annulus branch types
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.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 );
const double tubingThreshold = 1.0;
RiaDefines::RftBranchType branchType = RiaDefines::RftBranchType::RFT_UNKNOWN;
if ( length > tubingThreshold ) branchType = RiaDefines::RftBranchType::RFT_TUBING;
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
for ( auto branchId : branchIds )
{
auto branchType = segmentRef.branchType( branchId );
if ( branchType == RiaDefines::RftBranchType::RFT_ANNULUS )
{
auto segmentIndices = segmentRef.indicesForBranchNumber( branchId );
if ( segmentIndices.empty() ) continue;
auto firstSegmentIndex = segmentIndices.front();
auto firstSegment = segmentRef.topology()[firstSegmentIndex];
auto candidateSegmentNumber = firstSegment.segNext();
auto candidateDeviceSeg = segmentRef.segmentData( candidateSegmentNumber );
if ( candidateDeviceSeg )
{
auto branchIndex = segmentRef.oneBasedBranchIndexForBranchId( candidateDeviceSeg->segBrno() );
if ( branchIndex >= 0 )
{
segmentRef.setOneBasedBranchIndex( branchId, branchIndex );
}
}
}
}
}
}
@@ -540,6 +677,35 @@ std::vector<int>
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<int, int>> RifReaderOpmRft::annulusLinksForWell( const std::string& wellName ) const
{
auto it = m_wseglink.find( wellName );
if ( it != m_wseglink.end() )
{
return it->second;
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<int> RifReaderOpmRft::annulusSegmentsForWell( const std::string& wellName ) const
{
std::vector<int> annulusSegments;
for ( auto it : annulusLinksForWell( wellName ) )
{
annulusSegments.push_back( it.first );
}
return annulusSegments;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -37,6 +37,7 @@ class RifReaderOpmRft : public RifReaderRftInterface, public cvf::Object
{
public:
RifReaderOpmRft( const QString& fileName );
RifReaderOpmRft( const QString& fileName, const QString& dataDeckFileName );
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
void values( const RifEclipseRftAddress& rftAddress, std::vector<double>* values ) override;
@@ -58,6 +59,7 @@ private:
using RftDate = std::tuple<int, int, int>;
using RftSegmentKey = std::pair<std::string, RftDate>;
void openFiles( const QString& fileName, const QString& dataDeckFileName );
void buildMetaData();
void buildSegmentData();
void segmentDataDebugLog() const;
@@ -67,6 +69,10 @@ private:
std::vector<int> importWellData( const std::string& wellName, const std::string& propertyName, const RftDate& date ) const;
void readWseglink( const std::string& filePath );
std::vector<std::pair<int, int>> annulusLinksForWell( const std::string& wellName ) const;
std::vector<int> annulusSegmentsForWell( const std::string& wellName ) const;
static RifEclipseRftAddress::RftWellLogChannelType identifyChannelType( const std::string& resultName );
static std::string resultNameFromChannelType( RifEclipseRftAddress::RftWellLogChannelType channelType );
@@ -79,4 +85,6 @@ private:
std::map<RftSegmentKey, RifRftSegment> m_rftWellDateSegments;
std::set<QDateTime> m_rftSegmentTimeSteps;
std::map<std::string, std::vector<std::pair<int, int>>> m_wseglink;
};

View File

@@ -149,6 +149,62 @@ std::vector<int> RifRftSegment::branchIds() const
return v;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RifRftSegment::oneBasedBranchIndices() const
{
std::set<int> indices;
for ( auto b : m_oneBasedBranchIndexMap )
{
indices.insert( b.second );
}
return indices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifRftSegment::oneBasedBranchIndexForBranchId( int branchId ) const
{
if ( m_oneBasedBranchIndexMap.count( branchId ) > 0 ) return m_oneBasedBranchIndexMap.at( branchId );
return -1;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RifRftSegmentData* RifRftSegment::segmentData( int segmentNumber ) const
{
for ( const auto& segData : m_topology )
{
if ( segData.segNo() == segmentNumber ) return &segData;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifRftSegment::createDeviceBranch( int deviceBranchFirstSegmentNumber, int oneBasedBranchIndex )
{
for ( auto& segData : m_topology )
{
if ( segData.segNo() < deviceBranchFirstSegmentNumber ) continue;
auto branchNumber = segData.segBrno();
if ( branchType( branchNumber ) != RiaDefines::RftBranchType::RFT_UNKNOWN ) return;
setOneBasedBranchIndex( segData.segBrno(), oneBasedBranchIndex );
setBranchType( segData.segBrno(), RiaDefines::RftBranchType::RFT_DEVICE );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -165,6 +221,24 @@ void RifRftSegment::setBranchType( int branchId, RiaDefines::RftBranchType branc
m_branchType[branchId] = branchType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifRftSegment::setOneBasedBranchIndex( int branchId, int oneBasedBranchIndex )
{
m_oneBasedBranchIndexMap[branchId] = oneBasedBranchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RftBranchType RifRftSegment::branchType( int branchId ) const
{
if ( m_branchType.count( branchId ) ) return m_branchType.at( branchId );
return RiaDefines::RftBranchType::RFT_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -182,3 +256,32 @@ std::vector<size_t> RifRftSegment::indicesForBranchNumber( int branchNumber ) co
return v;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RifRftSegment::indicesForBranchIndex( int branchIndex, RiaDefines::RftBranchType branchType ) const
{
std::vector<size_t> v;
for ( size_t i = 0; i < m_topology.size(); i++ )
{
if ( branchIndex <= 0 )
{
v.push_back( i );
continue;
}
auto segment = m_topology[i];
auto it = m_oneBasedBranchIndexMap.find( segment.segBrno() );
if ( it != m_oneBasedBranchIndexMap.end() )
{
if ( it->second == branchIndex && m_branchType.at( segment.segBrno() ) == branchType )
{
v.push_back( i );
}
}
}
return v;
}

View File

@@ -18,13 +18,15 @@
#pragma once
#include "RiaRftDefines.h"
#include "opm/io/eclipse/EclFile.hpp"
#include <set>
#include <string>
#include <tuple>
#include <vector>
#include "RiaRftDefines.h"
#include "opm/io/eclipse/EclFile.hpp"
class RifRftSegmentData
{
public:
@@ -53,13 +55,22 @@ public:
void addResultNameAndSize( const Opm::EclIO::EclFile::EclEntry& resultNameAndSize );
std::vector<Opm::EclIO::EclFile::EclEntry> resultNameAndSize() const;
std::vector<int> tubingBranchIds() const;
std::vector<int> branchIds() const;
std::vector<int> tubingBranchIds() const;
std::vector<int> branchIds() const;
std::set<int> oneBasedBranchIndices() const;
int oneBasedBranchIndexForBranchId( int branchId ) const;
const RifRftSegmentData* segmentData( int segmentNumber ) const;
void createDeviceBranch( int deviceBranchFirstSegmentNumber, int oneBasedBranchIndex );
void setBranchLength( int branchId, double length );
void setBranchType( int branchId, RiaDefines::RftBranchType branchType );
void setOneBasedBranchIndex( int branchId, int oneBasedBranchIndex );
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;
private:
std::vector<RifRftSegmentData> m_topology;
@@ -67,4 +78,5 @@ private:
std::map<int, double> m_branchLength;
std::map<int, RiaDefines::RftBranchType> m_branchType;
std::map<int, int> m_oneBasedBranchIndexMap;
};