#933 Fixed the closes result for intersections also. Display the tensor data from the closest element node transformed onto the plane.

This commit is contained in:
Jacob Støren
2016-10-26 17:05:39 +02:00
parent 1a23e6c670
commit c93c7e41df
18 changed files with 454 additions and 125 deletions

View File

@@ -36,6 +36,7 @@ ${CEE_CURRENT_LIST_DIR}RiuViewer.h
${CEE_CURRENT_LIST_DIR}RiuViewerCommands.h
${CEE_CURRENT_LIST_DIR}RiuWellLogPlot.h
${CEE_CURRENT_LIST_DIR}RiuWellLogTrack.h
${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.h
)
set (SOURCE_GROUP_SOURCE_FILES
@@ -70,6 +71,8 @@ ${CEE_CURRENT_LIST_DIR}RiuViewer.cpp
${CEE_CURRENT_LIST_DIR}RiuViewerCommands.cpp
${CEE_CURRENT_LIST_DIR}RiuWellLogPlot.cpp
${CEE_CURRENT_LIST_DIR}RiuWellLogTrack.cpp
${CEE_CURRENT_LIST_DIR}RiuGeoMechXfTensorResultAccessor.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -29,13 +29,18 @@
#include "RimGeoMechCase.h"
#include "RimGeoMechResultDefinition.h"
#include "RimGeoMechView.h"
#include "RiuGeoMechXfTensorResultAccessor.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuFemResultTextBuilder::RiuFemResultTextBuilder(RimGeoMechView* reservoirView, int gridIndex, int cellIndex, int timeStepIndex)
RiuFemResultTextBuilder::RiuFemResultTextBuilder(RimGeoMechView* reservoirView,
int gridIndex,
int cellIndex,
int timeStepIndex)
: m_isIntersectionTriangleSet(false)
{
CVF_ASSERT(reservoirView);
@@ -56,6 +61,15 @@ void RiuFemResultTextBuilder::setIntersectionPoint(cvf::Vec3d intersectionPoint)
m_intersectionPoint = intersectionPoint;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuFemResultTextBuilder::setIntersectionTriangle(const std::array<cvf::Vec3f, 3>& triangle)
{
m_intersectionTriangle = triangle;
m_isIntersectionTriangleSet = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -341,7 +355,8 @@ QString RiuFemResultTextBuilder::closestNodeResultText(RimGeoMechResultDefinitio
m_intersectionPoint);
int resultIndex = closestIndexCalc.resultIndexToClosestResult();
int closestNodeId = closestIndexCalc.closestNodeId();
int closestElmNodResIdx = closestIndexCalc.closestElementNodeResIdx();
float scalarValue = (resultIndex >= 0) ? scalarResults[resultIndex]: std::numeric_limits<float>::infinity();
@@ -356,6 +371,16 @@ QString RiuFemResultTextBuilder::closestNodeResultText(RimGeoMechResultDefinitio
.arg(caf::AppEnum<cvf::StructGridInterface::FaceType>::textFromIndex(m_face))
.arg(scalarValue));
}
else if (m_isIntersectionTriangleSet && activeResultPosition == RIG_ELEMENT_NODAL_FACE)
{
RiuGeoMechXfTensorResultAccessor tensAccessor(geomData->femPartResults(), resultColors->resultAddress(), m_timeStepIndex);
float tensValue = tensAccessor.calculateElmNodeValue(m_intersectionTriangle, closestElmNodResIdx);
text.append(QString("Closest result: N[%1], in Element[%2] transformed onto intersection: %3 \n")
.arg(closestNodeId)
.arg(femPart->elmId(m_cellIndex))
.arg(tensValue));
}
}
}

View File

