#3630 Implement volume calculation on grid

This commit is contained in:
Gaute Lindkvist
2018-11-06 12:47:54 +01:00
parent 8ebfe074f1
commit ef4b70d6e5
12 changed files with 261 additions and 22 deletions

View File

@@ -961,6 +961,12 @@ void RigCaseCellResultsData::createPlaceholderResultEntries()
}
}
// Cell Volume
{
addStaticScalarResult(RiaDefines::STATIC_NATIVE, RiaDefines::riCellVolumeResultName(), false, 0);
}
// Mobile Pore Volume
{
if (findScalarResultIndex(RiaDefines::STATIC_NATIVE, "PORV") != cvf::UNDEFINED_SIZE_T)
@@ -1140,6 +1146,10 @@ size_t RigCaseCellResultsData::findOrLoadScalarResult(RiaDefines::ResultCatType
progressInfo.incrementProgress();
}
}
else if (resultName == RiaDefines::riCellVolumeResultName())
{
computeCellVolumes();
}
else if (resultName == RiaDefines::mobilePoreVolumeName())
{
computeMobilePV();
@@ -2404,6 +2414,30 @@ double RigCaseCellResultsData::darchysValue()
return RiaEclipseUnitTools::darcysConstant(m_ownerCaseData->unitsType());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigCaseCellResultsData::computeCellVolumes()
{
size_t cellVolIdx = this->findOrCreateScalarResultIndex(RiaDefines::STATIC_NATIVE, RiaDefines::riCellVolumeResultName(), false);
std::vector<double>& cellVolumeResults = this->cellScalarResults(cellVolIdx)[0];
size_t cellResultCount = m_activeCellInfo->reservoirCellResultCount();
cellVolumeResults.resize(cellResultCount, 0u);
#pragma omp parallel for
for (int nativeResvCellIndex = 0; nativeResvCellIndex < static_cast<int>(m_ownerMainGrid->globalCellArray().size()); nativeResvCellIndex++)
{
size_t resultIndex = activeCellInfo()->cellResultIndex(nativeResvCellIndex);
if (resultIndex != cvf::UNDEFINED_SIZE_T)
{
const RigCell& cell = m_ownerMainGrid->globalCellArray()[nativeResvCellIndex];
cellVolumeResults[resultIndex] = cell.volume();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -154,6 +154,7 @@ private: // from RimReservoirCellResultsStorage
void computeCompletionTypeForTimeStep(size_t timeStep);
double darchysValue();
void computeCellVolumes();
void computeMobilePV();
bool isDataPresent(size_t scalarResultIndex) const;

View File

@@ -20,6 +20,7 @@
#include "RigCell.h"
#include "RigCellGeometryTools.h"
#include "RigMainGrid.h"
#include "cvfPlane.h"
#include "cvfRay.h"
@@ -301,6 +302,21 @@ cvf::Vec3d RigCell::faceNormalWithAreaLenght(cvf::StructGridInterface::FaceType
( nodeCoords[m_cornerIndices[faceVertexIndices[3]]] - nodeCoords[m_cornerIndices[faceVertexIndices[1]]]);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigCell::volume() const
{
const std::vector<cvf::Vec3d>& nodeCoords = m_hostGrid->mainGrid()->nodes();
std::array<cvf::Vec3d, 8> hexCorners;
for (size_t i = 0; i < 8; ++i)
{
hexCorners[i] = nodeCoords.at(m_cornerIndices[i]);
}
return RigCellGeometryTools::calculateCellVolume(hexCorners);
}
//--------------------------------------------------------------------------------------------------
/// Find the intersection between the cell and the ray. The point closest to the ray origin is returned
/// in \a intersectionPoint, while the return value is the total number of intersections with the 24 triangles

View File

@@ -70,6 +70,8 @@ public:
cvf::Vec3d center() const;
cvf::Vec3d faceCenter(cvf::StructGridInterface::FaceType face) const;
cvf::Vec3d faceNormalWithAreaLenght(cvf::StructGridInterface::FaceType face) const;
double volume() const;
int firstIntersectionPoint(const cvf::Ray& ray, cvf::Vec3d* intersectionPoint) const;
bool isLongPyramidCell(double maxHeightFactor = 5, double nodeNearTolerance = 1e-3 ) const;

View File

@@ -23,12 +23,64 @@
#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h"
#include "cvfBoundingBox.h"
#include "cvfMatrix3.h"
#include "clipper/clipper.hpp"
#include <vector>
#include <array>
//--------------------------------------------------------------------------------------------------
/// Efficient Computation of Volume of Hexahedral Cells
/// Jeffrey Grandy, Lawrence Livermore National Laboratory
/// https://www.osti.gov/servlets/purl/632793/
///
/// Note that in the paper the following vertex numbering is used
/// 6---------7
/// /| /| |k
/// / | / | | /j
/// 4---------5 | |/
/// | 2------|--3 *---i
/// | / | /
/// |/ |/
/// 0---------1
///
/// While in ResInsight, this is the numbering. Thus 2<->3, 6<->7 from the paper.
/// Note the negative k!
/// 7---------6
/// /| /| |-k
/// / | / | | /j
/// 4---------5 | |/
/// | 3------|--2 *---i
/// | / | /
/// |/ |/
/// 0---------1
//--------------------------------------------------------------------------------------------------
double RigCellGeometryTools::calculateCellVolume(const std::array<cvf::Vec3d, 8>& x)
{
// 6 * 3 flops = 18 flops
// Perform index swap when retrieving corners but keep indices in variable names matching paper.
cvf::Vec3d x3mx0 = x[6] - x[4]; // Swap 3->2, then negate z by 2->6 and 0->4
cvf::Vec3d x5mx0 = x[1] - x[4]; // Negate z by Swap 5->1 and 0->4
cvf::Vec3d x6mx0 = x[3] - x[4]; // Swap 6->7, then negate z by 7->3 and 0->4
cvf::Vec3d x7mx1 = x[2] - x[5]; // Swap 7->6, then negate z by 6->2 and 1->5
cvf::Vec3d x7mx2 = x[2] - x[7]; // Swap 7->6, 2->3, then negate z by 6->2 and 3->7
cvf::Vec3d x7mx4 = x[2] - x[0]; // Swap 7->6 then negate z by 6->2 and 4->0
// 3 flops for summation + 5 for dot product + 9 flops for cross product = 17 flops
double det1 = (x7mx1 + x6mx0) * (x7mx2 ^ x3mx0);
// 3 flops for summation + 5 for dot product + 9 flops for cross product = 17 flops
double det2 = x6mx0 * ((x7mx2 + x5mx0) ^ x7mx4);
// 3 flops for summation + 5 for dot product + 9 flops for cross product = 17 flops
double det3 = x7mx1 * (x5mx0 ^ (x7mx4 + x3mx0));
// 2 flops for summation + 1 for division = 3 flops
double volume = (det1 + det2 + det3) / 12.0;
CVF_ASSERT(volume > 0.0);
return volume;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -33,6 +33,7 @@
class RigCellGeometryTools
{
public:
static double calculateCellVolume(const std::array<cvf::Vec3d, 8>& hexCorners);
static void createPolygonFromLineSegments(std::list<std::pair<cvf::Vec3d, cvf::Vec3d>> &intersectionLineSegments, std::vector<std::vector<cvf::Vec3d>> &polygons);