Improved simulation well visualization

* Move members to private in RigWellResultPoint
* Create simulation well path geometry using well topology
* Add separate MSW well pipe centerline computations
* Review comments

---------

Co-authored-by: magnesj <magnesj@users.noreply.github.com>
This commit is contained in:
Magne Sjaastad 2023-02-28 16:06:37 +01:00 committed by GitHub
parent 9b12885c23
commit d2f435c00a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 976 additions and 241 deletions

View File

@ -1268,11 +1268,10 @@ size_t localGridCellIndexFromErtConnection( const RigGridBase* grid, const well_
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint( const RigGridBase* grid, RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint( const RigGridBase* grid,
const well_conn_type* ert_connection, const well_conn_type* ert_connection,
int ertBranchId, const well_segment_type* segment,
int ertSegmentId, const char* wellName )
const char* wellName )
{ {
CVF_ASSERT( ert_connection ); CVF_ASSERT( ert_connection );
CVF_ASSERT( grid ); CVF_ASSERT( grid );
@ -1290,25 +1289,47 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint( const RigGridB
if ( gridCellIndex != cvf::UNDEFINED_SIZE_T ) if ( gridCellIndex != cvf::UNDEFINED_SIZE_T )
{ {
resultPoint.m_gridIndex = grid->gridIndex(); int branchId = -1, segmentId = -1, outletBranchId = -1, outletSegmentId = -1;
resultPoint.m_gridCellIndex = gridCellIndex;
resultPoint.m_isOpen = isCellOpen; if ( segment )
{
branchId = well_segment_get_branch_id( segment );
segmentId = well_segment_get_id( segment );
resultPoint.m_ertBranchId = ertBranchId; auto outletSegment = well_segment_get_outlet( segment );
resultPoint.m_ertSegmentId = ertSegmentId; if ( outletSegment )
resultPoint.m_flowRate = volumeRate; {
resultPoint.m_oilRate = oilRate; outletBranchId = well_segment_get_branch_id( outletSegment );
resultPoint.m_waterRate = waterRate; outletSegmentId = well_segment_get_id( outletSegment );
}
}
resultPoint.m_gasRate = RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents( m_eclipseCase->unitsType(), gasRate ); resultPoint.setGridIndex( grid->gridIndex() );
resultPoint.setGridCellIndex( gridCellIndex );
resultPoint.m_connectionFactor = connectionFactor; resultPoint.setIsOpen( isCellOpen );
resultPoint.setSegmentData( branchId, segmentId );
resultPoint.setOutletSegmentData( outletBranchId, outletSegmentId );
const double adjustedGasRate = RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents( m_eclipseCase->unitsType(), gasRate );
resultPoint.setFlowData( volumeRate, oilRate, adjustedGasRate, waterRate );
resultPoint.setConnectionFactor( connectionFactor );
} }
return resultPoint; return resultPoint;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigWellResultPoint
RifReaderEclipseOutput::createWellResultPoint( const RigGridBase* grid, const well_conn_type* ert_connection, const char* wellName )
{
return createWellResultPoint( grid, ert_connection, nullptr, wellName );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Inverse distance interpolation of the supplied points and distance weights for /// Inverse distance interpolation of the supplied points and distance weights for
/// the contributing points which are closest above, and closest below /// the contributing points which are closest above, and closest below
@ -1493,8 +1514,8 @@ public:
{ {
if ( !wellResultPoint.isCell() ) return false; if ( !wellResultPoint.isCell() ) return false;
size_t gridIndex = wellResultPoint.m_gridIndex; size_t gridIndex = wellResultPoint.gridIndex();
size_t gridCellIndex = wellResultPoint.m_gridCellIndex; size_t gridCellIndex = wellResultPoint.cellIndex();
size_t reservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex( gridIndex, gridCellIndex ); size_t reservoirCellIdx = m_mainGrid->reservoirCellIndexByGridAndGridLocalCellIndex( gridIndex, gridCellIndex );
@ -1657,11 +1678,11 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
const well_conn_type* ert_wellhead = well_state_iget_wellhead( ert_well_state, static_cast<int>( gridNr ) ); const well_conn_type* ert_wellhead = well_state_iget_wellhead( ert_well_state, static_cast<int>( gridNr ) );
if ( ert_wellhead ) if ( ert_wellhead )
{ {
wellResFrame.m_wellHead = createWellResultPoint( grids[gridNr], ert_wellhead, -1, -1, wellName ); wellResFrame.m_wellHead = createWellResultPoint( grids[gridNr], ert_wellhead, wellName );
// HACK: Ert returns open as "this is equally wrong as closed for well heads". // HACK: Ert returns open as "this is equally wrong as closed for well heads".
// Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016 // Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016
wellResFrame.m_wellHead.m_isOpen = false; wellResFrame.m_wellHead.setIsOpen( false );
break; break;
} }
} }
@ -1717,7 +1738,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
{ {
well_conn_type* ert_connection = well_conn_collection_iget( connections, connIdx ); well_conn_type* ert_connection = well_conn_collection_iget( connections, connIdx );
wellResultBranch.m_branchResultPoints.push_back( wellResultBranch.m_branchResultPoints.push_back(
createWellResultPoint( grids[gridNr], ert_connection, branchId, well_segment_get_id( segment ), wellName ) ); createWellResultPoint( grids[gridNr], ert_connection, segment, wellName ) );
} }
segmentHasConnections = true; segmentHasConnections = true;
@ -1725,11 +1746,10 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
// Prepare data for segment position calculation // Prepare data for segment position calculation
well_conn_type* ert_connection = well_conn_collection_iget( connections, 0 ); well_conn_type* ert_connection = well_conn_collection_iget( connections, 0 );
RigWellResultPoint point = RigWellResultPoint point = createWellResultPoint( grids[gridNr], ert_connection, segment, wellName );
createWellResultPoint( grids[gridNr], ert_connection, branchId, well_segment_get_id( segment ), wellName ); lastConnectionPos = grids[gridNr]->cell( point.cellIndex() ).center();
lastConnectionPos = grids[gridNr]->cell( point.m_gridCellIndex ).center();
cvf::Vec3d cellVxes[8]; cvf::Vec3d cellVxes[8];
grids[gridNr]->cellCornerVertices( point.m_gridCellIndex, cellVxes ); grids[gridNr]->cellCornerVertices( point.cellIndex(), cellVxes );
lastConnectionCellCorner = cellVxes[0]; lastConnectionCellCorner = cellVxes[0];
lastConnectionCellSize = ( lastConnectionPos - cellVxes[0] ).length(); lastConnectionCellSize = ( lastConnectionPos - cellVxes[0] ).length();
@ -1747,8 +1767,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
if ( !segmentHasConnections ) if ( !segmentHasConnections )
{ {
RigWellResultPoint data; RigWellResultPoint data;
data.m_ertBranchId = branchId; data.setSegmentData( branchId, well_segment_get_id( segment ) );
data.m_ertSegmentId = well_segment_get_id( segment );
wellResultBranch.m_branchResultPoints.push_back( data ); wellResultBranch.m_branchResultPoints.push_back( data );
@ -1801,11 +1820,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
// Select the deepest connection // Select the deepest connection
well_conn_type* ert_connection = well_conn_collection_iget( connections, connectionCount - 1 ); well_conn_type* ert_connection = well_conn_collection_iget( connections, connectionCount - 1 );
auto resultPoint = createWellResultPoint( grids[gridNr], auto resultPoint = createWellResultPoint( grids[gridNr], ert_connection, outletSegment, wellName );
ert_connection,
well_segment_get_branch_id( outletSegment ),
well_segment_get_id( outletSegment ),
wellName );
// This result point is only supposed to be used to indicate connection to a parent well // This result point is only supposed to be used to indicate connection to a parent well
// Clear all flow in this result point // Clear all flow in this result point
resultPoint.clearAllFlow(); resultPoint.clearAllFlow();
@ -1822,8 +1837,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
// Store the result point // Store the result point
RigWellResultPoint data; RigWellResultPoint data;
data.m_ertBranchId = well_segment_get_branch_id( outletSegment ); data.setSegmentData( well_segment_get_branch_id( outletSegment ), well_segment_get_id( outletSegment ) );
data.m_ertSegmentId = well_segment_get_id( outletSegment );
wellResultBranch.m_branchResultPoints.push_back( data ); wellResultBranch.m_branchResultPoints.push_back( data );
// Store data for segment position calculation, // Store data for segment position calculation,
@ -1954,17 +1968,12 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
prevResPoint = wellResultBranch.m_branchResultPoints[rpIdx - 1]; prevResPoint = wellResultBranch.m_branchResultPoints[rpIdx - 1];
} }
cvf::Vec3d lastConnectionPos = grids[prevResPoint.m_gridIndex]->cell( prevResPoint.m_gridCellIndex ).center(); cvf::Vec3d lastConnectionPos = grids[prevResPoint.gridIndex()]->cell( prevResPoint.cellIndex() ).center();
SegmentPositionContribution posContrib( prevResPoint.m_ertSegmentId, SegmentPositionContribution
lastConnectionPos, posContrib( prevResPoint.segmentId(), lastConnectionPos, 0.0, false, -1, prevResPoint.segmentId(), true );
0.0,
false,
-1,
prevResPoint.m_ertSegmentId,
true );
int ertSegmentId = resPoint.m_ertSegmentId; int ertSegmentId = resPoint.segmentId();
std::map<int, std::vector<SegmentPositionContribution>>::iterator posContribIt; std::map<int, std::vector<SegmentPositionContribution>>::iterator posContribIt;
posContribIt = segmentIdToPositionContrib.find( ertSegmentId ); posContribIt = segmentIdToPositionContrib.find( ertSegmentId );
@ -1973,7 +1982,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
std::vector<SegmentPositionContribution> posContributions = posContribIt->second; std::vector<SegmentPositionContribution> posContributions = posContribIt->second;
for ( size_t i = 0; i < posContributions.size(); ++i ) for ( size_t i = 0; i < posContributions.size(); ++i )
{ {
posContributions[i].m_segmentIdAbove = prevResPoint.m_ertSegmentId; posContributions[i].m_segmentIdAbove = prevResPoint.segmentId();
} }
posContributions.push_back( posContrib ); posContributions.push_back( posContrib );
@ -2006,7 +2015,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
RigWellResultPoint& resPoint = wellResultBranch.m_branchResultPoints[rpIdx]; RigWellResultPoint& resPoint = wellResultBranch.m_branchResultPoints[rpIdx];
if ( !resPoint.isCell() ) if ( !resPoint.isCell() )
{ {
resPoint.m_bottomPosition = bottomPositions[resPoint.m_ertSegmentId]; resPoint.setBottomPosition( bottomPositions[resPoint.segmentId()] );
} }
} }
} }
@ -2023,10 +2032,10 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
const well_conn_type* ert_wellhead = well_state_iget_wellhead( ert_well_state, static_cast<int>( gridNr ) ); const well_conn_type* ert_wellhead = well_state_iget_wellhead( ert_well_state, static_cast<int>( gridNr ) );
if ( ert_wellhead ) if ( ert_wellhead )
{ {
RigWellResultPoint wellHeadRp = createWellResultPoint( grids[gridNr], ert_wellhead, -1, -1, wellName ); RigWellResultPoint wellHeadRp = createWellResultPoint( grids[gridNr], ert_wellhead, wellName );
// HACK: Ert returns open as "this is equally wrong as closed for well heads". // HACK: Ert returns open as "this is equally wrong as closed for well heads".
// Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016 // Well heads are not open jfr mail communication with HHGS and JH Statoil 07.01.2016
wellHeadRp.m_isOpen = false; wellHeadRp.setIsOpen( false );
if ( !subCellConnCalc.hasSubCellConnection( wellHeadRp ) ) wellResFrame.m_wellHead = wellHeadRp; if ( !subCellConnCalc.hasSubCellConnection( wellHeadRp ) ) wellResFrame.m_wellHead = wellHeadRp;
} }
@ -2051,7 +2060,7 @@ void RifReaderEclipseOutput::readWellCells( const ecl_grid_type* mainEclGrid, bo
for ( int connIdx = 0; connIdx < connectionCount; connIdx++ ) for ( int connIdx = 0; connIdx < connectionCount; connIdx++ )
{ {
well_conn_type* ert_connection = well_conn_collection_iget( connections, connIdx ); well_conn_type* ert_connection = well_conn_collection_iget( connections, connIdx );
RigWellResultPoint wellRp = createWellResultPoint( grids[gridNr], ert_connection, -1, -1, wellName ); RigWellResultPoint wellRp = createWellResultPoint( grids[gridNr], ert_connection, wellName );
if ( !subCellConnCalc.hasSubCellConnection( wellRp ) ) if ( !subCellConnCalc.hasSubCellConnection( wellRp ) )
{ {

View File

@ -39,9 +39,10 @@ class QDateTime;
struct RigWellResultPoint; struct RigWellResultPoint;
typedef struct ecl_grid_struct ecl_grid_type; typedef struct ecl_grid_struct ecl_grid_type;
typedef struct ecl_file_struct ecl_file_type; typedef struct ecl_file_struct ecl_file_type;
typedef struct well_conn_struct well_conn_type; typedef struct well_conn_struct well_conn_type;
typedef struct well_segment_struct well_segment_type;
//================================================================================================== //==================================================================================================
// //
@ -91,11 +92,12 @@ private:
std::string ertGridName( size_t gridNr ); std::string ertGridName( size_t gridNr );
RigWellResultPoint createWellResultPoint( const RigGridBase* grid, RigWellResultPoint createWellResultPoint( const RigGridBase* grid, const well_conn_type* ert_connection, const char* wellName );
const well_conn_type* ert_connection,
int ertBranchId, RigWellResultPoint createWellResultPoint( const RigGridBase* grid,
int ertSegmentId, const well_conn_type* ert_connection,
const char* wellName ); const well_segment_type* segment,
const char* wellName );
void importFaults( const QStringList& fileSet, cvf::Collection<RigFault>* faults ); void importFaults( const QStringList& fileSet, cvf::Collection<RigFault>* faults );

View File

@ -22,8 +22,11 @@
#include "RiaColorTables.h" #include "RiaColorTables.h"
#include "RiaExtractionTools.h" #include "RiaExtractionTools.h"
#include "RiaPreferences.h"
#include "RigEclipseWellLogExtractor.h" #include "RigEclipseWellLogExtractor.h"
#include "RigMswCenterLineCalculator.h"
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigVirtualPerforationTransmissibilities.h" #include "RigVirtualPerforationTransmissibilities.h"
#include "RigWellLogExtractor.h" #include "RigWellLogExtractor.h"
#include "RigWellPath.h" #include "RigWellPath.h"
@ -154,9 +157,27 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor
m_wellBranches.clear(); m_wellBranches.clear();
m_flattenedBranchWellHeadOffsets.clear(); m_flattenedBranchWellHeadOffsets.clear();
m_pipeBranchesCLCoords.clear(); m_pipeBranchesCLCoords.clear();
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
m_simWellInView->calculateWellPipeStaticCenterLine( m_pipeBranchesCLCoords, pipeBranchesCellIds ); auto createSimWells = []( RimSimWellInView* simWellInView ) -> std::vector<SimulationWellCellBranch> {
std::vector<SimulationWellCellBranch> simWellBranches;
const RigSimWellData* simWellData = simWellInView->simWellData();
if ( simWellData && simWellData->isMultiSegmentWell() )
{
simWellBranches = RigMswCenterLineCalculator::calculateMswWellPipeGeometry( simWellInView );
}
else
{
simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( simWellInView );
}
return simWellBranches;
};
auto simWells = createSimWells( m_simWellInView );
const auto& [coords, wellCells] = RigSimulationWellCenterLineCalculator::extractBranchData( simWells );
m_pipeBranchesCLCoords = coords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds = wellCells;
double pipeRadius = m_simWellInView->pipeRadius(); double pipeRadius = m_simWellInView->pipeRadius();
int crossSectionVertexCount = m_simWellInView->pipeCrossSectionVertexCount(); int crossSectionVertexCount = m_simWellInView->pipeCrossSectionVertexCount();
@ -294,7 +315,7 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor
continue; continue;
} }
if ( !virtualPerforationResult->showConnectionFactorsOnClosedConnections() && !wResCell->m_isOpen ) if ( !virtualPerforationResult->showConnectionFactorsOnClosedConnections() && !wResCell->isOpen() )
{ {
continue; continue;
} }
@ -417,14 +438,14 @@ void RivSimWellPipesPartMgr::updatePipeResultColor( size_t frameIndex )
if ( cellIds[wcIdx].isCell() ) if ( cellIds[wcIdx].isCell() )
{ {
wResCell = wResFrame->findResultCellWellHeadExcluded( cellIds[wcIdx].m_gridIndex, cellIds[wcIdx].m_gridCellIndex ); wResCell = wResFrame->findResultCellWellHeadExcluded( cellIds[wcIdx].gridIndex(), cellIds[wcIdx].cellIndex() );
} }
if ( wResCell ) if ( wResCell )
{ {
double cellState = defaultState; double cellState = defaultState;
if ( wResCell->m_isOpen ) if ( wResCell->isOpen() )
{ {
switch ( wResFrame->m_productionType ) switch ( wResFrame->m_productionType )
{ {

View File

@ -88,13 +88,13 @@ void RivWellSpheresPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelBasicLi
{ {
for ( const RigWellResultPoint& wellResultPoint : wellResultBranch.m_branchResultPoints ) for ( const RigWellResultPoint& wellResultPoint : wellResultBranch.m_branchResultPoints )
{ {
size_t gridIndex = wellResultPoint.m_gridIndex; size_t gridIndex = wellResultPoint.gridIndex();
if ( gridIndex >= mainGrid->gridCount() ) continue; if ( gridIndex >= mainGrid->gridCount() ) continue;
const RigGridBase* rigGrid = mainGrid->gridByIndex( gridIndex ); const RigGridBase* rigGrid = mainGrid->gridByIndex( gridIndex );
size_t gridCellIndex = wellResultPoint.m_gridCellIndex; size_t gridCellIndex = wellResultPoint.cellIndex();
if ( gridCellIndex >= rigGrid->cellCount() ) continue; if ( gridCellIndex >= rigGrid->cellCount() ) continue;
const RigCell& rigCell = rigGrid->cell( gridCellIndex ); const RigCell& rigCell = rigGrid->cell( gridCellIndex );
@ -207,7 +207,7 @@ cvf::Color3f RivWellSpheresPartMgr::wellCellColor( const RigWellResultFrame* wel
if ( wellColl ) if ( wellColl )
{ {
if ( wellResultPoint.m_isOpen ) if ( wellResultPoint.isOpen() )
{ {
switch ( wellResultFrame->m_productionType ) switch ( wellResultFrame->m_productionType )
{ {

View File

@ -21,6 +21,8 @@
#include "RigCell.h" #include "RigCell.h"
#include "RigMainGrid.h" #include "RigMainGrid.h"
#include "RigSimWellData.h" #include "RigSimWellData.h"
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigWellPath.h"
#include "RigWellResultPoint.h" #include "RigWellResultPoint.h"
#include "RimEclipseView.h" #include "RimEclipseView.h"
@ -30,7 +32,6 @@
#include "RimProject.h" #include "RimProject.h"
#include "RimSimWellInView.h" #include "RimSimWellInView.h"
#include "RigWellPath.h"
#include "cafPdmUiDoubleSliderEditor.h" #include "cafPdmUiDoubleSliderEditor.h"
CAF_PDM_SOURCE_INIT( RimSimWellFracture, "SimWellFracture" ); CAF_PDM_SOURCE_INIT( RimSimWellFracture, "SimWellFracture" );
@ -344,14 +345,10 @@ void RimSimWellFracture::computeSimWellBranchCenterLines()
this->firstAncestorOrThisOfType( rimWell ); this->firstAncestorOrThisOfType( rimWell );
CVF_ASSERT( rimWell ); CVF_ASSERT( rimWell );
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords; const auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( rimWell );
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds; for ( const auto& [coords, wellCells] : simWellBranches )
rimWell->calculateWellPipeStaticCenterLine( pipeBranchesCLCoords, pipeBranchesCellIds );
for ( const auto& branch : pipeBranchesCLCoords )
{ {
RigSimulationWellCoordsAndMD wellPathWithMD( branch ); RigSimulationWellCoordsAndMD wellPathWithMD( coords );
m_branchCenterLines.push_back( wellPathWithMD ); m_branchCenterLines.push_back( wellPathWithMD );
} }

View File

@ -191,11 +191,11 @@ std::map<std::string, std::vector<int>> RimFlowDiagSolution::allTracerActiveCell
{ {
for ( const RigWellResultPoint& wrp : wBr.m_branchResultPoints ) for ( const RigWellResultPoint& wrp : wBr.m_branchResultPoints )
{ {
if ( wrp.isValid() && wrp.m_isOpen && if ( wrp.isValid() && wrp.isOpen() &&
( ( useInjectors && wrp.flowRate() < 0.0 ) || ( !useInjectors && wrp.flowRate() > 0.0 ) ) ) ( ( useInjectors && wrp.flowRate() < 0.0 ) || ( !useInjectors && wrp.flowRate() > 0.0 ) ) )
{ {
RigGridBase* grid = mainGrid->gridByIndex( wrp.m_gridIndex ); RigGridBase* grid = mainGrid->gridByIndex( wrp.gridIndex() );
size_t reservoirCellIndex = grid->reservoirCellIndex( wrp.m_gridCellIndex ); size_t reservoirCellIndex = grid->reservoirCellIndex( wrp.cellIndex() );
int cellActiveIndex = static_cast<int>( activeCellInfo->cellResultIndex( reservoirCellIndex ) ); int cellActiveIndex = static_cast<int>( activeCellInfo->cellResultIndex( reservoirCellIndex ) );

View File

@ -454,18 +454,16 @@ RimWellAllocationOverTimeCollection RimWellAllocationOverTimePlot::createWellAll
continue; continue;
} }
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
std::map<QString, const std::vector<double>*> tracerFractionCellValues = std::map<QString, const std::vector<double>*> tracerFractionCellValues =
RimWellAllocationTools::findOrCreateRelevantTracerCellFractions( simWellData, m_flowDiagSolution, i ); RimWellAllocationTools::findOrCreateRelevantTracerCellFractions( simWellData, m_flowDiagSolution, i );
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame( m_case->eclipseCaseData(), auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( m_case->eclipseCaseData(),
simWellData, simWellData,
i, i,
branchDetection, branchDetection,
true, true );
pipeBranchesCLCoords,
pipeBranchesCellIds ); const auto& [pipeBranchesCLCoords, pipeBranchesCellIds] = RigSimulationWellCenterLineCalculator::extractBranchData( simWellBranches );
if ( tracerFractionCellValues.size() ) if ( tracerFractionCellValues.size() )
{ {

View File

@ -246,16 +246,12 @@ void RimWellAllocationPlot::updateFromWell()
if ( !simWellData ) return; if ( !simWellData ) return;
// Set up the Accumulated Well Flow Calculator // Set up the Accumulated Well Flow Calculator
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords; const auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( m_case->eclipseCaseData(),
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds; simWellData,
m_timeStep,
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame( m_case->eclipseCaseData(), m_branchDetection,
simWellData, true );
m_timeStep, const auto& [pipeBranchesCLCoords, pipeBranchesCellIds] = RigSimulationWellCenterLineCalculator::extractBranchData( simWellBranches );
m_branchDetection,
true,
pipeBranchesCLCoords,
pipeBranchesCellIds );
std::map<QString, const std::vector<double>*> tracerFractionCellValues = std::map<QString, const std::vector<double>*> tracerFractionCellValues =
RimWellAllocationTools::findOrCreateRelevantTracerCellFractions( simWellData, m_flowDiagSolution, m_timeStep ); RimWellAllocationTools::findOrCreateRelevantTracerCellFractions( simWellData, m_flowDiagSolution, m_timeStep );

View File

@ -353,15 +353,14 @@ public:
m_pipeBranchMeasuredDepths.push_back( intersections[wpExIdx].endMD ); m_pipeBranchMeasuredDepths.push_back( intersections[wpExIdx].endMD );
RigWellResultPoint resPoint; RigWellResultPoint resPoint;
resPoint.m_isOpen = true; resPoint.setIsOpen( true );
resPoint.m_gridIndex = 0; // Always main grid resPoint.setGridIndex( 0 ); // Always main grid
resPoint.m_gridCellIndex = globCellIdx; // Shortcut, since we only have resPoint.setGridCellIndex( globCellIdx ); // Shortcut, since we only have
// main grid results from RFT // main grid results from RFT
resPoint.m_gasRate = RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents( eclCase->eclipseCaseData()->unitsType(), const double adjustedGasRate =
gasRates[it->second] ); RiaEclipseUnitTools::convertSurfaceGasFlowRateToOilEquivalents( eclCase->eclipseCaseData()->unitsType(), gasRates[it->second] );
resPoint.m_oilRate = oilRates[it->second]; resPoint.setFlowData( -1.0, oilRates[it->second], adjustedGasRate, watRates[it->second] );
resPoint.m_waterRate = watRates[it->second];
m_pipeBranchWellResultPoints.push_back( resPoint ); m_pipeBranchWellResultPoints.push_back( resPoint );
@ -415,8 +414,8 @@ public:
const std::vector<RigWellResultPoint>& branchResPoints = resFrame->m_wellResultBranches[brIdx].m_branchResultPoints; const std::vector<RigWellResultPoint>& branchResPoints = resFrame->m_wellResultBranches[brIdx].m_branchResultPoints;
for ( size_t wrpIdx = 0; wrpIdx < branchResPoints.size(); wrpIdx++ ) for ( size_t wrpIdx = 0; wrpIdx < branchResPoints.size(); wrpIdx++ )
{ {
const RigGridBase* grid = mainGrid->gridByIndex( branchResPoints[wrpIdx].m_gridIndex ); const RigGridBase* grid = mainGrid->gridByIndex( branchResPoints[wrpIdx].gridIndex() );
size_t globalCellIndex = grid->reservoirCellIndex( branchResPoints[wrpIdx].m_gridCellIndex ); size_t globalCellIndex = grid->reservoirCellIndex( branchResPoints[wrpIdx].cellIndex() );
globCellIdxToIdxInSimWellBranch[globalCellIndex] = std::make_pair( brIdx, wrpIdx ); globCellIdxToIdxInSimWellBranch[globalCellIndex] = std::make_pair( brIdx, wrpIdx );
} }

View File

@ -433,7 +433,7 @@ const RigVirtualPerforationTransmissibilities* RimEclipseCase::computeAndGetVirt
if ( r.isCell() ) if ( r.isCell() )
{ {
RigCompletionData compData( wellRes->m_wellName, RigCompletionData compData( wellRes->m_wellName,
RigCompletionDataGridCell( r.m_gridCellIndex, rigEclipseCase->mainGrid() ), RigCompletionDataGridCell( r.cellIndex(), rigEclipseCase->mainGrid() ),
0 ); 0 );
compData.setTransmissibility( r.connectionFactor() ); compData.setTransmissibility( r.connectionFactor() );

View File

@ -1685,14 +1685,14 @@ void RimEclipseView::calculateVisibleWellCellsIncFence( cvf::UByteArray* visible
const std::vector<RigWellResultPoint>& wsResCells = wellResSegments[wsIdx].m_branchResultPoints; const std::vector<RigWellResultPoint>& wsResCells = wellResSegments[wsIdx].m_branchResultPoints;
for ( size_t cIdx = 0; cIdx < wsResCells.size(); ++cIdx ) for ( size_t cIdx = 0; cIdx < wsResCells.size(); ++cIdx )
{ {
if ( wsResCells[cIdx].m_gridIndex == grid->gridIndex() ) if ( wsResCells[cIdx].gridIndex() == grid->gridIndex() )
{ {
if ( !wsResCells[cIdx].isCell() ) if ( !wsResCells[cIdx].isCell() )
{ {
continue; continue;
} }
size_t gridCellIndex = wsResCells[cIdx].m_gridCellIndex; size_t gridCellIndex = wsResCells[cIdx].cellIndex();
( *visibleCells )[gridCellIndex] = true; ( *visibleCells )[gridCellIndex] = true;
// Calculate well fence cells // Calculate well fence cells

View File

@ -192,15 +192,6 @@ std::vector<const RigWellPath*> RimSimWellInView::wellPipeBranches() const
return std::vector<const RigWellPath*>(); return std::vector<const RigWellPath*>();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSimWellInView::calculateWellPipeStaticCenterLine( std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords,
std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds )
{
RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( this, pipeBranchesCLCoords, pipeBranchesCellIds );
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// frameIndex = -1 will use the static well frame /// frameIndex = -1 will use the static well frame
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -340,8 +331,8 @@ bool RimSimWellInView::intersectsWellCellsFilteredCells( const RigWellResultFram
// First check the wellhead: // First check the wellhead:
size_t gridIndex = wrsf->m_wellHead.m_gridIndex; size_t gridIndex = wrsf->m_wellHead.gridIndex();
size_t gridCellIndex = wrsf->m_wellHead.m_gridCellIndex; size_t gridCellIndex = wrsf->m_wellHead.cellIndex();
if ( gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T ) if ( gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T )
{ {
@ -362,8 +353,8 @@ bool RimSimWellInView::intersectsWellCellsFilteredCells( const RigWellResultFram
{ {
if ( wellResultPoint.isCell() ) if ( wellResultPoint.isCell() )
{ {
gridIndex = wellResultPoint.m_gridIndex; gridIndex = wellResultPoint.gridIndex();
gridCellIndex = wellResultPoint.m_gridCellIndex; gridCellIndex = wellResultPoint.cellIndex();
const cvf::UByteArray* cellVisibility = rvMan->cellVisibility( visGridPart, gridIndex, frameIndex ); const cvf::UByteArray* cellVisibility = rvMan->cellVisibility( visGridPart, gridIndex, frameIndex );
if ( gridCellIndex < cellVisibility->size() && ( *cellVisibility )[gridCellIndex] ) if ( gridCellIndex < cellVisibility->size() && ( *cellVisibility )[gridCellIndex] )
@ -770,24 +761,21 @@ void RimSimWellInView::scaleDisk( double minValue, double maxValue )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
cvf::BoundingBox RimSimWellInView::boundingBoxInDomainCoords() const cvf::BoundingBox RimSimWellInView::boundingBoxInDomainCoords() const
{ {
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords; auto noConst = const_cast<RimSimWellInView*>( this );
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds; auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( noConst );
auto noConst = const_cast<RimSimWellInView*>( this );
RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( noConst, pipeBranchesCLCoords, pipeBranchesCellIds );
cvf::BoundingBox bb; cvf::BoundingBox bb;
for ( auto branch : pipeBranchesCLCoords ) for ( const auto& [coords, wellCells] : simWellBranches )
{ {
if ( !branch.empty() ) if ( !coords.empty() )
{ {
// Estimate the bounding box based on first, middle and last coordinate of branches // Estimate the bounding box based on first, middle and last coordinate of branches
bb.add( branch.front() ); bb.add( coords.front() );
size_t mid = branch.size() / 2; size_t mid = coords.size() / 2;
bb.add( branch[mid] ); bb.add( coords[mid] );
bb.add( branch.back() ); bb.add( coords.back() );
} }
} }

View File

@ -76,9 +76,6 @@ public:
std::vector<const RigWellPath*> wellPipeBranches() const; std::vector<const RigWellPath*> wellPipeBranches() const;
void calculateWellPipeStaticCenterLine( std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords,
std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds );
void wellHeadTopBottomPosition( int frameIndex, cvf::Vec3d* top, cvf::Vec3d* bottom ); void wellHeadTopBottomPosition( int frameIndex, cvf::Vec3d* top, cvf::Vec3d* bottom );
double pipeRadius(); double pipeRadius();
int pipeCrossSectionVertexCount(); int pipeCrossSectionVertexCount();

View File

@ -409,9 +409,9 @@ void RimStreamlineInViewCollection::findStartCells( int
{ {
for ( const auto& point : branch.m_branchResultPoints ) for ( const auto& point : branch.m_branchResultPoints )
{ {
if ( point.isValid() && point.m_isOpen ) if ( point.isValid() && point.isOpen() )
{ {
RigCell cell = grids[point.m_gridIndex]->cell( point.m_gridCellIndex ); RigCell cell = grids[point.gridIndex()]->cell( point.cellIndex() );
if ( frame->m_productionType == RiaDefines::WellProductionType::PRODUCER ) if ( frame->m_productionType == RiaDefines::WellProductionType::PRODUCER )
{ {
outProducerCells.push_back( std::pair<QString, RigCell>( swdata->m_wellName, cell ) ); outProducerCells.push_back( std::pair<QString, RigCell>( swdata->m_wellName, cell ) );

View File

@ -96,6 +96,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RigSurfaceStatisticsCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigSurfaceStatisticsCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RigWellLogIndexDepthOffset.h ${CMAKE_CURRENT_LIST_DIR}/RigWellLogIndexDepthOffset.h
${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.h ${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.h
${CMAKE_CURRENT_LIST_DIR}/RigMswCenterLineCalculator.h
) )
set(SOURCE_GROUP_SOURCE_FILES set(SOURCE_GROUP_SOURCE_FILES
@ -189,6 +190,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RigSurfaceStatisticsCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigSurfaceStatisticsCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellLogIndexDepthOffset.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellLogIndexDepthOffset.cpp
${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigPressureDepthData.cpp
${CMAKE_CURRENT_LIST_DIR}/RigMswCenterLineCalculator.cpp
) )
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -711,9 +711,9 @@ std::vector<double> RigAccWellFlowCalculator::calculateWellCellFlowPrTracer( con
if ( m_tracerCellFractionValues ) if ( m_tracerCellFractionValues )
{ {
if ( wellCell.isCell() && wellCell.m_isOpen ) if ( wellCell.isCell() && wellCell.isOpen() )
{ {
size_t resCellIndex = m_cellIndexCalculator.resultCellIndex( wellCell.m_gridIndex, wellCell.m_gridCellIndex ); size_t resCellIndex = m_cellIndexCalculator.resultCellIndex( wellCell.gridIndex(), wellCell.cellIndex() );
size_t tracerIdx = 0; size_t tracerIdx = 0;
double totalTracerFractionInCell = 0.0; double totalTracerFractionInCell = 0.0;
for ( const auto& tracerFractionValsPair : ( *m_tracerCellFractionValues ) ) for ( const auto& tracerFractionValsPair : ( *m_tracerCellFractionValues ) )
@ -768,23 +768,23 @@ std::vector<size_t> RigAccWellFlowCalculator::wrpToUniqueWrpIndexFromBottom( con
if ( clSegIdx < 0 ) return resPointToConnectionIndexFromBottom; if ( clSegIdx < 0 ) return resPointToConnectionIndexFromBottom;
size_t prevGridIdx = branchCells[clSegIdx].m_gridIndex; size_t prevGridIdx = branchCells[clSegIdx].gridIndex();
size_t prevGridCellIdx = branchCells[clSegIdx].m_gridCellIndex; size_t prevGridCellIdx = branchCells[clSegIdx].cellIndex();
int prevErtSegId = branchCells[clSegIdx].m_ertSegmentId; int prevErtSegId = branchCells[clSegIdx].segmentId();
int prevErtBranchId = branchCells[clSegIdx].m_ertBranchId; int prevErtBranchId = branchCells[clSegIdx].branchId();
while ( clSegIdx >= 0 ) while ( clSegIdx >= 0 )
{ {
if ( branchCells[clSegIdx].isValid() && if ( branchCells[clSegIdx].isValid() &&
( branchCells[clSegIdx].m_gridIndex != prevGridIdx || branchCells[clSegIdx].m_gridCellIndex != prevGridCellIdx || ( branchCells[clSegIdx].gridIndex() != prevGridIdx || branchCells[clSegIdx].cellIndex() != prevGridCellIdx ||
branchCells[clSegIdx].m_ertSegmentId != prevErtSegId || branchCells[clSegIdx].m_ertBranchId != prevErtBranchId ) ) branchCells[clSegIdx].segmentId() != prevErtSegId || branchCells[clSegIdx].branchId() != prevErtBranchId ) )
{ {
++connIdxFromBottom; ++connIdxFromBottom;
prevGridIdx = branchCells[clSegIdx].m_gridIndex; prevGridIdx = branchCells[clSegIdx].gridIndex();
prevGridCellIdx = branchCells[clSegIdx].m_gridCellIndex; prevGridCellIdx = branchCells[clSegIdx].cellIndex();
prevErtSegId = branchCells[clSegIdx].m_ertSegmentId; prevErtSegId = branchCells[clSegIdx].segmentId();
prevErtBranchId = branchCells[clSegIdx].m_ertBranchId; prevErtBranchId = branchCells[clSegIdx].branchId();
} }
resPointToConnectionIndexFromBottom[clSegIdx] = connIdxFromBottom; resPointToConnectionIndexFromBottom[clSegIdx] = connIdxFromBottom;
@ -812,10 +812,10 @@ std::vector<size_t> RigAccWellFlowCalculator::findDownStreamBranchIdxs( const Ri
for ( size_t bIdx = 0; bIdx < m_pipeBranchesWellResultPoints.size(); ++bIdx ) for ( size_t bIdx = 0; bIdx < m_pipeBranchesWellResultPoints.size(); ++bIdx )
{ {
if ( m_pipeBranchesWellResultPoints[bIdx][0].m_gridIndex == connectionPoint.m_gridIndex && if ( m_pipeBranchesWellResultPoints[bIdx][0].gridIndex() == connectionPoint.gridIndex() &&
m_pipeBranchesWellResultPoints[bIdx][0].m_gridCellIndex == connectionPoint.m_gridCellIndex && m_pipeBranchesWellResultPoints[bIdx][0].cellIndex() == connectionPoint.cellIndex() &&
m_pipeBranchesWellResultPoints[bIdx][0].m_ertBranchId == connectionPoint.m_ertBranchId && m_pipeBranchesWellResultPoints[bIdx][0].branchId() == connectionPoint.branchId() &&
m_pipeBranchesWellResultPoints[bIdx][0].m_ertSegmentId == connectionPoint.m_ertSegmentId ) m_pipeBranchesWellResultPoints[bIdx][0].segmentId() == connectionPoint.segmentId() )
{ {
downStreamBranchIdxs.push_back( bIdx ); downStreamBranchIdxs.push_back( bIdx );
} }

View File

@ -248,8 +248,8 @@ void RigEclipseCaseData::computeWellCellsPrGrid()
size_t cdIdx; size_t cdIdx;
for ( cdIdx = 0; cdIdx < wellSegment.m_branchResultPoints.size(); ++cdIdx ) for ( cdIdx = 0; cdIdx < wellSegment.m_branchResultPoints.size(); ++cdIdx )
{ {
size_t gridIndex = wellSegment.m_branchResultPoints[cdIdx].m_gridIndex; size_t gridIndex = wellSegment.m_branchResultPoints[cdIdx].gridIndex();
size_t gridCellIndex = wellSegment.m_branchResultPoints[cdIdx].m_gridCellIndex; size_t gridCellIndex = wellSegment.m_branchResultPoints[cdIdx].cellIndex();
if ( gridIndex < m_wellCellsInGrid.size() && gridCellIndex < m_wellCellsInGrid[gridIndex]->size() ) if ( gridIndex < m_wellCellsInGrid.size() && gridCellIndex < m_wellCellsInGrid[gridIndex]->size() )
{ {
@ -340,8 +340,8 @@ const RigCell& RigEclipseCaseData::cellFromWellResultCell( const RigWellResultPo
{ {
CVF_ASSERT( wellResultCell.isCell() ); CVF_ASSERT( wellResultCell.isCell() );
size_t gridIndex = wellResultCell.m_gridIndex; size_t gridIndex = wellResultCell.gridIndex();
size_t gridCellIndex = wellResultCell.m_gridCellIndex; size_t gridCellIndex = wellResultCell.cellIndex();
std::vector<const RigGridBase*> grids; std::vector<const RigGridBase*> grids;
allGrids( &grids ); allGrids( &grids );
@ -356,11 +356,11 @@ bool RigEclipseCaseData::findSharedSourceFace( cvf::StructGridInterface::FaceTyp
const RigWellResultPoint& sourceWellCellResult, const RigWellResultPoint& sourceWellCellResult,
const RigWellResultPoint& otherWellCellResult ) const const RigWellResultPoint& otherWellCellResult ) const
{ {
size_t gridIndex = sourceWellCellResult.m_gridIndex; size_t gridIndex = sourceWellCellResult.gridIndex();
size_t gridCellIndex = sourceWellCellResult.m_gridCellIndex; size_t gridCellIndex = sourceWellCellResult.cellIndex();
size_t otherGridIndex = otherWellCellResult.m_gridIndex; size_t otherGridIndex = otherWellCellResult.gridIndex();
size_t otherGridCellIndex = otherWellCellResult.m_gridCellIndex; size_t otherGridCellIndex = otherWellCellResult.cellIndex();
if ( gridIndex != otherGridIndex ) return false; if ( gridIndex != otherGridIndex ) return false;
@ -504,22 +504,17 @@ std::vector<const RigWellPath*>
if ( m_simWellBranchCache.find( simWellSeachItem ) == m_simWellBranchCache.end() ) if ( m_simWellBranchCache.find( simWellSeachItem ) == m_simWellBranchCache.end() )
{ {
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords; const auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( this,
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds; simWellData,
-1,
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame( this, useAutoDetectionOfBranches,
simWellData, includeAllCellCenters );
-1,
useAutoDetectionOfBranches,
includeAllCellCenters,
pipeBranchesCLCoords,
pipeBranchesCellIds );
m_simWellBranchCache.insert( std::make_pair( simWellSeachItem, cvf::Collection<RigWellPath>() ) ); m_simWellBranchCache.insert( std::make_pair( simWellSeachItem, cvf::Collection<RigWellPath>() ) );
for ( size_t brIdx = 0; brIdx < pipeBranchesCLCoords.size(); ++brIdx ) for ( const auto& [coords, wellCells] : simWellBranches )
{ {
auto wellMdCalculator = RigSimulationWellCoordsAndMD( pipeBranchesCLCoords[brIdx] ); auto wellMdCalculator = RigSimulationWellCoordsAndMD( coords );
cvf::ref<RigWellPath> newWellPath = new RigWellPath( wellMdCalculator.wellPathPoints(), wellMdCalculator.measuredDepths() ); cvf::ref<RigWellPath> newWellPath = new RigWellPath( wellMdCalculator.wellPathPoints(), wellMdCalculator.measuredDepths() );

View File

@ -0,0 +1,342 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "RigMswCenterLineCalculator.h"
#include "RiaLogging.h"
#include "RigCell.h"
#include "RigCellFaceGeometryTools.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigSimWellData.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimSimWellInView.h"
#include "RimSimWellInViewCollection.h"
#include "cvfRay.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SimulationWellCellBranch> RigMswCenterLineCalculator::calculateMswWellPipeGeometry( RimSimWellInView* rimWell )
{
CVF_ASSERT( rimWell );
const RigSimWellData* simWellData = rimWell->simWellData();
if ( !simWellData ) return {};
RimEclipseView* eclipseView;
rimWell->firstAncestorOrThisOfType( eclipseView );
CVF_ASSERT( eclipseView );
if ( eclipseView->eclipseCase() && eclipseView->eclipseCase()->eclipseCaseData() )
{
auto eclipseCaseData = eclipseView->eclipseCase()->eclipseCaseData();
int timeStepIndex = eclipseView->currentTimeStep();
return calculateMswWellPipeGeometryForTimeStep( eclipseCaseData, simWellData, timeStepIndex );
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SimulationWellCellBranch>
RigMswCenterLineCalculator::calculateMswWellPipeGeometryForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* wellResults,
int timeStepIndex )
{
if ( timeStepIndex >= 0 && !wellResults->hasAnyValidCells( timeStepIndex ) ) return {};
const RigWellResultFrame* wellFramePtr = nullptr;
if ( timeStepIndex < 0 )
{
wellFramePtr = wellResults->staticWellCells();
}
else
{
wellFramePtr = wellResults->wellResultFrame( timeStepIndex );
}
const RigWellResultFrame& wellFrame = *wellFramePtr;
const std::vector<RigWellResultBranch>& resultBranches = wellFrame.m_wellResultBranches;
std::vector<WellBranch> wellBranches = mergeShortBranchesIntoLongBranches( resultBranches );
// Connect outlet segment of branches to parent branch
for ( const auto& resultBranch : resultBranches )
{
if ( resultBranch.m_branchResultPoints.empty() ) continue;
const auto firstResultPoint = resultBranch.m_branchResultPoints.front();
for ( auto& wellBranch : wellBranches )
{
if ( wellBranch.m_branchId == resultBranch.m_ertBranchId )
{
if ( firstResultPoint.branchId() == resultBranch.m_ertBranchId )
{
// The first result point is on the same branch, use well head as outlet
RigWellResultPoint outletResultPoint = wellFrame.m_wellHead;
auto gridAndCellIndex = std::make_pair( outletResultPoint.gridIndex(), outletResultPoint.cellIndex() );
wellBranch.m_segmentsWithGridCells[outletResultPoint.segmentId()].push_back( gridAndCellIndex );
}
else
{
// The first result point on a different branch. Find the branch and add the grid cell
for ( const auto& candidateResultBranch : wellBranches )
{
if ( firstResultPoint.branchId() == candidateResultBranch.m_branchId )
{
std::pair<size_t, size_t> gridAndCellIndexForTieIn;
for ( const auto& [segment, gridAndCellIndices] : candidateResultBranch.m_segmentsWithGridCells )
{
if ( segment > firstResultPoint.segmentId() ) continue;
if ( !gridAndCellIndices.empty() )
{
gridAndCellIndexForTieIn = gridAndCellIndices.front();
}
}
wellBranch.m_segmentsWithGridCells[firstResultPoint.segmentId()].push_back( gridAndCellIndexForTieIn );
}
}
}
}
}
}
std::vector<SimulationWellCellBranch> simWellBranches;
for ( const auto& wellBranch : wellBranches )
{
std::vector<cvf::Vec3d> cellCenterCoords;
std::vector<RigWellResultPoint> cellCenterResultPoints;
if ( wellBranch.m_branchId == 1 && !wellBranch.m_segmentsWithGridCells.empty() )
{
const auto& [firstSegment, gridAndCellIndices] = *wellBranch.m_segmentsWithGridCells.begin();
if ( !gridAndCellIndices.empty() )
{
const auto& [gridIndex, cellIndex] = gridAndCellIndices.front();
if ( gridIndex < eclipseCaseData->gridCount() && cellIndex < eclipseCaseData->grid( gridIndex )->cellCount() )
{
const RigCell& cell = eclipseCaseData->grid( gridIndex )->cell( cellIndex );
cvf::Vec3d whStartPos = cell.faceCenter( cvf::StructGridInterface::NEG_K );
// Add extra coordinate between cell face and cell center
// to make sure the well pipe terminated in a segment parallel to z-axis
cvf::Vec3d whIntermediate = whStartPos;
whIntermediate.z() = ( whStartPos.z() + cell.center().z() ) / 2.0;
RigWellResultPoint resPoint;
for ( const auto& resBranch : resultBranches )
{
for ( const auto& respoint : resBranch.m_branchResultPoints )
{
if ( respoint.segmentId() == firstSegment )
{
resPoint = respoint;
break;
}
}
}
cellCenterCoords.push_back( whStartPos );
cellCenterResultPoints.push_back( resPoint );
cellCenterCoords.push_back( whIntermediate );
cellCenterResultPoints.push_back( resPoint );
}
}
}
for ( const auto& [segmentId, gridAndCellIndices] : wellBranch.m_segmentsWithGridCells )
{
for ( const auto& [gridIndex, cellIndex] : gridAndCellIndices )
{
if ( gridIndex < eclipseCaseData->gridCount() && cellIndex < eclipseCaseData->grid( gridIndex )->cellCount() )
{
const RigCell& cell = eclipseCaseData->grid( gridIndex )->cell( cellIndex );
cvf::Vec3d pos = cell.center();
RigWellResultPoint resPoint;
// The result point is only used to transport the grid index and cell index
// The current implementation will propagate the cell open state to the well segment from one cell to
// the next.
resPoint.setGridIndex( gridIndex );
resPoint.setGridCellIndex( cellIndex );
cellCenterCoords.push_back( pos );
cellCenterResultPoints.push_back( resPoint );
}
}
}
const auto simWellBranch = addCoordsAtCellFaceIntersectionsAndCreateBranch( cellCenterCoords, cellCenterResultPoints, eclipseCaseData );
simWellBranches.emplace_back( simWellBranch );
}
return simWellBranches;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SimulationWellCellBranch
RigMswCenterLineCalculator::addCoordsAtCellFaceIntersectionsAndCreateBranch( const std::vector<cvf::Vec3d> branchCoords,
const std::vector<RigWellResultPoint>& resultPoints,
const RigEclipseCaseData* eclipseCaseData )
{
std::vector<cvf::Vec3d> adjustedCoords;
std::vector<RigWellResultPoint> adjustedResPoints;
RigWellResultPoint previusPoint;
for ( size_t resPointIdx = 0; resPointIdx < resultPoints.size(); resPointIdx++ )
{
if ( resPointIdx >= branchCoords.size() ) continue;
const auto& currentPoint = resultPoints[resPointIdx];
const auto& currentCellCenter = branchCoords[resPointIdx];
if ( previusPoint.isCell() )
{
const RigCell& prevCell = eclipseCaseData->cellFromWellResultCell( previusPoint );
const cvf::Vec3d previousCellCenter = prevCell.center();
{
// Insert extra coordinate at the location where the well path is leaving the previous cell
cvf::Ray rayToThisCell;
rayToThisCell.setOrigin( previousCellCenter );
rayToThisCell.setDirection( ( currentCellCenter - previousCellCenter ).getNormalized() );
cvf::Vec3d outOfPrevCell( previousCellCenter );
prevCell.firstIntersectionPoint( rayToThisCell, &outOfPrevCell );
if ( ( currentCellCenter - outOfPrevCell ).lengthSquared() > 1e-3 )
{
adjustedCoords.push_back( outOfPrevCell );
adjustedResPoints.push_back( RigWellResultPoint() );
}
}
if ( currentPoint.isCell() )
{
// Insert extra coordinate at the location where the well path is entering the current cell
const RigCell& currentCell = eclipseCaseData->cellFromWellResultCell( currentPoint );
cvf::Ray rayFromThisCell;
rayFromThisCell.setOrigin( currentCellCenter );
rayFromThisCell.setDirection( ( previousCellCenter - currentCellCenter ).getNormalized() );
cvf::Vec3d outOfCurrentCell( currentCellCenter );
currentCell.firstIntersectionPoint( rayFromThisCell, &outOfCurrentCell );
if ( ( currentCellCenter - outOfCurrentCell ).lengthSquared() > 1e-3 )
{
adjustedCoords.push_back( outOfCurrentCell );
adjustedResPoints.push_back( currentPoint );
}
}
}
adjustedResPoints.push_back( currentPoint );
adjustedCoords.push_back( currentCellCenter );
previusPoint = currentPoint;
}
// Duplicate last coord to make sure we have N+1 coordinates for N result points
adjustedCoords.push_back( adjustedCoords.back() );
return { adjustedCoords, adjustedResPoints };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigMswCenterLineCalculator::WellBranch>
RigMswCenterLineCalculator::mergeShortBranchesIntoLongBranches( const std::vector<RigWellResultBranch>& resBranches )
{
std::vector<WellBranch> longWellBranches;
std::vector<WellBranch> shortWellBranches;
for ( const auto& resultBranch : resBranches )
{
WellBranch branch;
branch.m_branchId = resultBranch.m_ertBranchId;
for ( const auto& resPoint : resultBranch.m_branchResultPoints )
{
size_t gridIndex = resPoint.gridIndex();
size_t gridCellIndex = resPoint.cellIndex();
auto gridAndCellIndex = std::make_pair( gridIndex, gridCellIndex );
if ( gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T && !branch.containsGridCell( gridAndCellIndex ) )
{
OutputSegment outputSegment{ resPoint.outletSegmentId(), resPoint.outletBranchId() };
branch.m_gridCellsConnectedToSegments[gridAndCellIndex] = outputSegment;
branch.m_segmentsWithGridCells[resPoint.segmentId()].push_back( gridAndCellIndex );
}
}
const int resultPointThreshold = 3;
if ( resultBranch.m_branchResultPoints.size() > resultPointThreshold )
{
longWellBranches.push_back( branch );
}
else
{
shortWellBranches.push_back( branch );
}
}
// Move all grid cells of small branch to the long branch
for ( const auto& branch : shortWellBranches )
{
if ( branch.m_gridCellsConnectedToSegments.empty() ) continue;
const auto& outputSegment = branch.m_gridCellsConnectedToSegments.begin()->second;
for ( auto& longBranch : longWellBranches )
{
if ( longBranch.m_branchId == outputSegment.outputSegmentBranchId )
{
for ( const auto& [gridAndCellIndex, localOutputSegment] : branch.m_gridCellsConnectedToSegments )
{
longBranch.m_segmentsWithGridCells[outputSegment.outputSegmentId].push_back( gridAndCellIndex );
}
}
}
}
return longWellBranches;
}

View File

@ -0,0 +1,78 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "RigWellResultPoint.h"
#include "cvfVector3.h"
#include <map>
#include <vector>
class RigEclipseCaseData;
class RimSimWellInView;
class RigSimWellData;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class RigMswCenterLineCalculator
{
public:
static std::vector<SimulationWellCellBranch> calculateMswWellPipeGeometry( RimSimWellInView* rimWell );
private:
struct OutputSegment
{
int outputSegmentId = -1;
int outputSegmentBranchId = -1;
};
struct WellBranch
{
int m_branchId = -1;
std::map<std::pair<size_t, size_t>, OutputSegment> m_gridCellsConnectedToSegments;
std::map<int, std::vector<std::pair<size_t, size_t>>> m_segmentsWithGridCells;
bool containsGridCell( const std::pair<size_t, size_t>& candidateGridAndCellIndex ) const
{
for ( const auto& [segmentId, gridAndCellIndex] : m_segmentsWithGridCells )
{
if ( std::find( gridAndCellIndex.begin(), gridAndCellIndex.end(), candidateGridAndCellIndex ) != gridAndCellIndex.end() )
{
return true;
}
}
return false;
};
};
private:
static std::vector<SimulationWellCellBranch> calculateMswWellPipeGeometryForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* simWellData,
int timeStepIndex );
static SimulationWellCellBranch addCoordsAtCellFaceIntersectionsAndCreateBranch( const std::vector<cvf::Vec3d> branchCoords,
const std::vector<RigWellResultPoint>& resultPoints,
const RigEclipseCaseData* eclipseCaseData );
static std::vector<WellBranch> mergeShortBranchesIntoLongBranches( const std::vector<RigWellResultBranch>& resBranches );
};

View File

@ -396,8 +396,8 @@ void RigReservoirBuilderMock::addWellData( RigEclipseCaseData* eclipseCase, RigG
wellCells.m_productionType = RiaDefines::WellProductionType::PRODUCER; wellCells.m_productionType = RiaDefines::WellProductionType::PRODUCER;
wellCells.m_isOpen = true; wellCells.m_isOpen = true;
wellCells.m_wellHead.m_gridIndex = 0; wellCells.m_wellHead.setGridIndex( 0 );
wellCells.m_wellHead.m_gridCellIndex = grid->cellIndexFromIJK( 1, 0, 0 ); wellCells.m_wellHead.setGridCellIndex( grid->cellIndexFromIJK( 1, 0, 0 ) );
// Connections // Connections
// int connectionCount = std::min(dim.x(), std::min(dim.y(), dim.z())) - 2; // int connectionCount = std::min(dim.x(), std::min(dim.y(), dim.z())) - 2;
@ -414,53 +414,53 @@ void RigReservoirBuilderMock::addWellData( RigEclipseCaseData* eclipseCase, RigG
if ( connIdx == ( size_t )( connectionCount / 4 ) ) continue; if ( connIdx == ( size_t )( connectionCount / 4 ) ) continue;
RigWellResultPoint data; RigWellResultPoint data;
data.m_gridIndex = 0; data.setGridIndex( 0 );
if ( connIdx < dim.y() - 2 ) if ( connIdx < dim.y() - 2 )
data.m_gridCellIndex = grid->cellIndexFromIJK( 1, 1 + connIdx, 1 + connIdx ); data.setGridCellIndex( grid->cellIndexFromIJK( 1, 1 + connIdx, 1 + connIdx ) );
else else
data.m_gridCellIndex = grid->cellIndexFromIJK( 1, dim.y() - 2, 1 + connIdx ); data.setGridCellIndex( grid->cellIndexFromIJK( 1, dim.y() - 2, 1 + connIdx ) );
if ( connIdx < connectionCount / 2 ) if ( connIdx < connectionCount / 2 )
{ {
data.m_isOpen = true; data.setIsOpen( true );
} }
else else
{ {
data.m_isOpen = false; data.setIsOpen( false );
} }
if ( wellSegment.m_branchResultPoints.size() == 0 || if ( wellSegment.m_branchResultPoints.size() == 0 ||
wellSegment.m_branchResultPoints.back().m_gridCellIndex != data.m_gridCellIndex ) wellSegment.m_branchResultPoints.back().cellIndex() != data.cellIndex() )
{ {
wellSegment.m_branchResultPoints.push_back( data ); wellSegment.m_branchResultPoints.push_back( data );
if ( connIdx == connectionCount / 2 ) if ( connIdx == connectionCount / 2 )
{ {
RigWellResultPoint deadEndData = data; RigWellResultPoint deadEndData = data;
deadEndData.m_gridCellIndex = data.m_gridCellIndex + 1; deadEndData.setGridCellIndex( data.cellIndex() + 1 );
deadEndData.m_isOpen = true; deadEndData.setIsOpen( true );
RigWellResultPoint deadEndData1 = data; RigWellResultPoint deadEndData1 = data;
deadEndData1.m_gridCellIndex = data.m_gridCellIndex + 2; deadEndData1.setGridCellIndex( data.cellIndex() + 2 );
deadEndData1.m_isOpen = false; deadEndData1.setIsOpen( false );
wellSegment.m_branchResultPoints.push_back( deadEndData ); wellSegment.m_branchResultPoints.push_back( deadEndData );
wellSegment.m_branchResultPoints.push_back( deadEndData1 ); wellSegment.m_branchResultPoints.push_back( deadEndData1 );
wellSegment.m_branchResultPoints.push_back( deadEndData ); wellSegment.m_branchResultPoints.push_back( deadEndData );
data.m_isOpen = true; data.setIsOpen( true );
wellSegment.m_branchResultPoints.push_back( data ); wellSegment.m_branchResultPoints.push_back( data );
} }
} }
if ( connIdx < dim.y() - 2 ) if ( connIdx < dim.y() - 2 )
{ {
data.m_gridCellIndex = grid->cellIndexFromIJK( 1, 1 + connIdx, 2 + connIdx ); data.setGridCellIndex( grid->cellIndexFromIJK( 1, 1 + connIdx, 2 + connIdx ) );
if ( wellSegment.m_branchResultPoints.size() == 0 || if ( wellSegment.m_branchResultPoints.size() == 0 ||
wellSegment.m_branchResultPoints.back().m_gridCellIndex != data.m_gridCellIndex ) wellSegment.m_branchResultPoints.back().cellIndex() != data.cellIndex() )
{ {
wellSegment.m_branchResultPoints.push_back( data ); wellSegment.m_branchResultPoints.push_back( data );
} }

View File

@ -138,11 +138,11 @@ bool RigSimWellData::hasAnyValidCells( size_t resultTimeStepIndex ) const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool operator==( const RigWellResultPoint& p1, const RigWellResultPoint& p2 ) bool operator==( const RigWellResultPoint& p1, const RigWellResultPoint& p2 )
{ {
return p1.m_gridIndex == p2.m_gridIndex && p1.m_gridCellIndex == p2.m_gridCellIndex && p1.m_ertBranchId == p2.m_ertBranchId && // TODO : Remove when <=> operator has been added to RigWellResultPoint
p1.m_ertSegmentId == p2.m_ertSegmentId; return p1.gridIndex() == p2.gridIndex() && p1.cellIndex() == p2.cellIndex() && p1.branchId() == p2.branchId() &&
p1.segmentId() == p2.segmentId();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -369,7 +369,7 @@ const RigWellResultPoint* RigWellResultFrame::findResultCellWellHeadIncluded( si
// This behavior was different prior to release 2019.04 and was rendered as a closed connection (gray) // This behavior was different prior to release 2019.04 and was rendered as a closed connection (gray)
// https://github.com/OPM/ResInsight/issues/712 // https://github.com/OPM/ResInsight/issues/712
if ( m_wellHead.m_gridCellIndex == gridCellIndex && m_wellHead.m_gridIndex == gridIndex ) if ( m_wellHead.cellIndex() == gridCellIndex && m_wellHead.gridIndex() == gridIndex )
{ {
return &m_wellHead; return &m_wellHead;
} }
@ -388,8 +388,8 @@ const RigWellResultPoint* RigWellResultFrame::findResultCellWellHeadExcluded( si
{ {
for ( size_t wc = 0; wc < m_wellResultBranches[wb].m_branchResultPoints.size(); ++wc ) for ( size_t wc = 0; wc < m_wellResultBranches[wb].m_branchResultPoints.size(); ++wc )
{ {
if ( m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridCellIndex == gridCellIndex && if ( m_wellResultBranches[wb].m_branchResultPoints[wc].cellIndex() == gridCellIndex &&
m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridIndex == gridIndex ) m_wellResultBranches[wb].m_branchResultPoints[wc].gridIndex() == gridIndex )
{ {
return &( m_wellResultBranches[wb].m_branchResultPoints[wc] ); return &( m_wellResultBranches[wb].m_branchResultPoints[wc] );
} }

View File

@ -19,6 +19,8 @@
#include "RigSimulationWellCenterLineCalculator.h" #include "RigSimulationWellCenterLineCalculator.h"
#include "RiaLogging.h"
#include "RigCell.h" #include "RigCell.h"
#include "RigCellFaceGeometryTools.h" #include "RigCellFaceGeometryTools.h"
#include "RigEclipseCaseData.h" #include "RigEclipseCaseData.h"
@ -38,6 +40,79 @@
#include <deque> #include <deque>
#include <list> #include <list>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SimulationWellCellBranch> RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( RimSimWellInView* rimWell )
{
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
calculateWellPipeStaticCenterline( rimWell, pipeBranchesCLCoords, pipeBranchesCellIds );
std::vector<SimulationWellCellBranch> simuationBranches;
for ( size_t i = 0; i < pipeBranchesCLCoords.size(); i++ )
{
if ( i < pipeBranchesCellIds.size() )
{
simuationBranches.emplace_back( std::make_pair( pipeBranchesCLCoords[i], pipeBranchesCellIds[i] ) );
}
}
return simuationBranches;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SimulationWellCellBranch>
RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* simWellData,
int timeStepIndex,
bool isAutoDetectBranches,
bool useAllCellCenters )
{
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
calculateWellPipeCenterlineForTimeStep( eclipseCaseData,
simWellData,
timeStepIndex,
isAutoDetectBranches,
useAllCellCenters,
pipeBranchesCLCoords,
pipeBranchesCellIds );
std::vector<SimulationWellCellBranch> simuationBranches;
for ( size_t i = 0; i < pipeBranchesCLCoords.size(); i++ )
{
if ( i < pipeBranchesCellIds.size() )
{
simuationBranches.emplace_back( std::make_pair( pipeBranchesCLCoords[i], pipeBranchesCellIds[i] ) );
}
}
return simuationBranches;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<std::vector<cvf::Vec3d>>, std::vector<std::vector<RigWellResultPoint>>>
RigSimulationWellCenterLineCalculator::extractBranchData( const std::vector<SimulationWellCellBranch> simulationBranch )
{
std::vector<std::vector<cvf::Vec3d>> pipeBranchesCLCoords;
std::vector<std::vector<RigWellResultPoint>> pipeBranchesCellIds;
for ( const auto& [coords, wellCells] : simulationBranch )
{
pipeBranchesCLCoords.emplace_back( coords );
pipeBranchesCellIds.emplace_back( wellCells );
}
return { pipeBranchesCLCoords, pipeBranchesCellIds };
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Based on the points and cells, calculate a pipe centerline /// Based on the points and cells, calculate a pipe centerline
/// The returned CellIds is one less than the number of centerline points, /// The returned CellIds is one less than the number of centerline points,
@ -63,13 +138,56 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( R
bool useAllCellCenters = rimWell->isUsingCellCenterForPipe(); bool useAllCellCenters = rimWell->isUsingCellCenterForPipe();
int timeStepIndex = -1; int timeStepIndex = -1;
calculateWellPipeCenterlineFromWellFrame( eclipseCaseData, calculateWellPipeCenterlineForTimeStep( eclipseCaseData,
simWellData, simWellData,
timeStepIndex, timeStepIndex,
isAutoDetectBranches, isAutoDetectBranches,
useAllCellCenters, useAllCellCenters,
pipeBranchesCLCoords, pipeBranchesCLCoords,
pipeBranchesCellIds ); pipeBranchesCellIds );
// DEBUG output, please keep code
bool printDebug = false;
if ( printDebug )
{
QString txt;
for ( size_t idx = 0; idx < pipeBranchesCellIds.size(); idx++ )
{
const auto& branchCells = pipeBranchesCellIds[idx];
for ( const auto& resultPoint : branchCells )
{
QString myTxt;
int fieldWidth = 3;
myTxt += QString( "Ri branch index: %1 " ).arg( idx, fieldWidth );
myTxt += QString( "Seg: %1 Branch: %2 " ).arg( resultPoint.segmentId(), fieldWidth ).arg( resultPoint.branchId(), fieldWidth );
if ( resultPoint.isCell() )
{
size_t i = 0, j = 0, k = 0;
auto grid = eclipseCaseData->grid( resultPoint.gridIndex() );
grid->ijkFromCellIndex( resultPoint.cellIndex(), &i, &j, &k );
myTxt += QString( "Grid %1 %2 %3 " ).arg( i + 1, fieldWidth ).arg( j + 1, fieldWidth ).arg( k + 1, fieldWidth );
}
myTxt += QString( "OutSeg: %1 OutBranch: %2 " )
.arg( resultPoint.outletSegmentId(), fieldWidth )
.arg( resultPoint.outletBranchId(), fieldWidth );
int coordFieldWidth = 12;
myTxt += QString( "Bottom pos: %1 %2 %3 " )
.arg( resultPoint.bottomPosition().x(), coordFieldWidth )
.arg( resultPoint.bottomPosition().y(), coordFieldWidth )
.arg( resultPoint.bottomPosition().z(), coordFieldWidth );
myTxt += "\n";
txt += myTxt;
}
}
RiaLogging::debug( txt );
}
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -77,14 +195,13 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeStaticCenterline( R
/// The returned CellIds is one less than the number of centerline points, /// The returned CellIds is one less than the number of centerline points,
/// and are describing the lines between the points, starting with the first line /// and are describing the lines between the points, starting with the first line
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellFrame( void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigEclipseCaseData* eclipseCaseData, const RigSimWellData* wellResults,
const RigSimWellData* wellResults, int timeStepIndex,
int timeStepIndex, bool isAutoDetectBranches,
bool isAutoDetectBranches, bool useAllCellCenters,
bool useAllCellCenters, std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords,
std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords, std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds )
std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds )
{ {
// Initialize the return arrays // Initialize the return arrays
pipeBranchesCLCoords.clear(); pipeBranchesCLCoords.clear();
@ -200,7 +317,7 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellF
// Use the interpolated value of branch head // Use the interpolated value of branch head
CVF_ASSERT( currentWellResPoint.isPointValid() ); CVF_ASSERT( currentWellResPoint.isPointValid() );
cvf::Vec3d currentPoint = currentWellResPoint.m_bottomPosition; cvf::Vec3d currentPoint = currentWellResPoint.bottomPosition();
// If we have a real previous cell, we need to go out of it, before adding the current point // If we have a real previous cell, we need to go out of it, before adding the current point
// That is: add a CL-point describing where it leaves the previous cell. // That is: add a CL-point describing where it leaves the previous cell.
@ -273,7 +390,7 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellF
} }
else else
{ {
centerPreviousCell = prevWellResPoint->m_bottomPosition; centerPreviousCell = prevWellResPoint->bottomPosition();
} }
distanceToWellHeadIsLonger = ( centerThisCell - centerPreviousCell ).lengthSquared() <= distanceToWellHeadIsLonger = ( centerThisCell - centerPreviousCell ).lengthSquared() <=
@ -378,7 +495,7 @@ void RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineFromWellF
else if ( prevWellResPoint && prevWellResPoint->isPointValid() ) else if ( prevWellResPoint && prevWellResPoint->isPointValid() )
{ {
// Continue the line with the same point, just to keep the last Cell ID // Continue the line with the same point, just to keep the last Cell ID
pipeBranchesCLCoords.back().push_back( prevWellResPoint->m_bottomPosition ); pipeBranchesCLCoords.back().push_back( prevWellResPoint->bottomPosition() );
} }
else else
{ {
@ -660,7 +777,7 @@ private:
const RigCell& whCell = m_eclipseCaseData->cellFromWellResultCell( m_orgWellResultFrame.wellHeadOrStartCell() ); const RigCell& whCell = m_eclipseCaseData->cellFromWellResultCell( m_orgWellResultFrame.wellHeadOrStartCell() );
cvf::Vec3d whStartPos = whCell.faceCenter( cvf::StructGridInterface::NEG_K ); cvf::Vec3d whStartPos = whCell.faceCenter( cvf::StructGridInterface::NEG_K );
wellHeadAsPoint.m_bottomPosition = whStartPos; wellHeadAsPoint.setBottomPosition( whStartPos );
m_branchedWell.m_wellResultBranches[branchIdx].m_branchResultPoints.push_back( wellHeadAsPoint ); m_branchedWell.m_wellResultBranches[branchIdx].m_branchResultPoints.push_back( wellHeadAsPoint );
} }
@ -694,7 +811,7 @@ private:
} }
} }
branchStartAsResultPoint.m_bottomPosition = branchStartPos; branchStartAsResultPoint.setBottomPosition( branchStartPos );
m_branchedWell.m_wellResultBranches[branchIdx].m_branchResultPoints.push_back( branchStartAsResultPoint ); m_branchedWell.m_wellResultBranches[branchIdx].m_branchResultPoints.push_back( branchStartAsResultPoint );
} }
else else

View File

@ -19,8 +19,11 @@
#pragma once #pragma once
#include "RigWellResultPoint.h"
#include "cvfVector3.h" #include "cvfVector3.h"
#include <map>
#include <vector> #include <vector>
class RigEclipseCaseData; class RigEclipseCaseData;
@ -36,19 +39,38 @@ class RigWellResultFrame;
class RigSimulationWellCenterLineCalculator class RigSimulationWellCenterLineCalculator
{ {
public: public:
static std::vector<SimulationWellCellBranch> calculateWellPipeStaticCenterline( RimSimWellInView* rimWell );
static std::vector<SimulationWellCellBranch> calculateWellPipeCenterlineForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* simWellData,
int timeStepIndex,
bool isAutoDetectBranches,
bool useAllCellCenters );
static std::pair<std::vector<std::vector<cvf::Vec3d>>, std::vector<std::vector<RigWellResultPoint>>>
extractBranchData( const std::vector<SimulationWellCellBranch> simulationBranch );
private:
static void calculateWellPipeStaticCenterline( RimSimWellInView* rimWell, static void calculateWellPipeStaticCenterline( RimSimWellInView* rimWell,
std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords, std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords,
std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds ); std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds );
static void calculateWellPipeCenterlineFromWellFrame( const RigEclipseCaseData* eclipseCaseData, static void calculateWellPipeCenterlineForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* simWellData, const RigSimWellData* simWellData,
int timeStepIndex, int timeStepIndex,
bool isAutoDetectBranches, bool isAutoDetectBranches,
bool useAllCellCenters, bool useAllCellCenters,
std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords, std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords,
std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds ); std::vector<std::vector<RigWellResultPoint>>& pipeBranchesCellIds );
static std::vector<SimulationWellCellBranch> calculateMswWellPipeGeometryForTimeStep( const RigEclipseCaseData* eclipseCaseData,
const RigSimWellData* simWellData,
int timeStepIndex );
static SimulationWellCellBranch addSegmentsToCellFaces( const std::vector<cvf::Vec3d> branchCoords,
const std::vector<RigWellResultPoint>& resultPoints,
const RigEclipseCaseData* eclipseCaseData );
private:
static bool hasAnyValidDataCells( const RigWellResultBranch& branch ); static bool hasAnyValidDataCells( const RigWellResultBranch& branch );
static void finishPipeCenterLine( std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords, const cvf::Vec3d& lastCellCenter ); static void finishPipeCenterLine( std::vector<std::vector<cvf::Vec3d>>& pipeBranchesCLCoords, const cvf::Vec3d& lastCellCenter );

View File

@ -23,10 +23,12 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RigWellResultPoint::RigWellResultPoint() RigWellResultPoint::RigWellResultPoint()
: m_gridIndex( cvf::UNDEFINED_SIZE_T ) : m_gridIndex( cvf::UNDEFINED_SIZE_T )
, m_gridCellIndex( cvf::UNDEFINED_SIZE_T ) , m_cellIndex( cvf::UNDEFINED_SIZE_T )
, m_isOpen( false ) , m_isOpen( false )
, m_ertBranchId( -1 ) , m_ertBranchId( -1 )
, m_ertSegmentId( -1 ) , m_ertSegmentId( -1 )
, m_ertOutletBranchId( -1 )
, m_ertOutletSegmentId( -1 )
, m_bottomPosition( cvf::Vec3d::UNDEFINED ) , m_bottomPosition( cvf::Vec3d::UNDEFINED )
, m_flowRate( 0.0 ) , m_flowRate( 0.0 )
, m_oilRate( 0.0 ) , m_oilRate( 0.0 )
@ -36,6 +38,75 @@ RigWellResultPoint::RigWellResultPoint()
{ {
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setGridIndex( size_t gridIndex )
{
m_gridIndex = gridIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setGridCellIndex( size_t cellIndex )
{
m_cellIndex = cellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setIsOpen( bool isOpen )
{
m_isOpen = isOpen;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setFlowData( double flowRate, double oilRate, double gasRate, double waterRate )
{
m_flowRate = flowRate;
m_oilRate = oilRate;
m_gasRate = gasRate;
m_waterRate = waterRate;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setConnectionFactor( double connectionFactor )
{
m_connectionFactor = connectionFactor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setSegmentData( int branchId, int segmentId )
{
m_ertBranchId = branchId;
m_ertSegmentId = segmentId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setOutletSegmentData( int outletBranchId, int outletSegmentId )
{
m_ertOutletBranchId = outletBranchId;
m_ertOutletSegmentId = outletSegmentId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellResultPoint::setBottomPosition( const cvf::Vec3d& bottomPosition )
{
m_bottomPosition = bottomPosition;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,7 +120,7 @@ bool RigWellResultPoint::isPointValid() const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RigWellResultPoint::isCell() const bool RigWellResultPoint::isCell() const
{ {
return m_gridCellIndex != cvf::UNDEFINED_SIZE_T; return m_cellIndex != cvf::UNDEFINED_SIZE_T;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -60,12 +131,20 @@ bool RigWellResultPoint::isValid() const
return isCell() || isPointValid(); return isCell() || isPointValid();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigWellResultPoint::isOpen() const
{
return m_isOpen;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RigWellResultPoint::isEqual( const RigWellResultPoint& other ) const bool RigWellResultPoint::isEqual( const RigWellResultPoint& other ) const
{ {
return ( m_gridIndex == other.m_gridIndex && m_gridCellIndex == other.m_gridCellIndex && m_isOpen == other.m_isOpen && return ( m_gridIndex == other.m_gridIndex && m_cellIndex == other.m_cellIndex && m_isOpen == other.m_isOpen &&
m_ertBranchId == other.m_ertBranchId && m_ertSegmentId == other.m_ertSegmentId && m_flowRate == other.m_flowRate && m_ertBranchId == other.m_ertBranchId && m_ertSegmentId == other.m_ertSegmentId && m_flowRate == other.m_flowRate &&
m_oilRate == other.m_oilRate && m_gasRate == other.m_gasRate && m_waterRate == other.m_waterRate ); m_oilRate == other.m_oilRate && m_gasRate == other.m_gasRate && m_waterRate == other.m_waterRate );
} }
@ -149,3 +228,59 @@ void RigWellResultPoint::clearAllFlow()
m_gasRate = 0.0; m_gasRate = 0.0;
m_waterRate = 0.0; m_waterRate = 0.0;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigWellResultPoint::gridIndex() const
{
return m_gridIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigWellResultPoint::cellIndex() const
{
return m_cellIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigWellResultPoint::branchId() const
{
return m_ertBranchId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigWellResultPoint::segmentId() const
{
return m_ertSegmentId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigWellResultPoint::outletBranchId() const
{
return m_ertOutletBranchId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigWellResultPoint::outletSegmentId() const
{
return m_ertOutletSegmentId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RigWellResultPoint::bottomPosition() const
{
return m_bottomPosition;
}

View File

@ -34,9 +34,21 @@ struct RigWellResultPoint
{ {
RigWellResultPoint(); RigWellResultPoint();
void setGridIndex( size_t gridIndex );
void setGridCellIndex( size_t cellIndex );
void setIsOpen( bool isOpen );
void setFlowData( double flowRate, double oilRate, double gasRate, double waterRate );
void setConnectionFactor( double connectionFactor );
void setSegmentData( int branchId, int segmentId );
void setOutletSegmentData( int outletBranchId, int outletSegmentId );
void setBottomPosition( const cvf::Vec3d& bottomPosition );
bool isPointValid() const; bool isPointValid() const;
bool isCell() const; bool isCell() const;
bool isValid() const; bool isValid() const;
bool isOpen() const;
bool isEqual( const RigWellResultPoint& other ) const; bool isEqual( const RigWellResultPoint& other ) const;
double flowRate() const; double flowRate() const;
@ -46,12 +58,25 @@ struct RigWellResultPoint
double connectionFactor() const; double connectionFactor() const;
void clearAllFlow(); void clearAllFlow();
size_t gridIndex() const;
size_t cellIndex() const;
int branchId() const;
int segmentId() const;
int outletBranchId() const;
int outletSegmentId() const;
cvf::Vec3d bottomPosition() const;
private:
size_t m_gridIndex; size_t m_gridIndex;
size_t m_gridCellIndex; //< Index to cell which is included in the well size_t m_cellIndex; //< Index to cell which is included in the well
bool m_isOpen; //< Marks the well as open or closed as of Eclipse simulation bool m_isOpen; //< Marks the well as open or closed as of Eclipse simulation
int m_ertBranchId; int m_ertBranchId;
int m_ertSegmentId; int m_ertSegmentId;
int m_ertOutletBranchId;
int m_ertOutletSegmentId;
cvf::Vec3d m_bottomPosition; //< The estimated bottom position of the well segment, when we have no grid cell cvf::Vec3d m_bottomPosition; //< The estimated bottom position of the well segment, when we have no grid cell
// connections for the segment. // connections for the segment.
@ -103,3 +128,5 @@ public:
std::vector<RigWellResultBranch> m_wellResultBranches; std::vector<RigWellResultBranch> m_wellResultBranches;
}; };
using SimulationWellCellBranch = std::pair<std::vector<cvf::Vec3d>, std::vector<RigWellResultPoint>>;

View File

@ -295,11 +295,11 @@ public:
size_t i; size_t i;
size_t j; size_t j;
size_t k; size_t k;
size_t gridIdx = resPoint.m_gridIndex; size_t gridIdx = resPoint.gridIndex();
grids[gridIdx]->ijkFromCellIndex( resPoint.m_gridCellIndex, &i, &j, &k ); grids[gridIdx]->ijkFromCellIndex( resPoint.cellIndex(), &i, &j, &k );
bool isOpen = resPoint.m_isOpen; bool isOpen = resPoint.isOpen();
int branchId = resPoint.m_ertBranchId; int branchId = resPoint.branchId();
int segmentId = resPoint.m_ertSegmentId; int segmentId = resPoint.segmentId();
cellIs.push_back( static_cast<qint32>( i + 1 ) ); // NB: 1-based index in Octave cellIs.push_back( static_cast<qint32>( i + 1 ) ); // NB: 1-based index in Octave
cellJs.push_back( static_cast<qint32>( j + 1 ) ); // NB: 1-based index in Octave cellJs.push_back( static_cast<qint32>( j + 1 ) ); // NB: 1-based index in Octave

View File

@ -1155,24 +1155,34 @@ QString RiuResultTextBuilder::wellResultText()
if ( m_eclResDef->eclipseCase() && m_eclResDef->eclipseCase()->eclipseCaseData() ) if ( m_eclResDef->eclipseCase() && m_eclResDef->eclipseCase()->eclipseCaseData() )
{ {
cvf::Collection<RigSimWellData> simWellData = m_eclResDef->eclipseCase()->eclipseCaseData()->wellResults(); cvf::Collection<RigSimWellData> simWellData = m_eclResDef->eclipseCase()->eclipseCaseData()->wellResults();
for ( size_t i = 0; i < simWellData.size(); i++ ) for ( const auto& singleWellResultData : simWellData )
{ {
RigSimWellData* singleWellResultData = simWellData.at( i );
if ( !singleWellResultData->hasWellResult( m_timeStepIndex ) ) if ( !singleWellResultData->hasWellResult( m_timeStepIndex ) )
{ {
continue; continue;
} }
const RigWellResultFrame* wellResultFrame = singleWellResultData->wellResultFrame( m_timeStepIndex ); const RigWellResultFrame* wellResultFrame = singleWellResultData->wellResultFrame( m_timeStepIndex );
const RigWellResultPoint* wellResultCell = wellResultFrame->findResultCellWellHeadIncluded( m_gridIndex, m_cellIndex ); if ( !wellResultFrame )
{
continue;
}
const RigWellResultPoint* wellResultCell = wellResultFrame->findResultCellWellHeadIncluded( m_gridIndex, m_cellIndex );
if ( wellResultCell ) if ( wellResultCell )
{ {
const int branchId = wellResultCell->branchId();
const int segmentId = wellResultCell->segmentId();
const int outletBranchId = wellResultCell->outletBranchId();
const int outletSegmentId = wellResultCell->outletSegmentId();
text += QString( "-- Well-cell connection info --\n Well Name: %1\n Branch Id: %2\n Segment " text += QString( "-- Well-cell connection info --\n Well Name: %1\n Branch Id: %2\n Segment "
"Id: %3\n" ) "Id: %3\n Outlet Branch Id: %4\n Outlet Segment Id: %5" )
.arg( singleWellResultData->m_wellName ) .arg( singleWellResultData->m_wellName )
.arg( wellResultCell->m_ertBranchId ) .arg( branchId )
.arg( wellResultCell->m_ertSegmentId ); .arg( segmentId )
.arg( outletBranchId )
.arg( outletSegmentId );
} }
} }
} }

View File

@ -125,8 +125,8 @@ grpc::Status RiaGrpcSimulationWellService::GetSimulationWellCells( grpc::ServerC
size_t i; size_t i;
size_t j; size_t j;
size_t k; size_t k;
size_t gridIdx = resPoint.m_gridIndex; const size_t gridIdx = resPoint.gridIndex();
grids[gridIdx]->ijkFromCellIndex( resPoint.m_gridCellIndex, &i, &j, &k ); grids[gridIdx]->ijkFromCellIndex( resPoint.cellIndex(), &i, &j, &k );
Vec3i* ijk = new Vec3i; Vec3i* ijk = new Vec3i;
ijk->set_i( i ); ijk->set_i( i );
@ -135,9 +135,9 @@ grpc::Status RiaGrpcSimulationWellService::GetSimulationWellCells( grpc::ServerC
cellInfo->set_allocated_ijk( ijk ); cellInfo->set_allocated_ijk( ijk );
cellInfo->set_grid_index( gridIdx ); cellInfo->set_grid_index( gridIdx );
cellInfo->set_is_open( resPoint.m_isOpen ); cellInfo->set_is_open( resPoint.isOpen() );
cellInfo->set_branch_id( resPoint.m_ertBranchId ); cellInfo->set_branch_id( resPoint.branchId() );
cellInfo->set_segment_id( resPoint.m_ertSegmentId ); cellInfo->set_segment_id( resPoint.segmentId() );
} }
} }
} }