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:
Magne Sjaastad 2014-04-04 10:59:21 +02:00
parent bf9ecc7c5f
commit d10177494e
6 changed files with 145 additions and 14 deletions

View File

@ -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);
}
}
}

View File

@ -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);
}; };

View File

@ -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"; }
}; };

View File

@ -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());
} }

View File

@ -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;
}

View File

@ -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;