#1505 Fishbones : Calculate direction of a completion

This commit is contained in:
Bjørnar Grip Fjær 2017-05-22 13:23:48 +02:00
parent ee81f49ab1
commit b8557c8132
2 changed files with 225 additions and 60 deletions

View File

@ -186,26 +186,33 @@ void RicWellPathExportCompletionDataFeature::generateCompdatTable(RifEclipseOutp
{ {
for (const WellSegmentLateral& lateral : location.laterals) for (const WellSegmentLateral& lateral : location.laterals)
{ {
std::vector<size_t> cellIndices; formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex));
for (const WellSegmentLateralIntersection& intersection : lateral.intersections) for (const WellSegmentLateralIntersection& intersection : lateral.intersections)
{ {
if (settings.removeLateralsInMainBoreCells && intersection.mainBoreCell) continue; if (settings.removeLateralsInMainBoreCells && intersection.mainBoreCell) continue;
cellIndices.push_back(intersection.cellIndex); size_t i, j, k;
} grid->ijkFromCellIndex(intersection.cellIndex, &i, &j, &k);
std::vector<EclipseCellIndexRange> cellRanges = getCellIndexRange(grid, cellIndices); formatter.add(wellPath->name());
formatter.addZeroBasedCellIndex(i).addZeroBasedCellIndex(j).addZeroBasedCellIndex(k).addZeroBasedCellIndex(k);
formatter.comment(QString("Fishbone %1 - Sub: %2 - Lateral: %3").arg(location.fishbonesSubs->name()).arg(location.subIndex).arg(lateral.lateralIndex));
for (auto cellRange : cellRanges)
{
// Add cell indices
formatter.add(wellPath->name()).addZeroBasedCellIndex(cellRange.i).addZeroBasedCellIndex(cellRange.j).addZeroBasedCellIndex(cellRange.k1).addZeroBasedCellIndex(cellRange.k2);
// Remaining data, to be computed
formatter.add("'OPEN'").add("1*").add("1*"); formatter.add("'OPEN'").add("1*").add("1*");
// Diameter (originally in mm) in m
formatter.add(location.fishbonesSubs->holeRadius() / 1000); formatter.add(location.fishbonesSubs->holeRadius() / 1000);
formatter.add("1*").add("1*").add("1*"); formatter.add("1*").add("1*").add("1*");
formatter.add("'Z'"); // TODO - Calculate direction switch (intersection.direction)
{
case POS_I:
case NEG_I:
formatter.add("'X'");
break;
case POS_J:
case NEG_J:
formatter.add("'Y'");
break;
case POS_K:
case NEG_K:
formatter.add("'Z'");
break;
}
formatter.add("1*"); formatter.add("1*");
formatter.rowCompleted(); formatter.rowCompleted();
} }
@ -387,7 +394,21 @@ void RicWellPathExportCompletionDataFeature::generateCompsegsTable(RifEclipseOut
formatter.add(lateral.branchNumber); formatter.add(lateral.branchNumber);
formatter.add(length); formatter.add(length);
formatter.add("1*"); formatter.add("1*");
formatter.add("X"); // TODO - Calculate direction switch (intersection.direction)
{
case POS_I:
case NEG_I:
formatter.add("I");
break;
case POS_J:
case NEG_J:
formatter.add("J");
break;
case POS_K:
case NEG_K:
formatter.add("K");
break;
}
formatter.add(-1); formatter.add(-1);
formatter.rowCompleted(); formatter.rowCompleted();
} }
@ -483,6 +504,36 @@ bool RicWellPathExportCompletionDataFeature::cellOrdering(const EclipseCellIndex
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RicWellPathExportCompletionDataFeature::findCellFromCoords(const RigEclipseCaseData* caseData, const cvf::Vec3d& coords)
{
const std::vector<cvf::Vec3d>& nodeCoords = caseData->mainGrid()->nodes();
cvf::BoundingBox bb;
bb.add(coords);
std::vector<size_t> closeCells = findCloseCells(caseData, bb);
cvf::Vec3d hexCorners[8];
for (size_t closeCell : closeCells)
{
const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell];
if (cell.isInvalid()) continue;
setHexCorners(cell, nodeCoords, hexCorners);
if (RigHexIntersector::isPointInCell(coords, hexCorners, closeCell))
{
return closeCell;
}
}
// Coordinate is outside any cells?
CVF_ASSERT(false);
return 0;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -494,23 +545,10 @@ std::vector<size_t> RicWellPathExportCompletionDataFeature::findIntersectingCell
// Find starting cell // Find starting cell
if (coords.size() > 0) if (coords.size() > 0)
{ {
cvf::BoundingBox bb; size_t startCell = findCellFromCoords(caseData, coords[0]);
bb.add(coords[0]); if (startCell > 0)
std::vector<size_t> closeCells = findCloseCells(caseData, bb);
cvf::Vec3d hexCorners[8];
for (size_t closeCell : closeCells)
{ {
const RigCell& cell = caseData->mainGrid()->globalCellArray()[closeCell]; cells.insert(startCell);
if (cell.isInvalid()) continue;
setHexCorners(cell, nodeCoords, hexCorners);
if (RigHexIntersector::isPointInCell(coords[0], hexCorners, closeCell))
{
cells.insert(closeCell);
break;
}
} }
} }
@ -702,36 +740,59 @@ void RicWellPathExportCompletionDataFeature::calculateLateralIntersections(const
std::vector<HexIntersectionInfo> intersections = findIntersections(caseToApply->eclipseCaseData(), coords); std::vector<HexIntersectionInfo> intersections = findIntersections(caseToApply->eclipseCaseData(), coords);
filterIntersections(&intersections); filterIntersections(&intersections);
double length = 0; const HexIntersectionInfo* prevIntersection = nullptr;
double depth = 0;
cvf::Vec3d& startPoint = coords[0];
auto intersection = intersections.cbegin();
int attachedSegmentNumber = location->segmentNumber;
for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++)
{ {
if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint)) double length = 0;
{ double depth = 0;
cvf::Vec3d between = intersection->m_intersectionPoint - startPoint; cvf::Vec3d startPoint = coords[0];
length += between.length(); auto intersection = intersections.cbegin();
depth += intersection->m_intersectionPoint.z() - startPoint.z(); int attachedSegmentNumber = location->segmentNumber;
lateral.intersections.push_back(WellSegmentLateralIntersection(++(*segmentNum), attachedSegmentNumber, intersection->m_hexIndex, length, depth)); for (size_t i = 1; i < coords.size() && intersection != intersections.cend(); i++)
length = 0;
depth = 0;
startPoint = intersection->m_intersectionPoint;
attachedSegmentNumber = *segmentNum;
++intersection;
}
else
{ {
cvf::Vec3d between = coords[i] - startPoint; if (isPointBetween(startPoint, coords[i], intersection->m_intersectionPoint))
length += between.length(); {
depth += coords[i].z() - startPoint.z(); cvf::Vec3d between = intersection->m_intersectionPoint - startPoint;
startPoint = coords[i]; length += between.length();
depth += intersection->m_intersectionPoint.z() - startPoint.z();
// Find the direction of the previous cell
if (prevIntersection != nullptr)
{
std::pair<WellSegmentCellDirection, double> direction = calculateDirectionAndDistanceInCell(caseToApply->eclipseCaseData()->mainGrid(), prevIntersection->m_hexIndex, prevIntersection->m_intersectionPoint, intersection->m_intersectionPoint);
WellSegmentLateralIntersection& lateralIntersection = lateral.intersections[lateral.intersections.size() - 1];
lateralIntersection.direction = direction.first;
lateralIntersection.directionLength = direction.second;
}
lateral.intersections.push_back(WellSegmentLateralIntersection(++(*segmentNum), attachedSegmentNumber, intersection->m_hexIndex, length, depth));
length = 0;
depth = 0;
startPoint = intersection->m_intersectionPoint;
attachedSegmentNumber = *segmentNum;
++intersection;
prevIntersection = &*intersection;
}
else
{
const cvf::Vec3d between = coords[i] - startPoint;
length += between.length();
depth += coords[i].z() - startPoint.z();
startPoint = coords[i];
}
} }
} }
// Find the direction of the last cell
if (prevIntersection != nullptr && !coords.empty())
{
std::pair<WellSegmentCellDirection, double> direction = calculateDirectionAndDistanceInCell(caseToApply->eclipseCaseData()->mainGrid(), prevIntersection->m_hexIndex, prevIntersection->m_intersectionPoint, coords[coords.size()-1]);
WellSegmentLateralIntersection& lateralIntersection = lateral.intersections[lateral.intersections.size() - 1];
lateralIntersection.direction = direction.first;
lateralIntersection.directionLength = direction.second;
}
} }
} }
@ -754,3 +815,84 @@ void RicWellPathExportCompletionDataFeature::assignBranchAndSegmentNumbers(const
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature::calculateCellMainAxisDirections(const RigMainGrid* grid, size_t cellIndex, cvf::Vec3d* iAxisDirection, cvf::Vec3d* jAxisDirection, cvf::Vec3d* kAxisDirection)
{
const std::vector<cvf::Vec3d>& nodeCoords = grid->nodes();
cvf::Vec3d hexCorners[8];
const RigCell& cell = grid->globalCellArray()[cellIndex];
setHexCorners(cell, nodeCoords, hexCorners);
*iAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_I, cvf::StructGridInterface::POS_I);
*jAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_J, cvf::StructGridInterface::POS_J);
*kAxisDirection = calculateCellMainAxisDirection(hexCorners, cvf::StructGridInterface::FaceType::NEG_K, cvf::StructGridInterface::POS_K);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RicWellPathExportCompletionDataFeature::calculateCellMainAxisDirection(const cvf::Vec3d* hexCorners, cvf::StructGridInterface::FaceType startFace, cvf::StructGridInterface::FaceType endFace)
{
cvf::ubyte faceVertexIndices[4];
cvf::StructGridInterface::cellFaceVertexIndices(startFace, faceVertexIndices);
cvf::Vec3d startFaceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]);
cvf::StructGridInterface::cellFaceVertexIndices(endFace, faceVertexIndices);
cvf::Vec3d endFaceCenter = cvf::GeometryTools::computeFaceCenter(hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]]);
return endFaceCenter - startFaceCenter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<WellSegmentCellDirection, double> RicWellPathExportCompletionDataFeature::calculateDirectionAndDistanceInCell(const RigMainGrid* grid, size_t cellIndex, const cvf::Vec3d& startPoint, const cvf::Vec3d& endPoint)
{
cvf::Vec3d vec = endPoint - startPoint;
cvf::Vec3d iAxisDirection;
cvf::Vec3d jAxisDirection;
cvf::Vec3d kAxisDirection;
calculateCellMainAxisDirections(grid, cellIndex, &iAxisDirection, &jAxisDirection, &kAxisDirection);
double iLength = iAxisDirection.dot(vec);
double jLength = jAxisDirection.dot(vec);
double kLength = kAxisDirection.dot(vec);
double iNormalizedLength = abs(iLength / iAxisDirection.length());
double jNormalizedLength = abs(jLength / jAxisDirection.length());
double kNormalizedLength = abs(kLength / kAxisDirection.length());
if (iNormalizedLength > jNormalizedLength && iNormalizedLength > kNormalizedLength)
{
WellSegmentCellDirection direction = POS_I;
if (iLength < 0)
{
direction = NEG_I;
}
return std::make_pair(direction, iLength);
}
else if (jNormalizedLength > iNormalizedLength && jNormalizedLength > kNormalizedLength)
{
WellSegmentCellDirection direction = POS_J;
if (jLength < 0)
{
direction = NEG_J;
}
return std::make_pair(direction, jLength);
}
else
{
WellSegmentCellDirection direction = POS_K;
if (kLength < 0)
{
direction = NEG_K;
}
return std::make_pair(direction, kLength);
}
}

