Wells: Improved output in Result info window when picking a well-cell

p4#: 22241
This commit is contained in:
Jacob Støren 2013-08-28 15:36:29 +02:00
parent 5e629795e4
commit 79c016b6b6
4 changed files with 136 additions and 514 deletions

View File

@ -719,34 +719,10 @@ bool RifReaderEclipseOutput::dynamicResult(const QString& result, PorosityModelR
}
// Helper structure to handle the metadata for connections in segments
struct SegmentData
{
SegmentData(const well_conn_collection_type* connections) :
m_branchId(-1),
m_segmentId(-1),
//m_gridIndex(cvf::UNDEFINED_SIZE_T),
m_connections(connections)
{}
int m_branchId;
int m_segmentId;
//size_t m_gridIndex;
const well_conn_collection_type* m_connections;
};
struct SegmentTreeNode
{
SegmentTreeNode() : outletSegment(NULL), mainChildSegment(NULL) {}
std::vector<RigWellResultPoint> connections;
SegmentTreeNode* outletSegment;
SegmentTreeNode* mainChildSegment;
std::vector<SegmentTreeNode*> additionalChildSegments;
};
//--------------------------------------------------------------------------------------------------
/// Helper struct to store info on how a well-to-grid connection contributes to the position of
/// well segments without any connections.
//--------------------------------------------------------------------------------------------------
struct SegmentPositionContribution
{
SegmentPositionContribution( int connectionSegmentId,
@ -812,21 +788,9 @@ RigWellResultPoint RifReaderEclipseOutput::createWellResultPoint(const RigGridBa
}
void getSegmentDataByBranchId(const std::list<SegmentData>& segments, std::vector<SegmentData>& branchSegments, int branchId)
{
std::list<SegmentData>::const_iterator it;
for (it = segments.begin(); it != segments.end(); it++)
{
if (it->m_branchId == branchId)
{
branchSegments.push_back(*it);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Inverse distance interpolation of the supplied points and distance weights
/// Inverse distance interpolation of the supplied points and distance weights for
/// the contributing points which are closest above, and closest below
//--------------------------------------------------------------------------------------------------
cvf::Vec3d interpolate3DPosition(const std::vector<SegmentPositionContribution> positions)
{
@ -1044,7 +1008,6 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
{
wellResults->setMultiSegmentWell(true);
#if 1
// how do we handle LGR-s ?
// 1. Create separate visual branches for each Grid, with its own wellhead
// 2. Always use the connections to the grid with the highest number (innermost LGR).
@ -1217,74 +1180,75 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
data.m_ertSegmentId = well_segment_get_id(outletSegment);
wellResultBranch.m_branchResultPoints.push_back(data);
// Store data for segment position calculation, and propagate it upwards until we meet a segment with connections
// Store data for segment position calculation,
// and propagate it upwards until we meet a segment with connections
bool isAnInsolationContribution = accLengthFromLastConnection < lastConnectionCellSize;
bool isAnInsolationContribution = accLengthFromLastConnection < lastConnectionCellSize;
cvf::Vec3d lastConnectionPosWOffset = lastConnectionPos;
if (isAnInsolationContribution) lastConnectionPosWOffset += 0.4*(lastConnectionCellCorner-lastConnectionPos);
cvf::Vec3d lastConnectionPosWOffset = lastConnectionPos;
if (isAnInsolationContribution) lastConnectionPosWOffset += 0.4*(lastConnectionCellCorner-lastConnectionPos);
segmentIdToPositionContrib[well_segment_get_id(outletSegment)].push_back(
SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPosWOffset, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false));
segmentIdToPositionContrib[well_segment_get_id(outletSegment)].push_back(
SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPosWOffset, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false));
/// Loop further to add this position contribution until a segment with connections is found
/// Loop further to add this position contribution until a segment with connections is found
accLengthFromLastConnection += well_segment_get_length(outletSegment);
segmentIdBelow = well_segment_get_id(outletSegment);
accLengthFromLastConnection += well_segment_get_length(outletSegment);
segmentIdBelow = well_segment_get_id(outletSegment);
const well_segment_type* aboveOutletSegment = NULL;
const well_segment_type* aboveOutletSegment = NULL;
if (well_segment_get_outlet_id(outletSegment) == -1)
if (well_segment_get_outlet_id(outletSegment) == -1)
{
aboveOutletSegment = NULL;
}
else
{
aboveOutletSegment = well_segment_get_outlet(outletSegment);
}
while (aboveOutletSegment )
{
// Loop backwards, just because we do that the other places
bool segmentHasConnections = false;
for (int gridNr = lastGridNr; gridNr >= 0; --gridNr)
{
std::string gridName = this->ertGridName(gridNr);
// If this segment has connections in any grid, stop traversal
if (well_segment_has_grid_connections(aboveOutletSegment, gridName.data()))
{
segmentHasConnections = true;
break;
}
}
if (!segmentHasConnections)
{
segmentIdToPositionContrib[well_segment_get_id(aboveOutletSegment)].push_back(
SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPos, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false));
accLengthFromLastConnection += well_segment_get_length(aboveOutletSegment);
}
else
{
break; // We have found a segment with connections. We do not need to propagate position contributions further
}
segmentIdBelow = well_segment_get_id(aboveOutletSegment);
if (well_segment_get_outlet_id(aboveOutletSegment) == -1)
{
aboveOutletSegment = NULL;
}
else
{
aboveOutletSegment = well_segment_get_outlet(outletSegment);
aboveOutletSegment = well_segment_get_outlet(aboveOutletSegment);
}
}
while (aboveOutletSegment )
{
// Loop backwards, just because we do that the other places
bool segmentHasConnections = false;
for (int gridNr = lastGridNr; gridNr >= 0; --gridNr)
{
std::string gridName = this->ertGridName(gridNr);
// If this segment has connections in any grid, stop traversal
if (well_segment_has_grid_connections(aboveOutletSegment, gridName.data()))
{
segmentHasConnections = true;
break;
}
}
if (!segmentHasConnections)
{
segmentIdToPositionContrib[well_segment_get_id(aboveOutletSegment)].push_back(
SegmentPositionContribution(lastConnectionSegmentId, lastConnectionPos, accLengthFromLastConnection, isAnInsolationContribution, segmentIdBelow, -1, false));
accLengthFromLastConnection += well_segment_get_length(aboveOutletSegment);
}
else
{
break; // We have found a segment with connections. We do not need to propagate position contributions further
}
segmentIdBelow = well_segment_get_id(aboveOutletSegment);
if (well_segment_get_outlet_id(aboveOutletSegment) == -1)
{
aboveOutletSegment = NULL;
}
else
{
aboveOutletSegment = well_segment_get_outlet(aboveOutletSegment);
}
}
}
}
else
@ -1296,7 +1260,8 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
// Reverse the order of the resultpoints in this branch, making the deepest come last
std::reverse(wellResultBranch.m_branchResultPoints.begin(), wellResultBranch.m_branchResultPoints.end());
}
} // End of the branch loop
// Propagate position contributions from connections above unpositioned segments downwards
@ -1358,61 +1323,6 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
}
// Calculate the bottom position of all the unpositioned segments
// First merge all the contributions referring to the same segment under, to mean
// the interpolated position at the closest split point below
#if 0
std::map<int, std::vector<SegmentPositionContribution> >::iterator posContribIt = segmentIdToPositionContrib.begin();
while (posContribIt != segmentIdToPositionContrib.end())
{
std::vector<SegmentPositionContribution> posContribs = posContribIt->second;
// Merge contributions coming from above that has same segementAboveErtId
// Merge contributions coming from below that has same segementBelowErtId
// Split the contributions in above, below and by respective above/below segmentErtId
std::map<int, std::vector<SegmentPositionContribution> > aboveErtIdToContribs;
std::map<int, std::vector<SegmentPositionContribution> > belowErtIdToContribs;
for (size_t pcIdx = 0; pcIdx < posContribs.size(); ++pcIdx)
{
if (posContribs[pcIdx].m_isFromAbove )
{
aboveErtIdToContribs[posContribs[pcIdx].m_segmentIdUnder].push_back(posContribs[pcIdx]);
}
else
{
belowErtIdToContribs[posContribs[pcIdx].m_segmentIdUnder].push_back(posContribs[pcIdx]);
}
}
std::vector<SegmentPositionContribution> mergedPosContribs;
std::map<int, std::vector<SegmentPositionContribution> >::iterator pcIt;
for (pcIt = aboveErtIdToContribs.begin(); pcIt != aboveErtIdToContribs.end(); ++pcIt)
{
if (pcIt->second.size() == 1)
{
mergedPosContribs.push_back(pcIt->second[0]);
}
else if (pcIt->second.size() > 1)
{
// Merge them
// Find the closest distance -> splitpoint distance
double splitPointDistance = HUGE_VAL;
for (size_t pcIdx = 0; pcIdx < pcIt->second.size(); ++pcIdx)
{
if (pcIt->second[pcIdx].m_lengthFromConnection < splitPointDistance)
{
splitPointDistance = pcIt->second[pcIdx].m_lengthFromConnection;
}
}
// calculate splitpoint position
// Merged posContrib made from splitpoint distance, and splitpoint
}
}
}
#endif
// Then do the calculation based on the refined contributions
std::map<int, std::vector<SegmentPositionContribution> >::iterator posContribIt = segmentIdToPositionContrib.begin();
@ -1439,274 +1349,7 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
}
}
#else
for (size_t gridNr = 0; gridNr < grids.size(); ++gridNr)
{
// Set the wellhead
{
// If several grids have a wellhead definition for this well, we use the last one.
// (Possibly the innermost LGR)
const well_conn_type* ert_wellhead = well_state_iget_wellhead(ert_well_state, static_cast<int>(gridNr));
if (ert_wellhead)
{
wellResFrame.m_wellHead = createWellResultPoint(grids[gridNr], ert_wellhead, -1, -1 );
}
}
// Find the grid name to be used later as key towards ert
std::string gridName;
if (gridNr == 0)
{
gridName = ECL_GRID_GLOBAL_GRID;
}
else
{
RigGridBase* rigGrid = m_eclipseCase->grid(gridNr);
gridName = rigGrid->gridName();
}
// Fill the SegmentData list with the segments from ert in branch sorted order:
// Grid0(BrancN<TopSegment...BottomSegment>, ..., Branch0<TopSegment...BottomSegment>) ... GridN(BrancN<TopSegment...BottomSegment>, ..., Branch0<TopSegment...BottomSegment>)
std::list<SegmentData> segmentList;
std::vector<const well_segment_type*> outletBranchSegmentList; // Keep a list of branch outlet segments to avoid traversal twice
std::vector<int> ertBranchIDs;
well_branch_collection_type* branches = well_state_get_branches(ert_well_state);
int branchCount = well_branch_collection_get_size(branches);
for (int branchIdx = 0; branchIdx < well_branch_collection_get_size(branches); branchIdx++)
{
const well_segment_type* segment = well_branch_collection_iget_start_segment(branches, branchIdx);
int branchId = well_segment_get_branch_id(segment);
ertBranchIDs.push_back(branchId);
while (segment && branchId == well_segment_get_branch_id(segment))
{
SegmentData segmentData(NULL);
segmentData.m_branchId = branchId;
segmentData.m_segmentId = well_segment_get_id(segment);
//segmentData.m_gridIndex = gridNr;
if (well_segment_has_grid_connections(segment, gridName.data()))
{
const well_conn_collection_type* connections = well_segment_get_connections(segment, gridName.data());
segmentData.m_connections = connections;
}
// Insert in front, as the segments are accessed starting from grid cell closes to well head
segmentList.push_front(segmentData);
if (well_segment_get_outlet_id(segment) == -1)
{
break;
}
segment = well_segment_get_outlet(segment);
}
outletBranchSegmentList.push_back(segment);
}
size_t currentGridBranchStartIndex = wellResFrame.m_wellResultBranches.size();
wellResFrame.m_wellResultBranches.resize(currentGridBranchStartIndex + branchCount);
// Import all well result cells for all connections, adding one ResultPoint to represent the bottom position
// for each segment having no connections
for (int branchIdx = 0; branchIdx < branchCount; branchIdx++)
{
RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches[currentGridBranchStartIndex + branchIdx];
wellResultBranch.m_branchIndex = branchIdx;
int ertBranchId = ertBranchIDs[branchIdx];
wellResultBranch.m_ertBranchId = ertBranchId;
std::vector<SegmentData> branchSegments;
getSegmentDataByBranchId(segmentList, branchSegments, ertBranchId);
for (size_t segmentIdx = 0; segmentIdx < branchSegments.size(); segmentIdx++)
{
SegmentData& connData = branchSegments[segmentIdx];
if (!connData.m_connections)
{
RigWellResultPoint data;
data.m_ertBranchId = connData.m_branchId;
data.m_ertSegmentId = connData.m_segmentId;
wellResultBranch.m_branchResultPoints.push_back(data);
}
else
{
int connectionCount = well_conn_collection_get_size(connData.m_connections);
size_t existingCellCount = wellResultBranch.m_branchResultPoints.size();
wellResultBranch.m_branchResultPoints.resize(existingCellCount + connectionCount);
for (int connIdx = 0; connIdx < connectionCount; connIdx++)
{
well_conn_type* ert_connection = well_conn_collection_iget(connData.m_connections, connIdx);
wellResultBranch.m_branchResultPoints[existingCellCount + connIdx] =
createWellResultPoint(grids[gridNr], ert_connection, connData.m_branchId, connData.m_segmentId);
}
}
}
}
// Assign outlet well cells to leaf branch well heads
for (int branchIdx = 0; branchIdx < branchCount; branchIdx++)
{
RigWellResultBranch& wellResultLeafBranch = wellResFrame.m_wellResultBranches[currentGridBranchStartIndex + branchIdx];
const well_segment_type* outletBranchSegment = outletBranchSegmentList[branchIdx];
CVF_ASSERT(outletBranchSegment);
int outletErtBranchId = well_segment_get_branch_id(outletBranchSegment);
size_t outletErtBranchIndex = cvf::UNDEFINED_SIZE_T;
for (size_t i = 0; i < ertBranchIDs.size(); i++)
{
if (ertBranchIDs[i] == outletErtBranchId)
{
outletErtBranchIndex = i;
}
}
if (outletErtBranchIndex != cvf::UNDEFINED_SIZE_T) // Todo: Is this a correct guarding ? Or is it indicating an error ?
{
RigWellResultBranch& outletResultBranch = wellResFrame.m_wellResultBranches[currentGridBranchStartIndex + outletErtBranchIndex];
int outletErtSegmentId = well_segment_get_branch_id(outletBranchSegment);
size_t lastCellIndexForSegmentIdInOutletBranch = cvf::UNDEFINED_SIZE_T;
for (size_t outletCellIdx = 0; outletCellIdx < outletResultBranch.m_branchResultPoints.size(); outletCellIdx++)
{
if (outletResultBranch.m_branchResultPoints[outletCellIdx].m_ertSegmentId == outletErtSegmentId)
{
lastCellIndexForSegmentIdInOutletBranch = outletCellIdx;
}
}
if (lastCellIndexForSegmentIdInOutletBranch == cvf::UNDEFINED_SIZE_T)
{
// Did not find the cell in the outlet branch based on branch id and segment id from outlet cell in leaf branch
//std::cout << "Did not find the cell in the outlet branch based on branch id and segment id from outlet cell in leaf branch" << std::endl;
//CVF_ASSERT(0);
}
else
{
RigWellResultPoint& outletCell = outletResultBranch.m_branchResultPoints[lastCellIndexForSegmentIdInOutletBranch];
wellResultLeafBranch.m_outletBranchIndex_OBSOLETE = currentGridBranchStartIndex + outletErtBranchIndex;
wellResultLeafBranch.m_outletBranchHeadCellIndex_OBSOLETE = lastCellIndexForSegmentIdInOutletBranch;
}
}
}
// Update outlet well cells with no grid cell connections
for (int branchIdx = 0; branchIdx < branchCount; branchIdx++)
{
RigWellResultBranch& wellResultLeafBranch = wellResFrame.m_wellResultBranches[currentGridBranchStartIndex + branchIdx];
const RigWellResultPoint* leafBranchHead = wellResFrame.findResultCellFromOutletSpecification(wellResultLeafBranch.m_outletBranchIndex_OBSOLETE, wellResultLeafBranch.m_outletBranchHeadCellIndex_OBSOLETE);
if (!leafBranchHead || leafBranchHead->isCell())
{
continue;
}
RigWellResultBranch& outletResultBranch = wellResFrame.m_wellResultBranches[wellResultLeafBranch.m_outletBranchIndex_OBSOLETE];
size_t firstCellIndexWithGridConnectionInLeafBranch = cvf::UNDEFINED_SIZE_T;
for (size_t j = 0; j < wellResultLeafBranch.m_branchResultPoints.size(); j++)
{
if (wellResultLeafBranch.m_branchResultPoints[j].isCell())
{
firstCellIndexWithGridConnectionInLeafBranch = j;
break;
}
}
if (firstCellIndexWithGridConnectionInLeafBranch != cvf::UNDEFINED_SIZE_T)
{
const RigCell& firstCellWithGridConnectionInLeafBranch = m_eclipseCase->cellFromWellResultCell(wellResultLeafBranch.m_branchResultPoints[firstCellIndexWithGridConnectionInLeafBranch]);
cvf::Vec3d firstGridConnectionCenterInLeafBranch = firstCellWithGridConnectionInLeafBranch.center();
size_t cellIndexInOutletBranch = wellResultLeafBranch.m_outletBranchHeadCellIndex_OBSOLETE;
CVF_ASSERT(cellIndexInOutletBranch != cvf::UNDEFINED_SIZE_T);
RigWellResultPoint& currCell = outletResultBranch.m_branchResultPoints[cellIndexInOutletBranch];
while (cellIndexInOutletBranch != cvf::UNDEFINED_SIZE_T && !currCell.isCell())
{
size_t branchConnectionCount = currCell.m_branchConnectionCount;
if (branchConnectionCount == 0)
{
currCell.m_bottomPosition = firstGridConnectionCenterInLeafBranch;
}
else
{
cvf::Vec3d currentWeightedCoord = currCell.m_bottomPosition * branchConnectionCount / static_cast<double>(branchConnectionCount + 1);
cvf::Vec3d additionalWeightedCoord = firstGridConnectionCenterInLeafBranch / static_cast<double>(branchConnectionCount + 1);
currCell.m_bottomPosition = currentWeightedCoord + additionalWeightedCoord;
}
currCell.m_branchConnectionCount++;
if (cellIndexInOutletBranch == 0)
{
cellIndexInOutletBranch = cvf::UNDEFINED_SIZE_T;
// Find the branch the outlet is connected to, and continue update of
// segments until a segment with a grid connection is found
const RigWellResultPoint* leafBranchHead = wellResFrame.findResultCellFromOutletSpecification(outletResultBranch.m_outletBranchIndex_OBSOLETE, outletResultBranch.m_outletBranchHeadCellIndex_OBSOLETE);
if (leafBranchHead &&
!leafBranchHead->isCell() &&
leafBranchHead->m_ertBranchId != outletResultBranch.m_ertBranchId)
{
outletResultBranch = wellResFrame.m_wellResultBranches[outletResultBranch.m_outletBranchIndex_OBSOLETE];
cellIndexInOutletBranch = outletResultBranch.m_outletBranchHeadCellIndex_OBSOLETE;
}
}
else
{
cellIndexInOutletBranch--;
}
if(cellIndexInOutletBranch >= 0 && cellIndexInOutletBranch < outletResultBranch.m_branchResultPoints.size())
{
currCell = outletResultBranch.m_branchResultPoints[cellIndexInOutletBranch];
}
}
}
}
}
// Try to add a copy of the outlet wellResultPoint into the start of each branch
size_t bCount = wellResFrame.m_wellResultBranches.size();
for (size_t bIdx = 0; bIdx < bCount; ++bIdx)
{
size_t outBranchIdx = wellResFrame.m_wellResultBranches[bIdx].m_outletBranchIndex_OBSOLETE;
size_t outCellIdx = wellResFrame.m_wellResultBranches[bIdx].m_outletBranchHeadCellIndex_OBSOLETE;
const RigWellResultPoint* resPoint = wellResFrame.findResultCellFromOutletSpecification(outBranchIdx, outCellIdx);
if (resPoint) // Todo: Is this a correct guarding or indicating an error ?
{
wellResFrame.m_wellResultBranches[bIdx].m_branchResultPoints.insert(wellResFrame.m_wellResultBranches[bIdx].m_branchResultPoints.begin(), *resPoint);
}
}
#endif
}
} // End of the MSW section
else
{
// Code handling None-MSW Wells ... Normal wells that is.
@ -1756,7 +1399,6 @@ void RifReaderEclipseOutput::readWellCells(const ecl_grid_type* mainEclGrid)
wellResFrame.m_wellResultBranches.push_back(RigWellResultBranch());
RigWellResultBranch& wellResultBranch = wellResFrame.m_wellResultBranches.back();
wellResultBranch.m_branchIndex = 0;
wellResultBranch.m_ertBranchId = 0; // Normal wells have only one branch
size_t existingCellCount = wellResultBranch.m_branchResultPoints.size();

View File

@ -1059,12 +1059,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex,
const RigWellResultPoint* wellResultCell = wellResultFrame.findResultCell(gridIndex, cellIndex);
if (wellResultCell)
{
resultInfoText->append(QString("(0-based) Branch Id : %1 Segment Id %2\n").arg(wellResultCell->m_ertBranchId).arg(wellResultCell->m_ertSegmentId));
if (wellResultCell->m_branchConnectionCount)
{
resultInfoText->append(QString("Branch Connection Count : %1\n").arg(wellResultCell->m_branchConnectionCount));
resultInfoText->append(QString("Center coord : %1 %2 %3\n").arg(wellResultCell->m_bottomPosition.x()).arg(wellResultCell->m_bottomPosition.y()).arg(wellResultCell->m_bottomPosition.z()));
}
resultInfoText->append(QString("Well-cell connection info: Well Name: %1 Branch Id: %2 Segment Id: %3\n").arg(singleWellResultData->m_wellName).arg(wellResultCell->m_ertBranchId +1).arg(wellResultCell->m_ertSegmentId+1));
}
}
}

