mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-11 07:56:08 -06:00
Added ternary saturation visualization
Ternary saturation available on top of dynamic results Created visualization for ternary based on SOIL, SGAS and SWAT
This commit is contained in:
parent
bf9ecc7c5f
commit
d10177494e
@ -41,6 +41,8 @@
|
|||||||
#include "Rim3dOverlayInfoConfig.h"
|
#include "Rim3dOverlayInfoConfig.h"
|
||||||
#include "RimReservoirCellResultsCacher.h"
|
#include "RimReservoirCellResultsCacher.h"
|
||||||
#include "RivSourceInfo.h"
|
#include "RivSourceInfo.h"
|
||||||
|
#include "cvfRenderState_FF.h"
|
||||||
|
#include "cafProgressInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -250,15 +252,23 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot*
|
|||||||
{
|
{
|
||||||
CVF_ASSERT(cellResultSlot);
|
CVF_ASSERT(cellResultSlot);
|
||||||
|
|
||||||
|
|
||||||
const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper();
|
const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper();
|
||||||
RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData();
|
RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData();
|
||||||
|
|
||||||
|
cvf::ref<cvf::Color3ubArray> surfaceFacesColorArray;
|
||||||
|
|
||||||
// Outer surface
|
// Outer surface
|
||||||
if (m_surfaceFaces.notNull())
|
if (m_surfaceFaces.notNull())
|
||||||
{
|
{
|
||||||
if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0)
|
if (cellResultSlot->isTernarySaturationSelected())
|
||||||
|
{
|
||||||
|
surfaceFacesColorArray = new cvf::Color3ubArray;
|
||||||
|
|
||||||
|
const std::vector<size_t>& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices();
|
||||||
|
|
||||||
|
RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells);
|
||||||
|
}
|
||||||
|
else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0)
|
||||||
{
|
{
|
||||||
const std::vector<cvf::StructGridInterface::FaceType>& quadsToFaceTypes = m_surfaceGenerator.quadToFace();
|
const std::vector<cvf::StructGridInterface::FaceType>& quadsToFaceTypes = m_surfaceGenerator.quadToFace();
|
||||||
const std::vector<size_t>& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices();
|
const std::vector<size_t>& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices();
|
||||||
@ -309,16 +319,41 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot*
|
|||||||
}
|
}
|
||||||
|
|
||||||
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>(m_surfaceFaces->drawable());
|
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>(m_surfaceFaces->drawable());
|
||||||
if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p());
|
if (surfaceFacesColorArray.notNull())
|
||||||
|
{
|
||||||
|
if (dg)
|
||||||
|
{
|
||||||
|
dg->setColorArray(surfaceFacesColorArray.p());
|
||||||
|
}
|
||||||
|
|
||||||
caf::PolygonOffset polygonOffset = caf::PO_1;
|
cvf::ref<cvf::Effect> colorArrayEffect = new cvf::Effect;
|
||||||
caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset);
|
|
||||||
|
|
||||||
scalarEffgen.setOpacityLevel(m_opacityLevel);
|
cvf::ref<cvf::RenderStateMaterial_FF> mat = new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE);
|
||||||
|
mat->enableColorMaterial(true);
|
||||||
|
colorArrayEffect->setRenderState(mat.p());
|
||||||
|
|
||||||
cvf::ref<cvf::Effect> scalarEffect = scalarEffgen.generateEffect();
|
cvf::ref<cvf::RenderStateLighting_FF> lighting = new cvf::RenderStateLighting_FF;
|
||||||
|
lighting->enableTwoSided(true);
|
||||||
|
colorArrayEffect->setRenderState(lighting.p());
|
||||||
|
|
||||||
m_surfaceFaces->setEffect(scalarEffect.p());
|
m_surfaceFaces->setEffect(colorArrayEffect.p());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dg)
|
||||||
|
{
|
||||||
|
dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p());
|
||||||
|
}
|
||||||
|
|
||||||
|
caf::PolygonOffset polygonOffset = caf::PO_1;
|
||||||
|
caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset);
|
||||||
|
|
||||||
|
scalarEffgen.setOpacityLevel(m_opacityLevel);
|
||||||
|
|
||||||
|
cvf::ref<cvf::Effect> scalarEffect = scalarEffgen.generateEffect();
|
||||||
|
|
||||||
|
m_surfaceFaces->setEffect(scalarEffect.p());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Faults
|
// Faults
|
||||||
@ -535,3 +570,76 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Helper class used to provide zero for all cells
|
||||||
|
/// This way we can avoid to test if a StructGridScalarDataAccess object is valid before reading out the value.
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
class ScalarDataAccessZeroForAllCells : public cvf::StructGridScalarDataAccess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual double cellScalar(size_t cellIndex) const
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
virtual void setCellScalar(size_t cellIndex, double value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Creates and assigns a ternary saturation color for all four vertices of a quad representing a cell face
|
||||||
|
///
|
||||||
|
/// Loads ternary saturation results SOIL, SWAT and SGAS
|
||||||
|
/// If any of these are not present, the values for a missing component is set to 0.0
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t timeStepIndex, RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Color3ubArray* colorArray, const std::vector<size_t>& quadsToGridCells)
|
||||||
|
{
|
||||||
|
RimReservoirCellResultsStorage* gridCellResults = cellResultSlot->currentGridCellResults();
|
||||||
|
if (!gridCellResults) return;
|
||||||
|
|
||||||
|
RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData();
|
||||||
|
if (!eclipseCase) return;
|
||||||
|
|
||||||
|
size_t soilScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL");
|
||||||
|
size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS");
|
||||||
|
size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT");
|
||||||
|
|
||||||
|
RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel());
|
||||||
|
|
||||||
|
cvf::ref<cvf::StructGridScalarDataAccess> dataAccessObjectSoil = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, soilScalarSetIndex);
|
||||||
|
if (dataAccessObjectSoil.isNull()) dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells;
|
||||||
|
|
||||||
|
cvf::ref<cvf::StructGridScalarDataAccess> dataAccessObjectSgas = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, sgasScalarSetIndex);
|
||||||
|
if (dataAccessObjectSgas.isNull()) dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells;
|
||||||
|
|
||||||
|
cvf::ref<cvf::StructGridScalarDataAccess> dataAccessObjectSwat = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, swatScalarSetIndex);
|
||||||
|
if (dataAccessObjectSwat.isNull()) dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells;
|
||||||
|
|
||||||
|
size_t numVertices = quadsToGridCells.size()*4;
|
||||||
|
|
||||||
|
colorArray->resize(numVertices);
|
||||||
|
|
||||||
|
cvf::Color3f ternaryColor;
|
||||||
|
cvf::Color3ub ternaryColorByte;
|
||||||
|
|
||||||
|
#pragma omp parallel for private(ternaryColor, ternaryColorByte)
|
||||||
|
for (int idx = 0; idx < static_cast<int>(quadsToGridCells.size()); idx++)
|
||||||
|
{
|
||||||
|
size_t gridCellIndex = quadsToGridCells[idx];
|
||||||
|
|
||||||
|
ternaryColor.r() = dataAccessObjectSgas->cellScalar(gridCellIndex);
|
||||||
|
ternaryColor.g() = dataAccessObjectSoil->cellScalar(gridCellIndex);
|
||||||
|
ternaryColor.b() = dataAccessObjectSwat->cellScalar(gridCellIndex);
|
||||||
|
|
||||||
|
ternaryColorByte.set(ternaryColor.rByte(), ternaryColor.gByte(), ternaryColor.bByte());
|
||||||
|
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
colorArray->set(idx*4 + j, ternaryColorByte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -50,6 +50,13 @@ public:
|
|||||||
cvf::Vec2fArray* textureCoords,
|
cvf::Vec2fArray* textureCoords,
|
||||||
const std::vector<cvf::StructGridInterface::FaceType>& quadsToFaceTypes,
|
const std::vector<cvf::StructGridInterface::FaceType>& quadsToFaceTypes,
|
||||||
const std::vector<size_t>& quadsToGridCells);
|
const std::vector<size_t>& quadsToGridCells);
|
||||||
|
|
||||||
|
static void updateTernarySaturationColorArray(
|
||||||
|
size_t timeStepIndex,
|
||||||
|
RimResultSlot* cellResultSlot,
|
||||||
|
const RigGridBase* grid,
|
||||||
|
cvf::Color3ubArray* colorArray,
|
||||||
|
const std::vector<size_t>& quadsToGridCells);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,5 +43,6 @@ public:
|
|||||||
static QString undefinedGridFaultName() { return "Undefined grid faults"; }
|
static QString undefinedGridFaultName() { return "Undefined grid faults"; }
|
||||||
|
|
||||||
static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; }
|
static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; }
|
||||||
|
static QString ternarySaturationResultName() { return "TERNARY"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -818,7 +818,7 @@ void RimReservoirView::updateCurrentTimeStep()
|
|||||||
{
|
{
|
||||||
m_reservoirGridPartManager->updateCellEdgeResultColor(geometriesToRecolor[i], m_currentTimeStep, this->cellResult(), this->cellEdgeResult());
|
m_reservoirGridPartManager->updateCellEdgeResultColor(geometriesToRecolor[i], m_currentTimeStep, this->cellResult(), this->cellEdgeResult());
|
||||||
}
|
}
|
||||||
else if (this->animationMode() && this->cellResult()->hasResult())
|
else if ((this->animationMode() && this->cellResult()->hasResult()) || this->cellResult()->isTernarySaturationSelected())
|
||||||
{
|
{
|
||||||
m_reservoirGridPartManager->updateCellResultColor(geometriesToRecolor[i], m_currentTimeStep, this->cellResult());
|
m_reservoirGridPartManager->updateCellResultColor(geometriesToRecolor[i], m_currentTimeStep, this->cellResult());
|
||||||
}
|
}
|
||||||
|
@ -160,10 +160,10 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
|||||||
QStringList varList = getResultVariableListForCurrentUIFieldSettings();
|
QStringList varList = getResultVariableListForCurrentUIFieldSettings();
|
||||||
|
|
||||||
bool hasCombinedTransmissibility = false;
|
bool hasCombinedTransmissibility = false;
|
||||||
|
|
||||||
QList<caf::PdmOptionItemInfo> optionList;
|
QList<caf::PdmOptionItemInfo> optionList;
|
||||||
for (int i = 0; i < varList.size(); ++i)
|
for (int i = 0; i < varList.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0)
|
if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0)
|
||||||
{
|
{
|
||||||
hasCombinedTransmissibility = true;
|
hasCombinedTransmissibility = true;
|
||||||
@ -171,7 +171,6 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i]));
|
optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i]));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCombinedTransmissibility)
|
if (hasCombinedTransmissibility)
|
||||||
@ -179,6 +178,11 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
|||||||
optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedTransmissibilityResultName(), RimDefines::combinedTransmissibilityResultName()));
|
optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedTransmissibilityResultName(), RimDefines::combinedTransmissibilityResultName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_resultTypeUiField == RimDefines::DYNAMIC_NATIVE)
|
||||||
|
{
|
||||||
|
optionList.push_front(caf::PdmOptionItemInfo(RimDefines::ternarySaturationResultName(), RimDefines::ternarySaturationResultName()));
|
||||||
|
}
|
||||||
|
|
||||||
optionList.push_front(caf::PdmOptionItemInfo( RimDefines::undefinedResultName(), RimDefines::undefinedResultName() ));
|
optionList.push_front(caf::PdmOptionItemInfo( RimDefines::undefinedResultName(), RimDefines::undefinedResultName() ));
|
||||||
|
|
||||||
if (useOptionsOnly) *useOptionsOnly = true;
|
if (useOptionsOnly) *useOptionsOnly = true;
|
||||||
@ -223,7 +227,6 @@ void RimResultDefinition::loadResult()
|
|||||||
gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable);
|
gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -251,7 +254,6 @@ bool RimResultDefinition::hasStaticResult() const
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RimResultDefinition::hasResult() const
|
bool RimResultDefinition::hasResult() const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (this->currentGridCellResults() && this->currentGridCellResults()->cellResults())
|
if (this->currentGridCellResults() && this->currentGridCellResults()->cellResults())
|
||||||
{
|
{
|
||||||
const RigCaseCellResultsData* gridCellResults = this->currentGridCellResults()->cellResults();
|
const RigCaseCellResultsData* gridCellResults = this->currentGridCellResults()->cellResults();
|
||||||
@ -341,3 +343,14 @@ void RimResultDefinition::setPorosityModelUiFieldHidden(bool hide)
|
|||||||
{
|
{
|
||||||
m_porosityModelUiField.setUiHidden(true);
|
m_porosityModelUiField.setUiHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RimResultDefinition::isTernarySaturationSelected() const
|
||||||
|
{
|
||||||
|
bool isTernary = (m_resultType() == RimDefines::DYNAMIC_NATIVE) &&
|
||||||
|
(m_resultVariable().compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0);
|
||||||
|
|
||||||
|
return isTernary;
|
||||||
|
}
|
||||||
|
@ -55,6 +55,8 @@ public:
|
|||||||
bool hasStaticResult() const;
|
bool hasStaticResult() const;
|
||||||
bool hasDynamicResult() const;
|
bool hasDynamicResult() const;
|
||||||
bool hasResult() const;
|
bool hasResult() const;
|
||||||
|
bool isTernarySaturationSelected() const;
|
||||||
|
|
||||||
RimReservoirCellResultsStorage* currentGridCellResults() const;
|
RimReservoirCellResultsStorage* currentGridCellResults() const;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user