mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-10 23:46:00 -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 "RimReservoirCellResultsCacher.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);
|
||||
|
||||
|
||||
const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper();
|
||||
RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData();
|
||||
|
||||
|
||||
cvf::ref<cvf::Color3ubArray> surfaceFacesColorArray;
|
||||
|
||||
// Outer surface
|
||||
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<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());
|
||||
if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p());
|
||||
if (surfaceFacesColorArray.notNull())
|
||||
{
|
||||
if (dg)
|
||||
{
|
||||
dg->setColorArray(surfaceFacesColorArray.p());
|
||||
}
|
||||
|
||||
caf::PolygonOffset polygonOffset = caf::PO_1;
|
||||
caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset);
|
||||
cvf::ref<cvf::Effect> colorArrayEffect = new cvf::Effect;
|
||||
|
||||
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
|
||||
@ -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,
|
||||
const std::vector<cvf::StructGridInterface::FaceType>& quadsToFaceTypes,
|
||||
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 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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
@ -160,10 +160,10 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
||||
QStringList varList = getResultVariableListForCurrentUIFieldSettings();
|
||||
|
||||
bool hasCombinedTransmissibility = false;
|
||||
|
||||
QList<caf::PdmOptionItemInfo> optionList;
|
||||
for (int i = 0; i < varList.size(); ++i)
|
||||
{
|
||||
|
||||
if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
hasCombinedTransmissibility = true;
|
||||
@ -171,7 +171,6 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
||||
}
|
||||
|
||||
optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i]));
|
||||
|
||||
}
|
||||
|
||||
if (hasCombinedTransmissibility)
|
||||
@ -179,6 +178,11 @@ QList<caf::PdmOptionItemInfo> RimResultDefinition::calculateValueOptions(const c
|
||||
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() ));
|
||||
|
||||
if (useOptionsOnly) *useOptionsOnly = true;
|
||||
@ -223,7 +227,6 @@ void RimResultDefinition::loadResult()
|
||||
gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -251,7 +254,6 @@ bool RimResultDefinition::hasStaticResult() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimResultDefinition::hasResult() const
|
||||
{
|
||||
|
||||
if (this->currentGridCellResults() && this->currentGridCellResults()->cellResults())
|
||||
{
|
||||
const RigCaseCellResultsData* gridCellResults = this->currentGridCellResults()->cellResults();
|
||||
@ -341,3 +343,14 @@ void RimResultDefinition::setPorosityModelUiFieldHidden(bool hide)
|
||||
{
|
||||
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 hasDynamicResult() const;
|
||||
bool hasResult() const;
|
||||
bool isTernarySaturationSelected() const;
|
||||
|
||||
RimReservoirCellResultsStorage* currentGridCellResults() const;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user