mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#1505 Fishbones : Calculate direction of a completion
This commit is contained in:
parent
ee81f49ab1
commit
b8557c8132
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user