@@ -24,6 +24,7 @@
#include "cvfStructGrid.h"
#include <QString>
#include <array>
class RigGeoMechCaseData;
class RimEclipseCellColors;
@@ -44,6 +45,7 @@ public:
RiuFemResultTextBuilder(RimGeoMechView* reservoirView, int gridIndex, int cellIndex, int timeStepIndex);
void setFace(int face);
void setIntersectionPoint(cvf::Vec3d intersectionPoint);
void setIntersectionTriangle(const std::array<cvf::Vec3f, 3>& triangle);
QString mainResultText();
@@ -67,6 +69,8 @@ private:
int m_timeStepIndex;
int m_face;
bool m_isIntersectionTriangleSet;
std::array<cvf::Vec3f, 3> m_intersectionTriangle;
cvf::Vec3d m_intersectionPoint;
};

View File

@@ -0,0 +1,147 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuGeoMechXfTensorResultAccessor.h"
#include "RigFemPartResultsCollection.h"
#include "cvfGeometryTools.h"
#include "RivHexGridIntersectionTools.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuGeoMechXfTensorResultAccessor::RiuGeoMechXfTensorResultAccessor(RigFemPartResultsCollection * femResCollection, const RigFemResultAddress& resVarAddress, int timeStepIdx)
{
RigFemResultAddress tensComp = resVarAddress;
tensComp.resultPosType = RIG_ELEMENT_NODAL;
tensComp.componentName = "S11";
tens11 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
tensComp.componentName = "S22";
tens22 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
tensComp.componentName = "S33";
tens33 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
tensComp.componentName = "S12";
tens12 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
tensComp.componentName = "S23";
tens23 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
tensComp.componentName = "S13";
tens13 = &femResCollection->resultValues(tensComp, 0, timeStepIdx);
resultComponent = caf::Ten3f::SZZ;
if ( resVarAddress.componentName == "SN" ) resultComponent = caf::Ten3f::SZZ;
if ( resVarAddress.componentName == "STH" ) resultComponent = caf::Ten3f::SXX;
if ( resVarAddress.componentName == "STQV" ) resultComponent = caf::Ten3f::SYY;
if ( resVarAddress.componentName == "TNH" ) resultComponent = caf::Ten3f::SZX;
if ( resVarAddress.componentName == "TNQV" ) resultComponent = caf::Ten3f::SYZ;
if ( resVarAddress.componentName == "THQV" ) resultComponent = caf::Ten3f::SXY;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuGeoMechXfTensorResultAccessor::calculateInterpolatedValue(const cvf::Vec3f triangle[3], const RivIntersectionVertexWeights vertexWeights[3], float returnValues[3])
{
if ( tens11->size() == 0 )
{
returnValues[0] = returnValues[1] = returnValues[2] = std::numeric_limits<float>::infinity();
return;
}
cvf::Mat3f triangleXf = cvf::GeometryTools::computePlaneHorizontalRotationMx(triangle[1] - triangle[0], triangle[2] - triangle[0]);
for ( int triangleVxIdx = 0; triangleVxIdx < 3; ++triangleVxIdx )
{
float ipT11 = 0;
float ipT22 = 0;
float ipT33 = 0;
float ipT12 = 0;
float ipT23 = 0;
float ipT13 = 0;
int weightCount = vertexWeights[triangleVxIdx].size();
for ( int wIdx = 0; wIdx < weightCount; ++wIdx )
{
size_t resIdx = vertexWeights[triangleVxIdx].vxId(wIdx) ;
float interpolationWeight = vertexWeights[triangleVxIdx].weight(wIdx);
ipT11 += (*tens11)[resIdx] * interpolationWeight;
ipT22 += (*tens22)[resIdx] * interpolationWeight;
ipT33 += (*tens33)[resIdx] * interpolationWeight;
ipT12 += (*tens12)[resIdx] * interpolationWeight;
ipT23 += (*tens23)[resIdx] * interpolationWeight;
ipT13 += (*tens13)[resIdx] * interpolationWeight;
}
if ( ipT11 == HUGE_VAL || ipT11 != ipT11
|| ipT22 == HUGE_VAL || ipT22 != ipT22
|| ipT33 == HUGE_VAL || ipT33 != ipT33
|| ipT12 == HUGE_VAL || ipT12 != ipT12
|| ipT23 == HUGE_VAL || ipT23 != ipT23
|| ipT13 == HUGE_VAL || ipT13 != ipT13 ) // a != a is true for NAN's
{
returnValues[triangleVxIdx] = std::numeric_limits<float>::infinity();
}
else
{
caf::Ten3f tensor(ipT11, ipT22, ipT33,
ipT12, ipT23, ipT13);
caf::Ten3f xfTen = tensor.rotated(triangleXf);
returnValues[triangleVxIdx] = xfTen[resultComponent];
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RiuGeoMechXfTensorResultAccessor::calculateElmNodeValue(const std::array<cvf::Vec3f, 3> & triangle, int globalElmNodeResIndex)
{
if ( tens11->size() == 0 ) return std::numeric_limits<float>::infinity();
cvf::Mat3f triangleXf = cvf::GeometryTools::computePlaneHorizontalRotationMx(triangle[1] - triangle[0], triangle[2] - triangle[0]);
float ipT11 = (*tens11)[globalElmNodeResIndex];
float ipT22 = (*tens22)[globalElmNodeResIndex];
float ipT33 = (*tens33)[globalElmNodeResIndex];
float ipT12 = (*tens12)[globalElmNodeResIndex];
float ipT23 = (*tens23)[globalElmNodeResIndex];
float ipT13 = (*tens13)[globalElmNodeResIndex];
if ( ipT11 == HUGE_VAL || ipT11 != ipT11
|| ipT22 == HUGE_VAL || ipT22 != ipT22
|| ipT33 == HUGE_VAL || ipT33 != ipT33
|| ipT12 == HUGE_VAL || ipT12 != ipT12
|| ipT23 == HUGE_VAL || ipT23 != ipT23
|| ipT13 == HUGE_VAL || ipT13 != ipT13 ) // a != a is true for NAN's
{
return std::numeric_limits<float>::infinity();
}
else
{
caf::Ten3f tensor(ipT11, ipT22, ipT33,
ipT12, ipT23, ipT13);
caf::Ten3f xfTen = tensor.rotated(triangleXf);
float scalarValue = xfTen[resultComponent];
return scalarValue;
}
}

View File

@@ -0,0 +1,51 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <vector>
#include <array>
#include "cafTensor3.h"
class RigFemPartResultsCollection;
class RigFemResultAddress;
class RivIntersectionVertexWeights;
class RiuGeoMechXfTensorResultAccessor
{
public:
RiuGeoMechXfTensorResultAccessor(RigFemPartResultsCollection * femResCollection, const RigFemResultAddress& resVarAddress, int timeStepIdx);
void calculateInterpolatedValue(const cvf::Vec3f triangle[3], const RivIntersectionVertexWeights vertexWeights[3], float returnValues[3]);
float calculateElmNodeValue(const std::array<cvf::Vec3f, 3> & triangle, int globalElmNodeResIndex);
private:
const std::vector<float>* tens11;
const std::vector<float>* tens22;
const std::vector<float>* tens33;
const std::vector<float>* tens12;
const std::vector<float>* tens23;
const std::vector<float>* tens13;
caf::Ten3f::TensorComponentEnum resultComponent;
};

View File

@@ -44,6 +44,8 @@
#include <QStatusBar>
#include <assert.h>
#include "RigFemPartResultsCollection.h"
#include "RigFemPartCollection.h"
//--------------------------------------------------------------------------------------------------
///
@@ -143,12 +145,29 @@ void RiuSelectionChangedHandler::addCurveFromSelectionItem(const RiuGeoMechSelec
geoMechView->geoMechCase() &&
geoMechView->geoMechCase()->geoMechData())
{
RigFemTimeHistoryResultAccessor timeHistResultAccessor(geoMechView->geoMechCase()->geoMechData(),
geoMechView->cellResultResultDefinition()->resultAddress(),
geomSelectionItem->m_gridIndex,
geomSelectionItem->m_cellIndex,
geomSelectionItem->m_elementFace,
geomSelectionItem->m_localIntersectionPoint);
std::unique_ptr<RigFemTimeHistoryResultAccessor> timeHistResultAccessor;
if ( geomSelectionItem->m_hasIntersectionTriangle )
{
timeHistResultAccessor = std::unique_ptr<RigFemTimeHistoryResultAccessor>(
new RigFemTimeHistoryResultAccessor(geoMechView->geoMechCase()->geoMechData(),
geoMechView->cellResultResultDefinition()->resultAddress(),
geomSelectionItem->m_gridIndex,
static_cast<int>(geomSelectionItem->m_cellIndex),
geomSelectionItem->m_elementFace,
geomSelectionItem->m_localIntersectionPoint,
geomSelectionItem->m_intersectionTriangle));
}
else
{
timeHistResultAccessor = std::unique_ptr<RigFemTimeHistoryResultAccessor>(
new RigFemTimeHistoryResultAccessor(geoMechView->geoMechCase()->geoMechData(),
geoMechView->cellResultResultDefinition()->resultAddress(),
geomSelectionItem->m_gridIndex,
static_cast<int>(geomSelectionItem->m_cellIndex),
geomSelectionItem->m_elementFace,
geomSelectionItem->m_localIntersectionPoint));
}
QString curveName;
curveName.append(geoMechView->geoMechCase()->caseUserDescription() + ", ");
@@ -158,16 +177,22 @@ void RiuSelectionChangedHandler::addCurveFromSelectionItem(const RiuGeoMechSelec
curveName.append(geoMechView->cellResultResultDefinition()->resultFieldUiName()+ ", ") ;
curveName.append(geoMechView->cellResultResultDefinition()->resultComponentUiName() + " ");
if ( resPosAppEnum == RIG_ELEMENT_NODAL_FACE && geomSelectionItem->m_elementFace >= 0 )
{
curveName.append(", " + caf::AppEnum<cvf::StructGridInterface::FaceType>::textFromIndex(geomSelectionItem->m_elementFace));
if ( resPosAppEnum == RIG_ELEMENT_NODAL_FACE )
{
if ( geomSelectionItem->m_elementFace >= 0 )
{
curveName.append(", " + caf::AppEnum<cvf::StructGridInterface::FaceType>::textFromIndex(geomSelectionItem->m_elementFace));
}
else
{
curveName.append(", from N[" + QString::number(timeHistResultAccessor->closestNodeId()) + "] transformed onto intersection");
}
}
curveName.append("\n");
curveName.append(":\n");
curveName.append(timeHistResultAccessor->topologyText());
curveName.append(timeHistResultAccessor.topologyText());
std::vector<double> timeHistoryValues = timeHistResultAccessor.timeHistoryValues();
std::vector<double> timeHistoryValues = timeHistResultAccessor->timeHistoryValues();
QStringList stepNames = geoMechView->geoMechCase()->timeStepStrings();
std::vector<QDateTime> dates = RimGeoMechCase::dateTimeVectorFromTimeStepStrings(stepNames);
@@ -258,6 +283,8 @@ void RiuSelectionChangedHandler::updateResultInfo(const RiuSelectionItem* itemAd
RiuFemResultTextBuilder textBuilder(geomView, (int)geomSelectionItem->m_gridIndex, (int)geomSelectionItem->m_cellIndex, geomView->currentTimeStep());
textBuilder.setIntersectionPoint(geomSelectionItem->m_localIntersectionPoint);
textBuilder.setFace(geomSelectionItem->m_elementFace);
if (geomSelectionItem->m_hasIntersectionTriangle) textBuilder.setIntersectionTriangle(geomSelectionItem->m_intersectionTriangle);
resultInfo = textBuilder.mainResultText();
pickInfo = textBuilder.topologyText(", ");

View File

@@ -140,6 +140,29 @@ RiuGeoMechSelectionItem::RiuGeoMechSelectionItem(RimGeoMechView* view,
m_cellIndex(cellIndex),
m_color(color),
m_elementFace(elementFace),
m_localIntersectionPoint(localIntersectionPoint)
m_localIntersectionPoint(localIntersectionPoint),
m_hasIntersectionTriangle(false)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuGeoMechSelectionItem::RiuGeoMechSelectionItem(RimGeoMechView* view,
size_t gridIndex,
size_t cellIndex,
cvf::Color3f color,
int elementFace,
const cvf::Vec3d& localIntersectionPoint,
const std::array<cvf::Vec3f, 3>& intersectionTriangle)
: m_view(view),
m_gridIndex(gridIndex),
m_cellIndex(cellIndex),
m_color(color),
m_elementFace(elementFace),
m_localIntersectionPoint(localIntersectionPoint),
m_hasIntersectionTriangle(true),
m_intersectionTriangle(m_intersectionTriangle)
{
}

View File

@@ -27,6 +27,7 @@
#include <vector>
#include <assert.h>
#include <array>
class RimEclipseView;
class RiuSelectionChangedHandler;
@@ -138,6 +139,14 @@ public:
cvf::Color3f color,
int elementFace,
const cvf::Vec3d& localIntersectionPoint);
explicit RiuGeoMechSelectionItem(RimGeoMechView* view,
size_t gridIndex,
size_t cellIndex,
cvf::Color3f color,
int elementFace,
const cvf::Vec3d& localIntersectionPoint,
const std::array<cvf::Vec3f, 3>& m_intersectionTriangle );
virtual ~RiuGeoMechSelectionItem() {};
virtual RiuSelectionType type() const
@@ -151,6 +160,8 @@ public:
size_t m_cellIndex;
cvf::Color3f m_color;
int m_elementFace;
bool m_hasIntersectionTriangle;
std::array<cvf::Vec3f, 3> m_intersectionTriangle;
cvf::Vec3d m_localIntersectionPoint;
};

View File

@@ -80,6 +80,7 @@
#include <QMenu>
#include <QMouseEvent>
#include <QStatusBar>
#include <array>
@@ -470,6 +471,8 @@ void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardM
size_t nncIndex = cvf::UNDEFINED_SIZE_T;
cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::NO_FACE;
int gmFace = -1;
bool intersectionHit = false;
std::array<cvf::Vec3f, 3> intersectionTriangleHit;
cvf::Vec3d localIntersectionPoint(cvf::Vec3d::ZERO);
@@ -525,14 +528,20 @@ void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardM
else if (crossSectionSourceInfo)
{
findCellAndGridIndex(crossSectionSourceInfo, firstPartTriangleIndex, &cellIndex, &gridIndex);
intersectionHit = true;
intersectionTriangleHit = crossSectionSourceInfo->triangle(firstPartTriangleIndex);
RiuMainWindow::instance()->selectAsCurrentItem(const_cast<RimIntersection*>(crossSectionSourceInfo->crossSection()));
}
else if (intersectionBoxSourceInfo)
{
findCellAndGridIndex(intersectionBoxSourceInfo, firstPartTriangleIndex, &cellIndex, &gridIndex);
intersectionHit = true;
intersectionTriangleHit = intersectionBoxSourceInfo->triangle(firstPartTriangleIndex);
RiuMainWindow::instance()->selectAsCurrentItem(const_cast<RimIntersectionBox*>(intersectionBoxSourceInfo->intersectionBox()));
}
else if (eclipseWellSourceInfo)
{
@@ -580,9 +589,10 @@ void RiuViewerCommands::handlePickAction(int winPosX, int winPosY, Qt::KeyboardM
}
RimGeoMechView* geomView = dynamic_cast<RimGeoMechView*>(m_reservoirView.p());
if (geomView)
if (geomView )
{
selItem = new RiuGeoMechSelectionItem(geomView, gridIndex, cellIndex, curveColor, gmFace, localIntersectionPoint);
if(intersectionHit) selItem = new RiuGeoMechSelectionItem(geomView, gridIndex, cellIndex, curveColor, gmFace, localIntersectionPoint, intersectionTriangleHit);
else selItem = new RiuGeoMechSelectionItem(geomView, gridIndex, cellIndex, curveColor, gmFace, localIntersectionPoint);
}
}