From 955d07f9ce217d72e1122c304b636bd64c6c9bc4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 6 Dec 2019 10:10:02 +0100 Subject: [PATCH 1/5] #5196 Export MSW : Do not export segments before start measured depth --- .../RicWellPathExportMswCompletionsImpl.cpp | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp index f34a6182ff..bc22959893 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp @@ -1051,31 +1051,82 @@ RicMswExportInfo RicWellPathExportMswCompletionsImpl::generatePerforationsMswExp const std::vector& mds = wellPathGeometry->measureDepths(); CVF_ASSERT( !coords.empty() && !mds.empty() ); - std::vector intersections = - RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( eclipseCase->eclipseCaseData(), coords, mds ); + double initialMD = 0.0; // Start measured depth location to export MSW data for. Either based on first intersection + // with active grid, or user defined value. - double maxSegmentLength = wellPath->perforationIntervalCollection()->mswParameters()->maxSegmentLength(); - std::vector subSegIntersections = - SubSegmentIntersectionInfo::spiltIntersectionSegmentsToMaxLength( wellPathGeometry, - intersections, - maxSegmentLength ); + std::vector subSegIntersections; - double initialMD = 0.0; - if ( wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == - RimMswCompletionParameters::MANUAL_REFERENCE_MD ) { - initialMD = wellPath->perforationIntervalCollection()->mswParameters()->manualReferenceMD(); - } - else - { - for ( WellPathCellIntersectionInfo intersection : intersections ) + std::vector intersections = + RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( eclipseCase->eclipseCaseData(), coords, mds ); + + if ( wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == + RimMswCompletionParameters::MANUAL_REFERENCE_MD ) { - if ( activeCellInfo->isActive( intersection.globCellIndex ) ) + initialMD = wellPath->perforationIntervalCollection()->mswParameters()->manualReferenceMD(); + } + else + { + for ( const WellPathCellIntersectionInfo& intersection : intersections ) { - initialMD = intersection.startMD; - break; + if ( activeCellInfo->isActive( intersection.globCellIndex ) ) + { + initialMD = intersection.startMD; + break; + } } } + + // Skip all intersections before initialMD + + std::vector filteredIntersections; + { + const double epsilon = 0.001; + + for ( const WellPathCellIntersectionInfo& intersection : intersections ) + { + if ( ( intersection.endMD - initialMD ) < epsilon ) + { + // Skip all intersections before initial measured depth + continue; + } + else if ( ( intersection.startMD - initialMD ) > epsilon ) + { + filteredIntersections.push_back( intersection ); + } + else + { + // InitialMD is inside intersection, split based on intersection point + + cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); + + WellPathCellIntersectionInfo smallerIntersection; + + smallerIntersection.globCellIndex = intersection.globCellIndex; + smallerIntersection.startPoint = intersectionPoint; + smallerIntersection.endPoint = intersection.endPoint; + smallerIntersection.startMD = initialMD; + smallerIntersection.endMD = intersection.endMD; + smallerIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; + smallerIntersection.intersectedCellFaceOut = intersection.intersectedCellFaceOut; + + const RigMainGrid* grid = eclipseCase->mainGrid(); + + smallerIntersection.intersectionLengthsInCellCS = + RigWellPathIntersectionTools::calculateLengthInCell( grid, + intersection.globCellIndex, + intersectionPoint, + intersection.endPoint ); + filteredIntersections.push_back( smallerIntersection ); + } + } + } + + const double maxSegmentLength = wellPath->perforationIntervalCollection()->mswParameters()->maxSegmentLength(); + + subSegIntersections = SubSegmentIntersectionInfo::spiltIntersectionSegmentsToMaxLength( wellPathGeometry, + filteredIntersections, + maxSegmentLength ); } RicMswExportInfo exportInfo( wellPath, From 3babbe675a3cafadb7844e2320acc7a7736bd1d8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 6 Dec 2019 12:10:34 +0100 Subject: [PATCH 2/5] #5197 Export MSW : Set minimum segment length to 1.0e-3 --- .../RicWellPathExportMswCompletionsImpl.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp index bc22959893..d74fae15b6 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp @@ -1179,9 +1179,16 @@ RicWellPathExportMswCompletionsImpl::MainBoreSegments { MainBoreSegments mainBoreSegments; + // Intersections along the well path with grid geometry is handled by well log extraction tools. The threshold in + // RigWellLogExtractionTools::isEqualDepth is currently set to 0.1m, and this is a pretty large threshold based on + // the indicated threshold of 0.001m for MSW segments + const double segmentLengthThreshold = 1.0e-3; + for ( const auto& cellIntInfo : subSegIntersections ) { - if ( std::fabs( cellIntInfo.endMD - cellIntInfo.startMD ) > 1.0e-8 ) + const double segmentLength = std::fabs( cellIntInfo.endMD - cellIntInfo.startMD ); + + if ( segmentLength > segmentLengthThreshold ) { QString label = QString( "Main stem segment %1" ).arg( mainBoreSegments.size() + 2 ); std::shared_ptr segment( new RicMswSegment( label, @@ -1213,6 +1220,13 @@ RicWellPathExportMswCompletionsImpl::MainBoreSegments } mainBoreSegments.push_back( segment ); } + else + { + QString text = QString( "Skipping segment , threshold = %1, length = %2" ) + .arg( segmentLengthThreshold ) + .arg( segmentLength ); + RiaLogging::info( text ); + } } return mainBoreSegments; } From 312caa75685cd4885f85d1e845530a2bc48afd47 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 6 Dec 2019 13:14:42 +0100 Subject: [PATCH 3/5] #5198 Export MSW : Add extra segment if user defined measured depth is above grid --- .../RicWellPathExportMswCompletionsImpl.cpp | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp index d74fae15b6..cb478f94d1 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp @@ -1077,10 +1077,33 @@ RicMswExportInfo RicWellPathExportMswCompletionsImpl::generatePerforationsMswExp } } - // Skip all intersections before initialMD - std::vector filteredIntersections; + { + if ( !intersections.empty() && intersections[0].startMD > initialMD && + wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == + RimMswCompletionParameters::MANUAL_REFERENCE_MD ) + { + WellPathCellIntersectionInfo firstIntersection = intersections[0]; + + // Add a segment from user defined MD to start of grid + cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); + + WellPathCellIntersectionInfo extraIntersection; + + extraIntersection.globCellIndex = std::numeric_limits::max(); + extraIntersection.startPoint = intersectionPoint; + extraIntersection.endPoint = firstIntersection.startPoint; + extraIntersection.startMD = initialMD; + extraIntersection.endMD = firstIntersection.startMD; + extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; + extraIntersection.intersectedCellFaceOut = cvf::StructGridInterface::oppositeFace( + firstIntersection.intersectedCellFaceIn ); + extraIntersection.intersectionLengthsInCellCS = cvf::Vec3d::ZERO; + + filteredIntersections.push_back( extraIntersection ); + } + const double epsilon = 0.001; for ( const WellPathCellIntersectionInfo& intersection : intersections ) @@ -1100,24 +1123,24 @@ RicMswExportInfo RicWellPathExportMswCompletionsImpl::generatePerforationsMswExp cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); - WellPathCellIntersectionInfo smallerIntersection; + WellPathCellIntersectionInfo extraIntersection; - smallerIntersection.globCellIndex = intersection.globCellIndex; - smallerIntersection.startPoint = intersectionPoint; - smallerIntersection.endPoint = intersection.endPoint; - smallerIntersection.startMD = initialMD; - smallerIntersection.endMD = intersection.endMD; - smallerIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; - smallerIntersection.intersectedCellFaceOut = intersection.intersectedCellFaceOut; + extraIntersection.globCellIndex = intersection.globCellIndex; + extraIntersection.startPoint = intersectionPoint; + extraIntersection.endPoint = intersection.endPoint; + extraIntersection.startMD = initialMD; + extraIntersection.endMD = intersection.endMD; + extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; + extraIntersection.intersectedCellFaceOut = intersection.intersectedCellFaceOut; const RigMainGrid* grid = eclipseCase->mainGrid(); - smallerIntersection.intersectionLengthsInCellCS = + extraIntersection.intersectionLengthsInCellCS = RigWellPathIntersectionTools::calculateLengthInCell( grid, intersection.globCellIndex, intersectionPoint, intersection.endPoint ); - filteredIntersections.push_back( smallerIntersection ); + filteredIntersections.push_back( extraIntersection ); } } } From db3b8937fadf873c918e45d2e294b122ef8e53bc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 6 Dec 2019 13:34:52 +0100 Subject: [PATCH 4/5] #5198 Export MSW : Move into separate functions --- .../RicWellPathExportMswCompletionsImpl.cpp | 226 ++++++++++-------- .../RicWellPathExportMswCompletionsImpl.h | 12 + 2 files changed, 135 insertions(+), 103 deletions(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp index cb478f94d1..0092436e2a 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp @@ -1043,114 +1043,12 @@ RicMswExportInfo RicWellPathExportMswCompletionsImpl::generatePerforationsMswExp int timeStep, const std::vector& perforationIntervals ) { - const RigActiveCellInfo* activeCellInfo = eclipseCase->eclipseCaseData()->activeCellInfo( RiaDefines::MATRIX_MODEL ); RiaEclipseUnitTools::UnitSystem unitSystem = eclipseCase->eclipseCaseData()->unitsType(); - const RigWellPath* wellPathGeometry = wellPath->wellPathGeometry(); - const std::vector& coords = wellPathGeometry->wellPathPoints(); - const std::vector& mds = wellPathGeometry->measureDepths(); - CVF_ASSERT( !coords.empty() && !mds.empty() ); - double initialMD = 0.0; // Start measured depth location to export MSW data for. Either based on first intersection // with active grid, or user defined value. - std::vector subSegIntersections; - - { - std::vector intersections = - RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( eclipseCase->eclipseCaseData(), coords, mds ); - - if ( wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == - RimMswCompletionParameters::MANUAL_REFERENCE_MD ) - { - initialMD = wellPath->perforationIntervalCollection()->mswParameters()->manualReferenceMD(); - } - else - { - for ( const WellPathCellIntersectionInfo& intersection : intersections ) - { - if ( activeCellInfo->isActive( intersection.globCellIndex ) ) - { - initialMD = intersection.startMD; - break; - } - } - } - - std::vector filteredIntersections; - - { - if ( !intersections.empty() && intersections[0].startMD > initialMD && - wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == - RimMswCompletionParameters::MANUAL_REFERENCE_MD ) - { - WellPathCellIntersectionInfo firstIntersection = intersections[0]; - - // Add a segment from user defined MD to start of grid - cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); - - WellPathCellIntersectionInfo extraIntersection; - - extraIntersection.globCellIndex = std::numeric_limits::max(); - extraIntersection.startPoint = intersectionPoint; - extraIntersection.endPoint = firstIntersection.startPoint; - extraIntersection.startMD = initialMD; - extraIntersection.endMD = firstIntersection.startMD; - extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; - extraIntersection.intersectedCellFaceOut = cvf::StructGridInterface::oppositeFace( - firstIntersection.intersectedCellFaceIn ); - extraIntersection.intersectionLengthsInCellCS = cvf::Vec3d::ZERO; - - filteredIntersections.push_back( extraIntersection ); - } - - const double epsilon = 0.001; - - for ( const WellPathCellIntersectionInfo& intersection : intersections ) - { - if ( ( intersection.endMD - initialMD ) < epsilon ) - { - // Skip all intersections before initial measured depth - continue; - } - else if ( ( intersection.startMD - initialMD ) > epsilon ) - { - filteredIntersections.push_back( intersection ); - } - else - { - // InitialMD is inside intersection, split based on intersection point - - cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); - - WellPathCellIntersectionInfo extraIntersection; - - extraIntersection.globCellIndex = intersection.globCellIndex; - extraIntersection.startPoint = intersectionPoint; - extraIntersection.endPoint = intersection.endPoint; - extraIntersection.startMD = initialMD; - extraIntersection.endMD = intersection.endMD; - extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; - extraIntersection.intersectedCellFaceOut = intersection.intersectedCellFaceOut; - - const RigMainGrid* grid = eclipseCase->mainGrid(); - - extraIntersection.intersectionLengthsInCellCS = - RigWellPathIntersectionTools::calculateLengthInCell( grid, - intersection.globCellIndex, - intersectionPoint, - intersection.endPoint ); - filteredIntersections.push_back( extraIntersection ); - } - } - } - - const double maxSegmentLength = wellPath->perforationIntervalCollection()->mswParameters()->maxSegmentLength(); - - subSegIntersections = SubSegmentIntersectionInfo::spiltIntersectionSegmentsToMaxLength( wellPathGeometry, - filteredIntersections, - maxSegmentLength ); - } + std::vector subSegIntersections = generateSubSegments( eclipseCase, wellPath, initialMD ); RicMswExportInfo exportInfo( wellPath, unitSystem, @@ -1188,6 +1086,128 @@ RicMswExportInfo RicWellPathExportMswCompletionsImpl::generatePerforationsMswExp return exportInfo; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RicWellPathExportMswCompletionsImpl::generateSubSegments( const RimEclipseCase* eclipseCase, + const RimWellPath* wellPath, + double& initialMD ) +{ + const RigActiveCellInfo* activeCellInfo = eclipseCase->eclipseCaseData()->activeCellInfo( RiaDefines::MATRIX_MODEL ); + const RigWellPath* wellPathGeometry = wellPath->wellPathGeometry(); + const std::vector& coords = wellPathGeometry->wellPathPoints(); + const std::vector& mds = wellPathGeometry->measureDepths(); + CVF_ASSERT( !coords.empty() && !mds.empty() ); + + std::vector intersections = + RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( eclipseCase->eclipseCaseData(), coords, mds ); + + if ( wellPath->perforationIntervalCollection()->mswParameters()->referenceMDType() == + RimMswCompletionParameters::MANUAL_REFERENCE_MD ) + { + initialMD = wellPath->perforationIntervalCollection()->mswParameters()->manualReferenceMD(); + } + else + { + for ( const WellPathCellIntersectionInfo& intersection : intersections ) + { + if ( activeCellInfo->isActive( intersection.globCellIndex ) ) + { + initialMD = intersection.startMD; + break; + } + } + } + + std::vector filteredIntersections = filterIntersections( intersections, + initialMD, + wellPathGeometry, + eclipseCase ); + + const double maxSegmentLength = wellPath->perforationIntervalCollection()->mswParameters()->maxSegmentLength(); + + return SubSegmentIntersectionInfo::spiltIntersectionSegmentsToMaxLength( wellPathGeometry, + filteredIntersections, + maxSegmentLength ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RicWellPathExportMswCompletionsImpl::filterIntersections( + const std::vector& intersections, + double initialMD, + const RigWellPath* wellPathGeometry, + const RimEclipseCase* eclipseCase ) +{ + std::vector filteredIntersections; + + if ( !intersections.empty() && intersections[0].startMD > initialMD ) + { + WellPathCellIntersectionInfo firstIntersection = intersections[0]; + + // Add a segment from user defined MD to start of grid + cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); + + WellPathCellIntersectionInfo extraIntersection; + + extraIntersection.globCellIndex = std::numeric_limits::max(); + extraIntersection.startPoint = intersectionPoint; + extraIntersection.endPoint = firstIntersection.startPoint; + extraIntersection.startMD = initialMD; + extraIntersection.endMD = firstIntersection.startMD; + extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; + extraIntersection.intersectedCellFaceOut = cvf::StructGridInterface::oppositeFace( + firstIntersection.intersectedCellFaceIn ); + extraIntersection.intersectionLengthsInCellCS = cvf::Vec3d::ZERO; + + filteredIntersections.push_back( extraIntersection ); + } + + const double epsilon = 0.001; + + for ( const WellPathCellIntersectionInfo& intersection : intersections ) + { + if ( ( intersection.endMD - initialMD ) < epsilon ) + { + // Skip all intersections before initial measured depth + continue; + } + else if ( ( intersection.startMD - initialMD ) > epsilon ) + { + filteredIntersections.push_back( intersection ); + } + else + { + // InitialMD is inside intersection, split based on intersection point + + cvf::Vec3d intersectionPoint = wellPathGeometry->interpolatedPointAlongWellPath( initialMD ); + + WellPathCellIntersectionInfo extraIntersection; + + extraIntersection.globCellIndex = intersection.globCellIndex; + extraIntersection.startPoint = intersectionPoint; + extraIntersection.endPoint = intersection.endPoint; + extraIntersection.startMD = initialMD; + extraIntersection.endMD = intersection.endMD; + extraIntersection.intersectedCellFaceIn = cvf::StructGridInterface::NO_FACE; + extraIntersection.intersectedCellFaceOut = intersection.intersectedCellFaceOut; + + const RigMainGrid* grid = eclipseCase->mainGrid(); + + extraIntersection.intersectionLengthsInCellCS = + RigWellPathIntersectionTools::calculateLengthInCell( grid, + intersection.globCellIndex, + intersectionPoint, + intersection.endPoint ); + filteredIntersections.push_back( extraIntersection ); + } + } + + return filteredIntersections; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h index 14fa5cd310..f4b7b7abe8 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.h @@ -29,6 +29,9 @@ class RimWellPath; class RimWellPathValve; class RimWellPathFracture; class SubSegmentIntersectionInfo; +class RigWellPath; + +struct WellPathCellIntersectionInfo; class QFile; @@ -76,6 +79,15 @@ private: int timeStep, const std::vector& perforationIntervals ); + static std::vector + generateSubSegments( const RimEclipseCase* eclipseCase, const RimWellPath* wellPath, double& initialMD ); + + static std::vector + filterIntersections( const std::vector& intersections, + double initialMD, + const RigWellPath* wellPathGeometry, + const RimEclipseCase* eclipseCase ); + static void generateWelsegsTable( RifTextDataTableFormatter& formatter, const RicMswExportInfo& exportInfo ); static void generateWelsegsSegments( RifTextDataTableFormatter& formatter, From b1e631c32fd2178c8f13db32c5a9eb65e5312e68 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 6 Dec 2019 14:16:22 +0100 Subject: [PATCH 5/5] Fix notation --- .../RicWellPathExportMswCompletionsImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp index 0092436e2a..59453c659c 100644 --- a/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp +++ b/ApplicationCode/Commands/CompletionExportCommands/RicWellPathExportMswCompletionsImpl.cpp @@ -1165,7 +1165,7 @@ std::vector RicWellPathExportMswCompletionsImpl::f filteredIntersections.push_back( extraIntersection ); } - const double epsilon = 0.001; + const double epsilon = 1.0e-3; for ( const WellPathCellIntersectionInfo& intersection : intersections ) {