mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#1542 Always using radial transmissibility calculation if the fracture is transverse to well or azimuth. If alog well: Perforation length for fracture limits the intersection fracture/well.
This commit is contained in:
parent
56579e7b3e
commit
1f87681d7e
@ -147,48 +147,77 @@ std::vector<RigCompletionData> RicExportFractureCompletionsImpl::generateFractur
|
||||
|
||||
/////
|
||||
// Calculate transmissibility into the well
|
||||
|
||||
RigWellPathStimplanIntersector wellFractureIntersector(wellPath->wellPathGeometry(), fracture);
|
||||
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection >& fractureWellCells = wellFractureIntersector.intersections();
|
||||
|
||||
for (const auto& fracCellIdxIsectDataPair : fractureWellCells)
|
||||
|
||||
////
|
||||
//If fracture has orientation Azimuth or Transverse, assume only radial inflow
|
||||
if (fracture->attachedFractureDefinition()->orientation() == RimFractureTemplate::AZIMUTH
|
||||
|| fracture->attachedFractureDefinition()->orientation() == RimFractureTemplate::TRANSVERSE_WELL_PATH)
|
||||
{
|
||||
size_t fracWellCellIdx = fracCellIdxIsectDataPair.first;
|
||||
RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second;
|
||||
const RigFractureGrid* fracGrid = fracture->attachedFractureDefinition()->fractureGrid();
|
||||
std::pair<size_t, size_t> wellCellIJ = fracGrid->fractureCellAtWellCenter();
|
||||
size_t wellCellIndex = fracGrid->getGlobalIndexFromIJ(wellCellIJ.first, wellCellIJ.second);
|
||||
const RigFractureCell wellCell = fractureGrid->cellFromIndex(wellCellIndex);
|
||||
|
||||
const RigFractureCell fractureWellCell = fractureGrid->cellFromIndex(fracWellCellIdx);
|
||||
double radialTrans = RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(wellCell.getConductivtyValue(),
|
||||
wellCell.cellSizeX(),
|
||||
wellCell.cellSizeZ(),
|
||||
fracture->wellRadius(),
|
||||
fracTemplate->skinFactor(),
|
||||
cDarcyInCorrectUnit);
|
||||
|
||||
double radialTrans = 0.0;
|
||||
if (intersection.endpointCount)
|
||||
{
|
||||
radialTrans = RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(fractureWellCell.getConductivtyValue(),
|
||||
fractureWellCell.cellSizeX(),
|
||||
fractureWellCell.cellSizeZ(),
|
||||
fracture->wellRadius(),
|
||||
fracTemplate->skinFactor(),
|
||||
cDarcyInCorrectUnit);
|
||||
}
|
||||
|
||||
double linearTrans = 0.0;
|
||||
if (intersection.hlength > 0.0 || intersection.vlength > 0.0 )
|
||||
{
|
||||
linearTrans = RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(fractureWellCell.getConductivtyValue(),
|
||||
fractureWellCell.cellSizeX(),
|
||||
fractureWellCell.cellSizeZ(),
|
||||
intersection.vlength,
|
||||
intersection.hlength ,
|
||||
fracture->perforationEfficiency,
|
||||
fracTemplate->skinFactor(),
|
||||
cDarcyInCorrectUnit);
|
||||
}
|
||||
|
||||
double totalWellTrans = 0.5 * intersection.endpointCount * radialTrans + linearTrans;
|
||||
|
||||
transCondenser.addNeighborTransmissibility( { true, RigTransmissibilityCondenser::CellAddress::WELL, 1},
|
||||
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fracWellCellIdx },
|
||||
totalWellTrans);
|
||||
transCondenser.addNeighborTransmissibility({ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
|
||||
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, wellCellIndex },
|
||||
radialTrans);
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
//If fracture has orientation along well, assume only linear inflow
|
||||
if (fracture->attachedFractureDefinition()->orientation() == RimFractureTemplate::ALONG_WELL_PATH)
|
||||
{
|
||||
RigWellPathStimplanIntersector wellFractureIntersector(wellPath->wellPathGeometry(), fracture);
|
||||
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection >& fractureWellCells = wellFractureIntersector.intersections();
|
||||
|
||||
for (const auto& fracCellIdxIsectDataPair : fractureWellCells)
|
||||
{
|
||||
size_t fracWellCellIdx = fracCellIdxIsectDataPair.first;
|
||||
RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second;
|
||||
|
||||
const RigFractureCell fractureWellCell = fractureGrid->cellFromIndex(fracWellCellIdx);
|
||||
|
||||
double radialTrans = 0.0;
|
||||
if (intersection.endpointCount)
|
||||
{
|
||||
radialTrans = RigFractureTransmissibilityEquations::fractureCellToWellRadialTrans(fractureWellCell.getConductivtyValue(),
|
||||
fractureWellCell.cellSizeX(),
|
||||
fractureWellCell.cellSizeZ(),
|
||||
fracture->wellRadius(),
|
||||
fracTemplate->skinFactor(),
|
||||
cDarcyInCorrectUnit);
|
||||
}
|
||||
|
||||
double linearTrans = 0.0;
|
||||
if (intersection.hlength > 0.0 || intersection.vlength > 0.0 )
|
||||
{
|
||||
linearTrans = RigFractureTransmissibilityEquations::fractureCellToWellLinearTrans(fractureWellCell.getConductivtyValue(),
|
||||
fractureWellCell.cellSizeX(),
|
||||
fractureWellCell.cellSizeZ(),
|
||||
intersection.vlength,
|
||||
intersection.hlength ,
|
||||
fracture->perforationEfficiency,
|
||||
fracTemplate->skinFactor(),
|
||||
cDarcyInCorrectUnit);
|
||||
}
|
||||
|
||||
double totalWellTrans = 0.5 * intersection.endpointCount * radialTrans + linearTrans;
|
||||
|
||||
transCondenser.addNeighborTransmissibility( { true, RigTransmissibilityCondenser::CellAddress::WELL, 1},
|
||||
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, fracWellCellIdx },
|
||||
totalWellTrans);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////
|
||||
// Insert total transmissibility from eclipse-cell to well for this fracture into the map
|
||||
|
||||
|
@ -497,11 +497,6 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
|
||||
commandIds << "RicNewSimWellFractureFeature";
|
||||
commandIds << "RicExportSelectedSimWellFractureWellCompletionFeature";
|
||||
}
|
||||
else if (dynamic_cast<RimWellPath*>(uiItem))
|
||||
{
|
||||
commandIds << "RicExportSelectedWellPathFractureWellCompletionFeature";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
size_t jCellCount() const { return m_jCellCount; }
|
||||
size_t iCellCount() const { return m_iCellCount; }
|
||||
|
||||
std::pair<size_t, size_t> fractureCellAtWellCenter() const { return m_wellCenterFractureCellIJ; }
|
||||
std::pair<size_t, size_t> fractureCellAtWellCenter() const { return m_wellCenterFractureCellIJ; }
|
||||
|
||||
|
||||
private:
|
||||
|
@ -27,8 +27,9 @@ RigWellPathStimplanIntersector::RigWellPathStimplanIntersector(const RigWellPath
|
||||
for ( const auto& stpCell: stpCells ) stpCellPolygons.push_back(stpCell.getPolygon());
|
||||
}
|
||||
}
|
||||
double perforationLength = rimFracture->perforationLength();
|
||||
|
||||
calculate(fractureXf, wellPathPoints, wellRadius, stpCellPolygons, m_stimPlanCellIdxToIntersectionInfoMap);
|
||||
calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, m_stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
}
|
||||
|
||||
@ -39,27 +40,17 @@ RigWellPathStimplanIntersector::RigWellPathStimplanIntersector(const RigWellPath
|
||||
void RigWellPathStimplanIntersector::calculate(const cvf::Mat4f &fractureXf,
|
||||
const std::vector<cvf::Vec3d>& wellPathPointsOrg,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, WellCellIntersection>& m_stimPlanCellIdxToIntersectionInfoMap)
|
||||
{
|
||||
cvf::Mat4d toFractureXf = cvf::Mat4d(fractureXf.getInverted());
|
||||
|
||||
//Find bounding box
|
||||
cvf::BoundingBox polygonBBox;
|
||||
for (std::vector<cvf::Vec3d> fracCellPolygon : stpCellPolygons)
|
||||
{
|
||||
for (cvf::Vec3d nodeCoord : fracCellPolygon) polygonBBox.add(nodeCoord);
|
||||
}
|
||||
cvf::Vec3d bboxCorners[8];
|
||||
polygonBBox.cornerVertices(bboxCorners);
|
||||
|
||||
//put BB corners into polygon, to use clipPolylineByPolygon function below
|
||||
//Since we are in 2D, the 4 corners of the boundingbox are repeated so only 4 are included in the polygon
|
||||
std::vector<cvf::Vec3d> boundingBoxPolygon;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
boundingBoxPolygon.push_back(bboxCorners[i]);
|
||||
}
|
||||
std::vector<cvf::Vec3d> perforationLengthBoundingBoxPolygon;
|
||||
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(-perforationLength / 2, -perforationLength / 2, 0));
|
||||
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d( perforationLength / 2, -perforationLength / 2, 0));
|
||||
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d( perforationLength / 2, perforationLength / 2, 0));
|
||||
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(-perforationLength / 2, perforationLength / 2, 0));
|
||||
|
||||
// Convert well path to fracture template system
|
||||
|
||||
@ -69,7 +60,7 @@ void RigWellPathStimplanIntersector::calculate(const cvf::Mat4f &fractureXf,
|
||||
// Clip well path to fracture domain
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d> > wellPathPartsWithinFracture =
|
||||
RigCellGeometryTools::clipPolylineByPolygon(fractureRelativeWellPathPoints, boundingBoxPolygon, RigCellGeometryTools::INTERPOLATE_LINE_Z);
|
||||
RigCellGeometryTools::clipPolylineByPolygon(fractureRelativeWellPathPoints, perforationLengthBoundingBoxPolygon, RigCellGeometryTools::INTERPOLATE_LINE_Z);
|
||||
|
||||
// Remove the part of the well path that is more than well radius away from the fracture plane
|
||||
|
||||
|
@ -47,6 +47,7 @@ private:
|
||||
static void calculate(const cvf::Mat4f& fractureXf,
|
||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
@ -58,13 +59,13 @@ class RigWellPathStimplanIntersectorTester
|
||||
{
|
||||
public:
|
||||
static void testCalculate(const cvf::Mat4f& fractureXf,
|
||||
const std::vector<cvf::Vec3f>& fracturePolygon,
|
||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||
double wellRadius,
|
||||
double perforationLength,
|
||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap)
|
||||
{
|
||||
RigWellPathStimplanIntersector::calculate(fractureXf, wellPathPoints, wellRadius, stpCellPolygons, stimPlanCellIdxToIntersectionInfoMap);
|
||||
RigWellPathStimplanIntersector::calculate(fractureXf, wellPathPoints, wellRadius, perforationLength, stpCellPolygons, stimPlanCellIdxToIntersectionInfoMap);
|
||||
}
|
||||
|
||||
};
|
@ -315,7 +315,8 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
cvf::Mat4f fractureXf = cvf::Mat4f::IDENTITY;
|
||||
fractureXf.setTranslation({ 50.0f, 0.0f, 0.0f });
|
||||
|
||||
std::vector<cvf::Vec3f> fracturePolygon ={ {0.0f, 0.0f, 0.0f}, {5.0f, 10.0f, 0.0f}, {10.0f, 0.0f, 0.0f} };
|
||||
//std::vector<cvf::Vec3f> fracturePolygon ={ {0.0f, 0.0f, 0.0f}, {5.0f, 10.0f, 0.0f}, {10.0f, 0.0f, 0.0f} };
|
||||
double perforationLength = 25.0;
|
||||
std::vector<cvf::Vec3d> wellPathPoints ={ {50.0f-4.0f, 6.0f, 10.0f}, {50.0f+6.0f, 6.0f, 0.0f}, {50.0f+10.0f, 10.0f, -100.0f} };
|
||||
double wellRadius = 1.5;
|
||||
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons =
|
||||
@ -329,9 +330,9 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection> stimPlanCellIdxToIntersectionInfoMap;
|
||||
|
||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||
fracturePolygon,
|
||||
wellPathPoints,
|
||||
wellRadius,
|
||||
perforationLength,
|
||||
stpCellPolygons,
|
||||
stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
@ -344,11 +345,11 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
EXPECT_EQ(1, it->second.endpointCount);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
cvf::Mat4f fractureXf = cvf::Mat4f::IDENTITY;
|
||||
|
||||
std::vector<cvf::Vec3f> fracturePolygon ={ {0.0f, 0.0f, 0.0f}, {5.0f, 10.0f, 0.0f}, {10.0f, 0.0f, 0.0f} };
|
||||
// std::vector<cvf::Vec3f> fracturePolygon ={ {0.0f, 0.0f, 0.0f}, {5.0f, 10.0f, 0.0f}, {10.0f, 0.0f, 0.0f} };
|
||||
double perforationLength = 10;
|
||||
double wellRadius = 1.5;
|
||||
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons =
|
||||
{
|
||||
@ -364,9 +365,9 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
std::vector<cvf::Vec3d> wellPathPoints ={ {1.0f, 0.5f, 10.0f}, {1.0f, 1.5f, -10.0f} };
|
||||
|
||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||
fracturePolygon,
|
||||
wellPathPoints,
|
||||
wellRadius,
|
||||
perforationLength,
|
||||
stpCellPolygons,
|
||||
stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
@ -383,9 +384,9 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
std::vector<cvf::Vec3d> wellPathPoints ={ {1.0f, 0.5f, 10.0f}, {1.0f, 1.0f, 0.5f} };
|
||||
|
||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||
fracturePolygon,
|
||||
wellPathPoints,
|
||||
wellRadius,
|
||||
perforationLength,
|
||||
stpCellPolygons,
|
||||
stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
@ -402,9 +403,9 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
||||
std::vector<cvf::Vec3d> wellPathPoints ={ {1.0f, 0.5f, 10.0f}, {1.0f, 1.0f, 0.5f}, {1.0f, 1.5f, -0.5f}, {1.0f, 2.0f, -10.0f}};
|
||||
|
||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||
fracturePolygon,
|
||||
wellPathPoints,
|
||||
wellRadius,
|
||||
perforationLength,
|
||||
stpCellPolygons,
|
||||
stimPlanCellIdxToIntersectionInfoMap);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user