From dc1844f5d55c7f9611c13a0aa78f5fb3bfbe982b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 19 Sep 2017 17:20:49 +0200 Subject: [PATCH] #1901 Use the more robust WellLogExtraction system for perforation interval intersection calculations. --- ...sTransmissibilityCalculationFeatureImp.cpp | 10 ++-- ...RicWellPathExportCompletionDataFeature.cpp | 25 ++++++-- .../ModelVisualization/RivWellPathPartMgr.cpp | 10 ++-- .../RimCompletionCellIntersectionCalc.cpp | 12 +++- .../RigEclipseWellLogExtractor.cpp | 26 ++++++++ .../RigEclipseWellLogExtractor.h | 3 + .../ReservoirDataModel/RigWellPath.cpp | 20 ++++--- .../ReservoirDataModel/RigWellPath.h | 4 +- .../RigWellPathIntersectionTools.cpp | 59 ++++--------------- .../RigWellPathIntersectionTools.h | 4 +- 10 files changed, 100 insertions(+), 73 deletions(-) diff --git a/ApplicationCode/Commands/CompletionCommands/RicFishbonesTransmissibilityCalculationFeatureImp.cpp b/ApplicationCode/Commands/CompletionCommands/RicFishbonesTransmissibilityCalculationFeatureImp.cpp index 928ebadca4..626e1d73b7 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicFishbonesTransmissibilityCalculationFeatureImp.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicFishbonesTransmissibilityCalculationFeatureImp.cpp @@ -179,7 +179,8 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneImportedLate for (const RimFishboneWellPath* fishbonesPath : wellPath->fishbonesCollection()->wellPathCollection()->wellPaths()) { std::vector intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), - fishbonesPath->coordinates()); + fishbonesPath->coordinates(), + fishbonesPath->measuredDepths()); for (auto& cell : intersectedCells) { if (std::find(wellPathCells.begin(), wellPathCells.end(), cell.cellIndex) != wellPathCells.end()) continue; @@ -211,11 +212,12 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findMainWellBoreParts(st double wellPathEndMD = 0.0; if (wellPathMD.size() > 1) wellPathEndMD = wellPathMD.back(); - std::vector fishbonePerfWellPathCoords = wellPath->wellPathGeometry()->clippedPointSubset(wellPath->fishbonesCollection()->startMD(), - wellPathEndMD); + std::pair< std::vector, std::vector > fishbonePerfWellPathCoords = wellPath->wellPathGeometry()->clippedPointSubset(wellPath->fishbonesCollection()->startMD(), + wellPathEndMD); std::vector intersectedCellsIntersectionInfo = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), - fishbonePerfWellPathCoords); + fishbonePerfWellPathCoords.first, + fishbonePerfWellPathCoords.second); for (auto& cell : intersectedCellsIntersectionInfo) { diff --git a/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp b/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp index 25d0646cd9..d64d7a55ae 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicWellPathExportCompletionDataFeature.cpp @@ -716,9 +716,11 @@ std::vector RicWellPathExportCompletionDataFeature::generateP { if (!interval->isActiveOnDate(settings.caseToApply->timeStepDates()[settings.timeStep])) continue; - std::vector perforationPoints = wellPath->wellPathGeometry()->clippedPointSubset(interval->startMD(), interval->endMD()); + using namespace std; + pair, vector > perforationPointsAndMD = wellPath->wellPathGeometry()->clippedPointSubset(interval->startMD(), interval->endMD()); std::vector intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), - perforationPoints); + perforationPointsAndMD.first, + perforationPointsAndMD.second); for (auto& cell : intersectedCells) { bool cellIsActive = activeCellInfo->isActive(cell.cellIndex); @@ -861,9 +863,24 @@ void RicWellPathExportCompletionDataFeature::calculateLateralIntersections(const for (WellSegmentLateral& lateral : location->laterals) { lateral.branchNumber = ++(*branchNum); - std::vector lateralCoords = location->fishbonesSubs->coordsForLateral(location->subIndex, lateral.lateralIndex); + + std::vector > lateralCoordMDPairs = location->fishbonesSubs->coordsAndMDForLateral(location->subIndex, lateral.lateralIndex); + + std::vector lateralCoords; + std::vector lateralMDs; + + lateralCoords.reserve(lateralCoordMDPairs.size()); + lateralMDs.reserve(lateralCoordMDPairs.size()); + + for (auto& coordMD : lateralCoordMDPairs) + { + lateralCoords.push_back(coordMD.first); + lateralMDs.push_back(coordMD.second); + } + std::vector intersections = RigWellPathIntersectionTools::findCellsIntersectedByPath(caseToApply->eclipseCaseData(), - lateralCoords); + lateralCoords, + lateralMDs); auto intersection = intersections.cbegin(); double length = 0; diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 522cfce4ab..40d6fc5d5f 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -200,16 +200,18 @@ void RivWellPathPartMgr::appendPerforationsToModel(const QDateTime& currentViewD if (currentViewDate.isValid() && !perforation->isActiveOnDate(currentViewDate)) continue; - std::vector displayCoords = wellPathGeometry->clippedPointSubset(perforation->startMD(), perforation->endMD()); + using namespace std; + pair, vector > displayCoordsAndMD = wellPathGeometry->clippedPointSubset(perforation->startMD(), + perforation->endMD()); - if (displayCoords.size() < 2) continue; + if (displayCoordsAndMD.first.size() < 2) continue; - for (cvf::Vec3d& point : displayCoords) point = displayCoordTransform->transformToDisplayCoord(point); + for (cvf::Vec3d& point : displayCoordsAndMD.first) point = displayCoordTransform->transformToDisplayCoord(point); cvf::ref objectSourceInfo = new RivObjectSourceInfo(perforation); cvf::Collection parts; - geoGenerator.cylinderWithCenterLineParts(&parts, displayCoords, cvf::Color3f::GREEN, perforationRadius); + geoGenerator.cylinderWithCenterLineParts(&parts, displayCoordsAndMD.first, cvf::Color3f::GREEN, perforationRadius); for (auto part : parts) { part->setSourceInfo(objectSourceInfo.p()); diff --git a/ApplicationCode/ProjectDataModel/Completions/RimCompletionCellIntersectionCalc.cpp b/ApplicationCode/ProjectDataModel/Completions/RimCompletionCellIntersectionCalc.cpp index 1c0d610a5e..84166da951 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimCompletionCellIntersectionCalc.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimCompletionCellIntersectionCalc.cpp @@ -148,9 +148,17 @@ void RimCompletionCellIntersectionCalc::calculateFishbonesIntersections(const Ri //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimCompletionCellIntersectionCalc::calculatePerforationIntersections(const RimWellPath* wellPath, const RimPerforationInterval* perforationInterval, const RigMainGrid* grid, std::vector& values) +void RimCompletionCellIntersectionCalc::calculatePerforationIntersections(const RimWellPath* wellPath, + const RimPerforationInterval* perforationInterval, + const RigMainGrid* grid, + std::vector& values) { - std::vector intersections = RigWellPathIntersectionTools::getIntersectedCells(grid, wellPath->wellPathGeometry()->clippedPointSubset(perforationInterval->startMD(), perforationInterval->endMD())); + using namespace std; + pair, vector > clippedWellPathData = wellPath->wellPathGeometry()->clippedPointSubset(perforationInterval->startMD(), + perforationInterval->endMD()); + + std::vector intersections = RigWellPathIntersectionTools::getIntersectedCells(grid, + clippedWellPathData.first); for (auto& intersection : intersections) { values[intersection.m_hexIndex] = RiaDefines::PERFORATION_INTERVAL; diff --git a/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.cpp b/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.cpp index edb8648b81..9d5fb6aa2a 100644 --- a/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.cpp @@ -27,6 +27,7 @@ #include "RigWellLogExtractionTools.h" #include "RigMainGrid.h" +#include "RigWellPathIntersectionTools.h" //================================================================================================== /// @@ -131,6 +132,31 @@ void RigEclipseWellLogExtractor::curveData(const RigResultAccessor* resultAccess } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigEclipseWellLogExtractor::cellIntersectionInfo() +{ + std::vector cellIntersectionInfos; + cellIntersectionInfos.reserve(m_intersections.size()-1); + + for (size_t cpIdx = 0; cpIdx < m_intersections.size()-1; ++cpIdx) + { + size_t cellIdx1 = m_intersectedCells[cpIdx]; + size_t cellIdx2 = m_intersectedCells[cpIdx+1]; + + if (cellIdx1 == cellIdx2) + { + cvf::Vec3d internalCellLengths; + internalCellLengths = RigWellPathIntersectionTools::calculateLengthInCell( m_caseData->mainGrid(), cellIdx1, m_intersections[cpIdx], m_intersections[cpIdx+1] ); + + cellIntersectionInfos.push_back(WellPathCellIntersectionInfo(cellIdx1, m_intersections[cpIdx], m_intersections[cpIdx+1], internalCellLengths)); + } + } + + return cellIntersectionInfos; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.h b/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.h index abb0c3b03b..2b114e9c24 100644 --- a/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.h +++ b/ApplicationCode/ReservoirDataModel/RigEclipseWellLogExtractor.h @@ -28,6 +28,7 @@ #include #include "cvfStructGrid.h" +#include "RigWellPathIntersectionTools.h" class RigEclipseCaseData; class RigWellPath; @@ -48,6 +49,8 @@ public: void curveData(const RigResultAccessor* resultAccessor, std::vector* values ); const RigEclipseCaseData* caseData() { return m_caseData.p();} + std::vector cellIntersectionInfo(); + protected: void calculateIntersection(); std::vector findCloseCells(const cvf::BoundingBox& bb); diff --git a/ApplicationCode/ReservoirDataModel/RigWellPath.cpp b/ApplicationCode/ReservoirDataModel/RigWellPath.cpp index f792176a82..301872bb17 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPath.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellPath.cpp @@ -192,25 +192,29 @@ void RigWellPath::twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RigWellPath::clippedPointSubset(double startMD, double endMD) const +std::pair, std::vector > RigWellPath::clippedPointSubset(double startMD, double endMD) const { - std::vector points; - if (m_measuredDepths.empty()) return points; - if (startMD > endMD) return points; + std::pair, std::vector > pointsAndMDs; + if (m_measuredDepths.empty()) return pointsAndMDs; + if (startMD > endMD) return pointsAndMDs; + + pointsAndMDs.first.push_back(interpolatedPointAlongWellPath(startMD)); + pointsAndMDs.second.push_back(startMD); - points.push_back(interpolatedPointAlongWellPath(startMD)); for (size_t i = 0; i < m_measuredDepths.size(); ++i) { double measuredDepth = m_measuredDepths[i]; if (measuredDepth > startMD && measuredDepth < endMD) { - points.push_back(m_wellPathPoints[i]); + pointsAndMDs.first.push_back(m_wellPathPoints[i]); + pointsAndMDs.second.push_back(measuredDepth); } } - points.push_back(interpolatedPointAlongWellPath(endMD)); + pointsAndMDs.first.push_back(interpolatedPointAlongWellPath(endMD)); + pointsAndMDs.second.push_back(endMD); - return points; + return pointsAndMDs; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigWellPath.h b/ApplicationCode/ReservoirDataModel/RigWellPath.h index 4f563e612a..9f66d4d68a 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPath.h +++ b/ApplicationCode/ReservoirDataModel/RigWellPath.h @@ -43,7 +43,9 @@ public: cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth) const; double wellPathAzimuthAngle(const cvf::Vec3d& position) const; void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const; - std::vector clippedPointSubset(double startMD, double endMD) const; + + std::pair, std::vector > + clippedPointSubset(double startMD, double endMD) const; std::vector wellPathPointsIncludingFractureIntersection(double fractureIntersectionMD) const; private: diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.cpp b/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.cpp index e0ddf64047..7194975fad 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.cpp @@ -28,68 +28,29 @@ #include "cvfGeometryTools.h" #include "cvfMatrix3.h" +#include "RigEclipseWellLogExtractor.h" +#include "RimEclipseCase.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RigWellPathIntersectionTools::findCellsIntersectedByPath(const RigEclipseCaseData* caseData, - const std::vector& pathCoords) + const std::vector& pathCoords, + const std::vector& pathMds) { std::vector intersectionInfos; const RigMainGrid* grid = caseData->mainGrid(); if (pathCoords.size() < 2) return intersectionInfos; + cvf::ref dummyWellPath = new RigWellPath; + dummyWellPath->m_wellPathPoints = pathCoords; + dummyWellPath->m_measuredDepths = pathMds; - std::vector intersections = getIntersectedCells(grid, pathCoords); - removeEnteringIntersections(&intersections); + cvf::ref extractor = new RigEclipseWellLogExtractor(caseData, dummyWellPath.p(), caseData->ownerCase()->caseUserDescription().toStdString()); - if (intersections.empty()) return intersectionInfos; + return extractor->cellIntersectionInfo(); - cvf::Vec3d startPoint; - cvf::Vec3d endPoint; - size_t cellIndex; - cvf::Vec3d internalCellLengths; - - auto intersection = intersections.cbegin(); - - //start cell - bool foundCell; - startPoint = pathCoords[0]; - cellIndex = findCellFromCoords(grid, startPoint, &foundCell); - if (foundCell) - { - endPoint = intersection->m_intersectionPoint; - internalCellLengths = calculateLengthInCell(grid, cellIndex, startPoint, endPoint); - intersectionInfos.push_back(WellPathCellIntersectionInfo(cellIndex, startPoint, endPoint, internalCellLengths)); - } - else - { - RiaLogging::debug("Path starts outside valid cell"); - } - - //center cells - startPoint = intersection->m_intersectionPoint; - cellIndex = intersection->m_hexIndex; - - ++intersection; - - while (intersection != intersections.cend()) - { - endPoint = intersection->m_intersectionPoint; - internalCellLengths = calculateLengthInCell(grid, cellIndex, startPoint, endPoint); - intersectionInfos.push_back(WellPathCellIntersectionInfo(cellIndex, startPoint, endPoint, internalCellLengths)); - - startPoint = endPoint; - cellIndex = intersection->m_hexIndex; - ++intersection; - } - - //end cell - endPoint = pathCoords[pathCoords.size() - 1]; - internalCellLengths = calculateLengthInCell(grid, cellIndex, startPoint, endPoint); - intersectionInfos.push_back(WellPathCellIntersectionInfo(cellIndex, startPoint, endPoint, internalCellLengths)); - - return intersectionInfos; + } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.h b/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.h index 705ca69654..a54b15fa8b 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.h +++ b/ApplicationCode/ReservoirDataModel/RigWellPathIntersectionTools.h @@ -53,7 +53,9 @@ struct WellPathCellIntersectionInfo { class RigWellPathIntersectionTools { public: - static std::vector findCellsIntersectedByPath(const RigEclipseCaseData* caseData, const std::vector& pathCoords); + static std::vector findCellsIntersectedByPath(const RigEclipseCaseData* caseData, + const std::vector& pathCoords, + const std::vector& pathMds); static std::vector getIntersectedCells(const RigMainGrid* grid, const std::vector& coords);