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
|
// Calculate transmissibility into the well
|
||||||
|
|
||||||
RigWellPathStimplanIntersector wellFractureIntersector(wellPath->wellPathGeometry(), fracture);
|
////
|
||||||
const std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection >& fractureWellCells = wellFractureIntersector.intersections();
|
//If fracture has orientation Azimuth or Transverse, assume only radial inflow
|
||||||
|
if (fracture->attachedFractureDefinition()->orientation() == RimFractureTemplate::AZIMUTH
|
||||||
for (const auto& fracCellIdxIsectDataPair : fractureWellCells)
|
|| fracture->attachedFractureDefinition()->orientation() == RimFractureTemplate::TRANSVERSE_WELL_PATH)
|
||||||
{
|
{
|
||||||
size_t fracWellCellIdx = fracCellIdxIsectDataPair.first;
|
const RigFractureGrid* fracGrid = fracture->attachedFractureDefinition()->fractureGrid();
|
||||||
RigWellPathStimplanIntersector::WellCellIntersection intersection = fracCellIdxIsectDataPair.second;
|
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;
|
transCondenser.addNeighborTransmissibility({ true, RigTransmissibilityCondenser::CellAddress::WELL, 1 },
|
||||||
if (intersection.endpointCount)
|
{ false, RigTransmissibilityCondenser::CellAddress::STIMPLAN, wellCellIndex },
|
||||||
{
|
radialTrans);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////
|
||||||
|
//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
|
// Insert total transmissibility from eclipse-cell to well for this fracture into the map
|
||||||
|
|
||||||
|
@ -497,11 +497,6 @@ QStringList RimContextCommandBuilder::commandsFromSelection()
|
|||||||
commandIds << "RicNewSimWellFractureFeature";
|
commandIds << "RicNewSimWellFractureFeature";
|
||||||
commandIds << "RicExportSelectedSimWellFractureWellCompletionFeature";
|
commandIds << "RicExportSelectedSimWellFractureWellCompletionFeature";
|
||||||
}
|
}
|
||||||
else if (dynamic_cast<RimWellPath*>(uiItem))
|
|
||||||
{
|
|
||||||
commandIds << "RicExportSelectedWellPathFractureWellCompletionFeature";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
size_t jCellCount() const { return m_jCellCount; }
|
size_t jCellCount() const { return m_jCellCount; }
|
||||||
size_t iCellCount() const { return m_iCellCount; }
|
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:
|
private:
|
||||||
|
@ -27,8 +27,9 @@ RigWellPathStimplanIntersector::RigWellPathStimplanIntersector(const RigWellPath
|
|||||||
for ( const auto& stpCell: stpCells ) stpCellPolygons.push_back(stpCell.getPolygon());
|
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,
|
void RigWellPathStimplanIntersector::calculate(const cvf::Mat4f &fractureXf,
|
||||||
const std::vector<cvf::Vec3d>& wellPathPointsOrg,
|
const std::vector<cvf::Vec3d>& wellPathPointsOrg,
|
||||||
double wellRadius,
|
double wellRadius,
|
||||||
|
double perforationLength,
|
||||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||||
std::map<size_t, WellCellIntersection>& m_stimPlanCellIdxToIntersectionInfoMap)
|
std::map<size_t, WellCellIntersection>& m_stimPlanCellIdxToIntersectionInfoMap)
|
||||||
{
|
{
|
||||||
cvf::Mat4d toFractureXf = cvf::Mat4d(fractureXf.getInverted());
|
cvf::Mat4d toFractureXf = cvf::Mat4d(fractureXf.getInverted());
|
||||||
|
|
||||||
//Find bounding box
|
std::vector<cvf::Vec3d> perforationLengthBoundingBoxPolygon;
|
||||||
cvf::BoundingBox polygonBBox;
|
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(-perforationLength / 2, -perforationLength / 2, 0));
|
||||||
for (std::vector<cvf::Vec3d> fracCellPolygon : stpCellPolygons)
|
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d( perforationLength / 2, -perforationLength / 2, 0));
|
||||||
{
|
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d( perforationLength / 2, perforationLength / 2, 0));
|
||||||
for (cvf::Vec3d nodeCoord : fracCellPolygon) polygonBBox.add(nodeCoord);
|
perforationLengthBoundingBoxPolygon.push_back(cvf::Vec3d(-perforationLength / 2, perforationLength / 2, 0));
|
||||||
}
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert well path to fracture template system
|
// Convert well path to fracture template system
|
||||||
|
|
||||||
@ -69,7 +60,7 @@ void RigWellPathStimplanIntersector::calculate(const cvf::Mat4f &fractureXf,
|
|||||||
// Clip well path to fracture domain
|
// Clip well path to fracture domain
|
||||||
|
|
||||||
std::vector<std::vector<cvf::Vec3d> > wellPathPartsWithinFracture =
|
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
|
// 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,
|
static void calculate(const cvf::Mat4f& fractureXf,
|
||||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||||
double wellRadius,
|
double wellRadius,
|
||||||
|
double perforationLength,
|
||||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||||
std::map<size_t, WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap);
|
std::map<size_t, WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap);
|
||||||
|
|
||||||
@ -58,13 +59,13 @@ class RigWellPathStimplanIntersectorTester
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void testCalculate(const cvf::Mat4f& fractureXf,
|
static void testCalculate(const cvf::Mat4f& fractureXf,
|
||||||
const std::vector<cvf::Vec3f>& fracturePolygon,
|
|
||||||
const std::vector<cvf::Vec3d>& wellPathPoints,
|
const std::vector<cvf::Vec3d>& wellPathPoints,
|
||||||
double wellRadius,
|
double wellRadius,
|
||||||
|
double perforationLength,
|
||||||
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
const std::vector<std::vector<cvf::Vec3d> >& stpCellPolygons,
|
||||||
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection>& stimPlanCellIdxToIntersectionInfoMap)
|
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;
|
cvf::Mat4f fractureXf = cvf::Mat4f::IDENTITY;
|
||||||
fractureXf.setTranslation({ 50.0f, 0.0f, 0.0f });
|
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} };
|
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;
|
double wellRadius = 1.5;
|
||||||
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons =
|
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons =
|
||||||
@ -329,9 +330,9 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
|||||||
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection> stimPlanCellIdxToIntersectionInfoMap;
|
std::map<size_t, RigWellPathStimplanIntersector::WellCellIntersection> stimPlanCellIdxToIntersectionInfoMap;
|
||||||
|
|
||||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||||
fracturePolygon,
|
|
||||||
wellPathPoints,
|
wellPathPoints,
|
||||||
wellRadius,
|
wellRadius,
|
||||||
|
perforationLength,
|
||||||
stpCellPolygons,
|
stpCellPolygons,
|
||||||
stimPlanCellIdxToIntersectionInfoMap);
|
stimPlanCellIdxToIntersectionInfoMap);
|
||||||
|
|
||||||
@ -344,11 +345,11 @@ TEST(RigWellPathStimplanIntersector, intersection)
|
|||||||
EXPECT_EQ(1, it->second.endpointCount);
|
EXPECT_EQ(1, it->second.endpointCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
cvf::Mat4f fractureXf = cvf::Mat4f::IDENTITY;
|
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;
|
double wellRadius = 1.5;
|
||||||
std::vector<std::vector<cvf::Vec3d> > stpCellPolygons =
|
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} };
|
std::vector<cvf::Vec3d> wellPathPoints ={ {1.0f, 0.5f, 10.0f}, {1.0f, 1.5f, -10.0f} };
|
||||||
|
|
||||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||||
fracturePolygon,
|
|
||||||
wellPathPoints,
|
wellPathPoints,
|
||||||
wellRadius,
|
wellRadius,
|
||||||
|
perforationLength,
|
||||||
stpCellPolygons,
|
stpCellPolygons,
|
||||||
stimPlanCellIdxToIntersectionInfoMap);
|
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} };
|
std::vector<cvf::Vec3d> wellPathPoints ={ {1.0f, 0.5f, 10.0f}, {1.0f, 1.0f, 0.5f} };
|
||||||
|
|
||||||
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||||
fracturePolygon,
|
|
||||||
wellPathPoints,
|
wellPathPoints,
|
||||||
wellRadius,
|
wellRadius,
|
||||||
|
perforationLength,
|
||||||
stpCellPolygons,
|
stpCellPolygons,
|
||||||
stimPlanCellIdxToIntersectionInfoMap);
|
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}};
|
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,
|
RigWellPathStimplanIntersectorTester::testCalculate(fractureXf,
|
||||||
fracturePolygon,
|
|
||||||
wellPathPoints,
|
wellPathPoints,
|
||||||
wellRadius,
|
wellRadius,
|
||||||
|
perforationLength,
|
||||||
stpCellPolygons,
|
stpCellPolygons,
|
||||||
stimPlanCellIdxToIntersectionInfoMap);
|
stimPlanCellIdxToIntersectionInfoMap);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user