View File

@ -283,3 +283,30 @@ bool RigSingleWellResultsData::isMultiSegmentWell() const
return m_isMultiSegmentWell;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigWellResultPoint* RigWellResultFrame::findResultCell(size_t gridIndex, size_t gridCellIndex) const
{
CVF_ASSERT(gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T);
if (m_wellHead.m_gridCellIndex == gridCellIndex && m_wellHead.m_gridIndex == gridIndex )
{
return &m_wellHead;
}
for (size_t wb = 0; wb < m_wellResultBranches.size(); ++wb)
{
for (size_t wc = 0; wc < m_wellResultBranches[wb].m_branchResultPoints.size(); ++wc)
{
if ( m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridCellIndex == gridCellIndex
&& m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridIndex == gridIndex )
{
return &(m_wellResultBranches[wb].m_branchResultPoints[wc]);
}
}
}
return NULL;
}

View File

@ -27,6 +27,10 @@
#include <vector>
#include "cvfVector3.h"
//==================================================================================================
/// Stores the info on a significant point in the well. Either a well-to-grid connection, or the
/// bottom position of a connection less well-segment
//==================================================================================================
struct RigWellResultPoint
{
RigWellResultPoint() :
@ -35,8 +39,7 @@ struct RigWellResultPoint
m_isOpen(false),
m_ertBranchId(-1),
m_ertSegmentId(-1),
m_bottomPosition(cvf::Vec3d::UNDEFINED),
m_branchConnectionCount(0)
m_bottomPosition(cvf::Vec3d::UNDEFINED)
{ }
bool isPointValid() const
@ -54,42 +57,36 @@ struct RigWellResultPoint
return isCell() || isPointValid();
}
size_t m_gridIndex;
size_t m_gridCellIndex; //< Index to cell which is included in the well
size_t m_gridIndex;
size_t m_gridCellIndex; //< Index to cell which is included in the well
bool m_isOpen; //< Marks the well as open or closed as of Eclipse simulation
bool m_isOpen; //< Marks the well as open or closed as of Eclipse simulation
int m_ertBranchId;
int m_ertSegmentId;
int m_ertBranchId;
int m_ertSegmentId;
cvf::Vec3d m_bottomPosition;
size_t m_branchConnectionCount;
cvf::Vec3d m_bottomPosition; //< The estimated bottom position of the well segment, when we have no grid cell connections for the segment.
};
//==================================================================================================
/// This class contains the connection information from and including a splitpoint to the end of
/// that particular branch.
//==================================================================================================
struct RigWellResultBranch
{
RigWellResultBranch() :
m_branchIndex(cvf::UNDEFINED_SIZE_T),
m_ertBranchId(-1),
m_outletBranchIndex_OBSOLETE(cvf::UNDEFINED_SIZE_T),
m_outletBranchHeadCellIndex_OBSOLETE(cvf::UNDEFINED_SIZE_T)
m_ertBranchId(-1)
{}
size_t m_branchIndex;
int m_ertBranchId;
std::vector<RigWellResultPoint> m_branchResultPoints;
// Grid cell from last connection in outlet segment. For MSW wells, this is either well head or a well result cell in another branch
// For standard wells, this is always well head.
size_t m_outletBranchIndex_OBSOLETE;
size_t m_outletBranchHeadCellIndex_OBSOLETE;
int m_ertBranchId;
std::vector<RigWellResultPoint> m_branchResultPoints;
};
//==================================================================================================
/// This class contains the well information for one timestep.
/// The main content is the vector of RigWellResultBranch which contains all the simple pipe
/// sections that make up the well
//==================================================================================================
class RigWellResultFrame
{
public:
@ -101,51 +98,14 @@ public:
m_productionType(UNDEFINED_PRODUCTION_TYPE)
{ }
const RigWellResultPoint* findResultCell(size_t gridIndex, size_t gridCellIndex) const
{
CVF_ASSERT(gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T);
const RigWellResultPoint* findResultCell(size_t gridIndex, size_t gridCellIndex) const;
if (m_wellHead.m_gridCellIndex == gridCellIndex && m_wellHead.m_gridIndex == gridIndex )
{
return &m_wellHead;
}
for (size_t wb = 0; wb < m_wellResultBranches.size(); ++wb)
{
for (size_t wc = 0; wc < m_wellResultBranches[wb].m_branchResultPoints.size(); ++wc)
{
if ( m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridCellIndex == gridCellIndex
&& m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridIndex == gridIndex )
{
return &(m_wellResultBranches[wb].m_branchResultPoints[wc]);
}
}
}
return NULL;
}
const RigWellResultPoint* findResultCellFromOutletSpecification(size_t branchIndex, size_t wellResultCellIndex) const
{
if (branchIndex != cvf::UNDEFINED_SIZE_T && branchIndex < m_wellResultBranches.size())
{
const RigWellResultBranch& resBranch = m_wellResultBranches[branchIndex];
if (wellResultCellIndex != cvf::UNDEFINED_SIZE_T && wellResultCellIndex < resBranch.m_branchResultPoints.size())
{
return (&resBranch.m_branchResultPoints[wellResultCellIndex]);
}
}
return NULL;
}
WellProductionType m_productionType;
bool m_isOpen;
RigWellResultPoint m_wellHead;
QDateTime m_timestamp;
WellProductionType m_productionType;
bool m_isOpen;
RigWellResultPoint m_wellHead;
QDateTime m_timestamp;
std::vector<RigWellResultBranch> m_wellResultBranches;
std::vector<RigWellResultBranch> m_wellResultBranches;
};
@ -157,26 +117,24 @@ class RigSingleWellResultsData : public cvf::Object
public:
RigSingleWellResultsData() { m_isMultiSegmentWell = false; }
void setMultiSegmentWell(bool isMultiSegmentWell);
bool isMultiSegmentWell() const;
void setMultiSegmentWell(bool isMultiSegmentWell);
bool isMultiSegmentWell() const;
bool hasWellResult(size_t resultTimeStepIndex) const;
size_t firstResultTimeStep() const;
const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const;
void computeStaticWellCellPath();
void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector<QDateTime>& resultTimes);
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;
RigWellResultFrame m_staticWellCells;
bool hasWellResult(size_t resultTimeStepIndex) const;
size_t firstResultTimeStep() const;
const RigWellResultFrame& wellResultFrame(size_t resultTimeStepIndex) const;
void computeStaticWellCellPath();
void computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector<QDateTime>& resultTimes);
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;
RigWellResultFrame m_staticWellCells;
};