From d47d4060cc17b028550ac910889c8fbe6c2d31f5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 2 Mar 2023 13:06:38 +0100 Subject: [PATCH] Add valve visualization to MSW wells * Refactor geo generator * Add valve visualization to segments that are connected to a valve --- .../RivFishbonesSubsPartMgr.cpp | 10 +- .../RivPipeGeometryGenerator.cpp | 38 ++- .../RivPipeGeometryGenerator.h | 19 +- .../RivSimWellPipesPartMgr.cpp | 286 ++++++++++++++---- .../RivSimWellPipesPartMgr.h | 44 ++- .../RivWellFracturePartMgr.cpp | 9 +- .../ModelVisualization/RivWellPathPartMgr.cpp | 158 +++++----- .../ModelVisualization/RivWellPathPartMgr.h | 3 +- .../ProjectDataModel/RimSimWellInView.cpp | 37 +++ .../ProjectDataModel/RimSimWellInView.h | 1 + .../RimSimWellInViewCollection.cpp | 14 +- .../RimSimWellInViewCollection.h | 3 + .../RigMswCenterLineCalculator.cpp | 9 + .../RigMswCenterLineCalculator.h | 1 + .../ReservoirDataModel/RigWellResultPoint.cpp | 17 ++ .../ReservoirDataModel/RigWellResultPoint.h | 3 + 16 files changed, 452 insertions(+), 200 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp index 27eb026d04..f347a3a9d6 100644 --- a/ApplicationLibCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivFishbonesSubsPartMgr.cpp @@ -87,18 +87,16 @@ void RivFishbonesSubsPartMgr::buildParts( const caf::DisplayCoordTransform* disp RimWellPath* wellPath = nullptr; m_rimFishbonesSubs->firstAncestorOrThisOfTypeAsserted( wellPath ); - RivPipeGeometryGenerator geoGenerator; - for ( const auto& [subIndex, lateralIndex] : m_rimFishbonesSubs->installedLateralIndices() ) { std::vector lateralDomainCoords = m_rimFishbonesSubs->coordsForLateral( subIndex, lateralIndex ); std::vector displayCoords = displayCoordTransform->transformToDisplayCoords( lateralDomainCoords ); - geoGenerator.cylinderWithCenterLineParts( &m_parts, - displayCoords, - m_rimFishbonesSubs->fishbonesColor(), - wellPath->combinedScaleFactor() * characteristicCellSize * 0.5 ); + RivPipeGeometryGenerator::cylinderWithCenterLineParts( &m_parts, + displayCoords, + m_rimFishbonesSubs->fishbonesColor(), + wellPath->combinedScaleFactor() * characteristicCellSize * 0.5 ); } cvf::ref objectSourceInfo = new RivObjectSourceInfo( m_rimFishbonesSubs ); diff --git a/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.cpp index 17dbadbb14..46c8f33a4a 100644 --- a/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.cpp @@ -57,6 +57,14 @@ void RivPipeGeometryGenerator::setPipeCenterCoords( const cvf::Vec3dArray* coord clearComputedData(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::cref RivPipeGeometryGenerator::pipeCenterCoords() const +{ + return m_originalPipeCenterCoords.p(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -273,7 +281,7 @@ cvf::ref RivPipeGeometryGenerator::generateExtrudedCylinder( d size_t i; for ( i = 0; i < extrudedNodes.size(); i++ ) { - crossSectionVertices.push_back( cvf::Vec3f( extrudedNodes[i] ) ); + crossSectionVertices.emplace_back( extrudedNodes[i] ); } // Calculate first valid pipe direction, to be able to handle centerNodes in the same place @@ -435,9 +443,9 @@ cvf::ref RivPipeGeometryGenerator::generateVariableRadiusTube( std::vector cylinderSegmentNormals; // Insert the first set of vertices - for ( size_t i = 0; i < lastExtrudedNodes.size(); i++ ) + for ( const auto& lastExtrudedNode : lastExtrudedNodes ) { - crossSectionVertices.push_back( cvf::Vec3f( lastExtrudedNodes[i] ) ); + crossSectionVertices.emplace_back( lastExtrudedNode ); } // Loop along the cylinder center coords and calculate the cross section vertexes in each center vertex @@ -500,7 +508,7 @@ cvf::ref RivPipeGeometryGenerator::generateVariableRadiusTube( cvf::Vec3f circleDir = ( nextNodeAlongCircle - lastNodeAlongCircle ).getNormalized(); cvf::Vec3f segmentNormal = ( wellDirectionDir ^ circleDir ).getNormalized(); - crossSectionVertices.push_back( cvf::Vec3f( nextNodeAlongWellPath ) ); + crossSectionVertices.emplace_back( nextNodeAlongWellPath ); cylinderSegmentNormals.push_back( segmentNormal ); } @@ -629,7 +637,7 @@ void RivPipeGeometryGenerator::computeExtrudedCoordsAndNormals( cvf::Vec3d void RivPipeGeometryGenerator::updateFilteredPipeCenterCoords() { if ( m_originalPipeCenterCoords->size() < 2 ) return; - if ( m_filteredPipeCenterCoords.size() > 0 ) return; + if ( !m_filteredPipeCenterCoords.empty() ) return; double squareDistanceTolerance = 1e-4 * 1e-4; @@ -778,13 +786,15 @@ void RivPipeGeometryGenerator::cylinderWithCenterLineParts( cvf::Collection cvfCoords = new cvf::Vec3dArray( centerCoords ); - setPipeCenterCoords( cvfCoords.p() ); + geoGenerator.setPipeCenterCoords( cvfCoords.p() ); - cvf::ref surfaceGeo = createPipeSurface(); + cvf::ref surfaceGeo = geoGenerator.createPipeSurface(); if ( surfaceGeo.notNull() ) { cvf::Part* part = new cvf::Part; @@ -799,7 +809,7 @@ void RivPipeGeometryGenerator::cylinderWithCenterLineParts( cvf::Collectionpush_back( part ); } - cvf::ref centerLineGeo = createCenterLine(); + cvf::ref centerLineGeo = geoGenerator.createCenterLine(); if ( centerLineGeo.notNull() ) { cvf::Part* part = new cvf::Part; @@ -823,12 +833,10 @@ void RivPipeGeometryGenerator::tubeWithCenterLinePartsAndVariableWidth( cvf::Col const std::vector& radii, const cvf::Color3f& color ) { - setCrossSectionVertexCount( 12 ); - cvf::ref activeCoords = new cvf::Vec3dArray( centerCoords ); - setPipeCenterCoords( activeCoords.p() ); - cvf::ref surfaceGeo = generateVariableRadiusTube( m_crossSectionNodeCount, activeCoords.p(), radii ); + const size_t crossSectionNodeCount = 12; + cvf::ref surfaceGeo = generateVariableRadiusTube( crossSectionNodeCount, activeCoords.p(), radii ); if ( surfaceGeo.notNull() ) { @@ -844,7 +852,7 @@ void RivPipeGeometryGenerator::tubeWithCenterLinePartsAndVariableWidth( cvf::Col destinationParts->push_back( part ); } - cvf::ref centerLineGeo = createCenterLine(); + cvf::ref centerLineGeo = generateLine( activeCoords.p() ); if ( centerLineGeo.notNull() ) { cvf::Part* part = new cvf::Part; diff --git a/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.h index b61e3b685f..9cd1a182f3 100644 --- a/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/RivPipeGeometryGenerator.h @@ -42,7 +42,8 @@ public: ~RivPipeGeometryGenerator() override; // Coordinates and orientations - void setPipeCenterCoords( const cvf::Vec3dArray* coords ); + void setPipeCenterCoords( const cvf::Vec3dArray* coords ); + cvf::cref pipeCenterCoords() const; // Appearance void setRadius( double radius ); @@ -59,15 +60,15 @@ public: void setFirstVisibleSegmentIndex( size_t segmentIndex ); size_t segmentIndexFromTriangleIndex( size_t triangleIndex ) const; - void cylinderWithCenterLineParts( cvf::Collection* destinationParts, - const std::vector& centerCoords, - const cvf::Color3f& color, - double radius ); + static void cylinderWithCenterLineParts( cvf::Collection* destinationParts, + const std::vector& centerCoords, + const cvf::Color3f& color, + double radius ); - void tubeWithCenterLinePartsAndVariableWidth( cvf::Collection* destinationParts, - const std::vector& centerCoords, - const std::vector& radii, - const cvf::Color3f& color ); + static void tubeWithCenterLinePartsAndVariableWidth( cvf::Collection* destinationParts, + const std::vector& centerCoords, + const std::vector& radii, + const cvf::Color3f& color ); private: void clearComputedData(); diff --git a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp index 9daa02aa1f..8532b551f3 100644 --- a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.cpp @@ -33,6 +33,7 @@ #include "RigWellResultPoint.h" #include "Rim3dView.h" +#include "RimCase.h" #include "RimEclipseView.h" #include "RimRegularLegendConfig.h" #include "RimSimWellInView.h" @@ -50,10 +51,14 @@ #include "cafEffectGenerator.h" #include "cvfDrawableGeo.h" +#include "cvfGeometryBuilderDrawableGeo.h" +#include "cvfGeometryUtils.h" #include "cvfModelBasicList.h" #include "cvfPart.h" #include "cvfScalarMapperDiscreteLinear.h" +#include + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -110,6 +115,11 @@ void RivSimWellPipesPartMgr::appendDynamicGeometryPartsToModel( cvf::ModelBasicL { model->addPart( it->m_connectionFactorsPart.p() ); } + + for ( auto valvePart : it->m_valveParts ) + { + model->addPart( valvePart.p() ); + } } } @@ -156,7 +166,6 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor m_wellBranches.clear(); m_flattenedBranchWellHeadOffsets.clear(); - m_pipeBranchesCLCoords.clear(); auto createSimWells = []( RimSimWellInView* simWellInView ) -> std::vector { std::vector simWellBranches; @@ -176,8 +185,8 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor auto simWells = createSimWells( m_simWellInView ); const auto& [coords, wellCells] = RigSimulationWellCenterLineCalculator::extractBranchData( simWells ); - m_pipeBranchesCLCoords = coords; - std::vector> pipeBranchesCellIds = wellCells; + auto pipeBranchesCLCoords = coords; + auto pipeBranchesCellIds = wellCells; double pipeRadius = m_simWellInView->pipeRadius(); int crossSectionVertexCount = m_simWellInView->pipeCrossSectionVertexCount(); @@ -185,7 +194,7 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor // Take branch selection into account size_t branchIdxStart = 0; size_t branchIdxStop = pipeBranchesCellIds.size(); - if ( m_pipeBranchesCLCoords.size() > 1 ) + if ( pipeBranchesCLCoords.size() > 1 ) { if ( branchIndex >= 0 && branchIndex < static_cast( branchIdxStop ) ) { @@ -195,16 +204,16 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor } cvf::Vec3d flattenedStartOffset = cvf::Vec3d::ZERO; - if ( m_pipeBranchesCLCoords.size() > branchIdxStart && m_pipeBranchesCLCoords[branchIdxStart].size() ) + if ( pipeBranchesCLCoords.size() > branchIdxStart && !pipeBranchesCLCoords[branchIdxStart].empty() ) { - flattenedStartOffset = { 0.0, 0.0, m_pipeBranchesCLCoords[branchIdxStart][0].z() }; + flattenedStartOffset = { 0.0, 0.0, pipeBranchesCLCoords[branchIdxStart][0].z() }; } for ( size_t brIdx = branchIdxStart; brIdx < branchIdxStop; ++brIdx ) { cvf::ref sourceInfo = new RivSimWellPipeSourceInfo( m_simWellInView, brIdx ); - m_wellBranches.push_back( RivPipeBranchData() ); + m_wellBranches.emplace_back(); RivPipeBranchData& pbd = m_wellBranches.back(); pbd.m_cellIds = pipeBranchesCellIds[brIdx]; @@ -215,15 +224,15 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor pbd.m_pipeGeomGenerator->setCrossSectionVertexCount( crossSectionVertexCount ); cvf::ref cvfCoords = new cvf::Vec3dArray; - cvfCoords->assign( m_pipeBranchesCLCoords[brIdx] ); + cvfCoords->assign( pipeBranchesCLCoords[brIdx] ); - flattenedStartOffset.z() = m_pipeBranchesCLCoords[brIdx][0].z(); + flattenedStartOffset.z() = pipeBranchesCLCoords[brIdx][0].z(); m_flattenedBranchWellHeadOffsets.push_back( flattenedStartOffset.x() ); if ( doFlatten ) { - std::vector flatningCSs = RivSectionFlattener::calculateFlatteningCSsForPolyline( m_pipeBranchesCLCoords[brIdx], + std::vector flatningCSs = RivSectionFlattener::calculateFlatteningCSsForPolyline( pipeBranchesCLCoords[brIdx], cvf::Vec3d::Z_AXIS, flattenedStartOffset, &flattenedStartOffset ); @@ -280,93 +289,238 @@ void RivSimWellPipesPartMgr::buildWellPipeParts( const caf::DisplayCoordTransfor pbd.m_connectionFactorGeometryGenerator = nullptr; pbd.m_connectionFactorsPart = nullptr; + pbd.m_valveParts.clear(); RimEclipseView* eclipseView = nullptr; m_simWellInView->firstAncestorOrThisOfType( eclipseView ); - if ( eclipseView && eclipseView->isVirtualConnectionFactorGeometryVisible() ) + appendVirtualConnectionFactorGeo( eclipseView, frameIndex, brIdx, displayXf, pipeRadius, pbd ); + appendValvesGeo( eclipseView, frameIndex, brIdx, displayXf, pipeRadius, pbd ); + + if ( doFlatten ) flattenedStartOffset += { 2 * flattenedIntersectionExtentLength, 0.0, 0.0 }; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivSimWellPipesPartMgr::appendVirtualConnectionFactorGeo( const RimEclipseView* eclipseView, + size_t frameIndex, + size_t brIdx, + const caf::DisplayCoordTransform* displayXf, + double pipeRadius, + RivPipeBranchData& pbd ) +{ + if ( eclipseView && eclipseView->isVirtualConnectionFactorGeometryVisible() ) + { + RigSimWellData* simWellData = m_simWellInView->simWellData(); + + if ( simWellData && simWellData->hasWellResult( frameIndex ) ) { - RigSimWellData* simWellData = m_simWellInView->simWellData(); + const RigWellResultFrame* wResFrame = simWellData->wellResultFrame( frameIndex ); - if ( simWellData && simWellData->hasWellResult( frameIndex ) ) + std::vector completionVizDataItems; + + RimVirtualPerforationResults* virtualPerforationResult = eclipseView->virtualPerforationResult(); { - const RigWellResultFrame* wResFrame = simWellData->wellResultFrame( frameIndex ); + auto wellPaths = m_simWellInView->wellPipeBranches(); - std::vector completionVizDataItems; + const RigWellPath* wellPath = wellPaths[brIdx]; - RimVirtualPerforationResults* virtualPerforationResult = eclipseView->virtualPerforationResult(); + RigEclipseWellLogExtractor* extractor = RiaExtractionTools::findOrCreateSimWellExtractor( m_simWellInView, wellPath ); + if ( extractor ) { - auto wellPaths = m_simWellInView->wellPipeBranches(); + std::vector wellPathCellIntersections = extractor->cellIntersectionInfosAlongWellPath(); - const RigWellPath* wellPath = wellPaths[brIdx]; - - RigEclipseWellLogExtractor* extractor = RiaExtractionTools::findOrCreateSimWellExtractor( m_simWellInView, wellPath ); - if ( extractor ) + for ( const auto& intersectionInfo : wellPathCellIntersections ) { - std::vector wellPathCellIntersections = extractor->cellIntersectionInfosAlongWellPath(); + size_t globalCellIndex = intersectionInfo.globCellIndex; + const RigWellResultPoint* wResCell = wResFrame->findResultCellWellHeadIncluded( 0, globalCellIndex ); - for ( const auto& intersectionInfo : wellPathCellIntersections ) + if ( !wResCell || !wResCell->isValid() ) { - size_t globalCellIndex = intersectionInfo.globCellIndex; - const RigWellResultPoint* wResCell = wResFrame->findResultCellWellHeadIncluded( 0, globalCellIndex ); + continue; + } - if ( !wResCell || !wResCell->isValid() ) - { - continue; - } + if ( !virtualPerforationResult->showConnectionFactorsOnClosedConnections() && !wResCell->isOpen() ) + { + continue; + } - if ( !virtualPerforationResult->showConnectionFactorsOnClosedConnections() && !wResCell->isOpen() ) - { - continue; - } + double startMD = intersectionInfo.startMD; + double endMD = intersectionInfo.endMD; - double startMD = intersectionInfo.startMD; - double endMD = intersectionInfo.endMD; + double middleMD = ( startMD + endMD ) / 2.0; - double middleMD = ( startMD + endMD ) / 2.0; + cvf::Vec3d domainCoord = wellPath->interpolatedPointAlongWellPath( middleMD ); - cvf::Vec3d domainCoord = wellPath->interpolatedPointAlongWellPath( middleMD ); + cvf::Vec3d p1; + cvf::Vec3d p2; + wellPath->twoClosestPoints( domainCoord, &p1, &p2 ); - cvf::Vec3d p1; - cvf::Vec3d p2; - wellPath->twoClosestPoints( domainCoord, &p1, &p2 ); + cvf::Vec3d direction = ( p2 - p1 ).getNormalized(); - cvf::Vec3d direction = ( p2 - p1 ).getNormalized(); + cvf::Vec3d anchor = displayXf->transformToDisplayCoord( domainCoord ); + { + CompletionVizData data( anchor, direction, wResCell->connectionFactor(), globalCellIndex ); - cvf::Vec3d anchor = displayXf->transformToDisplayCoord( domainCoord ); - { - CompletionVizData data( anchor, direction, wResCell->connectionFactor(), globalCellIndex ); - - completionVizDataItems.push_back( data ); - } + completionVizDataItems.push_back( data ); } } } + } - if ( !completionVizDataItems.empty() ) + if ( !completionVizDataItems.empty() ) + { + double radius = pipeRadius * virtualPerforationResult->geometryScaleFactor(); + radius *= 2.0; // Enlarge the radius slightly to make the connection factor visible if geometry + // scale factor is set to 1.0 + + pbd.m_connectionFactorGeometryGenerator = new RivWellConnectionFactorGeometryGenerator( completionVizDataItems, radius ); + + cvf::ScalarMapper* scalarMapper = virtualPerforationResult->legendConfig()->scalarMapper(); + cvf::ref part = + pbd.m_connectionFactorGeometryGenerator->createSurfacePart( scalarMapper, eclipseView->isLightingDisabled() ); + if ( part.notNull() ) { - double radius = pipeRadius * virtualPerforationResult->geometryScaleFactor(); - radius *= 2.0; // Enlarge the radius slightly to make the connection factor visible if geometry - // scale factor is set to 1.0 - - pbd.m_connectionFactorGeometryGenerator = new RivWellConnectionFactorGeometryGenerator( completionVizDataItems, radius ); - - cvf::ScalarMapper* scalarMapper = virtualPerforationResult->legendConfig()->scalarMapper(); - cvf::ref part = - pbd.m_connectionFactorGeometryGenerator->createSurfacePart( scalarMapper, eclipseView->isLightingDisabled() ); - if ( part.notNull() ) - { - cvf::ref simWellSourceInfo = - new RivSimWellConnectionSourceInfo( m_simWellInView, pbd.m_connectionFactorGeometryGenerator.p() ); - part->setSourceInfo( simWellSourceInfo.p() ); - } - - pbd.m_connectionFactorsPart = part; + cvf::ref simWellSourceInfo = + new RivSimWellConnectionSourceInfo( m_simWellInView, pbd.m_connectionFactorGeometryGenerator.p() ); + part->setSourceInfo( simWellSourceInfo.p() ); } + + pbd.m_connectionFactorsPart = part; } } + } +} - if ( doFlatten ) flattenedStartOffset += { 2 * flattenedIntersectionExtentLength, 0.0, 0.0 }; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivSimWellPipesPartMgr::appendValvesGeo( const RimEclipseView* eclipseView, + size_t frameIndex, + size_t brIdx, + const caf::DisplayCoordTransform* displayXf, + double wellPathRadius, + RivPipeBranchData& pbd ) +{ + if ( !m_simWellInView || !m_simWellInView->isWellValvesVisible( frameIndex ) ) return; + if ( !eclipseView || !eclipseView->ownerCase() ) return; + + const auto characteristicCellSize = eclipseView->ownerCase()->characteristicCellSize(); + const auto coords = pbd.m_pipeGeomGenerator->pipeCenterCoords(); + + std::set> resultPointWithValve; + for ( size_t i = 0; i < pbd.m_cellIds.size(); i++ ) + { + const auto resultPoint = pbd.m_cellIds[i]; + + if ( resultPointWithValve.contains( { resultPoint.gridIndex(), resultPoint.cellIndex() } ) ) continue; + + const auto segmentStartCoord = coords->get( i ); + const auto segmentEndCoord = coords->get( i + 1 ); + const auto segmentLength = ( segmentEndCoord - segmentStartCoord ).length(); + const double valveLength = characteristicCellSize * 0.2; + + // Insert valve geometry if the length of the segment is sufficient + if ( resultPoint.isConnectedToValve() && ( valveLength * 2 < segmentLength ) ) + { + resultPointWithValve.insert( { resultPoint.gridIndex(), resultPoint.cellIndex() } ); + + const auto segmentDirection = ( segmentEndCoord - segmentStartCoord ).getNormalized(); + + // A segment ends at the center of a simulation cell + auto valveCenterCoord = ( segmentEndCoord + segmentStartCoord ) / 2.0; + + const cvf::Color3f valveColor = cvf::Color3f::ORANGE; + const auto measuredDepthsRelativeToStartMD = { 0.0, 1.0, valveLength - 1.0, valveLength }; + + const auto outerValveRadius = wellPathRadius * 1.3; + const auto radii = { wellPathRadius, outerValveRadius, outerValveRadius, wellPathRadius }; + + // The location of the valve is adjusted to locate the valve at the center of the segment + double locationAdjustment = -valveLength / 2.0; + + std::vector displayCoords; + for ( const auto& mdRelativeToStart : measuredDepthsRelativeToStartMD ) + { + displayCoords.push_back( valveCenterCoord + ( locationAdjustment + mdRelativeToStart ) * segmentDirection ); + } + + RivPipeGeometryGenerator::tubeWithCenterLinePartsAndVariableWidth( &pbd.m_valveParts, displayCoords, radii, valveColor ); + + auto computeRotationAxisAndAngle = []( const cvf::Vec3f& direction ) { + // Compute upwards normal based on direction + // Compute the rotation axis and angle between up vector and Z_AXIS + + cvf::Vec3f crossBetweenZAndDirection; + crossBetweenZAndDirection.cross( cvf::Vec3f::Z_AXIS, cvf::Vec3f( direction ) ); + + cvf::Vec3f upVector; + upVector.cross( cvf::Vec3f( direction ), crossBetweenZAndDirection ); + + cvf::Vec3f rotationAxis; + rotationAxis.cross( upVector, cvf::Vec3f::Z_AXIS ); + upVector.normalize(); + + float angle = cvf::Math::acos( upVector * cvf::Vec3f::Z_AXIS ); + + return std::make_pair( rotationAxis, angle ); + }; + + const auto& [rotationAxis, angle] = computeRotationAxisAndAngle( cvf::Vec3f( segmentDirection ) ); + + // Add visualization of valves openings for segments close to horizontal segments + if ( !std::isnan( angle ) && ( std::fabs( angle ) < ( std::numbers::pi / 2.0 ) ) ) + { + cvf::GeometryBuilderDrawableGeo builder; + + const float bottomRadius = wellPathRadius * 0.4f; + const float topRadius = bottomRadius; + const float height = outerValveRadius * 2.1f; + const float topOffsetX = 0.0f; + const float topOffsetY = 0.0f; + const uint numSlices = 12; + const bool normalsOutwards = true; + const bool closedBot = true; + const bool closedTop = true; + const uint numPolysZDir = 1; + + cvf::GeometryUtils::createObliqueCylinder( bottomRadius, + topRadius, + height, + topOffsetX, + topOffsetY, + numSlices, + normalsOutwards, + closedBot, + closedTop, + numPolysZDir, + &builder ); + + // Move center of cylinder to origo + builder.transformVertexRange( 0, builder.vertexCount() - 1, cvf::Mat4f::fromTranslation( cvf::Vec3f( 0.0, 0.0, -height / 2.0 ) ) ); + + // Rotate cylinder to match the be normal to the well path direction + const cvf::Mat4f rotMat = cvf::Mat4f::fromRotation( rotationAxis, -angle ); + builder.transformVertexRange( 0, builder.vertexCount() - 1, rotMat ); + + // Move the cylinder to display coordinate location + builder.transformVertexRange( 0, builder.vertexCount() - 1, cvf::Mat4f::fromTranslation( cvf::Vec3f( valveCenterCoord ) ) ); + + auto drawableGeo = builder.drawableGeo(); + auto part = new cvf::Part; + part->setName( "RivPipeGeometryGenerator::surface" ); + part->setDrawable( drawableGeo.p() ); + + caf::SurfaceEffectGenerator surfaceGen( cvf::Color4f( cvf::Color3f::BLACK ), caf::PO_1 ); + auto eff = surfaceGen.generateCachedEffect(); + + part->setEffect( eff.p() ); + + pbd.m_valveParts.push_back( part ); + } + } } } diff --git a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.h b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.h index 6084191876..17e5f61406 100644 --- a/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivSimWellPipesPartMgr.h @@ -20,11 +20,12 @@ #include "RigSimWellData.h" +#include "cafPdmPointer.h" + +#include "cvfCollection.h" #include "cvfObject.h" #include "cvfVector3.h" -#include "cafPdmPointer.h" - #include namespace cvf @@ -42,6 +43,7 @@ class DisplayCoordTransform; class RivPipeGeometryGenerator; class Rim3dView; class RimSimWellInView; +class RimEclipseView; class RivWellConnectionFactorGeometryGenerator; struct RigWellResultPoint; @@ -65,15 +67,6 @@ public: std::vector flattenedBranchWellHeadOffsets(); private: - Rim3dView* viewWithSettings(); - void buildWellPipeParts( const caf::DisplayCoordTransform* displayXf, - bool doFlatten, - double flattenedIntersectionExtentLength, - int branchIndex, - size_t frameIndex ); - - caf::PdmPointer m_simWellInView; - struct RivPipeBranchData { std::vector m_cellIds; @@ -87,10 +80,35 @@ private: cvf::ref m_connectionFactorGeometryGenerator; cvf::ref m_connectionFactorsPart; + + cvf::Collection m_valveParts; }; + Rim3dView* viewWithSettings(); + void buildWellPipeParts( const caf::DisplayCoordTransform* displayXf, + bool doFlatten, + double flattenedIntersectionExtentLength, + int branchIndex, + size_t frameIndex ); + + void appendVirtualConnectionFactorGeo( const RimEclipseView* eclipseView, + size_t frameIndex, + size_t brIdx, + const caf::DisplayCoordTransform* displayXf, + double pipeRadius, + RivPipeBranchData& pbd ); + + void appendValvesGeo( const RimEclipseView* eclipseView, + size_t frameIndex, + size_t brIdx, + const caf::DisplayCoordTransform* displayXf, + double pipeRadius, + RivPipeBranchData& pbd ); + +private: + caf::PdmPointer m_simWellInView; + std::list m_wellBranches; - std::vector> m_pipeBranchesCLCoords; - std::vector m_flattenedBranchWellHeadOffsets; + std::vector m_flattenedBranchWellHeadOffsets; }; diff --git a/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp index 408a70bbd6..1ef1d89d51 100644 --- a/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivWellFracturePartMgr.cpp @@ -961,11 +961,10 @@ void RivWellFracturePartMgr::appendFracturePerforationLengthParts( const RimEcli double perforationRadius = wellPathRadius * 1.2; cvf::Collection parts; - RivPipeGeometryGenerator geoGenerator; - geoGenerator.cylinderWithCenterLineParts( &parts, - displayCoords, - RiaColorTables::wellPathComponentColors()[RiaDefines::WellPathComponentType::PERFORATION_INTERVAL], - perforationRadius ); + RivPipeGeometryGenerator::cylinderWithCenterLineParts( &parts, + displayCoords, + RiaColorTables::wellPathComponentColors()[RiaDefines::WellPathComponentType::PERFORATION_INTERVAL], + perforationRadius ); for ( auto part : parts ) { diff --git a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp index e428f2247a..5688cb906e 100644 --- a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -400,7 +400,6 @@ void RivWellPathPartMgr::appendPerforationsToModel( cvf::ModelBasicList* double wellPathRadius = this->wellPathRadius( characteristicCellSize, wellPathCollection ); double perforationRadius = wellPathRadius * 1.1; - RivPipeGeometryGenerator geoGenerator; std::vector perforations; m_rimWellPath->descendantsIncludingThisOfType( perforations ); for ( RimPerforationInterval* perforation : perforations ) @@ -449,7 +448,7 @@ void RivWellPathPartMgr::appendPerforationsToModel( cvf::ModelBasicList* cvf::ref objectSourceInfo = new RivObjectSourceInfo( perforation ); cvf::Collection parts; - geoGenerator.cylinderWithCenterLineParts( &parts, perfIntervalCLDiplayCS, cvf::Color3f::GREEN, perforationRadius ); + RivPipeGeometryGenerator::cylinderWithCenterLineParts( &parts, perfIntervalCLDiplayCS, cvf::Color3f::GREEN, perforationRadius ); for ( auto part : parts ) { part->setSourceInfo( objectSourceInfo.p() ); @@ -457,7 +456,7 @@ void RivWellPathPartMgr::appendPerforationsToModel( cvf::ModelBasicList* } } - appendPerforationValvesToModel( model, perforation, wellPathRadius, displayCoordTransform, geoGenerator ); + appendPerforationValvesToModel( model, perforation, wellPathRadius, displayCoordTransform ); } } @@ -467,31 +466,83 @@ void RivWellPathPartMgr::appendPerforationsToModel( cvf::ModelBasicList* void RivWellPathPartMgr::appendPerforationValvesToModel( cvf::ModelBasicList* model, RimPerforationInterval* perforation, double wellPathRadius, - const caf::DisplayCoordTransform* displayCoordTransform, - RivPipeGeometryGenerator& geoGenerator ) + const caf::DisplayCoordTransform* displayCoordTransform ) { - // Valves + for ( RimWellPathValve* valve : perforation->valves() ) { - for ( RimWellPathValve* valve : perforation->valves() ) + if ( !valve->isChecked() ) continue; + + std::vector measuredDepthsRelativeToStartMD; + std::vector radii; + cvf::Color3f valveColor = valve->defaultComponentColor(); + if ( valve->componentType() == RiaDefines::WellPathComponentType::ICV ) { - if ( !valve->isChecked() ) continue; + measuredDepthsRelativeToStartMD = { 0.0, 1.0, 1.5, 4.0, 5.0, 5.5, 8.0, 9.0 }; + radii = { wellPathRadius, + wellPathRadius * 1.8, + wellPathRadius * 2.0, + wellPathRadius * 2.0, + wellPathRadius * 1.8, + wellPathRadius * 1.7, + wellPathRadius * 1.7, + wellPathRadius }; - std::vector measuredDepthsRelativeToStartMD; - std::vector radii; - cvf::Color3f valveColor = valve->defaultComponentColor(); - if ( valve->componentType() == RiaDefines::WellPathComponentType::ICV ) + double startMD = valve->startMD(); + std::vector displayCoords; + for ( double mdRelativeToStart : measuredDepthsRelativeToStartMD ) { - measuredDepthsRelativeToStartMD = { 0.0, 1.0, 1.5, 4.0, 5.0, 5.5, 8.0, 9.0 }; - radii = { wellPathRadius, - wellPathRadius * 1.8, - wellPathRadius * 2.0, - wellPathRadius * 2.0, - wellPathRadius * 1.8, - wellPathRadius * 1.7, - wellPathRadius * 1.7, - wellPathRadius }; + displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( + m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( mdRelativeToStart * 0.333 * wellPathRadius + startMD ) ) ); + } + + cvf::ref objectSourceInfo = new RivObjectSourceInfo( valve ); + + cvf::Collection parts; + RivPipeGeometryGenerator::tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, valveColor ); + for ( auto part : parts ) + { + part->setSourceInfo( objectSourceInfo.p() ); + model->addPart( part.p() ); + } + } + else if ( valve->componentType() == RiaDefines::WellPathComponentType::ICD || + valve->componentType() == RiaDefines::WellPathComponentType::AICD ) + { + std::vector valveLocations = valve->valveLocations(); + for ( double startMD : valveLocations ) + { + int size = 16; + + measuredDepthsRelativeToStartMD.resize( size ); + radii.resize( size ); + for ( int i = 0; i < size; i += 2 ) + { + measuredDepthsRelativeToStartMD[i] = double( i / 2 ); + measuredDepthsRelativeToStartMD[i + 1] = double( i / 2 + 0.5 ); + } + radii[0] = wellPathRadius; + bool inner = false; + int nInners = 0; + for ( int i = 1; i < size - 1; i += 2 ) + { + if ( inner && valve->componentType() == RiaDefines::WellPathComponentType::AICD && nInners > 0 ) + { + radii[i + 1] = radii[i] = wellPathRadius * 1.7; + nInners = 0; + } + else if ( inner ) + { + radii[i + 1] = radii[i] = wellPathRadius * 1.9; + nInners++; + } + else + { + radii[i + 1] = radii[i] = wellPathRadius * 2.0; + } + inner = !inner; + } + radii[size - 1] = wellPathRadius; - double startMD = valve->startMD(); std::vector displayCoords; for ( double mdRelativeToStart : measuredDepthsRelativeToStartMD ) { @@ -503,70 +554,13 @@ void RivWellPathPartMgr::appendPerforationValvesToModel( cvf::ModelBasicList* cvf::ref objectSourceInfo = new RivObjectSourceInfo( valve ); cvf::Collection parts; - geoGenerator.tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, valveColor ); + RivPipeGeometryGenerator::tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, valveColor ); for ( auto part : parts ) { part->setSourceInfo( objectSourceInfo.p() ); model->addPart( part.p() ); } } - else if ( valve->componentType() == RiaDefines::WellPathComponentType::ICD || - valve->componentType() == RiaDefines::WellPathComponentType::AICD ) - { - std::vector valveLocations = valve->valveLocations(); - for ( double startMD : valveLocations ) - { - int size = 16; - - measuredDepthsRelativeToStartMD.resize( size ); - radii.resize( size ); - for ( int i = 0; i < size; i += 2 ) - { - measuredDepthsRelativeToStartMD[i] = double( i / 2 ); - measuredDepthsRelativeToStartMD[i + 1] = double( i / 2 + 0.5 ); - } - radii[0] = wellPathRadius; - bool inner = false; - int nInners = 0; - for ( int i = 1; i < size - 1; i += 2 ) - { - if ( inner && valve->componentType() == RiaDefines::WellPathComponentType::AICD && nInners > 0 ) - { - radii[i + 1] = radii[i] = wellPathRadius * 1.7; - nInners = 0; - } - else if ( inner ) - { - radii[i + 1] = radii[i] = wellPathRadius * 1.9; - nInners++; - } - else - { - radii[i + 1] = radii[i] = wellPathRadius * 2.0; - } - inner = !inner; - } - radii[size - 1] = wellPathRadius; - - std::vector displayCoords; - for ( double mdRelativeToStart : measuredDepthsRelativeToStartMD ) - { - displayCoords.push_back( displayCoordTransform->transformToDisplayCoord( - m_rimWellPath->wellPathGeometry()->interpolatedPointAlongWellPath( mdRelativeToStart * 0.333 * wellPathRadius + - startMD ) ) ); - } - - cvf::ref objectSourceInfo = new RivObjectSourceInfo( valve ); - - cvf::Collection parts; - geoGenerator.tubeWithCenterLinePartsAndVariableWidth( &parts, displayCoords, radii, valveColor ); - for ( auto part : parts ) - { - part->setSourceInfo( objectSourceInfo.p() ); - model->addPart( part.p() ); - } - } - } } } } @@ -1027,8 +1021,6 @@ void RivWellPathPartMgr::appendWellIntegrityIntervalsToModel( cvf::ModelBasicLis double wellPathRadius = this->wellPathRadius( characteristicCellSize, wellPathCollection ); double wiaIntervalRadius = wellPathRadius * 1.15; - RivPipeGeometryGenerator geoGenerator; - for ( auto wiaModel : m_rimWellPath->wellIASettingsCollection()->settings() ) { if ( !wiaModel->isChecked() ) continue; @@ -1053,7 +1045,7 @@ void RivWellPathPartMgr::appendWellIntegrityIntervalsToModel( cvf::ModelBasicLis cvf::ref objectSourceInfo = new RivObjectSourceInfo( wiaModel ); cvf::Collection parts; - geoGenerator.cylinderWithCenterLineParts( &parts, intervalCLDisplayCS, cvf::Color3f::ORCHID, wiaIntervalRadius ); + RivPipeGeometryGenerator::cylinderWithCenterLineParts( &parts, intervalCLDisplayCS, cvf::Color3f::ORCHID, wiaIntervalRadius ); for ( auto& part : parts ) { part->setSourceInfo( objectSourceInfo.p() ); diff --git a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.h index 195d38b479..f718729824 100644 --- a/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivWellPathPartMgr.h @@ -107,8 +107,7 @@ private: void appendPerforationValvesToModel( cvf::ModelBasicList* model, RimPerforationInterval* perforation, double wellPathRadius, - const caf::DisplayCoordTransform* displayCoordTransform, - RivPipeGeometryGenerator& geoGenerator ); + const caf::DisplayCoordTransform* displayCoordTransform ); void appendVirtualTransmissibilitiesToModel( cvf::ModelBasicList* model, size_t timeStepIndex, diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp index c349973b34..ff86e34e2f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.cpp @@ -574,6 +574,43 @@ bool RimSimWellInView::isWellSpheresVisible( size_t frameIndex ) const } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSimWellInView::isWellValvesVisible( size_t frameIndex ) const +{ + const RimEclipseView* reservoirView = nullptr; + this->firstAncestorOrThisOfType( reservoirView ); + + if ( reservoirView == nullptr ) return false; + if ( this->simWellData() == nullptr ) return false; + + if ( frameIndex >= this->simWellData()->m_resultTimeStepIndexToWellTimeStepIndex.size() ) + { + return false; + } + + size_t wellTimeStepIndex = this->simWellData()->m_resultTimeStepIndexToWellTimeStepIndex[frameIndex]; + if ( wellTimeStepIndex == cvf::UNDEFINED_SIZE_T ) + { + return false; + } + + if ( !this->showWell() ) return false; + + if ( !reservoirView->wellCollection()->isActive() ) return false; + if ( !reservoirView->wellCollection()->showValves() ) return false; + + if ( reservoirView->intersectionCollection()->hasActiveIntersectionForSimulationWell( this ) ) return true; + + if ( reservoirView->wellCollection()->showWellsIntersectingVisibleCells() && reservoirView->cellFilterCollection()->hasActiveFilters() ) + { + return intersectsDynamicWellCellsFilteredCells( frameIndex ); + } + + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h index 8007bedabb..16d8b0cf25 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInView.h @@ -65,6 +65,7 @@ public: bool isWellCellsVisible() const; bool isWellPipeVisible( size_t frameIndex ) const; bool isWellSpheresVisible( size_t frameIndex ) const; + bool isWellValvesVisible( size_t frameIndex ) const; bool isUsingCellCenterForPipe() const; RigWellDiskData wellDiskData() const; diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.cpp index 16d33ac2e5..f74b8a8bb7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.cpp @@ -212,6 +212,8 @@ RimSimWellInViewCollection::RimSimWellInViewCollection() m_showWellCellFence.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() ); m_showWellCellFence.xmlCapability()->disableIO(); + CAF_PDM_InitField( &m_showWellValves, "ShowWellValvesTristate", true, "Valves" ); + CAF_PDM_InitFieldNoDefault( &m_wellDiskSummaryCase, "WellDiskSummaryCase", "Summary Case" ); CAF_PDM_InitField( &m_wellDiskQuantity, "WellDiskQuantity", QString( "WOPT" ), "Disk Quantity" ); @@ -439,7 +441,8 @@ void RimSimWellInViewCollection::fieldChangedByUi( const caf::PdmFieldHandle* ch { m_reservoirView->updateDisplayModelForCurrentTimeStepAndRedraw(); } - else if ( &spheresScaleFactor == changedField || &m_showWellSpheres == changedField || &showConnectionStatusColors == changedField ) + else if ( &spheresScaleFactor == changedField || &m_showWellSpheres == changedField || + &showConnectionStatusColors == changedField || &m_showWellValves == changedField ) { m_reservoirView->scheduleSimWellGeometryRegen(); m_reservoirView->scheduleCreateDisplayModelAndRedraw(); @@ -650,6 +653,7 @@ void RimSimWellInViewCollection::defineUiOrdering( QString uiConfigName, caf::Pd appearanceGroup->add( &m_showWellSpheres ); appearanceGroup->add( &m_showWellDisks ); appearanceGroup->add( &m_showWellCommunicationLines ); + appearanceGroup->add( &m_showWellValves ); if ( !isContourMap ) { @@ -943,6 +947,14 @@ double RimSimWellInViewCollection::wellDiskScaleFactor() const return m_wellDiskScaleFactor(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimSimWellInViewCollection::showValves() const +{ + return m_showWellValves(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.h b/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.h index 05b31e0ede..69dd54ce72 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimSimWellInViewCollection.h @@ -161,6 +161,8 @@ public: void scaleWellDisks(); double wellDiskScaleFactor() const; + bool showValves() const; + caf::PdmField wellDiskColor; protected: @@ -196,6 +198,7 @@ private: caf::PdmField m_showWellCells; caf::PdmField m_showWellCellFence; + caf::PdmField m_showWellValves; caf::PdmField m_showWellCommunicationLines; // Well Discs diff --git a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp index 588035be11..410002841e 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.cpp @@ -192,6 +192,14 @@ std::vector resPoint.setGridIndex( gridIndex ); resPoint.setGridCellIndex( cellIndex ); + auto gridAndCellIndex = std::make_pair( gridIndex, cellIndex ); + if ( std::find( wellBranch.m_gridCellsConnectedToValve.begin(), + wellBranch.m_gridCellsConnectedToValve.end(), + gridAndCellIndex ) != wellBranch.m_gridCellsConnectedToValve.end() ) + { + resPoint.setIsConnectedToValve( true ); + } + cellCenterCoords.push_back( pos ); cellCenterResultPoints.push_back( resPoint ); } @@ -333,6 +341,7 @@ std::vector for ( const auto& [gridAndCellIndex, localOutputSegment] : branch.m_gridCellsConnectedToSegments ) { longBranch.m_segmentsWithGridCells[outputSegment.outputSegmentId].push_back( gridAndCellIndex ); + longBranch.m_gridCellsConnectedToValve.push_back( gridAndCellIndex ); } } } diff --git a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h index 148daecc03..07d453f16b 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h +++ b/ApplicationLibCode/ReservoirDataModel/RigMswCenterLineCalculator.h @@ -50,6 +50,7 @@ private: std::map, OutputSegment> m_gridCellsConnectedToSegments; std::map>> m_segmentsWithGridCells; + std::vector> m_gridCellsConnectedToValve; bool containsGridCell( const std::pair& candidateGridAndCellIndex ) const { diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp index 88ad81d687..5d17092969 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.cpp @@ -35,6 +35,7 @@ RigWellResultPoint::RigWellResultPoint() , m_gasRate( 0.0 ) , m_waterRate( 0.0 ) , m_connectionFactor( 0.0 ) + , m_isConnectedToValve( false ) { } @@ -107,6 +108,14 @@ void RigWellResultPoint::setBottomPosition( const cvf::Vec3d& bottomPosition ) m_bottomPosition = bottomPosition; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellResultPoint::setIsConnectedToValve( bool enable ) +{ + m_isConnectedToValve = true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -149,6 +158,14 @@ bool RigWellResultPoint::isEqual( const RigWellResultPoint& other ) const m_oilRate == other.m_oilRate && m_gasRate == other.m_gasRate && m_waterRate == other.m_waterRate ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigWellResultPoint::isConnectedToValve() const +{ + return m_isConnectedToValve; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h index 74d11d698a..1c83694562 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h +++ b/ApplicationLibCode/ReservoirDataModel/RigWellResultPoint.h @@ -44,12 +44,14 @@ struct RigWellResultPoint void setOutletSegmentData( int outletBranchId, int outletSegmentId ); void setBottomPosition( const cvf::Vec3d& bottomPosition ); + void setIsConnectedToValve( bool enable ); bool isPointValid() const; bool isCell() const; bool isValid() const; bool isOpen() const; bool isEqual( const RigWellResultPoint& other ) const; + bool isConnectedToValve() const; double flowRate() const; double oilRate() const; @@ -86,6 +88,7 @@ private: double m_waterRate; //< Surface water rate double m_connectionFactor; + bool m_isConnectedToValve; }; //==================================================================================================