Skip to content

Commit

Permalink
(#540) Range filter matching: Prioritize cell matches with collapsed …
Browse files Browse the repository at this point in the history
…eclipse cells less.

To make better matches when one or more corner of the range is in a
collapsed cells area
  • Loading branch information
JacobStoren committed Oct 22, 2015
1 parent 9d106ec commit 44d1aaa
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
bool femIsDestination)
{
{
struct RangeFilterCorner { RangeFilterCorner() : isExactMatch(false){} cvf::Vec3st ijk; bool isExactMatch; };
struct RangeFilterCorner { RangeFilterCorner() : cellMatchType(APPROX_ON_COLLAPSED){} cvf::Vec3st ijk; CellMatchType cellMatchType; };

RangeFilterCorner rangeFilterMatches[8];

Expand All @@ -210,7 +210,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE

if (femIsDestination)
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
rangeFilterMatches[cornerIdx].cellMatchType = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
Expand All @@ -219,7 +219,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));

rangeFilterMatches[diagIdx].isExactMatch = findBestFemCellFromEclCell(eclGrid,
rangeFilterMatches[diagIdx].cellMatchType = findBestFemCellFromEclCell(eclGrid,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
Expand All @@ -230,7 +230,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
}
else
{
rangeFilterMatches[cornerIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
rangeFilterMatches[cornerIdx].cellMatchType = findBestEclCellFromFemCell(femPart,
srcRangeCube[cornerIdx][0],
srcRangeCube[cornerIdx][1],
srcRangeCube[cornerIdx][2],
Expand All @@ -239,7 +239,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
&(rangeFilterMatches[cornerIdx].ijk[1]),
&(rangeFilterMatches[cornerIdx].ijk[2]));

rangeFilterMatches[diagIdx].isExactMatch = findBestEclCellFromFemCell(femPart,
rangeFilterMatches[diagIdx].cellMatchType = findBestEclCellFromFemCell(femPart,
srcRangeCube[diagIdx][0],
srcRangeCube[diagIdx][1],
srcRangeCube[diagIdx][2],
Expand All @@ -249,7 +249,7 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
&(rangeFilterMatches[diagIdx].ijk[2]));
}

if (rangeFilterMatches[cornerIdx].isExactMatch && rangeFilterMatches[diagIdx].isExactMatch)
if (rangeFilterMatches[cornerIdx].cellMatchType == EXACT && rangeFilterMatches[diagIdx].cellMatchType == EXACT)
{
foundExactMatch = true;
break;
Expand All @@ -269,9 +269,8 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE
}
else
{
// Todo: be even smarter, and use possible matching corners to add up an as best solution as possible.
// For now we just take the first diagonal.

// Look at the matches for each "face" of the range filter cube,
// and use first exact match to determine the position of that "face"
size_t faceIJKs[6] = {cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T,cvf::UNDEFINED_SIZE_T};
for (int faceIdx = 0; faceIdx < 6; ++faceIdx)
{
Expand All @@ -282,28 +281,40 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE

cvf::ubyte surfCorners[4];
cvf::StructGridInterface::cellFaceVertexIndices((cvf::StructGridInterface::FaceType) faceIdx , surfCorners);
bool foundExactMatch = false;
std::vector<size_t> candidates;
bool foundAcceptedMatch = false;
for (int cIdx = 0; cIdx < 4; ++cIdx)
{
if (rangeFilterMatches[surfCorners[cIdx]].isExactMatch)
if (rangeFilterMatches[surfCorners[cIdx]].cellMatchType == EXACT)
{
foundExactMatch = true;
foundAcceptedMatch = true;

faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[cIdx]].ijk[ijOrk];
break;
}
else
{
candidates.push_back(rangeFilterMatches[surfCorners[cIdx]].ijk[ijOrk]);
}
}

if (!foundExactMatch)
if (!foundAcceptedMatch)
{
// Todo: Select the most common, or the max or the min or something clever.
CVF_TIGHT_ASSERT(candidates.size() == 4);
faceIJKs[faceIdx] = candidates[0];
// Take first match that is not related to a collapsed eclipse cell
for (int cIdx = 0; cIdx < 4; ++cIdx)
{
if (rangeFilterMatches[surfCorners[cIdx]].cellMatchType == APPROX)
{
foundAcceptedMatch = true;

faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[cIdx]].ijk[ijOrk];
break;
}
}


if (!foundAcceptedMatch)
{
// Only collapsed cell hits in this "face"
// Todo: then use opposite face - range filter thickness
// For now, just select the first
faceIJKs[faceIdx] = rangeFilterMatches[surfCorners[0]].ijk[ijOrk];
}
}
}

Expand All @@ -324,9 +335,10 @@ void RigCaseToCaseRangeFilterMapper::convertRangeFilterEndPoints(const RigRangeE


//--------------------------------------------------------------------------------------------------
///
/// Return 0 for collapsed cell 1 for
//--------------------------------------------------------------------------------------------------
bool RigCaseToCaseRangeFilterMapper::findBestFemCellFromEclCell(const RigMainGrid* masterEclGrid, size_t ei, size_t ej, size_t ek, const RigFemPart* dependentFemPart, size_t* fi, size_t * fj, size_t* fk)
RigCaseToCaseRangeFilterMapper::CellMatchType
RigCaseToCaseRangeFilterMapper::findBestFemCellFromEclCell(const RigMainGrid* masterEclGrid, size_t ei, size_t ej, size_t ek, const RigFemPart* dependentFemPart, size_t* fi, size_t * fj, size_t* fk)
{
// Find tolerance

Expand All @@ -340,6 +352,8 @@ bool RigCaseToCaseRangeFilterMapper::findBestFemCellFromEclCell(const RigMainGri

size_t cellIdx = masterEclGrid->cellIndexFromIJK(ei, ej, ek);

bool isCollapsedCell = masterEclGrid->cells()[cellIdx].isCollapsedCell();

cvf::Vec3d geoMechConvertedEclCell[8];
RigCaseToCaseCellMapperTools::estimatedFemCellFromEclCell(masterEclGrid, cellIdx, geoMechConvertedEclCell);

Expand Down Expand Up @@ -393,13 +407,16 @@ bool RigCaseToCaseRangeFilterMapper::findBestFemCellFromEclCell(const RigMainGri
(*fk) = cvf::UNDEFINED_SIZE_T;
}

return foundExactMatch;
if (foundExactMatch) return EXACT;
if (isCollapsedCell) return APPROX_ON_COLLAPSED;
return APPROX;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCaseToCaseRangeFilterMapper::findBestEclCellFromFemCell(const RigFemPart* dependentFemPart, size_t fi, size_t fj, size_t fk, const RigMainGrid* masterEclGrid, size_t* ei, size_t* ej, size_t* ek)
RigCaseToCaseRangeFilterMapper::CellMatchType
RigCaseToCaseRangeFilterMapper::findBestEclCellFromFemCell(const RigFemPart* dependentFemPart, size_t fi, size_t fj, size_t fk, const RigMainGrid* masterEclGrid, size_t* ei, size_t* ej, size_t* ek)
{
// Find tolerance

Expand Down Expand Up @@ -454,9 +471,11 @@ bool RigCaseToCaseRangeFilterMapper::findBestEclCellFromFemCell(const RigFemPart
}
}

bool isCollapsedCell = false;
if (globCellIdxToBestMatch != cvf::UNDEFINED_SIZE_T)
{
masterEclGrid->ijkFromCellIndex(globCellIdxToBestMatch, ei, ej, ek);
isCollapsedCell = masterEclGrid->cells()[globCellIdxToBestMatch].isCollapsedCell();
}
else
{
Expand All @@ -465,5 +484,7 @@ bool RigCaseToCaseRangeFilterMapper::findBestEclCellFromFemCell(const RigFemPart
(*ek) = cvf::UNDEFINED_SIZE_T;
}

return foundExactMatch;
if (foundExactMatch) return EXACT;
if (isCollapsedCell) return APPROX_ON_COLLAPSED;
return APPROX;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ class RigCaseToCaseRangeFilterMapper
const RigFemPart* femPart,
bool femIsDestination);


static bool findBestFemCellFromEclCell(const RigMainGrid* masterEclGrid, size_t ei, size_t ej, size_t ek,
enum CellMatchType {APPROX_ON_COLLAPSED, APPROX, EXACT };
static CellMatchType findBestFemCellFromEclCell(const RigMainGrid* masterEclGrid, size_t ei, size_t ej, size_t ek,
const RigFemPart* dependentFemPart, size_t* fi, size_t * fj, size_t* fk);

static bool findBestEclCellFromFemCell(const RigFemPart* dependentFemPart, size_t fi, size_t fj, size_t fk,
static CellMatchType findBestEclCellFromFemCell(const RigFemPart* dependentFemPart, size_t fi, size_t fj, size_t fk,
const RigMainGrid* masterEclGrid, size_t* ei, size_t* ej, size_t* ek);
};

Expand Down
43 changes: 43 additions & 0 deletions ApplicationCode/ReservoirDataModel/RigCell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,49 @@ bool RigCell::isLongPyramidCell(double maxHeightFactor, double nodeNearTolerance
return false;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigCell::isCollapsedCell(double nodeNearTolerance) const
{
const std::vector<cvf::Vec3d>& nodes = m_hostGrid->mainGrid()->nodes();

bool isPyramidCell = false;
cvf::ubyte faceVertexIndices[4];
cvf::ubyte oppFaceVertexIndices[4];

int face;
for ( face = 0; face < 6 ; face += 2)
{
cvf::StructGridInterface::cellFaceVertexIndices(static_cast<cvf::StructGridInterface::FaceType>(face), faceVertexIndices);
cvf::StructGridInterface::cellFaceVertexIndices(cvf::StructGridInterface::oppositeFace(static_cast<cvf::StructGridInterface::FaceType>(face)), oppFaceVertexIndices);

cvf::Vec3d c0 = nodes[m_cornerIndices[faceVertexIndices[0]]];
cvf::Vec3d c1 = nodes[m_cornerIndices[faceVertexIndices[1]]];
cvf::Vec3d c2 = nodes[m_cornerIndices[faceVertexIndices[2]]];
cvf::Vec3d c3 = nodes[m_cornerIndices[faceVertexIndices[3]]];

cvf::Vec3d oc0 = nodes[m_cornerIndices[oppFaceVertexIndices[0]]];
cvf::Vec3d oc1 = nodes[m_cornerIndices[oppFaceVertexIndices[1]]];
cvf::Vec3d oc2 = nodes[m_cornerIndices[oppFaceVertexIndices[2]]];
cvf::Vec3d oc3 = nodes[m_cornerIndices[oppFaceVertexIndices[3]]];

int zeroLengthEdgeCount = 0;
if (isNear(c0, oc0, nodeNearTolerance)) { ++zeroLengthEdgeCount; }
if (isNear(c1, oc3, nodeNearTolerance)) { ++zeroLengthEdgeCount; }
if (isNear(c2, oc2, nodeNearTolerance)) { ++zeroLengthEdgeCount; }
if (isNear(c3, oc1, nodeNearTolerance)) { ++zeroLengthEdgeCount; }

if (zeroLengthEdgeCount >= 4)
{
return true;
}
}

return false;
}


//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions ApplicationCode/ReservoirDataModel/RigCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class RigCell

int firstIntersectionPoint(const cvf::Ray& ray, cvf::Vec3d* intersectionPoint) const;
bool isLongPyramidCell(double maxHeightFactor = 5, double nodeNearTolerance = 1e-3 ) const;
bool isCollapsedCell( double nodeNearTolerance = 1e-3) const;
private:
caf::SizeTArray8 m_cornerIndices;

Expand Down

0 comments on commit 44d1aaa

Please sign in to comment.