#1901 Use the more robust WellLogExtraction system for perforation interval intersection calculations.

This commit is contained in:
Jacob Støren
2017-09-19 17:20:49 +02:00
parent 3f099861a0
commit dc1844f5d5
10 changed files with 100 additions and 73 deletions

View File

@@ -179,7 +179,8 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneImportedLate
for (const RimFishboneWellPath* fishbonesPath : wellPath->fishbonesCollection()->wellPathCollection()->wellPaths()) for (const RimFishboneWellPath* fishbonesPath : wellPath->fishbonesCollection()->wellPathCollection()->wellPaths())
{ {
std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(),
fishbonesPath->coordinates()); fishbonesPath->coordinates(),
fishbonesPath->measuredDepths());
for (auto& cell : intersectedCells) for (auto& cell : intersectedCells)
{ {
if (std::find(wellPathCells.begin(), wellPathCells.end(), cell.cellIndex) != wellPathCells.end()) continue; if (std::find(wellPathCells.begin(), wellPathCells.end(), cell.cellIndex) != wellPathCells.end()) continue;
@@ -211,11 +212,12 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findMainWellBoreParts(st
double wellPathEndMD = 0.0; double wellPathEndMD = 0.0;
if (wellPathMD.size() > 1) wellPathEndMD = wellPathMD.back(); if (wellPathMD.size() > 1) wellPathEndMD = wellPathMD.back();
std::vector<cvf::Vec3d> fishbonePerfWellPathCoords = wellPath->wellPathGeometry()->clippedPointSubset(wellPath->fishbonesCollection()->startMD(), std::pair< std::vector<cvf::Vec3d>, std::vector<double> > fishbonePerfWellPathCoords = wellPath->wellPathGeometry()->clippedPointSubset(wellPath->fishbonesCollection()->startMD(),
wellPathEndMD); wellPathEndMD);
std::vector<WellPathCellIntersectionInfo> intersectedCellsIntersectionInfo = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), std::vector<WellPathCellIntersectionInfo> intersectedCellsIntersectionInfo = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(),
fishbonePerfWellPathCoords); fishbonePerfWellPathCoords.first,
fishbonePerfWellPathCoords.second);
for (auto& cell : intersectedCellsIntersectionInfo) for (auto& cell : intersectedCellsIntersectionInfo)
{ {

View File

@@ -716,9 +716,11 @@ std::vector<RigCompletionData> RicWellPathExportCompletionDataFeature::generateP
{ {
if (!interval->isActiveOnDate(settings.caseToApply->timeStepDates()[settings.timeStep])) continue; if (!interval->isActiveOnDate(settings.caseToApply->timeStepDates()[settings.timeStep])) continue;
std::vector<cvf::Vec3d> perforationPoints = wellPath->wellPathGeometry()->clippedPointSubset(interval->startMD(), interval->endMD()); using namespace std;
pair<vector<cvf::Vec3d>, vector<double> > perforationPointsAndMD = wellPath->wellPathGeometry()->clippedPointSubset(interval->startMD(), interval->endMD());
std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(), std::vector<WellPathCellIntersectionInfo> intersectedCells = RigWellPathIntersectionTools::findCellsIntersectedByPath(settings.caseToApply->eclipseCaseData(),
perforationPoints); perforationPointsAndMD.first,
perforationPointsAndMD.second);
for (auto& cell : intersectedCells) for (auto& cell : intersectedCells)
{ {
bool cellIsActive = activeCellInfo->isActive(cell.cellIndex); bool cellIsActive = activeCellInfo->isActive(cell.cellIndex);
@@ -861,9 +863,24 @@ void RicWellPathExportCompletionDataFeature::calculateLateralIntersections(const
for (WellSegmentLateral& lateral : location->laterals) for (WellSegmentLateral& lateral : location->laterals)
{ {
lateral.branchNumber = ++(*branchNum); lateral.branchNumber = ++(*branchNum);
std::vector<cvf::Vec3d> lateralCoords = location->fishbonesSubs->coordsForLateral(location->subIndex, lateral.lateralIndex);
std::vector<std::pair<cvf::Vec3d, double> > lateralCoordMDPairs = location->fishbonesSubs->coordsAndMDForLateral(location->subIndex, lateral.lateralIndex);
std::vector<cvf::Vec3d> lateralCoords;
std::vector<double> 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<WellPathCellIntersectionInfo> intersections = RigWellPathIntersectionTools::findCellsIntersectedByPath(caseToApply->eclipseCaseData(), std::vector<WellPathCellIntersectionInfo> intersections = RigWellPathIntersectionTools::findCellsIntersectedByPath(caseToApply->eclipseCaseData(),
lateralCoords); lateralCoords,
lateralMDs);
auto intersection = intersections.cbegin(); auto intersection = intersections.cbegin();
double length = 0; double length = 0;

View File

@@ -200,16 +200,18 @@ void RivWellPathPartMgr::appendPerforationsToModel(const QDateTime& currentViewD
if (currentViewDate.isValid() && !perforation->isActiveOnDate(currentViewDate)) continue; if (currentViewDate.isValid() && !perforation->isActiveOnDate(currentViewDate)) continue;
std::vector<cvf::Vec3d> displayCoords = wellPathGeometry->clippedPointSubset(perforation->startMD(), perforation->endMD()); using namespace std;
pair<vector<cvf::Vec3d>, vector<double> > 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<RivObjectSourceInfo> objectSourceInfo = new RivObjectSourceInfo(perforation); cvf::ref<RivObjectSourceInfo> objectSourceInfo = new RivObjectSourceInfo(perforation);
cvf::Collection<cvf::Part> parts; cvf::Collection<cvf::Part> parts;
geoGenerator.cylinderWithCenterLineParts(&parts, displayCoords, cvf::Color3f::GREEN, perforationRadius); geoGenerator.cylinderWithCenterLineParts(&parts, displayCoordsAndMD.first, cvf::Color3f::GREEN, perforationRadius);
for (auto part : parts) for (auto part : parts)
{ {
part->setSourceInfo(objectSourceInfo.p()); part->setSourceInfo(objectSourceInfo.p());

View File

@@ -148,9 +148,17 @@ void RimCompletionCellIntersectionCalc::calculateFishbonesIntersections(const Ri
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimCompletionCellIntersectionCalc::calculatePerforationIntersections(const RimWellPath* wellPath, const RimPerforationInterval* perforationInterval, const RigMainGrid* grid, std::vector<double>& values) void RimCompletionCellIntersectionCalc::calculatePerforationIntersections(const RimWellPath* wellPath,
const RimPerforationInterval* perforationInterval,
const RigMainGrid* grid,
std::vector<double>& values)
{ {
std::vector<HexIntersectionInfo> intersections = RigWellPathIntersectionTools::getIntersectedCells(grid, wellPath->wellPathGeometry()->clippedPointSubset(perforationInterval->startMD(), perforationInterval->endMD())); using namespace std;
pair<vector<cvf::Vec3d>, vector<double> > clippedWellPathData = wellPath->wellPathGeometry()->clippedPointSubset(perforationInterval->startMD(),
perforationInterval->endMD());
std::vector<HexIntersectionInfo> intersections = RigWellPathIntersectionTools::getIntersectedCells(grid,
clippedWellPathData.first);
for (auto& intersection : intersections) for (auto& intersection : intersections)
{ {
values[intersection.m_hexIndex] = RiaDefines::PERFORATION_INTERVAL; values[intersection.m_hexIndex] = RiaDefines::PERFORATION_INTERVAL;

View File

@@ -27,6 +27,7 @@
#include "RigWellLogExtractionTools.h" #include "RigWellLogExtractionTools.h"
#include "RigMainGrid.h" #include "RigMainGrid.h"
#include "RigWellPathIntersectionTools.h"
//================================================================================================== //==================================================================================================
/// ///
@@ -131,6 +132,31 @@ void RigEclipseWellLogExtractor::curveData(const RigResultAccessor* resultAccess
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<WellPathCellIntersectionInfo> RigEclipseWellLogExtractor::cellIntersectionInfo()
{
std::vector<WellPathCellIntersectionInfo> 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;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -28,6 +28,7 @@
#include <vector> #include <vector>
#include "cvfStructGrid.h" #include "cvfStructGrid.h"
#include "RigWellPathIntersectionTools.h"
class RigEclipseCaseData; class RigEclipseCaseData;
class RigWellPath; class RigWellPath;
@@ -48,6 +49,8 @@ public:
void curveData(const RigResultAccessor* resultAccessor, std::vector<double>* values ); void curveData(const RigResultAccessor* resultAccessor, std::vector<double>* values );
const RigEclipseCaseData* caseData() { return m_caseData.p();} const RigEclipseCaseData* caseData() { return m_caseData.p();}
std::vector<WellPathCellIntersectionInfo> cellIntersectionInfo();
protected: protected:
void calculateIntersection(); void calculateIntersection();
std::vector<size_t> findCloseCells(const cvf::BoundingBox& bb); std::vector<size_t> findCloseCells(const cvf::BoundingBox& bb);

View File

@@ -192,25 +192,29 @@ void RigWellPath::twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, c
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RigWellPath::clippedPointSubset(double startMD, double endMD) const std::pair<std::vector<cvf::Vec3d>, std::vector<double> > RigWellPath::clippedPointSubset(double startMD, double endMD) const
{ {
std::vector<cvf::Vec3d> points; std::pair<std::vector<cvf::Vec3d>, std::vector<double> > pointsAndMDs;
if (m_measuredDepths.empty()) return points; if (m_measuredDepths.empty()) return pointsAndMDs;
if (startMD > endMD) return points; 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) for (size_t i = 0; i < m_measuredDepths.size(); ++i)
{ {
double measuredDepth = m_measuredDepths[i]; double measuredDepth = m_measuredDepths[i];
if (measuredDepth > startMD && measuredDepth < endMD) 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;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -43,7 +43,9 @@ public:
cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth) const; cvf::Vec3d interpolatedPointAlongWellPath(double measuredDepth) const;
double wellPathAzimuthAngle(const cvf::Vec3d& position) const; double wellPathAzimuthAngle(const cvf::Vec3d& position) const;
void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const; void twoClosestPoints(const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2) const;
std::vector<cvf::Vec3d> clippedPointSubset(double startMD, double endMD) const;
std::pair<std::vector<cvf::Vec3d>, std::vector<double> >
clippedPointSubset(double startMD, double endMD) const;
std::vector<cvf::Vec3d> wellPathPointsIncludingFractureIntersection(double fractureIntersectionMD) const; std::vector<cvf::Vec3d> wellPathPointsIncludingFractureIntersection(double fractureIntersectionMD) const;
private: private:

View File

@@ -28,68 +28,29 @@
#include "cvfGeometryTools.h" #include "cvfGeometryTools.h"
#include "cvfMatrix3.h" #include "cvfMatrix3.h"
#include "RigEclipseWellLogExtractor.h"
#include "RimEclipseCase.h"
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<WellPathCellIntersectionInfo> RigWellPathIntersectionTools::findCellsIntersectedByPath(const RigEclipseCaseData* caseData, std::vector<WellPathCellIntersectionInfo> RigWellPathIntersectionTools::findCellsIntersectedByPath(const RigEclipseCaseData* caseData,
const std::vector<cvf::Vec3d>& pathCoords) const std::vector<cvf::Vec3d>& pathCoords,
const std::vector<double>& pathMds)
{ {
std::vector<WellPathCellIntersectionInfo> intersectionInfos; std::vector<WellPathCellIntersectionInfo> intersectionInfos;
const RigMainGrid* grid = caseData->mainGrid(); const RigMainGrid* grid = caseData->mainGrid();
if (pathCoords.size() < 2) return intersectionInfos; if (pathCoords.size() < 2) return intersectionInfos;
cvf::ref<RigWellPath> dummyWellPath = new RigWellPath;
dummyWellPath->m_wellPathPoints = pathCoords;
dummyWellPath->m_measuredDepths = pathMds;
std::vector<HexIntersectionInfo> intersections = getIntersectedCells(grid, pathCoords); cvf::ref<RigEclipseWellLogExtractor> extractor = new RigEclipseWellLogExtractor(caseData, dummyWellPath.p(), caseData->ownerCase()->caseUserDescription().toStdString());
removeEnteringIntersections(&intersections);
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;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -53,7 +53,9 @@ struct WellPathCellIntersectionInfo {
class RigWellPathIntersectionTools class RigWellPathIntersectionTools
{ {
public: public:
static std::vector<WellPathCellIntersectionInfo> findCellsIntersectedByPath(const RigEclipseCaseData* caseData, const std::vector<cvf::Vec3d>& pathCoords); static std::vector<WellPathCellIntersectionInfo> findCellsIntersectedByPath(const RigEclipseCaseData* caseData,
const std::vector<cvf::Vec3d>& pathCoords,
const std::vector<double>& pathMds);
static std::vector<HexIntersectionInfo> getIntersectedCells(const RigMainGrid* grid, const std::vector<cvf::Vec3d>& coords); static std::vector<HexIntersectionInfo> getIntersectedCells(const RigMainGrid* grid, const std::vector<cvf::Vec3d>& coords);