Result Divided by Area: Establish concept used to compute flow velocity and normalized trans (#7349)

* Geometry Tools : Add convenience functions for polygon area

* #7232 Result Divided by Area: Add cell face result and show in GUI

Native support for flow rate is given by mass rate (mass per time) over a cell face. Add a derived result that takes flow rate divided by cell face area to get velocity (distance per time).

Add support for this concept on relevant native results, and indicate this result type in UI using a "/A" postfix

* Speed up divided-by-area calculations by using openmp

* Some refactoring of result data access.

* Make sure NNC data is scaled correctly in vector flow viz.

Co-authored-by: jonjenssen <jon@soundsoft.no>
This commit is contained in:
Magne Sjaastad
2021-02-11 03:01:17 +01:00
committed by GitHub
parent 424f66fd4e
commit cc292b197a
30 changed files with 631 additions and 321 deletions

View File

@@ -104,16 +104,7 @@ void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::Mode
maxAbsResult = std::max( cvf::Math::abs( max ), cvf::Math::abs( min ) );
}
float arrowScaling = arrowConstantScaling;
if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT )
{
arrowScaling = arrowConstantScaling / maxAbsResult;
}
if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT_LOG )
{
arrowScaling = result->sizeScale() * scaleLogarithmically( maxAbsResult );
}
float arrowScaling = arrowConstantScaling / maxAbsResult;
std::vector<RigEclipseResultAddress> resultAddresses;
std::vector<cvf::StructGridInterface::FaceType> directions;
@@ -190,15 +181,7 @@ void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::Mode
cvf::Vec3d faceCenter;
cvf::Vec3d faceNormal;
getFaceCenterAndNormal( gcIdx, directions[dir], faceCenter, faceNormal );
if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT )
{
faceNormal *= std::abs( resultValue );
}
else if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT_LOG )
{
faceNormal *= std::abs( scaleLogarithmically( std::abs( resultValue ) ) );
}
faceNormal *= std::abs( resultValue );
tensorVisualizations.push_back(
ElementVectorResultVisualization( faceCenter,
@@ -225,22 +208,8 @@ void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::Mode
cvf::Vec3d faceNormal;
cvf::Vec3d faceNormalScaled;
getFaceCenterAndNormal( gcIdx, directions[dir], faceCenter, faceNormal );
faceNormalScaled = faceNormal;
if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT )
{
faceNormalScaled *= resultValue;
}
else if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT_LOG )
{
faceNormalScaled *= ( 1.0 - static_cast<double>( std::signbit( resultValue ) ) * 2.0 ) *
scaleLogarithmically( std::abs( resultValue ) );
}
faceNormalScaled = faceNormal * resultValue;
aggregatedVector += faceNormalScaled;
// If the vector is scaled in a logarithmic scale, the result should still be the same as before.
// Hence, we need to separate the result value from the vector.
aggregatedResult += faceNormal.getNormalized() * resultValue;
}
if ( aggregatedResult.length() >= result->threshold() )
@@ -266,7 +235,7 @@ void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::Mode
for ( auto candidate : combinedAddresses )
{
if ( candidate.m_resultCatType == RiaDefines::ResultCatType::DYNAMIC_NATIVE )
if ( candidate.resultCatType() == RiaDefines::ResultCatType::DYNAMIC_NATIVE )
{
if ( nncData->hasScalarValues( candidate ) )
{
@@ -288,21 +257,14 @@ void RivElementVectorResultPartMgr::appendDynamicGeometryPartsToModel( cvf::Mode
resultValue += nncResultVals.at( flIdx )->at( timeStepIndex )[nIdx];
}
}
cvf::Vec3d connCenter =
static_cast<cvf::Vec3d>( cvf::GeometryTools::computePolygonCenter<cvf::Vec3f>( conn.polygon() ) );
cvf::Vec3d faceCenter;
cvf::Vec3d connNormal;
getFaceCenterAndNormal( conn.c1GlobIdx(), conn.face(), faceCenter, connNormal );
if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT )
{
connNormal *= std::abs( resultValue );
}
else if ( result->scaleMethod() == RimElementVectorResult::ScaleMethod::RESULT_LOG )
{
connNormal *= scaleLogarithmically( std::abs( resultValue ) );
}
connNormal *= std::abs( resultValue );
if ( std::abs( resultValue ) >= result->threshold() )
{
@@ -341,7 +303,7 @@ cvf::ref<cvf::Part>
vertices.reserve( tensorVisualizations.size() * 7 );
uint counter = 0;
for ( ElementVectorResultVisualization tensor : tensorVisualizations )
for ( const ElementVectorResultVisualization& tensor : tensorVisualizations )
{
for ( const cvf::Vec3f& vertex : createArrowVertices( tensor ) )
{
@@ -430,7 +392,7 @@ void RivElementVectorResultPartMgr::createResultColorTextureCoords(
size_t vertexCount = elementVectorResultVisualizations.size() * 7;
if ( textureCoords->size() != vertexCount ) textureCoords->reserve( vertexCount );
for ( auto evrViz : elementVectorResultVisualizations )
for ( auto& evrViz : elementVectorResultVisualizations )
{
for ( size_t vxIdx = 0; vxIdx < 7; ++vxIdx )
{

View File

@@ -169,7 +169,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
eclipseResultAddress = cellResultColors->eclipseResultAddress();
}
if ( eclipseResultAddress.m_resultCatType == RiaDefines::ResultCatType::ALLAN_DIAGRAMS )
if ( eclipseResultAddress.resultCatType() == RiaDefines::ResultCatType::ALLAN_DIAGRAMS )
{
showCompleteNncGeo = true;
}
@@ -183,7 +183,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
for ( const auto& s : stringsToMatch )
{
if ( eclipseResultAddress.m_resultName.contains( s, Qt::CaseInsensitive ) )
if ( eclipseResultAddress.resultName().contains( s, Qt::CaseInsensitive ) )
{
showCompleteNncGeo = true;
}
@@ -202,7 +202,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
if ( showNncs )
{
RigMainGrid* mainGrid = m_reservoirView->mainGrid();
mainGrid->nncData()->ensureConnectionDataIsProcecced();
mainGrid->nncData()->ensureConnectionDataIsProcessed();
if ( showCompleteNncGeo )
{