View File

@ -36,6 +36,18 @@ class RigMainGrid;
class RigCell; class RigCell;
class RimFishbonesMultipleSubs; class RimFishbonesMultipleSubs;
//==================================================================================================
///
//==================================================================================================
enum WellSegmentCellDirection {
POS_I,
NEG_I,
POS_J,
NEG_J,
POS_K,
NEG_K
};
//================================================================================================== //==================================================================================================
/// ///
//================================================================================================== //==================================================================================================
@ -46,15 +58,19 @@ struct WellSegmentLateralIntersection {
cellIndex(cellIndex), cellIndex(cellIndex),
length(length), length(length),
depth(depth), depth(depth),
direction(POS_I),
directionLength(-1.0),
mainBoreCell(false) mainBoreCell(false)
{} {}
int segmentNumber; int segmentNumber;
int attachedSegmentNumber; int attachedSegmentNumber;
size_t cellIndex; size_t cellIndex;
bool mainBoreCell; bool mainBoreCell;
double length; double length;
double depth; double depth;
WellSegmentCellDirection direction;
double directionLength;
}; };
//================================================================================================== //==================================================================================================
@ -128,6 +144,8 @@ private:
static std::map<size_t, double> computeLateralsPerCell(const std::vector<WellSegmentLocation>& segmentLocations, bool removeMainBoreCells); static std::map<size_t, double> computeLateralsPerCell(const std::vector<WellSegmentLocation>& segmentLocations, bool removeMainBoreCells);
static std::vector<size_t> findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb); static std::vector<size_t> findCloseCells(const RigEclipseCaseData* caseData, const cvf::BoundingBox& bb);
static size_t findCellFromCoords(const RigEclipseCaseData* caseData, const cvf::Vec3d& coords);
static std::vector<EclipseCellIndexRange> getCellIndexRange(const RigMainGrid* grid, const std::vector<size_t>& cellIndices); static std::vector<EclipseCellIndexRange> getCellIndexRange(const RigMainGrid* grid, const std::vector<size_t>& cellIndices);
static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2); static bool cellOrdering(const EclipseCellIndex& cell1, const EclipseCellIndex& cell2);
static std::vector<size_t> findIntersectingCells(const RigEclipseCaseData* grid, const std::vector<cvf::Vec3d>& coords); static std::vector<size_t> findIntersectingCells(const RigEclipseCaseData* grid, const std::vector<cvf::Vec3d>& coords);
@ -140,4 +158,9 @@ private:
static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply, RimWellPath* wellPath); static std::vector<WellSegmentLocation> findWellSegmentLocations(const RimEclipseCase* caseToApply, RimWellPath* wellPath);
static void calculateLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum); static void calculateLateralIntersections(const RimEclipseCase* caseToApply, WellSegmentLocation* location, int* branchNum, int* segmentNum);
static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector<WellSegmentLocation>* locations); static void assignBranchAndSegmentNumbers(const RimEclipseCase* caseToApply, std::vector<WellSegmentLocation>* locations);
// Calculate direction
static void calculateCellMainAxisDirections(const RigMainGrid* grid, size_t cellIndex, cvf::Vec3d* iAxisDirection, cvf::Vec3d* jAxisDirection, cvf::Vec3d* kAxisDirection);
static cvf::Vec3d calculateCellMainAxisDirection(const cvf::Vec3d* hexCorners, cvf::StructGridInterface::FaceType startFace, cvf::StructGridInterface::FaceType endFace);
static std::pair<WellSegmentCellDirection, double> calculateDirectionAndDistanceInCell(const RigMainGrid* grid, size_t cellIndex, const cvf::Vec3d& startPoint, const cvf::Vec3d& endPoint);
}; };