mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Multi Segment Wells: Read in connection between a well branch and the branch head.
Compute intersection point between branch top well cell and branch head in the main branch. p4#: 21954
This commit is contained in:
parent
fa410ba8a5
commit
16cd7a04ae
@ -783,20 +783,23 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
|
||||
|
||||
|
||||
|
||||
|
||||
// Loop over all the grids in the model. If we have connections in one, we will discard
|
||||
// the maingrid connections as they are "duplicates"
|
||||
// the main grid connections as the well connections are duplicated in the main grid and LGR grids
|
||||
|
||||
bool hasWellConnectionsInLGR = false;
|
||||
// for (size_t gridNr = 1; gridNr < grids.size(); ++gridNr)
|
||||
// {
|
||||
// RigGridBase* lgrGrid = m_eclipseCase->grid(gridNr);
|
||||
// if (well_state_has_grid_connections(ert_well_state, lgrGrid->gridName().data()))
|
||||
// {
|
||||
// hasWellConnectionsInLGR = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
#if 0
|
||||
// To be discussed with Statoil
|
||||
for (size_t gridNr = 1; gridNr < grids.size(); ++gridNr)
|
||||
{
|
||||
RigGridBase* lgrGrid = m_eclipseCase->grid(gridNr);
|
||||
if (well_state_has_grid_connections(ert_well_state, lgrGrid->gridName().data()))
|
||||
{
|
||||
hasWellConnectionsInLGR = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t gridNr = hasWellConnectionsInLGR ? 1 : 0;
|
||||
for (; gridNr < grids.size(); ++gridNr)
|
||||
@ -821,6 +824,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
|
||||
wellResFrame.m_wellHead.m_gridIndex = gridNr;
|
||||
}
|
||||
|
||||
|
||||
std::string gridName;
|
||||
if (gridNr == 0)
|
||||
{
|
||||
@ -840,108 +844,128 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
|
||||
|
||||
for (int branchIdx = 0; branchIdx < well_branch_collection_get_size(branches); branchIdx++)
|
||||
{
|
||||
RigWellResultBranch& wellSegment = wellResFrame.m_wellResultBranches[branchIdx];
|
||||
wellSegment.m_branchNumber = branchIdx;
|
||||
RigWellResultBranch& rigWellResultBranch = wellResFrame.m_wellResultBranches[branchIdx];
|
||||
rigWellResultBranch.m_branchIndex = branchIdx;
|
||||
wellResults->setMultiSegmentWell(true);
|
||||
|
||||
const well_segment_type* segment = well_branch_collection_iget_start_segment(branches, branchIdx);
|
||||
CVF_ASSERT(segment);
|
||||
const well_segment_type* branchBottomSegment = well_branch_collection_iget_start_segment(branches, branchIdx);
|
||||
CVF_ASSERT(branchBottomSegment);
|
||||
|
||||
std::vector<const well_segment_type*> ertBranchSegments; // Segment closest to well head first in this vector
|
||||
|
||||
int wellSegmentBranchId = well_segment_get_branch_id(segment);
|
||||
int nextWellSegmentBranchId = wellSegmentBranchId;
|
||||
while (segment && nextWellSegmentBranchId == wellSegmentBranchId)
|
||||
rigWellResultBranch.m_ertBranchId = well_segment_get_branch_id(branchBottomSegment);
|
||||
|
||||
|
||||
// Find outlet segment in next branch
|
||||
// Start from bottom, and iterate over segments until next branch is detected
|
||||
|
||||
int outletErtBranchId = rigWellResultBranch.m_ertBranchId;
|
||||
const well_segment_type* outletSegmentInNextBranch = branchBottomSegment;
|
||||
while (outletSegmentInNextBranch && outletErtBranchId == rigWellResultBranch.m_ertBranchId)
|
||||
{
|
||||
// Insert at front, as we want the segments to be ordered starting closest to the well head
|
||||
ertBranchSegments.insert(ertBranchSegments.begin(), segment);
|
||||
ertBranchSegments.insert(ertBranchSegments.begin(), outletSegmentInNextBranch);
|
||||
|
||||
segment = well_segment_get_outlet(segment);
|
||||
if (segment)
|
||||
outletSegmentInNextBranch = well_segment_get_outlet(outletSegmentInNextBranch);
|
||||
if (outletSegmentInNextBranch)
|
||||
{
|
||||
nextWellSegmentBranchId = well_segment_get_branch_id(segment);
|
||||
outletErtBranchId = well_segment_get_branch_id(outletSegmentInNextBranch);
|
||||
}
|
||||
}
|
||||
|
||||
// Get grid cell index to connect the branch to
|
||||
bool foundGridCellConnection = false;
|
||||
if (segment)
|
||||
if (outletSegmentInNextBranch)
|
||||
{
|
||||
const well_conn_collection_type* connections = well_segment_get_connections(segment, gridName.data());
|
||||
if (connections)
|
||||
{
|
||||
size_t existingConnCount = wellSegment.m_wellCells.size();
|
||||
int connectionCount = well_conn_collection_get_size(connections);
|
||||
if (connectionCount > 0)
|
||||
{
|
||||
// Get last connection from the outlet segment
|
||||
well_conn_type* ert_connection = well_conn_collection_iget(connections, connectionCount - 1);
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
rigWellResultBranch.m_connectionDepthOnOutletBranch = well_segment_get_depth(outletSegmentInNextBranch);
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
wellSegment.m_branchHead.m_gridIndex = gridNr;
|
||||
wellSegment.m_branchHead.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
|
||||
foundGridCellConnection = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No connections present in segment this branch is connected to
|
||||
// Store intersection data used for visualization in RivWellPipesPartMgr
|
||||
wellSegment.m_intersectionSegmentOutletBranchIndex = nextWellSegmentBranchId;
|
||||
wellSegment.m_intersectionSegmentOutletDepth = well_segment_get_depth(segment);
|
||||
}
|
||||
// No connections present in segment this branch is connected to
|
||||
// Store intersection data used for visualization in RivWellPipesPartMgr
|
||||
rigWellResultBranch.m_outletErtBranchId = outletErtBranchId;
|
||||
}
|
||||
|
||||
// Get first segment with connections in order to find grid cell index to connect the branch to
|
||||
while(outletSegmentInNextBranch && !well_segment_has_grid_connections(outletSegmentInNextBranch, gridName.data()))
|
||||
{
|
||||
outletSegmentInNextBranch = well_segment_get_outlet(outletSegmentInNextBranch);
|
||||
|
||||
// There are no connections in the directly connected outlet segment.
|
||||
rigWellResultBranch.m_useBranchHeadAsCenterLineIntersectionTop = true;
|
||||
}
|
||||
|
||||
if (outletSegmentInNextBranch)
|
||||
{
|
||||
const well_conn_collection_type* connections = well_segment_get_connections(outletSegmentInNextBranch, gridName.data());
|
||||
CVF_ASSERT(connections);
|
||||
size_t existingConnCount = rigWellResultBranch.m_wellCells.size();
|
||||
int connectionCount = well_conn_collection_get_size(connections);
|
||||
CVF_ASSERT(connectionCount > 0);
|
||||
|
||||
// Get last connection from the outlet segment
|
||||
well_conn_type* ert_connection = well_conn_collection_iget(connections, connectionCount - 1);
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
rigWellResultBranch.m_branchHead.m_gridIndex = gridNr;
|
||||
rigWellResultBranch.m_branchHead.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
rigWellResultBranch.m_branchHead.m_isOpen = well_conn_open(ert_connection);
|
||||
CVF_ASSERT(rigWellResultBranch.m_branchHead.m_gridCellIndex != cvf::UNDEFINED_SIZE_T);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use well head as branch head
|
||||
rigWellResultBranch.m_branchHead = wellResFrame.m_wellHead;
|
||||
CVF_ASSERT(rigWellResultBranch.m_branchHead.m_gridCellIndex != cvf::UNDEFINED_SIZE_T);
|
||||
|
||||
|
||||
// TODO: Possibly add branch ID for the main branch the well head is a part of
|
||||
}
|
||||
|
||||
CVF_ASSERT(rigWellResultBranch.m_branchHead.m_gridCellIndex != cvf::UNDEFINED_SIZE_T);
|
||||
|
||||
|
||||
for (size_t i = 0; i < ertBranchSegments.size(); i++)
|
||||
{
|
||||
segment = ertBranchSegments[i];
|
||||
outletSegmentInNextBranch = ertBranchSegments[i];
|
||||
|
||||
const well_conn_collection_type* connections = well_segment_get_connections(segment , gridName.data());
|
||||
const well_conn_collection_type* connections = well_segment_get_connections(outletSegmentInNextBranch , gridName.data());
|
||||
if (!connections) continue;
|
||||
|
||||
size_t existingConnCount = wellSegment.m_wellCells.size();
|
||||
size_t existingConnCount = rigWellResultBranch.m_wellCells.size();
|
||||
int connectionCount = well_conn_collection_get_size(connections);
|
||||
if (connectionCount > 0)
|
||||
{
|
||||
wellSegment.m_wellCells.resize(existingConnCount + connectionCount);
|
||||
rigWellResultBranch.m_wellCells.resize(existingConnCount + connectionCount);
|
||||
}
|
||||
|
||||
for (int connIdx = 0; connIdx < connectionCount; connIdx++)
|
||||
{
|
||||
well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx);
|
||||
|
||||
RigWellResultCell& data = wellSegment.m_wellCells[existingConnCount + connIdx];
|
||||
data.m_gridIndex = gridNr;
|
||||
RigWellResultCell& data = rigWellResultBranch.m_wellCells[existingConnCount + connIdx];
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
bool open = well_conn_open( ert_connection );
|
||||
int segmentId = well_conn_get_segment( ert_connection );
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
bool open = well_conn_open( ert_connection );
|
||||
int branch = well_segment_get_branch_id(segment);
|
||||
int segment = well_conn_get_segment( ert_connection );
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
data.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
|
||||
data.m_isOpen = open;
|
||||
data.m_branchId = branch;
|
||||
data.m_segmentId = segment;
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
data.m_gridIndex = gridNr;
|
||||
data.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
data.m_isOpen = open;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -955,7 +979,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
|
||||
wellResFrame.m_wellResultBranches.resize(branchIdx + 1);
|
||||
|
||||
RigWellResultBranch& wellSegment = wellResFrame.m_wellResultBranches[branchIdx];
|
||||
wellSegment.m_branchNumber = branchIdx;
|
||||
wellSegment.m_branchIndex = branchIdx;
|
||||
|
||||
int connectionCount = well_conn_collection_get_size(connections);
|
||||
size_t existingConnCount = wellSegment.m_wellCells.size();
|
||||
@ -966,30 +990,25 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
|
||||
well_conn_type* ert_connection = well_conn_collection_iget(connections, connIdx);
|
||||
|
||||
RigWellResultCell& data = wellSegment.m_wellCells[existingConnCount + connIdx];
|
||||
data.m_gridIndex = gridNr;
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
bool isCellOpen = well_conn_open( ert_connection );
|
||||
|
||||
// TODO: Are these available for this type of well?
|
||||
int segmentId = well_conn_get_segment( ert_connection );
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
int cellI = well_conn_get_i( ert_connection );
|
||||
int cellJ = well_conn_get_j( ert_connection );
|
||||
int cellK = well_conn_get_k( ert_connection );
|
||||
bool isCellOpen = well_conn_open( ert_connection );
|
||||
|
||||
// TODO: Are these available for this type of well?
|
||||
int segmentId = well_conn_get_segment( ert_connection );
|
||||
int branchId = branchIdx;
|
||||
|
||||
// If a well is defined in fracture region, the K-value is from (cellCountK - 1) -> cellCountK*2 - 1
|
||||
// Adjust K so index is always in valid grid region
|
||||
if (cellK >= static_cast<int>(grids[gridNr]->cellCountK()))
|
||||
{
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
data.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
|
||||
data.m_isOpen = isCellOpen;
|
||||
data.m_branchId = branchId;
|
||||
data.m_segmentId = segmentId;
|
||||
cellK -= static_cast<int>(grids[gridNr]->cellCountK());
|
||||
}
|
||||
|
||||
data.m_gridIndex = gridNr;
|
||||
data.m_gridCellIndex = grids[gridNr]->cellIndexFromIJK(cellI , cellJ , cellK);
|
||||
|
||||
data.m_isOpen = isCellOpen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,15 +185,15 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
RigCaseData* rigReservoir = m_rimReservoirView->eclipseCase()->reservoirData();
|
||||
RigSingleWellResultsData* wellResults = m_rimWell->wellResults();
|
||||
|
||||
const RigWellResultFrame& staticWellFrame = m_rimWell->wellResults()->m_staticWellCells;
|
||||
|
||||
// Make sure we have computed the static representation of the well
|
||||
if (staticWellFrame.m_wellResultBranches.size() == 0)
|
||||
if (wellResults->m_staticWellCells.m_wellResultBranches.size() == 0)
|
||||
{
|
||||
wellResults->computeStaticWellCellPath();
|
||||
}
|
||||
if (staticWellFrame.m_wellResultBranches.size() == 0) return;
|
||||
|
||||
const RigWellResultFrame& staticWellFrame = wellResults->m_staticWellCells;
|
||||
if (staticWellFrame.m_wellResultBranches.size() == 0) return;
|
||||
|
||||
// Initialize the return arrays
|
||||
pipeBranchesCLCoords.clear();
|
||||
pipeBranchesCellIds.clear();
|
||||
@ -230,7 +230,7 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
const RigWellResultCell* prevResCell = NULL;
|
||||
|
||||
// Use well head if branch head is not specified
|
||||
if (resBranches[0].m_branchHead.m_gridCellIndex == cvf::UNDEFINED_SIZE_T)
|
||||
if (!wellResults->isMultiSegmentWell())
|
||||
{
|
||||
// Create a new branch from wellhead
|
||||
|
||||
@ -251,20 +251,40 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
if (resBranches[brIdx].m_wellCells.size() == 0)
|
||||
continue; // Skip empty branches. Do not know why they exist, but they make problems.
|
||||
|
||||
if (resBranches[brIdx].m_branchHead.m_gridCellIndex != cvf::UNDEFINED_SIZE_T)
|
||||
if (wellResults->isMultiSegmentWell())
|
||||
{
|
||||
// Create a new branch and use branch head as previous result cell
|
||||
|
||||
pipeBranchesCLCoords.push_back(std::vector<cvf::Vec3d>());
|
||||
pipeBranchesCellIds.push_back(std::vector <RigWellResultCell>());
|
||||
|
||||
prevResCell = &(resBranches[brIdx].m_branchHead);
|
||||
if (resBranches[brIdx].m_useBranchHeadAsCenterLineIntersectionTop)
|
||||
{
|
||||
// Intersection evaluation is done when all center lines are computed,
|
||||
// as the center lines are used to compute the intersections
|
||||
|
||||
const RigCell& whCell = rigReservoir->cellFromWellResultCell(resBranches[brIdx].m_branchHead);
|
||||
cvf::Vec3d branchHeadStartPos = whCell.faceCenter(cvf::StructGridInterface::NEG_K);
|
||||
// Insert well head if this is branch head, as we have all information we need
|
||||
if (isIdentical(&resBranches[brIdx].m_branchHead, whResCell))
|
||||
{
|
||||
prevResCell = whResCell;
|
||||
|
||||
pipeBranchesCLCoords.back().push_back(branchHeadStartPos);
|
||||
pipeBranchesCellIds.back().push_back(*prevResCell);
|
||||
pipeBranchesCLCoords.back().push_back(whStartPos);
|
||||
pipeBranchesCellIds.back().push_back(*prevResCell);
|
||||
|
||||
pipeBranchesCLCoords.back().push_back(whIntermediate);
|
||||
pipeBranchesCellIds.back().push_back(*prevResCell);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new branch and use branch head as previous result cell
|
||||
|
||||
prevResCell = &(resBranches[brIdx].m_branchHead);
|
||||
|
||||
const RigCell& whCell = rigReservoir->cellFromWellResultCell(resBranches[brIdx].m_branchHead);
|
||||
cvf::Vec3d branchHeadStartPos = whCell.faceCenter(cvf::StructGridInterface::NEG_K);
|
||||
|
||||
pipeBranchesCLCoords.back().push_back(branchHeadStartPos);
|
||||
pipeBranchesCellIds.back().push_back(*prevResCell);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over all the resultCells in the branch
|
||||
@ -281,7 +301,14 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
// Check if this and the previous cells has shared faces
|
||||
|
||||
cvf::StructGridInterface::FaceType sharedFace;
|
||||
if (rigReservoir->findSharedSourceFace(sharedFace, resCell, *prevResCell))
|
||||
if (resBranches[brIdx].m_useBranchHeadAsCenterLineIntersectionTop && cIdx == 0)
|
||||
{
|
||||
// Insert cell center of first cell
|
||||
// Intersection point to connect to is inserted further down in this function
|
||||
branchCLCoords.push_back(cell.center());
|
||||
branchCellIds.push_back(resCell);
|
||||
}
|
||||
else if (rigReservoir->findSharedSourceFace(sharedFace, resCell, *prevResCell))
|
||||
{
|
||||
branchCLCoords.push_back(cell.faceCenter(sharedFace));
|
||||
branchCellIds.push_back(resCell);
|
||||
@ -316,13 +343,15 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
if ((intoThisCell - outOfPrevCell).lengthSquared() > 1e-3)
|
||||
{
|
||||
branchCLCoords.push_back(outOfPrevCell);
|
||||
branchCellIds.push_back(RigWellResultCell());
|
||||
branchCellIds.push_back(*prevResCell);
|
||||
}
|
||||
branchCLCoords.push_back(intoThisCell);
|
||||
branchCellIds.push_back(resCell);
|
||||
}
|
||||
else
|
||||
{
|
||||
CVF_ASSERT(!wellResults->isMultiSegmentWell());
|
||||
|
||||
// This cell is further from the previous cell than from the well head,
|
||||
// thus we interpret it as a new branch.
|
||||
|
||||
@ -349,15 +378,120 @@ void RivWellPipesPartMgr::calculateWellPipeCenterline( std::vector< std::vector
|
||||
}
|
||||
|
||||
prevResCell = &resCell;
|
||||
|
||||
}
|
||||
|
||||
if (wellResults->isMultiSegmentWell())
|
||||
{
|
||||
// All MSW branches are completed using the point 0.5 past the center of last cell
|
||||
const RigCell& prevCell = rigReservoir->cellFromWellResultCell(*prevResCell);
|
||||
cvf::Vec3d centerPrevCell = prevCell.center();
|
||||
pipeBranchesCLCoords.back().push_back(pipeBranchesCLCoords.back().back() + 1.5*(centerPrevCell - pipeBranchesCLCoords.back().back()) );
|
||||
}
|
||||
}
|
||||
|
||||
// For the last cell, add the point 0.5 past the center of that cell
|
||||
const RigCell& prevCell = rigReservoir->cellFromWellResultCell(*prevResCell);
|
||||
cvf::Vec3d centerPrevCell = prevCell.center();
|
||||
pipeBranchesCLCoords.back().push_back(pipeBranchesCLCoords.back().back() + 1.5*(centerPrevCell - pipeBranchesCLCoords.back().back()) );
|
||||
if (!wellResults->isMultiSegmentWell())
|
||||
{
|
||||
// For the last cell, add the point 0.5 past the center of that cell
|
||||
const RigCell& prevCell = rigReservoir->cellFromWellResultCell(*prevResCell);
|
||||
cvf::Vec3d centerPrevCell = prevCell.center();
|
||||
pipeBranchesCLCoords.back().push_back(pipeBranchesCLCoords.back().back() + 1.5*(centerPrevCell - pipeBranchesCLCoords.back().back()) );
|
||||
}
|
||||
|
||||
if (wellResults->isMultiSegmentWell())
|
||||
{
|
||||
// Compute intersection points for multi segment wells connected to segments of other branches
|
||||
for (size_t brIdx = 0; brIdx < resBranches.size(); brIdx++)
|
||||
{
|
||||
const RigWellResultBranch& branchToConnect = resBranches[brIdx];
|
||||
|
||||
if (branchToConnect.m_useBranchHeadAsCenterLineIntersectionTop)
|
||||
{
|
||||
// Find intersection grid cell in branch to connect to
|
||||
|
||||
cvf::Vec3d intersectionPoint = cvf::Vec3d::UNDEFINED;
|
||||
|
||||
int outletErtBranchId = branchToConnect.m_outletErtBranchId;
|
||||
|
||||
for (size_t outletBranchIdx = 0; outletBranchIdx < resBranches.size(); outletBranchIdx++)
|
||||
{
|
||||
if (resBranches[outletBranchIdx].m_ertBranchId == outletErtBranchId)
|
||||
{
|
||||
RigWellResultCell outletResultCell = resBranches[outletBranchIdx].m_branchHead;
|
||||
|
||||
// Find generated pipe branch this cell resides in
|
||||
for (size_t i = 0; i < pipeBranchesCellIds.size(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < pipeBranchesCellIds[i].size(); j++)
|
||||
{
|
||||
const RigWellResultCell& candidate = pipeBranchesCellIds[i][j];
|
||||
if (isIdentical(&candidate, &outletResultCell))
|
||||
{
|
||||
// Find the coordinate pair at the intersection between two cell IDs
|
||||
while (j + 1 < pipeBranchesCellIds[i].size() && isIdentical(&pipeBranchesCellIds[i][j + 1], &outletResultCell))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
|
||||
if (j + 1 >= pipeBranchesCLCoords[i].size())
|
||||
{
|
||||
// Use the last point in the center line
|
||||
intersectionPoint = pipeBranchesCLCoords[i][j];
|
||||
}
|
||||
else
|
||||
{
|
||||
cvf::Vec3d lineStart = pipeBranchesCLCoords[i][j];
|
||||
cvf::Vec3d lineEnd = pipeBranchesCLCoords[i][j + 1];
|
||||
|
||||
cvf::Plane depthPlane;
|
||||
depthPlane.setFromPointAndNormal(cvf::Vec3d(0.0, 0.0, -branchToConnect.m_connectionDepthOnOutletBranch), cvf::Vec3d::Z_AXIS);
|
||||
cvf::Vec3d linePlaneIntersect;
|
||||
if (depthPlane.intersect(lineStart, lineEnd, &linePlaneIntersect))
|
||||
{
|
||||
intersectionPoint = linePlaneIntersect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersectionPoint.isUndefined())
|
||||
{
|
||||
// Find generated pipe branch this cell resides in
|
||||
// and insert intersection point at start of list
|
||||
|
||||
bool foundBranchToInsertInto = false;
|
||||
|
||||
size_t i = 0;
|
||||
while(!foundBranchToInsertInto && i < pipeBranchesCellIds.size())
|
||||
{
|
||||
size_t j = 0;
|
||||
while(!foundBranchToInsertInto && j < pipeBranchesCellIds[i].size())
|
||||
{
|
||||
const RigWellResultCell& candidate = pipeBranchesCellIds[i][j];
|
||||
if (isIdentical(&candidate, &branchToConnect.m_wellCells[0]))
|
||||
{
|
||||
pipeBranchesCellIds[i].insert(pipeBranchesCellIds[i].begin(), candidate);
|
||||
pipeBranchesCLCoords[i].insert(pipeBranchesCLCoords[i].begin(), intersectionPoint);
|
||||
|
||||
foundBranchToInsertInto = true;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could not detect intersection, use well head as fall back?
|
||||
// Currently, if nothing is found, the end of the branch closest to well head is not connected to main branch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CVF_ASSERT(pipeBranchesCellIds.size() == pipeBranchesCLCoords.size());
|
||||
|
@ -118,7 +118,7 @@ void RigSingleWellResultsData::computeStaticWellCellPath()
|
||||
|
||||
for (size_t bIdx = 0; bIdx < m_wellCellsTimeSteps[0].m_wellResultBranches.size(); ++bIdx)
|
||||
{
|
||||
size_t branchNumber = m_wellCellsTimeSteps[0].m_wellResultBranches[bIdx].m_branchNumber;
|
||||
size_t branchNumber = m_wellCellsTimeSteps[0].m_wellResultBranches[bIdx].m_branchIndex;
|
||||
std::vector<RigWellResultCell>& frameCells = m_wellCellsTimeSteps[0].m_wellResultBranches[bIdx].m_wellCells;
|
||||
|
||||
std::list< RigWellResultCell >& branch = staticWellBranches[branchNumber];
|
||||
@ -137,7 +137,7 @@ void RigSingleWellResultsData::computeStaticWellCellPath()
|
||||
|
||||
for (size_t bIdx = 0; bIdx < m_wellCellsTimeSteps[tIdx].m_wellResultBranches.size(); ++bIdx)
|
||||
{
|
||||
size_t branchNumber = m_wellCellsTimeSteps[tIdx].m_wellResultBranches[bIdx].m_branchNumber;
|
||||
size_t branchNumber = m_wellCellsTimeSteps[tIdx].m_wellResultBranches[bIdx].m_branchIndex;
|
||||
std::vector<RigWellResultCell>& resBranch = m_wellCellsTimeSteps[tIdx].m_wellResultBranches[bIdx].m_wellCells;
|
||||
|
||||
std::list< RigWellResultCell >& stBranch = staticWellBranches[branchNumber];
|
||||
@ -252,12 +252,15 @@ void RigSingleWellResultsData::computeStaticWellCellPath()
|
||||
|
||||
for (bIt = staticWellBranches.begin(); bIt != staticWellBranches.end(); ++bIt)
|
||||
{
|
||||
RigWellResultBranch rigBranch;
|
||||
rigBranch.m_branchNumber = bIt->first;
|
||||
// Copy from first time step
|
||||
RigWellResultBranch rigBranch = m_wellCellsTimeSteps[0].m_wellResultBranches[bIt->first];
|
||||
rigBranch.m_branchIndex = bIt->first;
|
||||
|
||||
// Clear well cells, and insert the collection of well cells for the static situation
|
||||
rigBranch.m_wellCells.clear();
|
||||
|
||||
std::list< RigWellResultCell >& branch = bIt->second;
|
||||
std::list< RigWellResultCell >::iterator cIt;
|
||||
|
||||
for (cIt = branch.begin(); cIt != branch.end(); ++cIt)
|
||||
{
|
||||
RigWellResultCell rwc = *cIt;
|
||||
@ -269,3 +272,19 @@ void RigSingleWellResultsData::computeStaticWellCellPath()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigSingleWellResultsData::setMultiSegmentWell(bool isMultiSegmentWell)
|
||||
{
|
||||
m_isMultiSegmentWell = isMultiSegmentWell;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigSingleWellResultsData::isMultiSegmentWell() const
|
||||
{
|
||||
return m_isMultiSegmentWell;
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,11 @@ struct RigWellResultCell
|
||||
RigWellResultCell() :
|
||||
m_gridIndex(cvf::UNDEFINED_SIZE_T),
|
||||
m_gridCellIndex(cvf::UNDEFINED_SIZE_T),
|
||||
m_branchId(-1),
|
||||
m_segmentId(-1),
|
||||
m_isOpen(false)
|
||||
{ }
|
||||
|
||||
size_t m_gridIndex;
|
||||
size_t m_gridCellIndex; //< Index to cell which is included in the well
|
||||
int m_branchId;
|
||||
int m_segmentId;
|
||||
|
||||
bool m_isOpen; //< Marks the well as open or closed as of Eclipse simulation
|
||||
};
|
||||
@ -47,10 +43,13 @@ struct RigWellResultCell
|
||||
struct RigWellResultBranch
|
||||
{
|
||||
RigWellResultBranch() :
|
||||
m_branchNumber(cvf::UNDEFINED_SIZE_T)
|
||||
m_branchIndex(cvf::UNDEFINED_SIZE_T),
|
||||
m_ertBranchId(-1),
|
||||
m_useBranchHeadAsCenterLineIntersectionTop(false)
|
||||
{}
|
||||
|
||||
size_t m_branchNumber;
|
||||
size_t m_branchIndex;
|
||||
int m_ertBranchId;
|
||||
|
||||
std::vector<RigWellResultCell> m_wellCells;
|
||||
|
||||
@ -58,11 +57,13 @@ struct RigWellResultBranch
|
||||
// For standard wells, this is always well head.
|
||||
RigWellResultCell m_branchHead;
|
||||
|
||||
bool m_useBranchHeadAsCenterLineIntersectionTop;
|
||||
|
||||
// If the outlet segment does not have any connections, it is not possible to populate branch head
|
||||
// Instead, use the intersection segment outlet branch index and the depth of this segment to identify intersection point
|
||||
// when computing centerline coords in RivWellPipesPartMgr
|
||||
size_t m_intersectionSegmentOutletBranchIndex;
|
||||
double m_intersectionSegmentOutletDepth;
|
||||
int m_outletErtBranchId;
|
||||
double m_connectionDepthOnOutletBranch;
|
||||
};
|
||||
|
||||
class RigWellResultFrame
|
||||
@ -113,6 +114,11 @@ public:
|
||||
class RigSingleWellResultsData : public cvf::Object
|
||||
{
|
||||
public:
|
||||
RigSingleWellResultsData() { m_isMultiSegmentWell = false; }
|
||||
|
||||
void setMultiSegmentWell(bool isMultiSegmentWell);
|
||||
bool isMultiSegmentWell() const;
|
||||
|
||||
bool hasWellResult(size_t resultTimeStepIndex) const;
|
||||
size_t firstResultTimeStep() const;
|
||||
|
||||
@ -124,6 +130,7 @@ public:
|
||||
|
||||
public:
|
||||
QString m_wellName;
|
||||
bool m_isMultiSegmentWell;
|
||||
|
||||
std::vector<size_t> m_resultTimeStepIndexToWellTimeStepIndex; // Well result timesteps may differ from result timesteps
|
||||
std::vector< RigWellResultFrame > m_wellCellsTimeSteps;
|
||||
|
Loading…
Reference in New Issue
Block a user