From 7da999fa8bfa2db7f0e521f2d862b2685ae0ff53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 16:53:53 +0200 Subject: [PATCH 001/346] Fixed some compiler warnings --- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 5feeb2908c..819a65d5a5 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -73,6 +73,8 @@ bool readDoubleValues(RigCaseData* reservoir, size_t resultIndex, ecl_kw_type* e newPropertyData.push_back(std::vector()); newPropertyData[0].resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, newPropertyData[0].data()); + + return true; } //-------------------------------------------------------------------------------------------------- @@ -110,6 +112,8 @@ bool readDoubleValuesForActiveCells(RigCaseData* reservoir, size_t resultIndex, newPropertyData[0].resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, newPropertyData[0].data()); } + + return true; } From adeeae6a04ff11c3671c3734f2426125e43f60fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 17:19:30 +0200 Subject: [PATCH 002/346] Created StructGrid...ToCellFaceMapper Done to start refactoring to pave way for many new combined result properties --- .../RivCellEdgeEffectGenerator.cpp | 13 +- .../RivFaultGeometryGenerator.cpp | 67 ++-------- .../RivFaultGeometryGenerator.h | 23 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 33 ++--- .../ModelVisualization/RivGridPartMgr.cpp | 123 ++++++++++-------- .../ModelVisualization/RivGridPartMgr.h | 5 +- .../ModelVisualization/RivSourceInfo.cpp | 5 +- .../ModelVisualization/RivSourceInfo.h | 10 +- ApplicationCode/UserInterface/RiuViewer.cpp | 15 ++- .../cvfStructGridGeometryGenerator.cpp | 82 ++++++------ .../cvfStructGridGeometryGenerator.h | 49 +++++-- 11 files changed, 199 insertions(+), 226 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index b2e37f55bc..a195179b51 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -78,8 +78,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t gridIndex, float opacityLevel) { - const std::vector& quadToCell = generator->quadToGridCellIndices(); - const std::vector& quadToFace = generator->quadToFace(); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -166,13 +165,13 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - faceIndexArray->set(quadIdx * 4 + 0, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 1, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 2, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 3, quadToFace[quadIdx] ); + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - size_t cellIndex = quadToCell[quadIdx]; + size_t cellIndex = quadToCellFace->cellIndex(quadIdx); { double scalarValue = HUGE_VAL; diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index 0a8b3efe2f..e9ed113620 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -24,6 +24,8 @@ #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfOutlineEdgeExtractor.h" #include "cvfStructGridScalarDataAccess.h" +#include "cvfStructGridGeometryGenerator.h" + #include "cvfScalarMapper.h" #include "RigFault.h" @@ -38,6 +40,8 @@ RivFaultGeometryGenerator::RivFaultGeometryGenerator(const cvf::StructGridInterf m_fault(fault), m_computeNativeFaultFaces(computeNativeFaultFaces) { + m_quadMapper = new cvf::StructGridQuadToCellFaceMapper; + m_triangleMapper = new cvf::StuctGridTriangleToCellFaceMapper(m_quadMapper.p()); } //-------------------------------------------------------------------------------------------------- @@ -149,8 +153,8 @@ cvf::ref RivFaultGeometryGenerator::lineIndicesFromQuadVertexArr void RivFaultGeometryGenerator::computeArrays() { std::vector vertices; - m_quadsToGridCells.clear(); - m_quadsToFace.clear(); + m_quadMapper->quadToCellIndexMap().clear(); + m_quadMapper->quadToCellFaceMap().clear(); cvf::Vec3d offset = m_grid->displayModelOffset(); @@ -186,8 +190,8 @@ void RivFaultGeometryGenerator::computeArrays() } // Keep track of the source cell index per quad - m_quadsToGridCells.push_back(cellIndex); - m_quadsToFace.push_back(face); + m_quadMapper->quadToCellIndexMap().push_back(cellIndex); + m_quadMapper->quadToCellFaceMap().push_back(face); } } @@ -203,7 +207,7 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord { if (!dataAccessObject) return; - size_t numVertices = m_quadsToGridCells.size()*4; + size_t numVertices = m_quadMapper->quadCount()*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -212,9 +216,9 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadsToGridCells[i]); + cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -229,38 +233,6 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > RivFaultGeometryGenerator::triangleToSourceGridCellMap() const -{ - cvf::ref > triangles = new cvf::Array(2*m_quadsToGridCells.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) - { - triangles->set(i*2, m_quadsToGridCells[i]); - triangles->set(i*2+1, m_quadsToGridCells[i]); - } - - return triangles; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > RivFaultGeometryGenerator::triangleToFaceType() const -{ - cvf::ref > triangles = new cvf::Array(2*m_quadsToFace.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToFace.size()); i++) - { - triangles->set(i*2, m_quadsToFace[i]); - triangles->set(i*2+1, m_quadsToFace[i]); - } - - return triangles; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -268,20 +240,3 @@ void RivFaultGeometryGenerator::setCellVisibility(const cvf::UByteArray* cellVis { m_cellVisibility = cellVisibility; } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivFaultGeometryGenerator::quadToGridCellIndices() const -{ - return m_quadsToGridCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivFaultGeometryGenerator::quadToFace() const -{ - return m_quadsToFace; -} - diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index 43329a408d..81162a67c7 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -52,11 +52,9 @@ class RivFaultGeometryGenerator : public cvf::Object const cvf::ScalarMapper* mapper) const; // Mapping between cells and geometry - cvf::ref > triangleToSourceGridCellMap() const; - cvf::ref > triangleToFaceType() const; - const std::vector& quadToGridCellIndices() const; - const std::vector& quadToFace() const; + const cvf::StructGridQuadToCellFaceMapper * cellFromQuadMapper() { return m_quadMapper.p(); } + const cvf::StuctGridTriangleToCellFaceMapper * cellFromTriangleMapper() { return m_triangleMapper.p(); } // Generated geometry cvf::ref generateSurface(); @@ -70,18 +68,19 @@ class RivFaultGeometryGenerator : public cvf::Object private: // Input - cvf::cref m_grid; - cvf::cref m_fault; - cvf::cref m_cellVisibility; + cvf::cref m_grid; + cvf::cref m_fault; + cvf::cref m_cellVisibility; - bool m_computeNativeFaultFaces; + bool m_computeNativeFaultFaces; // Created arrays - cvf::ref m_vertices; + cvf::ref m_vertices; // Mappings - std::vector m_triangleIndexToGridCellIndex; - std::vector m_quadsToGridCells; + std::vector m_quadsToGridCells; std::vector m_quadsToFace; - std::vector m_triangleToFace; + + cvf::ref m_quadMapper; + cvf::ref m_triangleMapper; }; diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 33e3474d97..f9354a83b6 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -126,17 +126,15 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), + surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_nativeFaultGenerator->quadToFace(); - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_nativeFaultFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, + m_nativeFaultGenerator->cellFromQuadMapper()); } else { @@ -150,14 +148,15 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_nativeFaultFacesTextureCoords->size(); ++i) { if ((*m_nativeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -200,17 +199,13 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_oppositeFaultGenerator->quadToFace(); - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_oppositeFaultFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_oppositeFaultGenerator->cellFromQuadMapper()); } else { @@ -224,14 +219,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) { if ((*m_oppositeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -307,8 +302,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = m_nativeFaultGenerator->triangleToSourceGridCellMap().p(); - si->m_faceTypes = m_nativeFaultGenerator->triangleToFaceType().p(); + si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->cellFromTriangleMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -361,8 +355,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = m_oppositeFaultGenerator->triangleToSourceGridCellMap().p(); - si->m_faceTypes = m_oppositeFaultGenerator->triangleToFaceType().p(); + si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->cellFromTriangleMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ddf67713c6..193571e2b8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -123,8 +123,8 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = geoBuilder.triangleToSourceGridCellMap().p(); - si->m_faceTypes = geoBuilder.triangleToFaceTypes().p(); + si->m_cellFaceFromTriangleMapper = geoBuilder.triangleToCellFaceMapper(); + part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -269,17 +269,12 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_surfaceGenerator.quadToFace(); - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); } else { @@ -304,14 +299,14 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); for(size_t i = 0; i < m_surfaceFacesTextureCoords->size(); ++i) { if ((*m_surfaceFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -373,14 +368,15 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_faultGenerator.quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); for(size_t i = 0; i < m_faultFacesTextureCoords->size(); ++i) { if ((*m_faultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -520,8 +516,7 @@ cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacit void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Vec2fArray* textureCoords, - const std::vector& quadsToFaceTypes, - const std::vector& quadsToGridCells) + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) { const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); if (!mapper) return; @@ -545,7 +540,8 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi cvf::ref dataAccessObjectTranZ = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); - size_t numVertices = quadsToGridCells.size()*4; + int quadCount = static_cast(quadToCellFaceMapper->quadCount()); + size_t numVertices = quadCount*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -554,53 +550,68 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int idx = 0; idx < static_cast(quadsToGridCells.size()); idx++) + for (int quadIdx = 0; quadIdx < quadCount; quadIdx++) { cellScalarValue = HUGE_VAL; - if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_I) - { - cellScalarValue = dataAccessObjectTranX->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_I) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + switch (cellFace) + { + case cvf::StructGridInterface::POS_I: { - cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranX->cellScalar(cellIndex); } - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_J) - { - cellScalarValue = dataAccessObjectTranY->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_J) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + break; + case cvf::StructGridInterface::NEG_I: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); + } + } + break; + case cvf::StructGridInterface::POS_J: { - cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranY->cellScalar(cellIndex); } - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_K) - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_K) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + break; + case cvf::StructGridInterface::NEG_J: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); + } + } + break; + case cvf::StructGridInterface::POS_K: { - cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranZ->cellScalar(cellIndex); } + break; + case cvf::StructGridInterface::NEG_K: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); + + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); + } + } + break; + default: + CVF_ASSERT(false); } + texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -610,7 +621,7 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi size_t j; for (j = 0; j < 4; j++) { - rawPtr[idx*4 + j] = texCoord; + rawPtr[quadIdx*4 + j] = texCoord; } } @@ -640,7 +651,9 @@ class ScalarDataAccessZeroForAllCells : public cvf::StructGridScalarDataAccess /// 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& quadsToGridCells) +void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t timeStepIndex, RimResultSlot* cellResultSlot, + const RigGridBase* grid, cvf::Color3ubArray* colorArray, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) { RimReservoirCellResultsStorage* gridCellResults = cellResultSlot->currentGridCellResults(); if (!gridCellResults) return; @@ -690,7 +703,7 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti double swatRange = swatMax - swatMin; double swatFactor = 255.0 / swatRange; - size_t numVertices = quadsToGridCells.size()*4; + size_t numVertices = quadToCellFaceMapper->quadCount()*4; colorArray->resize(numVertices); @@ -698,9 +711,9 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti double v, vNormalized; #pragma omp parallel for private(ternaryColorByte, v, vNormalized) - for (int idx = 0; idx < static_cast(quadsToGridCells.size()); idx++) + for (int quadIdx = 0; quadIdx < static_cast(quadToCellFaceMapper->quadCount()); quadIdx++) { - size_t gridCellIndex = quadsToGridCells[idx]; + size_t gridCellIndex = quadToCellFaceMapper->cellIndex(quadIdx); { v = dataAccessObjectSgas->cellScalar(gridCellIndex); @@ -729,7 +742,7 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti size_t j; for (j = 0; j < 4; j++) { - colorArray->set(idx*4 + j, ternaryColorByte); + colorArray->set(quadIdx*4 + j, ternaryColorByte); } } } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index d205256381..d866bd5f34 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -49,15 +49,14 @@ class RivTransmissibilityColorMapper RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Vec2fArray* textureCoords, - const std::vector& quadsToFaceTypes, - const std::vector& quadsToGridCells); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); static void updateTernarySaturationColorArray( size_t timeStepIndex, RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Color3ubArray* colorArray, - const std::vector& quadsToGridCells); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); }; diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp index 9df69e03a9..1e67105cde 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp @@ -17,14 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RivSourceInfo.h" +#include "cvfStructGridGeometryGenerator.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RivSourceInfo::hasCellIndices() const +bool RivSourceInfo::hasCellFaceMapping() const { - return m_cellIndices.notNull(); + return m_cellFaceFromTriangleMapper.notNull(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.h b/ApplicationCode/ModelVisualization/RivSourceInfo.h index de670c52a7..b4e5f1306c 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.h +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.h @@ -21,17 +21,15 @@ #include "cvfBase.h" #include "cvfObject.h" #include "cvfArray.h" -#include "cvfStructGrid.h" +#include "cvfStructGridGeometryGenerator.h" class RivSourceInfo : public cvf::Object { public: - bool hasCellIndices() const; + bool hasCellFaceMapping() const; bool hasNNCIndices() const; public: - cvf::ref > m_cellIndices; - cvf::ref > m_faceTypes; - - cvf::ref > m_NNCIndices; + cvf::cref m_cellFaceFromTriangleMapper; + cvf::ref > m_NNCIndices; }; diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 354cc30af3..e58a7bb8a7 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -274,10 +274,10 @@ void RiuViewer::mouseReleaseEvent(QMouseEvent* event) const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivSourceInfo) { - if (rivSourceInfo->hasCellIndices()) + if (rivSourceInfo->hasCellFaceMapping()) { m_currentGridIdx = firstHitPart->id(); - m_currentCellIndex = rivSourceInfo->m_cellIndices->get(faceIndex); + m_currentCellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); QMenu menu; menu.addAction(QString("I-slice range filter"), this, SLOT(slotRangeFilterI())); @@ -436,13 +436,14 @@ void RiuViewer::handlePickAction(int winPosX, int winPosY) const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivSourceInfo) { - if (rivSourceInfo->hasCellIndices()) + if (rivSourceInfo->hasCellFaceMapping()) { - size_t cellIndex = cvf::UNDEFINED_SIZE_T; - cellIndex = rivSourceInfo->m_cellIndices->get(faceIndex); + CVF_ASSERT(rivSourceInfo->m_cellFaceFromTriangleMapper.notNull()); - CVF_ASSERT(rivSourceInfo->m_faceTypes.notNull()); - cvf::StructGridInterface::FaceType face = rivSourceInfo->m_faceTypes->get(faceIndex); + size_t cellIndex = cvf::UNDEFINED_SIZE_T; + cellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); + + cvf::StructGridInterface::FaceType face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, &pickInfo); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index 977b451e63..a5dbdd0633 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -159,6 +159,8 @@ StructGridGeometryGenerator::StructGridGeometryGenerator(const StructGridInterfa : m_grid(grid) { CVF_ASSERT(grid); + m_quadMapper = new StructGridQuadToCellFaceMapper; + m_triangleMapper = new StuctGridTriangleToCellFaceMapper(m_quadMapper.p()); } @@ -309,8 +311,8 @@ bool StructGridGeometryGenerator::isCellFaceVisible(size_t i, size_t j, size_t k void StructGridGeometryGenerator::computeArrays() { std::vector vertices; - m_quadsToGridCells.clear(); - m_quadsToFace.clear(); + m_quadMapper->quadToCellIndexMap().clear(); + m_quadMapper->quadToCellFaceMap().clear(); cvf::Vec3d offset = m_grid->displayModelOffset(); @@ -362,8 +364,8 @@ void StructGridGeometryGenerator::computeArrays() } // Keep track of the source cell index per quad - m_quadsToGridCells.push_back(cellIndex); - m_quadsToFace.push_back(face); + m_quadMapper->quadToCellIndexMap().push_back(cellIndex); + m_quadMapper->quadToCellFaceMap().push_back(face); } } } @@ -385,7 +387,7 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, { if (!dataAccessObject) return; - size_t numVertices = m_quadsToGridCells.size()*4; + size_t numVertices = m_quadMapper->quadCount()*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -394,9 +396,9 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadsToGridCells[i]); + cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -411,37 +413,43 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, } } +#if 0 //-------------------------------------------------------------------------------------------------- /// +/// //-------------------------------------------------------------------------------------------------- -ref > StructGridGeometryGenerator::triangleToSourceGridCellMap() const +void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* dataAccessObject) const { - ref > triangles = new Array(2*m_quadsToGridCells.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) - { - triangles->set(i*2, m_quadsToGridCells[i]); - triangles->set(i*2+1, m_quadsToGridCells[i]); - } + if (!dataAccessObject) return; - return triangles; -} + textureCoords->resize(m_quadMapper->quadCount()*4); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > StructGridGeometryGenerator::triangleToFaceTypes() const -{ - ref > triangles = new Array(2*m_quadsToFace.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToFace.size()); i++) + cvf::Vec2f* rawPtr = textureCoords->ptr(); + + double cellFaceValue; + cvf::Vec2f texCoord; + int quadCount = static_cast(m_quadMapper->quadCount()); + +#pragma omp parallel for private(texCoord, cellFaceValue) + for (int qIdx = 0; qIdx < quadCount; qIdx++) { - triangles->set(i*2, m_quadsToFace[i]); - triangles->set(i*2+1, m_quadsToFace[i]); - } + cellFaceValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); + + texCoord = mapper->mapToTextureCoord(cellFaceValue); - return triangles; + if (cellFaceValue == HUGE_VAL || cellFaceValue != cellFaceValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + } + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[qIdx*4 + j] = texCoord; + } + } } +#endif //-------------------------------------------------------------------------------------------------- /// @@ -451,21 +459,5 @@ void StructGridGeometryGenerator::setCellVisibility(const UByteArray* cellVisibi m_cellVisibility = cellVisibility; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& StructGridGeometryGenerator::quadToGridCellIndices() const -{ - return m_quadsToGridCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& StructGridGeometryGenerator::quadToFace() const -{ - return m_quadsToFace; -} - } // namespace cvf diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index 9b95797a1d..32f0c2cafa 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -121,6 +121,37 @@ class CellFaceVisibilityFilter }; +class StructGridQuadToCellFaceMapper : public Object +{ +public: + size_t quadCount() const { return m_quadsToCells.size();} + + size_t cellIndex(size_t quadIdx) const {return m_quadsToCells[quadIdx]; } + StructGridInterface::FaceType cellFace(size_t quadIdx) const {return m_quadsToFace[quadIdx]; } + + // Interface for building the mappings + std::vector& quadToCellIndexMap() { return m_quadsToCells; } + std::vector& quadToCellFaceMap() { return m_quadsToFace; } + +private: + std::vector m_quadsToCells; + std::vector m_quadsToFace; +}; + + +class StuctGridTriangleToCellFaceMapper : public Object +{ +public: + StuctGridTriangleToCellFaceMapper(const StructGridQuadToCellFaceMapper* quadMapper) { m_quadMapper = quadMapper; } + size_t triangleCount() const { return 2* m_quadMapper->quadCount();} + + size_t cellIndex(size_t triangleIdx) const {return m_quadMapper->cellIndex(triangleIdx/2); } + StructGridInterface::FaceType cellFace(size_t triangleIdx) const {return m_quadMapper->cellFace(triangleIdx/2); } + +private: + cref m_quadMapper; +}; + //================================================================================================== // @@ -145,16 +176,9 @@ class StructGridGeometryGenerator : public Object void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const; // Mapping between cells and geometry - ref > - triangleToSourceGridCellMap() const; - - cvf::ref > - triangleToFaceTypes() const; - const std::vector& - quadToGridCellIndices() const; - const std::vector& - quadToFace() const; + const StructGridQuadToCellFaceMapper * quadToCellFaceMapper() { return m_quadMapper.p(); } + const StuctGridTriangleToCellFaceMapper * triangleToCellFaceMapper() { return m_triangleMapper.p(); } // Generated geometry ref generateSurface(); @@ -176,11 +200,10 @@ class StructGridGeometryGenerator : public Object // Created arrays cvf::ref m_vertices; + // Mappings - std::vector m_triangleIndexToGridCellIndex; - std::vector m_quadsToGridCells; - std::vector m_quadsToFace; - + ref m_quadMapper; + ref m_triangleMapper; }; } From 4f70189734a5766cfa727ddbf2fc25ef2647eea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 22:49:56 +0200 Subject: [PATCH 003/346] Wip - reactoring result texture handling --- .../RivCellEdgeEffectGenerator.h | 59 ++++++++++++- .../ModelVisualization/RivGridPartMgr.cpp | 86 +++++++++++++------ .../ModelVisualization/RivGridPartMgr.h | 7 +- 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index f05d7e1a49..0c37fb84bc 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -43,7 +43,64 @@ class RivCellEdgeGeometryGenerator float opacityLevel); }; - +/* + Thoughts on organizing the texture coords generation a bit. + + Conceptually several mappings takes place: + + 1. ResultValues to ResultPointValues <-- Eg. Cell Center values to CellFace Values + 2. ResultPointValues to GeometryPointValues <-- Eg. CellCenter Values to Triangle Vertex + 3. GeometryPointValues to TextureCoordinates/Colors <-- Handled by ScalarMapper + + When evaluating, we normally use the geometry as starting point, as that often is + a subset of the total results/geometry domain. + + To make this efficient, a minimum of internal storage should be used, so we want + to make the mappings as a set of functions called for each (or a few) texture + coordinate positions + + The mapping is then actually accessed in the opposite way of the above, while calculated in the 1-3 order + + Accessing correct values: + GeometryPointIdx->ResultPointIdx->ResultValueIdx + Calculating color: + ResultValue->ResultPointValue->GeometryPointValue->Texture/ColorValue + + In ResInsight (for now) + the ResultPointValue will be the same for all the corresponding GeometryPoints, + which means each quadvertex has the same texcoord for all corners. + + Proposal: + ---------- + Let the FaceValue to Face vertex texture coordinate mapping be the same for all. + Extract that from the code floating around. + + Create a PrimitiveFaceIdx to CellIdx with Face mapper class that handles the lookup, + created by the geometry generation + + Create separate calculators/mappers/Strategies to create FaceValues from results. + + Test Code + ----------- + // Example code + // 1. CellCenterToCellFace + // 2. CellFace to Quad Corners + // 3. Quad Corner Values to tex coords + + texCoords.resize(m_quadsToGridCells.size()*4); + for (i = 0; i < m_quadsToGridCells.size(); ++i) + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(dataAccessObject->cellScalar(m_quadsToGridCells[i])); + ResValue ResPoint To ResValue + texCoords[i*4 + 0] = texCoord; + texCoords[i*4 + 1] = texCoord; + texCoords[i*4 + 2] = texCoord; + texCoords[i*4 + 3] = texCoord; + } + + + +*/ //================================================================================================== // diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 193571e2b8..df5220b023 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -294,7 +294,13 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* // if this gridpart manager is set to have some transparency, we // interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but // we turn that off for particular cells, if the well pipe is not shown for that cell - + + setResultsTransparentForWellCells( + cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), + m_surfaceGenerator.quadToCellFaceMapper(), + m_surfaceFacesTextureCoords.p()); + /* if (m_opacityLevel < 1.0f ) { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); @@ -317,10 +323,11 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } - - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + + */ if (surfaceFacesColorArray.notNull()) { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); if (dg) { dg->setColorArray(surfaceFacesColorArray.p()); @@ -333,19 +340,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } 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 scalarEffect = scalarEffgen.generateEffect(); - - m_surfaceFaces->setEffect(scalarEffect.p()); + applyResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } @@ -363,7 +358,14 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (dataAccessObject.isNull()) return; m_faultGenerator.textureCoordinates(m_faultFacesTextureCoords.p(), dataAccessObject.p(), mapper); - + + setResultsTransparentForWellCells( + cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), + m_surfaceGenerator.quadToCellFaceMapper(), + m_faultFacesTextureCoords.p()); + + /* if (m_opacityLevel < 1.0f ) { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); @@ -387,18 +389,54 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } + */ + applyResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); + } +} - cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); - if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); +cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) +{ + caf::PolygonOffset polygonOffset = caf::PO_1; + caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + return scalarEffect; +} - caf::PolygonOffset polygonOffset = caf::PO_1; - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); +void RivGridPartMgr::applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) +{ + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); - scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = createScalarMapperEffect(mapper); + part->setEffect(scalarEffect.p()); +} - cvf::ref scalarEffect = scalarEffgen.generateEffect(); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap, + const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, + cvf::Vec2fArray* resultTextureCoords) +{ + if (m_opacityLevel < 1.0f ) + { + for(size_t i = 0; i < resultTextureCoords->size(); ++i) + { + if ((*resultTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - m_faultFaces->setEffect(scalarEffect.p()); + size_t quadIdx = i/4; + size_t cellIndex = quadsToCellFaceMapper->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellIndexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if ( !isWellPipeVisibleForWellIndex[wellIndex]) + { + (*resultTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture + } + } + } } } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index d866bd5f34..c395392902 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -90,7 +90,12 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); - + void applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); + cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); + void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap, + const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, + cvf::Vec2fArray* resultTextureCoords); private: size_t m_gridIdx; cvf::cref m_grid; From a78b056ae309373eb574879da07a88f19a9bd06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 25 Jun 2014 08:47:47 +0200 Subject: [PATCH 004/346] First step in refactoring result texture handling In order to support more derived reults properties more consistently across cell/fault/nnc and celledgevisualizations --- .../ModelVisualization/RivGridPartMgr.cpp | 75 +++++-------------- .../ModelVisualization/RivGridPartMgr.h | 2 +- 2 files changed, 18 insertions(+), 59 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index df5220b023..9bb2544180 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -291,40 +291,13 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), dataAccessObject.p(), mapper); } - // if this gridpart manager is set to have some transparency, we - // interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but - // we turn that off for particular cells, if the well pipe is not shown for that cell - + setResultsTransparentForWellCells( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), m_surfaceGenerator.quadToCellFaceMapper(), m_surfaceFacesTextureCoords.p()); - /* - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); - - for(size_t i = 0; i < m_surfaceFacesTextureCoords->size(); ++i) - { - if ((*m_surfaceFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_surfaceFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } - */ if (surfaceFacesColorArray.notNull()) { cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); @@ -340,7 +313,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - applyResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } @@ -365,35 +338,15 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.quadToCellFaceMapper(), m_faultFacesTextureCoords.p()); - /* - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); - - for(size_t i = 0; i < m_faultFacesTextureCoords->size(); ++i) - { - if ((*m_faultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_faultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } - */ - applyResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); + + applyTextureResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) { caf::PolygonOffset polygonOffset = caf::PO_1; @@ -403,17 +356,23 @@ cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::Scalar return scalarEffect; } -void RivGridPartMgr::applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) { cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); - if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); + if (dg) dg->setTextureCoordArray(textureCoords); cvf::ref scalarEffect = createScalarMapperEffect(mapper); part->setEffect(scalarEffect.p()); } //-------------------------------------------------------------------------------------------------- -/// +/// if this gridpart manager is set to have some transparency, we +/// interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but +/// we turn that off for particular cells, if the well pipe is not shown for that cell //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, const cvf::UIntArray* gridCellToWellIndexMap, diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index c395392902..eb656de4ab 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -90,7 +90,7 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); - void applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); + void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, const cvf::UIntArray* gridCellToWellIndexMap, From ab63b0dccffec25a334646bf33c20c48ae1bc2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 09:12:42 +0200 Subject: [PATCH 005/346] FaultCelledge : Extracted a method from some duplicate code. --- .../ModelVisualization/RivGridPartMgr.cpp | 46 +++++++++++++++++++ .../ModelVisualization/RivGridPartMgr.h | 7 ++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 9bb2544180..16a213cbe0 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -404,6 +404,7 @@ void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector(m_surfaceFaces->drawable()); @@ -424,6 +425,20 @@ void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSl m_surfaceFaces->setEffect(eff.p()); } } + */ + updateCellEdgeResultColorOnPart( + m_surfaceFaces.p(), + &m_surfaceGenerator, + timeStepIndex, cellResultSlot, cellEdgeResultSlot); + + if (m_faultFaces.notNull()) + { + updateCellEdgeResultColorOnPart( + m_faultFaces.p(), + &m_faultGenerator, + timeStepIndex, cellResultSlot, cellEdgeResultSlot); + } + /* if (m_faultFaces.notNull()) { cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); @@ -444,6 +459,37 @@ void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSl m_faultFaces->setEffect(eff.p()); } } + */ +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, + cvf::StructGridGeometryGenerator* surfaceGenerator, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + if (facePart) + { + cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); + if (dg) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); + + cvf::ScalarMapper* cellScalarMapper = NULL; + if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); + cellFaceEffectGen.setOpacityLevel(m_opacityLevel); + cellFaceEffectGen.setDefaultCellColor(m_defaultColor); + + cvf::ref eff = cellFaceEffectGen.generateEffect(); + + facePart->setEffect(eff.p()); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index eb656de4ab..4ef7bb7e13 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -96,6 +96,11 @@ class RivGridPartMgr: public cvf::Object const cvf::UIntArray* gridCellToWellIndexMap, const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, cvf::Vec2fArray* resultTextureCoords); + void updateCellEdgeResultColorOnPart(cvf::Part* facePart, + cvf::StructGridGeometryGenerator* surfaceGenerator, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); private: size_t m_gridIdx; cvf::cref m_grid; @@ -112,7 +117,7 @@ class RivGridPartMgr: public cvf::Object cvf::ref m_surfaceGridLines; - // Fault visualization + // Fault visualization: Dead ?? JJS cvf::StructGridGeometryGenerator m_faultGenerator; RigFaultFaceVisibilityFilter m_faultFaceFilter; cvf::ref m_faultFaces; From 40705830ebc8b4b54b219446f0c834f90a6aac6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 15:08:38 +0200 Subject: [PATCH 006/346] Set version text to development version 1.3.0-dev --- ResInsightVersion.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 69e4286f37..f0906e5df6 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,8 +1,9 @@ set(CMAKE_MAJOR_VERSION 1) -set(CMAKE_MINOR_VERSION 2) +set(CMAKE_MINOR_VERSION 3) set(CMAKE_PATCH_VERSION 0) +set(DEV_VERSION "-dev") set(PRODUCTVER ${CMAKE_MAJOR_VERSION},${CMAKE_MINOR_VERSION},0,${CMAKE_PATCH_VERSION}) -set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}) +set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}${DEV_VERSION}) From ed516f20293b3656ad4c5e1b19d87ffbbeef7e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 15:09:26 +0200 Subject: [PATCH 007/346] Fixed bug/assert introduced after merge --- ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index b33523952d..b8de115c23 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -223,7 +223,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_oppositeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) { From bcb0bce1da2f7b07735d330dbb2e27e69c3fa4b3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 10:14:36 +0200 Subject: [PATCH 008/346] Added build configuration description for Octave for Windows --- .../MinGWBuildConfigurationForOctave.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 OctavePlugin/MinGWBuildConfigurationForOctave.txt diff --git a/OctavePlugin/MinGWBuildConfigurationForOctave.txt b/OctavePlugin/MinGWBuildConfigurationForOctave.txt new file mode 100644 index 0000000000..f74b37cda3 --- /dev/null +++ b/OctavePlugin/MinGWBuildConfigurationForOctave.txt @@ -0,0 +1,17 @@ +Build configuration MinGW +================================== + +http://wiki.octave.org/Windows_Installer + +To be able to build with 64-bit indexing, run the following + +./configure --enable-64 + + + +// To get changes from server +hg pull +hg update + +http://hgbook.red-bean.com/read/a-tour-of-mercurial-the-basics.html + From d93a98815ae4860bf0927c9b0d5a61542115d052 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:09:15 +0200 Subject: [PATCH 009/346] Fwk: Allow label text on check box widget --- .../cafPdmUiCheckBoxEditor.cpp | 21 ++++++++++++------- .../cafUserInterface/cafPdmUiCheckBoxEditor.h | 7 +++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp index 748cf69a9a..7a8ac5dc30 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp @@ -63,14 +63,24 @@ void PdmUiCheckBoxEditor::configureAndUpdateUi(const QString& uiConfigName) assert(!m_checkBox.isNull()); assert(!m_label.isNull()); - QIcon ic = field()->uiIcon(uiConfigName); - if (!ic.isNull()) + PdmUiCheckBoxEditorAttribute attributes; + field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); + + if (attributes.m_useNativeCheckBoxLabel) { - m_label->setPixmap(ic.pixmap(ic.actualSize(QSize(64, 64)))); + m_checkBox->setText(field()->uiName(uiConfigName)); } else { - m_label->setText(field()->uiName(uiConfigName)); + QIcon ic = field()->uiIcon(uiConfigName); + if (!ic.isNull()) + { + m_label->setPixmap(ic.pixmap(ic.actualSize(QSize(64, 64)))); + } + else + { + m_label->setText(field()->uiName(uiConfigName)); + } } m_label->setEnabled(!field()->isUiReadOnly(uiConfigName)); @@ -79,9 +89,6 @@ void PdmUiCheckBoxEditor::configureAndUpdateUi(const QString& uiConfigName) m_checkBox->setEnabled(!field()->isUiReadOnly(uiConfigName)); m_checkBox->setToolTip(field()->uiToolTip(uiConfigName)); - PdmUiCheckBoxEditorAttribute attributes; - field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); - m_checkBox->setChecked(field()->uiValue().toBool()); } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h index 6b01f50e5a..bf67da9809 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h @@ -52,7 +52,14 @@ namespace caf class PdmUiCheckBoxEditorAttribute : public PdmUiEditorAttribute { +public: + PdmUiCheckBoxEditorAttribute() + { + m_useNativeCheckBoxLabel = false; + } +public: + bool m_useNativeCheckBoxLabel; }; From d014e5d228c93be147d90bf304757172ce16c3ac Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:10:51 +0200 Subject: [PATCH 010/346] Preferences : Control if info text from Octave is displayed before executing scripts --- .../Application/RiaPreferences.cpp | 20 +++++++++++++++++-- ApplicationCode/Application/RiaPreferences.h | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 3e45619055..0acd148c48 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -21,6 +21,7 @@ #include "cafPdmUiFilePathEditor.h" #include "cafPdmFieldCvfColor.h" +#include "cafPdmUiCheckBoxEditor.h" CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- @@ -36,8 +37,12 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", QString("kate"), "Script Editor", "", "", ""); scriptEditorExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); - CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave", "", "", ""); + CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave executable location", "", "", ""); octaveExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + octaveExecutable.setUiLabelPosition(caf::PdmUiItemInfo::TOP); + + CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", true, "Show text header when executing scripts", "", "", ""); + octaveShowHeaderInfoWhenExecutingScripts.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "ssihub Address", "", "", ""); @@ -84,6 +89,14 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt myAttr->m_appendUiSelectedFolderToText = true; } } + else if (field == &octaveShowHeaderInfoWhenExecutingScripts) + { + caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_useNativeCheckBoxLabel = true; + } + } } //-------------------------------------------------------------------------------------------------- @@ -96,7 +109,10 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* scriptGroup = uiOrdering.addNewGroup("Script configuration"); scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); - scriptGroup->add(&octaveExecutable); + + caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); + octaveGroup->add(&octaveExecutable); + octaveGroup->add(&octaveShowHeaderInfoWhenExecutingScripts); caf::PdmUiGroup* defaultSettingsGroup = uiOrdering.addNewGroup("Default settings"); defaultSettingsGroup->add(&defaultScaleFactorZ); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 4623599926..4ee1873d49 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -40,7 +40,10 @@ class RiaPreferences : public caf::PdmObject caf::PdmField scriptDirectories; caf::PdmField scriptEditorExecutable; + caf::PdmField octaveExecutable; + caf::PdmField octaveShowHeaderInfoWhenExecutingScripts; + caf::PdmField ssihubAddress; caf::PdmField defaultScaleFactorZ; From 2fbcfde791f11dfeb28b07149982ec2e4bd3b031 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:11:48 +0200 Subject: [PATCH 011/346] Aggregated common Octave argument list --- .../Application/RiaApplication.cpp | 28 +++++++++++++++ ApplicationCode/Application/RiaApplication.h | 2 ++ .../ProjectDataModel/RimCommandObject.cpp | 8 +---- .../ProjectDataModel/RimUiTreeView.cpp | 34 ++----------------- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 28c6de9612..79b9a501bf 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1066,6 +1066,34 @@ QString RiaApplication::octavePath() const return m_preferences->octaveExecutable(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RiaApplication::octaveArguments() const +{ + // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options + + // -p path + // Add path to the head of the search path for function files. The value of path specified on the command line + // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or + // user startup files that set the internal load path through one of the path functions. + + + QStringList arguments; + arguments.append("--path"); + arguments << QApplication::applicationDirPath(); + + if (!m_preferences->octaveShowHeaderInfoWhenExecutingScripts) + { + // -q + // Don't print the usual greeting and version message at startup. + + arguments.append("-q"); + } + + return arguments; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index f026d613b6..d15203870f 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -123,7 +123,9 @@ class RiaApplication : public QApplication RINavigationPolicy navigationPolicy() const; QString scriptDirectories() const; QString scriptEditorPath() const; + QString octavePath() const; + QStringList octaveArguments() const; bool launchProcess(const QString& program, const QStringList& arguments); bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index f24c7bd956..858f936def 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -106,13 +106,7 @@ void RimCommandExecuteScript::redo() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - QStringList arguments; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); + QStringList arguments = app->octaveArguments(); arguments.append("--eval"); arguments << this->scriptText(); diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 690c0bdfa7..60bde2559f 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -538,29 +538,14 @@ void RimUiTreeView::slotExecuteScript() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - // -p path - // Add path to the head of the search path for function files. The value of path specified on the command line - // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or - // user startup files that set the internal load path through one of the path functions. - - // -q - // Don't print the usual greeting and version message at startup. - - // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); - QStringList arguments; + QStringList arguments = app->octaveArguments(); arguments.append("--path"); arguments << octaveFunctionSearchPath; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); arguments << calcScript->absolutePath(); RiaApplication::instance()->launchProcess(octavePath, arguments); @@ -593,29 +578,14 @@ void RimUiTreeView::slotExecuteScriptForSelectedCases() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - // -p path - // Add path to the head of the search path for function files. The value of path specified on the command line - // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or - // user startup files that set the internal load path through one of the path functions. - - // -q - // Don't print the usual greeting and version message at startup. - - // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); - QStringList arguments; + QStringList arguments = app->octaveArguments(); arguments.append("--path"); arguments << octaveFunctionSearchPath; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); arguments << calcScript->absolutePath(); // Get case ID from selected cases in selection model From 22b1f85b614e7df847eb65e2f1d5b3b4a98aff32 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 12 Jun 2014 12:35:48 +0200 Subject: [PATCH 012/346] Removed obsolete includes --- ApplicationCode/ProjectDataModel/RimFault.cpp | 16 +--------------- .../ProjectDataModel/RimFaultCollection.cpp | 15 +++------------ .../ProjectDataModel/RimFaultCollection.h | 2 +- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFault.cpp b/ApplicationCode/ProjectDataModel/RimFault.cpp index 88a3686a19..cbb223c56c 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.cpp +++ b/ApplicationCode/ProjectDataModel/RimFault.cpp @@ -21,12 +21,6 @@ #include "RigFault.h" #include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimFault, "Fault"); @@ -72,17 +66,9 @@ void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const Q if (&showFault == changedField) { this->updateUiIconFromState(showFault); - - RimReservoirView* reservoirView = NULL; - this->firstAncestorOfType(reservoirView); - - if (reservoirView) - { - reservoirView->scheduleCreateDisplayModelAndRedraw(); - } } - if (&faultColor == changedField) + if (&faultColor == changedField || &showFault == changedField) { RimReservoirView* reservoirView = NULL; this->firstAncestorOfType(reservoirView); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index b6a201af09..2de8ac55df 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -21,23 +21,14 @@ #include "cafAppEnum.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirView.h" - -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellEdgeResultSlot.h" #include "RiaApplication.h" #include "RiaPreferences.h" - -#include "RimCase.h" -#include "RimReservoirCellResultsCacher.h" #include "RigCaseData.h" -#include "RivColorTableArray.h" +#include "RimCase.h" +#include "RimReservoirView.h" #include "RiuMainWindow.h" +#include "RivColorTableArray.h" namespace caf diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 632c3bd7c8..0d2cb37b66 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -27,7 +27,7 @@ #include "cvfBase.h" #include "cvfColor3.h" -#include "RimFault.h" +class RimFault; class RimReservoirView; From bf5b42870f6b41215a235db3664b08c3b816823c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 23 Jul 2014 12:22:57 +0200 Subject: [PATCH 013/346] Added recent file list --- .../UserInterface/RiuMainWindow.cpp | 94 ++++++++++++++++++- ApplicationCode/UserInterface/RiuMainWindow.h | 12 ++- 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index a1fe0b204e..7a2d8f163d 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -214,7 +214,15 @@ void RiuMainWindow::createActions() m_saveProjectAsAction = new QAction(QIcon(":/Save.png"), "Save Project &As", this); m_closeProjectAction = new QAction("&Close Project", this); - m_exitAction = new QAction("E&xit", this); + + for (int i = 0; i < MaxRecentFiles; ++i) + { + m_recentFileActions[i] = new QAction(this); + m_recentFileActions[i]->setVisible(false); + connect(m_recentFileActions[i], SIGNAL(triggered()), this, SLOT(slotOpenRecentFile())); + } + + m_exitAction = new QAction("E&xit", this); connect(m_openProjectAction, SIGNAL(triggered()), SLOT(slotOpenProject())); connect(m_openLastUsedProjectAction, SIGNAL(triggered()), SLOT(slotOpenLastUsedProject())); @@ -352,6 +360,12 @@ void RiuMainWindow::createMenus() fileMenu->addAction(m_saveProjectAction); fileMenu->addAction(m_saveProjectAsAction); + m_recentFilesSeparatorAction = fileMenu->addSeparator(); + for (int i = 0; i < MaxRecentFiles; ++i) + fileMenu->addAction(m_recentFileActions[i]); + + updateRecentFileActions(); + fileMenu->addSeparator(); QMenu* testMenu = fileMenu->addMenu("&Testing"); @@ -763,7 +777,10 @@ void RiuMainWindow::slotImportEclipseCase() if (!fileNames.isEmpty()) { - app->openEclipseCaseFromFile(fileName); + if (app->openEclipseCaseFromFile(fileName)) + { + addRecentFiles(fileName); + } } } } @@ -807,7 +824,10 @@ void RiuMainWindow::slotOpenProject() // Remember the path to next time app->setDefaultFileDialogDirectory("BINARY_GRID", QFileInfo(fileName).absolutePath()); - app->loadProject(fileName); + if (app->loadProject(fileName)) + { + addRecentFiles(fileName); + } } } @@ -819,8 +839,11 @@ void RiuMainWindow::slotOpenLastUsedProject() { RiaApplication* app = RiaApplication::instance(); QString fileName = app->preferences()->lastUsedProjectFileName; - app->loadProject(fileName); - + + if (app->loadProject(fileName)) + { + addRecentFiles(fileName); + } } //-------------------------------------------------------------------------------------------------- @@ -937,6 +960,67 @@ void RiuMainWindow::slotCloseProject() bool ret = app->closeProject(true); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::slotOpenRecentFile() +{ + QAction *action = qobject_cast(sender()); + if (action) + { + QString filename = action->data().toString(); + + if (filename.contains(".rsp", Qt::CaseInsensitive) || filename.contains(".rip", Qt::CaseInsensitive) ) + { + RiaApplication::instance()->loadProject(action->data().toString()); + } + else if ( filename.contains(".egrid", Qt::CaseInsensitive) || filename.contains(".grid", Qt::CaseInsensitive) ) + { + RiaApplication::instance()->openEclipseCaseFromFile(filename); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::updateRecentFileActions() +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + + int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles); + + for (int i = 0; i < numRecentFiles; ++i) { + QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); + m_recentFileActions[i]->setText(text); + m_recentFileActions[i]->setData(files[i]); + m_recentFileActions[i]->setVisible(true); + } + for (int j = numRecentFiles; j < MaxRecentFiles; ++j) + m_recentFileActions[j]->setVisible(false); + + m_recentFilesSeparatorAction->setVisible(numRecentFiles > 0); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::addRecentFiles(const QString& file) +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(file); + files.prepend(file); + while (files.size() > MaxRecentFiles) + files.removeLast(); + + settings.setValue("recentFileList", files); + + updateRecentFileActions(); +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index ae3f922af3..54da53911b 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -111,7 +111,8 @@ class RiuMainWindow : public QMainWindow bool checkForDocumentModifications(); - void updateMRUList(const QString &fileName, bool remove = false); + void updateRecentFileActions(); + void addRecentFiles(const QString& file); QMdiSubWindow* findMdiSubWindow(RiuViewer* viewer); @@ -137,6 +138,13 @@ class RiuMainWindow : public QMainWindow QAction* m_closeProjectAction; QAction* m_exitAction; + // Recent files + enum { MaxRecentFiles = 5 }; + QAction* m_recentFilesSeparatorAction; + QMenu* m_recentFilesMenu; + QAction* m_recentFileActions[MaxRecentFiles]; + + // Edit actions QAction* m_editPreferences; QAction* m_newPropertyView; @@ -203,6 +211,8 @@ private slots: void slotSaveProjectAs(); void slotCloseProject(); + void slotOpenRecentFile(); + void slotRefreshFileActions(); // Edit slots From ad7e3b8eef25f6e2758a178593ecfb87e688284c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:11:43 +0200 Subject: [PATCH 014/346] Cleaned up includes for ProjectDataModel --- .../Application/RiaApplication.cpp | 2 + ApplicationCode/Application/RiaPreferences.h | 3 + .../ModelVisualization/RivFaultPartMgr.cpp | 1 + .../ModelVisualization/RivGridPartMgr.cpp | 1 + .../RivReservoirPipesPartMgr.cpp | 1 + .../RivReservoirViewPartMgr.cpp | 1 + .../RivWellPathCollectionPartMgr.cpp | 20 +----- .../RivWellPathCollectionPartMgr.h | 9 +++ .../ModelVisualization/RivWellPathPartMgr.h | 2 + .../RivWellPipesPartMgr.cpp | 1 + .../Rim3dOverlayInfoConfig.cpp | 17 ++--- .../ProjectDataModel/RimAnalysisModels.cpp | 30 ++------ .../ProjectDataModel/RimAnalysisModels.h | 6 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 50 ++++--------- .../ProjectDataModel/RimCaseCollection.cpp | 14 +--- .../RimCellEdgeResultSlot.cpp | 13 ++-- .../RimCellPropertyFilter.cpp | 10 +-- .../ProjectDataModel/RimCellPropertyFilter.h | 13 ---- .../RimCellPropertyFilterCollection.cpp | 7 -- .../ProjectDataModel/RimCellRangeFilter.cpp | 19 ++--- .../ProjectDataModel/RimCellRangeFilter.h | 10 +-- .../RimCellRangeFilterCollection.cpp | 12 +--- .../ProjectDataModel/RimCommandObject.cpp | 25 ++----- .../ProjectDataModel/RimCommandObject.h | 2 - ApplicationCode/ProjectDataModel/RimFault.h | 5 +- .../ProjectDataModel/RimFaultCollection.cpp | 7 +- .../ProjectDataModel/RimFaultCollection.h | 14 ++-- .../RimIdenticalGridCaseGroup.cpp | 28 +++----- .../RimIdenticalGridCaseGroup.h | 1 - .../ProjectDataModel/RimInputCase.cpp | 31 +++----- .../ProjectDataModel/RimInputProperty.cpp | 5 +- .../RimInputPropertyCollection.cpp | 5 +- .../RimInputPropertyCollection.h | 2 +- .../ProjectDataModel/RimOilField.cpp | 25 +------ .../ProjectDataModel/RimOilField.h | 14 ++-- .../ProjectDataModel/RimProject.cpp | 34 +++------ ApplicationCode/ProjectDataModel/RimProject.h | 4 +- .../RimReservoirCellResultsCacher.cpp | 37 +++------- .../RimReservoirCellResultsCacher.h | 10 +-- .../ProjectDataModel/RimReservoirView.cpp | 70 +++++++------------ .../ProjectDataModel/RimReservoirView.h | 36 +++++----- .../ProjectDataModel/RimResultCase.cpp | 44 ++++-------- .../ProjectDataModel/RimResultCase.h | 4 -- .../ProjectDataModel/RimResultDefinition.cpp | 20 ++---- .../ProjectDataModel/RimResultDefinition.h | 5 +- .../ProjectDataModel/RimResultSlot.cpp | 2 - .../ProjectDataModel/RimResultSlot.h | 3 - .../ProjectDataModel/RimScriptCollection.cpp | 13 ++-- .../ProjectDataModel/RimScriptCollection.h | 3 +- .../ProjectDataModel/RimStatisticsCase.cpp | 34 +++------ .../RimStatisticsCaseCollection.cpp | 16 +---- .../RimStatisticsCaseCollection.h | 6 +- .../RimStatisticsCaseEvaluator.cpp | 16 +---- .../RimStatisticsCaseEvaluator.h | 8 +-- ApplicationCode/ProjectDataModel/RimTools.cpp | 24 +------ ApplicationCode/ProjectDataModel/RimTools.h | 2 +- .../ProjectDataModel/RimUiTreeModelPdm.cpp | 45 +++++------- .../ProjectDataModel/RimUiTreeView.cpp | 2 + ApplicationCode/ProjectDataModel/RimWell.cpp | 15 +--- ApplicationCode/ProjectDataModel/RimWell.h | 8 ++- .../ProjectDataModel/RimWellCollection.cpp | 16 ++--- .../ProjectDataModel/RimWellCollection.h | 7 +- .../ProjectDataModel/RimWellPath.cpp | 33 ++------- .../ProjectDataModel/RimWellPath.h | 5 +- .../RimWellPathCollection.cpp | 34 +++------ .../ProjectDataModel/RimWellPathCollection.h | 12 +++- .../RiaPropertyDataCommands.cpp | 1 + .../UserInterface/RiuMainWindow.cpp | 55 ++++++--------- 68 files changed, 332 insertions(+), 698 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 79b9a501bf..61862f5b8c 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -39,6 +39,7 @@ #include "RimWellPathCollection.h" #include "RimOilField.h" #include "RimAnalysisModels.h" +#include "RimFaultCollection.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -78,6 +79,7 @@ #include "cvfProgramOptions.h" #include "cvfqtUtils.h" +#include "RimCommandObject.h" namespace caf diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 4ee1873d49..bb7d3f3354 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -24,6 +24,9 @@ #include "cafPdmField.h" #include "cafAppEnum.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + class RiaPreferences : public caf::PdmObject { diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index b8de115c23..7da6f4c85d 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -47,6 +47,7 @@ #include "RivGridPartMgr.h" #include "cvfRenderStateDepth.h" #include "RivSourceInfo.h" +#include "RimFaultCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 16a213cbe0..ee795b0004 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,6 +50,7 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" +#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp index 842990aed1..64e58e3b3e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp @@ -20,6 +20,7 @@ #include "RivReservoirPipesPartMgr.h" #include "RimReservoirView.h" +#include "RimWell.h" #include "RimWellCollection.h" #include "RivWellPipesPartMgr.h" #include "RivWellHeadPartMgr.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 3f78c6d111..4dbd4bb183 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -37,6 +37,7 @@ #include "RimCellEdgeResultSlot.h" #include "Rim3dOverlayInfoConfig.h" #include "RimReservoirCellResultsCacher.h" +#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp index ee443be4ee..4e34fcbf45 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp @@ -16,27 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" + +#include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RivWellPathPartMgr.h" -#include "RimWellPathCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index 8e5963d543..e5ac6a5d0e 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -21,11 +21,20 @@ #include "cvfCollection.h" #include "cafPdmPointer.h" +#include "cvfVector3.h" +#include "cvfBoundingBox.h" +#include "cvfTransform.h" class RimWellPathCollection; class RimProject; class RivWellPathPartMgr; +namespace cvf +{ + class ModelBasicList; +} + + class RivWellPathCollectionPartMgr : public cvf::Object { public: diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index b1dc9ed3c8..873c15296e 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -28,6 +28,8 @@ namespace cvf class ModelBasicList; class Transform; class Effect; + class DrawableGeo; + class ScalarMapper; } class RivPipeGeometryGenerator; diff --git a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp index 592da5a8a9..546c9ef627 100644 --- a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp @@ -36,6 +36,7 @@ #include "RimCase.h" #include "RimReservoirView.h" +#include "RimWell.h" #include "RimWellCollection.h" #include "RimReservoirCellResultsCacher.h" diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 347895c6a1..2ffb186033 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -18,20 +18,17 @@ #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirView.h" -#include "RiuViewer.h" -#include "RimCase.h" +#include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RimResultSlot.h" +#include "RimCase.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" - #include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" - +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RigCaseCellResultsData.h" +#include "RiuViewer.h" +#include "RimFaultCollection.h" CAF_PDM_SOURCE_INIT(Rim3dOverlayInfoConfig, "View3dOverlayInfoConfig"); diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp index e0968679fa..5d2bd3c368 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp @@ -16,37 +16,17 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimAnalysisModels.h" -#include "RiaApplication.h" -#include "RimProject.h" -#include "cafAppEnum.h" -#include "RimReservoirView.h" - -#include "RimIdenticalGridCaseGroup.h" #include "RiaApplication.h" - -#include "RigGridManager.h" #include "RigCaseData.h" -#include "RimResultCase.h" -#include "RimWellPathCollection.h" - - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" +#include "RigGridManager.h" +#include "RimCase.h" #include "RimCaseCollection.h" -#include "RimResultSlot.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimProject.h" #include "RimStatisticsCase.h" -#include "RimOilField.h" -#include "RimScriptCollection.h" + CAF_PDM_SOURCE_INIT(RimAnalysisModels, "ResInsightAnalysisModels"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h index b36cd1d28e..6a205d4778 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h @@ -18,7 +18,11 @@ #pragma once -#include "cafPdmDocument.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" + +#include "cvfObject.h" class RimCase; class RigGridManager; diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index e412c1557e..90f1115fc5 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -16,52 +16,26 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimCase.h" -#include -#include -#include -#include - -#include "RifReaderEclipseOutput.h" -#include "RifReaderMockModel.h" - -#include "RimReservoirView.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimCaseCollection.h" +#include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimWellCollection.h" -#include "RimWellPathCollection.h" - -#include "RimScriptCollection.h" - -#include "RigCaseData.h" -#include "RigMainGrid.h" -#include "RigCaseCellResultsData.h" - -#include "cvfAssert.h" - -#include "cafPdmFieldCvfColor.h" - -#include "cafPdmUiPushButtonEditor.h" - -#include -#include "RimProject.h" #include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCaseCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" + #include "cafProgressInfo.h" +#include +#include +#include +#include + + CAF_PDM_SOURCE_INIT(RimCase, "RimReservoir"); //------------------------------------------------------------------------------------------------ diff --git a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp index bf8064a8bb..630684c92c 100644 --- a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp @@ -17,22 +17,10 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCaseCollection.h" -#include "RimCase.h" -#include "RimReservoirView.h" +#include "RimCase.h" #include "RimIdenticalGridCaseGroup.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - -#include "RimReservoirCellResultsCacher.h" -#include "RimResultSlot.h" - -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCaseCollection, "RimCaseCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 93383d0522..51c17c1a5d 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -17,20 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RigCaseCellResultsData.h" #include "RimLegendConfig.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RigCaseCellResultsData.h" + #include "cafPdmUiListEditor.h" +#include "cvfMath.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCellEdgeResultSlot, "CellEdgeResultSlot"); diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index abb2b6d3fc..ecfa62dbe5 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -17,13 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCellPropertyFilter.h" -#include "RimResultDefinition.h" -#include "cvfMath.h" -#include "RimCellPropertyFilterCollection.h" #include "RigCaseCellResultsData.h" -#include "cafPdmUiDoubleSliderEditor.h" +#include "RimCellPropertyFilterCollection.h" #include "RimReservoirCellResultsCacher.h" +#include "RimResultDefinition.h" + +#include "cafPdmUiDoubleSliderEditor.h" +#include "cvfAssert.h" +#include "cvfMath.h" namespace caf diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h index 02c7677a60..71a942b3ee 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h @@ -18,14 +18,7 @@ #pragma once -#include "cafPdmObject.h" -#include "cafPdmField.h" -#include "cafPdmDocument.h" -#include "cafAppEnum.h" - -#include "RimDefines.h" #include "RimCellFilter.h" -//#include "cvfStructGridGeometryGenerator.h" class RimReservoirView; class RimCellPropertyFilterCollection; @@ -34,10 +27,6 @@ class RimResultDefinition; class RigGridBase; class RigCaseCellResultsData; -namespace cvf -{ - //enum CellRangeFilter::CellStateType; -} //================================================================================================== /// @@ -81,5 +70,3 @@ class RimCellPropertyFilter : public RimCellFilter double m_minimumResultValue, m_maximumResultValue; }; - - diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp index b12923b5c5..9c4b2bcfb3 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp @@ -22,13 +22,6 @@ #include "RimResultDefinition.h" #include "RimResultSlot.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimCellRangeFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCellEdgeResultSlot.h" - CAF_PDM_SOURCE_INIT(RimCellPropertyFilterCollection, "CellPropertyFilters"); diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp index 2bb0fc64cf..4bc3f601d2 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp @@ -16,26 +16,19 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" -#include "RimReservoirView.h" + +#include "RigActiveCellInfo.h" #include "RigCaseData.h" +#include "RigGridBase.h" +#include "RigMainGrid.h" #include "RimCase.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "cafPdmUiSliderEditor.h" - +#include "cvfAssert.h" CAF_PDM_SOURCE_INIT(RimCellRangeFilter, "CellRangeFilter"); diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h index acb2372a87..fe4bbbc10e 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h @@ -18,11 +18,11 @@ #pragma once -#include "cafPdmField.h" -#include "cafPdmObject.h" -#include "cafPdmPointer.h" #include "RimCellFilter.h" +class RigGridBase; +class RigMainGrid; +class RimCellRangeFilterCollection; class RimReservoirView; namespace cvf @@ -30,10 +30,6 @@ namespace cvf class CellRangeFilter; } -class RimCellRangeFilterCollection; -class RigMainGrid; -class RigGridBase; - //================================================================================================== /// /// diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp index eb9bc8bbba..7d1a6ec91f 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp @@ -16,20 +16,12 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimCellRangeFilterCollection.h" + #include "RimCase.h" +#include "RigGridBase.h" #include "RimReservoirView.h" #include "RigCaseData.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCellRangeFilterCollection, "CellRangeFilterCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index 858f936def..554d8d926b 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -17,34 +17,17 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCommandObject.h" + #include "RiaApplication.h" #include "RimCalcScript.h" #include "RimProject.h" +#include "RimStatisticsCase.h" -#include "cafPdmUiTextEditor.h" -#include "cafPdmUiPushButtonEditor.h" #include "cafPdmDocument.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTextEditor.h" #include -#include "RimStatisticsCase.h" - -// Included due to template use in pdm fields -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimScriptCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimAnalysisModels.h" -#include "RimWellPathCollection.h" -#include "RimCaseCollection.h" - - CAF_PDM_SOURCE_INIT(RimCommandObject, "RimCommandObject"); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.h b/ApplicationCode/ProjectDataModel/RimCommandObject.h index 4123802cda..25e40878fb 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.h +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.h @@ -22,9 +22,7 @@ #include "cvfObject.h" #include "cafPdmField.h" #include "cafPdmObject.h" -#include "cafPdmDocument.h" -#include //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimFault.h b/ApplicationCode/ProjectDataModel/RimFault.h index b85c18d7da..22bac08bf6 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.h +++ b/ApplicationCode/ProjectDataModel/RimFault.h @@ -23,8 +23,9 @@ #include "cafPdmPointer.h" #include "cvfBase.h" -#include "cvfColor3.h" -#include "cafPdmFieldCvfColor.h" + +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" class RigFault; diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 2de8ac55df..e634f26644 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -18,10 +18,6 @@ #include "RimFaultCollection.h" -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - #include "RiaApplication.h" #include "RiaPreferences.h" #include "RigCaseData.h" @@ -30,6 +26,9 @@ #include "RiuMainWindow.h" #include "RivColorTableArray.h" +#include "cafAppEnum.h" +#include "cafPdmFieldCvfColor.h" +#include "cafPdmFieldCvfMat4d.h" namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 0d2cb37b66..aacb41cd51 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -18,19 +18,21 @@ #pragma once +#include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmPointer.h" -#include "cafAppEnum.h" -#include - #include "cvfBase.h" -#include "cvfColor3.h" -class RimFault; +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" -class RimReservoirView; +#include "RimReservoirCellResultsCacher.h" + +#include +class RimFault; +class RimReservoirView; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 0b1708f315..86a64b0b19 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -18,33 +18,21 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimIdenticalGridCaseGroup.h" -#include "RimCaseCollection.h" +#include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigGridManager.h" #include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RigCaseData.h" -#include "RigCaseCellResultsData.h" - +#include "RimResultCase.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" #include "RimStatisticsCase.h" -#include "RimResultCase.h" #include "cafProgressInfo.h" -#include "RigActiveCellInfo.h" -#include "RigActiveCellInfo.h" - -#include "RigGridManager.h" -#include "RimReservoirCellResultsCacher.h" - - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" - CAF_PDM_SOURCE_INIT(RimIdenticalGridCaseGroup, "RimIdenticalGridCaseGroup"); diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h index e3da03cc8e..31c66c8211 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h @@ -25,7 +25,6 @@ #include "RifReaderInterface.h" -//#include "RimStatisticsCaseCollection.h" class RimCaseCollection; class RimStatisticsCase; diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index e9ab1a607f..b1a77bf364 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -16,34 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimInputCase.h" -#include "RimInputPropertyCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include -#include "RimReservoirView.h" +#include "RiaPreferences.h" +#include "RifEclipseInputFileTools.h" #include "RifReaderEclipseInput.h" -#include "RigCaseData.h" +#include "RifReaderInterface.h" +#include "RifReaderMockModel.h" #include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimDefines.h" +#include "RimInputProperty.h" +#include "RimInputPropertyCollection.h" +#include "RimReservoirCellResultsCacher.h" -#include "RifReaderMockModel.h" -#include "RifEclipseInputFileTools.h" #include "cafProgressInfo.h" -#include "RiaApplication.h" -#include "RiaPreferences.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - -#include "RimCellEdgeResultSlot.h" -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" +#include CAF_PDM_SOURCE_INIT(RimInputCase, "RimInputReservoir"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp index 95936e5f54..3aed9d899f 100644 --- a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp @@ -16,13 +16,10 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimInputProperty.h" -#include "cvfAssert.h" - #include "cafPdmUiLineEditor.h" +#include "cvfAssert.h" #include diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp index 5798253f13..8250191135 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp @@ -16,10 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimInputPropertyCollection.h" +#include "RimInputProperty.h" + +#include CAF_PDM_SOURCE_INIT(RimInputPropertyCollection, "RimInputPropertyCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h index 2e865fda76..302e97a50b 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h @@ -23,7 +23,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimInputProperty.h" +class RimInputProperty; //================================================================================================== diff --git a/ApplicationCode/ProjectDataModel/RimOilField.cpp b/ApplicationCode/ProjectDataModel/RimOilField.cpp index 8f078071de..13855a3962 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.cpp +++ b/ApplicationCode/ProjectDataModel/RimOilField.cpp @@ -16,33 +16,10 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimOilField.h" -#include "cafAppEnum.h" -#include "RimReservoirView.h" - -#include "RimIdenticalGridCaseGroup.h" - -#include "RiaApplication.h" -#include "RigGridManager.h" -#include "RigCaseData.h" -#include "RimResultCase.h" -#include "RimWellPathCollection.h" #include "RimAnalysisModels.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimStatisticsCase.h" +#include "RimWellPathCollection.h" CAF_PDM_SOURCE_INIT(RimOilField, "ResInsightOilField"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimOilField.h b/ApplicationCode/ProjectDataModel/RimOilField.h index 9b296aad83..925c20b378 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.h +++ b/ApplicationCode/ProjectDataModel/RimOilField.h @@ -18,13 +18,10 @@ #pragma once -#include "cafPdmDocument.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" -class RimCase; -class RigGridManager; -class RimIdenticalGridCaseGroup; -class RigMainGrid; -class RigCaseData; class RimWellPathCollection; class RimAnalysisModels; @@ -40,7 +37,6 @@ class RimOilField : public caf::PdmObject RimOilField(void); virtual ~RimOilField(void); - caf::PdmField analysisModels; - caf::PdmField wellPathCollection; - + caf::PdmField analysisModels; + caf::PdmField wellPathCollection; }; diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 357a18bfdc..03bd43fcfe 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -16,38 +16,22 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimProject.h" -#include "cafAppEnum.h" - -#include "RimOilField.h" -#include "RimAnalysisModels.h" - -#include "RimReservoirView.h" -#include "RimScriptCollection.h" -#include "RimIdenticalGridCaseGroup.h" #include "RiaApplication.h" #include "RiaVersionInfo.h" - -#include "RigGridManager.h" #include "RigCaseData.h" -#include "RimResultCase.h" +#include "RimAnalysisModels.h" +#include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimOilField.h" +#include "RimReservoirView.h" +#include "RimScriptCollection.h" #include "RimWellPathCollection.h" +#include "RimWellPathImport.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimStatisticsCase.h" +#include CAF_PDM_SOURCE_INIT(RimProject, "ResInsightProject"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 28c6b5f9fa..3226a0ee1e 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -19,8 +19,6 @@ #pragma once #include "cafPdmDocument.h" -#include "RimWellPathImport.h" -#include "RimCommandObject.h" class RimOilField; class RimCase; @@ -29,6 +27,8 @@ class RimScriptCollection; class RimIdenticalGridCaseGroup; class RigMainGrid; class RigCaseData; +class RimWellPathImport; +class RimCommandObject; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp index 9b3357a8e1..25bbd9f503 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp @@ -16,39 +16,20 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" -#include -#include -#include -#include -#include - #include "RimReservoirCellResultsCacher.h" + #include "RigCaseCellResultsData.h" -#include "RiaApplication.h" #include "RigMainGrid.h" -#include "RigCell.h" -#include "cafProgressInfo.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimCaseCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" #include "RimTools.h" +#include "cafProgressInfo.h" + +#include +#include +#include +#include +#include + CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorage, "ReservoirCellResultStorage"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h index f6f7a567f3..7208bcd83e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h @@ -18,15 +18,17 @@ #pragma once -#include -#include "cvfBase.h" -#include "cvfObject.h" +#include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" -#include "cafAppEnum.h" +#include "cvfBase.h" +#include "cvfObject.h" + #include "RimDefines.h" +#include + class RimReservoirCellResultsStorageEntryInfo; class RigCaseCellResultsData; class RifReaderInterface; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 3438706133..ddbbf10f36 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -16,66 +16,44 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimReservoirView.h" -#include "RiuViewer.h" -#include "cvfViewport.h" -#include "cvfModelBasicList.h" -#include "cvfPart.h" -#include "cvfDrawable.h" -#include "cvfScene.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include - - -#include "RimProject.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCaseCollection.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" #include "RimOilField.h" -#include "RimAnalysisModels.h" +#include "RimProject.h" +#include "RimResultSlot.h" #include "RimTernaryLegendConfig.h" - +#include "RimWell.h" +#include "RimWellCollection.h" +#include "RimWellPathCollection.h" #include "RiuMainWindow.h" -#include "RigGridBase.h" -#include "RigCaseData.h" -#include "RiaApplication.h" -#include "RiaPreferences.h" +#include "RiuViewer.h" +#include "RivReservoirPipesPartMgr.h" +#include "RivWellPathCollectionPartMgr.h" -#include "cafEffectGenerator.h" +#include "cafCadNavigation.h" +#include "cafCeetronPlusNavigation.h" #include "cafFrameAnimationControl.h" -#include "cvfStructGridGeometryGenerator.h" -#include "RigCaseCellResultsData.h" -#include "RivCellEdgeEffectGenerator.h" +#include "cvfDrawable.h" +#include "cvfModelBasicList.h" +#include "cvfOverlayScalarMapperLegend.h" +#include "cvfPart.h" +#include "cvfScene.h" +#include "cvfViewport.h" #include "cvfqtUtils.h" -#include "RivReservoirViewPartMgr.h" -#include "RivReservoirPipesPartMgr.h" -#include "cafCadNavigation.h" -#include "cafCeetronNavigation.h" -#include "RimCase.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RigGridScalarDataAccess.h" -#include "RimReservoirCellResultsCacher.h" -#include "RivWellPathCollectionPartMgr.h" -#include "cvfOverlayScalarMapperLegend.h" +#include -#include -#include "cafCeetronPlusNavigation.h" -#include "RimFaultCollection.h" -#include "RivTernarySaturationOverlayItem.h" namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index a45a6c2e1d..95ae186b5a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -17,40 +17,38 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once -#include "cafPdmObject.h" -#include "cafPdmField.h" + #include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cvfArray.h" #include "cvfBase.h" #include "cvfObject.h" +// Includes to make Pdm work for cvf::Color and cvf:Mat +#include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" - -#include -#include -#include "RimFaultCollection.h" +#include "RivReservoirViewPartMgr.h" +class RigActiveCellInfo; +class RigGridBase; +class RigGridCellFaceVisibilityFilter; +class Rim3dOverlayInfoConfig; class RimCase; -class RimResultSlot; class RimCellEdgeResultSlot; -class RimCellRangeFilter; -class RimCellRangeFilterCollection; class RimCellPropertyFilter; class RimCellPropertyFilterCollection; -class Rim3dOverlayInfoConfig; +class RimCellRangeFilter; +class RimCellRangeFilterCollection; +class RimFaultCollection; +class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; +class RimResultSlot; class RimWellCollection; -class RigActiveCellInfo; - -#include "RivReservoirViewPartMgr.h" -class RivReservoirPipesPartMgr; - class RiuViewer; -class RigGridBase; -class RigGridCellFaceVisibilityFilter; -class RimReservoirCellResultsStorage; +class RivReservoirPipesPartMgr; namespace cvf { diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index d0d72587fa..626f4cf15a 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -16,41 +16,25 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "cafProgressInfo.h" -#include "cafPdmSettings.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmUiPropertyDialog.h" - #include "RimResultCase.h" -#include "RigCaseData.h" + +#include "RiaPreferences.h" +#include "RifEclipseOutputFileTools.h" #include "RifReaderEclipseOutput.h" -#include "RigCaseCellResultsData.h" -#include "RimReservoirView.h" #include "RifReaderMockModel.h" -#include "RifReaderEclipseInput.h" - +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimMockModelSettings.h" #include "RimProject.h" -#include "RifEclipseOutputFileTools.h" -#include "RiaApplication.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCaseCollection.h" #include "RimReservoirCellResultsCacher.h" -#include "RimWellPathCollection.h" - -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include "RiaPreferences.h" -#include "RimMockModelSettings.h" + +#include "cafPdmSettings.h" +#include "cafPdmUiPropertyDialog.h" +#include "cafProgressInfo.h" + +#include +#include +#include CAF_PDM_SOURCE_INIT(RimResultCase, "EclipseCase"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.h b/ApplicationCode/ProjectDataModel/RimResultCase.h index 0463cdf508..9d768fc36b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.h +++ b/ApplicationCode/ProjectDataModel/RimResultCase.h @@ -18,10 +18,6 @@ #pragma once -#include "cvfBase.h" -#include "cvfObject.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" #include "RimCase.h" class RifReaderInterface; diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 110036ffb8..4e5873dda3 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -16,27 +16,15 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimResultDefinition.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimReservoirView.h" -#include "RimCase.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigMainGrid.h" -#include "cafPdmUiListEditor.h" - +#include "RimCase.h" +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "cafPdmUiListEditor.h" CAF_PDM_SOURCE_INIT(RimResultDefinition, "ResultDefinition"); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index 3e7e463f7d..f399262ee2 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -18,10 +18,11 @@ #pragma once -#include "cafPdmObject.h" +#include "RimDefines.h" + #include "cafAppEnum.h" #include "cafPdmField.h" -#include "RimDefines.h" +#include "cafPdmObject.h" #include "cafPdmPointer.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index 38108eaf5f..dc7af09867 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -16,8 +16,6 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimResultSlot.h" #include "RimReservoirView.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index afa92bb3a3..390b3cc053 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -18,9 +18,6 @@ #pragma once -#include "cafAppEnum.h" -#include "cafPdmObject.h" - #include "RimDefines.h" #include "RimLegendConfig.h" #include "RimResultDefinition.h" diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 2e597e678e..17e3053bd6 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -16,15 +16,16 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - - #include "RimScriptCollection.h" -#include "cafPdmField.h" -#include "cafUtils.h" -#include "RiuMainWindow.h" + +#include "RimCalcScript.h" #include "RimUiTreeModelPdm.h" +#include "RiuMainWindow.h" + #include "cafPdmUiFilePathEditor.h" +#include "cafUtils.h" + +#include CAF_PDM_SOURCE_INIT(RimScriptCollection, "ScriptLocation"); diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.h b/ApplicationCode/ProjectDataModel/RimScriptCollection.h index 0c030e9be6..88c4bcffa3 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.h +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.h @@ -20,7 +20,8 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimCalcScript.h" + +class RimCalcScript; namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index e942b18b0d..dba119e9b7 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -16,35 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimStatisticsCase.h" -#include "RimReservoirView.h" -#include "cafPdmUiOrdering.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RigCaseData.h" + #include "RigCaseCellResultsData.h" -#include "RimStatisticsCaseEvaluator.h" -#include "RigMainGrid.h" -#include "cafPdmUiTextEditor.h" -#include "cafPdmUiLineEditor.h" -#include "cafPdmUiPushButtonEditor.h" -#include "RiuMainWindow.h" -#include "RimUiTreeModelPdm.h" -#include "cafProgressInfo.h" +#include "RigCaseData.h" #include "RimCaseCollection.h" - - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" +#include "RimStatisticsCaseEvaluator.h" +#include "RimUiTreeModelPdm.h" #include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "RiuMainWindow.h" -#include "RimReservoirCellResultsCacher.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTextEditor.h" +#include "cafProgressInfo.h" namespace caf { template<> diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp index 40daa70a63..a5fb4e94a6 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp @@ -16,23 +16,9 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "RimReservoirView.h" - #include "RimStatisticsCaseCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimCaseCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimIdenticalGridCaseGroup.h" CAF_PDM_SOURCE_INIT(RimStatisticsCaseCollection, "RimStatisticalCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h index e7c0059363..699c28a5c6 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h @@ -23,8 +23,8 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimStatisticsCase.h" - +class RimStatisticsCase; +class RimIdenticalGridCaseGroup; //================================================================================================== @@ -44,6 +44,4 @@ class RimStatisticsCaseCollection : public caf::PdmObject RimIdenticalGridCaseGroup* parentCaseGroup(); -private: - }; diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 4d8a499d8c..6d49322ed4 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -15,29 +15,17 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimStatisticsCaseEvaluator.h" + #include "RigCaseCellResultsData.h" -#include "RimReservoirView.h" -#include "RimCase.h" #include "RigCaseData.h" #include "RigStatisticsMath.h" #include "RimReservoirCellResultsCacher.h" +#include "cafProgressInfo.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" - -//#include "RigCaseData.h" #include -#include "cafProgressInfo.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 7c825c8b8d..906ad17c7d 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -18,15 +18,13 @@ #pragma once -#include "cvfBase.h" -#include "cvfObject.h" -#include "cvfCollection.h" +#include "RimDefines.h" +#include "RimStatisticsCase.h" + #include #include #include -#include "RimDefines.h" -#include "RimStatisticsCase.h" class RimCase; class RigCaseData; diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 3ab3439da0..453bc259ba 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -16,30 +16,12 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimTools.h" -#include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RivWellPathPartMgr.h" -#include "RimWellPathCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" #include "RiaApplication.h" +#include "RimProject.h" + +#include //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimTools.h b/ApplicationCode/ProjectDataModel/RimTools.h index 0d301ff002..e39f961043 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.h +++ b/ApplicationCode/ProjectDataModel/RimTools.h @@ -18,7 +18,7 @@ #pragma once -class RimProject; +#include class RimTools { diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index 68ec961b7c..dc340cb014 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -16,47 +16,34 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimUiTreeModelPdm.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" - -#include "cafPdmObject.h" -#include "RimCellPropertyFilter.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimReservoirView.h" -#include "RiuViewer.h" -#include "RimCalcScript.h" #include "RiaApplication.h" -#include "RiuMainWindow.h" -#include "RimInputProperty.h" -#include "RimInputPropertyCollection.h" -#include "cafPdmField.h" -#include "RimInputCase.h" -#include "RimStatisticsCase.h" -#include "RimResultCase.h" #include "RigGridManager.h" +#include "RimAnalysisModels.h" #include "RimCase.h" -#include "RigCaseData.h" -#include "RimMimeData.h" #include "RimCaseCollection.h" +#include "RimCellPropertyFilterCollection.h" +#include "RimCellRangeFilterCollection.h" #include "RimIdenticalGridCaseGroup.h" +#include "RimInputCase.h" +#include "RimInputProperty.h" +#include "RimInputPropertyCollection.h" +#include "RimMimeData.h" +#include "RimOilField.h" #include "RimProject.h" +#include "RimReservoirView.h" +#include "RimResultCase.h" #include "RimScriptCollection.h" +#include "RimStatisticsCase.h" +#include "RimUiTreeView.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" #include "RimWellPathCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include "RimUiTreeView.h" +#include "cvfAssert.h" + +#include +#include //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 60bde2559f..2887bbd1c4 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -64,6 +64,8 @@ #include "RimProject.h" #include "RimOilField.h" #include "RimAnalysisModels.h" +#include "RimInputProperty.h" +#include "RigSingleWellResultsData.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWell.cpp b/ApplicationCode/ProjectDataModel/RimWell.cpp index 76f740cbe2..9a3a221ecc 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.cpp +++ b/ApplicationCode/ProjectDataModel/RimWell.cpp @@ -16,22 +16,13 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimWell.h" - -#include "cafAppEnum.h" -#include "cafPdmField.h" -#include "RivReservoirViewPartMgr.h" +#include "RigSingleWellResultsData.h" #include "RimReservoirView.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" + +#include "cvfMath.h" CAF_PDM_SOURCE_INIT(RimWell, "Well"); diff --git a/ApplicationCode/ProjectDataModel/RimWell.h b/ApplicationCode/ProjectDataModel/RimWell.h index 32e724e536..1e591f85c7 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.h +++ b/ApplicationCode/ProjectDataModel/RimWell.h @@ -22,11 +22,15 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "RigSingleWellResultsData.h" +#include "cvfObject.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +class RigSingleWellResultsData; class RimReservoirView; + //================================================================================================== /// /// diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp index 0c9783a885..710e1948a3 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp @@ -18,19 +18,13 @@ #include "RimWellCollection.h" -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirView.h" - -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" - -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellEdgeResultSlot.h" #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigSingleWellResultsData.h" +#include "RimReservoirView.h" +#include "RimWell.h" +#include "RivReservoirViewPartMgr.h" + namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.h b/ApplicationCode/ProjectDataModel/RimWellCollection.h index 515574bf41..8ca7232006 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.h @@ -22,11 +22,14 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include -#include "RimWell.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +#include class RimReservoirView; +class RimWell; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 18e1b7bb2c..29ed5040b9 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -16,37 +16,16 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - - -#include "cafAppEnum.h" -#include "cafPdmField.h" -#include "RiaApplication.h" - #include "RimWellPath.h" -#include "RimWellPathCollection.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RivWellPathPartMgr.h" + #include "RifJsonEncodeDecode.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" - -#include -#include +#include "RimProject.h" #include "RimTools.h" +#include "RimWellPathCollection.h" +#include "RivWellPathPartMgr.h" +#include +#include CAF_PDM_SOURCE_INIT(RimWellPath, "WellPath"); diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 4d25a145b9..068f84d4f8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -22,7 +22,10 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" + +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + #include "RigWellPath.h" class RimProject; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index 5483feee76..c76a5f0df3 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -16,34 +16,20 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafProgressInfo.h" - #include "RimWellPathCollection.h" -#include "RimWellPath.h" -#include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RivWellPathCollectionPartMgr.h" + +#include "cafProgressInfo.h" + +#include +#include + +#include namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h index b734bd5f97..7d30e10fca 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h @@ -22,12 +22,20 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include -#include "RimWellPath.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +#include "cvfObject.h" + +#include class RivWellPathCollectionPartMgr; class RimWellPathAsciiFileReader; +class RimWellPath; +class RimProject; +class RigWellPath; + //================================================================================================== /// diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index fa5fc419fd..043e18c5eb 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -43,6 +43,7 @@ #include "RiaApplication.h" #include "RiaPreferences.h" #include "RiaSocketDataTransfer.h" +#include "RimInputProperty.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 7a2d8f163d..18f509d09c 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -19,51 +19,42 @@ #include "RiaStdInclude.h" #include "RiuMainWindow.h" -#include "RiaApplication.h" -#include "RimProject.h" +#include "RiaApplication.h" +#include "RiaBaseDefs.h" +#include "RiaPreferences.h" +#include "RiaRegressionTest.h" +#include "RigCaseCellResultsData.h" #include "RimAnalysisModels.h" +#include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimCellPropertyFilterCollection.h" +#include "RimCommandObject.h" +#include "RimFaultCollection.h" #include "RimOilField.h" +#include "RimProject.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RimUiTreeView.h" -#include "RimCase.h" #include "RimResultSlot.h" -#include "RimCellPropertyFilterCollection.h" +#include "RimTools.h" +#include "RimUiTreeModelPdm.h" +#include "RimUiTreeView.h" #include "RimWellCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" #include "RimWellPathCollection.h" - -#include "RimUiTreeModelPdm.h" - -#include "RiaBaseDefs.h" -#include "RiuViewer.h" -#include "RiuResultInfoPanel.h" -#include "RiuProcessMonitor.h" +#include "RimWellPathImport.h" #include "RiuMultiCaseImportDialog.h" +#include "RiuProcessMonitor.h" +#include "RiuResultInfoPanel.h" +#include "RiuViewer.h" +#include "RiuWellImportWizard.h" -#include "RiaPreferences.h" - -#include "RigCaseCellResultsData.h" - -#include "cafAnimationToolBar.h" -#include "cafPdmUiPropertyView.h" #include "cafAboutDialog.h" -#include "cvfTimer.h" - +#include "cafAnimationToolBar.h" #include "cafPdmFieldCvfMat4d.h" - -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RiuWellImportWizard.h" -#include "RimCalcScript.h" -#include "RimTools.h" -#include "RiaRegressionTest.h" #include "cafPdmUiPropertyDialog.h" +#include "cafPdmUiPropertyView.h" +#include "cvfTimer.h" //================================================================================================== From cbf86a438704aa64a2580f65d7aaac804f4912b5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:26:26 +0200 Subject: [PATCH 015/346] Linux fix: Added missing include --- ApplicationCode/ProjectDataModel/RimCommandObject.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.h b/ApplicationCode/ProjectDataModel/RimCommandObject.h index 25e40878fb..81417ac7d5 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.h +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.h @@ -22,6 +22,7 @@ #include "cvfObject.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmDocument.h" //-------------------------------------------------------------------------------------------------- From a40b9554e5b82b94947e510495ed781002962d4f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:39:49 +0200 Subject: [PATCH 016/346] Linux fix: Added missing include --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ddbbf10f36..47f8977158 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -54,6 +54,8 @@ #include +#include + namespace caf { From 07139d3675ed99fb3a161a7f4e8d51ebc9bdf34a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 02:01:02 -0700 Subject: [PATCH 017/346] Linux fixes: Added missing includes --- .../ModelVisualization/RivWellPathCollectionPartMgr.h | 4 +++- ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp | 1 + ApplicationCode/ReservoirDataModel/RigMainGrid.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index e5ac6a5d0e..88b6dd86ca 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -18,13 +18,15 @@ #pragma once - +#include "cvfBase.h" #include "cvfCollection.h" #include "cafPdmPointer.h" #include "cvfVector3.h" #include "cvfBoundingBox.h" #include "cvfTransform.h" +#include "cafPdmPointer.h" + class RimWellPathCollection; class RimProject; class RivWellPathPartMgr; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index c76a5f0df3..edc4c74fcf 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -30,6 +30,7 @@ #include #include +#include namespace caf { diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 10d6ae9aaf..db11222984 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -296,7 +296,7 @@ void RigMainGrid::calculateFaults() // Add as fault face only if the grid index is less than the neighbors - if (gcIdx < neighborGlobalCellIdx) + if (static_cast(gcIdx) < neighborGlobalCellIdx) { { RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborGlobalCellIdx); From 0c8a69a445e36453c1fca9623ee84dd6b9d77ad2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 14:03:17 +0200 Subject: [PATCH 018/346] Renamed file to match class name for RimReservoirCellResultStorage --- ApplicationCode/Application/RiaApplication.cpp | 2 +- ApplicationCode/Application/RiaProjectModifier.cpp | 2 +- .../ModelVisualization/RivCellEdgeEffectGenerator.cpp | 2 +- ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivGridPartMgr.cpp | 2 +- .../ModelVisualization/RivReservoirViewPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp | 2 +- ApplicationCode/ProjectDataModel/CMakeLists_files.cmake | 4 ++-- ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp | 2 +- ApplicationCode/ProjectDataModel/RimFaultCollection.h | 2 +- .../ProjectDataModel/RimIdenticalGridCaseGroup.cpp | 2 +- ApplicationCode/ProjectDataModel/RimInputCase.cpp | 2 +- ...llResultsCacher.cpp => RimReservoirCellResultsStorage.cpp} | 2 +- ...irCellResultsCacher.h => RimReservoirCellResultsStorage.h} | 0 ApplicationCode/ProjectDataModel/RimResultCase.cpp | 2 +- ApplicationCode/ProjectDataModel/RimResultDefinition.cpp | 2 +- ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp | 2 +- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 2 +- ApplicationCode/ProjectDataModel/RimUiTreeView.cpp | 2 +- ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaGeometryCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaSocketServer.cpp | 2 +- ApplicationCode/SocketInterface/RiaSocketTools.cpp | 2 +- ApplicationCode/SocketInterface/RiaWellDataCommands.cpp | 2 +- ApplicationCode/UserInterface/RiuMainWindow.cpp | 2 +- ApplicationCode/UserInterface/RiuViewer.cpp | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) rename ApplicationCode/ProjectDataModel/{RimReservoirCellResultsCacher.cpp => RimReservoirCellResultsStorage.cpp} (99%) rename ApplicationCode/ProjectDataModel/{RimReservoirCellResultsCacher.h => RimReservoirCellResultsStorage.h} (100%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 61862f5b8c..472a2b9a23 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -68,7 +68,7 @@ #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" diff --git a/ApplicationCode/Application/RiaProjectModifier.cpp b/ApplicationCode/Application/RiaProjectModifier.cpp index af5a1d57e2..0840d24be2 100644 --- a/ApplicationCode/Application/RiaProjectModifier.cpp +++ b/ApplicationCode/Application/RiaProjectModifier.cpp @@ -32,7 +32,7 @@ #include "RimScriptCollection.h" #include "RimCellPropertyFilterCollection.h" #include "RimCellPropertyFilter.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index a195179b51..8c1b6ed601 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -55,7 +55,7 @@ #include "RigCaseData.h" #include "RigActiveCellInfo.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafPdmFieldCvfMat4d.h" #include "cafPdmFieldCvfColor.h" diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 7da6f4c85d..731faf4dae 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -39,7 +39,7 @@ #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cvfDrawableText.h" #include "cvfqtUtils.h" #include "cvfPrimitiveSetIndexedUInt.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ee795b0004..d8edaca5b4 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -43,7 +43,7 @@ #include "RigCaseData.h" #include "RimCase.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimTernaryLegendConfig.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 4dbd4bb183..fc1fcddc26 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -36,7 +36,7 @@ #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp index 3878329c7c..cbd0d78d8d 100644 --- a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp @@ -41,7 +41,7 @@ #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimLegendConfig.h" diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 1ba6b3a2a1..f8b5542ab3 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -23,7 +23,7 @@ #include "RimCase.h" #include "RimProject.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimIdenticalGridCaseGroup.h" #include "RimScriptCollection.h" #include "RimCaseCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp index 546c9ef627..8c2eae1287 100644 --- a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp @@ -38,7 +38,7 @@ #include "RimReservoirView.h" #include "RimWell.h" #include "RimWellCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 1b265e3dd2..2abc7eacba 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -39,7 +39,7 @@ ${CEE_CURRENT_LIST_DIR}RimBinaryExportSettings.h ${CEE_CURRENT_LIST_DIR}Rim3dOverlayInfoConfig.h ${CEE_CURRENT_LIST_DIR}RimUiTreeModelPdm.h ${CEE_CURRENT_LIST_DIR}RimUiTreeView.h -${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsCacher.h +${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsStorage.h ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.h ${CEE_CURRENT_LIST_DIR}RimMimeData.h ${CEE_CURRENT_LIST_DIR}RimCommandObject.h @@ -85,7 +85,7 @@ ${CEE_CURRENT_LIST_DIR}RimBinaryExportSettings.cpp ${CEE_CURRENT_LIST_DIR}Rim3dOverlayInfoConfig.cpp ${CEE_CURRENT_LIST_DIR}RimUiTreeModelPdm.cpp ${CEE_CURRENT_LIST_DIR}RimUiTreeView.cpp -${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsCacher.cpp +${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsStorage.cpp ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.cpp ${CEE_CURRENT_LIST_DIR}RimMimeData.cpp ${CEE_CURRENT_LIST_DIR}RimCommandObject.cpp diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 2ffb186033..f08a803814 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -23,7 +23,7 @@ #include "RimCase.h" #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 90f1115fc5..c386fed410 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -24,7 +24,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 51c17c1a5d..48cbe7ffc2 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -20,7 +20,7 @@ #include "RigCaseCellResultsData.h" #include "RimLegendConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "cafPdmUiListEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index ecfa62dbe5..7d73bb92a8 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -20,7 +20,7 @@ #include "RigCaseCellResultsData.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultDefinition.h" #include "cafPdmUiDoubleSliderEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index aacb41cd51..095a65f96b 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -27,7 +27,7 @@ // Include to make Pdm work for cvf::Color #include "cafPdmFieldCvfColor.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 86a64b0b19..442dd7886f 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -26,7 +26,7 @@ #include "RimCase.h" #include "RimCaseCollection.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultCase.h" #include "RimResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index b1a77bf364..adc91355bf 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -28,7 +28,7 @@ #include "RimDefines.h" #include "RimInputProperty.h" #include "RimInputPropertyCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp similarity index 99% rename from ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp rename to ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 25bbd9f503..c46fe8b347 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseCellResultsData.h" #include "RigMainGrid.h" diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h similarity index 100% rename from ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h rename to ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index 626f4cf15a..8d1041fa63 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -26,7 +26,7 @@ #include "RigCaseData.h" #include "RimMockModelSettings.h" #include "RimProject.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafPdmSettings.h" #include "cafPdmUiPropertyDialog.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 4e5873dda3..7d16b522e6 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -21,7 +21,7 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimCase.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "cafPdmUiListEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index dba119e9b7..51e8d45859 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -22,7 +22,7 @@ #include "RigCaseData.h" #include "RimCaseCollection.h" #include "RimIdenticalGridCaseGroup.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimStatisticsCaseEvaluator.h" diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 6d49322ed4..ecb06dd92f 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -21,7 +21,7 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigStatisticsMath.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 2887bbd1c4..0b7331ce8a 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -59,7 +59,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimWellCollection.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "Rim3dOverlayInfoConfig.h" #include "RimProject.h" #include "RimOilField.h" diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index e81b9db3ea..a10762e2a6 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -30,7 +30,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index c76bc690ae..a682b5b3cb 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -27,7 +27,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp index 660effb8b5..35c221d4fd 100644 --- a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp @@ -27,7 +27,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 043e18c5eb..85d154a2a4 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -26,7 +26,7 @@ #include "RigCaseData.h" #include "RigCaseCellResultsData.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.cpp b/ApplicationCode/SocketInterface/RiaSocketServer.cpp index 1258030bcf..f27c0679b0 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketServer.cpp @@ -41,7 +41,7 @@ #include "RimScriptCollection.h" #include "RimCaseCollection.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseData.h" #include "RigCaseCellResultsData.h" diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.cpp b/ApplicationCode/SocketInterface/RiaSocketTools.cpp index 967c0b43b4..c275994254 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketTools.cpp @@ -34,7 +34,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp index 4c9d935206..83fc17b77e 100644 --- a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp @@ -25,7 +25,7 @@ #include "RigCaseData.h" #include "RigCaseCellResultsData.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 18f509d09c..e8f7ca5c10 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -33,7 +33,7 @@ #include "RimFaultCollection.h" #include "RimOilField.h" #include "RimProject.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimTools.h" diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index e58a7bb8a7..71489243e2 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -35,7 +35,7 @@ #include "RimUiTreeModelPdm.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseData.h" From aa228b90b777e2720df5a60fcfae980d87507c57 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 07:27:00 +0200 Subject: [PATCH 019/346] Rename and simplified control of fault visibility --- .../RivReservoirFaultsPartMgr.cpp | 7 ++++- .../ProjectDataModel/RimReservoirView.cpp | 30 ++++++------------- .../ProjectDataModel/RimReservoirView.h | 2 +- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index edf8642a9c..ff01f2bd59 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -101,7 +101,12 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) CVF_ASSERT(rivFaultPart.notNull()); // Parts that is overridden by the grid settings - bool forceDisplayOfFault = isShowingGrid; + bool forceDisplayOfFault = false; + if (!m_faultCollection->showFaultsOutsideFilters()) + { + forceDisplayOfFault = isShowingGrid; + } + if (m_forceVisibility) { forceDisplayOfFault = true; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 47f8977158..73ee88346a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -615,7 +615,7 @@ void RimReservoirView::createDisplayModel() if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) { - std::vector faultGeometryTypesToAppend = visibleFaultParts(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); RivReservoirViewPartMgr::ReservoirGeometryCacheType faultLabelType = m_reservoirGridPartManager->geometryTypeForFaultLabels(faultGeometryTypesToAppend); @@ -630,7 +630,6 @@ void RimReservoirView::createDisplayModel() } updateFaultForcedVisibility(); - } // Compute triangle count, Debug only @@ -709,7 +708,7 @@ void RimReservoirView::updateCurrentTimeStep() if (faultCollection()->showFaultsOutsideFilters) { - std::vector faultGeometryTypesToAppend = visibleFaultParts(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); for (size_t i = 0; i < faultGeometryTypesToAppend.size(); i++) { @@ -1941,31 +1940,20 @@ void RimReservoirView::updateFaultForcedVisibility() // As fault geometry is visible in grid visualization mode, fault geometry must be forced visible // even if the fault item is disabled in project tree view - caf::FixedArray forceOn; - - for (size_t i = 0; i < RivReservoirViewPartMgr::PROPERTY_FILTERED; i++) - { - forceOn[i] = false; - } - - std::vector faultParts = visibleFaultParts(); - for (size_t i = 0; i < faultParts.size(); i++) + if (!faultCollection->showFaultCollection) { - forceOn[faultParts[i]]; + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::ALL_WELL_CELLS, true); } - for (size_t i = 0; i < RivReservoirViewPartMgr::PROPERTY_FILTERED; i++) - { - RivReservoirViewPartMgr::ReservoirGeometryCacheType cacheType = (RivReservoirViewPartMgr::ReservoirGeometryCacheType)i; - - m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(cacheType, forceOn[i]); - } + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::RANGE_FILTERED, true); + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::VISIBLE_WELL_FENCE_CELLS, true); + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::VISIBLE_WELL_FENCE_CELLS_OUTSIDE_RANGE_FILTER, true); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimReservoirView::visibleFaultParts() const +std::vector RimReservoirView::visibleFaultGeometryTypes() const { std::vector faultParts; @@ -2043,7 +2031,7 @@ std::vector RimReservoirVie void RimReservoirView::updateFaultColors() { // Update all fault geometry - std::vector faultGeometriesToRecolor = visibleFaultParts(); + std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 95ae186b5a..4c37031753 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -191,7 +191,7 @@ class RimReservoirView : public caf::PdmObject void updateStaticCellColors(unsigned short geometryType); void updateLegends(); - std::vector visibleFaultParts() const; + std::vector visibleFaultGeometryTypes() const; void updateFaultForcedVisibility(); void updateFaultColors(); From e73095e862a026158ae577da1612ffdb4947b122 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 18:25:00 +0200 Subject: [PATCH 020/346] Moved update for force visibility before retrieving display parts --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 73ee88346a..6d6c7ac57e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -615,6 +615,8 @@ void RimReservoirView::createDisplayModel() if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) { + updateFaultForcedVisibility(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); RivReservoirViewPartMgr::ReservoirGeometryCacheType faultLabelType = m_reservoirGridPartManager->geometryTypeForFaultLabels(faultGeometryTypesToAppend); @@ -629,7 +631,6 @@ void RimReservoirView::createDisplayModel() m_reservoirGridPartManager->appendFaultLabelsStaticGeometryPartsToModel(frameModels[frameIdx].p(), faultLabelType); } - updateFaultForcedVisibility(); } // Compute triangle count, Debug only From 7549a69b65874884fa66ce80b7e208ea4798c080 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 18:25:48 +0200 Subject: [PATCH 021/346] Create geometry if needed before accessing fault parts --- .../ModelVisualization/RivReservoirViewPartMgr.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index fc1fcddc26..8f8e095c3e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -906,6 +906,10 @@ RivReservoirViewPartMgr::ReservoirGeometryCacheType RivReservoirViewPartMgr::geo //-------------------------------------------------------------------------------------------------- void RivReservoirViewPartMgr::appendFaultLabelsStaticGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType) { + if (m_geometriesNeedsRegen[geometryType]) + { + createGeometry(geometryType); + } m_geometries[geometryType].appendFaultLabelPartsToModel(model); } @@ -922,5 +926,9 @@ void RivReservoirViewPartMgr::appendFaultLabelsDynamicGeometryPartsToModel(cvf:: //-------------------------------------------------------------------------------------------------- void RivReservoirViewPartMgr::setFaultForceVisibilityForGeometryType(ReservoirGeometryCacheType geometryType, bool forceVisibility) { + if (m_geometriesNeedsRegen[geometryType]) + { + createGeometry(geometryType); + } m_geometries[geometryType].setFaultForceVisibility(forceVisibility); } From ce5b108cc1930f68ee2a539f1c237527b7613881 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 09:10:45 +0200 Subject: [PATCH 022/346] Adjusted file unit test --- .../RifReaderEclipseOutput-Test.cpp | 64 +++++++++++++++++-- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp index d1fbe43b49..59739e33b2 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp @@ -27,7 +27,7 @@ #include "ecl_file.h" #include "RifEclipseOutputFileTools.h" #include "RigCaseCellResultsData.h" - +#include "RifEclipseUnifiedRestartFileAccess.h" @@ -35,15 +35,14 @@ #if 0 + TEST(RigReservoirTest, FileOutputToolsTest) { - cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; - cvf::ref reservoir = new RigReservoir; - // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.EGRID"); - QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +// QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); - ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data()); + ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data(), ECL_FILE_CLOSE_STREAM); EXPECT_TRUE(ertFile); @@ -53,7 +52,6 @@ TEST(RigReservoirTest, FileOutputToolsTest) EXPECT_TRUE(keywords.size() == keywordDataItemCounts.size()); - qDebug() << "Keyword - Number of data items"; for (int i = 0; i < keywords.size(); i++) { @@ -66,6 +64,58 @@ TEST(RigReservoirTest, FileOutputToolsTest) } +TEST(RigReservoirTest, UnifiedTestFile) +{ + + // Location of test dataset received from Håkon Høgstøl in July 2011 with 10k active cells +#ifdef WIN32 + QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +#else + QString filename("/mnt/hgfs/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +#endif + + { + cvf::ref restartFile = new RifEclipseUnifiedRestartFileAccess(); + + QStringList fileNameList; + fileNameList << filename; + restartFile->setRestartFiles(fileNameList); + restartFile->open(); + + QStringList resultNames; + std::vector resultDataItemCounts; + restartFile->resultNames(&resultNames, &resultDataItemCounts); + + for (int i = 0; i < resultNames.size(); i++) + { + qDebug() << "Result names\n" << resultNames[i] << " - " << resultDataItemCounts[i]; + } + + std::vector tsteps = restartFile->timeSteps(); + + qDebug() << "Time step texts\n"; + for (int i = 0; i < tsteps.size(); i++) + { + qDebug() << tsteps[i].toString(); + } + + /* + std::vector resultValues; + size_t timeStep = 0; + restartFile->results(resultNames[0], timeStep, &resultValues); + + size_t i; + for (i = 0; i < 500; i++) + { + qDebug() << resultValues[i]; + } + */ + } + +} + + + void buildResultInfoString(RigReservoir* reservoir, RifReaderInterface::PorosityModelResultType porosityModel, RimDefines::ResultCatType resultType) { RigCaseCellResultsData* matrixResults = reservoir->results(porosityModel); From db57780f9e761cc73030c1d781a855e868369f61 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 12:36:22 +0200 Subject: [PATCH 023/346] Map result color on fault if fault is disabled by user --- .../RivReservoirFaultsPartMgr.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index ff01f2bd59..8616541032 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -166,16 +166,18 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { - if (m_faultCollection->showResultsOnFaults()) + for (size_t i = 0; i < m_faultCollection->faults.size(); i++) { - for (size_t i = 0; i < m_faultParts.size(); i++) + RimFault* rimFault = m_faultCollection->faults[i]; + + if (m_faultCollection->showFaultCollection && rimFault->showFault && !m_faultCollection->showResultsOnFaults()) { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + m_faultParts[i]->applySingleColorEffect(); + } + else + { + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } - } - else - { - applySingleColorEffect(); } } From dfbd8db69ec6449af409a499d4010b2be64b9361 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 13:26:43 +0200 Subject: [PATCH 024/346] Always show result color when showing grid --- .../RivReservoirFaultsPartMgr.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 8616541032..48e73ff06f 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -107,7 +107,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) forceDisplayOfFault = isShowingGrid; } - if (m_forceVisibility) + if (m_forceVisibility && isShowingGrid) { forceDisplayOfFault = true; } @@ -166,17 +166,26 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { + bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); + for (size_t i = 0; i < m_faultCollection->faults.size(); i++) { RimFault* rimFault = m_faultCollection->faults[i]; - if (m_faultCollection->showFaultCollection && rimFault->showFault && !m_faultCollection->showResultsOnFaults()) + if (isShowingGrid) { - m_faultParts[i]->applySingleColorEffect(); + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } else { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + if (m_faultCollection->showResultsOnFaults()) + { + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + } + else + { + m_faultParts[i]->applySingleColorEffect(); + } } } } From b53623eb49ecda0e10265775b07e96028faf6444 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 14:48:37 +0200 Subject: [PATCH 025/346] Added hide fault to context menu in 3D view --- .../ProjectDataModel/RimFaultCollection.h | 3 +- .../ProjectDataModel/RimReservoirView.cpp | 31 ++------------- .../ProjectDataModel/RimReservoirView.h | 2 +- .../ReservoirDataModel/RigMainGrid.cpp | 33 ++++++++++++++++ .../ReservoirDataModel/RigMainGrid.h | 1 + ApplicationCode/UserInterface/RiuViewer.cpp | 39 +++++++++++++++++-- ApplicationCode/UserInterface/RiuViewer.h | 3 ++ 7 files changed, 79 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 095a65f96b..39b1fe982a 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -75,13 +75,12 @@ class RimFaultCollection : public caf::PdmObject caf::PdmField showFaultCollection; caf::PdmPointersField faults; + RimFault* findFaultByName(QString name); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); virtual caf::PdmFieldHandle* objectToggleField(); private: - RimFault* findFaultByName(QString name); - virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); private: diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 6d6c7ac57e..750729323b 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -2043,39 +2043,16 @@ void RimReservoirView::updateFaultColors() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) +void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString) { if (grid->isMainGrid()) { RigMainGrid* mainGrid = grid->mainGrid(); - for (size_t i = 0; i < mainGrid->faults().size(); i++) + const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(cellIndex, face); + if (fault) { - const RigFault* rigFault = mainGrid->faults().at(i); - const std::vector& faultFaces = rigFault->faultFaces(); - - for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) - { - if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) - { - if (face == faultFaces[fIdx].m_nativeFace ) - { - resultInfoText->append(QString("Fault Name: %1\n").arg(rigFault->name())); - } - - return; - } - - if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) - { - if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) - { - resultInfoText->append(QString("Fault Name: %1\n").arg(rigFault->name())); - } - - return; - } - } + textString->append(QString("Fault Name: %1\n").arg(fault->name())); } } } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 4c37031753..178d17ecd5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -180,7 +180,7 @@ class RimReservoirView : public caf::PdmObject // Display model generation private: - void appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText); + void appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString); void createDisplayModel(); void updateDisplayModelVisibility(); diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index db11222984..4bbdea1cb9 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -369,3 +369,36 @@ bool RigMainGrid::faceNormalsIsOutwards() const { return m_flipXAxis ^ m_flipYAxis; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const +{ + for (size_t i = 0; i < m_faults.size(); i++) + { + const RigFault* rigFault = m_faults.at(i); + const std::vector& faultFaces = rigFault->faultFaces(); + + for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) + { + if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) + { + if (face == faultFaces[fIdx].m_nativeFace ) + { + return rigFault; + } + } + + if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) + { + if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) + { + return rigFault; + } + } + } + } + + return NULL; +} diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index f7fc927571..0cf0dc8286 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -51,6 +51,7 @@ class RigMainGrid : public RigGridBase void setFaults(const cvf::Collection& faults); const cvf::Collection& faults() { return m_faults; } void calculateFaults(); + const RigFault* findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const; bool faceNormalsIsOutwards() const; void computeCachedData(); diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 71489243e2..286058a707 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -25,12 +25,13 @@ #include "RimReservoirView.h" +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimResultSlot.h" #include "RimWellCollection.h" #include "RimUiTreeModelPdm.h" @@ -278,11 +279,24 @@ void RiuViewer::mouseReleaseEvent(QMouseEvent* event) { m_currentGridIdx = firstHitPart->id(); m_currentCellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); + m_currentFaceIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); QMenu menu; + menu.addAction(QString("I-slice range filter"), this, SLOT(slotRangeFilterI())); menu.addAction(QString("J-slice range filter"), this, SLOT(slotRangeFilterJ())); menu.addAction(QString("K-slice range filter"), this, SLOT(slotRangeFilterK())); + + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + menu.addSeparator(); + + QString faultName = fault->name(); + menu.addAction(QString("Hide ") + faultName, this, SLOT(slotHideFault())); + } + menu.exec(event->globalPos()); } } @@ -759,3 +773,22 @@ void RiuViewer::removeOverlayItem(cvf::OverlayItem* overlayItem) m_renderingSequence->firstRendering()->removeOverlayItem(overlayItem); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuViewer::slotHideFault() +{ + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + QString faultName = fault->name(); + + RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); + if (rimFault) + { + rimFault->showFault.setValueFromUi(!rimFault->showFault); + } + } +} + diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index 7e881a1464..a2f5c4de92 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -24,6 +24,7 @@ #include "cafPdmPointer.h" #include "cafMouseState.h" +#include "cvfStructGrid.h" class RimReservoirView; class QLabel; @@ -87,6 +88,7 @@ private slots: void slotRangeFilterI(); void slotRangeFilterJ(); void slotRangeFilterK(); + void slotHideFault(); private: void updateLegends(); @@ -114,6 +116,7 @@ private slots: size_t m_currentGridIdx; size_t m_currentCellIndex; + cvf::StructGridInterface::FaceType m_currentFaceIndex; QPoint m_lastMousePressPosition; }; From 69523184ed562c028fc0d4fa297867066025bee5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 14:58:54 +0200 Subject: [PATCH 026/346] Make sure grid view is active after a range filter is added --- ApplicationCode/UserInterface/RiuViewer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 286058a707..79a073f43c 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -338,6 +338,8 @@ void RiuViewer::slotRangeFilterI() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- @@ -371,6 +373,8 @@ void RiuViewer::slotRangeFilterJ() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- @@ -404,6 +408,8 @@ void RiuViewer::slotRangeFilterK() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- From 1f5977cbc698e80aef06907105c77d5810e7dda1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 29 Jul 2014 08:49:54 +0200 Subject: [PATCH 027/346] Faults: Added fault result mapping management --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimFaultResultSlot.cpp | 53 +++++++++++++++++++ .../ProjectDataModel/RimFaultResultSlot.h | 47 ++++++++++++++++ .../ProjectDataModel/RimReservoirView.cpp | 6 +++ .../ProjectDataModel/RimReservoirView.h | 2 + 5 files changed, 110 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimFaultResultSlot.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 2abc7eacba..c9cb08a878 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,6 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -94,6 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp new file mode 100644 index 0000000000..dbfebd4a46 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFaultResultSlot.h" + + +namespace caf +{ + template<> + void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() + { + addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSlot::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); + addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSlot::CELL_RESULT_MAPPING); + } +} + +CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultResultSlot::RimFaultResultSlot() +{ + CAF_PDM_InitObject("Fault Result Slot", "", "", ""); + + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultResultSlot::~RimFaultResultSlot() +{ +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h new file mode 100644 index 0000000000..010ce4d474 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultResultSlot : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + enum FaultVisualizationMode + { + FAULT_COLOR, + CELL_RESULT_MAPPING, + CUSTOM_RESULT_MAPPING + }; + +public: + RimFaultResultSlot(); + virtual ~RimFaultResultSlot(); + +private: + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; +}; + diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 750729323b..0d893222a0 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,6 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" +#include "RimFaultResultSlot.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -101,6 +102,11 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); + CAF_PDM_InitFieldNoDefault(&cellFaultResult, "GridCellFaultResult", "Fault Cell Result", ":/CellResult.png", "", ""); + cellFaultResult = new RimFaultResultSlot(); + cellFaultResult.setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); overlayInfoConfig->setReservoirView(this); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 178d17ecd5..f6a5ba96f5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -43,6 +43,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; +class RimFaultResultSlot; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -96,6 +97,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; + caf::PdmField cellFaultResult; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From eecbc1e0ef14cf3dcd7c8de29bf540f90724d30a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 09:13:47 +0200 Subject: [PATCH 028/346] Performance: Control how much data to import from file User can control if faults, NNCs and simulation wells are to be imported from file. --- .../Application/RiaPreferences.cpp | 34 ++++++++-- ApplicationCode/Application/RiaPreferences.h | 4 +- .../FileInterface/CMakeLists_files.cmake | 3 + .../FileInterface_UnitTests/CMakeLists.txt | 1 + .../FileInterface/RifReaderEclipseOutput.cpp | 15 +++- .../FileInterface/RifReaderInterface.cpp | 68 +++++++++++++++++++ .../FileInterface/RifReaderInterface.h | 19 ++++-- .../FileInterface/RifReaderSettings.cpp | 59 ++++++++++++++++ .../FileInterface/RifReaderSettings.h | 46 +++++++++++++ ApplicationCode/ProjectDataModel/RimCase.cpp | 12 +++- .../ProjectDataModel/RimInputCase.cpp | 5 +- .../ProjectDataModel/RimResultCase.cpp | 3 +- 12 files changed, 246 insertions(+), 23 deletions(-) create mode 100644 ApplicationCode/FileInterface/RifReaderInterface.cpp create mode 100644 ApplicationCode/FileInterface/RifReaderSettings.cpp create mode 100644 ApplicationCode/FileInterface/RifReaderSettings.h diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 0acd148c48..337084d979 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -22,6 +22,7 @@ #include "cafPdmUiFilePathEditor.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmUiCheckBoxEditor.h" +#include "RifReaderSettings.h" CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- @@ -61,10 +62,16 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&lastUsedProjectFileName,"lastUsedProjectFileName", "Last Used Project File", "", "", ""); lastUsedProjectFileName.setUiHidden(true); - CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "SOIL", "", "SOIL = 1.0 - SGAS - SWAT", ""); - CAF_PDM_InitField(&autocomputeDepthRelatedProperties,"autocomputeDepth", true, "DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); + CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "SOIL", "", "SOIL = 1.0 - SGAS - SWAT", ""); + CAF_PDM_InitField(&autocomputeDepthRelatedProperties, "autocomputeDepth", true, "DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); + CAF_PDM_InitField(&autocomputeGridFaults, "autocomputeGridFaults", true, "Grid faults", "", "Detect all fault faces geometrically", ""); - CAF_PDM_InitField(&readFaultData, "readFaultData", true, "Read fault data", "", "", ""); + autocomputeDepthRelatedProperties.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + autocomputeSOIL.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + autocomputeGridFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + readerSettings = new RifReaderSettings; + CAF_PDM_InitFieldNoDefault(&readerSettings, "readerSettings", "Reader settings", "", "", ""); } //-------------------------------------------------------------------------------------------------- @@ -80,6 +87,8 @@ RiaPreferences::~RiaPreferences(void) //-------------------------------------------------------------------------------------------------- void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) { + readerSettings->defineEditorAttribute(field, uiConfigName, attribute); + if (field == &scriptDirectories) { caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); @@ -89,7 +98,10 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt myAttr->m_appendUiSelectedFolderToText = true; } } - else if (field == &octaveShowHeaderInfoWhenExecutingScripts) + else if (field == &octaveShowHeaderInfoWhenExecutingScripts || + field == &autocomputeSOIL || + field == &autocomputeDepthRelatedProperties || + field == &autocomputeGridFaults) { caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); if (myAttr) @@ -125,9 +137,16 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* autoComputeGroup = uiOrdering.addNewGroup("Compute when loading new case"); autoComputeGroup->add(&autocomputeSOIL); autoComputeGroup->add(&autocomputeDepthRelatedProperties); + autoComputeGroup->add(&autocomputeGridFaults); - caf::PdmUiGroup* faultsGroup = uiOrdering.addNewGroup("Faults"); - faultsGroup->add(&readFaultData); + + caf::PdmUiGroup* readerSettingsGroup = uiOrdering.addNewGroup("Reader settings"); + std::vector readerSettingsFields; + readerSettings->fields(readerSettingsFields); + for (size_t i = 0; i < readerSettingsFields.size(); i++) + { + readerSettingsGroup->add(readerSettingsFields[i]); + } } //-------------------------------------------------------------------------------------------------- @@ -142,6 +161,7 @@ void RiaPreferences::configureForRegressionTests() autocomputeSOIL = true; autocomputeDepthRelatedProperties = true; - readFaultData = false; + CVF_ASSERT(readerSettings); + readerSettings->importFaults = false; } diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index bb7d3f3354..78fd48e44e 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -27,6 +27,7 @@ // Include to make Pdm work for cvf::Color #include "cafPdmFieldCvfColor.h" +class RifReaderSettings; class RiaPreferences : public caf::PdmObject { @@ -63,8 +64,9 @@ class RiaPreferences : public caf::PdmObject caf::PdmField autocomputeSOIL; caf::PdmField autocomputeDepthRelatedProperties; + caf::PdmField autocomputeGridFaults; - caf::PdmField readFaultData; + caf::PdmField readerSettings; protected: virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index 1ddd99f08a..34a6ec93be 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CEE_CURRENT_LIST_DIR}RifReaderEclipseOutput.h ${CEE_CURRENT_LIST_DIR}RifJsonEncodeDecode.h ${CEE_CURRENT_LIST_DIR}RifReaderInterface.h ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.h +${CEE_CURRENT_LIST_DIR}RifReaderSettings.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -26,7 +27,9 @@ ${CEE_CURRENT_LIST_DIR}RifEclipseUnifiedRestartFileAccess.cpp ${CEE_CURRENT_LIST_DIR}RifReaderEclipseInput.cpp ${CEE_CURRENT_LIST_DIR}RifReaderEclipseOutput.cpp ${CEE_CURRENT_LIST_DIR}RifJsonEncodeDecode.cpp +${CEE_CURRENT_LIST_DIR}RifReaderInterface.cpp ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.cpp +${CEE_CURRENT_LIST_DIR}RifReaderSettings.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt index 475f353da7..092d8d9098 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt @@ -59,6 +59,7 @@ set( UNIT_TEST_CPP_SOURCES ) set( LINK_LIBRARIES + cafProjectDataModel CommonCode LibViewing diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index e9cb4e2918..a620ce1893 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -434,17 +434,26 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigCaseData* eclipseC progInfo.setProgressDescription("Reading NNC data"); progInfo.setNextProgressIncrement(5); - transferNNCData(mainEclGrid, m_ecl_init_file, eclipseCase->mainGrid()); + if (isNNCsEnabled()) + { + transferNNCData(mainEclGrid, m_ecl_init_file, eclipseCase->mainGrid()); + } progInfo.incrementProgress(); progInfo.setProgressDescription("Processing NNC data"); progInfo.setNextProgressIncrement(20); - eclipseCase->mainGrid()->nncData()->processConnections( *(eclipseCase->mainGrid())); + if (isNNCsEnabled()) + { + eclipseCase->mainGrid()->nncData()->processConnections( *(eclipseCase->mainGrid())); + } progInfo.incrementProgress(); progInfo.setNextProgressIncrement(8); progInfo.setProgressDescription("Reading Well information"); - readWellCells(mainEclGrid); + if (isSimulationWellDataEnabled()) + { + readWellCells(mainEclGrid); + } progInfo.setProgressDescription("Releasing reader memory"); ecl_grid_free( mainEclGrid ); diff --git a/ApplicationCode/FileInterface/RifReaderInterface.cpp b/ApplicationCode/FileInterface/RifReaderInterface.cpp new file mode 100644 index 0000000000..c08eb619e5 --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderInterface.cpp @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifReaderInterface.h" + +#include "RifReaderSettings.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderInterface::setReaderSetting(RifReaderSettings* settings) +{ + m_settings = settings; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isFaultImportEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importFaults; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isSimulationWellDataEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importSimulationWellData; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isNNCsEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importNNCs; + } + + return false; +} diff --git a/ApplicationCode/FileInterface/RifReaderInterface.h b/ApplicationCode/FileInterface/RifReaderInterface.h index b57a8d4976..6f66a4aeda 100644 --- a/ApplicationCode/FileInterface/RifReaderInterface.h +++ b/ApplicationCode/FileInterface/RifReaderInterface.h @@ -22,12 +22,16 @@ #include "cvfObject.h" #include "cvfLibCore.h" +#include "cafPdmPointer.h" + #include #include #include class RigCaseData; +class RifReaderSettings; + //================================================================================================== // @@ -44,11 +48,14 @@ class RifReaderInterface : public cvf::Object }; public: - RifReaderInterface() { m_readFaultData = false; } - virtual ~RifReaderInterface() {} + RifReaderInterface() { } + virtual ~RifReaderInterface() { } + + void setReaderSetting(RifReaderSettings* settings); - void readFaultData(bool readFaultData) { m_readFaultData = readFaultData; } - bool isFaultImportEnabled() { return m_readFaultData; } + bool isFaultImportEnabled(); + bool isSimulationWellDataEnabled(); + bool isNNCsEnabled(); virtual bool open(const QString& fileName, RigCaseData* eclipseCase) = 0; virtual void close() = 0; @@ -63,6 +70,6 @@ class RifReaderInterface : public cvf::Object private: - std::vector m_filenamesWithFaults; - bool m_readFaultData; + std::vector m_filenamesWithFaults; + caf::PdmPointer m_settings; }; diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp new file mode 100644 index 0000000000..e3a743d188 --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + + +#include "RifReaderSettings.h" +#include "cafPdmUiCheckBoxEditor.h" + + +CAF_PDM_SOURCE_INIT(RifReaderSettings, "RifReaderSettings"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifReaderSettings::RifReaderSettings() +{ + CAF_PDM_InitObject("RifReaderSettings", "", "", ""); + + CAF_PDM_InitField(&importFaults, "importFaults", false, "Import faults", "", "", ""); + importFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", false, "Import simulation wells", "", "", ""); + importSimulationWellData.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", false, "Import NNCs", "", "", ""); + importNNCs.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderSettings::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (field == &importFaults || + field == &importSimulationWellData || + field == &importNNCs) + { + caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_useNativeCheckBoxLabel = true; + } + } +} + diff --git a/ApplicationCode/FileInterface/RifReaderSettings.h b/ApplicationCode/FileInterface/RifReaderSettings.h new file mode 100644 index 0000000000..7bf3ed050e --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderSettings.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmField.h" +#include "cafPdmObject.h" + + +//================================================================================================== +/// +/// +//================================================================================================== +class RifReaderSettings : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + + friend class RiaPreferences; + +public: + RifReaderSettings(); + + caf::PdmField importFaults; + caf::PdmField importSimulationWellData; + caf::PdmField importNNCs; + +protected: + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); + +}; + diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index c386fed410..c58b36f476 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -18,6 +18,8 @@ #include "RimCase.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimCaseCollection.h" @@ -298,9 +300,13 @@ void RimCase::computeCachedData() rigEclipseCase->mainGrid()->computeCachedData(); pInf.incrementProgress(); - pInf.setProgressDescription("Calculating faults"); - rigEclipseCase->mainGrid()->calculateFaults(); - pInf.incrementProgress(); + RiaPreferences* prefs = RiaApplication::instance()->preferences(); + if (prefs->autocomputeGridFaults) + { + pInf.setProgressDescription("Calculating faults"); + rigEclipseCase->mainGrid()->calculateFaults(); + pInf.incrementProgress(); + } } } diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index adc91355bf..f003e5db0f 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -23,6 +23,7 @@ #include "RifReaderEclipseInput.h" #include "RifReaderInterface.h" #include "RifReaderMockModel.h" +#include "RifReaderSettings.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimDefines.h" @@ -96,7 +97,7 @@ void RimInputCase::openDataFileSet(const QStringList& fileNames) for (int i = 0; i < fileNames.size(); i++) { - if (RifEclipseInputFileTools::openGridFile(fileNames[i], this->reservoirData(), prefs->readFaultData())) + if (RifEclipseInputFileTools::openGridFile(fileNames[i], this->reservoirData(), prefs->readerSettings->importFaults())) { m_gridFileName = fileNames[i]; @@ -181,7 +182,7 @@ bool RimInputCase::openEclipseGridFile() { RiaPreferences* prefs = RiaApplication::instance()->preferences(); readerInterface = new RifReaderEclipseInput; - readerInterface->readFaultData(prefs->readFaultData()); + readerInterface->setReaderSetting(prefs->readerSettings()); cvf::ref eclipseCase = new RigCaseData; if (!readerInterface->open(m_gridFileName, eclipseCase.p())) diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index 8d1041fa63..da71221787 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -22,6 +22,7 @@ #include "RifEclipseOutputFileTools.h" #include "RifReaderEclipseOutput.h" #include "RifReaderMockModel.h" +#include "RifReaderSettings.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimMockModelSettings.h" @@ -90,7 +91,7 @@ bool RimResultCase::openEclipseGridFile() RiaPreferences* prefs = RiaApplication::instance()->preferences(); readerInterface = new RifReaderEclipseOutput; - readerInterface->readFaultData(prefs->readFaultData()); + readerInterface->setReaderSetting(prefs->readerSettings()); readerInterface->setFilenamesWithFaults(this->filesContainingFaults()); cvf::ref eclipseCase = new RigCaseData; From 5ad874b179bb8b761172d609d3646b0d7e3df792 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 09:14:54 +0200 Subject: [PATCH 029/346] Updates to tests --- .../RifReaderEclipseOutput-Test.cpp | 80 ++++++++++++++++--- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp index 59739e33b2..98bd5fbba8 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp @@ -28,19 +28,78 @@ #include "RifEclipseOutputFileTools.h" #include "RigCaseCellResultsData.h" #include "RifEclipseUnifiedRestartFileAccess.h" +#include "RifReaderSettings.h" +#if 0 -#if 0 +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RigReservoirTest, DISABLED_BasicTest) +{ + + cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; + cvf::ref reservoir = new RigCaseData; + + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.EGRID"); + + RifReaderSettings readerSettings; + readerInterfaceEcl->setReaderSetting(&readerSettings); + + bool result = readerInterfaceEcl->open(filename, reservoir.p()); + EXPECT_TRUE(result); + + { +// QStringList staticResults = readerInterfaceEcl->staticResults(); +// EXPECT_EQ(42, staticResults.size()); +// qDebug() << "Static results\n" << staticResults; +// +// QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); +// EXPECT_EQ(23, dynamicResults.size()); +// qDebug() << "Dynamic results\n" << dynamicResults; +// +// int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); +// EXPECT_EQ(9, numTimeSteps); +// +// QStringList timeStepText = readerInterfaceEcl->timeStepText(); +// EXPECT_EQ(numTimeSteps, timeStepText.size()); +// qDebug() << "Time step texts\n" << timeStepText; + } + + + readerInterfaceEcl->close(); + { +// QStringList staticResults = readerInterfaceEcl->staticResults(); +// EXPECT_EQ(0, staticResults.size()); +// +// QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); +// EXPECT_EQ(0, dynamicResults.size()); +// +// int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); +// EXPECT_EQ(0, numTimeSteps); +// +// QStringList timeStepText = readerInterfaceEcl->timeStepText(); +// EXPECT_EQ(numTimeSteps, timeStepText.size()); + } -TEST(RigReservoirTest, FileOutputToolsTest) +} + + + +TEST(RigReservoirTest, DISABLED_FileOutputToolsTest) { + cvf::DebugTimer timer("test"); + + // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.EGRID"); // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); - QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); +// QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); + QString filename("c:/tmp/troll_MSW/T07-4A-W2012-16-F3.UNRST"); + ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data(), ECL_FILE_CLOSE_STREAM); EXPECT_TRUE(ertFile); @@ -61,18 +120,16 @@ TEST(RigReservoirTest, FileOutputToolsTest) ecl_file_close(ertFile); ertFile = NULL; + + timer.reportTime(); + //qDebug() << timer.lapt; } TEST(RigReservoirTest, UnifiedTestFile) { - - // Location of test dataset received from Håkon Høgstøl in July 2011 with 10k active cells -#ifdef WIN32 - QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); -#else - QString filename("/mnt/hgfs/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); -#endif + //QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); { cvf::ref restartFile = new RifEclipseUnifiedRestartFileAccess(); @@ -86,9 +143,10 @@ TEST(RigReservoirTest, UnifiedTestFile) std::vector resultDataItemCounts; restartFile->resultNames(&resultNames, &resultDataItemCounts); + qDebug() << "Result names\n"; for (int i = 0; i < resultNames.size(); i++) { - qDebug() << "Result names\n" << resultNames[i] << " - " << resultDataItemCounts[i]; + qDebug() << resultNames[i] << "\t" << resultDataItemCounts[i]; } std::vector tsteps = restartFile->timeSteps(); From bc57b8b0912feb52fa0c66365c2ac830b3623ca9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 10:54:46 +0200 Subject: [PATCH 030/346] Improved management of multiple legend overlay items --- .../ProjectDataModel/RimReservoirView.cpp | 59 +++++------ ApplicationCode/UserInterface/RiuViewer.cpp | 97 ++++++------------- ApplicationCode/UserInterface/RiuViewer.h | 11 +-- 3 files changed, 62 insertions(+), 105 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 0d893222a0..c4175aa2b5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -221,8 +221,10 @@ void RimReservoirView::updateViewerWidget() this->cellResult()->legendConfig->recreateLegend(); this->cellResult()->ternaryLegendConfig->recreateLegend(); this->cellEdgeResult()->legendConfig->recreateLegend(); - m_viewer->setColorLegend1(this->cellResult()->legendConfig->legend()); - m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); + + m_viewer->removeAllColorLegends(); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); if (RiaApplication::instance()->navigationPolicy() == RiaApplication::NAVIGATION_POLICY_CEETRON) { @@ -1370,6 +1372,11 @@ void RimReservoirView::indicesToVisibleGrids(std::vector* gridIndices) //-------------------------------------------------------------------------------------------------- void RimReservoirView::updateLegends() { + if (m_viewer) + { + m_viewer->removeAllColorLegends(); + } + if (!m_reservoir || !m_viewer || !m_reservoir->reservoirData() ) { return; @@ -1408,40 +1415,15 @@ void RimReservoirView::updateLegends() this->cellResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); this->cellResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); - m_viewer->setColorLegend1(this->cellResult()->legendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); this->cellResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Cell Results: \n") + this->cellResult()->resultVariable())); } else { this->cellResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); this->cellResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); - m_viewer->setColorLegend1(NULL); - } - - if (this->cellEdgeResult()->hasResult()) - { - double globalMin, globalMax; - double globalPosClosestToZero, globalNegClosestToZero; - this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); - this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); - - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); - - m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); - this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); - - } - else - { - m_viewer->setColorLegend2(NULL); - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); } - - viewer()->removeOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); - size_t maxTimeStepCount = results->maxTimeStepCount(); if (this->cellResult()->isTernarySaturationSelected() && maxTimeStepCount > 1) { @@ -1496,9 +1478,28 @@ void RimReservoirView::updateLegends() if (this->cellResult()->ternaryLegendConfig->legend()) { - viewer()->addOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->ternaryLegendConfig->legend()); } } + + if (this->cellEdgeResult()->hasResult()) + { + double globalMin, globalMax; + double globalPosClosestToZero, globalNegClosestToZero; + this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); + this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); + + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); + + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); + this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); + } + else + { + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 79a073f43c..29476f1678 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -146,55 +146,6 @@ RiuViewer::~RiuViewer() } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::setColorLegend1(cvf::OverlayScalarMapperLegend* legend) -{ - m_mainRendering->removeOverlayItem(m_legend1.p()); - - m_legend1 = legend; - - this->updateLegends(); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::setColorLegend2(cvf::OverlayScalarMapperLegend* legend) -{ - m_mainRendering->removeOverlayItem(m_legend2.p()); - - m_legend2 = legend; - - this->updateLegends(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::updateLegends() -{ - cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); - CVF_ASSERT(firstRendering); - - firstRendering->removeOverlayItem(m_legend1.p()); - firstRendering->removeOverlayItem(m_legend2.p()); - - if (m_legend1.notNull()) - { - m_legend1->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); - firstRendering->addOverlayItem(m_legend1.p()); - } - - if (m_legend2.notNull()) - { - m_legend2->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); - firstRendering->addOverlayItem(m_legend2.p()); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -510,9 +461,6 @@ void RiuViewer::slotEndAnimation() cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); CVF_ASSERT(firstRendering); - firstRendering->removeOverlayItem(m_legend1.p()); - firstRendering->removeOverlayItem(m_legend2.p()); - if (m_reservoirView) m_reservoirView->endAnimation(); caf::Viewer::slotEndAnimation(); @@ -530,8 +478,6 @@ void RiuViewer::slotSetCurrentFrame(int frameIndex) if (m_reservoirView) m_reservoirView->setCurrentTimeStep(frameIndex); - this->updateLegends(); - caf::Viewer::slotSetCurrentFrame(frameIndex); } @@ -763,38 +709,53 @@ void RiuViewer::mousePressEvent(QMouseEvent* event) m_lastMousePressPosition = event->pos(); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::addOverlayItem(cvf::OverlayItem* overlayItem) +void RiuViewer::slotHideFault() { - m_renderingSequence->firstRendering()->addOverlayItem(overlayItem); + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + QString faultName = fault->name(); + + RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); + if (rimFault) + { + rimFault->showFault.setValueFromUi(!rimFault->showFault); + } + } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::removeOverlayItem(cvf::OverlayItem* overlayItem) +void RiuViewer::removeAllColorLegends() { - m_renderingSequence->firstRendering()->removeOverlayItem(overlayItem); + for (size_t i = 0; i < m_visibleLegends.size(); i++) + { + m_mainRendering->removeOverlayItem(m_visibleLegends[i].p()); + } + + m_visibleLegends.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::slotHideFault() +void RiuViewer::addColorLegendToBottomLeftCorner(cvf::OverlayItem* legend) { - const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); - const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); - if (fault) + cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); + CVF_ASSERT(firstRendering); + + if (legend) { - QString faultName = fault->name(); + legend->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); + firstRendering->addOverlayItem(legend); - RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); - if (rimFault) - { - rimFault->showFault.setValueFromUi(!rimFault->showFault); - } + m_visibleLegends.push_back(legend); } } diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index a2f5c4de92..5dd21d8a0b 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -51,8 +51,6 @@ class RiuViewer : public caf::Viewer RiuViewer(const QGLFormat& format, QWidget* parent); ~RiuViewer(); - void setColorLegend1(cvf::OverlayScalarMapperLegend* legend); - void setColorLegend2(cvf::OverlayScalarMapperLegend* legend); void setDefaultView(); cvf::Vec3d pointOfInterest(); void setPointOfInterest(cvf::Vec3d poi); @@ -67,8 +65,8 @@ class RiuViewer : public caf::Viewer void showAnimationProgress(bool enable); - void addOverlayItem(cvf::OverlayItem* overlayItem); - void removeOverlayItem(cvf::OverlayItem* overlayItem); + void removeAllColorLegends(); + void addColorLegendToBottomLeftCorner(cvf::OverlayItem* legend); public slots: @@ -91,7 +89,6 @@ private slots: void slotHideFault(); private: - void updateLegends(); void ijkFromCellIndex(size_t gridIdx, size_t cellIndex, size_t* i, size_t* j, size_t* k); private: @@ -108,9 +105,7 @@ private slots: QCDEStyle* m_progressBarStyle; - cvf::ref m_legend1; - cvf::ref m_legend2; - + cvf::Collection m_visibleLegends; caf::PdmPointer m_reservoirView; From 407c838f03f7f3465c2f18694f24c83aa0b16862 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 14:26:39 +0200 Subject: [PATCH 031/346] Fault result: Added custom result to fault result project model --- .../Application/RiaApplication.cpp | 4 ++ .../ProjectDataModel/RimFaultResultSlot.cpp | 55 +++++++++++++++++++ .../ProjectDataModel/RimFaultResultSlot.h | 14 +++++ .../ProjectDataModel/RimReservoirView.cpp | 5 +- 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 472a2b9a23..d95d7d6f02 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,6 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" +#include "RimFaultResultSlot.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -649,6 +650,9 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } + riv->cellFaultResult()->customResultSlot()->setResultVariable(RimDefines::undefinedResultName()); + + RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); uiModel->updateUiSubTree(analysisModels); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index dbfebd4a46..d78a3534d9 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -18,6 +18,11 @@ #include "RimFaultResultSlot.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RiuMainWindow.h" +#include "RimUiTreeModelPdm.h" + namespace caf { @@ -42,6 +47,10 @@ RimFaultResultSlot::RimFaultResultSlot() CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitFieldNoDefault(&customResultSlot, "CustomResultSlot", "Custom Cell Result", ":/CellResult.png", "", ""); + customResultSlot = new RimResultSlot(); + + updateVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -51,3 +60,49 @@ RimFaultResultSlot::~RimFaultResultSlot() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) +{ + customResultSlot->setReservoirView(ownerReservoirView); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + if (changedField == &visualizationMode) + { + updateVisibility(); + + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::initAfterRead() +{ + updateVisibility(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::updateVisibility() +{ + if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + { + this->customResultSlot.setUiHidden(true); + this->customResultSlot.setUiChildrenHidden(true); + } + else + { + this->customResultSlot.setUiHidden(false); + this->customResultSlot.setUiChildrenHidden(false); + } +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 010ce4d474..2fa532d58a 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -22,6 +22,9 @@ #include "cafPdmField.h" #include "cafPdmObject.h" +class RimResultSlot; +class RimReservoirView; + //================================================================================================== /// /// @@ -41,6 +44,17 @@ class RimFaultResultSlot : public caf::PdmObject RimFaultResultSlot(); virtual ~RimFaultResultSlot(); + void setReservoirView(RimReservoirView* ownerReservoirView); + + caf::PdmField customResultSlot; + +protected: + virtual void initAfterRead(); + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + +private: + void updateVisibility(); + private: caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index c4175aa2b5..bba2901cc8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -167,6 +167,8 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); + this->cellFaultResult()->setReservoirView(this); + m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); m_pipesPartManager = new RivReservoirPipesPartMgr(this); @@ -180,6 +182,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { + delete this->cellFaultResult(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -969,11 +972,11 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { + this->cellFaultResult()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); this->propertyFilterCollection()->setReservoirView(this); - } //-------------------------------------------------------------------------------------------------- From def9b57c6542b2ea559056b56ed34e887410301d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 14:52:32 +0200 Subject: [PATCH 032/346] Removed obsolete fault code --- .../ModelVisualization/RivGridPartMgr.cpp | 149 ++---------------- .../ModelVisualization/RivGridPartMgr.h | 15 +- .../RivReservoirPartMgr.cpp | 2 +- 3 files changed, 18 insertions(+), 148 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index d8edaca5b4..98145b17ad 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,27 +50,22 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" -#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection) +RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx) : m_surfaceGenerator(grid), - m_faultGenerator(grid), m_gridIdx(gridIdx), m_grid(grid), m_surfaceFaceFilter(grid), - m_faultFaceFilter(grid), m_opacityLevel(1.0f), - m_defaultColor(cvf::Color3::WHITE), - m_rimFaultCollection(rimFaultCollection) + m_defaultColor(cvf::Color3::WHITE) { CVF_ASSERT(grid); m_cellVisibility = new cvf::UByteArray; m_surfaceFacesTextureCoords = new cvf::Vec2fArray; - m_faultFacesTextureCoords = new cvf::Vec2fArray; } //-------------------------------------------------------------------------------------------------- @@ -94,14 +89,10 @@ void RivGridPartMgr::setCellVisibility(cvf::UByteArray* cellVisibilities) m_surfaceGenerator.setCellVisibility(cellVisibilities); m_surfaceGenerator.addFaceVisibilityFilter(&m_surfaceFaceFilter); - m_faultGenerator.setCellVisibility(cellVisibilities); - m_faultGenerator.addFaceVisibilityFilter(&m_faultFaceFilter); - - generatePartGeometry(m_surfaceGenerator, false); - generatePartGeometry(m_faultGenerator, true); + generatePartGeometry(m_surfaceGenerator); } -void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry) +void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder) { bool useBufferObjects = true; // Surface geometry @@ -134,17 +125,8 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB caf::SurfaceEffectGenerator geometryEffgen(cvf::Color4f(cvf::Color3f::WHITE), caf::PO_1); cvf::ref geometryOnlyEffect = geometryEffgen.generateEffect(); part->setEffect(geometryOnlyEffect.p()); - - if (faultGeometry) - { - part->setEnableMask(faultBit); - m_faultFaces = part; - } - else - { - part->setEnableMask(surfaceBit); - m_surfaceFaces = part; - } + part->setEnableMask(surfaceBit); + m_surfaceFaces = part; } } @@ -168,30 +150,19 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB RiaPreferences* prefs = RiaApplication::instance()->preferences(); cvf::ref eff; - if (faultGeometry) - { - caf::MeshEffectGenerator effGen(prefs->defaultFaultGridLineColors()); - eff = effGen.generateEffect(); - - part->setEnableMask(meshFaultBit); - part->setEffect(eff.p()); - m_faultGridLines = part; - } - else - { - caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); - eff = effGen.generateEffect(); + caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); + eff = effGen.generateEffect(); - // Set priority to make sure fault lines are rendered first - part->setPriority(10); + // Set priority to make sure fault lines are rendered first + part->setPriority(10); - part->setEnableMask(meshSurfaceBit); - part->setEffect(eff.p()); - m_surfaceGridLines = part; - } + part->setEnableMask(meshSurfaceBit); + part->setEffect(eff.p()); + m_surfaceGridLines = part; } } } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -201,12 +172,6 @@ void RivGridPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if(m_surfaceFaces.notNull() ) model->addPart(m_surfaceFaces.p() ); if(m_surfaceGridLines.notNull()) model->addPart(m_surfaceGridLines.p()); - - if (m_rimFaultCollection && m_rimFaultCollection->showGeometryDetectedFaults()) - { - if(m_faultFaces.notNull() ) model->addPart(m_faultFaces.p() ); - if(m_faultGridLines.notNull() ) model->addPart(m_faultGridLines.p() ); - } } //-------------------------------------------------------------------------------------------------- @@ -214,20 +179,18 @@ void RivGridPartMgr::appendPartsToModel(cvf::ModelBasicList* model) //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::updateCellColor(cvf::Color4f color) { - if (m_surfaceFaces.isNull() && m_faultFaces.isNull()) return; + if (m_surfaceFaces.isNull()) return; // Set default effect caf::SurfaceEffectGenerator geometryEffgen(color, caf::PO_1); cvf::ref geometryOnlyEffect = geometryEffgen.generateEffect(); if (m_surfaceFaces.notNull()) m_surfaceFaces->setEffect(geometryOnlyEffect.p()); - if (m_faultFaces.notNull()) m_faultFaces->setEffect(geometryOnlyEffect.p()); if (color.a() < 1.0f) { // Set priority to make sure this transparent geometry are rendered last if (m_surfaceFaces.notNull()) m_surfaceFaces->setPriority(100); - if (m_faultFaces.notNull()) m_faultFaces->setPriority(100); } m_opacityLevel = color.a(); @@ -237,12 +200,6 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) RiaPreferences* prefs = RiaApplication::instance()->preferences(); cvf::ref eff; - if (m_faultFaces.notNull()) - { - caf::MeshEffectGenerator faultEffGen(prefs->defaultFaultGridLineColors()); - eff = faultEffGen.generateEffect(); - m_faultGridLines->setEffect(eff.p()); - } if (m_surfaceFaces.notNull()) { caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); @@ -317,31 +274,6 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } - - // Faults - if (m_faultFaces.notNull()) - { - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (dataAccessObject.isNull()) return; - - m_faultGenerator.textureCoordinates(m_faultFacesTextureCoords.p(), dataAccessObject.p(), mapper); - - setResultsTransparentForWellCells( - cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), - m_surfaceGenerator.quadToCellFaceMapper(), - m_faultFacesTextureCoords.p()); - - - applyTextureResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); - } } //-------------------------------------------------------------------------------------------------- @@ -405,62 +337,11 @@ void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector(m_surfaceFaces->drawable()); - if (dg) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - &m_surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); - - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); - - m_surfaceFaces->setEffect(eff.p()); - } - } - */ updateCellEdgeResultColorOnPart( m_surfaceFaces.p(), &m_surfaceGenerator, timeStepIndex, cellResultSlot, cellEdgeResultSlot); - if (m_faultFaces.notNull()) - { - updateCellEdgeResultColorOnPart( - m_faultFaces.p(), - &m_faultGenerator, - timeStepIndex, cellResultSlot, cellEdgeResultSlot); - } - /* - if (m_faultFaces.notNull()) - { - cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); - if (dg) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - &m_faultGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); - - m_faultFaces->setEffect(eff.p()); - } - } - */ } //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 4ef7bb7e13..6e555300a6 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -34,7 +34,6 @@ namespace cvf class RimResultSlot; class RimCellEdgeResultSlot; -class RimFaultCollection; @@ -72,7 +71,7 @@ class RivTransmissibilityColorMapper class RivGridPartMgr: public cvf::Object { public: - RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection); + RivGridPartMgr(const RigGridBase* grid, size_t gridIdx); ~RivGridPartMgr(); void setTransform(cvf::Transform* scaleTransform); void setCellVisibility(cvf::UByteArray* cellVisibilities ); @@ -89,7 +88,7 @@ class RivGridPartMgr: public cvf::Object static cvf::ref createPerVertexColoringEffect(float opacity); private: - void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); + void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, @@ -117,15 +116,5 @@ class RivGridPartMgr: public cvf::Object cvf::ref m_surfaceGridLines; - // Fault visualization: Dead ?? JJS - cvf::StructGridGeometryGenerator m_faultGenerator; - RigFaultFaceVisibilityFilter m_faultFaceFilter; - cvf::ref m_faultFaces; - cvf::ref m_faultFacesTextureCoords; - - cvf::ref m_faultGridLines; - cvf::ref m_cellVisibility; - - const RimFaultCollection* m_rimFaultCollection; }; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 5ac14e77ce..806bd08023 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -38,7 +38,7 @@ void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, c eclipseCase->allGrids(&grids); for (size_t i = 0; i < grids.size() ; ++i) { - m_allGrids.push_back(new RivGridPartMgr(grids[i], i, faultCollection)); + m_allGrids.push_back(new RivGridPartMgr(grids[i], i)); } if (eclipseCase->mainGrid()) From ee3d74b9fc029752896243a4abd4519d47177cc7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 08:46:30 +0200 Subject: [PATCH 033/346] Fault result: Added fault result legend --- .../Application/RiaApplication.cpp | 2 +- .../ProjectDataModel/RimFaultResultSlot.cpp | 36 ++-- .../ProjectDataModel/RimFaultResultSlot.h | 13 +- .../ProjectDataModel/RimReservoirView.cpp | 159 +++++++++++------- .../ProjectDataModel/RimReservoirView.h | 4 +- .../UserInterface/RiuMainWindow.cpp | 5 +- 6 files changed, 136 insertions(+), 83 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index d95d7d6f02..69a330e63f 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->cellFaultResult()->customResultSlot()->setResultVariable(RimDefines::undefinedResultName()); + riv->cellFaultResult()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index d78a3534d9..249216a6fb 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -45,10 +45,10 @@ RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&m_visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); - CAF_PDM_InitFieldNoDefault(&customResultSlot, "CustomResultSlot", "Custom Cell Result", ":/CellResult.png", "", ""); - customResultSlot = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); + m_customResultSlot = new RimResultSlot(); updateVisibility(); } @@ -65,7 +65,8 @@ RimFaultResultSlot::~RimFaultResultSlot() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { - customResultSlot->setReservoirView(ownerReservoirView); + m_reservoirView = ownerReservoirView; + m_customResultSlot->setReservoirView(ownerReservoirView); } //-------------------------------------------------------------------------------------------------- @@ -73,12 +74,14 @@ void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (changedField == &visualizationMode) + if (changedField == &m_visualizationMode) { updateVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } + + if (m_reservoirView) m_reservoirView->createDisplayModelAndRedraw(); } //-------------------------------------------------------------------------------------------------- @@ -94,15 +97,28 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::updateVisibility() { - if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + if (this->m_visualizationMode() == FAULT_COLOR || this->m_visualizationMode() == CELL_RESULT_MAPPING) { - this->customResultSlot.setUiHidden(true); - this->customResultSlot.setUiChildrenHidden(true); + this->m_customResultSlot.setUiHidden(true); + this->m_customResultSlot.setUiChildrenHidden(true); } else { - this->customResultSlot.setUiHidden(false); - this->customResultSlot.setUiChildrenHidden(false); + this->m_customResultSlot.setUiHidden(false); + this->m_customResultSlot.setUiChildrenHidden(false); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimResultSlot* RimFaultResultSlot::customResultSlot() +{ + if (this->m_visualizationMode() == CUSTOM_RESULT_MAPPING) + { + return this->m_customResultSlot(); } + + return NULL; } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 2fa532d58a..4ff776ed04 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSlot : public caf::PdmObject +class RimFaultResultSlot : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -45,17 +45,18 @@ class RimFaultResultSlot : public caf::PdmObject virtual ~RimFaultResultSlot(); void setReservoirView(RimReservoirView* ownerReservoirView); - - caf::PdmField customResultSlot; + + RimResultSlot* customResultSlot(); + void updateVisibility(); protected: virtual void initAfterRead(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - void updateVisibility(); + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > m_visualizationMode; + caf::PdmField m_customResultSlot; -private: - caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + caf::PdmPointer m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index bba2901cc8..42da59e136 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -102,10 +102,8 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&cellFaultResult, "GridCellFaultResult", "Fault Cell Result", ":/CellResult.png", "", ""); - cellFaultResult = new RimFaultResultSlot(); - cellFaultResult.setUiHidden(true); - + CAF_PDM_InitFieldNoDefault(&faultResult, "GridCellFaultResult", "Fault Result", ":/CellResult.png", "", ""); + faultResult = new RimFaultResultSlot(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); @@ -167,7 +165,7 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); - this->cellFaultResult()->setReservoirView(this); + this->faultResult()->setReservoirView(this); m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); @@ -182,7 +180,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { - delete this->cellFaultResult(); + delete this->faultResult(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -521,10 +519,7 @@ void RimReservoirView::createDisplayModel() // Find the number of time frames the animation needs to show the requested data. - if (this->cellResult()->hasDynamicResult() - || this->propertyFilterCollection()->hasActiveDynamicFilters() - || this->wellCollection->hasVisibleWellPipes() - || this->cellResult()->isTernarySaturationSelected()) + if (isTimeStepDependentDataVisible()) { CVF_ASSERT(currentGridCellResults()); @@ -972,7 +967,7 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { - this->cellFaultResult()->setReservoirView(this); + this->faultResult()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); @@ -1392,45 +1387,76 @@ void RimReservoirView::updateLegends() RigCaseCellResultsData* results = eclipseCase->results(porosityModel); CVF_ASSERT(results); - if (this->cellResult()->hasResult()) + updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); + if (this->faultResult()->customResultSlot()) + { + updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResult()->customResultSlot(), results); + } + + if (this->cellEdgeResult()->hasResult()) { double globalMin, globalMax; double globalPosClosestToZero, globalNegClosestToZero; - results->minMaxCellScalarValues(this->cellResult()->gridScalarIndex(), globalMin, globalMax); - results->posNegClosestToZero(this->cellResult()->gridScalarIndex(), globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); + this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); + + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); + + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); + this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); + } + else + { + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirView::updateMinMaxValuesAndAddLegendToView(QString legendLabel, RimResultSlot* resultSlot, RigCaseCellResultsData* cellResultsData) +{ + if (resultSlot->hasResult()) + { + double globalMin, globalMax; + double globalPosClosestToZero, globalNegClosestToZero; + cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), globalMin, globalMax); + cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), globalPosClosestToZero, globalNegClosestToZero); double localMin, localMax; double localPosClosestToZero, localNegClosestToZero; - if (this->cellResult()->hasDynamicResult()) + if (resultSlot->hasDynamicResult()) { - results->minMaxCellScalarValues(this->cellResult()->gridScalarIndex(), m_currentTimeStep, localMin, localMax); - results->posNegClosestToZero(this->cellResult()->gridScalarIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); + cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), m_currentTimeStep, localMin, localMax); + cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); } else { - localMin = globalMin; - localMax = globalMax; + localMin = globalMin; + localMax = globalMax; - localPosClosestToZero = globalPosClosestToZero; - localNegClosestToZero = globalNegClosestToZero; + localPosClosestToZero = globalPosClosestToZero; + localNegClosestToZero = globalNegClosestToZero; } - this->cellResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); - this->cellResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); + resultSlot->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); + resultSlot->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); - m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); - this->cellResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Cell Results: \n") + this->cellResult()->resultVariable())); + m_viewer->addColorLegendToBottomLeftCorner(resultSlot->legendConfig->legend()); + resultSlot->legendConfig->legend()->setTitle(cvfqt::Utils::toString(legendLabel + resultSlot->resultVariable())); } else { - this->cellResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + resultSlot->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + resultSlot->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); } - size_t maxTimeStepCount = results->maxTimeStepCount(); - if (this->cellResult()->isTernarySaturationSelected() && maxTimeStepCount > 1) + size_t maxTimeStepCount = cellResultsData->maxTimeStepCount(); + if (resultSlot->isTernarySaturationSelected() && maxTimeStepCount > 1) { - RimReservoirCellResultsStorage* gridCellResults = this->cellResult()->currentGridCellResults(); + RimReservoirCellResultsStorage* gridCellResults = resultSlot->currentGridCellResults(); { double globalMin = 0.0; double globalMax = 1.0; @@ -1440,10 +1466,10 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SOIL_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SOIL_IDX, globalMin, globalMax, localMin, localMax); } } @@ -1456,10 +1482,10 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SGAS_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SGAS_IDX, globalMin, globalMax, localMin, localMax); } } @@ -1472,37 +1498,18 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SWAT_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SWAT_IDX, globalMin, globalMax, localMin, localMax); } } - if (this->cellResult()->ternaryLegendConfig->legend()) + if (resultSlot->ternaryLegendConfig->legend()) { - m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->ternaryLegendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(resultSlot->ternaryLegendConfig->legend()); } } - - if (this->cellEdgeResult()->hasResult()) - { - double globalMin, globalMax; - double globalPosClosestToZero, globalNegClosestToZero; - this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); - this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); - - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); - - m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); - this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); - } - else - { - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); - } } //-------------------------------------------------------------------------------------------------- @@ -2044,9 +2051,15 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); + RimResultSlot* resultSlot = this->faultResult()->customResultSlot(); + if (!resultSlot) + { + resultSlot = this->cellResult(); + } + for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, this->cellResult()); + m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, resultSlot); } } @@ -2066,3 +2079,27 @@ void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf: } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimReservoirView::isTimeStepDependentDataVisible() const +{ + if (this->cellResult()->hasDynamicResult()) return true; + + if (this->propertyFilterCollection()->hasActiveDynamicFilters()) return true; + + if (this->wellCollection->hasVisibleWellPipes()) return true; + + if (this->cellResult()->isTernarySaturationSelected()) return true; + + if (this->faultResult->customResultSlot()) + { + if (this->faultResult->customResultSlot()->hasDynamicResult()) return true; + + if (this->faultResult->customResultSlot()->isTernarySaturationSelected()) return true; + } + + return false; +} + diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index f6a5ba96f5..7d9cb3c9e5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -33,6 +33,7 @@ #include "RivReservoirViewPartMgr.h" class RigActiveCellInfo; +class RigCaseCellResultsData; class RigGridBase; class RigGridCellFaceVisibilityFilter; class Rim3dOverlayInfoConfig; @@ -170,6 +171,7 @@ class RimReservoirView : public caf::PdmObject void loadDataAndUpdate(); void createDisplayModelAndRedraw(); void scheduleCreateDisplayModelAndRedraw(); + bool isTimeStepDependentDataVisible() const; void scheduleGeometryRegen(unsigned short geometryType); void scheduleReservoirGridGeometryRegen(); @@ -192,12 +194,12 @@ class RimReservoirView : public caf::PdmObject void updateStaticCellColors(); void updateStaticCellColors(unsigned short geometryType); void updateLegends(); + void updateMinMaxValuesAndAddLegendToView(QString legendLabel, RimResultSlot* resultSlot, RigCaseCellResultsData* cellResultsData); std::vector visibleFaultGeometryTypes() const; void updateFaultForcedVisibility(); void updateFaultColors(); - cvf::ref m_reservoirGridPartManager; cvf::ref m_pipesPartManager; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index e8f7ca5c10..323e1acc4a 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -666,10 +666,7 @@ void RiuMainWindow::refreshAnimationActions() if (app->activeReservoirView()->currentGridCellResults()) { - if (app->activeReservoirView()->cellResult()->hasDynamicResult() - || app->activeReservoirView()->propertyFilterCollection()->hasActiveDynamicFilters() - || app->activeReservoirView()->wellCollection()->hasVisibleWellPipes() - || app->activeReservoirView()->cellResult()->isTernarySaturationSelected()) + if (app->activeReservoirView()->isTimeStepDependentDataVisible()) { std::vector timeStepDates = app->activeReservoirView()->currentGridCellResults()->cellResults()->timeStepDates(0); bool showHoursAndMinutes = false; From 820dbaae5cead9767cd2d60a6aefd6b6346c607a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:05:16 +0200 Subject: [PATCH 034/346] Preferences : Added support for pdm objects recursively --- .../Application/RiaApplication.cpp | 45 ++++++++++++++++--- ApplicationCode/Application/RiaApplication.h | 4 +- .../ProjectDataModel/RimReservoirView.h | 2 +- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 69a330e63f..afbab6c1d6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->cellFaultResult()->updateVisibility(); + riv->faultResult()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); @@ -1236,7 +1236,7 @@ bool RiaApplication::launchProcessForMultipleCases(const QString& program, const //-------------------------------------------------------------------------------------------------- /// Read fields of a Pdm object using QSettings //-------------------------------------------------------------------------------------------------- -void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) +void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object, const QString context) { QSettings settings; std::vector fields; @@ -1247,10 +1247,24 @@ void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) { caf::PdmFieldHandle* fieldHandle = fields[i]; - if (settings.contains(fieldHandle->keyword())) + std::vector children; + fieldHandle->childObjects(&children); + for (size_t childIdx = 0; childIdx < children.size(); childIdx++) { - QVariant val = settings.value(fieldHandle->keyword()); - fieldHandle->setValueFromUi(val); + caf::PdmObject* child = children[childIdx]; + QString subContext = context + child->classKeyword() + "/"; + readFieldsFromApplicationStore(child, subContext); + } + + + if (children.size() == 0) + { + QString key = context + fieldHandle->keyword(); + if (settings.contains(key)) + { + QVariant val = settings.value(key); + fieldHandle->setValueFromUi(val); + } } } } @@ -1258,7 +1272,7 @@ void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) //-------------------------------------------------------------------------------------------------- /// Write fields of a Pdm object using QSettings //-------------------------------------------------------------------------------------------------- -void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object) +void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object, const QString context) { CVF_ASSERT(object); @@ -1272,7 +1286,24 @@ void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object) { caf::PdmFieldHandle* fieldHandle = fields[i]; - settings.setValue(fieldHandle->keyword(), fieldHandle->uiValue()); + std::vector children; + fieldHandle->childObjects(&children); + for (size_t childIdx = 0; childIdx < children.size(); childIdx++) + { + caf::PdmObject* child = children[childIdx]; + QString subContext; + if (context.isEmpty()) + { + subContext = context + child->classKeyword() + "/"; + } + + writeFieldsToApplicationStore(child, subContext); + } + + if (children.size() == 0) + { + settings.setValue(context + fieldHandle->keyword(), fieldHandle->uiValue()); + } } } diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index d15203870f..d724644b94 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -132,8 +132,8 @@ class RiaApplication : public QApplication void terminateProcess(); RiaPreferences* preferences(); - void readFieldsFromApplicationStore(caf::PdmObject* object); - void writeFieldsToApplicationStore(const caf::PdmObject* object); + void readFieldsFromApplicationStore(caf::PdmObject* object, const QString context = ""); + void writeFieldsToApplicationStore(const caf::PdmObject* object, const QString context = ""); void applyPreferences(); cvf::Font* standardFont(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 7d9cb3c9e5..8c7ac5efaa 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField cellFaultResult; + caf::PdmField faultResult; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From d424f2f25fd30e1939896750d9d9d9531394d443 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:49:23 +0200 Subject: [PATCH 035/346] Fault result: Moved result mapping from collection to fault result --- .../RivReservoirFaultsPartMgr.cpp | 70 ++++++++++--------- .../RivReservoirFaultsPartMgr.h | 6 +- .../RivReservoirPartMgr.cpp | 4 +- .../ModelVisualization/RivReservoirPartMgr.h | 4 +- .../RivReservoirViewPartMgr.cpp | 12 ++-- .../ProjectDataModel/RimFaultResultSlot.cpp | 8 +-- .../ProjectDataModel/RimFaultResultSlot.h | 7 +- 7 files changed, 57 insertions(+), 54 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 48e73ff06f..929baaae94 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -27,18 +27,21 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" +#include "RimReservoirView.h" +#include "RimFaultResultSlot.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, const RimFaultCollection* faultCollection) -: m_faultCollection(faultCollection) +RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, RimReservoirView* reservoirView) +: m_reservoirView(reservoirView) { CVF_ASSERT(grid); - if (faultCollection) + if (reservoirView) { + RimFaultCollection* faultCollection = reservoirView->faultCollection(); for (size_t i = 0; i < faultCollection->faults.size(); i++) { m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); @@ -83,26 +86,27 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) { CVF_ASSERT(model != NULL); - if (!m_faultCollection) return; + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + if (!faultCollection) return; - bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); - if (!m_faultCollection->showFaultCollection() && !isShowingGrid) return; + bool isShowingGrid = faultCollection->isGridVisualizationMode(); + if (!faultCollection->showFaultCollection() && !isShowingGrid) return; // Check match between model fault count and fault parts - CVF_ASSERT(m_faultCollection->faults.size() == m_faultParts.size()); + CVF_ASSERT(faultCollection->faults.size() == m_faultParts.size()); cvf::ModelBasicList parts; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - const RimFault* rimFault = m_faultCollection->faults[i]; + const RimFault* rimFault = faultCollection->faults[i]; cvf::ref rivFaultPart = m_faultParts[i]; CVF_ASSERT(rivFaultPart.notNull()); // Parts that is overridden by the grid settings bool forceDisplayOfFault = false; - if (!m_faultCollection->showFaultsOutsideFilters()) + if (!faultCollection->showFaultsOutsideFilters()) { forceDisplayOfFault = isShowingGrid; } @@ -114,17 +118,17 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if (rimFault->showFault() || forceDisplayOfFault) { - if (m_faultCollection->showFaultFaces() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || forceDisplayOfFault) { rivFaultPart->appendNativeFaultFacesToModel(&parts); } - if (m_faultCollection->showOppositeFaultFaces() || forceDisplayOfFault) + if (faultCollection->showOppositeFaultFaces() || forceDisplayOfFault) { rivFaultPart->appendOppositeFaultFacesToModel(&parts); } - if (m_faultCollection->showFaultFaces() || m_faultCollection->showOppositeFaultFaces() || m_faultCollection->showNNCs() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || faultCollection->showNNCs() || forceDisplayOfFault) { rivFaultPart->appendMeshLinePartsToModel(&parts); } @@ -132,9 +136,9 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) // Parts that is not overridden by the grid settings - if (rimFault->showFault() && m_faultCollection->showFaultCollection()) + if (rimFault->showFault() && faultCollection->showFaultCollection()) { - if (m_faultCollection->showNNCs()) + if (faultCollection->showNNCs()) { rivFaultPart->appendNNCFacesToModel(&parts); } @@ -166,26 +170,22 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { - bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); + if (!m_reservoirView) return; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + CVF_ASSERT(faultCollection); + + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - RimFault* rimFault = m_faultCollection->faults[i]; + RimFault* rimFault = faultCollection->faults[i]; - if (isShowingGrid) + if (m_reservoirView->faultResult()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + m_faultParts[i]->applySingleColorEffect(); } else { - if (m_faultCollection->showResultsOnFaults()) - { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); - } - else - { - m_faultParts[i]->applySingleColorEffect(); - } + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } } } @@ -207,21 +207,23 @@ void RivReservoirFaultsPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, void RivReservoirFaultsPartMgr::appendLabelPartsToModel(cvf::ModelBasicList* model) { CVF_ASSERT(model != NULL); + if (!m_reservoirView) return; - if (!m_faultCollection) return; + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + CVF_ASSERT(faultCollection); - if (!m_faultCollection->showFaultCollection()) return; + if (!faultCollection->showFaultCollection()) return; - if (!m_faultCollection->showFaultLabel() ) return; + if (!faultCollection->showFaultLabel() ) return; // Check match between model fault count and fault parts - CVF_ASSERT(m_faultCollection->faults.size() == m_faultParts.size()); + CVF_ASSERT(faultCollection->faults.size() == m_faultParts.size()); cvf::ModelBasicList parts; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - const RimFault* rimFault = m_faultCollection->faults[i]; + const RimFault* rimFault = faultCollection->faults[i]; cvf::ref rivFaultPart = m_faultParts[i]; CVF_ASSERT(rivFaultPart.notNull()); diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h index 105b20468f..3bc9c23587 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h @@ -31,7 +31,7 @@ namespace cvf class RimResultSlot; class RimCellEdgeResultSlot; -class RimFaultCollection; +class RimReservoirView; //================================================================================================== /// @@ -39,7 +39,7 @@ class RimFaultCollection; class RivReservoirFaultsPartMgr : public cvf::Object { public: - RivReservoirFaultsPartMgr(const RigMainGrid* grid, const RimFaultCollection* faultCollection); + RivReservoirFaultsPartMgr(const RigMainGrid* grid, RimReservoirView* reservoirView); ~RivReservoirFaultsPartMgr(); void setTransform(cvf::Transform* scaleTransform); @@ -59,7 +59,7 @@ class RivReservoirFaultsPartMgr : public cvf::Object private: cvf::ref m_scaleTransform; - const RimFaultCollection* m_faultCollection; + caf::PdmPointer m_reservoirView; cvf::Collection m_faultParts; bool m_forceVisibility; }; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 806bd08023..60dae98bd0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -28,7 +28,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection) +void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, RimReservoirView* reservoirView) { m_allGrids.clear(); @@ -44,7 +44,7 @@ void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, c if (eclipseCase->mainGrid()) { // Faults read from file are present only on main grid - m_faultsPartMgr = new RivReservoirFaultsPartMgr(eclipseCase->mainGrid(), faultCollection); + m_faultsPartMgr = new RivReservoirFaultsPartMgr(eclipseCase->mainGrid(), reservoirView); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index 7f07979603..6f7075aeac 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -33,7 +33,7 @@ class RimResultSlot; class RimCellEdgeResultSlot; class RivGridPartMgr; class RigCaseData; -class RimFaultCollection; +class RimReservoirView; //================================================================================================== /// @@ -45,7 +45,7 @@ class RimFaultCollection; class RivReservoirPartMgr: public cvf::Object { public: - void clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection); + void clearAndSetReservoir(const RigCaseData* eclipseCase, RimReservoirView* reservoirView); void setTransform(cvf::Transform* scaleTransform); void setCellVisibility(size_t gridIndex, cvf::UByteArray* cellVisibilities ); void setFaultForceVisibility(bool isGeneratedByFilter); diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 8f8e095c3e..8346961b45 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -152,7 +152,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom m_propFilteredGeometryFramesNeedsRegen[i] = true; if (m_propFilteredGeometryFrames[i].notNull()) { - m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView); m_propFilteredGeometryFrames[i]->setTransform(m_scaleTransform.p()); } } @@ -164,7 +164,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom m_propFilteredWellGeometryFramesNeedsRegen[i] = true; if (m_propFilteredWellGeometryFrames[i].notNull()) { - m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView); m_propFilteredWellGeometryFrames[i]->setTransform(m_scaleTransform.p()); } } @@ -172,7 +172,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom else { m_geometriesNeedsRegen[geomType] = true; - m_geometries[geomType].clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_geometries[geomType].clearAndSetReservoir(eclipseCase, m_reservoirView); m_geometries[geomType].setTransform(m_scaleTransform.p()); } } @@ -239,7 +239,7 @@ void RivReservoirViewPartMgr::appendDynamicGeometryPartsToModel(cvf::ModelBasicL void RivReservoirViewPartMgr::createGeometry(ReservoirGeometryCacheType geometryType) { RigCaseData* res = m_reservoirView->eclipseCase()->reservoirData(); - m_geometries[geometryType].clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_geometries[geometryType].clearAndSetReservoir(res, m_reservoirView); m_geometries[geometryType].setTransform(m_scaleTransform.p()); std::vector grids; @@ -395,7 +395,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredNoneWellCellGeometry(size_t if ( m_propFilteredGeometryFrames[frameIndex].isNull()) m_propFilteredGeometryFrames[frameIndex] = new RivReservoirPartMgr; - m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView); m_propFilteredGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p()); std::vector grids; @@ -472,7 +472,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredWellGeometry(size_t frameInd if ( m_propFilteredWellGeometryFrames[frameIndex].isNull()) m_propFilteredWellGeometryFrames[frameIndex] = new RivReservoirPartMgr; - m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView); m_propFilteredWellGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p()); std::vector grids; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 249216a6fb..bb459ed023 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -45,7 +45,7 @@ RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&m_visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); m_customResultSlot = new RimResultSlot(); @@ -74,7 +74,7 @@ void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (changedField == &m_visualizationMode) + if (changedField == &visualizationMode) { updateVisibility(); @@ -97,7 +97,7 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::updateVisibility() { - if (this->m_visualizationMode() == FAULT_COLOR || this->m_visualizationMode() == CELL_RESULT_MAPPING) + if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) { this->m_customResultSlot.setUiHidden(true); this->m_customResultSlot.setUiChildrenHidden(true); @@ -114,7 +114,7 @@ void RimFaultResultSlot::updateVisibility() //-------------------------------------------------------------------------------------------------- RimResultSlot* RimFaultResultSlot::customResultSlot() { - if (this->m_visualizationMode() == CUSTOM_RESULT_MAPPING) + if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) { return this->m_customResultSlot(); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 4ff776ed04..c8d57151b6 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -43,10 +43,12 @@ class RimFaultResultSlot : public caf::PdmObject public: RimFaultResultSlot(); virtual ~RimFaultResultSlot(); - + void setReservoirView(RimReservoirView* ownerReservoirView); - RimResultSlot* customResultSlot(); + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + + RimResultSlot* customResultSlot(); void updateVisibility(); protected: @@ -54,7 +56,6 @@ class RimFaultResultSlot : public caf::PdmObject virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - caf::PdmField< caf::AppEnum< FaultVisualizationMode > > m_visualizationMode; caf::PdmField m_customResultSlot; caf::PdmPointer m_reservoirView; From baa8e2518108d919d2cdf3447d2e66cd7a4882a2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:53:38 +0200 Subject: [PATCH 036/346] Added missing pointer check --- .../ModelVisualization/RivReservoirFaultsPartMgr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 929baaae94..797e6244a4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -42,9 +42,12 @@ RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, R if (reservoirView) { RimFaultCollection* faultCollection = reservoirView->faultCollection(); - for (size_t i = 0; i < faultCollection->faults.size(); i++) + if (faultCollection) { - m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); + for (size_t i = 0; i < faultCollection->faults.size(); i++) + { + m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); + } } } From 1cd32ee0d3e462ccce75f3e1f4e51a1774f73de1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 11:09:48 +0200 Subject: [PATCH 037/346] Fault result : Renamed file and improved interface --- .../Application/RiaApplication.cpp | 4 +- .../RivReservoirFaultsPartMgr.cpp | 4 +- .../ProjectDataModel/CMakeLists_files.cmake | 4 +- ...ultSlot.cpp => RimFaultResultSettings.cpp} | 46 +++++++++---------- ...tResultSlot.h => RimFaultResultSettings.h} | 15 +++--- .../ProjectDataModel/RimReservoirView.cpp | 31 +++++++------ .../ProjectDataModel/RimReservoirView.h | 4 +- 7 files changed, 56 insertions(+), 52 deletions(-) rename ApplicationCode/ProjectDataModel/{RimFaultResultSlot.cpp => RimFaultResultSettings.cpp} (64%) rename ApplicationCode/ProjectDataModel/{RimFaultResultSlot.h => RimFaultResultSettings.h} (82%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index afbab6c1d6..b6c68ecdba 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,7 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->faultResult()->updateVisibility(); + riv->faultResultSettings()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 797e6244a4..8176d31b1c 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -28,7 +28,7 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" #include "RimReservoirView.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" //-------------------------------------------------------------------------------------------------- @@ -182,7 +182,7 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot { RimFault* rimFault = faultCollection->faults[i]; - if (m_reservoirView->faultResult()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index c9cb08a878..656f19e48e 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,7 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h -${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -95,7 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp -${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp similarity index 64% rename from ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp rename to ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index bb459ed023..548b86f878 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -27,28 +27,28 @@ namespace caf { template<> - void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() + void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() { - addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSlot::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); - addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSlot::CELL_RESULT_MAPPING); + addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSettings::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); + addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSettings::CELL_RESULT_MAPPING); } } -CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); +CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSlot::RimFaultResultSlot() +RimFaultResultSettings::RimFaultResultSettings() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); - m_customResultSlot = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); + m_customFaultResult = new RimResultSlot(); updateVisibility(); } @@ -56,23 +56,23 @@ RimFaultResultSlot::RimFaultResultSlot() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSlot::~RimFaultResultSlot() +RimFaultResultSettings::~RimFaultResultSettings() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) +void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; - m_customResultSlot->setReservoirView(ownerReservoirView); + m_customFaultResult->setReservoirView(ownerReservoirView); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { if (changedField == &visualizationMode) { @@ -87,7 +87,7 @@ void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::initAfterRead() +void RimFaultResultSettings::initAfterRead() { updateVisibility(); } @@ -95,28 +95,28 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::updateVisibility() +void RimFaultResultSettings::updateVisibility() { if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) { - this->m_customResultSlot.setUiHidden(true); - this->m_customResultSlot.setUiChildrenHidden(true); + this->m_customFaultResult.setUiHidden(true); + this->m_customFaultResult.setUiChildrenHidden(true); } else { - this->m_customResultSlot.setUiHidden(false); - this->m_customResultSlot.setUiChildrenHidden(false); + this->m_customFaultResult.setUiHidden(false); + this->m_customFaultResult.setUiChildrenHidden(false); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimResultSlot* RimFaultResultSlot::customResultSlot() +RimResultSlot* RimFaultResultSettings::customFaultResult() { if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) { - return this->m_customResultSlot(); + return this->m_customFaultResult(); } return NULL; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h similarity index 82% rename from ApplicationCode/ProjectDataModel/RimFaultResultSlot.h rename to ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index c8d57151b6..6c3b68e462 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSlot : public caf::PdmObject +class RimFaultResultSettings : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -41,23 +41,22 @@ class RimFaultResultSlot : public caf::PdmObject }; public: - RimFaultResultSlot(); - virtual ~RimFaultResultSlot(); + RimFaultResultSettings(); + virtual ~RimFaultResultSettings(); void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; - RimResultSlot* customResultSlot(); - void updateVisibility(); + RimResultSlot* customFaultResult(); + void updateVisibility(); protected: virtual void initAfterRead(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - caf::PdmField m_customResultSlot; - - caf::PdmPointer m_reservoirView; + caf::PdmField m_customFaultResult; + caf::PdmPointer m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 42da59e136..fa9b2a2ed9 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,7 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -102,8 +102,8 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResult, "GridCellFaultResult", "Fault Result", ":/CellResult.png", "", ""); - faultResult = new RimFaultResultSlot(); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/CellResult.png", "", ""); + faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); @@ -165,7 +165,7 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); - this->faultResult()->setReservoirView(this); + this->faultResultSettings()->setReservoirView(this); m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); @@ -180,7 +180,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { - delete this->faultResult(); + delete this->faultResultSettings(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -967,7 +967,7 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { - this->faultResult()->setReservoirView(this); + this->faultResultSettings()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); @@ -1388,9 +1388,10 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResult()->customResultSlot()) + if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) { - updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResult()->customResultSlot(), results); + CVF_ASSERT(this->faultResultSettings()->customFaultResult()); + updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } if (this->cellEdgeResult()->hasResult()) @@ -2051,8 +2052,12 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = this->faultResult()->customResultSlot(); - if (!resultSlot) + RimResultSlot* resultSlot = NULL; + if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + { + resultSlot = this->faultResultSettings()->customFaultResult(); + } + else { resultSlot = this->cellResult(); } @@ -2093,11 +2098,11 @@ bool RimReservoirView::isTimeStepDependentDataVisible() const if (this->cellResult()->isTernarySaturationSelected()) return true; - if (this->faultResult->customResultSlot()) + if (this->faultResultSettings->customFaultResult()) { - if (this->faultResult->customResultSlot()->hasDynamicResult()) return true; + if (this->faultResultSettings->customFaultResult()->hasDynamicResult()) return true; - if (this->faultResult->customResultSlot()->isTernarySaturationSelected()) return true; + if (this->faultResultSettings->customFaultResult()->isTernarySaturationSelected()) return true; } return false; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 8c7ac5efaa..4ae47bf513 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -44,7 +44,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; -class RimFaultResultSlot; +class RimFaultResultSettings; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField faultResult; + caf::PdmField faultResultSettings; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From 0590e56fd5b7bbb30b8833a2586d344b5b98036a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 11:54:07 +0200 Subject: [PATCH 038/346] Recent files : Set last opened file first, remove file if load fails --- .../UserInterface/RiuMainWindow.cpp | 28 +++++++++++++++++-- ApplicationCode/UserInterface/RiuMainWindow.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 323e1acc4a..5e2b857ac4 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -957,14 +957,24 @@ void RiuMainWindow::slotOpenRecentFile() if (action) { QString filename = action->data().toString(); + bool loadingSucceded = false; if (filename.contains(".rsp", Qt::CaseInsensitive) || filename.contains(".rip", Qt::CaseInsensitive) ) { - RiaApplication::instance()->loadProject(action->data().toString()); + loadingSucceded = RiaApplication::instance()->loadProject(action->data().toString()); } else if ( filename.contains(".egrid", Qt::CaseInsensitive) || filename.contains(".grid", Qt::CaseInsensitive) ) { - RiaApplication::instance()->openEclipseCaseFromFile(filename); + loadingSucceded = RiaApplication::instance()->openEclipseCaseFromFile(filename); + } + + if (loadingSucceded) + { + addRecentFiles(filename); + } + else + { + removeRecentFiles(filename); } } } @@ -1009,6 +1019,20 @@ void RiuMainWindow::addRecentFiles(const QString& file) } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::removeRecentFiles(const QString& file) +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(file); + + settings.setValue("recentFileList", files); + + updateRecentFileActions(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 54da53911b..0e2aa40bee 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -113,6 +113,7 @@ class RiuMainWindow : public QMainWindow void updateRecentFileActions(); void addRecentFiles(const QString& file); + void removeRecentFiles(const QString& file); QMdiSubWindow* findMdiSubWindow(RiuViewer* viewer); From 8a360e0f0a83be8b03e51f8400bb51e86f47260b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 12:23:15 +0200 Subject: [PATCH 039/346] Recent files : Show full path in tooltip --- .../UserInterface/RiuMainWindow.cpp | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 5e2b857ac4..a5c475fcfe 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -323,13 +323,53 @@ void RiuMainWindow::createActions() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class ToolTipableMenu : public QMenu +{ +public: + ToolTipableMenu( QWidget * parent ) : QMenu( parent ) {}; + + bool event(QEvent* e) + { + if (e->type() == QEvent::ToolTip) + { + QHelpEvent* he = dynamic_cast(e); + QAction* act = actionAt(he->pos()); + if (act) + { + // Remove ampersand as this is used to define shortcut key + QString actionTextWithoutAmpersand = act->text().remove("&"); + + if (actionTextWithoutAmpersand != act->toolTip()) + { + QToolTip::showText(he->globalPos(), act->toolTip(), this); + } + + return true; + } + } + else if (e->type() == QEvent::Paint && QToolTip::isVisible()) + { + QToolTip::hideText(); + } + + return QMenu::event(e); + } +}; + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuMainWindow::createMenus() { // File menu - QMenu* fileMenu = menuBar()->addMenu("&File"); + QMenu* fileMenu = new ToolTipableMenu(menuBar()); + fileMenu->setTitle("&File"); + + menuBar()->addMenu(fileMenu); fileMenu->addAction(m_openProjectAction); fileMenu->addAction(m_openLastUsedProjectAction); @@ -993,6 +1033,7 @@ void RiuMainWindow::updateRecentFileActions() QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); m_recentFileActions[i]->setText(text); m_recentFileActions[i]->setData(files[i]); + m_recentFileActions[i]->setToolTip(files[i]); m_recentFileActions[i]->setVisible(true); } for (int j = numRecentFiles; j < MaxRecentFiles; ++j) From 28e7e8efc9ae817aa30e778cb96ade3923159f46 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 14:04:37 +0200 Subject: [PATCH 040/346] Added special handling to expand an item in tree view --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 12 ++++++++++++ ApplicationCode/UserInterface/RiuMainWindow.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index a5c475fcfe..e6cab5e794 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -2010,3 +2010,15 @@ void RiuMainWindow::appendActionsContextMenuForPdmObject(caf::PdmObject* pdmObje menu->addAction(m_openMultipleEclipseCasesAction); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::setExpanded(const caf::PdmObject* pdmObject, bool expanded) +{ + QModelIndex mi = m_treeModelPdm->getModelIndexFromPdmObject(pdmObject); + if (m_treeView && mi.isValid()) + { + m_treeView->setExpanded(mi, expanded); + } +} diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 0e2aa40bee..42e1a7c8f2 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -97,7 +97,8 @@ class RiuMainWindow : public QMainWindow void appendActionsContextMenuForPdmObject(caf::PdmObject* pdmObject, QMenu* menu); void refreshDrawStyleActions(); - + + void setExpanded(const caf::PdmObject* pdmObject, bool expanded); protected: virtual void closeEvent(QCloseEvent* event); From bc23b044682a46e08f5c68bfd428402330841e0b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 14:05:40 +0200 Subject: [PATCH 041/346] Fault result : Moved config from FaultCollection to FaultResultSettings --- ApplicationCode/Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 4 ++-- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 5 +++-- .../ProjectDataModel/RimFaultCollection.cpp | 14 ++------------ .../ProjectDataModel/RimFaultCollection.h | 4 ---- .../ProjectDataModel/RimFaultResultSettings.cpp | 11 +++++++---- .../ProjectDataModel/RimFaultResultSettings.h | 2 ++ 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index b6c68ecdba..665e3af43a 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2066,7 +2066,7 @@ void RiaApplication::regressionTestConfigureProject() } riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); - riv->faultCollection->showResultsOnFaults.setValueFromUi(true); + riv->faultResultSettings->visualizationMode.setValueFromUi(RimFaultResultSettings::CELL_RESULT_MAPPING); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 8176d31b1c..5fc6bcb431 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -131,7 +131,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) rivFaultPart->appendOppositeFaultFacesToModel(&parts); } - if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || faultCollection->showNNCs() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || m_reservoirView->faultResultSettings()->showNNCs() || forceDisplayOfFault) { rivFaultPart->appendMeshLinePartsToModel(&parts); } @@ -141,7 +141,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if (rimFault->showFault() && faultCollection->showFaultCollection()) { - if (faultCollection->showNNCs()) + if (m_reservoirView->faultResultSettings()->showNNCs()) { rivFaultPart->appendNNCFacesToModel(&parts); } diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index f08a803814..f35932f066 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -23,12 +23,13 @@ #include "RimCase.h" #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimFaultResultSettings.h" #include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimWellCollection.h" #include "RiuViewer.h" -#include "RimFaultCollection.h" CAF_PDM_SOURCE_INIT(Rim3dOverlayInfoConfig, "View3dOverlayInfoConfig"); @@ -159,7 +160,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("" "
MinP10 Mean P90 Max
%1 %2 %3 %4 %5
").arg(min).arg(p10).arg(mean).arg(p90).arg(max); - if (m_reservoirView->faultCollection()->showResultsOnFaults()) + if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSettings::FAULT_COLOR) { QString faultMapping; bool isShowingGrid = m_reservoirView->faultCollection()->isGridVisualizationMode(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index e634f26644..8aac2a264f 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -57,13 +57,8 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showFaultCollection, "Active", true, "Active", "", "", ""); showFaultCollection.setUiHidden(true); - CAF_PDM_InitField(&showGeometryDetectedFaults, "ShowGeometryDetectedFaults", false, "Show geometry detected faults", "", "", ""); - showGeometryDetectedFaults.setUiHidden(true); - CAF_PDM_InitField(&showFaultFaces, "ShowFaultFaces", true, "Show defined faces", "", "", ""); CAF_PDM_InitField(&showOppositeFaultFaces, "ShowOppositeFaultFaces", true, "Show opposite faces", "", "", ""); - CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitField(&showResultsOnFaults, "ShowResultsOnFaults", true, "Show results on faults", "", "", ""); CAF_PDM_InitField(&showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); CAF_PDM_InitField(&faultResult, "FaultFaceCulling", caf::AppEnum(RimFaultCollection::FAULT_BACK_FACE_CULLING), "Dynamic Face Selection", "", "", ""); @@ -101,16 +96,13 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel m_reservoirView->scheduleReservoirGridGeometryRegen(); } - if (&showGeometryDetectedFaults == changedField || - &showFaultFaces == changedField || + if (&showFaultFaces == changedField || &showOppositeFaultFaces == changedField || - &showNNCs == changedField || &showFaultCollection == changedField || &showFaultLabel == changedField || &showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || - &faultResult == changedField || - &showResultsOnFaults == changedField + &faultResult == changedField ) { if (m_reservoirView) @@ -266,8 +258,6 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi caf::PdmUiGroup* adv = uiOrdering.addNewGroup("Fault Options"); adv->add(&showFaultsOutsideFilters); - adv->add(&showResultsOnFaults); - adv->add(&showNNCs); caf::PdmUiGroup* ffviz = uiOrdering.addNewGroup("Fault Face Visibility"); ffviz->add(&showFaultFaces); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 39b1fe982a..b5fbc7b759 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -58,13 +58,9 @@ class RimFaultCollection : public caf::PdmObject bool isGridVisualizationMode() const; - caf::PdmField showGeometryDetectedFaults; // Obsolete, to be removed - caf::PdmField showFaultFaces; caf::PdmField showOppositeFaultFaces; caf::PdmField showFaultsOutsideFilters; - caf::PdmField showNNCs; - caf::PdmField showResultsOnFaults; caf::PdmField > faultResult; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index 548b86f878..ab1bd59fe4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -46,11 +46,12 @@ RimFaultResultSettings::RimFaultResultSettings() CAF_PDM_InitObject("Fault Result Slot", "", "", ""); CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); - m_customFaultResult = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); + m_customFaultResult = new RimResultSlot(); - updateVisibility(); + updateVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -79,9 +80,11 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed updateVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + + RiuMainWindow::instance()->setExpanded(this, true); } - if (m_reservoirView) m_reservoirView->createDisplayModelAndRedraw(); + if (m_reservoirView) m_reservoirView->scheduleCreateDisplayModelAndRedraw(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 6c3b68e462..05aa4f0dad 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -47,6 +47,8 @@ class RimFaultResultSettings : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + caf::PdmField showNNCs; + RimResultSlot* customFaultResult(); void updateVisibility(); From 66808a5e670947a62869625e9ae3c1eeb75dcdc3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 07:53:15 +0200 Subject: [PATCH 042/346] Fault result: Updated icon --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index fa9b2a2ed9..c9472be7d4 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -102,7 +102,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/CellResult.png", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/draw_style_faults_24x24.png", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); From 0f6e7891378301fa8d024d752ba80f8316dc826f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 08:15:22 +0200 Subject: [PATCH 043/346] Preferences : Updated default values --- ApplicationCode/Application/RiaPreferences.cpp | 2 +- ApplicationCode/FileInterface/RifReaderSettings.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 337084d979..2e36180a84 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -42,7 +42,7 @@ RiaPreferences::RiaPreferences(void) octaveExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); octaveExecutable.setUiLabelPosition(caf::PdmUiItemInfo::TOP); - CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", true, "Show text header when executing scripts", "", "", ""); + CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", false, "Show text header when executing scripts", "", "", ""); octaveShowHeaderInfoWhenExecutingScripts.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "ssihub Address", "", "", ""); diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp index e3a743d188..c2b05aaa4e 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.cpp +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -30,13 +30,13 @@ RifReaderSettings::RifReaderSettings() { CAF_PDM_InitObject("RifReaderSettings", "", "", ""); - CAF_PDM_InitField(&importFaults, "importFaults", false, "Import faults", "", "", ""); + CAF_PDM_InitField(&importFaults, "importFaults", true, "Import faults", "", "", ""); importFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", false, "Import simulation wells", "", "", ""); + CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", true, "Import simulation wells", "", "", ""); importSimulationWellData.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", false, "Import NNCs", "", "", ""); + CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", true, "Import NNCs", "", "", ""); importNNCs.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); } From b0d3df3a8ce42afb27f81c6a8cfd3f2dd5e7885c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 08:46:46 +0200 Subject: [PATCH 044/346] Ternary legend : Added title --- .../RivTernarySaturationOverlayItem.cpp | 41 +++++++++++++++---- .../RivTernarySaturationOverlayItem.h | 7 +++- .../ProjectDataModel/RimReservoirView.cpp | 2 + .../RimTernaryLegendConfig.cpp | 2 +- .../ProjectDataModel/RimTernaryLegendConfig.h | 3 +- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 651297c813..2160d0eb53 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -121,11 +121,25 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con cvf::TextDrawer textDrawer(m_font.p()); textDrawer.setTextColor(m_textColor); + float lineHeightInPixels = 10; + + float textPosY = static_cast(size.y() - 10); + for (size_t it = 0; it < m_titleStrings.size(); it++) + { + cvf::Vec2f pos(5, textPosY); + textDrawer.addText(m_titleStrings[it], pos); + + textPosY -= lineHeightInPixels; + } + + textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY)); + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY - lineHeightInPixels)); + textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); textDrawer.addText(m_swatRange, cvf::Vec2f(0.0, 0.0)); textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - 25), 10.0)); - + float soilRangePos = static_cast(size.x() - 40); if (m_soilRange.size() < 6) { @@ -133,12 +147,9 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con } textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); - textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), static_cast(size.y() - 10))); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), static_cast(size.y() - 20))); - textDrawer.renderSoftware(oglContext, camera); - renderAxisImmediateMode(oglContext); + renderAxisImmediateMode(textPosY - lineHeightInPixels, oglContext); CVF_CHECK_OGL(oglContext); } @@ -148,7 +159,7 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con //-------------------------------------------------------------------------------------------------- /// Draw the axis using immediate mode OpenGL //-------------------------------------------------------------------------------------------------- -void RivTernarySaturationOverlayItem::renderAxisImmediateMode(cvf::OpenGLContext* oglContext) +void RivTernarySaturationOverlayItem::renderAxisImmediateMode(float upperBoundY, cvf::OpenGLContext* oglContext) { #ifdef CVF_OPENGL_ES CVF_UNUSED(layout); @@ -166,7 +177,7 @@ void RivTernarySaturationOverlayItem::renderAxisImmediateMode(cvf::OpenGLContext cvf::Color3ub colC(cvf::Color3::RED); float lowerBoundY = 20; - float upperBoundY = static_cast(m_size.y() - 20); + //float upperBoundY = static_cast(m_size.y() - 20); cvf::Vec3f a(0, lowerBoundY, 0); cvf::Vec3f b(static_cast(m_size.x()), lowerBoundY, 0); @@ -219,4 +230,20 @@ void RivTernarySaturationOverlayItem::setRangeText(const cvf::String& soilRange, m_swatRange = swatRange; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernarySaturationOverlayItem::setTitle(const cvf::String& title) +{ + // Title + if (title.isEmpty()) + { + m_titleStrings.clear(); + } + else + { + m_titleStrings = title.split("\n"); + } +} + diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h index ca145cf496..a016060560 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h @@ -48,12 +48,13 @@ class RivTernarySaturationOverlayItem : public cvf::OverlayItem virtual void renderSoftware(cvf::OpenGLContext* oglContext, const cvf::Vec2i& position, const cvf::Vec2ui& size); void setSize(const cvf::Vec2ui& size); - void setAxisLabelsColor(const cvf::Color3f& color); + void setTitle(const cvf::String& title); + private: void render(cvf::OpenGLContext* oglContext, const cvf::Vec2i& position, const cvf::Vec2ui& size, bool software); - void renderAxisImmediateMode(cvf::OpenGLContext* oglContext); + void renderAxisImmediateMode(float upperY, cvf::OpenGLContext* oglContext); private: cvf::Color3f m_textColor; // Text color @@ -64,5 +65,7 @@ class RivTernarySaturationOverlayItem : public cvf::OverlayItem cvf::String m_swatRange; cvf::Vec2ui m_size; // Pixel size of draw area + + std::vector m_titleStrings; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index c9472be7d4..ca8ada6732 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -40,6 +40,7 @@ #include "RiuViewer.h" #include "RivReservoirPipesPartMgr.h" #include "RivWellPathCollectionPartMgr.h" +#include "RivTernarySaturationOverlayItem.h" #include "cafCadNavigation.h" #include "cafCeetronPlusNavigation.h" @@ -1508,6 +1509,7 @@ void RimReservoirView::updateMinMaxValuesAndAddLegendToView(QString legendLabel, if (resultSlot->ternaryLegendConfig->legend()) { + resultSlot->ternaryLegendConfig->legend()->setTitle(cvfqt::Utils::toString(legendLabel)); m_viewer->addColorLegendToBottomLeftCorner(resultSlot->ternaryLegendConfig->legend()); } } diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 4f5a9bcde6..6da31598c9 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -298,7 +298,7 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::OverlayItem* RimTernaryLegendConfig::legend() +RivTernarySaturationOverlayItem* RimTernaryLegendConfig::legend() { return m_legend.p(); } diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h index 6697441da9..79c94d5d11 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -69,7 +69,8 @@ class RimTernaryLegendConfig : public caf::PdmObject void ternaryRanges(double& soilLower, double& soilUpper, double& sgasLower, double& sgasUpper, double& swatLower, double& swatUpper) const; void recreateLegend(); - cvf::OverlayItem* legend(); + + RivTernarySaturationOverlayItem* legend(); protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); From c310b702e13a179501e3a39bbbed2951ded1fb54 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 09:40:35 +0200 Subject: [PATCH 045/346] Fault result : Use checkbox to enable custom fault visualization When checkbox is disabled, faults are visualized using current cell visualization. When checkbox is activated, fault colors or custom fault result is active --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 3 ++- .../RimFaultResultSettings.cpp | 25 +++++++++++++++---- .../ProjectDataModel/RimFaultResultSettings.h | 9 ++++--- .../ProjectDataModel/RimReservoirView.cpp | 11 +++----- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 665e3af43a..023836cbd6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2066,7 +2066,7 @@ void RiaApplication::regressionTestConfigureProject() } riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); - riv->faultResultSettings->visualizationMode.setValueFromUi(RimFaultResultSettings::CELL_RESULT_MAPPING); + riv->faultResultSettings->showCustomFaultResult.setValueFromUi(false); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 5fc6bcb431..f1284c9a3f 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -182,7 +182,8 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot { RimFault* rimFault = faultCollection->faults[i]; - if (m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->showCustomFaultResult() && + m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index ab1bd59fe4..3da4e842c4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -30,9 +30,8 @@ namespace caf void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() { addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSettings::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSettings::CELL_RESULT_MAPPING); + setDefault(RimFaultResultSettings::FAULT_COLOR); } } @@ -45,7 +44,10 @@ RimFaultResultSettings::RimFaultResultSettings() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); + showCustomFaultResult.setUiHidden(true); + + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::FAULT_COLOR), "Fault Color Mapping", "", "", ""); CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); @@ -75,6 +77,11 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { + if (&showCustomFaultResult == changedField) + { + this->updateUiIconFromState(showCustomFaultResult); + } + if (changedField == &visualizationMode) { updateVisibility(); @@ -100,7 +107,7 @@ void RimFaultResultSettings::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::updateVisibility() { - if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + if (this->visualizationMode() == FAULT_COLOR) { this->m_customFaultResult.setUiHidden(true); this->m_customFaultResult.setUiChildrenHidden(true); @@ -117,7 +124,7 @@ void RimFaultResultSettings::updateVisibility() //-------------------------------------------------------------------------------------------------- RimResultSlot* RimFaultResultSettings::customFaultResult() { - if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) + if (showCustomFaultResult() && this->visualizationMode() == CUSTOM_RESULT_MAPPING) { return this->m_customFaultResult(); } @@ -125,3 +132,11 @@ RimResultSlot* RimFaultResultSettings::customFaultResult() return NULL; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() +{ + return &showCustomFaultResult; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 05aa4f0dad..85edd71fef 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -36,7 +36,6 @@ class RimFaultResultSettings : public caf::PdmObject enum FaultVisualizationMode { FAULT_COLOR, - CELL_RESULT_MAPPING, CUSTOM_RESULT_MAPPING }; @@ -47,15 +46,17 @@ class RimFaultResultSettings : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; - caf::PdmField showNNCs; + caf::PdmField showNNCs; + caf::PdmField showCustomFaultResult; RimResultSlot* customFaultResult(); void updateVisibility(); protected: - virtual void initAfterRead(); - virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + virtual void initAfterRead(); + virtual caf::PdmFieldHandle* objectToggleField(); + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: caf::PdmField m_customFaultResult; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ca8ada6732..d97ba1ec22 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1389,9 +1389,8 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + if (this->faultResultSettings()->customFaultResult()) { - CVF_ASSERT(this->faultResultSettings()->customFaultResult()); updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } @@ -2054,15 +2053,11 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = NULL; - if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + RimResultSlot* resultSlot = this->cellResult(); + if (this->faultResultSettings()->customFaultResult()) { resultSlot = this->faultResultSettings()->customFaultResult(); } - else - { - resultSlot = this->cellResult(); - } for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { From a89dc563b74bd8f16c7eae933b42ca83aad90ffd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 12:07:26 +0200 Subject: [PATCH 046/346] Do nothing if no source tree can be created --- Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp b/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp index 5c5718e878..4e5832b608 100644 --- a/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp @@ -392,6 +392,7 @@ void UiTreeModelPdm::updateUiSubTree(PdmObject* pdmRoot) // Build the new "Correct" Tree PdmUiTreeItem* tempUpdatedPdmTree = UiTreeItemBuilderPdm::buildViewItems(NULL, -1, pdmRoot); + if (!tempUpdatedPdmTree) return; // Find the corresponding entry for "root" in the existing Ui tree From 95639772d8ac3d23cbf85fc51c14e2bf1ddee331 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 12:55:43 +0200 Subject: [PATCH 047/346] Fault result: Moved fault result up one level in tree view --- .../Application/RiaApplication.cpp | 3 - .../RimFaultResultSettings.cpp | 68 +++++++++++++------ .../ProjectDataModel/RimFaultResultSettings.h | 5 +- .../ProjectDataModel/RimReservoirView.cpp | 13 ++-- .../ProjectDataModel/RimResultDefinition.cpp | 44 ++++++------ .../ProjectDataModel/RimResultDefinition.h | 5 +- .../ProjectDataModel/RimResultSlot.cpp | 2 + .../ProjectDataModel/RimResultSlot.h | 1 + 8 files changed, 91 insertions(+), 50 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 023836cbd6..9dfa6d43e7 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,9 +650,6 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->faultResultSettings()->updateVisibility(); - - RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); uiModel->updateUiSubTree(analysisModels); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index 3da4e842c4..e709ec62df 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -42,7 +42,7 @@ CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- RimFaultResultSettings::RimFaultResultSettings() { - CAF_PDM_InitObject("Fault Result Slot", "", "", ""); + CAF_PDM_InitObject("Fault Result Slot", ":/draw_style_faults_24x24.png", "", ""); CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); @@ -52,8 +52,15 @@ RimFaultResultSettings::RimFaultResultSettings() CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); m_customFaultResult = new RimResultSlot(); + m_customFaultResult.setOwnerObject(this); + m_customFaultResult.setUiHidden(true); - updateVisibility(); + // Take ownership of the fields in RimResultDefinition to be able to trap fieldChangedByUi in this class + m_customFaultResult->m_resultTypeUiField.setOwnerObject(this); + m_customFaultResult->m_porosityModelUiField.setOwnerObject(this); + m_customFaultResult->m_resultVariableUiField.setOwnerObject(this); + + updateFieldVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -77,18 +84,20 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showCustomFaultResult == changedField) - { - this->updateUiIconFromState(showCustomFaultResult); - } + this->updateUiIconFromState(showCustomFaultResult); + + m_customFaultResult->fieldChangedByUi(changedField, oldValue, newValue); if (changedField == &visualizationMode) { - updateVisibility(); + updateFieldVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + } - RiuMainWindow::instance()->setExpanded(this, true); + if (changedField == &m_customFaultResult->m_resultVariableUiField) + { + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } if (m_reservoirView) m_reservoirView->scheduleCreateDisplayModelAndRedraw(); @@ -99,24 +108,18 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::initAfterRead() { - updateVisibility(); + m_customFaultResult->initAfterRead(); + updateFieldVisibility(); + + this->updateUiIconFromState(showCustomFaultResult); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::updateVisibility() +void RimFaultResultSettings::updateFieldVisibility() { - if (this->visualizationMode() == FAULT_COLOR) - { - this->m_customFaultResult.setUiHidden(true); - this->m_customFaultResult.setUiChildrenHidden(true); - } - else - { - this->m_customFaultResult.setUiHidden(false); - this->m_customFaultResult.setUiChildrenHidden(false); - } + m_customFaultResult->updateFieldVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -140,3 +143,28 @@ caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() return &showCustomFaultResult; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&visualizationMode); + uiOrdering.add(&showNNCs); + + if (visualizationMode == CUSTOM_RESULT_MAPPING) + { + caf::PdmUiGroup* group1 = uiOrdering.addNewGroup("Result"); + group1->add(&(m_customFaultResult->m_resultTypeUiField)); + group1->add(&(m_customFaultResult->m_porosityModelUiField)); + group1->add(&(m_customFaultResult->m_resultVariableUiField)); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimFaultResultSettings::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +{ + return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 85edd71fef..3c07267547 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -51,12 +51,15 @@ class RimFaultResultSettings : public caf::PdmObject RimResultSlot* customFaultResult(); - void updateVisibility(); + void updateFieldVisibility(); + + virtual QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly ); protected: virtual void initAfterRead(); virtual caf::PdmFieldHandle* objectToggleField(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) ; private: caf::PdmField m_customFaultResult; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index d97ba1ec22..2f5de1eab5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -103,7 +103,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/draw_style_faults_24x24.png", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", "", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); @@ -933,14 +933,15 @@ void RimReservoirView::loadDataAndUpdate() CVF_ASSERT(this->cellResult() != NULL); this->cellResult()->loadResult(); - if (m_reservoir->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) - { - this->cellResult->setPorosityModelUiFieldHidden(true); - } - CVF_ASSERT(this->cellEdgeResult() != NULL); this->cellEdgeResult()->loadResult(); + if (this->faultResultSettings()->customFaultResult()) + { + this->faultResultSettings()->customFaultResult()->loadResult(); + } + this->faultResultSettings()->updateFieldVisibility(); + updateViewerWidget(); this->propertyFilterCollection()->loadAndInitializePropertyFilters(); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 7d16b522e6..52a64404d1 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -38,7 +38,7 @@ RimResultDefinition::RimResultDefinition() CAF_PDM_InitFieldNoDefault(&m_resultType, "ResultType", "Type", "", "", ""); m_resultType.setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Type", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Porosity", "", "", ""); m_porosityModel.setUiHidden(true); CAF_PDM_InitField(&m_resultVariable, "ResultVariable", RimDefines::undefinedResultName(), "Variable", "", "", "" ); m_resultVariable.setUiHidden(true); @@ -46,7 +46,7 @@ RimResultDefinition::RimResultDefinition() CAF_PDM_InitFieldNoDefault(&m_resultTypeUiField, "MResultType", "Type", "", "", ""); m_resultTypeUiField.setIOReadable(false); m_resultTypeUiField.setIOWritable(false); - CAF_PDM_InitFieldNoDefault(&m_porosityModelUiField, "MPorosityModelType", "Type", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_porosityModelUiField, "MPorosityModelType", "Porosity", "", "", ""); m_porosityModelUiField.setIOReadable(false); m_porosityModelUiField.setIOWritable(false); CAF_PDM_InitField(&m_resultVariableUiField, "MResultVariable", RimDefines::undefinedResultName(), "Result property", "", "", "" ); @@ -72,16 +72,7 @@ void RimResultDefinition::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; - // TODO: This code is executed before reservoir is read, and then porosity model is never set to zero - if (m_reservoirView->eclipseCase() && - m_reservoirView->eclipseCase()->reservoirData() && - m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) - { - if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) - { - m_porosityModelUiField.setUiHidden(true); - } - } + updateFieldVisibility(); } QStringList RimResultDefinition::getResultVariableListForCurrentUIFieldSettings() @@ -220,6 +211,8 @@ void RimResultDefinition::loadResult() gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); } } + + updateFieldVisibility(); } @@ -332,18 +325,31 @@ void RimResultDefinition::setResultVariable(const QString& val) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimResultDefinition::setPorosityModelUiFieldHidden(bool hide) +bool RimResultDefinition::isTernarySaturationSelected() const { - m_porosityModelUiField.setUiHidden(true); + bool isTernary = (m_resultType() == RimDefines::DYNAMIC_NATIVE) && + (m_resultVariable().compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0); + + return isTernary; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimResultDefinition::isTernarySaturationSelected() const +void RimResultDefinition::updateFieldVisibility() { - bool isTernary = (m_resultType() == RimDefines::DYNAMIC_NATIVE) && - (m_resultVariable().compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0); - - return isTernary; + if (m_reservoirView && + m_reservoirView->eclipseCase() && + m_reservoirView->eclipseCase()->reservoirData() && + m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) + { + if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) + { + m_porosityModelUiField.setUiHidden(true); + } + else + { + m_porosityModelUiField.setUiHidden(false); + } + } } diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index f399262ee2..a725da96d8 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -49,7 +49,6 @@ class RimResultDefinition : public caf::PdmObject void setPorosityModel(RimDefines::PorosityModelType val); QString resultVariable() const { return m_resultVariable(); } virtual void setResultVariable(const QString& val); - void setPorosityModelUiFieldHidden(bool hide); void loadResult(); size_t gridScalarIndex() const; @@ -71,6 +70,7 @@ class RimResultDefinition : public caf::PdmObject caf::PdmField m_resultVariable; friend class RimCellPropertyFilter; + friend class RimFaultResultSettings; // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultTypeUiField; caf::PdmField< caf::AppEnum< RimDefines::PorosityModelType > > m_porosityModelUiField; @@ -81,6 +81,9 @@ class RimResultDefinition : public caf::PdmObject caf::PdmPointer m_reservoirView; +protected: + void updateFieldVisibility(); + private: QStringList getResultVariableListForCurrentUIFieldSettings(); }; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index dc7af09867..7ceb23ad01 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -154,6 +154,8 @@ void RimResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { + RimResultDefinition::setReservoirView(ownerReservoirView); + m_reservoirView = ownerReservoirView; this->legendConfig()->setReservoirView(ownerReservoirView); std::list >::iterator it; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index 390b3cc053..da5a8b932c 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -44,6 +44,7 @@ class RimResultSlot : public RimResultDefinition virtual void setResultVariable(const QString& resultName); protected: + friend class RimFaultResultSettings; virtual void initAfterRead(); private: From a0f91ee0c28dcc74f812434f34addc5fc54d3b65 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:03:05 +0200 Subject: [PATCH 048/346] Fault result : Renamed in tree view --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 2f5de1eab5..0e17b8eca9 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -103,7 +103,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", "", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result", "", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); From 451a97b7f0639b4a57f8af8ac1aa37952c260ba0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:35:28 +0200 Subject: [PATCH 049/346] Fwk: Update enabled state for icons based on object toggle field --- Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp | 12 ++++++++++++ Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp index d752765d8e..d32c20c4fa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp @@ -464,5 +464,17 @@ void PdmObject::addUiTreeChildren(PdmUiTreeOrdering* root, QString uiConfigName } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObject::updateUiIconFromToggleField() +{ + if (objectToggleField()) + { + bool active = objectToggleField()->uiValue().toBool(); + updateUiIconFromState(active); + } +} + } //End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 94eb759c48..457a8b1371 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -174,6 +174,8 @@ class PdmObject : public PdmUiItem /// Return object editor specific parameters used to customize the editor behavior. void objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute); + void updateUiIconFromToggleField(); + // Virtual interface to override in subclasses to support special behaviour if needed public: // Virtual virtual PdmFieldHandle* userDescriptionField() { return NULL; } @@ -196,7 +198,8 @@ class PdmObject : public PdmUiItem protected: // Virtual /// Method gets called from PdmDocument after all objects are read. /// Re-implement to set up internal pointers etc. in your data structure - virtual void initAfterRead() {}; + virtual void initAfterRead() { updateUiIconFromToggleField(); }; + /// Method gets called from PdmDocument before saving document. /// Re-implement to make sure your fields have correct data before saving virtual void setupBeforeSave() {}; From 0c7fc311703340050270a30aac0a45c12bd58fa0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:35:52 +0200 Subject: [PATCH 050/346] Improved handling of icon enabled state --- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 2 +- .../ProjectDataModel/RimCellPropertyFilterCollection.cpp | 4 +++- .../ProjectDataModel/RimCellRangeFilterCollection.cpp | 5 +++-- ApplicationCode/ProjectDataModel/RimFault.cpp | 5 +---- ApplicationCode/ProjectDataModel/RimFaultCollection.cpp | 7 ++----- .../ProjectDataModel/RimFaultResultSettings.cpp | 4 ++-- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimResultDefinition.cpp | 2 ++ ApplicationCode/ProjectDataModel/RimWellCollection.cpp | 2 +- ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp | 2 ++ 10 files changed, 20 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index f35932f066..250f5a00ee 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -82,7 +82,7 @@ void Rim3dOverlayInfoConfig::setPosition(cvf::Vec2ui position) //-------------------------------------------------------------------------------------------------- void Rim3dOverlayInfoConfig::update3DInfo() { - this->updateUiIconFromState(active); + this->updateUiIconFromToggleField(); if (!m_reservoirView) return; if (!m_reservoirView->viewer()) return; diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp index 9c4b2bcfb3..c1024f6c3a 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp @@ -76,7 +76,7 @@ RimReservoirView* RimCellPropertyFilterCollection::reservoirView() //-------------------------------------------------------------------------------------------------- void RimCellPropertyFilterCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - this->updateUiIconFromState(active); + this->updateUiIconFromToggleField(); m_reservoirView->fieldChangedByUi(&(m_reservoirView->propertyFilterCollection), oldValue, newValue); } @@ -131,6 +131,8 @@ void RimCellPropertyFilterCollection::loadAndInitializePropertyFilters() void RimCellPropertyFilterCollection::initAfterRead() { loadAndInitializePropertyFilters(); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp index 7d1a6ec91f..6c1a7bde75 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp @@ -138,7 +138,7 @@ RigActiveCellInfo* RimCellRangeFilterCollection::activeCellInfo() const //-------------------------------------------------------------------------------------------------- void RimCellRangeFilterCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - updateUiIconFromState(isActive); + this->updateUiIconFromToggleField(); CVF_ASSERT(m_reservoirView); @@ -184,8 +184,9 @@ void RimCellRangeFilterCollection::initAfterRead() RimCellRangeFilter* rangeFilter = *it; rangeFilter->setParentContainer(this); rangeFilter->updateIconState(); - } + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFault.cpp b/ApplicationCode/ProjectDataModel/RimFault.cpp index cbb223c56c..b0d1c99d4d 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.cpp +++ b/ApplicationCode/ProjectDataModel/RimFault.cpp @@ -63,10 +63,7 @@ caf::PdmFieldHandle* RimFault::userDescriptionField() //-------------------------------------------------------------------------------------------------- void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showFault == changedField) - { - this->updateUiIconFromState(showFault); - } + this->updateUiIconFromToggleField(); if (&faultColor == changedField || &showFault == changedField) { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 8aac2a264f..87ad6441cc 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -86,11 +86,8 @@ RimFaultCollection::~RimFaultCollection() //-------------------------------------------------------------------------------------------------- void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showFaultCollection == changedField) - { - this->updateUiIconFromState(showFaultCollection); - } - + this->updateUiIconFromToggleField(); + if (&faultLabelColor == changedField) { m_reservoirView->scheduleReservoirGridGeometryRegen(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index e709ec62df..9ba1391503 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -84,7 +84,7 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - this->updateUiIconFromState(showCustomFaultResult); + this->updateUiIconFromToggleField(); m_customFaultResult->fieldChangedByUi(changedField, oldValue, newValue); @@ -111,7 +111,7 @@ void RimFaultResultSettings::initAfterRead() m_customFaultResult->initAfterRead(); updateFieldVisibility(); - this->updateUiIconFromState(showCustomFaultResult); + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 0e17b8eca9..345ec4d235 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -415,7 +415,7 @@ void RimReservoirView::fieldChangedByUi(const caf::PdmFieldHandle* changedField, } } - this->updateUiIconFromState(showWindow); + this->updateUiIconFromToggleField(); } else if (changedField == &backgroundColor ) { @@ -974,6 +974,8 @@ void RimReservoirView::initAfterRead() this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); this->propertyFilterCollection()->setReservoirView(this); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 52a64404d1..b61801dc61 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -293,6 +293,8 @@ void RimResultDefinition::initAfterRead() m_porosityModelUiField = m_porosityModel; m_resultTypeUiField = m_resultType; m_resultVariableUiField = m_resultVariable; + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp index 710e1948a3..a4efac4ea8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp @@ -190,7 +190,7 @@ void RimWellCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField { if (&showWellLabel == changedField || &isActive == changedField) { - this->updateUiIconFromState(isActive); + this->updateUiIconFromToggleField(); if (m_reservoirView) { diff --git a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp index fa61910c5b..17d8fe61da 100644 --- a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp +++ b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp @@ -89,6 +89,8 @@ void RimOilFieldEntry::fieldChangedByUi(const caf::PdmFieldHandle* changedField, void RimOilFieldEntry::initAfterRead() { updateEnabledState(); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- From 1da9920067fadc81fc18631e30d5929c28912736 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 14:48:37 +0200 Subject: [PATCH 051/346] Fault visibility : Restructured code --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 2 +- .../ProjectDataModel/RimFaultCollection.cpp | 24 ++++++++++++++++--- .../ProjectDataModel/RimFaultCollection.h | 7 ++++-- .../ProjectDataModel/RimReservoirView.cpp | 10 ++++---- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9dfa6d43e7..0f84a4413e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2062,7 +2062,7 @@ void RiaApplication::regressionTestConfigureProject() riv->viewer()->setFixedSize(1000, 745); } - riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); + riv->faultCollection->setShowFaultsOutsideFilters(false); riv->faultResultSettings->showCustomFaultResult.setValueFromUi(false); } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index f1284c9a3f..fcf3c7d7f7 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -119,7 +119,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) forceDisplayOfFault = true; } - if (rimFault->showFault() || forceDisplayOfFault) + if ( (faultCollection->showFaultCollection() && rimFault->showFault()) || forceDisplayOfFault) { if (faultCollection->showFaultFaces() || forceDisplayOfFault) { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 87ad6441cc..dbdda464e4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -59,7 +59,7 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showFaultFaces, "ShowFaultFaces", true, "Show defined faces", "", "", ""); CAF_PDM_InitField(&showOppositeFaultFaces, "ShowOppositeFaultFaces", true, "Show opposite faces", "", "", ""); - CAF_PDM_InitField(&showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); + CAF_PDM_InitField(&m_showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); CAF_PDM_InitField(&faultResult, "FaultFaceCulling", caf::AppEnum(RimFaultCollection::FAULT_BACK_FACE_CULLING), "Dynamic Face Selection", "", "", ""); @@ -97,7 +97,7 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel &showOppositeFaultFaces == changedField || &showFaultCollection == changedField || &showFaultLabel == changedField || - &showFaultsOutsideFilters == changedField || + &m_showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || &faultResult == changedField ) @@ -254,7 +254,7 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi labs->add(&faultLabelColor); caf::PdmUiGroup* adv = uiOrdering.addNewGroup("Fault Options"); - adv->add(&showFaultsOutsideFilters); + adv->add(&m_showFaultsOutsideFilters); caf::PdmUiGroup* ffviz = uiOrdering.addNewGroup("Fault Face Visibility"); ffviz->add(&showFaultFaces); @@ -262,3 +262,21 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi ffviz->add(&faultResult); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultCollection::showFaultsOutsideFilters() const +{ + if (!showFaultCollection) return false; + + return m_showFaultsOutsideFilters; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultCollection::setShowFaultsOutsideFilters(bool enableState) +{ + m_showFaultsOutsideFilters = enableState; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index b5fbc7b759..f940209d77 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -57,10 +57,12 @@ class RimFaultCollection : public caf::PdmObject void syncronizeFaults(); bool isGridVisualizationMode() const; + + bool showFaultsOutsideFilters() const; + void setShowFaultsOutsideFilters(bool enableState); caf::PdmField showFaultFaces; caf::PdmField showOppositeFaultFaces; - caf::PdmField showFaultsOutsideFilters; caf::PdmField > faultResult; @@ -80,6 +82,7 @@ class RimFaultCollection : public caf::PdmObject virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); private: - RimReservoirView* m_reservoirView; + caf::PdmField m_showFaultsOutsideFilters; + RimReservoirView* m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 345ec4d235..e0eecb863d 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -620,7 +620,7 @@ void RimReservoirView::createDisplayModel() m_visibleGridParts = geometryTypesToAdd; } - if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) + if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters()) { updateFaultForcedVisibility(); @@ -714,7 +714,7 @@ void RimReservoirView::updateCurrentTimeStep() geometriesToRecolor.push_back( RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS); m_reservoirGridPartManager->appendDynamicGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS, m_currentTimeStep, gridIndices); - if (faultCollection()->showFaultsOutsideFilters) + if (faultCollection()->showFaultsOutsideFilters()) { std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); @@ -748,7 +748,7 @@ void RimReservoirView::updateCurrentTimeStep() { m_reservoirGridPartManager->appendStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE, gridIndices); - if (!faultCollection()->showFaultsOutsideFilters) + if (!faultCollection()->showFaultsOutsideFilters()) { m_reservoirGridPartManager->appendFaultsStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE); } @@ -757,7 +757,7 @@ void RimReservoirView::updateCurrentTimeStep() { m_reservoirGridPartManager->appendStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::INACTIVE, gridIndices); - if (!faultCollection()->showFaultsOutsideFilters) + if (!faultCollection()->showFaultsOutsideFilters()) { m_reservoirGridPartManager->appendFaultsStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::INACTIVE); } @@ -1980,7 +1980,7 @@ std::vector RimReservoirVie { std::vector faultParts; - if (this->propertyFilterCollection()->hasActiveFilters() && !faultCollection()->showFaultsOutsideFilters) + if (this->propertyFilterCollection()->hasActiveFilters() && !faultCollection()->showFaultsOutsideFilters()) { faultParts.push_back(RivReservoirViewPartMgr::PROPERTY_FILTERED); faultParts.push_back(RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS); From 18b149baa3cf4377d75c495deb7337ee41019241 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:39:52 +0200 Subject: [PATCH 052/346] Rename --- .../ReservoirDataModel/RigGridScalarDataAccess.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp index 655e8939ae..1a83658480 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp @@ -84,10 +84,10 @@ void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, d //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -class RigGridMatrixActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess { public: - RigGridMatrixActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + RigGridActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_activeCellInfo(activeCellInfo) @@ -186,7 +186,7 @@ cvf::ref RigGridScalarDataAccessFactory::create bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigGridMatrixActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + cvf::ref object = new RigGridActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); return object; } else From e718b760b638868a61825d63597eb9db15723db0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:47:27 +0200 Subject: [PATCH 053/346] Renamed to RimFaultResultSlot --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 4 +-- .../ProjectDataModel/CMakeLists_files.cmake | 4 +-- .../Rim3dOverlayInfoConfig.cpp | 4 +-- ...ultSettings.cpp => RimFaultResultSlot.cpp} | 34 +++++++++---------- ...tResultSettings.h => RimFaultResultSlot.h} | 6 ++-- .../ProjectDataModel/RimReservoirView.cpp | 4 +-- .../ProjectDataModel/RimReservoirView.h | 4 +-- .../ProjectDataModel/RimResultDefinition.h | 2 +- .../ProjectDataModel/RimResultSlot.h | 2 +- 10 files changed, 33 insertions(+), 33 deletions(-) rename ApplicationCode/ProjectDataModel/{RimFaultResultSettings.cpp => RimFaultResultSlot.cpp} (80%) rename ApplicationCode/ProjectDataModel/{RimFaultResultSettings.h => RimFaultResultSlot.h} (94%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 0f84a4413e..9c9e323a52 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,7 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index fcf3c7d7f7..7a418eb3ba 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -28,7 +28,7 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" #include "RimReservoirView.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" //-------------------------------------------------------------------------------------------------- @@ -183,7 +183,7 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot RimFault* rimFault = faultCollection->faults[i]; if (m_reservoirView->faultResultSettings()->showCustomFaultResult() && - m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) + m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 656f19e48e..c9cb08a878 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,7 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h -${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -95,7 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp -${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 250f5a00ee..752f4894f7 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -24,7 +24,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -160,7 +160,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("" "
MinP10 Mean P90 Max
%1 %2 %3 %4 %5
").arg(min).arg(p10).arg(mean).arg(p90).arg(max); - if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSettings::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSlot::FAULT_COLOR) { QString faultMapping; bool isShowingGrid = m_reservoirView->faultCollection()->isGridVisualizationMode(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp similarity index 80% rename from ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp rename to ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 9ba1391503..dfdbcadf48 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -27,27 +27,27 @@ namespace caf { template<> - void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() + void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() { - addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSettings::FAULT_COLOR); + addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSlot::FAULT_COLOR); } } -CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); +CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSettings::RimFaultResultSettings() +RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", ":/draw_style_faults_24x24.png", "", ""); CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::FAULT_COLOR), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::FAULT_COLOR), "Fault Color Mapping", "", "", ""); CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); @@ -66,14 +66,14 @@ RimFaultResultSettings::RimFaultResultSettings() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSettings::~RimFaultResultSettings() +RimFaultResultSlot::~RimFaultResultSlot() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirView) +void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; m_customFaultResult->setReservoirView(ownerReservoirView); @@ -82,7 +82,7 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { this->updateUiIconFromToggleField(); @@ -106,7 +106,7 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::initAfterRead() +void RimFaultResultSlot::initAfterRead() { m_customFaultResult->initAfterRead(); updateFieldVisibility(); @@ -117,7 +117,7 @@ void RimFaultResultSettings::initAfterRead() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::updateFieldVisibility() +void RimFaultResultSlot::updateFieldVisibility() { m_customFaultResult->updateFieldVisibility(); } @@ -125,7 +125,7 @@ void RimFaultResultSettings::updateFieldVisibility() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimResultSlot* RimFaultResultSettings::customFaultResult() +RimResultSlot* RimFaultResultSlot::customFaultResult() { if (showCustomFaultResult() && this->visualizationMode() == CUSTOM_RESULT_MAPPING) { @@ -138,7 +138,7 @@ RimResultSlot* RimFaultResultSettings::customFaultResult() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() +caf::PdmFieldHandle* RimFaultResultSlot::objectToggleField() { return &showCustomFaultResult; } @@ -146,7 +146,7 @@ caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +void RimFaultResultSlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { uiOrdering.add(&visualizationMode); uiOrdering.add(&showNNCs); @@ -163,7 +163,7 @@ void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList RimFaultResultSettings::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +QList RimFaultResultSlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h similarity index 94% rename from ApplicationCode/ProjectDataModel/RimFaultResultSettings.h rename to ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 3c07267547..07d4be9a53 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSettings : public caf::PdmObject +class RimFaultResultSlot : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -40,8 +40,8 @@ class RimFaultResultSettings : public caf::PdmObject }; public: - RimFaultResultSettings(); - virtual ~RimFaultResultSettings(); + RimFaultResultSlot(); + virtual ~RimFaultResultSlot(); void setReservoirView(RimReservoirView* ownerReservoirView); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index e0eecb863d..fe969de1ac 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,7 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -104,7 +104,7 @@ RimReservoirView::RimReservoirView() cellEdgeResult = new RimCellEdgeResultSlot(); CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result", "", "", ""); - faultResultSettings = new RimFaultResultSettings(); + faultResultSettings = new RimFaultResultSlot(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 4ae47bf513..36568bc8f0 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -44,7 +44,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; -class RimFaultResultSettings; +class RimFaultResultSlot; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField faultResultSettings; + caf::PdmField faultResultSettings; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index a725da96d8..462709a898 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -70,7 +70,7 @@ class RimResultDefinition : public caf::PdmObject caf::PdmField m_resultVariable; friend class RimCellPropertyFilter; - friend class RimFaultResultSettings; + friend class RimFaultResultSlot; // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultTypeUiField; caf::PdmField< caf::AppEnum< RimDefines::PorosityModelType > > m_porosityModelUiField; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index da5a8b932c..f39250f7ad 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -44,7 +44,7 @@ class RimResultSlot : public RimResultDefinition virtual void setResultVariable(const QString& resultName); protected: - friend class RimFaultResultSettings; + friend class RimFaultResultSlot; virtual void initAfterRead(); private: From 6812912c06a14218615bbf5d2da733c9a32dd705 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:56:41 +0200 Subject: [PATCH 054/346] Renamed to RigResultAccessObjectFactory --- .../RivReservoirViewPartMgr.cpp | 2 +- .../ReservoirDataModel/CMakeLists_files.cmake | 4 +- .../ReservoirDataModel/RigCaseData.cpp | 4 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../RigGridScalarDataAccess.cpp | 4 +- .../RigResultAccessObjectFactory.cpp | 198 ++++++++++++++++++ ...ccess.h => RigResultAccessObjectFactory.h} | 4 +- 7 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp rename ApplicationCode/ReservoirDataModel/{RigGridScalarDataAccess.h => RigResultAccessObjectFactory.h} (92%) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 8346961b45..284985349c 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -23,7 +23,7 @@ #include "RigCaseData.h" #include "RigGridBase.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "RimCase.h" #include "RimCellRangeFilterCollection.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index aace5df653..fb9614f179 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,7 +10,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h -${CEE_CURRENT_LIST_DIR}RigGridScalarDataAccess.h +${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -30,7 +30,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp -${CEE_CURRENT_LIST_DIR}RigGridScalarDataAccess.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index c9483020e0..741dc86ee8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -19,7 +19,7 @@ #include "RigCaseData.h" #include "RigMainGrid.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" //-------------------------------------------------------------------------------------------------- /// @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigGridScalarDataAccessFactory::createPerGridDataAccessObject( this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessObjectFactory::createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index dc602d41ed..4c195270da 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -20,7 +20,7 @@ #include "RigMainGrid.h" #include "RigCell.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "cvfAssert.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp index 1a83658480..218d8fb2f2 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "cvfLibCore.h" #include "cvfBase.h" @@ -146,7 +146,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigGridScalarDataAccessFactory::createPerGridDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp new file mode 100644 index 0000000000..218d8fb2f2 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -0,0 +1,198 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultAccessObjectFactory.h" + +#include "cvfLibCore.h" +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfAssert.h" + +#include "RigMainGrid.h" +#include "RigCaseCellResultsData.h" +#include "RigActiveCellInfo.h" +#include "RigGridBase.h" +#include "RigCaseData.h" +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RigGridAllCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +{ +public: + RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues); + + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual void setCellScalar(size_t cellIndex, double value); + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigGridAllCellsScalarDataAccess::RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues) +{ + CVF_ASSERT(reservoirResultValues != NULL); + CVF_ASSERT(grid != NULL); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) const +{ + if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(globalGridCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +{ +public: + RigGridActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo) + { + + CVF_ASSERT(grid != NULL); + } + + virtual double cellScalar(size_t gridLocalCellIndex) const + { + if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; + + CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(resultValueIndex); + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; + } + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + + + +class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess +{ +public: + virtual double cellScalar(size_t cellIndex) const + { + return HUGE_VAL; + } + virtual void setCellScalar(size_t cellIndex, double value) + { + } +}; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarSetIndex) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); + + // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps + // See RiaSetGridProperty command in RiaPropertyDataCommands + // + // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) + { + cvf::ref object = new StructGridScalarDataAccessHugeVal; + + return object; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigGridActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigGridAllCellsScalarDataAccess(grid, resultValues); + return object; + } +} + diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h similarity index 92% rename from ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index d098829f66..2183cd0fd1 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -25,11 +25,11 @@ class RigActiveCellInfo; class RigGridBase; -class RigGridScalarDataAccessFactory +class RigResultAccessObjectFactory { public: static cvf::ref - createPerGridDataAccessObject(RigCaseData* eclipseCase, + createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From be7a4326c391b80c9015f3ba3404957cc6942fa5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 13:14:38 +0200 Subject: [PATCH 055/346] Added RigResultAccessObject --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigResultAccessObject.cpp | 19 +++++ .../RigResultAccessObject.h | 75 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index fb9614f179..66f639fd08 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,6 +10,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h +${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h @@ -30,6 +31,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp new file mode 100644 index 0000000000..6d732c7309 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp @@ -0,0 +1,19 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultAccessObject.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h new file mode 100644 index 0000000000..021efe6846 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" + + +class RigResultAccessObject : public cvf::Object +{ +public: + virtual double cellScalar(size_t localCellIndex) const = 0; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + + virtual void setCellScalar(size_t cellIndex, double value) = 0; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ From bee8e8d114d859232c789f99ac1492d7d7617e84 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 13:47:15 +0200 Subject: [PATCH 056/346] Added data access objects for native results --- .../ReservoirDataModel/CMakeLists_files.cmake | 4 + .../RigActiveCellsResultAccessObject.cpp | 76 +++++++++++++++++ .../RigActiveCellsResultAccessObject.h | 83 +++++++++++++++++++ .../RigAllGridCellsResultAccessObject.cpp | 72 ++++++++++++++++ .../RigAllGridCellsResultAccessObject.h | 81 ++++++++++++++++++ .../RigResultAccessObject.h | 5 +- .../RigResultAccessObjectFactory.cpp | 2 +- .../RigResultAccessObjectFactory.h | 2 +- 8 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h create mode 100644 ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 66f639fd08..31552802cb 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -12,6 +12,8 @@ ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -33,6 +35,8 @@ ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp new file mode 100644 index 0000000000..3cfddaf58f --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigActiveCellsResultAccessObject.h" + +#include "RigGridBase.h" +#include "RigActiveCellInfo.h" + +RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo), + m_resultName(resultName) +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const +{ + if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; + + CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(resultValueIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(localCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigActiveCellsResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigActiveCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; +} diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h new file mode 100644 index 0000000000..1bcb18d66a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +class RigGridBase; +class RigActiveCellInfo; + + +//================================================================================================== +/// +//================================================================================================== +class RigActiveCellsResultAccessObject : public RigResultAccessObject +{ +public: + RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; + QString m_resultName; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp new file mode 100644 index 0000000000..1d7b0ff8f1 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigAllGridCellsResultAccessObject.h" + +#include "RigGridBase.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_resultName(resultName) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) const +{ + if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(globalGridCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(localCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigAllGridCellsResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigAllGridCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; +} diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h new file mode 100644 index 0000000000..c503960ef5 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigActiveCellsResultAccessObject.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigAllGridCellsResultAccessObject : public RigResultAccessObject +{ +public: + RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; + QString m_resultName; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 021efe6846..caf9640931 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -25,6 +25,9 @@ #include "cvfStructGrid.h" +//================================================================================================== +/// +//================================================================================================== class RigResultAccessObject : public cvf::Object { public: @@ -33,7 +36,7 @@ class RigResultAccessObject : public cvf::Object virtual QString resultName() const = 0; - virtual void setCellScalar(size_t cellIndex, double value) = 0; + virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index 218d8fb2f2..e47a35e2d5 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index 2183cd0fd1..d19a8ff386 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 3bd46bda222bc678e1f2db7932cd31cbb2cc82ad Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 14:04:26 +0200 Subject: [PATCH 057/346] Added RigCellFaceResultAccessObject --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigActiveCellsResultAccessObject.h | 37 --------- .../RigAllGridCellsResultAccessObject.h | 36 -------- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../RigCellFaceResultAccessObject.cpp | 82 +++++++++++++++++++ .../RigCellFaceResultAccessObject.h | 45 ++++++++++ .../RigResultAccessObject.h | 37 --------- .../RigResultAccessObjectFactory.cpp | 2 +- .../RigResultAccessObjectFactory.h | 10 ++- 9 files changed, 140 insertions(+), 113 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 31552802cb..154b885bd0 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -14,6 +14,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -37,6 +38,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 1bcb18d66a..901fe90638 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -44,40 +44,3 @@ class RigActiveCellsResultAccessObject : public RigResultAccessObject QString m_resultName; }; - -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h index c503960ef5..86eb65ecb5 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -43,39 +43,3 @@ class RigAllGridCellsResultAccessObject : public RigResultAccessObject }; -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 741dc86ee8..3b1dfebeca 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigResultAccessObjectFactory::createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp new file mode 100644 index 0000000000..808d8b7708 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCellFaceResultAccessObject.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resultName) + : m_resultName(resultName) +{ + m_resultAccessObjects.resize(6); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +{ + m_resultAccessObjects[faceId] = resultAccessObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const +{ + + // TODO: How to handle when we get here? + CVF_ASSERT(false); + + return cvf::UNDEFINED_DOUBLE; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(faceId); + if (resultAccessObj != NULL) + { + return resultAccessObj->cellFaceScalar(localCellIndex, faceId); + } + + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigCellFaceResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCellFaceResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + // TODO: How to handle when we get here? + CVF_ASSERT(false); + +} + diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h new file mode 100644 index 0000000000..27afad5aea --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +#include "cvfCollection.h" + + +//================================================================================================== +/// +//================================================================================================== +class RigCellFaceResultAccessObject : public RigResultAccessObject +{ +public: + RigCellFaceResultAccessObject(const QString& resultName); + + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + cvf::Collection m_resultAccessObjects; + + QString m_resultName; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index caf9640931..8d723b567b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -39,40 +39,3 @@ class RigResultAccessObject : public cvf::Object virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; - -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index e47a35e2d5..d093fca77b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -146,7 +146,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index d19a8ff386..b50adc5240 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -28,8 +28,16 @@ class RigGridBase; class RigResultAccessObjectFactory { public: + + + + + + + + // TO BE DELETED static cvf::ref - createNativeDataAccessObject(RigCaseData* eclipseCase, + TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From b39ec291c90c6172bfdfc49d71e6ff57a73b6d63 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 14:18:02 +0200 Subject: [PATCH 058/346] Linux: Added include of cmath for define of HUGE_VAL --- .../ReservoirDataModel/RigActiveCellsResultAccessObject.cpp | 3 +++ .../ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp index 3cfddaf58f..6552f938f7 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -21,6 +21,9 @@ #include "RigGridBase.h" #include "RigActiveCellInfo.h" +#include + + RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp index 1d7b0ff8f1..37eaa0ffa6 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -20,6 +20,8 @@ #include "RigGridBase.h" +#include + //-------------------------------------------------------------------------------------------------- /// From 9aead74f47a841adfd7b499121577a155002855e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:14:01 +0200 Subject: [PATCH 059/346] Added ResultAccessObject for combined transmissibility --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigCellFaceResultAccessObject.cpp | 2 + .../RigCombTransResultAccessObject.cpp | 157 ++++++++++++++++++ .../RigCombTransResultAccessObject.h | 48 ++++++ .../ReservoirDataModel/RigGridBase.h | 1 - .../RigResultAccessObjectFactory.cpp | 142 ++++++++++++++++ .../RigResultAccessObjectFactory.h | 29 +++- 7 files changed, 372 insertions(+), 9 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 154b885bd0..123e156828 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -39,6 +40,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index 808d8b7708..86b8bbbfaa 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -18,6 +18,8 @@ #include "RigCellFaceResultAccessObject.h" +#include + //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp new file mode 100644 index 0000000000..60786a606a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCombTransResultAccessObject.h" + +#include "RigGridBase.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName) + : m_grid(grid), + m_resultName(resultName) +{ + m_resultAccessObjects.resize(6); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +{ + m_resultAccessObjects[faceId] = resultAccessObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const +{ + + // TODO: How to handle when we get here? + CVF_ASSERT(false); + + return cvf::UNDEFINED_DOUBLE; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + switch (faceId) + { + case cvf::StructGridInterface::POS_I: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_I: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + case cvf::StructGridInterface::POS_J: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_J: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + case cvf::StructGridInterface::POS_K: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_K: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + } + + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigCombTransResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombTransResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + // TODO: How to handle when we get here? + CVF_ASSERT(false); + +} + diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h new file mode 100644 index 0000000000..19e27b487a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +#include "cvfCollection.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigCombTransResultAccessObject : public RigResultAccessObject +{ +public: + RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName); + + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + cvf::Collection m_resultAccessObjects; + + const RigGridBase* m_grid; + QString m_resultName; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index cc061c18fa..a8285ad227 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -37,7 +37,6 @@ class RigMainGrid; class RigCell; -class RigGridScalarDataAccess; class RigActiveCellInfo; class RigGridBase : public cvf::StructGridInterface diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index d093fca77b..052aa35a6a 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -18,6 +18,10 @@ #include "RigResultAccessObjectFactory.h" +#include "RigResultAccessObject.h" +#include "RigActiveCellsResultAccessObject.h" +#include "RigAllGridCellsResultAccessObject.h" + #include "cvfLibCore.h" #include "cvfBase.h" #include "cvfObject.h" @@ -29,6 +33,84 @@ #include "RigGridBase.h" #include "RigCaseData.h" #include +#include "RigCombTransResultAccessObject.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(uiResultName); + if (scalarSetIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); + + // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps + // See RiaSetGridProperty command in RiaPropertyDataCommands + // + // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultAccessObject(grid, resultValues, uiResultName); + return object; + } +} + + + + + + + + + + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +// Rest of this file is to be deleted +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- /// @@ -196,3 +278,63 @@ cvf::ref RigResultAccessObjectFactory::TO_BE_DE } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + // Ternary + if (uiResultName == RimDefines::ternarySaturationResultName()) + { + return NULL; + } + else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + // TODO + // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates + // + + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); + } + } + + return cellFaceAccessObject; + } + + + return NULL; +} + diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index b50adc5240..aa54258936 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -24,24 +24,37 @@ class RigActiveCellInfo; class RigGridBase; +class RigResultAccessObject; class RigResultAccessObjectFactory { public: + static cvf::ref + createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName); + // TO BE DELETED + static cvf::ref + TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarSetIndex); +private: + static cvf::ref + createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& resultName); - - // TO BE DELETED - static cvf::ref - TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex); }; From 8e54279e58a161777505d54389b3e2332de0d7dc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:52:59 +0200 Subject: [PATCH 060/346] Improved visual appearance of legend --- .../RivTernarySaturationOverlayItem.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 2160d0eb53..761f4bb6fb 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -41,7 +41,7 @@ RivTernarySaturationOverlayItem::RivTernarySaturationOverlayItem(cvf::Font* font) : m_textColor(cvf::Color3::BLACK), m_font(font), - m_size(100, 120) + m_size(100, 140) { } @@ -132,20 +132,31 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textPosY -= lineHeightInPixels; } - textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY)); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY - lineHeightInPixels)); + cvf::Vec2f pos(5, textPosY); + textDrawer.addText("TERNARY", pos); + textPosY -= lineHeightInPixels; + textPosY -= 2; + + { + cvf::uint sgasTextWidth = m_font->textExtent("SGAS").x(); + textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - sgasTextWidth / 2 ), textPosY)); + + cvf::uint sgasRangeTextWidth = m_font->textExtent(m_sgasRange).x(); + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY - lineHeightInPixels)); + } textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); textDrawer.addText(m_swatRange, cvf::Vec2f(0.0, 0.0)); - textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - 25), 10.0)); - - float soilRangePos = static_cast(size.x() - 40); - if (m_soilRange.size() < 6) { - soilRangePos += 15; + cvf::uint soilTextWidth = m_font->textExtent("SOIL").x(); + textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - soilTextWidth), 10.0)); + + cvf::uint soilRangeTextWidth = m_font->textExtent(m_soilRange).x(); + float soilRangePos = static_cast(size.x()) - soilRangeTextWidth; + + textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); } - textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); textDrawer.renderSoftware(oglContext, camera); From 84b871e6bed0810c7235c148c89e7a1511cddd23 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:53:08 +0200 Subject: [PATCH 061/346] Reordered UI --- .../ProjectDataModel/RimTernaryLegendConfig.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 6da31598c9..dab84420e6 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -264,12 +264,6 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr if (rangeMode == USER_DEFINED) { caf::PdmUiOrdering* ternaryGroupContainer = uiOrdering.addNewGroup("Ternary "); - { - caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SOIL"); - ternaryGroup->add(&userDefinedMinValueSoil); - ternaryGroup->add(&userDefinedMaxValueSoil); - } - { caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SGAS"); ternaryGroup->add(&userDefinedMinValueSgas); @@ -282,6 +276,12 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr ternaryGroup->add(&userDefinedMaxValueSwat); } + { + caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SOIL"); + ternaryGroup->add(&userDefinedMinValueSoil); + ternaryGroup->add(&userDefinedMaxValueSoil); + } + ternaryGroupContainer->add(&applyLocalMinMax); ternaryGroupContainer->add(&applyGlobalMinMax); ternaryGroupContainer->add(&applyFullRangeMinMax); From d3ac12f826d12c766905fc9a7b7c953eb35018a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 6 Aug 2014 16:51:09 +0200 Subject: [PATCH 062/346] Moved needed code to above "delete" mark --- .../RivCellEdgeEffectGenerator.h | 8 ++ .../RigResultAccessObjectFactory.cpp | 117 +++++++++--------- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 0c37fb84bc..ba2a6018a6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -98,6 +98,14 @@ class RivCellEdgeGeometryGenerator texCoords[i*4 + 3] = texCoord; } + Texturing needs in ResInsight: + * ScalarMapper + * Handle HugeVal/nan + * PipeCellTransparency + - includes geometry point to cell mapping + * Modify the Scalarmapper Texture + * The domain values to convert pr geometry point + */ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index 052aa35a6a..b2f724a114 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -95,9 +95,65 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + RigGridBase* grid = eclipseCase->grid(gridIndex); + // Ternary + if (uiResultName == RimDefines::ternarySaturationResultName()) + { + return NULL; + } + else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + // TODO + // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates + // + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); + } + } + + return cellFaceAccessObject; + } + + + return NULL; +} @@ -277,64 +333,3 @@ cvf::ref RigResultAccessObjectFactory::TO_BE_DE return object; } } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - QString& uiResultName) -{ - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); - - RigGridBase* grid = eclipseCase->grid(gridIndex); - - // Ternary - if (uiResultName == RimDefines::ternarySaturationResultName()) - { - return NULL; - } - else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) - { - // TODO - // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates - // - - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); - } - } - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); - } - } - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); - } - } - - return cellFaceAccessObject; - } - - - return NULL; -} - From 160a2a2fdf72021910563de2981cea13642be0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 6 Aug 2014 16:54:12 +0200 Subject: [PATCH 063/346] Added comments and asserts related to neg. faces Negative face results is not applicable for this result access object, as they are never used (by intention) --- .../ReservoirDataModel/RigCombTransResultAccessObject.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp index 60786a606a..a7bb5fdf6d 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -34,10 +34,13 @@ RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase } //-------------------------------------------------------------------------------------------------- -/// +/// Only sensible to provide the positive values, as the negative ones will never be used. +/// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) { + CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); + m_resultAccessObjects[faceId] = resultAccessObject; } From c552cea28970cb341ffdb14d08b37ee2fd70a290 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 07:28:46 +0200 Subject: [PATCH 064/346] Fwk: Moved function call out of initAfterRead --- Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp | 1 + Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp index d6c3c5504b..2de957026c 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp @@ -113,6 +113,7 @@ void PdmObjectGroup::initAfterReadTraversal(PdmObject* object) } object->initAfterRead(); + object->updateUiIconFromToggleField(); } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 457a8b1371..8bb9410b87 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -198,7 +198,7 @@ class PdmObject : public PdmUiItem protected: // Virtual /// Method gets called from PdmDocument after all objects are read. /// Re-implement to set up internal pointers etc. in your data structure - virtual void initAfterRead() { updateUiIconFromToggleField(); }; + virtual void initAfterRead() {}; /// Method gets called from PdmDocument before saving document. /// Re-implement to make sure your fields have correct data before saving From d8f3a2cfca60a95ccb1196499999fb03c635a690 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 03:07:27 -0700 Subject: [PATCH 065/346] Linux fix: No default cast from QString to QString& --- .../ReservoirDataModel/RigResultAccessObjectFactory.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index b2f724a114..bede69dffe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -125,7 +125,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + QString resultName = "TRANX"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); @@ -133,7 +134,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess } { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + QString resultName = "TRANY"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); @@ -141,7 +143,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess } { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + QString resultName = "TRANZ"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); From 68f7103639dd4059d07c3e356f94dc8a7ee5dd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 12:17:04 +0200 Subject: [PATCH 066/346] Prototyping of new resultAccessor/texture system To make it simlier to add all the combined results MULTXYZ/riMULTXYZ etc --- .../RigResultAccessObject.h | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 8d723b567b..0b6ef234bd 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -39,3 +39,208 @@ class RigResultAccessObject : public cvf::Object virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; +#if 0 + +//================================================================================================== +/// +//================================================================================================== +class RigResultAccessor2d : public cvf::Object +{ +public: + virtual cvf::Vec2d cellScalar(size_t localCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + +}; + +//================================================================================================== +/// +//================================================================================================== +class RigTernaryResultAccessor : public Rig2DResultAccessor +{ +public: + /// Requires two of the arguments to be present + void setTernaryResultAccessors(RigResultAccessObject* soil, RigResultAccessObject* sgas, RigResultAccessObject* swat); + + /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// based on the two others + virtual cvf::Vec2d cellScalar(size_t localCellIndex) { }; + virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t localCellIndex); }; + + virtual QString resultName() const = 0; + +}; + +class RivTernaryScalarMapper : public cvf::Object +{ +public: + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) : m_undefScalarColor(undefScalarColor), m_opacityLevel(opacityLevel) + { + + } + + /// Calculate texture coords into an image produced by updateTexture, from the scalarValue + Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent) {} + + /// Update the supplied TextureImage to be addressable by the texture coords delivered by mapToTextureCoord + bool updateTexture(TextureImage* image){} + +private: + cvf::Color3f m_undefScalarColor; + float m_opacityLevel; +}; + +class RigPipeInCellEvaluator: public cvf::Object +{ +public: + RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap) + : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), + m_gridCellToWellIndexMap(gridCellToWellIndexMap) + { + } + + bool isWellPipeInCell( size_t cellIndex) + { + cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); + + if (wellIndex == cvf::UNDEFINED_UINT) + { + return false; + } + + return m_isWellPipeVisibleForWellIndex[wellIndex]; + } + +private: + + const std::vector& m_isWellPipeVisibleForWellIndex; + const cvf::UIntArray* m_gridCellToWellIndexMap; +}; + +class RivResultToTextureMapper : public cvf::Object +{ + + RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, + const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + Vec2f getTexCoord(double resultValue, size_t cellIndex) + { + Vec2f texCoord(0,0); + + if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + return texCoord; + } + + texCoord = m_scalarMapper->mapToTexCoord(resultValue); + + if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) + { + texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture + } + + return texCoord; + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) +{ + CVF_ASSERT(cellResultSlot); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + cvf::ref surfaceFacesColorArray; + + // Outer surface + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { + surfaceFacesColorArray = new cvf::Color3ubArray; + + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + } + else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); + } + else + { + // If the result is static, only read that. + size_t resTimeStepIdx = timeStepIndex; + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + cvf::ref dataAccessObject = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + + if (dataAccessObject.isNull()) return; + + RivResultToTextureMapper texMapper(mapper, + RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()))); + + const StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); + + size_t numVertices = quadMapper->quadCount()*4; + m_surfaceFacesTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); + + double cellScalarValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, cellScalarValue) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) + { + StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); + + cellScalarValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); + + texCoord = texMapper->mapToTextureCoord(cellScalarValue); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } + } + + + if (surfaceFacesColorArray.notNull()) // Ternary result + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + dg->setColorArray(surfaceFacesColorArray.p()); + } + + cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); + m_surfaceFaces->setEffect(perVertexColorEffect.p()); + + m_surfaceFaces->setPriority(100); + } + else + { + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + } + } +} + +#endif From 1408398150d6649e15ef8e72dae239f1218fece0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 13:22:09 +0200 Subject: [PATCH 067/346] Class Rename: ResultAccessObject to ResultAccessor --- .../RigActiveCellsResultAccessObject.h | 2 +- .../RigAllGridCellsResultAccessObject.cpp | 10 ++++---- .../RigAllGridCellsResultAccessObject.h | 4 ++-- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../RigCellFaceResultAccessObject.cpp | 14 +++++------ .../RigCellFaceResultAccessObject.h | 8 +++---- .../RigCombTransResultAccessObject.cpp | 24 +++++++++---------- .../RigCombTransResultAccessObject.h | 8 +++---- .../RigResultAccessObject.h | 2 +- .../RigResultAccessObjectFactory.cpp | 18 +++++++------- .../RigResultAccessObjectFactory.h | 12 +++++----- 11 files changed, 52 insertions(+), 52 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 901fe90638..14fb8c1dfe 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -27,7 +27,7 @@ class RigActiveCellInfo; //================================================================================================== /// //================================================================================================== -class RigActiveCellsResultAccessObject : public RigResultAccessObject +class RigActiveCellsResultAccessObject : public RigResultAccessor { public: RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp index 37eaa0ffa6..8e240d2f09 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) +RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_resultName(resultName) @@ -36,7 +36,7 @@ RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) const +double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; @@ -49,7 +49,7 @@ double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) cons //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(localCellIndex); } @@ -57,7 +57,7 @@ double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigAllGridCellsResultAccessObject::resultName() const +QString RigAllGridCellsResultAccessor::resultName() const { return m_resultName; } @@ -65,7 +65,7 @@ QString RigAllGridCellsResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigAllGridCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigAllGridCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h index 86eb65ecb5..2af694fa50 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -26,10 +26,10 @@ class RigGridBase; //================================================================================================== /// //================================================================================================== -class RigAllGridCellsResultAccessObject : public RigResultAccessObject +class RigAllGridCellsResultAccessor : public RigResultAccessor { public: - RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 3b1dfebeca..1b2d8b18bc 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index 86b8bbbfaa..fe2327d835 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -24,7 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resultName) +RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) : m_resultName(resultName) { m_resultAccessObjects.resize(6); @@ -33,7 +33,7 @@ RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resu //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { m_resultAccessObjects[faceId] = resultAccessObject; } @@ -41,7 +41,7 @@ void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridIn //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const +double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -53,9 +53,9 @@ double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(faceId); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); if (resultAccessObj != NULL) { return resultAccessObj->cellFaceScalar(localCellIndex, faceId); @@ -67,7 +67,7 @@ double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCellFaceResultAccessObject::resultName() const +QString RigCellFaceResultAccessor::resultName() const { return m_resultName; } @@ -75,7 +75,7 @@ QString RigCellFaceResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCellFaceResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h index 27afad5aea..bbb64cc8e9 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -26,12 +26,12 @@ //================================================================================================== /// //================================================================================================== -class RigCellFaceResultAccessObject : public RigResultAccessObject +class RigCellFaceResultAccessor : public RigResultAccessor { public: - RigCellFaceResultAccessObject(const QString& resultName); + RigCellFaceResultAccessor(const QString& resultName); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; @@ -39,7 +39,7 @@ class RigCellFaceResultAccessObject : public RigResultAccessObject virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: - cvf::Collection m_resultAccessObjects; + cvf::Collection m_resultAccessObjects; QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp index a7bb5fdf6d..6e651c55f2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName) +RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName) : m_grid(grid), m_resultName(resultName) { @@ -37,7 +37,7 @@ RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase /// Only sensible to provide the positive values, as the negative ones will never be used. /// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); @@ -47,7 +47,7 @@ void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridI //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const +double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -59,13 +59,13 @@ double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { switch (faceId) { case cvf::StructGridInterface::POS_I: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -74,7 +74,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_I: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -89,7 +89,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::POS_J: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -98,7 +98,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_J: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -113,7 +113,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::POS_K: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -122,7 +122,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_K: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -143,7 +143,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCombTransResultAccessObject::resultName() const +QString RigCombTransResultAccessor::resultName() const { return m_resultName; } @@ -151,7 +151,7 @@ QString RigCombTransResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCombTransResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h index 19e27b487a..5830f410ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h @@ -28,12 +28,12 @@ class RigGridBase; //================================================================================================== /// //================================================================================================== -class RigCombTransResultAccessObject : public RigResultAccessObject +class RigCombTransResultAccessor : public RigResultAccessor { public: - RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName); + RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; @@ -41,7 +41,7 @@ class RigCombTransResultAccessObject : public RigResultAccessObject virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: - cvf::Collection m_resultAccessObjects; + cvf::Collection m_resultAccessObjects; const RigGridBase* m_grid; QString m_resultName; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 0b6ef234bd..af60714385 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -28,7 +28,7 @@ //================================================================================================== /// //================================================================================================== -class RigResultAccessObject : public cvf::Object +class RigResultAccessor : public cvf::Object { public: virtual double cellScalar(size_t localCellIndex) const = 0; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index bede69dffe..bcbc705706 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -39,7 +39,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -83,12 +83,12 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); return object; } else { - cvf::ref object = new RigAllGridCellsResultAccessObject(grid, resultValues, uiResultName); + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues, uiResultName); return object; } } @@ -98,7 +98,7 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -122,11 +122,11 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid, uiResultName); { QString resultName = "TRANX"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); @@ -135,7 +135,7 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess { QString resultName = "TRANY"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); @@ -144,7 +144,7 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess { QString resultName = "TRANZ"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); @@ -287,7 +287,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index aa54258936..8a6ca4bd89 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -24,13 +24,13 @@ class RigActiveCellInfo; class RigGridBase; -class RigResultAccessObject; +class RigResultAccessor; -class RigResultAccessObjectFactory +class RigResultAccessorFactory { public: - static cvf::ref - createResultAccessObject(RigCaseData* eclipseCase, + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -47,8 +47,8 @@ class RigResultAccessObjectFactory private: - static cvf::ref - createNativeDataAccessObject(RigCaseData* eclipseCase, + static cvf::ref + createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From 1a9d9c4ca19cc21a2f20a82f25a7f375e02ff407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 13:32:31 +0200 Subject: [PATCH 068/346] More renaming : AccessObject-Accessor And CellFaceAccessor to CellEdgeAccessor --- .../RigActiveCellsResultAccessObject.cpp | 10 +++++----- .../RigActiveCellsResultAccessObject.h | 4 ++-- .../RigCellFaceResultAccessObject.cpp | 12 ++++++------ .../RigCellFaceResultAccessObject.h | 4 ++-- .../RigResultAccessObjectFactory.cpp | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp index 6552f938f7..643d834575 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -24,7 +24,7 @@ #include -RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) +RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_activeCellInfo(activeCellInfo), @@ -36,7 +36,7 @@ RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGrid //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const +double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; @@ -52,7 +52,7 @@ double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(localCellIndex); } @@ -60,7 +60,7 @@ double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigActiveCellsResultAccessObject::resultName() const +QString RigActiveCellsResultAccessor::resultName() const { return m_resultName; } @@ -68,7 +68,7 @@ QString RigActiveCellsResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigActiveCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 14fb8c1dfe..47f640a17d 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -27,10 +27,10 @@ class RigActiveCellInfo; //================================================================================================== /// //================================================================================================== -class RigActiveCellsResultAccessObject : public RigResultAccessor +class RigActiveCellsResultAccessor : public RigResultAccessor { public: - RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index fe2327d835..eabe99cb33 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -24,7 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) +RigCellEdgeResultAccessor::RigCellEdgeResultAccessor(const QString& resultName) : m_resultName(resultName) { m_resultAccessObjects.resize(6); @@ -33,7 +33,7 @@ RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) +void RigCellEdgeResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { m_resultAccessObjects[faceId] = resultAccessObject; } @@ -41,7 +41,7 @@ void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const +double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -53,7 +53,7 @@ double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); if (resultAccessObj != NULL) @@ -67,7 +67,7 @@ double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::Str //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCellFaceResultAccessor::resultName() const +QString RigCellEdgeResultAccessor::resultName() const { return m_resultName; } @@ -75,7 +75,7 @@ QString RigCellFaceResultAccessor::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCellEdgeResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h index bbb64cc8e9..7d0ead9536 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -26,10 +26,10 @@ //================================================================================================== /// //================================================================================================== -class RigCellFaceResultAccessor : public RigResultAccessor +class RigCellEdgeResultAccessor : public RigResultAccessor { public: - RigCellFaceResultAccessor(const QString& resultName); + RigCellEdgeResultAccessor(const QString& resultName); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index bcbc705706..dccfd0fed9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -83,7 +83,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); return object; } else From 066682974030d37799cef56e06d8621da206bf5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 14:20:20 +0200 Subject: [PATCH 069/346] Renamed files to reflect new classnames --- .../RivReservoirViewPartMgr.cpp | 2 +- .../ReservoirDataModel/CMakeLists_files.cmake | 24 +++++++++---------- ...t.cpp => RigActiveCellsResultAccessor.cpp} | 2 +- ...bject.h => RigActiveCellsResultAccessor.h} | 2 +- ....cpp => RigAllGridCellsResultAccessor.cpp} | 2 +- ...ject.h => RigAllGridCellsResultAccessor.h} | 2 +- .../ReservoirDataModel/RigCaseData.cpp | 2 +- ...ject.cpp => RigCellEdgeResultAccessor.cpp} | 2 +- ...ssObject.h => RigCellEdgeResultAccessor.h} | 2 +- ...ect.cpp => RigCombTransResultAccessor.cpp} | 2 +- ...sObject.h => RigCombTransResultAccessor.h} | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- ...AccessObject.cpp => RigResultAccessor.cpp} | 2 +- ...sultAccessObject.h => RigResultAccessor.h} | 0 ...ctory.cpp => RigResultAccessorFactory.cpp} | 10 ++++---- ...ctFactory.h => RigResultAccessorFactory.h} | 0 16 files changed, 29 insertions(+), 29 deletions(-) rename ApplicationCode/ReservoirDataModel/{RigActiveCellsResultAccessObject.cpp => RigActiveCellsResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigActiveCellsResultAccessObject.h => RigActiveCellsResultAccessor.h} (98%) rename ApplicationCode/ReservoirDataModel/{RigAllGridCellsResultAccessObject.cpp => RigAllGridCellsResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigAllGridCellsResultAccessObject.h => RigAllGridCellsResultAccessor.h} (97%) rename ApplicationCode/ReservoirDataModel/{RigCellFaceResultAccessObject.cpp => RigCellEdgeResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigCellFaceResultAccessObject.h => RigCellEdgeResultAccessor.h} (97%) rename ApplicationCode/ReservoirDataModel/{RigCombTransResultAccessObject.cpp => RigCombTransResultAccessor.cpp} (99%) rename ApplicationCode/ReservoirDataModel/{RigCombTransResultAccessObject.h => RigCombTransResultAccessor.h} (98%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObject.cpp => RigResultAccessor.cpp} (95%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObject.h => RigResultAccessor.h} (100%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObjectFactory.cpp => RigResultAccessorFactory.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObjectFactory.h => RigResultAccessorFactory.h} (100%) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 284985349c..abc229ffa0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -23,7 +23,7 @@ #include "RigCaseData.h" #include "RigGridBase.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" #include "RimCase.h" #include "RimCellRangeFilterCollection.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 123e156828..53420405e8 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,12 +10,12 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h -${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h -${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigResultAccessorFactory.h +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -35,12 +35,12 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp -${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp -${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessorFactory.cpp +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index 643d834575..edd5ae168c 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigActiveCellsResultAccessObject.h" +#include "RigActiveCellsResultAccessor.h" #include "RigGridBase.h" #include "RigActiveCellInfo.h" diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 47f640a17d..306b70fcda 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" class RigGridBase; class RigActiveCellInfo; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 8e240d2f09..7e5762a184 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigAllGridCellsResultAccessObject.h" +#include "RigAllGridCellsResultAccessor.h" #include "RigGridBase.h" diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h similarity index 97% rename from ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 2af694fa50..1c4473daa0 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigActiveCellsResultAccessObject.h" +#include "RigActiveCellsResultAccessor.h" class RigGridBase; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 1b2d8b18bc..8a9192f107 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -19,7 +19,7 @@ #include "RigCaseData.h" #include "RigMainGrid.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index eabe99cb33..a5dfc0ee28 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigCellFaceResultAccessObject.h" +#include "RigCellEdgeResultAccessor.h" #include diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h similarity index 97% rename from ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index 7d0ead9536..73ea161fb8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" #include "cvfCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp similarity index 99% rename from ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 6e651c55f2..86a27788b2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigCombTransResultAccessObject.h" +#include "RigCombTransResultAccessor.h" #include "RigGridBase.h" diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index 5830f410ad..e99002d799 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" #include "cvfCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 4c195270da..1342059660 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -20,7 +20,7 @@ #include "RigMainGrid.h" #include "RigCell.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" #include "cvfAssert.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp similarity index 95% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp index 6d732c7309..160c2b9abe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp @@ -16,4 +16,4 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h similarity index 100% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessor.h diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp rename to ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index dccfd0fed9..0e6fba79b9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -16,11 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" -#include "RigResultAccessObject.h" -#include "RigActiveCellsResultAccessObject.h" -#include "RigAllGridCellsResultAccessObject.h" +#include "RigResultAccessor.h" +#include "RigActiveCellsResultAccessor.h" +#include "RigAllGridCellsResultAccessor.h" #include "cvfLibCore.h" #include "cvfBase.h" @@ -33,7 +33,7 @@ #include "RigGridBase.h" #include "RigCaseData.h" #include -#include "RigCombTransResultAccessObject.h" +#include "RigCombTransResultAccessor.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h similarity index 100% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h From 077a714b8151e6b9c14ed7796c543074b7240058 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:44:28 +0200 Subject: [PATCH 070/346] Ternary legend: Minor layout tweaks --- .../ModelVisualization/RivTernarySaturationOverlayItem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 761f4bb6fb..85404d9cd2 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -142,7 +142,8 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - sgasTextWidth / 2 ), textPosY)); cvf::uint sgasRangeTextWidth = m_font->textExtent(m_sgasRange).x(); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY - lineHeightInPixels)); + textPosY -= lineHeightInPixels; + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY)); } textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); @@ -160,7 +161,8 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textDrawer.renderSoftware(oglContext, camera); - renderAxisImmediateMode(textPosY - lineHeightInPixels, oglContext); + textPosY -= 3; + renderAxisImmediateMode(textPosY, oglContext); CVF_CHECK_OGL(oglContext); } From 584a93d9eb03c704e9d63a64de8c545abfca8cce Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:48:38 +0200 Subject: [PATCH 071/346] Added RigResultModifier --- .../ReservoirDataModel/CMakeLists_files.cmake | 1 + .../ReservoirDataModel/RigResultModifier.h | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifier.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 53420405e8..1da15926a7 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -16,6 +16,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigResultModifier.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h new file mode 100644 index 0000000000..3ab82e3462 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +//================================================================================================== +/// +//================================================================================================== +class RigResultModifier : public cvf::Object +{ +public: + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) = 0; +}; + + + +//================================================================================================== +/// +//================================================================================================== +class RigAllGridCellsResultModifier : public RigResultModifier +{ +public: + RigAllGridCellsResultModifier(const RigGridBase* grid, std::vector* reservoirResultValues) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues) + { + } + + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + } + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + + +//================================================================================================== +/// +//================================================================================================== +class RigActiveCellsResultModifier : public RigResultModifier +{ +public: + RigActiveCellsResultModifier(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo) + { + } + + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; + } + + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + From 53426b910370efb9273a87038192091e066732d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 14:55:33 +0200 Subject: [PATCH 072/346] Replaced dataAccessObject with resultAccessor --- .../RifEclipseInputFileTools.cpp | 6 ++-- .../RivCellEdgeEffectGenerator.cpp | 4 +-- .../RivCellEdgeEffectGenerator.h | 2 +- .../RivFaultGeometryGenerator.cpp | 6 ++-- .../RivFaultGeometryGenerator.h | 2 +- .../ModelVisualization/RivFaultPartMgr.cpp | 10 +++---- .../ModelVisualization/RivGridPartMgr.cpp | 18 +++++------ .../RivReservoirViewPartMgr.cpp | 6 ++-- .../ProjectDataModel/RimReservoirView.cpp | 30 +++++++++---------- .../RimStatisticsCaseEvaluator.cpp | 16 +++++----- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../ReservoirDataModel/RigCaseData.h | 2 +- .../ReservoirDataModel/RigResultAccessor.h | 6 ++-- .../RiaPropertyDataCommands.cpp | 4 +-- .../cvfStructGridGeometryGenerator.cpp | 12 ++++---- .../cvfStructGridGeometryGenerator.h | 2 +- 16 files changed, 64 insertions(+), 64 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 819a65d5a5..74a7892560 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -500,8 +500,8 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa return false; } - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); - if (dataAccessObject.isNull()) + cvf::ref resultAccessor = eclipseCase->resultAccessor(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); + if (resultAccessor.isNull()) { return false; } @@ -514,7 +514,7 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa { for (i = 0; i < eclipseCase->mainGrid()->cellCountI(); i++) { - double resultValue = dataAccessObject->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); + double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); if (resultValue == HUGE_VAL) { resultValue = undefinedValue; diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 8c1b6ed601..0dd9043c09 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -121,7 +121,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( } RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); + cellCenterDataAccessObject = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); } CVF_ASSERT(cellEdgeResultSlot->hasResult()); @@ -140,7 +140,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( { // Assuming static values to be mapped onto cell edge, always using time step zero // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->dataAccessObject(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); + daObj = eclipseCase->resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); } cellEdgeDataAccessObjects.push_back(daObj.p()); diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index ba2a6018a6..8fea369a1c 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -90,7 +90,7 @@ class RivCellEdgeGeometryGenerator texCoords.resize(m_quadsToGridCells.size()*4); for (i = 0; i < m_quadsToGridCells.size(); ++i) { - cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(dataAccessObject->cellScalar(m_quadsToGridCells[i])); + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(resultAccessor->cellScalar(m_quadsToGridCells[i])); ResValue ResPoint To ResValue texCoords[i*4 + 0] = texCoord; texCoords[i*4 + 1] = texCoord; diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index e9ed113620..a45a4dad3e 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -203,9 +203,9 @@ void RivFaultGeometryGenerator::computeArrays() /// Calculates the texture coordinates in a "nearly" one dimensional texture. /// Undefined values are coded with a y-texture coordinate value of 1.0 instead of the normal 0.5 //-------------------------------------------------------------------------------------------------- -void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* dataAccessObject, const cvf::ScalarMapper* mapper) const +void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* resultAccessor, const cvf::ScalarMapper* mapper) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; size_t numVertices = m_quadMapper->quadCount()*4; @@ -218,7 +218,7 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord #pragma omp parallel for private(texCoord, cellScalarValue) for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); + cellScalarValue = resultAccessor->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index 81162a67c7..f0e8fd1cc2 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -48,7 +48,7 @@ class RivFaultGeometryGenerator : public cvf::Object void setCellVisibility(const cvf::UByteArray* cellVisibilities ); void textureCoordinates(cvf::Vec2fArray* textureCoords, - const cvf::StructGridScalarDataAccess* dataAccessObject, + const cvf::StructGridScalarDataAccess* resultAccessor, const cvf::ScalarMapper* mapper) const; // Mapping between cells and geometry diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 731faf4dae..2d261dfc0c 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -117,7 +117,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); + cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); // Faults if (m_nativeFaultFaces.notNull()) @@ -139,11 +139,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - if (dataAccessObject.isNull()) + if (resultAccessor.isNull()) { return; } - m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); } @@ -212,12 +212,12 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - if (dataAccessObject.isNull()) + if (resultAccessor.isNull()) { return; } - m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); } if (m_opacityLevel < 1.0f ) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 98145b17ad..47fe6765b8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -243,10 +243,10 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (dataAccessObject.isNull()) return; + cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); + if (resultAccessor.isNull()) return; - m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), resultAccessor.p(), mapper); } @@ -460,9 +460,9 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObjectTranX = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); + cvf::ref dataAccessObjectTranX = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); + cvf::ref dataAccessObjectTranY = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); + cvf::ref dataAccessObjectTranZ = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); int quadCount = static_cast(quadToCellFaceMapper->quadCount()); @@ -601,19 +601,19 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - cvf::ref dataAccessObjectSoil = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectSoil = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); if (dataAccessObjectSoil.isNull()) { dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSgas = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectSgas = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); if (dataAccessObjectSgas.isNull()) { dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSwat = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, swatScalarSetIndex); + cvf::ref dataAccessObjectSwat = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); if (dataAccessObjectSwat.isNull()) { dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index abc229ffa0..e3fa51f9af 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -728,8 +728,8 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); - CVF_ASSERT(dataAccessObject.notNull()); + cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) for (int cellIndex = 0; cellIndex < static_cast(grid->cellCount()); cellIndex++) @@ -738,7 +738,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis { size_t resultValueIndex = cellIndex; - double scalarValue = dataAccessObject->cellScalar(resultValueIndex); + double scalarValue = resultAccessor->cellScalar(resultValueIndex); if (lowerBound <= scalarValue && scalarValue <= upperBound) { if (filterType == RimCellFilter::EXCLUDE) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index fe969de1ac..d7cb997020 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1105,7 +1105,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, RigGridBase* grid = eclipseCase->grid(gridIndex); RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject; + cvf::ref resultAccessor; if (this->cellResult()->isTernarySaturationSelected()) { @@ -1116,9 +1116,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - cvf::ref dataAccessObjectX = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); + cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); + cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); double scalarValue = 0.0; @@ -1138,7 +1138,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, else if (this->cellResult()->hasResult()) { RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject; + cvf::ref resultAccessor; if (cellResult->hasStaticResult()) { @@ -1147,9 +1147,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t tranX, tranY, tranZ; if (eclipseCase->results(porosityModel)->findTransmissibilityResults(tranX, tranY, tranZ)) { - cvf::ref dataAccessObjectX = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranX); - cvf::ref dataAccessObjectY = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranY); - cvf::ref dataAccessObjectZ = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranZ); + cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, 0, tranX); + cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, 0, tranY); + cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, 0, tranZ); double scalarValue = dataAccessObjectX->cellScalar(cellIndex); resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); @@ -1163,17 +1163,17 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, } else { - dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); } } else { - dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); } - if (dataAccessObject.notNull()) + if (resultAccessor.notNull()) { - double scalarValue = dataAccessObject->cellScalar(cellIndex); + double scalarValue = resultAccessor->cellScalar(cellIndex); resultInfoText->append(QString("Cell result : %1\n").arg(scalarValue)); } } @@ -1191,10 +1191,10 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, 0, resultIndices[idx]); - if (dataAccessObject.notNull()) + cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, resultIndices[idx]); + if (resultAccessor.notNull()) { - double scalarValue = dataAccessObject->cellScalar(cellIndex); + double scalarValue = resultAccessor->cellScalar(cellIndex); resultInfoText->append(QString("%1 : %2\n").arg(resultNames[idx]).arg(scalarValue)); } } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index ecb06dd92f..ae6f742925 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -194,15 +194,15 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - cvf::ref dataAccessObject = sourceCase->reservoirData()->dataAccessObject(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); - if (dataAccessObject.notNull()) + cvf::ref resultAccessor = sourceCase->reservoirData()->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + if (resultAccessor.notNull()) { - sourceDataAccessList.push_back(dataAccessObject.p()); + sourceDataAccessList.push_back(resultAccessor.p()); } } // Build data access objects for destination scalar results - // Find the created result container, if any, and put its dataAccessObject into the enum indexed destination collection + // Find the created result container, if any, and put its resultAccessor into the enum indexed destination collection cvf::Collection destinationDataAccessList; std::vector statisticalResultNames(STAT_PARAM_COUNT); @@ -221,7 +221,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = destCellResultsData->findScalarResultIndex(resultType, statisticalResultNames[stIdx]); if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) { - destinationDataAccessList.push_back(m_destinationCase->dataAccessObject(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); + destinationDataAccessList.push_back(m_destinationCase->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); } else { @@ -351,12 +351,12 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - cvf::ref dataAccessObject = m_destinationCase->dataAccessObject(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); - if (dataAccessObject.isNull()) return; + cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); + if (resultAccessor.isNull()) return; for (size_t cellIdx = 0; cellIdx < m_globalCellCount; cellIdx++) { - qDebug() << dataAccessObject->cellScalar(cellIdx); + qDebug() << resultAccessor->cellScalar(cellIdx); } } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 8a9192f107..34830722fd 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -488,7 +488,7 @@ const RigCaseCellResultsData* RigCaseData::results(RifReaderInterface::PorosityM //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigCaseData::dataAccessObject(const RigGridBase* grid, +cvf::ref RigCaseData::resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index 2ab3432815..68960b381a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -54,7 +54,7 @@ class RigCaseData: public cvf::Object void setActiveCellInfo(RifReaderInterface::PorosityModelResultType porosityModel, RigActiveCellInfo* activeCellInfo); - cvf::ref dataAccessObject(const RigGridBase* grid, + cvf::ref resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index af60714385..fb1837c3bb 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -188,9 +188,9 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + cvf::ref resultAccessor = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - if (dataAccessObject.isNull()) return; + if (resultAccessor.isNull()) return; RivResultToTextureMapper texMapper(mapper, RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), @@ -210,7 +210,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); - cellScalarValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); + cellScalarValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); texCoord = texMapper->mapToTextureCoord(cellScalarValue); diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 85d154a2a4..01073c5cc8 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -322,7 +322,7 @@ class RiaGetGridProperty: public RiaSocketCommand for (size_t tsIdx = 0; tsIdx < timestepCount; tsIdx++) { - cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->dataAccessObject(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); + cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->resultAccessor(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); if (cellCenterDataAccessObject.isNull()) { continue; @@ -935,7 +935,7 @@ class RiaSetGridProperty : public RiaSocketCommand } cvf::ref cellCenterDataAccessObject = - m_currentReservoir->reservoirData()->dataAccessObject(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); + m_currentReservoir->reservoirData()->resultAccessor(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); if (!cellCenterDataAccessObject.isNull()) { diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index a5dbdd0633..3af8efd688 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -383,9 +383,9 @@ void StructGridGeometryGenerator::computeArrays() /// Calculates the texture coordinates in a "nearly" one dimentional texture. /// Undefined values are coded with a y-texturecoordinate value of 1.0 instead of the normal 0.5 //-------------------------------------------------------------------------------------------------- -void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const +void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* resultAccessor, const ScalarMapper* mapper) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; size_t numVertices = m_quadMapper->quadCount()*4; @@ -398,7 +398,7 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, #pragma omp parallel for private(texCoord, cellScalarValue) for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); + cellScalarValue = resultAccessor->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -418,9 +418,9 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, /// /// //-------------------------------------------------------------------------------------------------- -void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* dataAccessObject) const +void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* resultAccessor) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; textureCoords->resize(m_quadMapper->quadCount()*4); @@ -433,7 +433,7 @@ void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fAr #pragma omp parallel for private(texCoord, cellFaceValue) for (int qIdx = 0; qIdx < quadCount; qIdx++) { - cellFaceValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); + cellFaceValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); texCoord = mapper->mapToTextureCoord(cellFaceValue); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index 32f0c2cafa..cced178fe9 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -173,7 +173,7 @@ class StructGridGeometryGenerator : public Object const StructGridInterface* activeGrid() { return m_grid.p(); } - void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const; + void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* resultAccessor, const ScalarMapper* mapper) const; // Mapping between cells and geometry From 0157181e5b1477d64d9db3cbe3fa1121298d49ef Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:56:29 +0200 Subject: [PATCH 073/346] Removed setCellScalar and resultName from Resultaccessor --- .../RigActiveCellsResultAccessor.cpp | 25 ++----------------- .../RigActiveCellsResultAccessor.h | 5 +--- .../RigAllGridCellsResultAccessor.cpp | 23 ++--------------- .../RigAllGridCellsResultAccessor.h | 5 +--- .../RigCellEdgeResultAccessor.cpp | 21 +--------------- .../RigCellEdgeResultAccessor.h | 6 +---- .../RigCombTransResultAccessor.cpp | 23 ++--------------- .../RigCombTransResultAccessor.h | 5 +--- .../ReservoirDataModel/RigResultAccessor.h | 4 --- .../RigResultAccessorFactory.cpp | 6 ++--- 10 files changed, 14 insertions(+), 109 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index edd5ae168c..a72a3b1ec4 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -24,11 +24,10 @@ #include -RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) +RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), - m_activeCellInfo(activeCellInfo), - m_resultName(resultName) + m_activeCellInfo(activeCellInfo) { } @@ -57,23 +56,3 @@ double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf:: return cellScalar(localCellIndex); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigActiveCellsResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigActiveCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); - - CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[resultValueIndex] = scalarValue; -} diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 306b70fcda..9647033722 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -30,17 +30,14 @@ class RigActiveCellInfo; class RigActiveCellsResultAccessor : public RigResultAccessor { public: - RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: const RigActiveCellInfo* m_activeCellInfo; const RigGridBase* m_grid; std::vector* m_reservoirResultValues; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 7e5762a184..5ba549176f 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -26,10 +26,9 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) +RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues) : m_grid(grid), - m_reservoirResultValues(reservoirResultValues), - m_resultName(resultName) + m_reservoirResultValues(reservoirResultValues) { } @@ -54,21 +53,3 @@ double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf: return cellScalar(localCellIndex); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigAllGridCellsResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigAllGridCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; -} diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 1c4473daa0..840e3f46a7 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -29,17 +29,14 @@ class RigGridBase; class RigAllGridCellsResultAccessor : public RigResultAccessor { public: - RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: const RigGridBase* m_grid; std::vector* m_reservoirResultValues; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index a5dfc0ee28..f94aebe8c2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -24,8 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellEdgeResultAccessor::RigCellEdgeResultAccessor(const QString& resultName) - : m_resultName(resultName) +RigCellEdgeResultAccessor::RigCellEdgeResultAccessor() { m_resultAccessObjects.resize(6); } @@ -64,21 +63,3 @@ double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::Str return HUGE_VAL; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigCellEdgeResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCellEdgeResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - // TODO: How to handle when we get here? - CVF_ASSERT(false); - -} - diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index 73ea161fb8..cdc70c0937 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -29,17 +29,13 @@ class RigCellEdgeResultAccessor : public RigResultAccessor { public: - RigCellEdgeResultAccessor(const QString& resultName); + RigCellEdgeResultAccessor(); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: cvf::Collection m_resultAccessObjects; - - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 86a27788b2..af7b992e7f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -26,9 +26,8 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName) - : m_grid(grid), - m_resultName(resultName) +RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid) + : m_grid(grid) { m_resultAccessObjects.resize(6); } @@ -140,21 +139,3 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St return HUGE_VAL; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigCombTransResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - // TODO: How to handle when we get here? - CVF_ASSERT(false); - -} - diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index e99002d799..6a7a0b5cda 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -31,18 +31,15 @@ class RigGridBase; class RigCombTransResultAccessor : public RigResultAccessor { public: - RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName); + RigCombTransResultAccessor(const RigGridBase* grid); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: cvf::Collection m_resultAccessObjects; const RigGridBase* m_grid; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index fb1837c3bb..a49bdc62da 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -33,10 +33,6 @@ class RigResultAccessor : public cvf::Object public: virtual double cellScalar(size_t localCellIndex) const = 0; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - - virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; #if 0 diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 0e6fba79b9..66096010cd 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -83,12 +83,12 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); return object; } else { - cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues, uiResultName); + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); return object; } } @@ -122,7 +122,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid, uiResultName); + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); { QString resultName = "TRANX"; From 5382122094aafdb7a60833e3dca7ac424eb7a666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 15:30:12 +0200 Subject: [PATCH 074/346] Trimmed CombTransResultAccessor interface setTransResultAccessors --- .../RigCombTransResultAccessor.cpp | 49 +++++++++---------- .../RigCombTransResultAccessor.h | 11 +++-- .../RigResultAccessorFactory.cpp | 39 +++------------ .../RigResultAccessorFactory.h | 4 +- 4 files changed, 39 insertions(+), 64 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index af7b992e7f..2e67ac5b6f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -29,18 +29,21 @@ RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid) : m_grid(grid) { - m_resultAccessObjects.resize(6); + } //-------------------------------------------------------------------------------------------------- /// Only sensible to provide the positive values, as the negative ones will never be used. /// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) -{ - CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); +void RigCombTransResultAccessor::setTransResultAccessors(RigResultAccessor* xTransAccessor, + RigResultAccessor* yTransAccessor, + RigResultAccessor* zTransAccessor) - m_resultAccessObjects[faceId] = resultAccessObject; +{ + m_xTransAccessor = xTransAccessor; + m_yTransAccessor = yTransAccessor; + m_zTransAccessor = zTransAccessor; } //-------------------------------------------------------------------------------------------------- @@ -48,11 +51,9 @@ void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInter //-------------------------------------------------------------------------------------------------- double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const { + CVF_TIGHT_ASSERT(false); - // TODO: How to handle when we get here? - CVF_ASSERT(false); - - return cvf::UNDEFINED_DOUBLE; + return HUGE_VAL; } //-------------------------------------------------------------------------------------------------- @@ -64,72 +65,66 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { case cvf::StructGridInterface::POS_I: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); - if (resultAccessObj) + if (m_xTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_xTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_I: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); - if (resultAccessObj) + if (m_xTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_xTransAccessor->cellScalar(neighborGridCellIdx); } } } break; case cvf::StructGridInterface::POS_J: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); - if (resultAccessObj) + if (m_yTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_yTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_J: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); - if (resultAccessObj) + if (m_yTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_yTransAccessor->cellScalar(neighborGridCellIdx); } } } break; case cvf::StructGridInterface::POS_K: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); - if (resultAccessObj) + if (m_zTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_zTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_K: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); - if (resultAccessObj) + if (m_zTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_zTransAccessor->cellScalar(neighborGridCellIdx); } } } diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index 6a7a0b5cda..fe9b89128f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -33,13 +33,18 @@ class RigCombTransResultAccessor : public RigResultAccessor public: RigCombTransResultAccessor(const RigGridBase* grid); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); + void setTransResultAccessors(RigResultAccessor* xTransAccessor, + RigResultAccessor* yTransAccessor, + RigResultAccessor* zTransAccessor); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: - cvf::Collection m_resultAccessObjects; - + + cvf::ref m_xTransAccessor; + cvf::ref m_yTransAccessor; + cvf::ref m_zTransAccessor; + const RigGridBase* m_grid; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 66096010cd..ff735d47a9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -43,7 +43,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName) + const QString& uiResultName) { CVF_ASSERT(gridIndex < eclipseCase->gridCount()); CVF_ASSERT(eclipseCase); @@ -102,7 +102,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName) + const QString& uiResultName) { CVF_ASSERT(gridIndex < eclipseCase->gridCount()); CVF_ASSERT(eclipseCase); @@ -118,38 +118,13 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa } else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) { - // TODO - // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates - // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - { - QString resultName = "TRANX"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); - } - } - - { - QString resultName = "TRANY"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); - } - } - - { - QString resultName = "TRANZ"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); - } - } + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); + + cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); return cellFaceAccessObject; } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 8a6ca4bd89..6a4a414865 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -34,7 +34,7 @@ class RigResultAccessorFactory size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName); + const QString& uiResultName); // TO BE DELETED @@ -52,7 +52,7 @@ class RigResultAccessorFactory size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& resultName); + const QString& resultName); }; From 161cba253d3e919cdbc7383af4c11f51f931fa04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 15:53:05 +0200 Subject: [PATCH 075/346] Removed fvector and replaced with FixedArray. Needs replacing with std::array when we get to c++11 --- .../ProjectDataModel/RimCellEdgeResultSlot.cpp | 10 +++++----- .../ProjectDataModel/RimCellEdgeResultSlot.h | 15 ++------------- .../RigResultAccessorFactory.cpp | 6 +----- Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h | 4 ++-- 4 files changed, 10 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 48cbe7ffc2..b52e9f0cec 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -144,7 +144,7 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const QList optionList; - std::map > varBaseNameToVarsMap; + std::map > varBaseNameToVarsMap; int i; for (i = 0; i < varList.size(); ++i) @@ -164,7 +164,7 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const } } - std::map >::iterator it; + std::map >::iterator it; for (it = varBaseNameToVarsMap.begin(); it != varBaseNameToVarsMap.end(); ++it) { @@ -174,16 +174,16 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const bool firstText = true; for (cubeFaceIdx = 0; cubeFaceIdx < 6; ++cubeFaceIdx) { - if (!it->second.v[cubeFaceIdx].isEmpty()) + if (!it->second[cubeFaceIdx].isEmpty()) { if (firstText) { - optionUiName += it->second.v[cubeFaceIdx]; + optionUiName += it->second[cubeFaceIdx]; firstText = false; } else { - optionUiName += QString(", ") + it->second.v[cubeFaceIdx]; + optionUiName += QString(", ") + it->second[cubeFaceIdx]; } } } diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h index 4bf0bd1ef1..51ebce253a 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h @@ -22,23 +22,12 @@ #include "cafPdmField.h" #include "cafAppEnum.h" #include "RimDefines.h" +#include "cafFixedArray.h" class RigCaseCellResultsData; class RimLegendConfig; class RimReservoirView; -namespace caf -{ -template -class fvector -{ -public: - T v[vectorSize]; - T& operator[] (size_t idx) { return v[idx]; } -const T& operator[] (size_t idx) const { return v[idx]; } - -}; -} //================================================================================================== /// @@ -86,7 +75,7 @@ class RimCellEdgeResultSlot : public caf::PdmObject void resetResultIndices(); void updateIgnoredScalarValue(); protected: - caf::fvector, 6 > m_resultNameToIndexPairs; + caf::FixedArray, 6 > m_resultNameToIndexPairs; caf::PdmPointer m_reservoirView; double m_ignoredResultScalar; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index ff735d47a9..4b45c963b0 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -64,11 +64,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor } std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); - - // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps - // See RiaSetGridProperty command in RiaPropertyDataCommands - // - // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) { return NULL; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h b/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h index 56a8c83393..6602c333cb 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h @@ -55,8 +55,8 @@ class FixedArray FixedArray& operator=(const T* ptr) { for (size_t i = 0; i < size ; ++i) m_array[i] = ptr[i]; return *this;} - template T& operator[](const IndexType& index) { CVF_TIGHT_ASSERT(static_cast(index) < size); return m_array[index]; } - template const T& operator[](const IndexType& index) const { CVF_TIGHT_ASSERT(static_cast(index) < size); return m_array[index]; } + template T& operator[](const IndexType& index) { return m_array[index]; } + template const T& operator[](const IndexType& index) const { return m_array[index]; } }; typedef FixedArray IntArray3; From a5e926ce1b123ef84febddbfaa5b6f255e4bd165 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 8 Aug 2014 08:37:56 +0200 Subject: [PATCH 076/346] Added RigResultModifier and use this object for result modifications --- .../RimStatisticsCaseEvaluator.cpp | 16 ++- .../RimStatisticsCaseEvaluator.h | 1 - .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigResultAccessorFactory.cpp | 2 +- .../ReservoirDataModel/RigResultModifier.h | 3 + .../RigResultModifierFactory.cpp | 102 ++++++++++++++++++ .../RigResultModifierFactory.h | 44 ++++++++ .../RiaPropertyDataCommands.cpp | 37 +++---- 8 files changed, 175 insertions(+), 32 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index ae6f742925..5693b69ec9 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,7 +20,10 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultModifier.h" +#include "RigResultModifierFactory.h" #include "RigStatisticsMath.h" + #include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" @@ -204,7 +207,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result // Build data access objects for destination scalar results // Find the created result container, if any, and put its resultAccessor into the enum indexed destination collection - cvf::Collection destinationDataAccessList; + cvf::Collection destinationDataAccessList; std::vector statisticalResultNames(STAT_PARAM_COUNT); statisticalResultNames[MIN] = createResultNameMin(resultName); @@ -219,14 +222,9 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result for (size_t stIdx = 0; stIdx < statisticalResultNames.size(); ++stIdx) { size_t scalarResultIndex = destCellResultsData->findScalarResultIndex(resultType, statisticalResultNames[stIdx]); - if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) - { - destinationDataAccessList.push_back(m_destinationCase->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); - } - else - { - destinationDataAccessList.push_back(NULL); - } + + cvf::ref resultModifier = RigResultModifierFactory::createResultModifier(m_destinationCase, grid->gridIndex(), poroModel, dataAccessTimeStepIndex, scalarResultIndex); + destinationDataAccessList.push_back(resultModifier.p()); } std::vector statParams(STAT_PARAM_COUNT, HUGE_VAL); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 906ad17c7d..6e3392ef7a 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -24,7 +24,6 @@ #include #include -#include class RimCase; class RigCaseData; diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 1da15926a7..950bbb3f0d 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -17,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigResultModifier.h +${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -42,6 +43,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 4b45c963b0..41c30f3fc7 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -37,7 +37,7 @@ //-------------------------------------------------------------------------------------------------- -/// +/// This function must be harmonized with RigResultModifierFactory::createResultModifier() //-------------------------------------------------------------------------------------------------- cvf::ref RigResultAccessorFactory::createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h index 3ab82e3462..4c9d8d7dc1 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifier.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -18,6 +18,9 @@ #pragma once +#include "RigGridBase.h" +#include "RigActiveCellInfo.h" + //================================================================================================== /// diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp new file mode 100644 index 0000000000..80efe51c5a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultModifierFactory.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultModifier.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// This function must be harmonized with RigResultAccessorFactory::createNativeResultAccessor() +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultModifierFactory::createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(uiResultName); + + return createResultModifier(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultModifierFactory::createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, size_t scalarResultIndex) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarResultIndex); + + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarResultIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultModifier(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultModifier(grid, resultValues); + return object; + } +} diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h new file mode 100644 index 0000000000..18f7dbd3f3 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifReaderInterface.h" + +class RigCaseData; +class RigResultModifier; + +class RigResultModifierFactory +{ +public: + static cvf::ref + createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName); + + static cvf::ref + createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarResultIndex); +}; + + diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 01073c5cc8..101f9edcea 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -16,34 +16,31 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaStdInclude.h" + #include "RiaSocketCommand.h" +#include "RiaSocketDataTransfer.h" #include "RiaSocketServer.h" #include "RiaSocketTools.h" -#include "RiuMainWindow.h" -#include "RiuProcessMonitor.h" +#include "RifReaderInterface.h" -#include "RigCaseData.h" +#include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultModifier.h" +#include "RigResultModifierFactory.h" -#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" +#include "RimInputProperty.h" #include "RimInputPropertyCollection.h" -#include "RimUiTreeModelPdm.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" - -#include -#include "RiaApplication.h" -#include "RiaPreferences.h" -#include "RiaSocketDataTransfer.h" -#include "RimInputProperty.h" +#include "RimUiTreeModelPdm.h" + +#include "RiuMainWindow.h" +#include "RiuProcessMonitor.h" //-------------------------------------------------------------------------------------------------- @@ -934,14 +931,12 @@ class RiaSetGridProperty : public RiaSocketCommand return true; } - cvf::ref cellCenterDataAccessObject = - m_currentReservoir->reservoirData()->resultAccessor(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); - - if (!cellCenterDataAccessObject.isNull()) + cvf::ref resultModifier = RigResultModifierFactory::createResultModifier(m_currentReservoir->reservoirData(), grid->gridIndex(), m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); + if (!resultModifier.isNull()) { for (size_t cellIdx = 0; static_cast(cellIdx) < cellCountFromOctave; cellIdx++) { - cellCenterDataAccessObject->setCellScalar(cellIdx, doubleValues[cellIdx]); + resultModifier->setCellScalar(cellIdx, doubleValues[cellIdx]); } } From d10de8cddf9118bf943ed4aaaab96c3de3d36627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 08:38:12 +0200 Subject: [PATCH 077/346] cellEdgeAccessor : Use FixedArray instead of collection --- .../ReservoirDataModel/RigCellEdgeResultAccessor.cpp | 4 ++-- .../ReservoirDataModel/RigCellEdgeResultAccessor.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index f94aebe8c2..52f1c136da 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- RigCellEdgeResultAccessor::RigCellEdgeResultAccessor() { - m_resultAccessObjects.resize(6); + } //-------------------------------------------------------------------------------------------------- @@ -54,7 +54,7 @@ double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects[faceId].p(); if (resultAccessObj != NULL) { return resultAccessObj->cellFaceScalar(localCellIndex, faceId); diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index cdc70c0937..b6fb3d8534 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -20,7 +20,7 @@ #include "RigResultAccessor.h" -#include "cvfCollection.h" +#include "cafFixedArray.h" //================================================================================================== @@ -37,5 +37,5 @@ class RigCellEdgeResultAccessor : public RigResultAccessor virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: - cvf::Collection m_resultAccessObjects; + caf::FixedArray, 6> m_resultAccessObjects; }; From efd571c7debe797a67a92979625aba1b761d29a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 09:50:57 +0200 Subject: [PATCH 078/346] Renamed localCellIndex to gridLocalCellIndex --- .../FileInterface/RifReaderEclipseOutput.cpp | 24 +++++++++---------- .../ProjectDataModel/RimReservoirView.cpp | 8 +++---- .../RigActiveCellsResultAccessor.cpp | 8 +++---- .../RigActiveCellsResultAccessor.h | 4 ++-- .../RigAllGridCellsResultAccessor.cpp | 8 +++---- .../RigAllGridCellsResultAccessor.h | 4 ++-- .../RigCellEdgeResultAccessor.cpp | 6 ++--- .../RigCellEdgeResultAccessor.h | 4 ++-- .../RigCombTransResultAccessor.cpp | 16 ++++++------- .../RigCombTransResultAccessor.h | 4 ++-- .../ReservoirDataModel/RigFault.cpp | 6 ++--- .../ReservoirDataModel/RigResultAccessor.h | 12 +++++----- .../SocketInterface/RiaGeometryCommands.cpp | 8 +++---- 13 files changed, 56 insertions(+), 56 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index a620ce1893..a5650aa826 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -112,29 +112,29 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn // Loop over cells and fill them with data #pragma omp parallel for - for (int localCellIdx = 0; localCellIdx < cellCount; ++localCellIdx) + for (int gridLocalCellIndex = 0; gridLocalCellIndex < cellCount; ++gridLocalCellIndex) { - RigCell& cell = mainGrid->cells()[cellStartIndex + localCellIdx]; + RigCell& cell = mainGrid->cells()[cellStartIndex + gridLocalCellIndex]; - cell.setCellIndex(localCellIdx); + cell.setCellIndex(gridLocalCellIndex); // Active cell index - int matrixActiveIndex = ecl_grid_get_active_index1(localEclGrid, localCellIdx); + int matrixActiveIndex = ecl_grid_get_active_index1(localEclGrid, gridLocalCellIndex); if (matrixActiveIndex != -1) { - activeCellInfo->setCellResultIndex(cellStartIndex + localCellIdx, matrixActiveStartIndex + matrixActiveIndex); + activeCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, matrixActiveStartIndex + matrixActiveIndex); } - int fractureActiveIndex = ecl_grid_get_active_fracture_index1(localEclGrid, localCellIdx); + int fractureActiveIndex = ecl_grid_get_active_fracture_index1(localEclGrid, gridLocalCellIndex); if (fractureActiveIndex != -1) { - fractureActiveCellInfo->setCellResultIndex(cellStartIndex + localCellIdx, fractureActiveStartIndex + fractureActiveIndex); + fractureActiveCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, fractureActiveStartIndex + fractureActiveIndex); } // Parent cell index - int parentCellIndex = ecl_grid_get_parent_cell1(localEclGrid, localCellIdx); + int parentCellIndex = ecl_grid_get_parent_cell1(localEclGrid, gridLocalCellIndex); if (parentCellIndex == -1) { cell.setParentCellIndex(cvf::UNDEFINED_SIZE_T); @@ -148,14 +148,14 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn int cIdx; for (cIdx = 0; cIdx < 8; ++cIdx) { - double * point = mainGrid->nodes()[nodeStartIndex + localCellIdx * 8 + cellMappingECLRi[cIdx]].ptr(); - ecl_grid_get_corner_xyz1(localEclGrid, localCellIdx, cIdx, &(point[0]), &(point[1]), &(point[2])); + double * point = mainGrid->nodes()[nodeStartIndex + gridLocalCellIndex * 8 + cellMappingECLRi[cIdx]].ptr(); + ecl_grid_get_corner_xyz1(localEclGrid, gridLocalCellIndex, cIdx, &(point[0]), &(point[1]), &(point[2])); point[2] = -point[2]; // Flipping Z making depth become negative z values - cell.cornerIndices()[cIdx] = nodeStartIndex + localCellIdx*8 + cIdx; + cell.cornerIndices()[cIdx] = nodeStartIndex + gridLocalCellIndex*8 + cIdx; } // Sub grid in cell - const ecl_grid_type* subGrid = ecl_grid_get_cell_lgr1(localEclGrid, localCellIdx); + const ecl_grid_type* subGrid = ecl_grid_get_cell_lgr1(localEclGrid, gridLocalCellIndex); if (subGrid != NULL) { int subGridId = ecl_grid_get_lgr_nr(subGrid); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index d7cb997020..39492f74ec 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1899,10 +1899,10 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t localCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.cellIndex(); size_t i, j, k; - if (hostGrid->ijkFromCellIndex(localCellIndex, &i, &j, &k)) + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) { // Adjust to 1-based Eclipse indexing i++; @@ -1921,10 +1921,10 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c2GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t localCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.cellIndex(); size_t i, j, k; - if (hostGrid->ijkFromCellIndex(localCellIndex, &i, &j, &k)) + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) { // Adjust to 1-based Eclipse indexing i++; diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index a72a3b1ec4..7555ad8c4d 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -35,11 +35,11 @@ RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* gr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const +double RigActiveCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; @@ -51,8 +51,8 @@ double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigActiveCellsResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { - return cellScalar(localCellIndex); + return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 9647033722..4cd7ae73f0 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -32,8 +32,8 @@ class RigActiveCellsResultAccessor : public RigResultAccessor public: RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: const RigActiveCellInfo* m_activeCellInfo; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 5ba549176f..14b7b30a3c 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -35,11 +35,11 @@ RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const +double RigAllGridCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); return m_reservoirResultValues->at(globalGridCellIndex); @@ -48,8 +48,8 @@ double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigAllGridCellsResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { - return cellScalar(localCellIndex); + return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 840e3f46a7..194b591d4d 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -31,8 +31,8 @@ class RigAllGridCellsResultAccessor : public RigResultAccessor public: RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: const RigGridBase* m_grid; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index 52f1c136da..f21876d427 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -40,7 +40,7 @@ void RigCellEdgeResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const +double RigCellEdgeResultAccessor::cellScalar(size_t gridLocalCellIndex) const { // TODO: How to handle when we get here? @@ -52,12 +52,12 @@ double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellEdgeResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { const RigResultAccessor* resultAccessObj = m_resultAccessObjects[faceId].p(); if (resultAccessObj != NULL) { - return resultAccessObj->cellFaceScalar(localCellIndex, faceId); + return resultAccessObj->cellFaceScalar(gridLocalCellIndex, faceId); } return HUGE_VAL; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index b6fb3d8534..4ca4d0a09a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -33,8 +33,8 @@ class RigCellEdgeResultAccessor : public RigResultAccessor void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: caf::FixedArray, 6> m_resultAccessObjects; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 2e67ac5b6f..715a073137 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -49,7 +49,7 @@ void RigCombTransResultAccessor::setTransResultAccessors(RigResultAccessor* xTra //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const +double RigCombTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const { CVF_TIGHT_ASSERT(false); @@ -59,7 +59,7 @@ double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCombTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { switch (faceId) { @@ -67,7 +67,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_xTransAccessor.notNull()) { - return m_xTransAccessor->cellScalar(localCellIndex); + return m_xTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -76,7 +76,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_xTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) { @@ -89,7 +89,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_yTransAccessor.notNull()) { - return m_yTransAccessor->cellScalar(localCellIndex); + return m_yTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -98,7 +98,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_yTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) { @@ -111,7 +111,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_zTransAccessor.notNull()) { - return m_zTransAccessor->cellScalar(localCellIndex); + return m_zTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -120,7 +120,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_zTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) { diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index fe9b89128f..2ecdc6202c 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -37,8 +37,8 @@ class RigCombTransResultAccessor : public RigResultAccessor RigResultAccessor* yTransAccessor, RigResultAccessor* zTransAccessor); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 6bfaba0dca..8d9cfc5560 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,16 +115,16 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t globalCellIndex = grid->globalGridCellIndex(localCellIndex); + //size_t globalCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); if (ni < mainGrid->cellCountI() && nj < mainGrid->cellCountJ() && nk < mainGrid->cellCountK()) { - size_t localCellIndex = mainGrid->cellIndexFromIJK(i, j, k); + size_t gridLocalCellIndex = mainGrid->cellIndexFromIJK(i, j, k); size_t oppositeCellIndex = mainGrid->cellIndexFromIJK(ni, nj, nk); - m_faultFaces.push_back(FaultFace(localCellIndex, faceEnum, oppositeCellIndex)); + m_faultFaces.push_back(FaultFace(gridLocalCellIndex, faceEnum, oppositeCellIndex)); } else { diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index a49bdc62da..1113695e22 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -31,8 +31,8 @@ class RigResultAccessor : public cvf::Object { public: - virtual double cellScalar(size_t localCellIndex) const = 0; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + virtual double cellScalar(size_t gridLocalCellIndex) const = 0; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; #if 0 @@ -43,8 +43,8 @@ class RigResultAccessor : public cvf::Object class RigResultAccessor2d : public cvf::Object { public: - virtual cvf::Vec2d cellScalar(size_t localCellIndex) const = 0; - virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; virtual QString resultName() const = 0; @@ -61,8 +61,8 @@ class RigTernaryResultAccessor : public Rig2DResultAccessor /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others - virtual cvf::Vec2d cellScalar(size_t localCellIndex) { }; - virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t localCellIndex); }; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) { }; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t gridLocalCellIndex); }; virtual QString resultName() const = 0; diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index a682b5b3cb..567dc990eb 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -101,8 +101,8 @@ class RiaGetCellCenters : public RiaSocketCommand { for (size_t i = 0; i < cellCountI; i++) { - size_t localCellIdx = rigGrid->cellIndexFromIJK(i, j, k); - cvf::Vec3d center = rigGrid->cell(localCellIdx).center(); + size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK(i, j, k); + cvf::Vec3d center = rigGrid->cell(gridLocalCellIndex).center(); doubleValues[valueIndex++] = center[coordIdx]; } @@ -268,8 +268,8 @@ class RiaGetCellCorners : public RiaSocketCommand { for (size_t i = 0; i < cellCountI; i++) { - size_t localCellIdx = rigGrid->cellIndexFromIJK(i, j, k); - rigGrid->cellCornerVertices(localCellIdx, cornerVerts); + size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK(i, j, k); + rigGrid->cellCornerVertices(gridLocalCellIndex, cornerVerts); doubleValues[valueIndex++] = cornerVerts[cornerIndexMapping][coordIdx]; } From 52383cab6f9b79dc966025e5299c58d1dea1dd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:02:26 +0200 Subject: [PATCH 079/346] Renamed globalCellIndex to reservoirCellIndex --- .../RivReservoirViewPartMgr.cpp | 6 +++--- .../RimIdenticalGridCaseGroup.cpp | 12 ++++++------ .../ReservoirDataModel/RigActiveCellInfo.cpp | 18 +++++++++--------- .../ReservoirDataModel/RigActiveCellInfo.h | 6 +++--- .../ReservoirDataModel/RigFault.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigFault.h | 8 ++++---- .../ReservoirDataModel/RigNNCData.cpp | 4 ++-- .../ReservoirDataModel/RigNNCData.h | 2 +- .../SocketInterface/RiaGeometryCommands.cpp | 12 ++++++------ 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index e3fa51f9af..7c31d28ce4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -562,11 +562,11 @@ void RivReservoirViewPartMgr::computeNativeVisibility(cvf::UByteArray* cellVisib for (int cellIndex = 0; cellIndex < static_cast(grid->cellCount()); cellIndex++) { const RigCell& cell = grid->cell(cellIndex); - size_t globalCellIndex = cell.mainGridCellIndex(); + size_t reservoirCellIndex = cell.mainGridCellIndex(); if ( !invalidCellsIsVisible && cell.isInvalid() - || !inactiveCellsIsVisible && !activeCellInfo->isActive(globalCellIndex) - || !activeCellsIsVisible && activeCellInfo->isActive(globalCellIndex) + || !inactiveCellsIsVisible && !activeCellInfo->isActive(reservoirCellIndex) + || !activeCellsIsVisible && activeCellInfo->isActive(reservoirCellIndex) //|| mainGridIsVisible && (cell.subGrid() != NULL) // this is handled on global level instead || (*cellIsInWellStatuses)[cellIndex] ) diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 442dd7886f..91c67b2af9 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -254,11 +254,11 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t globalCellIdx = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); if (activeM[localGridCellIdx] == 0) { - if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(globalCellIdx)) + if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(reservoirCellIndex)) { activeM[localGridCellIdx] = 1; } @@ -266,7 +266,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() if (activeF[localGridCellIdx] == 0) { - if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(globalCellIdx)) + if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(reservoirCellIndex)) { activeF[localGridCellIdx] = 1; } @@ -279,17 +279,17 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) { - size_t globalCellIdx = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); if (activeM[localGridCellIdx] != 0) { - m_unionOfMatrixActiveCells->setCellResultIndex(globalCellIdx, globalActiveMatrixIndex++); + m_unionOfMatrixActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveMatrixIndex++); activeMatrixIndex++; } if (activeF[localGridCellIdx] != 0) { - m_unionOfFractureActiveCells->setCellResultIndex(globalCellIdx, globalActiveFractureIndex++); + m_unionOfFractureActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveFractureIndex++); activeFractureIndex++; } } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index b58b17c5d4..7e9c07b5a3 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -58,41 +58,41 @@ size_t RigActiveCellInfo::globalCellResultCount() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RigActiveCellInfo::isActive(size_t globalCellIndex) const +bool RigActiveCellInfo::isActive(size_t reservoirCellIndex) const { if (m_cellIndexToResultIndex.size() == 0) { return true; } - CVF_TIGHT_ASSERT(globalCellIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_cellIndexToResultIndex.size()); - return m_cellIndexToResultIndex[globalCellIndex] != cvf::UNDEFINED_SIZE_T; + return m_cellIndexToResultIndex[reservoirCellIndex] != cvf::UNDEFINED_SIZE_T; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::cellResultIndex(size_t globalCellIndex) const +size_t RigActiveCellInfo::cellResultIndex(size_t reservoirCellIndex) const { if (m_cellIndexToResultIndex.size() == 0) { - return globalCellIndex; + return reservoirCellIndex; } - CVF_TIGHT_ASSERT(globalCellIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_cellIndexToResultIndex.size()); - return m_cellIndexToResultIndex[globalCellIndex]; + return m_cellIndexToResultIndex[reservoirCellIndex]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setCellResultIndex(size_t globalCellIndex, size_t globalCellResultIndex) +void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t globalCellResultIndex) { CVF_TIGHT_ASSERT(globalCellResultIndex < m_cellIndexToResultIndex.size()); - m_cellIndexToResultIndex[globalCellIndex] = globalCellResultIndex; + m_cellIndexToResultIndex[reservoirCellIndex] = globalCellResultIndex; if (globalCellResultIndex >= m_globalCellResultCount) { diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index cbe11c9b8c..562d4e1074 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -38,9 +38,9 @@ class RigActiveCellInfo : public cvf::Object size_t globalCellResultCount() const; bool isCoarseningActive() const; - bool isActive(size_t globalCellIndex) const; - size_t cellResultIndex(size_t globalCellIndex) const; - void setCellResultIndex(size_t globalCellIndex, size_t globalResultCellIndex); + bool isActive(size_t reservoirCellIndex) const; + size_t cellResultIndex(size_t reservoirCellIndex) const; + void setCellResultIndex(size_t reservoirCellIndex, size_t globalResultCellIndex); void setGridCount(size_t gridCount); void setGridActiveCellCounts(size_t gridIndex, size_t activeCellCount); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 8d9cfc5560..476f2d1f4c 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,7 +115,7 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t globalCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + //size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 39198b5feb..b4a31c9ad3 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -46,14 +46,14 @@ class RigFaultsPrCellAccumulator : public cvf::Object m_faultIdxForCellFace.resize(globalCellCount, initVal); } - inline int faultIdx(size_t globalCellIdx, cvf::StructGridInterface::FaceType face) + inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) { - return m_faultIdxForCellFace[globalCellIdx][face]; + return m_faultIdxForCellFace[reservoirCellIndex][face]; } - inline void setFaultIdx(size_t globalCellIdx, cvf::StructGridInterface::FaceType face, int faultIdx) + inline void setFaultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face, int faultIdx) { - m_faultIdxForCellFace[globalCellIdx][face] = faultIdx; + m_faultIdxForCellFace[reservoirCellIndex][face] = faultIdx; } private: diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index c5da5e45de..f6b619fbdc 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -164,12 +164,12 @@ void RigNNCData::processConnections(const RigMainGrid& mainGrid) //-------------------------------------------------------------------------------------------------- /// TODO: Possibly not needed ! //-------------------------------------------------------------------------------------------------- -const std::vector& RigNNCData::findConnectionIndices( size_t globalCellIndex, cvf::StructGridInterface::FaceType face) const +const std::vector& RigNNCData::findConnectionIndices( size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const { ConnectionSearchMap::const_iterator it; static std::vector empty; - it = m_cellIdxToFaceToConnectionIdxMap.find(globalCellIndex); + it = m_cellIdxToFaceToConnectionIdxMap.find(reservoirCellIndex); if (it != m_cellIdxToFaceToConnectionIdxMap.end()) { return it->second[face]; diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index ca4b9bf54d..bbad5e3fe7 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -63,7 +63,7 @@ class RigNNCData : public cvf::Object const std::vector& connections() const { return m_connections; }; private: // This section is possibly not needed - //const std::vector& findConnectionIndices(size_t globalCellIndex, cvf::StructGridInterface::FaceType face) const; + //const std::vector& findConnectionIndices(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; //typedef std::map, 7 > > ConnectionSearchMap; //ConnectionSearchMap m_cellIdxToFaceToConnectionIdxMap; diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index 567dc990eb..7a07f09d4a 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -177,11 +177,11 @@ class RiaGetActiveCellCenters : public RiaSocketCommand { quint64 valueIndex = 0; - for (size_t globalCellIdx = 0; globalCellIdx < mainGrid->cells().size(); globalCellIdx++) + for (size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->cells().size(); reservoirCellIndex++) { - if (!actCellInfo->isActive(globalCellIdx)) continue; + if (!actCellInfo->isActive(reservoirCellIndex)) continue; - cvf::Vec3d center = mainGrid->cells()[globalCellIdx].center(); + cvf::Vec3d center = mainGrid->cells()[reservoirCellIndex].center(); doubleValues[valueIndex++] = center[coordIdx]; } @@ -351,11 +351,11 @@ class RiaGetActiveCellCorners : public RiaSocketCommand quint64 valueIndex = 0; - for (size_t globalCellIdx = 0; globalCellIdx < mainGrid->cells().size(); globalCellIdx++) + for (size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->cells().size(); reservoirCellIndex++) { - if (!actCellInfo->isActive(globalCellIdx)) continue; + if (!actCellInfo->isActive(reservoirCellIndex)) continue; - mainGrid->cellCornerVertices(globalCellIdx, cornerVerts); + mainGrid->cellCornerVertices(reservoirCellIndex, cornerVerts); doubleValues[valueIndex++] = cornerVerts[cornerIndexMapping][coordIdx]; } From d87f2e9e7d7e32241dc0b1315e2756866fdbb659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:07:32 +0200 Subject: [PATCH 080/346] Renamed more stuff to gridLocalCellIndex --- .../RimIdenticalGridCaseGroup.cpp | 20 +++++++++---------- .../ReservoirDataModel/RigGridBase.cpp | 4 ++-- .../ReservoirDataModel/RigGridBase.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 91c67b2af9..45f83d47ea 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -250,25 +250,25 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() std::vector activeM(grid->cellCount(), 0); std::vector activeF(grid->cellCount(), 0); - for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) + for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); - if (activeM[localGridCellIdx] == 0) + if (activeM[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(reservoirCellIndex)) { - activeM[localGridCellIdx] = 1; + activeM[gridLocalCellIndex] = 1; } } - if (activeF[localGridCellIdx] == 0) + if (activeF[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(reservoirCellIndex)) { - activeF[localGridCellIdx] = 1; + activeF[gridLocalCellIndex] = 1; } } } @@ -277,17 +277,17 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() size_t activeMatrixIndex = 0; size_t activeFractureIndex = 0; - for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) + for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); - if (activeM[localGridCellIdx] != 0) + if (activeM[gridLocalCellIndex] != 0) { m_unionOfMatrixActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveMatrixIndex++); activeMatrixIndex++; } - if (activeF[localGridCellIdx] != 0) + if (activeF[gridLocalCellIndex] != 0) { m_unionOfFractureActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveFractureIndex++); activeFractureIndex++; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 1342059660..42036ff6a0 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -368,9 +368,9 @@ double RigGridBase::characteristicIJCellSize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigGridBase::globalGridCellIndex(size_t localGridCellIndex) const +size_t RigGridBase::globalGridCellIndex(size_t gridLocalCellIndex) const { - return m_indexToStartOfCells + localGridCellIndex; + return m_indexToStartOfCells + gridLocalCellIndex; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index a8285ad227..e2819dec68 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -52,7 +52,7 @@ class RigGridBase : public cvf::StructGridInterface RigCell& cell(size_t gridCellIndex); const RigCell& cell(size_t gridCellIndex) const; - size_t globalGridCellIndex(size_t localGridCellIndex) const; + size_t globalGridCellIndex(size_t gridLocalCellIndex) const; void setIndexToStartOfCells(size_t indexToStartOfCells) { m_indexToStartOfCells = indexToStartOfCells; } void setGridIndex(size_t index) { m_gridIndex = index; } From 6fbb1d52a909cc878b74dc60621f32aa9de515c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:16:54 +0200 Subject: [PATCH 081/346] Renamed globalGridCellIndex to reservoirCellIndex --- .../FileInterface/RifReaderEclipseOutput.cpp | 4 ++-- .../RimIdenticalGridCaseGroup.cpp | 4 ++-- .../ProjectDataModel/RimReservoirView.cpp | 8 ++++---- .../RimStatisticsCaseEvaluator.cpp | 4 ++-- .../RigActiveCellsResultAccessor.cpp | 4 ++-- .../RigAllGridCellsResultAccessor.cpp | 6 +++--- .../ReservoirDataModel/RigCaseData.cpp | 6 +++--- .../ReservoirDataModel/RigFault.cpp | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../ReservoirDataModel/RigGridBase.h | 2 +- .../ReservoirDataModel/RigMainGrid.cpp | 2 +- .../RigResultAccessorFactory.cpp | 20 +++++++++---------- .../ReservoirDataModel/RigResultModifier.h | 10 +++++----- 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index a5650aa826..3018d29dd4 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -482,9 +482,9 @@ void RifReaderEclipseOutput::transferNNCData( const ecl_grid_type * mainEclGrid for (int nIdx = 0; nIdx < numNNC; ++nIdx) { RigGridBase* grid1 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr1); - mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->globalGridCellIndex(eclNNCData[nIdx].global_index1); + mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->reservoirCellIndex(eclNNCData[nIdx].global_index1); RigGridBase* grid2 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr2); - mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->globalGridCellIndex(eclNNCData[nIdx].global_index2); + mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->reservoirCellIndex(eclNNCData[nIdx].global_index2); mainGrid->nncData()->connections()[nIdx].m_transmissibility = eclNNCData[nIdx].trans; } diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 45f83d47ea..0ac3651308 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -254,7 +254,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] == 0) { @@ -279,7 +279,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] != 0) { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 39492f74ec..65a8f6706a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1641,9 +1641,9 @@ void RimReservoirView::calculateVisibleWellCellsIncFence(cvf::UByteArray* visibl if (wellResFrames[wfIdx].m_wellHead.m_gridIndex == grid->gridIndex()) { size_t gridCellIndex = wellResFrames[wfIdx].m_wellHead.m_gridCellIndex; - size_t globalGridCellIndex = grid->globalGridCellIndex(gridCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridCellIndex); - if (activeCellInfo->isActive(globalGridCellIndex)) + if (activeCellInfo->isActive(reservoirCellIndex)) { (*visibleCells)[gridCellIndex] = true; } @@ -1698,9 +1698,9 @@ void RimReservoirView::calculateVisibleWellCellsIncFence(cvf::UByteArray* visibl for ( fIdx = 0; fIdx < cellCountFenceDirection; ++fIdx) { size_t fenceCellIndex = grid->cellIndexFromIJK(*pI,*pJ,*pK); - size_t globalGridCellIndex = grid->globalGridCellIndex(fenceCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(fenceCellIndex); - if (activeCellInfo && activeCellInfo->isActive(globalGridCellIndex)) + if (activeCellInfo && activeCellInfo->isActive(reservoirCellIndex)) { (*visibleCells)[fenceCellIndex] = true; } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 5693b69ec9..85f7c999e9 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -234,8 +234,8 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result for (int cellIdx = 0; static_cast(cellIdx) < grid->cellCount(); cellIdx++) { - size_t globalGridCellIdx = grid->globalGridCellIndex(cellIdx); - if (m_destinationCase->activeCellInfo(poroModel)->isActive(globalGridCellIdx)) + size_t reservoirCellIndex = grid->reservoirCellIndex(cellIdx); + if (m_destinationCase->activeCellInfo(poroModel)->isActive(reservoirCellIndex)) { // Extract the cell values from each of the cases and assemble them into one vector diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index 7555ad8c4d..29c563a25e 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -39,8 +39,8 @@ double RigActiveCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 14b7b30a3c..247ef7f953 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -39,10 +39,10 @@ double RigAllGridCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) cons { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - return m_reservoirResultValues->at(globalGridCellIndex); + return m_reservoirResultValues->at(reservoirCellIndex); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 34830722fd..1d5619f87b 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -166,9 +166,9 @@ void RigCaseData::computeWellCellsPrGrid() if (gridIndex < m_wellCellsInGrid.size() && gridCellIndex < m_wellCellsInGrid[gridIndex]->size()) { - size_t globalGridCellIndex = grids[gridIndex]->globalGridCellIndex(gridCellIndex); - if (m_activeCellInfo->isActive(globalGridCellIndex) - || m_fractureActiveCellInfo->isActive(globalGridCellIndex)) + size_t reservoirCellIndex = grids[gridIndex]->reservoirCellIndex(gridCellIndex); + if (m_activeCellInfo->isActive(reservoirCellIndex) + || m_fractureActiveCellInfo->isActive(reservoirCellIndex)) { m_wellCellsInGrid[gridIndex]->set(gridCellIndex, true); m_gridCellToWellIndex[gridIndex]->set(gridCellIndex, static_cast(wIdx)); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 476f2d1f4c..0db6f08c90 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,7 +115,7 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + //size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 42036ff6a0..6f145298a4 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -368,7 +368,7 @@ double RigGridBase::characteristicIJCellSize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigGridBase::globalGridCellIndex(size_t gridLocalCellIndex) const +size_t RigGridBase::reservoirCellIndex(size_t gridLocalCellIndex) const { return m_indexToStartOfCells + gridLocalCellIndex; } diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index e2819dec68..c9ce6d8c54 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -52,7 +52,7 @@ class RigGridBase : public cvf::StructGridInterface RigCell& cell(size_t gridCellIndex); const RigCell& cell(size_t gridCellIndex) const; - size_t globalGridCellIndex(size_t gridLocalCellIndex) const; + size_t reservoirCellIndex(size_t gridLocalCellIndex) const; void setIndexToStartOfCells(size_t indexToStartOfCells) { m_indexToStartOfCells = indexToStartOfCells; } void setGridIndex(size_t index) { m_gridIndex = index; } diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 4bbdea1cb9..dc58bf21c3 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -259,7 +259,7 @@ void RigMainGrid::calculateFaults() continue; } - neighborGlobalCellIdx = hostGrid->globalGridCellIndex(neighborGridCellIdx); + neighborGlobalCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); if (m_cells[neighborGlobalCellIdx].isInvalid()) { continue; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 41c30f3fc7..d44ffc0dfb 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -176,10 +176,10 @@ double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) co { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - return m_reservoirResultValues->at(globalGridCellIndex); + return m_reservoirResultValues->at(reservoirCellIndex); } //-------------------------------------------------------------------------------------------------- @@ -187,10 +187,10 @@ double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) co //-------------------------------------------------------------------------------------------------- void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + (*m_reservoirResultValues)[reservoirCellIndex] = scalarValue; } //-------------------------------------------------------------------------------------------------- @@ -212,8 +212,8 @@ class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAcces { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); @@ -226,8 +226,8 @@ class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAcces //-------------------------------------------------------------------------------------------------- virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h index 4c9d8d7dc1..651d12c4fe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifier.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -47,10 +47,10 @@ class RigAllGridCellsResultModifier : public RigResultModifier virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + (*m_reservoirResultValues)[reservoirCellIndex] = scalarValue; } private: @@ -74,8 +74,8 @@ class RigActiveCellsResultModifier : public RigResultModifier virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); From 1c36204553a49c3926a34eed69877f3b7c7b3b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:27:29 +0200 Subject: [PATCH 082/346] Renamed globalCell to reservoirCell etc. --- .../RifEclipseInputFileTools.cpp | 6 ++-- .../FileInterface/RifReaderEclipseOutput.cpp | 28 +++++++++---------- .../Rim3dOverlayInfoConfig.cpp | 4 +-- .../RimIdenticalGridCaseGroup.cpp | 6 ++-- .../ProjectDataModel/RimResultDefinition.cpp | 2 +- .../RimStatisticsCaseEvaluator.cpp | 4 +-- .../RigActiveCellInfo-Test.cpp | 6 ++-- .../ReservoirDataModel/RigActiveCellInfo.cpp | 8 +++--- .../ReservoirDataModel/RigActiveCellInfo.h | 8 +++--- .../RigReservoirBuilderMock.cpp | 2 +- .../SocketInterface/RiaCaseInfoCommands.cpp | 2 +- .../SocketInterface/RiaGeometryCommands.cpp | 4 +-- .../RiaPropertyDataCommands.cpp | 12 ++++---- 13 files changed, 46 insertions(+), 46 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 74a7892560..1211dc9208 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -88,17 +88,17 @@ bool readDoubleValuesForActiveCells(RigCaseData* reservoir, size_t resultIndex, newPropertyData.push_back(std::vector()); RigActiveCellInfo* activeCellInfo = reservoir->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); - if (activeCellInfo->globalCellCount() > 0 && activeCellInfo->globalCellCount() != activeCellInfo->globalActiveCellCount()) + if (activeCellInfo->reservoirCellCount() > 0 && activeCellInfo->reservoirCellCount() != activeCellInfo->reservoirActiveCellCount()) { std::vector valuesAllCells; valuesAllCells.resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, valuesAllCells.data()); - newPropertyData[0].resize(activeCellInfo->globalActiveCellCount(), HUGE_VAL); + newPropertyData[0].resize(activeCellInfo->reservoirActiveCellCount(), HUGE_VAL); std::vector& valuesActiveCells = newPropertyData[0]; size_t acIdx = 0; - for (size_t gcIdx = 0; gcIdx < activeCellInfo->globalCellCount(); gcIdx++) + for (size_t gcIdx = 0; gcIdx < activeCellInfo->reservoirCellCount(); gcIdx++) { size_t activeCellResultIndex = activeCellInfo->cellResultIndex(gcIdx); if (activeCellResultIndex != cvf::UNDEFINED_SIZE_T) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 3018d29dd4..f96e70bba3 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -287,8 +287,8 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, totalCellCount += ecl_grid_get_global_size(localEclGrid); } - activeCellInfo->setGlobalCellCount(totalCellCount); - fractureActiveCellInfo->setGlobalCellCount(totalCellCount); + activeCellInfo->setReservoirCellCount(totalCellCount); + fractureActiveCellInfo->setReservoirCellCount(totalCellCount); // Reserve room for the cells and nodes and fill them with data @@ -570,8 +570,8 @@ bool RifReaderEclipseOutput::readActiveCellInfo() RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - activeCellInfo->setGlobalCellCount(globalCellCount); - fractureActiveCellInfo->setGlobalCellCount(globalCellCount); + activeCellInfo->setReservoirCellCount(globalCellCount); + fractureActiveCellInfo->setReservoirCellCount(globalCellCount); activeCellInfo->setGridCount(actnumKeywordCount); fractureActiveCellInfo->setGridCount(actnumKeywordCount); @@ -773,7 +773,7 @@ bool RifReaderEclipseOutput::staticResult(const QString& result, PorosityModelRe if (result.compare("ACTNUM", Qt::CaseInsensitive) == 0) { RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(matrixOrFracture); - values->resize(activeCellInfo->globalActiveCellCount(), 1.0); + values->resize(activeCellInfo->reservoirActiveCellCount(), 1.0); return true; } @@ -1551,7 +1551,7 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL if (matrixOrFracture == RifReaderInterface::FRACTURE_RESULTS) { - if (fractureActiveCellInfo->globalActiveCellCount() == 0) + if (fractureActiveCellInfo->reservoirActiveCellCount() == 0) { return QStringList(); } @@ -1564,16 +1564,16 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL QString keyword = keywords[i]; size_t keywordDataCount = keywordDataItemCounts[i]; - if (activeCellInfo->globalActiveCellCount() > 0) + if (activeCellInfo->reservoirActiveCellCount() > 0) { - size_t timeStepsAllCells = keywordDataItemCounts[i] / activeCellInfo->globalCellCount(); - size_t timeStepsAllCellsRest = keywordDataItemCounts[i] % activeCellInfo->globalCellCount(); + size_t timeStepsAllCells = keywordDataItemCounts[i] / activeCellInfo->reservoirCellCount(); + size_t timeStepsAllCellsRest = keywordDataItemCounts[i] % activeCellInfo->reservoirCellCount(); - size_t timeStepsMatrix = keywordDataItemCounts[i] / activeCellInfo->globalActiveCellCount(); - size_t timeStepsMatrixRest = keywordDataItemCounts[i] % activeCellInfo->globalActiveCellCount(); + size_t timeStepsMatrix = keywordDataItemCounts[i] / activeCellInfo->reservoirActiveCellCount(); + size_t timeStepsMatrixRest = keywordDataItemCounts[i] % activeCellInfo->reservoirActiveCellCount(); - size_t timeStepsMatrixAndFracture = keywordDataItemCounts[i] / (activeCellInfo->globalActiveCellCount() + fractureActiveCellInfo->globalActiveCellCount()); - size_t timeStepsMatrixAndFractureRest = keywordDataItemCounts[i] % (activeCellInfo->globalActiveCellCount() + fractureActiveCellInfo->globalActiveCellCount()); + size_t timeStepsMatrixAndFracture = keywordDataItemCounts[i] / (activeCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount()); + size_t timeStepsMatrixAndFractureRest = keywordDataItemCounts[i] % (activeCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount()); if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS) { @@ -1620,7 +1620,7 @@ void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(PorosityMod RigActiveCellInfo* fracActCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS && fracActCellInfo->globalActiveCellCount() == 0) + if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS && fracActCellInfo->reservoirActiveCellCount() == 0) { destinationResultValues->insert(destinationResultValues->end(), sourceResultValues.begin(), sourceResultValues.end()); } diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 752f4894f7..3bc4c76a18 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -117,8 +117,8 @@ void Rim3dOverlayInfoConfig::update3DInfo() { caseName = m_reservoirView->eclipseCase()->caseUserDescription(); totCellCount = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cells().size()); - size_t mxActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->globalActiveCellCount(); - size_t frActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount(); + size_t mxActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->reservoirActiveCellCount(); + size_t frActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->reservoirActiveCellCount(); if (frActCellCount > 0) activeCellCountText += "Matrix : "; activeCellCountText += QString::number(mxActCellCount); if (frActCellCount > 0) activeCellCountText += " Fracture : " + QString::number(frActCellCount); diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 0ac3651308..1dec69908d 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -223,7 +223,7 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { - if (m_unionOfMatrixActiveCells->globalActiveCellCount() > 0) + if (m_unionOfMatrixActiveCells->reservoirActiveCellCount() > 0) { return; } @@ -235,8 +235,8 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() return; } - m_unionOfMatrixActiveCells->setGlobalCellCount(m_mainGrid->cells().size()); - m_unionOfFractureActiveCells->setGlobalCellCount(m_mainGrid->cells().size()); + m_unionOfMatrixActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); + m_unionOfFractureActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); m_unionOfMatrixActiveCells->setGridCount(m_mainGrid->gridCount()); m_unionOfFractureActiveCells->setGridCount(m_mainGrid->gridCount()); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index b61801dc61..a15c100d9b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -345,7 +345,7 @@ void RimResultDefinition::updateFieldVisibility() m_reservoirView->eclipseCase()->reservoirData() && m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) { - if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) + if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->reservoirActiveCellCount() == 0) { m_porosityModelUiField.setUiHidden(true); } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 85f7c999e9..147db21832 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -103,7 +103,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result RimDefines::ResultCatType resultType = resultSpecification[i].m_resType; QString resultName = resultSpecification[i].m_resVarName; - size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->globalActiveCellCount(); + size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->reservoirActiveCellCount(); RigCaseCellResultsData* destCellResultsData = m_destinationCase->results(poroModel); // Special handling if SOIL is asked for @@ -172,7 +172,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result RimDefines::ResultCatType resultType = resultSpecification[resSpecIdx].m_resType; QString resultName = resultSpecification[resSpecIdx].m_resVarName; - size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->globalActiveCellCount(); + size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->reservoirActiveCellCount(); if (activeCellCount == 0) continue; diff --git a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp index 57e99d4ec0..5252bbac88 100644 --- a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp +++ b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp @@ -32,7 +32,7 @@ TEST(RigActiveCellInfo, BasicTest) RigActiveCellInfo rigActiveCellInfo; size_t globalActiveCellCount = 10; - rigActiveCellInfo.setGlobalCellCount(globalActiveCellCount); + rigActiveCellInfo.setReservoirCellCount(globalActiveCellCount); for (size_t i = 0; i < globalActiveCellCount; i++) { @@ -57,7 +57,7 @@ TEST(RigActiveCellInfo, GridCellCounts) rigActiveCellInfo.setGridActiveCellCounts(2, 2); rigActiveCellInfo.computeDerivedData(); - EXPECT_TRUE(rigActiveCellInfo.globalActiveCellCount() == 3); + EXPECT_TRUE(rigActiveCellInfo.reservoirActiveCellCount() == 3); } { @@ -68,6 +68,6 @@ TEST(RigActiveCellInfo, GridCellCounts) rigActiveCellInfo.setGridActiveCellCounts(2, 5 ); rigActiveCellInfo.computeDerivedData(); - EXPECT_TRUE(rigActiveCellInfo.globalActiveCellCount() == 12); + EXPECT_TRUE(rigActiveCellInfo.reservoirActiveCellCount() == 12); } } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index 7e9c07b5a3..0013a2da44 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -34,7 +34,7 @@ RigActiveCellInfo::RigActiveCellInfo() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setGlobalCellCount(size_t globalCellCount) +void RigActiveCellInfo::setReservoirCellCount(size_t globalCellCount) { m_cellIndexToResultIndex.resize(globalCellCount, cvf::UNDEFINED_SIZE_T); } @@ -42,7 +42,7 @@ void RigActiveCellInfo::setGlobalCellCount(size_t globalCellCount) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalCellCount() const +size_t RigActiveCellInfo::reservoirCellCount() const { return m_cellIndexToResultIndex.size(); } @@ -50,7 +50,7 @@ size_t RigActiveCellInfo::globalCellCount() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalCellResultCount() const +size_t RigActiveCellInfo::reservoirCellResultCount() const { return m_globalCellResultCount; } @@ -134,7 +134,7 @@ void RigActiveCellInfo::computeDerivedData() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalActiveCellCount() const +size_t RigActiveCellInfo::reservoirActiveCellCount() const { return m_globalActiveCellCount; } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index 562d4e1074..a1118f1d54 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -32,10 +32,10 @@ class RigActiveCellInfo : public cvf::Object public: RigActiveCellInfo(); - void setGlobalCellCount(size_t globalCellCount); - size_t globalCellCount() const; - size_t globalActiveCellCount() const; - size_t globalCellResultCount() const; + void setReservoirCellCount(size_t globalCellCount); + size_t reservoirCellCount() const; + size_t reservoirActiveCellCount() const; + size_t reservoirCellResultCount() const; bool isCoarseningActive() const; bool isActive(size_t reservoirCellIndex) const; diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index ec981ebc21..bca46da76c 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -247,7 +247,7 @@ void RigReservoirBuilderMock::populateReservoir(RigCaseData* eclipseCase) // Set all cells active RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); - activeCellInfo->setGlobalCellCount(eclipseCase->mainGrid()->cells().size()); + activeCellInfo->setReservoirCellCount(eclipseCase->mainGrid()->cells().size()); for (size_t i = 0; i < eclipseCase->mainGrid()->cells().size(); i++) { activeCellInfo->setCellResultIndex(i, i); diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index a10762e2a6..f80a0c54b7 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -158,7 +158,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } RigActiveCellInfo* actCellInfo = reservoirCase->reservoirData()->activeCellInfo(porosityModel); - size_t numMatrixModelActiveCells = actCellInfo->globalActiveCellCount(); + size_t numMatrixModelActiveCells = actCellInfo->reservoirActiveCellCount(); gridNumber.reserve(numMatrixModelActiveCells); cellI.reserve(numMatrixModelActiveCells); diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index 7a07f09d4a..d7784f1997 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -152,7 +152,7 @@ class RiaGetActiveCellCenters : public RiaSocketCommand RigActiveCellInfo* actCellInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); RigMainGrid* mainGrid = rimCase->reservoirData()->mainGrid(); - size_t activeCellCount = actCellInfo->globalActiveCellCount(); + size_t activeCellCount = actCellInfo->reservoirActiveCellCount(); size_t doubleValueCount = activeCellCount * 3; socketStream << (quint64)activeCellCount; @@ -321,7 +321,7 @@ class RiaGetActiveCellCorners : public RiaSocketCommand RigActiveCellInfo* actCellInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); RigMainGrid* mainGrid = rimCase->reservoirData()->mainGrid(); - size_t activeCellCount = actCellInfo->globalActiveCellCount(); + size_t activeCellCount = actCellInfo->reservoirActiveCellCount(); size_t doubleValueCount = activeCellCount * 3 * 8; socketStream << (quint64)activeCellCount; diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 101f9edcea..fa98846c15 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -138,7 +138,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand // then the byte-size of the result values in one timestep const RigActiveCellInfo* activeInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); - size_t timestepResultCount = activeInfo->globalActiveCellCount(); + size_t timestepResultCount = activeInfo->reservoirActiveCellCount(); quint64 timestepByteCount = (quint64)(timestepResultCount*sizeof(double)); socketStream << timestepByteCount ; @@ -148,7 +148,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand std::vector values(valueCount); size_t valueIndex = 0; - size_t globalCellCount = activeInfo->globalCellCount(); + size_t globalCellCount = activeInfo->reservoirCellCount(); for (size_t tIdx = 0; tIdx < requestedTimesteps.size(); ++tIdx) { std::vector& doubleValues = scalarResultFrames->at(requestedTimesteps[tIdx]); @@ -159,7 +159,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand if (resultIdx < doubleValues.size()) { - if (doubleValues.size() == activeInfo->globalCellCount()) + if (doubleValues.size() == activeInfo->reservoirCellCount()) { // When reading data from input text files, result data is read for all grid cells // Read out values from data vector using global cell index instead of active cell result index @@ -528,9 +528,9 @@ class RiaSetActiveCellProperty: public RiaSocketCommand RigActiveCellInfo* activeCellInfo = m_currentReservoir->reservoirData()->activeCellInfo(m_porosityModelEnum); - size_t globalActiveCellCount = activeCellInfo->globalActiveCellCount(); - size_t totalCellCount = activeCellInfo->globalCellCount(); - size_t globalCellResultCount = activeCellInfo->globalCellResultCount(); + size_t globalActiveCellCount = activeCellInfo->reservoirActiveCellCount(); + size_t totalCellCount = activeCellInfo->reservoirCellCount(); + size_t globalCellResultCount = activeCellInfo->reservoirCellResultCount(); bool isCoarseningActive = globalCellResultCount != globalActiveCellCount; From 5c3a47e37d1bdf589c950d386423646d5115d169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:45:52 +0200 Subject: [PATCH 083/346] More Rename of globalCell to reservoirCell --- .../FileInterface/RifReaderEclipseOutput.cpp | 10 +++---- .../RimStatisticsCaseEvaluator.cpp | 6 ++-- .../RimStatisticsCaseEvaluator.h | 2 +- .../ReservoirDataModel/RigActiveCellInfo.cpp | 30 +++++++++---------- .../ReservoirDataModel/RigActiveCellInfo.h | 6 ++-- ApplicationCode/ReservoirDataModel/RigFault.h | 6 ++-- .../SocketInterface/RiaCaseInfoCommands.cpp | 12 ++++---- .../RiaPropertyDataCommands.cpp | 16 +++++----- 8 files changed, 44 insertions(+), 44 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index f96e70bba3..48b56da2ae 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -553,16 +553,16 @@ bool RifReaderEclipseOutput::readActiveCellInfo() std::vector > actnumValuesPerGrid; actnumValuesPerGrid.resize(actnumKeywordCount); - size_t globalCellCount = 0; + size_t reservoirCellCount = 0; for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) { RifEclipseOutputFileTools::keywordData(ecl_file, ACTNUM_KW, gridIdx, &actnumValuesPerGrid[gridIdx]); - globalCellCount += actnumValuesPerGrid[gridIdx].size(); + reservoirCellCount += actnumValuesPerGrid[gridIdx].size(); } // Check if number of cells is matching - if (m_eclipseCase->mainGrid()->cells().size() != globalCellCount) + if (m_eclipseCase->mainGrid()->cells().size() != reservoirCellCount) { return false; } @@ -570,8 +570,8 @@ bool RifReaderEclipseOutput::readActiveCellInfo() RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - activeCellInfo->setReservoirCellCount(globalCellCount); - fractureActiveCellInfo->setReservoirCellCount(globalCellCount); + activeCellInfo->setReservoirCellCount(reservoirCellCount); + fractureActiveCellInfo->setReservoirCellCount(reservoirCellCount); activeCellInfo->setGridCount(actnumKeywordCount); fractureActiveCellInfo->setGridCount(actnumKeywordCount); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 147db21832..0225d62e56 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -352,7 +352,7 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); if (resultAccessor.isNull()) return; - for (size_t cellIdx = 0; cellIdx < m_globalCellCount; cellIdx++) + for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) { qDebug() << resultAccessor->cellScalar(cellIdx); } @@ -365,12 +365,12 @@ RimStatisticsCaseEvaluator::RimStatisticsCaseEvaluator(const std::vector 0) { - m_globalCellCount = sourceCases[0]->reservoirData()->mainGrid()->cells().size(); + m_reservoirCellCount = sourceCases[0]->reservoirData()->mainGrid()->cells().size(); } CVF_ASSERT(m_destinationCase); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 6e3392ef7a..87b21c7aae 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -85,7 +85,7 @@ class RimStatisticsCaseEvaluator std::vector m_sourceCases; std::vector m_timeStepIndices; - size_t m_globalCellCount; + size_t m_reservoirCellCount; RimStatisticsConfig m_statisticsConfig; RigCaseData* m_destinationCase; }; diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index 0013a2da44..2c631b2d16 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -23,8 +23,8 @@ /// //-------------------------------------------------------------------------------------------------- RigActiveCellInfo::RigActiveCellInfo() - : m_globalActiveCellCount(0), - m_globalCellResultCount(0), + : m_reservoirActiveCellCount(0), + m_reservoirCellResultCount(0), m_activeCellPositionMin(cvf::Vec3d::ZERO), m_activeCellPositionMax(cvf::Vec3d::ZERO) { @@ -34,9 +34,9 @@ RigActiveCellInfo::RigActiveCellInfo() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setReservoirCellCount(size_t globalCellCount) +void RigActiveCellInfo::setReservoirCellCount(size_t reservoirCellCount) { - m_cellIndexToResultIndex.resize(globalCellCount, cvf::UNDEFINED_SIZE_T); + m_cellIndexToResultIndex.resize(reservoirCellCount, cvf::UNDEFINED_SIZE_T); } //-------------------------------------------------------------------------------------------------- @@ -52,7 +52,7 @@ size_t RigActiveCellInfo::reservoirCellCount() const //-------------------------------------------------------------------------------------------------- size_t RigActiveCellInfo::reservoirCellResultCount() const { - return m_globalCellResultCount; + return m_reservoirCellResultCount; } //-------------------------------------------------------------------------------------------------- @@ -88,15 +88,15 @@ size_t RigActiveCellInfo::cellResultIndex(size_t reservoirCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t globalCellResultIndex) +void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t reservoirCellResultIndex) { - CVF_TIGHT_ASSERT(globalCellResultIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellResultIndex < m_cellIndexToResultIndex.size()); - m_cellIndexToResultIndex[reservoirCellIndex] = globalCellResultIndex; + m_cellIndexToResultIndex[reservoirCellIndex] = reservoirCellResultIndex; - if (globalCellResultIndex >= m_globalCellResultCount) + if (reservoirCellResultIndex >= m_reservoirCellResultCount) { - m_globalCellResultCount = globalCellResultIndex + 1; + m_reservoirCellResultCount = reservoirCellResultIndex + 1; } } @@ -123,11 +123,11 @@ void RigActiveCellInfo::setGridActiveCellCounts(size_t gridIndex, size_t activeC //-------------------------------------------------------------------------------------------------- void RigActiveCellInfo::computeDerivedData() { - m_globalActiveCellCount = 0; + m_reservoirActiveCellCount = 0; for (size_t i = 0; i < m_perGridActiveCellInfo.size(); i++) { - m_globalActiveCellCount += m_perGridActiveCellInfo[i].activeCellCount(); + m_reservoirActiveCellCount += m_perGridActiveCellInfo[i].activeCellCount(); } } @@ -136,7 +136,7 @@ void RigActiveCellInfo::computeDerivedData() //-------------------------------------------------------------------------------------------------- size_t RigActiveCellInfo::reservoirActiveCellCount() const { - return m_globalActiveCellCount; + return m_reservoirActiveCellCount; } //-------------------------------------------------------------------------------------------------- @@ -187,7 +187,7 @@ void RigActiveCellInfo::clear() { m_perGridActiveCellInfo.clear(); m_cellIndexToResultIndex.clear(); - m_globalActiveCellCount = 0; + m_reservoirActiveCellCount = 0; m_activeCellPositionMin = cvf::Vec3st(0,0,0); m_activeCellPositionMax = cvf::Vec3st(0,0,0); m_activeCellsBoundingBox.reset(); @@ -198,7 +198,7 @@ void RigActiveCellInfo::clear() //-------------------------------------------------------------------------------------------------- bool RigActiveCellInfo::isCoarseningActive() const { - return m_globalCellResultCount != m_globalActiveCellCount; + return m_reservoirCellResultCount != m_reservoirActiveCellCount; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index a1118f1d54..8002f5bbb7 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -32,7 +32,7 @@ class RigActiveCellInfo : public cvf::Object public: RigActiveCellInfo(); - void setReservoirCellCount(size_t globalCellCount); + void setReservoirCellCount(size_t reservoirCellCount); size_t reservoirCellCount() const; size_t reservoirActiveCellCount() const; size_t reservoirCellResultCount() const; @@ -72,8 +72,8 @@ class RigActiveCellInfo : public cvf::Object std::vector m_cellIndexToResultIndex; - size_t m_globalActiveCellCount; - size_t m_globalCellResultCount; + size_t m_reservoirActiveCellCount; + size_t m_reservoirCellResultCount; cvf::Vec3st m_activeCellPositionMin; cvf::Vec3st m_activeCellPositionMax; diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index b4a31c9ad3..0d310bce35 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -38,12 +38,12 @@ class RigFaultsPrCellAccumulator : public cvf::Object enum { NO_FAULT = -1, UNKNOWN_FAULT = -2 }; public: - RigFaultsPrCellAccumulator(size_t globalCellCount) + RigFaultsPrCellAccumulator(size_t reservoirCellCount) { const int initVals[6] = { NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT}; caf::IntArray6 initVal; initVal = initVals; - m_faultIdxForCellFace.resize(globalCellCount, initVal); + m_faultIdxForCellFace.resize(reservoirCellCount, initVal); } inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) @@ -95,7 +95,7 @@ class RigFault : public cvf::Object const std::vector& connectionIndices() const { return m_connectionIndices; } static RigFaultsPrCellAccumulator* faultsPrCellAccumulator() { CVF_ASSERT(m_faultsPrCellAcc.notNull()); return m_faultsPrCellAcc.p();} - static void initFaultsPrCellAccumulator(size_t globalCellCount) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(globalCellCount); } + static void initFaultsPrCellAccumulator(size_t reservoirCellCount) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(reservoirCellCount); } private: QString m_name; diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index f80a0c54b7..793cebdc1c 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -170,7 +170,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand hostCellK.reserve(numMatrixModelActiveCells); globalCoarseningBoxIdx.reserve(numMatrixModelActiveCells); - const std::vector& globalCells = reservoirCase->reservoirData()->mainGrid()->cells(); + const std::vector& reservoirCells = reservoirCase->reservoirData()->mainGrid()->cells(); std::vector globalCoarseningBoxIndexStart; @@ -190,13 +190,13 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } - for (size_t cIdx = 0; cIdx < globalCells.size(); ++cIdx) + for (size_t cIdx = 0; cIdx < reservoirCells.size(); ++cIdx) { if (actCellInfo->isActive(cIdx)) { - RigGridBase* grid = globalCells[cIdx].hostGrid(); + RigGridBase* grid = reservoirCells[cIdx].hostGrid(); CVF_ASSERT(grid != NULL); - size_t cellIndex = globalCells[cIdx].cellIndex(); + size_t cellIndex = reservoirCells[cIdx].cellIndex(); size_t i, j, k; grid->ijkFromCellIndex(cellIndex, &i, &j, &k); @@ -213,7 +213,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } else { - size_t parentCellIdx = globalCells[cIdx].parentCellIndex(); + size_t parentCellIdx = reservoirCells[cIdx].parentCellIndex(); parentGrid = (static_cast(grid))->parentGrid(); CVF_ASSERT(parentGrid != NULL); parentGrid->ijkFromCellIndex(parentCellIdx, &pi, &pj, &pk); @@ -229,7 +229,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand hostCellJ.push_back(static_cast(pj + 1)); // NB: 1-based index in Octave hostCellK.push_back(static_cast(pk + 1)); // NB: 1-based index in Octave - size_t coarseningIdx = globalCells[cIdx].coarseningBoxIndex(); + size_t coarseningIdx = reservoirCells[cIdx].coarseningBoxIndex(); if (coarseningIdx != cvf::UNDEFINED_SIZE_T) { size_t globalCoarseningIdx = globalCoarseningBoxIndexStart[grid->gridIndex()] + coarseningIdx; diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index fa98846c15..9edfad2c82 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -148,11 +148,11 @@ class RiaGetActiveCellProperty: public RiaSocketCommand std::vector values(valueCount); size_t valueIndex = 0; - size_t globalCellCount = activeInfo->reservoirCellCount(); + size_t reservoirCellCount = activeInfo->reservoirCellCount(); for (size_t tIdx = 0; tIdx < requestedTimesteps.size(); ++tIdx) { std::vector& doubleValues = scalarResultFrames->at(requestedTimesteps[tIdx]); - for (size_t gcIdx = 0; gcIdx < globalCellCount; ++gcIdx) + for (size_t gcIdx = 0; gcIdx < reservoirCellCount; ++gcIdx) { size_t resultIdx = activeInfo->cellResultIndex(gcIdx); if (resultIdx == cvf::UNDEFINED_SIZE_T) continue; @@ -528,18 +528,18 @@ class RiaSetActiveCellProperty: public RiaSocketCommand RigActiveCellInfo* activeCellInfo = m_currentReservoir->reservoirData()->activeCellInfo(m_porosityModelEnum); - size_t globalActiveCellCount = activeCellInfo->reservoirActiveCellCount(); + size_t activeCellCountReservoir = activeCellInfo->reservoirActiveCellCount(); size_t totalCellCount = activeCellInfo->reservoirCellCount(); - size_t globalCellResultCount = activeCellInfo->reservoirCellResultCount(); + size_t reservoirCellResultCount = activeCellInfo->reservoirCellResultCount(); - bool isCoarseningActive = globalCellResultCount != globalActiveCellCount; + bool isCoarseningActive = reservoirCellResultCount != activeCellCountReservoir; - if (cellCountFromOctave != globalActiveCellCount ) + if (cellCountFromOctave != activeCellCountReservoir ) { server->errorMessageDialog()->showMessage(RiaSocketServer::tr("ResInsight SocketServer: \n") + RiaSocketServer::tr("The number of cells in the data coming from octave does not match the case") + ":\"" + m_currentReservoir->caseUserDescription() + "\"\n" " Octave: " + QString::number(cellCountFromOctave) + "\n" - " " + m_currentReservoir->caseUserDescription() + ": Active cell count: " + QString::number(globalActiveCellCount) + " Total cell count: " + QString::number(totalCellCount)) ; + " " + m_currentReservoir->caseUserDescription() + ": Active cell count: " + QString::number(activeCellCountReservoir) + " Total cell count: " + QString::number(totalCellCount)) ; cellCountFromOctave = 0; m_invalidActiveCellCountDetected = true; @@ -554,7 +554,7 @@ class RiaSetActiveCellProperty: public RiaSocketCommand for (size_t tIdx = 0; tIdx < m_timeStepCountToRead; ++tIdx) { size_t tsId = m_requestedTimesteps[tIdx]; - m_scalarResultsToAdd->at(tsId).resize(globalCellResultCount, HUGE_VAL); + m_scalarResultsToAdd->at(tsId).resize(reservoirCellResultCount, HUGE_VAL); } std::vector readBuffer; From 70dc296a13089e86841e9836fc9e76e12718d2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:51:39 +0200 Subject: [PATCH 084/346] Rename of GlobalCell to ReservoirCell --- .../RivFaultGeometryGenerator.cpp | 4 ++-- .../ReservoirDataModel/RigFault.cpp | 6 +++--- ApplicationCode/ReservoirDataModel/RigFault.h | 10 +++++----- .../ReservoirDataModel/RigMainGrid.cpp | 20 +++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index a45a4dad3e..a0ef33d344 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -163,12 +163,12 @@ void RivFaultGeometryGenerator::computeArrays() #pragma omp parallel for for (int fIdx = 0; fIdx < static_cast(faultFaces.size()); fIdx++) { - size_t cellIndex = faultFaces[fIdx].m_nativeGlobalCellIndex; + size_t cellIndex = faultFaces[fIdx].m_nativeReservoirCellIndex; cvf::StructGridInterface::FaceType face = faultFaces[fIdx].m_nativeFace; if (!m_computeNativeFaultFaces) { - cellIndex = faultFaces[fIdx].m_oppositeGlobalCellIndex; + cellIndex = faultFaces[fIdx].m_oppositeReservoirCellIndex; face = cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace); } diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 0db6f08c90..82e5c35eb3 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -145,10 +145,10 @@ void RigFault::accumulateFaultsPrCell(RigFaultsPrCellAccumulator* faultsPrCellA { const FaultFace& ff = m_faultFaces[ffIdx]; - // Could detect overlapping faults here .... if (faultsPrCellAcc->faultIdx(ff.m_nativeGlobalCellIndex, ff.m_nativeFace) >= 0) + // Could detect overlapping faults here .... if (faultsPrCellAcc->faultIdx(ff.m_nativeReservoirCellIndex, ff.m_nativeFace) >= 0) - faultsPrCellAcc->setFaultIdx(ff.m_nativeGlobalCellIndex, ff.m_nativeFace, faultIdx); - faultsPrCellAcc->setFaultIdx(ff.m_oppositeGlobalCellIndex, cvf::StructGridInterface::oppositeFace(ff.m_nativeFace), faultIdx); + faultsPrCellAcc->setFaultIdx(ff.m_nativeReservoirCellIndex, ff.m_nativeFace, faultIdx); + faultsPrCellAcc->setFaultIdx(ff.m_oppositeReservoirCellIndex, cvf::StructGridInterface::oppositeFace(ff.m_nativeFace), faultIdx); } } diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 0d310bce35..44d232bd7d 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -66,15 +66,15 @@ class RigFault : public cvf::Object struct FaultFace { - FaultFace(size_t nativeGlobalCellIndex, cvf::StructGridInterface::FaceType nativeFace, size_t oppositeGlobalCellIndex) : - m_nativeGlobalCellIndex(nativeGlobalCellIndex), + FaultFace(size_t nativeReservoirCellIndex, cvf::StructGridInterface::FaceType nativeFace, size_t oppositeReservoirCellIndex) : + m_nativeReservoirCellIndex(nativeReservoirCellIndex), m_nativeFace(nativeFace), - m_oppositeGlobalCellIndex(oppositeGlobalCellIndex) + m_oppositeReservoirCellIndex(oppositeReservoirCellIndex) { } - size_t m_nativeGlobalCellIndex; + size_t m_nativeReservoirCellIndex; cvf::StructGridInterface::FaceType m_nativeFace; - size_t m_oppositeGlobalCellIndex; + size_t m_oppositeReservoirCellIndex; }; public: diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index dc58bf21c3..21a8645632 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -234,7 +234,7 @@ void RigMainGrid::calculateFaults() continue; } - size_t neighborGlobalCellIdx; + size_t neighborReservoirCellIdx; size_t neighborGridCellIdx; size_t i, j, k; RigGridBase* hostGrid = NULL; @@ -259,8 +259,8 @@ void RigMainGrid::calculateFaults() continue; } - neighborGlobalCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); - if (m_cells[neighborGlobalCellIdx].isInvalid()) + neighborReservoirCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); + if (m_cells[neighborReservoirCellIdx].isInvalid()) { continue; } @@ -271,7 +271,7 @@ void RigMainGrid::calculateFaults() caf::SizeTArray4 faceIdxs; m_cells[gcIdx].faceIndices(face, &faceIdxs); caf::SizeTArray4 nbFaceIdxs; - m_cells[neighborGlobalCellIdx].faceIndices(StructGridInterface::oppositeFace(face), &nbFaceIdxs); + m_cells[neighborReservoirCellIdx].faceIndices(StructGridInterface::oppositeFace(face), &nbFaceIdxs); const std::vector& vxs = m_mainGrid->nodes(); @@ -289,17 +289,17 @@ void RigMainGrid::calculateFaults() // To avoid doing this calculation for the opposite face faultsPrCellAcc->setFaultIdx(gcIdx, face, unNamedFaultIdx); - faultsPrCellAcc->setFaultIdx(neighborGlobalCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); + faultsPrCellAcc->setFaultIdx(neighborReservoirCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); //m_cells[gcIdx].setCellFaceFault(face); - //m_cells[neighborGlobalCellIdx].setCellFaceFault(StructGridInterface::oppositeFace(face)); + //m_cells[neighborReservoirCellIdx].setCellFaceFault(StructGridInterface::oppositeFace(face)); // Add as fault face only if the grid index is less than the neighbors - if (static_cast(gcIdx) < neighborGlobalCellIdx) + if (static_cast(gcIdx) < neighborReservoirCellIdx) { { - RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborGlobalCellIdx); + RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborReservoirCellIdx); unNamedFault->faultFaces().push_back(ff); } @@ -382,7 +382,7 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) { - if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) + if (faultFaces[fIdx].m_nativeReservoirCellIndex == cellIndex) { if (face == faultFaces[fIdx].m_nativeFace ) { @@ -390,7 +390,7 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, } } - if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) + if (faultFaces[fIdx].m_oppositeReservoirCellIndex == cellIndex) { if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) { From bb82610fd8132f27730042563a7ede60ea59cf83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:07:05 +0200 Subject: [PATCH 085/346] New classes for the generalized texturing --- .../RivResultToTextureMapper.h | 64 +++++++++++++ .../RivTextureCoordsCreator.cpp | 89 +++++++++++++++++++ .../RivTextureCoordsCreator.h | 62 +++++++++++++ .../RigPipeInCellEvaluator.h | 52 +++++++++++ 4 files changed, 267 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/RivResultToTextureMapper.h create mode 100644 ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h create mode 100644 ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h diff --git a/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h new file mode 100644 index 0000000000..06dff66b72 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigPipeInCellEvaluator.h" + +#include "cvfVector2.h" +#include "cvfScalarMapper.h" +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" + +#include + +class RivResultToTextureMapper : public cvf::Object +{ +public: + RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, + const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + cvf::Vec2f getTexCoord(double resultValue, size_t cellIndex) const + { + cvf::Vec2f texCoord(0,0); + + if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + return texCoord; + } + + texCoord = m_scalarMapper->mapToTextureCoord(resultValue); + + if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) + { + texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture + } + + return texCoord; + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp new file mode 100644 index 0000000000..59163d5fdb --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -0,0 +1,89 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTextureCoordsCreator.h" + +#include "RimResultSlot.h" +#include "RigCaseData.h" +#include "RimReservoirView.h" +#include "RimCase.h" +#include "RigCaseCellResultsData.h" +#include "RigResultAccessorFactory.h" +#include "RigPipeInCellEvaluator.h" +#include "RivResultToTextureMapper.h" +#include "RimWellCollection.h" +#include "RigResultAccessor.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, size_t timeStepIndex, size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + m_quadMapper = quadMapper; + CVF_ASSERT(quadMapper && eclipseCase ); + + size_t resTimeStepIdx = timeStepIndex; + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + CVF_ASSERT(m_resultAccessor.notNull()); + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(gridIndex)); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + + m_texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); + CVF_ASSERT(m_texMapper.notNull()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords, const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper) +{ + CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); + + size_t numVertices = quadMapper->quadCount()*4; + quadTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = quadTextureCoords->ptr(); + + double resultValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, resultValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + resultValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(resultValue, cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } +} diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h new file mode 100644 index 0000000000..c08d647b0a --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RimResultSlot; +class RigResultAccessor; +class RivResultToTextureMapper; + +namespace cvf{ +class StructGridQuadToCellFaceMapper; + +} + + +class RivTextureCoordsCreator +{ +public: + RivTextureCoordsCreator(RimResultSlot* cellResultSlot, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) + { + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); + } + +private: + + static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigResultAccessor* resultAccessor, + const RivResultToTextureMapper* texMapper); + + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; +}; + + + + diff --git a/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h new file mode 100644 index 0000000000..5a65f69475 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RigPipeInCellEvaluator: public cvf::Object +{ +public: + RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap) + : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), + m_gridCellToWellIndexMap(gridCellToWellIndexMap) + { + } + + bool isWellPipeInCell( size_t cellIndex) const + { + cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); + + if (wellIndex == cvf::UNDEFINED_UINT) + { + return false; + } + + return m_isWellPipeVisibleForWellIndex[wellIndex]; + } + +private: + + const std::vector& m_isWellPipeVisibleForWellIndex; + const cvf::UIntArray* m_gridCellToWellIndexMap; +}; From 6a7652c597259a6c0138c3ca0bdd1f623de019bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:08:11 +0200 Subject: [PATCH 086/346] Wip: New generalized texturing in play Only on GridParts --- .../ModelVisualization/CMakeLists_files.cmake | 3 + .../ModelVisualization/RivGridPartMgr.cpp | 97 ++++++++++- .../ReservoirDataModel/CMakeLists_files.cmake | 1 + .../ReservoirDataModel/RigResultAccessor.h | 153 +----------------- .../RigResultAccessorFactory.cpp | 10 +- 5 files changed, 103 insertions(+), 161 deletions(-) diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 02509f21c9..9ca5bb10e4 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -22,6 +22,8 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h +${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h +${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -42,6 +44,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp +${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 47fe6765b8..9a018b8ed4 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,6 +50,11 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" +#include "cvfStructGridGeometryGenerator.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RivResultToTextureMapper.h" +#include "RivTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -207,7 +212,7 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) m_surfaceGridLines->setEffect(eff.p()); } } - +#if 0 //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -275,6 +280,96 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } +#endif +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) +{ + CVF_ASSERT(cellResultSlot); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + cvf::ref surfaceFacesColorArray; + + // Outer surface + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { + surfaceFacesColorArray = new cvf::Color3ubArray; + + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); + /* + // If the result is static, only read that. + size_t resTimeStepIdx = timeStepIndex; + const cvf::StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, m_grid->gridIndex(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + + if (resultAccessor.isNull()) return; + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex())); + + cvf::ref texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); + + + + size_t numVertices = quadMapper->quadCount()*4; + m_surfaceFacesTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); + + double cellScalarValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, cellScalarValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + cellScalarValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(cellScalarValue, cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } + */ + } + + + if (surfaceFacesColorArray.notNull()) // Ternary result + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + dg->setColorArray(surfaceFacesColorArray.p()); + } + + cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); + m_surfaceFaces->setEffect(perVertexColorEffect.p()); + + m_surfaceFaces->setPriority(100); + } + else + { + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + } + } +} //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 950bbb3f0d..4a23c7302f 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -29,6 +29,7 @@ ${CEE_CURRENT_LIST_DIR}RigFault.h ${CEE_CURRENT_LIST_DIR}RigNNCData.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.inl +${CEE_CURRENT_LIST_DIR}RigPipeInCellEvaluator.h ) set (SOURCE_GROUP_SOURCE_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index 1113695e22..dc248b7c73 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -87,156 +87,5 @@ class RivTernaryScalarMapper : public cvf::Object float m_opacityLevel; }; -class RigPipeInCellEvaluator: public cvf::Object -{ -public: - RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap) - : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), - m_gridCellToWellIndexMap(gridCellToWellIndexMap) - { - } - - bool isWellPipeInCell( size_t cellIndex) - { - cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); - - if (wellIndex == cvf::UNDEFINED_UINT) - { - return false; - } - - return m_isWellPipeVisibleForWellIndex[wellIndex]; - } - -private: - - const std::vector& m_isWellPipeVisibleForWellIndex; - const cvf::UIntArray* m_gridCellToWellIndexMap; -}; - -class RivResultToTextureMapper : public cvf::Object -{ - - RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, - const RigPipeInCellEvaluator* pipeInCellEvaluator) - : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) - {} - - Vec2f getTexCoord(double resultValue, size_t cellIndex) - { - Vec2f texCoord(0,0); - - if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's - { - texCoord[1] = 1.0f; - return texCoord; - } - - texCoord = m_scalarMapper->mapToTexCoord(resultValue); - - if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) - { - texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture - } - - return texCoord; - } - -private: - cvf::cref m_scalarMapper; - cvf::cref m_pipeInCellEvaluator; -}; - - - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) -{ - CVF_ASSERT(cellResultSlot); - - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - - cvf::ref surfaceFacesColorArray; - - // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); - } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); - } - else - { - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - - if (resultAccessor.isNull()) return; - - RivResultToTextureMapper texMapper(mapper, - RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()))); - - const StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); - - size_t numVertices = quadMapper->quadCount()*4; - m_surfaceFacesTextureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) - { - StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); - - cellScalarValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); - - texCoord = texMapper->mapToTextureCoord(cellScalarValue); - - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[i*4 + j] = texCoord; - } - } - } - - - if (surfaceFacesColorArray.notNull()) // Ternary result - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } - } -} #endif diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index d44ffc0dfb..de23da6f87 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -107,12 +107,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa RigGridBase* grid = eclipseCase->grid(gridIndex); - // Ternary - if (uiResultName == RimDefines::ternarySaturationResultName()) - { - return NULL; - } - else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + if (uiResultName == RimDefines::combinedTransmissibilityResultName()) { cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); @@ -125,8 +120,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } - - return NULL; + return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From a9794815c7bd58b89a94adecf7bd80dddaaad18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:44:21 +0200 Subject: [PATCH 087/346] Used new texturing on faults --- .../ModelVisualization/RivFaultPartMgr.cpp | 85 ++-------- .../ModelVisualization/RivGridPartMgr.cpp | 146 +----------------- .../ModelVisualization/RivGridPartMgr.h | 4 - 3 files changed, 19 insertions(+), 216 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 2d261dfc0c..47195d7d3b 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -32,6 +32,8 @@ #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigResultAccessor.h" + #include "RimCase.h" #include "RimWellCollection.h" #include "cafPdmFieldCvfMat4d.h" @@ -48,8 +50,9 @@ #include "cvfRenderStateDepth.h" #include "RivSourceInfo.h" #include "RimFaultCollection.h" +#include "RivTextureCoordsCreator.h" - +#include "RivResultToTextureMapper.h" @@ -130,45 +133,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_nativeFaultFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, - m_nativeFaultGenerator->cellFromQuadMapper()); - } else { - if (resultAccessor.isNull()) - { - return; - } - m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); - - } - - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_nativeFaultGenerator->cellFromQuadMapper()); - for(size_t i = 0; i < m_nativeFaultFacesTextureCoords->size(); ++i) - { - if ((*m_nativeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_nativeFaultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); } cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); @@ -204,43 +176,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_oppositeFaultFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_oppositeFaultGenerator->cellFromQuadMapper()); - } else { - if (resultAccessor.isNull()) - { - return; - } - - m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); - } - - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_oppositeFaultGenerator->cellFromQuadMapper(); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); - for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) - { - if ((*m_oppositeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_oppositeFaultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); } cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 9a018b8ed4..51bd6e77c0 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -212,75 +212,7 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) m_surfaceGridLines->setEffect(eff.p()); } } -#if 0 -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) -{ - CVF_ASSERT(cellResultSlot); - - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - - cvf::ref surfaceFacesColorArray; - - // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); - } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); - } - else - { - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (resultAccessor.isNull()) return; - - m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), resultAccessor.p(), mapper); - } - - - setResultsTransparentForWellCells( - cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), - m_surfaceGenerator.quadToCellFaceMapper(), - m_surfaceFacesTextureCoords.p()); - - if (surfaceFacesColorArray.notNull()) - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } - } -} -#endif //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -304,50 +236,12 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); - texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - /* - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - const cvf::StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); - - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, m_grid->gridIndex(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - - if (resultAccessor.isNull()) return; - - cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex())); - - cvf::ref texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); - - - - size_t numVertices = quadMapper->quadCount()*4; - m_surfaceFacesTextureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) - { - cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); - size_t cellIdx = quadMapper->cellIndex(i); - - cellScalarValue = resultAccessor->cellFaceScalar(cellIdx, faceId); - texCoord = texMapper->getTexCoord(cellScalarValue, cellIdx); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[i*4 + j] = texCoord; - } - } - */ + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); } @@ -397,36 +291,6 @@ void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* part->setEffect(scalarEffect.p()); } -//-------------------------------------------------------------------------------------------------- -/// if this gridpart manager is set to have some transparency, we -/// interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but -/// we turn that off for particular cells, if the well pipe is not shown for that cell -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap, - const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, - cvf::Vec2fArray* resultTextureCoords) -{ - if (m_opacityLevel < 1.0f ) - { - for(size_t i = 0; i < resultTextureCoords->size(); ++i) - { - if ((*resultTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToCellFaceMapper->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellIndexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisibleForWellIndex[wellIndex]) - { - (*resultTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 6e555300a6..ed6efb4c11 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -91,10 +91,6 @@ class RivGridPartMgr: public cvf::Object void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); - void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap, - const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, - cvf::Vec2fArray* resultTextureCoords); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, cvf::StructGridGeometryGenerator* surfaceGenerator, size_t timeStepIndex, From faff8dd380fe06177fd6c3952df65c85903599c3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:45:21 +0200 Subject: [PATCH 088/346] Removed asserts and simplified code --- .../RigResultModifierFactory.cpp | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp index 80efe51c5a..8d04aa6bcf 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp @@ -34,12 +34,9 @@ cvf::ref RigResultModifierFactory::createResultModifier(RigCa size_t timeStepIndex, QString& uiResultName) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + if (!eclipseCase) return NULL; - if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + if (!eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) { return NULL; } @@ -58,23 +55,24 @@ cvf::ref RigResultModifierFactory::createResultModifier(RigCa RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarResultIndex) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + if (!eclipseCase) return NULL; - RigGridBase* grid = eclipseCase->grid(gridIndex); - - if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) - { - return NULL; - } + if (!eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { return NULL; } + RigGridBase* grid = eclipseCase->grid(gridIndex); + if (!grid) + { + return NULL; + } + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarResultIndex); if (timeStepIndex >= scalarSetResults.size()) From b5d79ecb65b7017c170c3d57512909b6a96c7c11 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:46:27 +0200 Subject: [PATCH 089/346] Use RigResultAccessFactory --- .../SocketInterface/RiaPropertyDataCommands.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 9edfad2c82..df9106bcf8 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -41,6 +41,8 @@ #include "RiuMainWindow.h" #include "RiuProcessMonitor.h" +#include "RigResultAccessorFactory.h" +#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- @@ -319,8 +321,9 @@ class RiaGetGridProperty: public RiaSocketCommand for (size_t tsIdx = 0; tsIdx < timestepCount; tsIdx++) { - cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->resultAccessor(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); - if (cellCenterDataAccessObject.isNull()) + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(rimCase->reservoirData(), gridIdx, porosityModelEnum, requestedTimesteps[tsIdx], propertyName); + + if (resultAccessor.isNull()) { continue; } @@ -330,7 +333,7 @@ class RiaGetGridProperty: public RiaSocketCommand size_t valueIndex = 0; for (size_t cellIdx = 0; cellIdx < rigGrid->cellCount(); cellIdx++) { - double cellValue = cellCenterDataAccessObject->cellScalar(cellIdx); + double cellValue = resultAccessor->cellScalar(cellIdx); if (cellValue == HUGE_VAL) { cellValue = 0.0; From 14b5919e59c65dfd05dc53715a8b07c7b566f249 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:46:48 +0200 Subject: [PATCH 090/346] Use RigResultAccessFactory --- .../FileInterface/RifEclipseInputFileTools.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 1211dc9208..63c50908f3 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -21,6 +21,8 @@ #include "RifReaderEclipseOutput.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "cafProgressInfo.h" @@ -500,8 +502,8 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa return false; } - cvf::ref resultAccessor = eclipseCase->resultAccessor(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); - if (resultAccessor.isNull()) + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, eclipseCase->mainGrid()->gridIndex(), porosityModel, timeStep, resultName); + if (resultAccessor.isNull()) { return false; } @@ -514,7 +516,7 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa { for (i = 0; i < eclipseCase->mainGrid()->cellCountI(); i++) { - double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); + double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); if (resultValue == HUGE_VAL) { resultValue = undefinedValue; From 852afd9318543a02e66f295352cd1949a3557446 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:47:36 +0200 Subject: [PATCH 091/346] Prefix function to be deleted to easily spot the function in code --- .../RivCellEdgeEffectGenerator.cpp | 4 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 1 - .../ModelVisualization/RivGridPartMgr.cpp | 12 ++++++------ .../RivReservoirViewPartMgr.cpp | 2 +- .../ProjectDataModel/RimReservoirView.cpp | 18 +++++++++--------- .../RimStatisticsCaseEvaluator.cpp | 4 ++-- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../ReservoirDataModel/RigCaseData.h | 2 +- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 0dd9043c09..67ce43d69d 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -121,7 +121,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( } RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); + cellCenterDataAccessObject = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); } CVF_ASSERT(cellEdgeResultSlot->hasResult()); @@ -140,7 +140,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( { // Assuming static values to be mapped onto cell edge, always using time step zero // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); + daObj = eclipseCase->TO_BE_DELETED_resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); } cellEdgeDataAccessObjects.push_back(daObj.p()); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 47195d7d3b..ba9cc67315 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -120,7 +120,6 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); // Faults if (m_nativeFaultFaces.notNull()) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 51bd6e77c0..21ef0d7169 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -419,9 +419,9 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObjectTranX = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); + cvf::ref dataAccessObjectTranX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); + cvf::ref dataAccessObjectTranY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); + cvf::ref dataAccessObjectTranZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); int quadCount = static_cast(quadToCellFaceMapper->quadCount()); @@ -560,19 +560,19 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - cvf::ref dataAccessObjectSoil = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectSoil = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); if (dataAccessObjectSoil.isNull()) { dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSgas = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectSgas = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); if (dataAccessObjectSgas.isNull()) { dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSwat = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); + cvf::ref dataAccessObjectSwat = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); if (dataAccessObjectSwat.isNull()) { dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 7c31d28ce4..4e7e4598d4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -728,7 +728,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 65a8f6706a..21782dbcc7 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1116,9 +1116,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); + cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); + cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); double scalarValue = 0.0; @@ -1147,9 +1147,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t tranX, tranY, tranZ; if (eclipseCase->results(porosityModel)->findTransmissibilityResults(tranX, tranY, tranZ)) { - cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, 0, tranX); - cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, 0, tranY); - cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, 0, tranZ); + cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranX); + cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranY); + cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranZ); double scalarValue = dataAccessObjectX->cellScalar(cellIndex); resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); @@ -1163,12 +1163,12 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, } else { - resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); } } else { - resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); } if (resultAccessor.notNull()) @@ -1191,7 +1191,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, resultIndices[idx]); + cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, resultIndices[idx]); if (resultAccessor.notNull()) { double scalarValue = resultAccessor->cellScalar(cellIndex); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 0225d62e56..0be78814ba 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -197,7 +197,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - cvf::ref resultAccessor = sourceCase->reservoirData()->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = sourceCase->reservoirData()->TO_BE_DELETED_resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); if (resultAccessor.notNull()) { sourceDataAccessList.push_back(resultAccessor.p()); @@ -349,7 +349,7 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); + cvf::ref resultAccessor = m_destinationCase->TO_BE_DELETED_resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); if (resultAccessor.isNull()) return; for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 1d5619f87b..4aa6af1889 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -488,7 +488,7 @@ const RigCaseCellResultsData* RigCaseData::results(RifReaderInterface::PorosityM //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigCaseData::resultAccessor(const RigGridBase* grid, +cvf::ref RigCaseData::TO_BE_DELETED_resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index 68960b381a..9177e5d7ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -54,7 +54,7 @@ class RigCaseData: public cvf::Object void setActiveCellInfo(RifReaderInterface::PorosityModelResultType porosityModel, RigActiveCellInfo* activeCellInfo); - cvf::ref resultAccessor(const RigGridBase* grid, + cvf::ref TO_BE_DELETED_resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex); From 77c8edf3482fa79830d1eed3f7d9eb98e3559ba2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:51:00 +0200 Subject: [PATCH 092/346] Removed obsolete code --- .../ModelVisualization/RivGridPartMgr.cpp | 118 ------------------ .../ModelVisualization/RivGridPartMgr.h | 5 - 2 files changed, 123 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 21ef0d7169..712c4e1e45 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -394,124 +394,6 @@ cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacit } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Vec2fArray* textureCoords, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) -{ - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - if (!mapper) return; - - const RimReservoirCellResultsStorage* gridCellResults = cellResultSlot->currentGridCellResults(); - if (!gridCellResults) return; - - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - if (!eclipseCase) return; - - size_t tranPosXScalarSetIndex, tranPosYScalarSetIndex, tranPosZScalarSetIndex; - if (!gridCellResults->cellResults()->findTransmissibilityResults(tranPosXScalarSetIndex, tranPosYScalarSetIndex, tranPosZScalarSetIndex)) return; - - // If the result is static, only read that. - size_t resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - cvf::ref dataAccessObjectTranX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); - - - int quadCount = static_cast(quadToCellFaceMapper->quadCount()); - size_t numVertices = quadCount*4; - - textureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = textureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int quadIdx = 0; quadIdx < quadCount; quadIdx++) - { - cellScalarValue = HUGE_VAL; - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - - switch (cellFace) - { - case cvf::StructGridInterface::POS_I: - { - cellScalarValue = dataAccessObjectTranX->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_I: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); - } - } - break; - case cvf::StructGridInterface::POS_J: - { - cellScalarValue = dataAccessObjectTranY->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_J: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); - } - } - break; - case cvf::StructGridInterface::POS_K: - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_K: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); - } - } - break; - default: - CVF_ASSERT(false); - } - - - texCoord = mapper->mapToTextureCoord(cellScalarValue); - if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's - { - texCoord[1] = 1.0f; - } - - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[quadIdx*4 + j] = texCoord; - } - } - -} - - //-------------------------------------------------------------------------------------------------- /// 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. diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index ed6efb4c11..4985a360bf 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -44,11 +44,6 @@ class RimCellEdgeResultSlot; class RivTransmissibilityColorMapper { public: - static void updateCombinedTransmissibilityTextureCoordinates( - RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Vec2fArray* textureCoords, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); static void updateTernarySaturationColorArray( size_t timeStepIndex, From f023ec98e8259aacf43aa7d1df79dd3613fd7bdb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:08:30 +0200 Subject: [PATCH 093/346] Added overload to result accessor factory --- .../RigResultAccessorFactory.cpp | 147 ++++++++++++------ .../RigResultAccessorFactory.h | 17 +- 2 files changed, 112 insertions(+), 52 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index de23da6f87..71f20f5083 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -36,6 +36,69 @@ #include "RigCombTransResultAccessor.h" +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); + + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); + + cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); + + return cellFaceAccessObject; + } + + return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName, + RimDefines::ResultCatType resultType) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(resultType, uiResultName); + if (scalarSetIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + return createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); +} + //-------------------------------------------------------------------------------------------------- /// This function must be harmonized with RigResultModifierFactory::createResultModifier() //-------------------------------------------------------------------------------------------------- @@ -63,64 +126,46 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor return NULL; } - std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); - - if (timeStepIndex >= scalarSetResults.size()) - { - return NULL; - } - - std::vector* resultValues = NULL; - if (timeStepIndex < scalarSetResults.size()) - { - resultValues = &(scalarSetResults[timeStepIndex]); - } - - bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); - if (useGlobalActiveIndex) - { - cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); - return object; - } - else - { - cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); - return object; - } + return createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); } - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - const QString& uiResultName) + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); - - RigGridBase* grid = eclipseCase->grid(gridIndex); - - if (uiResultName == RimDefines::combinedTransmissibilityResultName()) - { - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - - cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); - cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); - cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); - - cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); - - return cellFaceAccessObject; - } - - return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); + if (!eclipseCase) return NULL; + + RigGridBase* grid = eclipseCase->grid(gridIndex); + if (!grid) return NULL; + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(resultIndex); + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(resultIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); + return object; + } } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 6a4a414865..15d2ebd99f 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -18,9 +18,10 @@ #pragma once -#include "cvfStructGridScalarDataAccess.h" #include "RifReaderInterface.h" +#include "RimDefines.h" +#include "cvfStructGridScalarDataAccess.h" class RigActiveCellInfo; class RigGridBase; @@ -36,6 +37,14 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& uiResultName); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName, + RimDefines::ResultCatType resultType); + // TO BE DELETED static cvf::ref @@ -54,6 +63,12 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& resultName); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex); }; From 566263776d0877263ebdcd10e47678e1538dc3bd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:10:10 +0200 Subject: [PATCH 094/346] Use RigResultAccessor --- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 0be78814ba..f6bbada699 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,6 +20,8 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "RigResultModifier.h" #include "RigResultModifierFactory.h" #include "RigStatisticsMath.h" @@ -190,14 +192,12 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result // Build data access objects for source scalar results - cvf::Collection sourceDataAccessList; + cvf::Collection sourceDataAccessList; for (size_t caseIdx = 0; caseIdx < m_sourceCases.size(); caseIdx++) { RimCase* sourceCase = m_sourceCases.at(caseIdx); - size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - - cvf::ref resultAccessor = sourceCase->reservoirData()->TO_BE_DELETED_resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(sourceCase->reservoirData(), gridIdx, poroModel, dataAccessTimeStepIndex, resultName, resultType); if (resultAccessor.notNull()) { sourceDataAccessList.push_back(resultAccessor.p()); From e0fb65188efaad96d827c75e2ccf54d23d491c28 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:11:30 +0200 Subject: [PATCH 095/346] Deleted unused code --- .../RimStatisticsCaseEvaluator.cpp | 19 ------------------- .../RimStatisticsCaseEvaluator.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index f6bbada699..83af15a0dc 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -338,25 +338,6 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultType, const QString& resultName, size_t timeStepIdx) -{ - CVF_ASSERT(m_destinationCase); - - qDebug() << resultName << "timeIdx : " << timeStepIdx; - - size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - - cvf::ref resultAccessor = m_destinationCase->TO_BE_DELETED_resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); - if (resultAccessor.isNull()) return; - - for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) - { - qDebug() << resultAccessor->cellScalar(cellIdx); - } -} //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 87b21c7aae..62f4ca36cc 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -73,8 +73,6 @@ class RimStatisticsCaseEvaluator void evaluateForResults(const QList& resultSpecification); - void debugOutput(RimDefines::ResultCatType resultType, const QString& resultName, size_t timeStepIdx); - private: void addNamedResult(RigCaseCellResultsData* cellResults, RimDefines::ResultCatType resultType, const QString& resultName, size_t activeCellCount); void buildSourceMetaData(RifReaderInterface::PorosityModelResultType poroModel, RimDefines::ResultCatType resultType, const QString& resultName); From e2e054d4617166084522fd04bf1f783bbd645475 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:21:46 +0200 Subject: [PATCH 096/346] Added include to RigResultAccessor in factory --- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 1 - ApplicationCode/ModelVisualization/RivGridPartMgr.cpp | 1 - ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp | 1 - ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 1 - ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h | 2 +- ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 63c50908f3..dedd0e78f0 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -21,7 +21,6 @@ #include "RifReaderEclipseOutput.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 712c4e1e45..99fa9bf715 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -51,7 +51,6 @@ #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" #include "cvfStructGridGeometryGenerator.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "RivResultToTextureMapper.h" #include "RivTextureCoordsCreator.h" diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index 59163d5fdb..ff97711e3d 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -27,7 +27,6 @@ #include "RigPipeInCellEvaluator.h" #include "RivResultToTextureMapper.h" #include "RimWellCollection.h" -#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 83af15a0dc..778b4d19c0 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,7 +20,6 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "RigResultModifier.h" #include "RigResultModifierFactory.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 15d2ebd99f..6c1d890dd7 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -19,13 +19,13 @@ #pragma once #include "RifReaderInterface.h" +#include "RigResultAccessor.h" #include "RimDefines.h" #include "cvfStructGridScalarDataAccess.h" class RigActiveCellInfo; class RigGridBase; -class RigResultAccessor; class RigResultAccessorFactory { diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index df9106bcf8..a8257f834b 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -42,7 +42,6 @@ #include "RiuMainWindow.h" #include "RiuProcessMonitor.h" #include "RigResultAccessorFactory.h" -#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- From 932f00ab1ae59f884713c1deb581f683d166fa8e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:22:00 +0200 Subject: [PATCH 097/346] Use RigResultAccessor --- .../RivReservoirViewPartMgr.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 4e7e4598d4..461a90c7d0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -17,27 +17,27 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaStdInclude.h" + #include "RivReservoirViewPartMgr.h" -#include "RivGridPartMgr.h" -#include "RimReservoirView.h" + +#include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigGridBase.h" -#include "RigCaseCellResultsData.h" #include "RigResultAccessorFactory.h" + +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimCellRangeFilterCollection.h" -#include "RimWellCollection.h" +#include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimReservoirView.h" #include "RimResultDefinition.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" - #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsStorage.h" -#include "RimFaultCollection.h" +#include "RimWellCollection.h" + +#include "RivGridPartMgr.h" //-------------------------------------------------------------------------------------------------- /// @@ -728,7 +728,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, adjustedTimeStepIndex, (*pfIt)->resultDefinition->resultVariable(), (*pfIt)->resultDefinition->resultType()); CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) From 0861ab041dc6fc23478c91d214fd5e452f8648b5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:26:50 +0200 Subject: [PATCH 098/346] Moved include from header to cpp --- .../ModelVisualization/RivCellEdgeEffectGenerator.cpp | 1 + ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 1 + ApplicationCode/ReservoirDataModel/RigGridBase.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 67ce43d69d..bbaf9eafb6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -65,6 +65,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" +#include "cvfStructGridScalarDataAccess.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 21782dbcc7..063474c3f8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -51,6 +51,7 @@ #include "cvfOverlayScalarMapperLegend.h" #include "cvfPart.h" #include "cvfScene.h" +#include "cvfStructGridScalarDataAccess.h" #include "cvfViewport.h" #include "cvfqtUtils.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index c9ce6d8c54..0197cd0405 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -24,7 +24,6 @@ #include "cvfBoundingBox.h" #include "cvfStructGrid.h" #include "cvfStructGridGeometryGenerator.h" -#include "cvfStructGridScalarDataAccess.h" #include "cafFixedArray.h" From 94f184b1beb863ac8a1a7ec5b71d19228bcd5b33 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 22:23:41 +0200 Subject: [PATCH 099/346] Added RivTernaryScalarMapper and unit test --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../CMakeLists.txt | 5 + .../RivTernaryScalarMapper-Test.cpp | 49 +++++++++ .../RivTernaryScalarMapper.cpp | 102 ++++++++++++++++++ .../RivTernaryScalarMapper.h | 47 ++++++++ 5 files changed, 205 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 9ca5bb10e4..ee8779f9c2 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -24,6 +24,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h ${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -45,6 +46,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt index 0b0bb00ce8..97e839bfc1 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt @@ -19,6 +19,7 @@ include_directories( set( MODEL_VISUALIZATION_CPP_SOURCES ../RivPipeGeometryGenerator.cpp + ../RivTernaryScalarMapper.cpp ) @@ -29,6 +30,7 @@ set( CPP_SOURCES set( UNIT_TEST_CPP_SOURCES main.cpp RivPipeGeometryGenerator-Test.cpp + RivTernaryScalarMapper-Test.cpp ) @@ -37,10 +39,13 @@ set( LINK_LIBRARIES LibRender LibGeometry LibCore + LibGuiQt CommonCode ${OPENGL_LIBRARIES} + ${QT_LIBRARIES} + ) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp new file mode 100644 index 0000000000..f39cedfb77 --- /dev/null +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +// #include "cvfLibCore.h" +// #include "cvfLibViewing.h" +// #include "cvfLibRender.h" +// #include "cvfLibGeometry.h" +// +// #include "RivPipeGeometryGenerator.h" + +#include "RivTernaryScalarMapper.h" +#include "cvfTextureImage.h" + +#include +#include "cvfqtUtils.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(TernaryScalarMapperTest, BasicFunctions) +{ + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + + cvf::ref texImage = new cvf::TextureImage; + scalarMapper->updateTexture(texImage.p()); + + QImage img = cvfqt::Utils::toQImage(*(texImage.p())); + + img.save("c:/tmp/test.bmp"); + +} + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp new file mode 100644 index 0000000000..0f0f1ed9cf --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryScalarMapper.h" +#include "cvfTextureImage.h" + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) +: m_undefScalarColor(undefScalarColor), + m_opacityLevel(opacityLevel), + m_textureSize(128, 256) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) +{ + cvf::Vec2f texCoord; + + return texCoord; +} + +//-------------------------------------------------------------------------------------------------- +/// F * +/// * * +/// * * +/// * * Texture in this region is assigned the given opacity level +/// * * +/// D *********** E +/// C * +/// * * +/// * * Texture in this region is opaque +/// * * +/// * * +/// A *********** B +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) +{ + CVF_ASSERT(image); + image->allocate(m_textureSize.x(), m_textureSize.y()); + + // For now fill with white so we can see any errors more easily + image->fill(cvf::Color4ub(cvf::Color3::WHITE)); + + + + cvf::uint halfTextureHeight = m_textureSize.y() / 2; + + // Create texture + + float xStride = static_cast(1.0f / m_textureSize.x()); + float yStride = static_cast(1.0f / halfTextureHeight); + + float sgas_red = 0.0f; + for (int yPos = 0; yPos < halfTextureHeight; yPos++) + { + float soil_green = 0.0f; + for (int xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) + { + float swat_blue = 1.0f - sgas_red - soil_green; + + cvf::Color3f floatCol(sgas_red, soil_green, swat_blue); + + cvf::ubyte rByteCol = floatCol.rByte(); + cvf::ubyte gByteCol = floatCol.gByte(); + cvf::ubyte bByteCol = floatCol.bByte(); + + const cvf::Color4ub clr(rByteCol, gByteCol, bByteCol, 255); + image->setPixel(xPos, yPos, clr); + + // Set opacity + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, 255 * m_opacityLevel); + image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); + + soil_green += xStride; + } + sgas_red += yStride; + } + + return true; +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h new file mode 100644 index 0000000000..8da5bf112e --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector2.h" +#include "cvfColor3.h" + +namespace cvf +{ + class TextureImage; +} + +//================================================================================================== +/// +//================================================================================================== +class RivTernaryScalarMapper : public cvf::Object +{ +public: + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + + cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); + bool updateTexture(cvf::TextureImage* image); + +private: + cvf::Color3f m_undefScalarColor; + float m_opacityLevel; + cvf::Vec2ui m_textureSize; +}; + From 3dbf7cb866587ade8d0e5ece32a34383d9c7fb2d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 10 Aug 2014 09:50:50 +0200 Subject: [PATCH 100/346] Created texture and texture coord calculations --- .../RivTernaryScalarMapper-Test.cpp | 73 ++++++++++++++++--- .../RivTernaryScalarMapper.cpp | 34 ++++++++- .../RivTernaryScalarMapper.h | 10 +++ 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index f39cedfb77..dc7f62b9a6 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -18,18 +18,12 @@ #include "gtest/gtest.h" -// #include "cvfLibCore.h" -// #include "cvfLibViewing.h" -// #include "cvfLibRender.h" -// #include "cvfLibGeometry.h" -// -// #include "RivPipeGeometryGenerator.h" - #include "RivTernaryScalarMapper.h" + #include "cvfTextureImage.h" +#include "cvfqtUtils.h" #include -#include "cvfqtUtils.h" //-------------------------------------------------------------------------------------------------- /// @@ -43,7 +37,66 @@ TEST(TernaryScalarMapperTest, BasicFunctions) QImage img = cvfqt::Utils::toQImage(*(texImage.p())); - img.save("c:/tmp/test.bmp"); - + img.save("c:/tmp/test.png"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(TernaryScalarMapperTest, TextureMapping) +{ + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + + // Without opacity + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 0.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(1.0, 0.0, false); + EXPECT_DOUBLE_EQ(1.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 1.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.5, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(3.0, 3.0, false); + EXPECT_DOUBLE_EQ(1.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(-1.0, -1.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.5, 3.0, false); + EXPECT_DOUBLE_EQ(0.5, texCoord.x()); + EXPECT_DOUBLE_EQ(0.25, texCoord.y()); + } + + + + + // Opacity + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 0.0, true); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.5, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 1.0, true); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(1.0, texCoord.y()); + } +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 0f0f1ed9cf..33561806dc 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -29,6 +29,7 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo m_opacityLevel(opacityLevel), m_textureSize(128, 256) { + setTernaryRanges(0.0, 1.0, 0.0, 1.0); } //-------------------------------------------------------------------------------------------------- @@ -36,8 +37,19 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo //-------------------------------------------------------------------------------------------------- cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) { - cvf::Vec2f texCoord; + double soilNormalized = (soil - m_rangeMinSoil) * m_soilFactor; + soilNormalized = cvf::Math::clamp(soilNormalized, 0.0, 1.0); + double swatNormalized = (swat - m_rangeMinSwat) * m_swatFactor; + swatNormalized = cvf::Math::clamp(swatNormalized, 0.0, 1.0 - soilNormalized); + swatNormalized /= 2.0; + + if (isTransparent) + { + swatNormalized += 0.5; + } + + cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(swatNormalized)); return texCoord; } @@ -73,10 +85,10 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) float yStride = static_cast(1.0f / halfTextureHeight); float sgas_red = 0.0f; - for (int yPos = 0; yPos < halfTextureHeight; yPos++) + for (cvf::uint yPos = 0; yPos < halfTextureHeight; yPos++) { float soil_green = 0.0f; - for (int xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) + for (cvf::uint xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) { float swat_blue = 1.0f - sgas_red - soil_green; @@ -90,7 +102,7 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) image->setPixel(xPos, yPos, clr); // Set opacity - const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, 255 * m_opacityLevel); + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * m_opacityLevel)); image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); soil_green += xStride; @@ -100,3 +112,17 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) return true; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper) +{ + m_rangeMinSoil = soilLower; + m_rangeMaxSoil = soilUpper; + m_soilFactor = 1.0 / (soilUpper - soilLower); + + m_rangeMinSwat = swatLower; + m_rangeMaxSwat = swatUpper; + m_swatFactor = 1.0 / (swatUpper - swatLower); +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 8da5bf112e..5c952782a5 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -36,6 +36,8 @@ class RivTernaryScalarMapper : public cvf::Object public: RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + void setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper); + cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); bool updateTexture(cvf::TextureImage* image); @@ -43,5 +45,13 @@ class RivTernaryScalarMapper : public cvf::Object cvf::Color3f m_undefScalarColor; float m_opacityLevel; cvf::Vec2ui m_textureSize; + + double m_rangeMaxSoil; + double m_rangeMinSoil; + double m_soilFactor; + + double m_rangeMaxSwat; + double m_rangeMinSwat; + double m_swatFactor; }; From 7f01d1cf664d6754fe3ea1870c49eb1f14e43bd9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 10 Aug 2014 14:55:27 +0200 Subject: [PATCH 101/346] Added RigResultAccessor2d --- .../ReservoirDataModel/CMakeLists_files.cmake | 3 + .../ReservoirDataModel/RigResultAccessor2d.h | 39 +++++++++ .../RigTernaryResultAccessor2d.cpp | 86 +++++++++++++++++++ .../RigTernaryResultAccessor2d.h | 46 ++++++++++ 4 files changed, 174 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h create mode 100644 ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 4a23c7302f..25f9be656d 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -30,6 +30,8 @@ ${CEE_CURRENT_LIST_DIR}RigNNCData.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.inl ${CEE_CURRENT_LIST_DIR}RigPipeInCellEvaluator.h +${CEE_CURRENT_LIST_DIR}RigResultAccessor2d.h +${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -55,6 +57,7 @@ ${CEE_CURRENT_LIST_DIR}RigWellPath.cpp ${CEE_CURRENT_LIST_DIR}RigFault.cpp ${CEE_CURRENT_LIST_DIR}RigNNCData.cpp ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.cpp +${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h new file mode 100644 index 0000000000..87e0e2b3f5 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector2.h" +#include "cvfStructGrid.h" + +//================================================================================================== +/// +//================================================================================================== +class RigResultAccessor2d : public cvf::Object +{ +public: + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + +}; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp new file mode 100644 index 0000000000..ef3b02d8ad --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigTernaryResultAccessor2d.h" + +#include "RigResultAccessor.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigTernaryResultAccessor::RigTernaryResultAccessor() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// Requires at least two data objects present, asserts if more than one data accessor is NULL +//-------------------------------------------------------------------------------------------------- +void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat) +{ + m_soilAccessor = soil; + m_sgasAccessor = sgas; + m_swatAccessor = swat; + + int nullPointerCount = 0; + if (!soil) nullPointerCount++; + if (!sgas) nullPointerCount++; + if (!swat) nullPointerCount++; + + CVF_ASSERT(nullPointerCount <= 1); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) +{ + double soil = 0.0; + double swat = 0.0; + + if (m_soilAccessor.notNull()) + { + soil = m_soilAccessor->cellScalar(gridLocalCellIndex); + + if (m_swatAccessor.notNull()) + { + swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + } + else + { + swat = 1.0 - soil - m_sgasAccessor->cellScalar(gridLocalCellIndex); + } + } + else + { + swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + + soil = 1.0 - swat - m_sgasAccessor->cellScalar(gridLocalCellIndex); + } + + return cvf::Vec2d(soil, swat); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +{ + return cellScalar(gridLocalCellIndex); +} diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h new file mode 100644 index 0000000000..d1e85bcade --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessor2d.h" + +class RigResultAccessor; + +//================================================================================================== +/// +//================================================================================================== +class RigTernaryResultAccessor : public RigResultAccessor2d +{ +public: + RigTernaryResultAccessor(); + + /// Requires two of the arguments to be present + void setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat); + + /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// based on the two others + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex); + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId);; + +private: + cvf::ref m_soilAccessor; + cvf::ref m_sgasAccessor; + cvf::ref m_swatAccessor; +}; + From 5c9a57178e83146cb9187ae6159dfbb0c6d01955 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:41:28 +0200 Subject: [PATCH 102/346] Minor fixes for result accessors --- .../ReservoirDataModel/RigResultAccessor.h | 54 ------------------- .../ReservoirDataModel/RigResultAccessor2d.h | 3 -- .../RigTernaryResultAccessor2d.cpp | 4 +- .../RigTernaryResultAccessor2d.h | 7 ++- 4 files changed, 5 insertions(+), 63 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index dc248b7c73..7bf45e048c 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -35,57 +35,3 @@ class RigResultAccessor : public cvf::Object virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; -#if 0 - -//================================================================================================== -/// -//================================================================================================== -class RigResultAccessor2d : public cvf::Object -{ -public: - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - -}; - -//================================================================================================== -/// -//================================================================================================== -class RigTernaryResultAccessor : public Rig2DResultAccessor -{ -public: - /// Requires two of the arguments to be present - void setTernaryResultAccessors(RigResultAccessObject* soil, RigResultAccessObject* sgas, RigResultAccessObject* swat); - - /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated - /// based on the two others - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) { }; - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t gridLocalCellIndex); }; - - virtual QString resultName() const = 0; - -}; - -class RivTernaryScalarMapper : public cvf::Object -{ -public: - RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) : m_undefScalarColor(undefScalarColor), m_opacityLevel(opacityLevel) - { - - } - - /// Calculate texture coords into an image produced by updateTexture, from the scalarValue - Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent) {} - - /// Update the supplied TextureImage to be addressable by the texture coords delivered by mapToTextureCoord - bool updateTexture(TextureImage* image){} - -private: - cvf::Color3f m_undefScalarColor; - float m_opacityLevel; -}; - - -#endif diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h index 87e0e2b3f5..c3b568be20 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h @@ -33,7 +33,4 @@ class RigResultAccessor2d : public cvf::Object public: virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - }; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index ef3b02d8ad..fbb01f2bf4 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -49,7 +49,7 @@ void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) +cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { double soil = 0.0; double swat = 0.0; @@ -80,7 +80,7 @@ cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h index d1e85bcade..47ff642b2e 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -19,8 +19,7 @@ #pragma once #include "RigResultAccessor2d.h" - -class RigResultAccessor; +#include "RigResultAccessor.h" //================================================================================================== /// @@ -35,8 +34,8 @@ class RigTernaryResultAccessor : public RigResultAccessor2d /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex); - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId);; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: cvf::ref m_soilAccessor; From 748e056bbc15d9aec11349b72df8b8e17a60ad46 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:42:54 +0200 Subject: [PATCH 103/346] Created setter for opacity --- .../RivTernaryScalarMapper-Test.cpp | 4 +- .../RivTernaryScalarMapper.cpp | 39 ++++++++++++------- .../RivTernaryScalarMapper.h | 14 ++++--- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index dc7f62b9a6..6f50cb5717 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -30,7 +30,7 @@ //-------------------------------------------------------------------------------------------------- TEST(TernaryScalarMapperTest, BasicFunctions) { - cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); cvf::ref texImage = new cvf::TextureImage; scalarMapper->updateTexture(texImage.p()); @@ -45,7 +45,7 @@ TEST(TernaryScalarMapperTest, BasicFunctions) //-------------------------------------------------------------------------------------------------- TEST(TernaryScalarMapperTest, TextureMapping) { - cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); // Without opacity { diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 33561806dc..0ea8fe889b 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -24,32 +24,41 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) +RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor) : m_undefScalarColor(undefScalarColor), - m_opacityLevel(opacityLevel), m_textureSize(128, 256) { + m_opacityLevel = 1.0; + setTernaryRanges(0.0, 1.0, 0.0, 1.0); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) +void RivTernaryScalarMapper::setOpacityLevel(float opacityLevel) +{ + m_opacityLevel = opacityLevel; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, bool isTransparent) const { double soilNormalized = (soil - m_rangeMinSoil) * m_soilFactor; soilNormalized = cvf::Math::clamp(soilNormalized, 0.0, 1.0); - double swatNormalized = (swat - m_rangeMinSwat) * m_swatFactor; - swatNormalized = cvf::Math::clamp(swatNormalized, 0.0, 1.0 - soilNormalized); - swatNormalized /= 2.0; + double sgasNormalized = (sgas - m_rangeMinSgas) * m_sgasFactor; + sgasNormalized = cvf::Math::clamp(sgasNormalized, 0.0, 1.0 - soilNormalized); + sgasNormalized /= 2.0; if (isTransparent) { - swatNormalized += 0.5; + sgasNormalized += 0.5; } - cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(swatNormalized)); + cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(sgasNormalized)); return texCoord; } @@ -60,12 +69,13 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, b /// * * Texture in this region is assigned the given opacity level /// * * /// D *********** E -/// C * +/// C * SGAS /// * * /// * * Texture in this region is opaque /// * * /// * * -/// A *********** B +/// A *********** B +/// SWAT SOIL //-------------------------------------------------------------------------------------------------- bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) { @@ -116,13 +126,14 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper) +void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper) { m_rangeMinSoil = soilLower; m_rangeMaxSoil = soilUpper; m_soilFactor = 1.0 / (soilUpper - soilLower); - m_rangeMinSwat = swatLower; - m_rangeMaxSwat = swatUpper; - m_swatFactor = 1.0 / (swatUpper - swatLower); + m_rangeMinSgas = sgasLower; + m_rangeMaxSgas = sgasUpper; + m_sgasFactor = 1.0 / (sgasUpper - sgasLower); } + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 5c952782a5..9ba59cefa4 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -34,11 +34,13 @@ namespace cvf class RivTernaryScalarMapper : public cvf::Object { public: - RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor); - void setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper); + void setOpacityLevel(float opacityLevel); - cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); + void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); + + cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; bool updateTexture(cvf::TextureImage* image); private: @@ -50,8 +52,8 @@ class RivTernaryScalarMapper : public cvf::Object double m_rangeMinSoil; double m_soilFactor; - double m_rangeMaxSwat; - double m_rangeMinSwat; - double m_swatFactor; + double m_rangeMaxSgas; + double m_rangeMinSgas; + double m_sgasFactor; }; From a8de19984acc977f8c293e643009e6c1028efb5f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:46:08 +0200 Subject: [PATCH 104/346] Layout cleanup --- .../RivTextureCoordsCreator.cpp | 8 ++++++-- .../RivTextureCoordsCreator.h | 17 +++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index ff97711e3d..e3bca13c4e 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -47,7 +47,7 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); CVF_ASSERT(m_resultAccessor.notNull()); - cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(gridIndex)); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); @@ -59,7 +59,11 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords, const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper) +void RivTextureCoordsCreator::createTextureCoords( + cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigResultAccessor* resultAccessor, + const RivResultToTextureMapper* texMapper) { CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h index c08d647b0a..0e1a543982 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -26,9 +26,9 @@ class RimResultSlot; class RigResultAccessor; class RivResultToTextureMapper; -namespace cvf{ -class StructGridQuadToCellFaceMapper; - +namespace cvf +{ + class StructGridQuadToCellFaceMapper; } @@ -38,7 +38,7 @@ class RivTextureCoordsCreator RivTextureCoordsCreator(RimResultSlot* cellResultSlot, size_t timeStepIndex, size_t gridIndex, - const cvf::StructGridQuadToCellFaceMapper* quadMapper); + const cvf::StructGridQuadToCellFaceMapper* quadMapper); void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) { @@ -52,11 +52,8 @@ class RivTextureCoordsCreator const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper); - cvf::cref m_quadMapper; - cvf::ref m_resultAccessor; - cvf::ref m_texMapper; + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; }; - - - From 6b9412e2ba97bf94cb5c06a3360a1b54907e8779 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 08:10:07 +0200 Subject: [PATCH 105/346] Added ternary texture and scalar mappers --- .../ModelVisualization/CMakeLists_files.cmake | 3 + .../RivTernaryResultToTextureMapper.h | 51 +++++++++ .../RivTernaryTextureCoordsCreator.cpp | 106 ++++++++++++++++++ .../RivTernaryTextureCoordsCreator.h | 59 ++++++++++ .../RimTernaryLegendConfig.cpp | 15 ++- .../ProjectDataModel/RimTernaryLegendConfig.h | 5 +- 6 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h create mode 100644 ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index ee8779f9c2..4197e8e99f 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -23,8 +23,10 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h ${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h +${CEE_CURRENT_LIST_DIR}RivTernaryResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h +${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -47,6 +49,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h new file mode 100644 index 0000000000..a93e8e95c2 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigPipeInCellEvaluator.h" + +#include "RivTernaryScalarMapper.h" + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" +#include "cvfVector2.h" + +#include + +class RivTernaryResultToTextureMapper : public cvf::Object +{ +public: + RivTernaryResultToTextureMapper(const RivTernaryScalarMapper* scalarMapper, const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + cvf::Vec2f getTexCoord(double soil, double sgas, size_t cellIndex) const + { + bool isTransparent = m_pipeInCellEvaluator->isWellPipeInCell(cellIndex); + + return m_scalarMapper->mapToTextureCoord(soil, sgas, isTransparent); + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp new file mode 100644 index 0000000000..9a8826ec03 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryTextureCoordsCreator.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigPipeInCellEvaluator.h" +#include "RigResultAccessorFactory.h" +#include "RigTernaryResultAccessor2d.h" + +#include "RimCase.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" + +#include "RivTernaryResultToTextureMapper.h" +#include "RivTernaryScalarMapper.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryTextureCoordsCreator::RivTernaryTextureCoordsCreator( + RimResultSlot* cellResultSlot, + RimTernaryLegendConfig* ternaryLegendConfig, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + m_quadMapper = quadMapper; + CVF_ASSERT(quadMapper && eclipseCase ); + + size_t resTimeStepIdx = timeStepIndex; + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + cvf::ref soil = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SOIL"); + cvf::ref sgas = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SGAS"); + cvf::ref swat = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SWAT"); + + m_resultAccessor = new RigTernaryResultAccessor(); + m_resultAccessor->setTernaryResultAccessors(soil.p(), sgas.p(), swat.p()); + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(gridIndex)); + + const RivTernaryScalarMapper* mapper = ternaryLegendConfig->scalarMapper(); + + m_texMapper = new RivTernaryResultToTextureMapper(mapper, pipeInCellEval.p()); + CVF_ASSERT(m_texMapper.notNull()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryTextureCoordsCreator::createTextureCoords( + cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigTernaryResultAccessor* resultAccessor, + const RivTernaryResultToTextureMapper* texMapper) +{ + CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); + + size_t numVertices = quadMapper->quadCount()*4; + quadTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = quadTextureCoords->ptr(); + + cvf::Vec2d resultValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, resultValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + resultValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(resultValue.x(), resultValue.y(), cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h new file mode 100644 index 0000000000..fcf41f8eb7 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RimResultSlot; +class RigTernaryResultAccessor; +class RivTernaryResultToTextureMapper; +class RimTernaryLegendConfig; + +namespace cvf +{ + class StructGridQuadToCellFaceMapper; +} + + +class RivTernaryTextureCoordsCreator +{ +public: + RivTernaryTextureCoordsCreator( RimResultSlot* cellResultSlot, + RimTernaryLegendConfig* ternaryLegendConfig, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) + { + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); + } + +private: + static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigTernaryResultAccessor* resultAccessor, + const RivTernaryResultToTextureMapper* texMapper); + + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; +}; diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index dab84420e6..5ee3e364a3 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -25,10 +25,12 @@ #include "RimReservoirView.h" #include "RivTernarySaturationOverlayItem.h" +#include "RivTernaryScalarMapper.h" -#include #include "cvfqtUtils.h" +#include + CAF_PDM_SOURCE_INIT(RimTernaryLegendConfig, "RimTernaryLegendConfig"); @@ -93,6 +95,8 @@ RimTernaryLegendConfig::RimTernaryLegendConfig() m_localAutoMin.resize(3, 0.0); m_localAutoMax.resize(3, 1.0); + m_scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); + recreateLegend(); updateLegend(); } @@ -163,6 +167,7 @@ void RimTernaryLegendConfig::updateLegend() double swatUpper = 1.0; ternaryRanges(soilLower, soilUpper, sgasLower, sgasUpper, swatLower, swatUpper); + m_scalarMapper->setTernaryRanges(soilLower, soilUpper, sgasLower, sgasUpper); cvf::String soilRange; cvf::String sgasRange; @@ -438,3 +443,11 @@ void RimTernaryLegendConfig::updateLabelText() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapper* RimTernaryLegendConfig::scalarMapper() +{ + return m_scalarMapper.p(); +} + diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h index 79c94d5d11..7567867752 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -27,6 +27,7 @@ class RimReservoirView; class RivTernarySaturationOverlayItem; +class RivTernaryScalarMapper; namespace cvf { @@ -70,7 +71,8 @@ class RimTernaryLegendConfig : public caf::PdmObject void recreateLegend(); - RivTernarySaturationOverlayItem* legend(); + RivTernarySaturationOverlayItem* legend(); + RivTernaryScalarMapper* scalarMapper(); protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); @@ -106,4 +108,5 @@ class RimTernaryLegendConfig : public caf::PdmObject caf::PdmPointer m_reservoirView; cvf::ref m_legend; + cvf::ref m_scalarMapper; }; From 3fef95d794c6e85e9e3d6c687d5b5dea756ee130 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 10:49:42 +0200 Subject: [PATCH 106/346] Added ternary scalar mapper effect generator --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivTernaryScalarMapper.cpp | 2 +- .../RivTernaryScalarMapper.h | 2 +- .../RivTernaryScalarMapperEffectGenerator.cpp | 244 ++++++++++++++++++ .../RivTernaryScalarMapperEffectGenerator.h | 68 +++++ 5 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 4197e8e99f..fc4c22bbe0 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -27,6 +27,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -50,6 +51,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 0ea8fe889b..2c5eb14efc 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -77,7 +77,7 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, b /// A *********** B /// SWAT SOIL //-------------------------------------------------------------------------------------------------- -bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const { CVF_ASSERT(image); image->allocate(m_textureSize.x(), m_textureSize.y()); diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 9ba59cefa4..5e0c827635 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -41,7 +41,7 @@ class RivTernaryScalarMapper : public cvf::Object void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; - bool updateTexture(cvf::TextureImage* image); + bool updateTexture(cvf::TextureImage* image) const; private: cvf::Color3f m_undefScalarColor; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp new file mode 100644 index 0000000000..092929f43b --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp @@ -0,0 +1,244 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryScalarMapperEffectGenerator.h" + +#include "RivTernaryScalarMapper.h" + +#include "cvfRenderStateBlending.h" +#include "cvfRenderStateCullFace.h" +#include "cvfRenderStateDepth.h" +#include "cvfRenderStateTextureBindings.h" +#include "cvfRenderState_FF.h" +#include "cvfSampler.h" +#include "cvfShaderProgram.h" +#include "cvfShaderProgramGenerator.h" +#include "cvfShaderSourceProvider.h" +#include "cvfTexture.h" +#include "cvfTexture2D_FF.h" + + + +//================================================================================================== +// +// RivTernaryScalarMapperEffectGenerator +// +//================================================================================================== + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapperEffectGenerator::RivTernaryScalarMapperEffectGenerator(const RivTernaryScalarMapper* scalarMapper, caf::PolygonOffset polygonOffset) + : m_undefinedColor(cvf::Color3::GRAY) +{ + m_scalarMapper = scalarMapper; + m_polygonOffset = polygonOffset; + m_opacityLevel = 1.0f; + m_faceCulling = caf::FC_NONE; + m_enableDepthWrite = true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) const +{ + cvf::ref eff = effect; + + cvf::ShaderProgramGenerator gen("ScalarMapperMeshEffectGenerator", cvf::ShaderSourceProvider::instance()); + gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); + gen.addFragmentCode(cvf::ShaderSourceRepository::src_Texture); + gen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); + gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); + + cvf::ref prog = gen.generate(); + eff->setShaderProgram(prog.p()); + + // Result mapping texture + + m_textureImage = new cvf::TextureImage(); + m_scalarMapper->updateTexture(m_textureImage.p()); + + cvf::ref texture = new cvf::Texture(m_textureImage.p()); + cvf::ref sampler = new cvf::Sampler; + sampler->setWrapMode(cvf::Sampler::CLAMP_TO_EDGE); + sampler->setMinFilter(cvf::Sampler::NEAREST); + sampler->setMagFilter(cvf::Sampler::NEAREST); + + cvf::ref texBind = new cvf::RenderStateTextureBindings; + texBind->addBinding(texture.p(), sampler.p(), "u_texture2D"); + eff->setRenderState(texBind.p()); + + // Hardware independent: + + updateCommonEffect(eff.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateForFixedFunctionRendering(cvf::Effect* effect) const +{ + cvf::ref eff = effect; + + cvf::ref mat = new cvf::RenderStateMaterial_FF(cvf::Color3::WHITE); + eff->setRenderState(mat.p()); + + cvf::ref lighting = new cvf::RenderStateLighting_FF; + lighting->enableTwoSided(true); + eff->setRenderState(lighting.p()); + + // Result mapping texture + + m_textureImage = new cvf::TextureImage; + m_scalarMapper->updateTexture(m_textureImage.p()); + + cvf::ref texture = new cvf::Texture2D_FF(m_textureImage.p()); + texture->setWrapMode(cvf::Texture2D_FF::CLAMP); + texture->setMinFilter(cvf::Texture2D_FF::NEAREST); + texture->setMagFilter(cvf::Texture2D_FF::NEAREST); + cvf::ref texMapping = new cvf::RenderStateTextureMapping_FF(texture.p()); + eff->setRenderState(texMapping.p()); + + // Hardware independent: + + updateCommonEffect(eff.p()); + +} + +//-------------------------------------------------------------------------------------------------- +/// It also modifies the texture, and adds two more pixel lines +/// one with a transparent version of the legend color, and one with color for undefined values +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateCommonEffect(cvf::Effect* effect) const +{ + CVF_ASSERT(effect); + + if (m_polygonOffset != caf::PO_NONE) + { + cvf::ref polyOffset = EffectGenerator::createAndConfigurePolygonOffsetRenderState(m_polygonOffset); + effect->setRenderState(polyOffset.p()); + } + + // Simple transparency + if (m_opacityLevel < 1.0f) + { + cvf::ref blender = new cvf::RenderStateBlending; + blender->configureTransparencyBlending(); + effect->setRenderState(blender.p()); + } + + // Backface culling + if (m_faceCulling != caf::FC_NONE) + { + cvf::ref faceCulling = new cvf::RenderStateCullFace; + if (m_faceCulling == caf::FC_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::BACK); + } + else if (m_faceCulling == caf::FC_FRONT) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT); + } + else if (m_faceCulling == caf::FC_FRONT_AND_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT_AND_BACK); + } + + effect->setRenderState(faceCulling.p()); + } + + if (!m_enableDepthWrite) + { + cvf::ref depth = new cvf::RenderStateDepth; + depth->enableDepthWrite(false); + effect->setRenderState(depth.p()); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapperEffectGenerator::isEqual(const EffectGenerator* other) const +{ + const RivTernaryScalarMapperEffectGenerator* otherTextureResultEffect = dynamic_cast(other); + + if (otherTextureResultEffect) + { + if (m_scalarMapper.p() == otherTextureResultEffect->m_scalarMapper + && m_polygonOffset == otherTextureResultEffect->m_polygonOffset + && m_opacityLevel == otherTextureResultEffect->m_opacityLevel + && m_undefinedColor == otherTextureResultEffect->m_undefinedColor + && m_faceCulling == otherTextureResultEffect->m_faceCulling + && m_enableDepthWrite == otherTextureResultEffect->m_enableDepthWrite) + { + cvf::ref texImg2 = new cvf::TextureImage; + otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p()); + + return RivTernaryScalarMapperEffectGenerator::isImagesEqual(m_textureImage.p(), texImg2.p()); + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::EffectGenerator* RivTernaryScalarMapperEffectGenerator::copy() const +{ + RivTernaryScalarMapperEffectGenerator* scEffGen = new RivTernaryScalarMapperEffectGenerator(m_scalarMapper.p(), m_polygonOffset); + scEffGen->m_textureImage = m_textureImage; + scEffGen->m_opacityLevel = m_opacityLevel; + scEffGen->m_undefinedColor = m_undefinedColor; + scEffGen->m_faceCulling = m_faceCulling; + scEffGen->m_enableDepthWrite = m_enableDepthWrite; + + return scEffGen; +} + + +//-------------------------------------------------------------------------------------------------- +/// Tests whether two texture images are equal. It might in some rare cases not detect the difference +/// but to make the comparison fast only some sampling points are used. If both pointers are NULL, +/// they are considered equal. +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapperEffectGenerator::isImagesEqual(const cvf::TextureImage* texImg1, const cvf::TextureImage* texImg2) +{ + if (texImg1 == NULL && texImg2 == NULL) return true; + + if (texImg1 != NULL && texImg2 != NULL + && texImg1->height() == texImg2->height() + && texImg1->width() == texImg2->width() + && texImg1->width() > 0 && texImg1->height() > 0 + && texImg1->pixel(0, 0) == texImg2->pixel(0, 0) + && texImg1->pixel(texImg1->width() - 1, texImg1->height() - 1) == texImg2->pixel(texImg1->width() - 1, texImg1->height() - 1) + && texImg1->pixel(texImg1->width() / 2, texImg1->height() / 2) == texImg2->pixel(texImg1->width() / 2, texImg1->height() / 2) + && texImg1->pixel(texImg1->width() / 4, texImg1->height() / 4) == texImg2->pixel(texImg1->width() / 4, texImg1->height() / 4) + && texImg1->pixel(texImg1->width() / 2 + texImg1->width() / 4, texImg1->height() / 2 + texImg1->height() / 4) == texImg2->pixel(texImg1->width() / 2 + texImg1->width() / 4, texImg1->height() / 2 + texImg1->height() / 4) + ) + { + return true; + } + + return false; +} + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h new file mode 100644 index 0000000000..3d953ef8df --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafEffectGenerator.h" + +class RivTernaryScalarMapper; + +namespace cvf +{ + class TextureImage; +} + +//================================================================================================== +// +// ScalarMapperEffectGenerator +// +//================================================================================================== +class RivTernaryScalarMapperEffectGenerator : public caf::EffectGenerator +{ +public: + RivTernaryScalarMapperEffectGenerator(const RivTernaryScalarMapper* scalarMapper, caf::PolygonOffset polygonOffset); + + void setOpacityLevel(float opacity) { m_opacityLevel = cvf::Math::clamp(opacity, 0.0f, 1.0f); } + void setUndefinedColor(cvf::Color3f color) { m_undefinedColor = color; } + void setFaceCulling(caf::FaceCulling faceCulling) { m_faceCulling = faceCulling; } + void enableDepthWrite(bool enableWrite) { m_enableDepthWrite = enableWrite; } + + +public: + static bool isImagesEqual(const cvf::TextureImage* texImg1, const cvf::TextureImage* texImg2); + +protected: + virtual bool isEqual(const caf::EffectGenerator* other) const; + virtual caf::EffectGenerator* copy() const; + + virtual void updateForShaderBasedRendering(cvf::Effect* effect) const; + virtual void updateForFixedFunctionRendering(cvf::Effect* effect) const; + +private: + void updateCommonEffect(cvf::Effect* effect) const; + +private: + cvf::cref m_scalarMapper; + mutable cvf::ref m_textureImage; + caf::PolygonOffset m_polygonOffset; + float m_opacityLevel; + cvf::Color3f m_undefinedColor; + caf::FaceCulling m_faceCulling; + bool m_enableDepthWrite; +}; + From 45cf2583866c524951883fb592043448bdcf4081 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 10:50:31 +0200 Subject: [PATCH 107/346] Use texture based ternary visualization --- .../ModelVisualization/RivGridPartMgr.cpp | 63 +++++++++++++------ .../RivTernaryTextureCoordsCreator.cpp | 8 +++ .../RivTernaryTextureCoordsCreator.h | 14 +++-- .../RigTernaryResultAccessor2d.cpp | 14 ++--- .../RigTernaryResultAccessor2d.h | 2 +- 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 99fa9bf715..ee88d87002 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -54,6 +54,8 @@ #include "RigResultAccessorFactory.h" #include "RivResultToTextureMapper.h" #include "RivTextureCoordsCreator.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTernaryScalarMapperEffectGenerator.h" //-------------------------------------------------------------------------------------------------- @@ -229,9 +231,28 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { if (cellResultSlot->isTernarySaturationSelected()) { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); + + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); + + //void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces.p()->drawable()); + if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p()); + } + + // void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) + { + caf::PolygonOffset polygonOffset = caf::PO_1; + RivTernaryScalarMapperEffectGenerator scalarEffgen(cellResultSlot->ternaryLegendConfig()->scalarMapper(), polygonOffset); + scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + m_surfaceFaces->setEffect(scalarEffect.p()); + } } else { @@ -241,26 +262,28 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.quadToCellFaceMapper()); texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - } + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); + } - if (surfaceFacesColorArray.notNull()) // Ternary result - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } +// if (surfaceFacesColorArray.notNull()) // Ternary result +// { +// cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); +// if (dg) +// { +// dg->setColorArray(surfaceFacesColorArray.p()); +// } +// +// cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); +// m_surfaceFaces->setEffect(perVertexColorEffect.p()); +// +// m_surfaceFaces->setPriority(100); +// } +// else +// { +// applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); +// } } } diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp index 9a8826ec03..10b8bc3aad 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp @@ -70,6 +70,14 @@ RivTernaryTextureCoordsCreator::RivTernaryTextureCoordsCreator( CVF_ASSERT(m_texMapper.notNull()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords) +{ + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h index fcf41f8eb7..751cd51b73 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h @@ -18,13 +18,14 @@ #pragma once +#include "RigTernaryResultAccessor2d.h" +#include "RivTernaryResultToTextureMapper.h" + #include "cvfBase.h" #include "cvfObject.h" #include "cvfArray.h" class RimResultSlot; -class RigTernaryResultAccessor; -class RivTernaryResultToTextureMapper; class RimTernaryLegendConfig; namespace cvf @@ -33,6 +34,9 @@ namespace cvf } +//================================================================================================== +/// +//================================================================================================== class RivTernaryTextureCoordsCreator { public: @@ -42,10 +46,7 @@ class RivTernaryTextureCoordsCreator size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper); - void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) - { - createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); - } + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords); private: static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, @@ -53,6 +54,7 @@ class RivTernaryTextureCoordsCreator const RigTernaryResultAccessor* resultAccessor, const RivTernaryResultToTextureMapper* texMapper); +private: cvf::cref m_quadMapper; cvf::ref m_resultAccessor; cvf::ref m_texMapper; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index fbb01f2bf4..d58fe8486a 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -52,29 +52,29 @@ void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { double soil = 0.0; - double swat = 0.0; + double sgas = 0.0; if (m_soilAccessor.notNull()) { soil = m_soilAccessor->cellScalar(gridLocalCellIndex); - if (m_swatAccessor.notNull()) + if (m_sgasAccessor.notNull()) { - swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); } else { - swat = 1.0 - soil - m_sgasAccessor->cellScalar(gridLocalCellIndex); + sgas = 1.0 - soil - m_swatAccessor->cellScalar(gridLocalCellIndex); } } else { - swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); - soil = 1.0 - swat - m_sgasAccessor->cellScalar(gridLocalCellIndex); + soil = 1.0 - sgas - m_swatAccessor->cellScalar(gridLocalCellIndex); } - return cvf::Vec2d(soil, swat); + return cvf::Vec2d(soil, sgas); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h index 47ff642b2e..14f71a72ae 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -32,7 +32,7 @@ class RigTernaryResultAccessor : public RigResultAccessor2d /// Requires two of the arguments to be present void setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat); - /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// Returns [SOIL, SGAS] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const; virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; From a71c6009e282e7fc3f3ea8394c8d44775eea5211 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 11:02:16 +0200 Subject: [PATCH 108/346] Fixed viz bug introduced by new texturing method SHA: a9794815c7bd58b89a94adecf7bd80dddaaad18b --- .../ModelVisualization/RivFaultPartMgr.cpp | 10 ++++++++ .../ModelVisualization/RivGridPartMgr.cpp | 4 ++++ .../RivTextureCoordsCreator.cpp | 23 ++++++++++++++++++- .../RivTextureCoordsCreator.h | 8 +++---- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index ba9cc67315..7421b51684 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -139,6 +139,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_grid->gridIndex(), m_nativeFaultGenerator->cellFromQuadMapper()); + if (!texturer.isValid()) + { + return; + } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); } @@ -182,6 +187,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_grid->gridIndex(), m_oppositeFaultGenerator->cellFromQuadMapper()); + if (!texturer.isValid()) + { + return; + } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ee88d87002..cb5283ab27 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -260,6 +260,10 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); + if (!texturer.isValid()) + { + return; + } texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index e3bca13c4e..2f2ec89591 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -45,7 +45,6 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - CVF_ASSERT(m_resultAccessor.notNull()); cvf::ref pipeInCellEval = new RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(gridIndex)); @@ -56,6 +55,27 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, CVF_ASSERT(m_texMapper.notNull()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivTextureCoordsCreator::isValid() +{ + if (m_quadMapper.isNull() || m_resultAccessor.isNull() || m_texMapper.isNull()) + { + return false; + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords) +{ + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -90,3 +110,4 @@ void RivTextureCoordsCreator::createTextureCoords( } } } + diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h index 0e1a543982..f73cbf8315 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -40,10 +40,9 @@ class RivTextureCoordsCreator size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper); - void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) - { - createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); - } + bool isValid(); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords); private: @@ -51,7 +50,6 @@ class RivTextureCoordsCreator const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper); - cvf::cref m_quadMapper; cvf::ref m_resultAccessor; cvf::ref m_texMapper; From 877dc0dc580fc47121b238cf3b9777f9cbfe2513 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:17:09 +0200 Subject: [PATCH 109/346] Fixed transparency for ternary well cells --- .../RivTernaryScalarMapper-Test.cpp | 2 +- .../ModelVisualization/RivTernaryScalarMapper.cpp | 14 ++------------ .../ModelVisualization/RivTernaryScalarMapper.h | 5 +---- .../RivTernaryScalarMapperEffectGenerator.cpp | 6 +++--- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index 6f50cb5717..f9ac412145 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -33,7 +33,7 @@ TEST(TernaryScalarMapperTest, BasicFunctions) cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); cvf::ref texImage = new cvf::TextureImage; - scalarMapper->updateTexture(texImage.p()); + scalarMapper->updateTexture(texImage.p(), 1.0); QImage img = cvfqt::Utils::toQImage(*(texImage.p())); diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 2c5eb14efc..a81a16d2f2 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -28,19 +28,9 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo : m_undefScalarColor(undefScalarColor), m_textureSize(128, 256) { - m_opacityLevel = 1.0; - setTernaryRanges(0.0, 1.0, 0.0, 1.0); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivTernaryScalarMapper::setOpacityLevel(float opacityLevel) -{ - m_opacityLevel = opacityLevel; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -77,7 +67,7 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, b /// A *********** B /// SWAT SOIL //-------------------------------------------------------------------------------------------------- -bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image, float opacityLevel) const { CVF_ASSERT(image); image->allocate(m_textureSize.x(), m_textureSize.y()); @@ -112,7 +102,7 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const image->setPixel(xPos, yPos, clr); // Set opacity - const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * m_opacityLevel)); + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * opacityLevel)); image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); soil_green += xStride; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 5e0c827635..566f499e01 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -36,16 +36,13 @@ class RivTernaryScalarMapper : public cvf::Object public: RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor); - void setOpacityLevel(float opacityLevel); - void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; - bool updateTexture(cvf::TextureImage* image) const; + bool updateTexture(cvf::TextureImage* image, float opacityLevel) const; private: cvf::Color3f m_undefScalarColor; - float m_opacityLevel; cvf::Vec2ui m_textureSize; double m_rangeMaxSoil; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp index 092929f43b..76041518bb 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp @@ -74,7 +74,7 @@ void RivTernaryScalarMapperEffectGenerator::updateForShaderBasedRendering(cvf::E // Result mapping texture m_textureImage = new cvf::TextureImage(); - m_scalarMapper->updateTexture(m_textureImage.p()); + m_scalarMapper->updateTexture(m_textureImage.p(), m_opacityLevel); cvf::ref texture = new cvf::Texture(m_textureImage.p()); cvf::ref sampler = new cvf::Sampler; @@ -108,7 +108,7 @@ void RivTernaryScalarMapperEffectGenerator::updateForFixedFunctionRendering(cvf: // Result mapping texture m_textureImage = new cvf::TextureImage; - m_scalarMapper->updateTexture(m_textureImage.p()); + m_scalarMapper->updateTexture(m_textureImage.p(), m_opacityLevel); cvf::ref texture = new cvf::Texture2D_FF(m_textureImage.p()); texture->setWrapMode(cvf::Texture2D_FF::CLAMP); @@ -191,7 +191,7 @@ bool RivTernaryScalarMapperEffectGenerator::isEqual(const EffectGenerator* other && m_enableDepthWrite == otherTextureResultEffect->m_enableDepthWrite) { cvf::ref texImg2 = new cvf::TextureImage; - otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p()); + otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p(), m_opacityLevel); return RivTernaryScalarMapperEffectGenerator::isImagesEqual(m_textureImage.p(), texImg2.p()); } From 8ec3c99727c6cd1fe0480a8aa10813867d0aad1c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:55:53 +0200 Subject: [PATCH 110/346] Added scalarMapperUtils for code sharing between grids/faults --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivScalarMapperUtils.cpp | 86 +++++++++++++++++++ .../ModelVisualization/RivScalarMapperUtils.h | 45 ++++++++++ 3 files changed, 133 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp create mode 100644 ApplicationCode/ModelVisualization/RivScalarMapperUtils.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index fc4c22bbe0..5079ead6ff 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -28,6 +28,7 @@ ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h +${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -52,6 +53,7 @@ ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp +${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp new file mode 100644 index 0000000000..e9620f6536 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivScalarMapperUtils.h" + +#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RivTernaryScalarMapper.h" + +#include "cafEffectGenerator.h" + +#include "cvfDrawableGeo.h" +#include "cvfPart.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivScalarMapperUtils::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(part && textureCoords && mapper); + + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(textureCoords); + + cvf::ref scalarEffect = RivScalarMapperUtils::createScalarMapperEffect(mapper, opacityLevel); + part->setEffect(scalarEffect.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(part && textureCoords && mapper); + + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(textureCoords); + + cvf::ref scalarEffect = RivScalarMapperUtils::createTernaryScalarMapperEffect(mapper, opacityLevel); + part->setEffect(scalarEffect.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(mapper); + + caf::PolygonOffset polygonOffset = caf::PO_1; + caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + return scalarEffect; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(mapper); + + caf::PolygonOffset polygonOffset = caf::PO_1; + RivTernaryScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + return scalarEffect; +} diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h new file mode 100644 index 0000000000..de92c033b0 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfArray.h" + +namespace cvf +{ + class ScalarMapper; + class Part; + class Effect; +} + +class RivTernaryScalarMapper; + +//================================================================================================== +/// +//================================================================================================== +class RivScalarMapperUtils +{ +public: + static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel); + static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel); + +private: + static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel); + static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel); +}; + From 4a488e0683e4988649c2400b07221bd17b8ac8aa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:59:12 +0200 Subject: [PATCH 111/346] Use RivScalarMapperUtils --- .../ModelVisualization/RivGridPartMgr.cpp | 138 ++++++------------ .../ModelVisualization/RivGridPartMgr.h | 2 - 2 files changed, 42 insertions(+), 98 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index cb5283ab27..b4a3068d13 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -18,11 +18,34 @@ #include "RivGridPartMgr.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultAccessorFactory.h" + +#include "RimCase.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" + +#include "RivCellEdgeEffectGenerator.h" +#include "RivResultToTextureMapper.h" +#include "RivScalarMapperUtils.h" +#include "RivSourceInfo.h" +#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTextureCoordsCreator.h" #include "cafEffectGenerator.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" #include "cafProgressInfo.h" + #include "cvfDrawableGeo.h" #include "cvfMath.h" #include "cvfModelBasicList.h" @@ -35,27 +58,8 @@ #include "cvfShaderSourceProvider.h" #include "cvfShaderSourceRepository.h" #include "cvfStructGrid.h" -#include "cvfUniform.h" - -#include "RiaApplication.h" -#include "RiaPreferences.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RimCase.h" -#include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsStorage.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimTernaryLegendConfig.h" -#include "RimWellCollection.h" -#include "RivCellEdgeEffectGenerator.h" -#include "RivSourceInfo.h" #include "cvfStructGridGeometryGenerator.h" -#include "RigResultAccessorFactory.h" -#include "RivResultToTextureMapper.h" -#include "RivTextureCoordsCreator.h" -#include "RivTernaryTextureCoordsCreator.h" -#include "RivTernaryScalarMapperEffectGenerator.h" +#include "cvfUniform.h" //-------------------------------------------------------------------------------------------------- @@ -221,16 +225,15 @@ 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 surfaceFacesColorArray; // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), @@ -238,83 +241,26 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - //void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces.p()->drawable()); - if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p()); - } - - // void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) - { - caf::PolygonOffset polygonOffset = caf::PO_1; - RivTernaryScalarMapperEffectGenerator scalarEffgen(cellResultSlot->ternaryLegendConfig()->scalarMapper(), polygonOffset); - scalarEffgen.setOpacityLevel(m_opacityLevel); - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - - m_surfaceFaces->setEffect(scalarEffect.p()); - } - } - else - { - RivTextureCoordsCreator texturer(cellResultSlot, - timeStepIndex, - m_grid->gridIndex(), - m_surfaceGenerator.quadToCellFaceMapper()); + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); if (!texturer.isValid()) { return; } - texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); - } - - -// if (surfaceFacesColorArray.notNull()) // Ternary result -// { -// cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); -// if (dg) -// { -// dg->setColorArray(surfaceFacesColorArray.p()); -// } -// -// cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); -// m_surfaceFaces->setEffect(perVertexColorEffect.p()); -// -// m_surfaceFaces->setPriority(100); -// } -// else -// { -// applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); -// } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) -{ - caf::PolygonOffset polygonOffset = caf::PO_1; - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); - scalarEffgen.setOpacityLevel(m_opacityLevel); - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - return scalarEffect; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) -{ - cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); - if (dg) dg->setTextureCoordArray(textureCoords); + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - cvf::ref scalarEffect = createScalarMapperEffect(mapper); - part->setEffect(scalarEffect.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 4985a360bf..54bde9110c 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -84,8 +84,6 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); - void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); - cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, cvf::StructGridGeometryGenerator* surfaceGenerator, size_t timeStepIndex, From fc6b17e3ffee44f026462b00b69e66e1634c0799 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:28:32 +0200 Subject: [PATCH 112/346] Use shared grid/fault visualization code --- .../ModelVisualization/RivFaultPartMgr.cpp | 160 ++++++------------ .../ModelVisualization/RivFaultPartMgr.h | 1 - 2 files changed, 50 insertions(+), 111 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 7421b51684..eabf868769 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -18,42 +18,32 @@ #include "RivFaultPartMgr.h" -#include "cvfPart.h" -#include "cafEffectGenerator.h" -#include "cvfStructGrid.h" -#include "cvfDrawableGeo.h" -#include "cvfModelBasicList.h" -#include "RivCellEdgeEffectGenerator.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" #include "RigResultAccessor.h" #include "RimCase.h" -#include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsStorage.h" -#include "cvfDrawableText.h" -#include "cvfqtUtils.h" -#include "cvfPrimitiveSetIndexedUInt.h" -#include "cvfPrimitiveSetDirect.h" -#include "RivGridPartMgr.h" -#include "cvfRenderStateDepth.h" -#include "RivSourceInfo.h" #include "RimFaultCollection.h" -#include "RivTextureCoordsCreator.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" #include "RivResultToTextureMapper.h" +#include "RivScalarMapperUtils.h" +#include "RivSourceInfo.h" +#include "RivTernaryScalarMapper.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTextureCoordsCreator.h" +#include "cvfDrawableGeo.h" +#include "cvfDrawableText.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfPrimitiveSetDirect.h" +#include "cvfqtUtils.h" //-------------------------------------------------------------------------------------------------- @@ -109,9 +99,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* updateNNCColors(cellResultSlot); - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); // If the result is static, only read that. size_t resTimeStepIdx = timeStepIndex; @@ -124,14 +112,18 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* // Faults if (m_nativeFaultFaces.notNull()) { - cvf::ref surfaceFacesColorArray; if (cellResultSlot->isTernarySaturationSelected()) { - surfaceFacesColorArray = new cvf::Color3ubArray; + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_nativeFaultGenerator->cellFromQuadMapper()); - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), - surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); - } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); + + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } else { RivTextureCoordsCreator texturer(cellResultSlot, @@ -145,80 +137,44 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); - } - - cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); - if (surfaceFacesColorArray.notNull()) - { - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_nativeFaultFaces->setEffect(perVertexColorEffect.p()); - - m_nativeFaultFaces->setPriority(100); - } - else - { - if (dg) dg->setTextureCoordArray(m_nativeFaultFacesTextureCoords.p()); - - cvf::ref scalarEffect = cellResultEffect(mapper, caf::PO_1); - m_nativeFaultFaces->setEffect(scalarEffect.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); } } - if (m_oppositeFaultFaces.notNull()) { - cvf::ref surfaceFacesColorArray; - - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); - } - else - { - RivTextureCoordsCreator texturer(cellResultSlot, - timeStepIndex, - m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + if (cellResultSlot->isTernarySaturationSelected()) + { + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); + + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); + + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); if (!texturer.isValid()) { return; } - texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); - } - - cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); - if (surfaceFacesColorArray.notNull()) - { - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_oppositeFaultFaces->setEffect(perVertexColorEffect.p()); - - m_oppositeFaultFaces->setPriority(100); - } - else - { - if (dg) dg->setTextureCoordArray(m_oppositeFaultFacesTextureCoords.p()); - - // Use a different offset than native fault faces to avoid z-fighting - cvf::ref scalarEffect = cellResultEffect(mapper, caf::PO_2); - - m_oppositeFaultFaces->setEffect(scalarEffect.p()); - } - } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } + } } //-------------------------------------------------------------------------------------------------- @@ -619,22 +575,6 @@ void RivFaultPartMgr::appendNNCFacesToModel(cvf::ModelBasicList* model) if (m_NNCFaces.notNull()) model->addPart(m_NNCFaces.p()); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivFaultPartMgr::cellResultEffect(const cvf::ScalarMapper* mapper, caf::PolygonOffset polygonOffset) const -{ - CVF_ASSERT(mapper); - - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); - scalarEffgen.setFaceCulling(faceCullingMode()); - scalarEffgen.setOpacityLevel(m_opacityLevel); - - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - - return scalarEffect; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h index d4a01e8736..44f2a66538 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h @@ -69,7 +69,6 @@ class RivFaultPartMgr : public cvf::Object void updateNNCColors(RimResultSlot* cellResultSlot); - cvf::ref cellResultEffect(const cvf::ScalarMapper* mapper, caf::PolygonOffset polygonOffset) const; caf::FaceCulling faceCullingMode() const; void createLabelWithAnchorLine(const cvf::Part* part); From 5f3b2e00ec7942041edee8d908ec3d5136486017 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:38:36 +0200 Subject: [PATCH 113/346] Rename --- .../ModelVisualization/RivFaultGeometryGenerator.h | 4 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index f0e8fd1cc2..f6ec717715 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -53,8 +53,8 @@ class RivFaultGeometryGenerator : public cvf::Object // Mapping between cells and geometry - const cvf::StructGridQuadToCellFaceMapper * cellFromQuadMapper() { return m_quadMapper.p(); } - const cvf::StuctGridTriangleToCellFaceMapper * cellFromTriangleMapper() { return m_triangleMapper.p(); } + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper() { return m_quadMapper.p(); } + const cvf::StuctGridTriangleToCellFaceMapper* triangleToCellFaceMapper() { return m_triangleMapper.p(); } // Generated geometry cvf::ref generateSurface(); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index eabf868769..dc036eb046 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -117,7 +117,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), - m_nativeFaultGenerator->cellFromQuadMapper()); + m_nativeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); @@ -129,7 +129,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), - m_nativeFaultGenerator->cellFromQuadMapper()); + m_nativeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { @@ -150,7 +150,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + m_oppositeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); @@ -162,7 +162,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + m_oppositeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { @@ -215,7 +215,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->cellFromTriangleMapper(); + si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->triangleToCellFaceMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -268,7 +268,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->cellFromTriangleMapper(); + si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->triangleToCellFaceMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); From 186867a8313e05c34370d3c32796d88139375445 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:51:27 +0200 Subject: [PATCH 114/346] Removed unused code --- .../ModelVisualization/RivGridPartMgr.cpp | 101 ------------------ .../ModelVisualization/RivGridPartMgr.h | 18 ---- 2 files changed, 119 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index b4a3068d13..f06db186b1 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -383,104 +383,3 @@ class ScalarDataAccessZeroForAllCells : public cvf::StructGridScalarDataAccess }; -//-------------------------------------------------------------------------------------------------- -/// 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 cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) -{ - 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()); - - double soilMin = 0.0; - double soilMax = 1.0; - double sgasMin = 0.0; - double sgasMax = 1.0; - double swatMin = 0.0; - double swatMax = 1.0; - - cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - - cvf::ref dataAccessObjectSoil = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); - if (dataAccessObjectSoil.isNull()) - { - dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; - } - - cvf::ref dataAccessObjectSgas = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); - if (dataAccessObjectSgas.isNull()) - { - dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; - } - - cvf::ref dataAccessObjectSwat = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); - if (dataAccessObjectSwat.isNull()) - { - dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; - } - - double soilRange = soilMax - soilMin; - double soilFactor = 255.0 / soilRange; - - double sgasRange = sgasMax - sgasMin; - double sgasFactor = 255.0 / sgasRange; - - double swatRange = swatMax - swatMin; - double swatFactor = 255.0 / swatRange; - - size_t numVertices = quadToCellFaceMapper->quadCount()*4; - - colorArray->resize(numVertices); - - cvf::Color3ub ternaryColorByte; - double v, vNormalized; - -#pragma omp parallel for private(ternaryColorByte, v, vNormalized) - for (int quadIdx = 0; quadIdx < static_cast(quadToCellFaceMapper->quadCount()); quadIdx++) - { - size_t gridCellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - - { - v = dataAccessObjectSgas->cellScalar(gridCellIndex); - vNormalized = (v - sgasMin) * sgasFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.r() = vNormalized; - } - - { - v = dataAccessObjectSoil->cellScalar(gridCellIndex); - vNormalized = (v - soilMin) * soilFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.g() = vNormalized; - } - - { - v = dataAccessObjectSwat->cellScalar(gridCellIndex); - vNormalized = (v - swatMin) * swatFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.b() = vNormalized; - } - - size_t j; - for (j = 0; j < 4; j++) - { - colorArray->set(quadIdx*4 + j, ternaryColorByte); - } - } -} diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 54bde9110c..711d276135 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -37,24 +37,6 @@ class RimCellEdgeResultSlot; -//================================================================================================== -/// -/// -//================================================================================================== -class RivTransmissibilityColorMapper -{ -public: - - static void updateTernarySaturationColorArray( - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Color3ubArray* colorArray, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); -}; - - - //================================================================================================== /// /// RivGridGeometry: Class to handle visualization structures that embodies a specific grid at a specific time step. From 8c22508e829eab14d6dba1f008800c2a75aa842d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 15:21:37 +0200 Subject: [PATCH 115/346] Linux include fix --- ApplicationCode/ModelVisualization/RivScalarMapperUtils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index de92c033b0..f807585422 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -18,6 +18,7 @@ #pragma once +#include "cvfBase.h" #include "cvfArray.h" namespace cvf From afa130a634c56300dfef5e8cb52c41c38f15a355 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 10:54:46 +0200 Subject: [PATCH 116/346] Bugfix statistics: Trigger loading of dataset before creating a result accessor --- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 778b4d19c0..66b6f25a30 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -196,6 +196,9 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result { RimCase* sourceCase = m_sourceCases.at(caseIdx); + // Trigger loading of dataset + sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(sourceCase->reservoirData(), gridIdx, poroModel, dataAccessTimeStepIndex, resultName, resultType); if (resultAccessor.notNull()) { From c11109d0356412db336f3658be7dbce354dfa34e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 11:16:46 +0200 Subject: [PATCH 117/346] Added RigHugeValResultAccessor Linux: Added include of cmath for define of HUGE_VAL --- .../ReservoirDataModel/RigResultAccessor.cpp | 18 ++++++++++++++++++ .../ReservoirDataModel/RigResultAccessor.h | 9 +++++++++ .../RigResultAccessorFactory.cpp | 8 +++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp index 160c2b9abe..aed929abea 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp @@ -17,3 +17,21 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RigResultAccessor.h" + +#include // Needed for HUGE_VAL on Linux + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigHugeValResultAccessor::cellScalar(size_t gridLocalCellIndex) const +{ + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigHugeValResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(gridLocalCellIndex); +} diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index 7bf45e048c..92f860037d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -35,3 +35,12 @@ class RigResultAccessor : public cvf::Object virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; +//================================================================================================== +/// +//================================================================================================== +class RigHugeValResultAccessor : public RigResultAccessor +{ +public: + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 71f20f5083..38bb2cf17d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -144,9 +144,10 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa if (!grid) return NULL; std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(resultIndex); + if (timeStepIndex >= scalarSetResults.size()) { - return NULL; + return new RigHugeValResultAccessor; } std::vector* resultValues = NULL; @@ -155,6 +156,11 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa resultValues = &(scalarSetResults[timeStepIndex]); } + if (!resultValues || resultValues->size() == 0) + { + return new RigHugeValResultAccessor; + } + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(resultIndex); if (useGlobalActiveIndex) { From 08e2a74f11be69e8ba7451f9471dd02417aedcaa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 12:58:03 +0200 Subject: [PATCH 118/346] Removed unused code --- .../ModelVisualization/RivGridPartMgr.cpp | 47 ------------------- .../ModelVisualization/RivGridPartMgr.h | 2 - 2 files changed, 49 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index f06db186b1..ad4017a1d8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -318,53 +318,6 @@ RivGridPartMgr::~RivGridPartMgr() #endif } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacity) -{ - cvf::ref colorArrayEffect = new cvf::Effect; - - if (RiaApplication::instance()->useShaders()) - { - cvf::ShaderProgramGenerator gen("PerVertexColor", cvf::ShaderSourceProvider::instance()); - gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); - gen.addFragmentCode(cvf::ShaderSourceRepository::src_VaryingColorGlobalAlpha); - gen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); - gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); - - cvf::ref m_shaderProg = gen.generate(); - m_shaderProg->setDefaultUniform(new cvf::UniformFloat("u_alpha", opacity)); - - colorArrayEffect->setShaderProgram(m_shaderProg.p()); - } - else - { - cvf::ref mat = new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE); - mat->setAlpha(opacity); - mat->enableColorMaterial(true); - colorArrayEffect->setRenderState(mat.p()); - - cvf::ref lighting = new cvf::RenderStateLighting_FF; - lighting->enableTwoSided(true); - colorArrayEffect->setRenderState(lighting.p()); - } - - // Simple transparency - if (opacity < 1.0f) - { - cvf::ref blender = new cvf::RenderStateBlending; - blender->configureTransparencyBlending(); - colorArrayEffect->setRenderState(blender.p()); - } - - caf::PolygonOffset polygonOffset = caf::PO_1; - cvf::ref polyOffset = caf::EffectGenerator::createAndConfigurePolygonOffsetRenderState(polygonOffset); - colorArrayEffect->setRenderState(polyOffset.p()); - - return colorArrayEffect; -} - //-------------------------------------------------------------------------------------------------- /// Helper class used to provide zero for all cells diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 711d276135..ea79932791 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -62,8 +62,6 @@ class RivGridPartMgr: public cvf::Object void appendPartsToModel(cvf::ModelBasicList* model); - static cvf::ref createPerVertexColoringEffect(float opacity); - private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, From aa8bc78d3069b87a1e344a936396344d014dd89b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 14:36:15 +0200 Subject: [PATCH 119/346] Cell edge visualization can now handle individual per face center values --- .../RivCellEdgeEffectGenerator.cpp | 135 ++++++++++-------- .../RivCellEdgeEffectGenerator.h | 16 +++ .../RigResultAccessorFactory.cpp | 5 + .../RigResultAccessorFactory.h | 13 +- 4 files changed, 104 insertions(+), 65 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index bbaf9eafb6..8714dbeaee 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -66,6 +66,9 @@ #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" #include "cvfStructGridScalarDataAccess.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RigCellEdgeResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// @@ -79,7 +82,19 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t gridIndex, float opacityLevel) { - const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + const RigGridBase* grid = dynamic_cast(generator->activeGrid()); + CVF_ASSERT(grid != NULL); + + // Create result access objects + + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, grid); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); + + + const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -105,48 +120,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - cvf::ref cellCenterDataAccessObject = NULL; - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); - } - - CVF_ASSERT(cellEdgeResultSlot->hasResult()); - - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - - cvf::Collection cellEdgeDataAccessObjects; - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - cvf::ref daObj; - - if (resultIndices[cubeFaceIdx] != cvf::UNDEFINED_SIZE_T) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->TO_BE_DELETED_resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); - } - - cellEdgeDataAccessObjects.push_back(daObj.p()); - } - + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); const std::vector* isWellPipeVisible = NULL; @@ -173,18 +147,12 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color size_t cellIndex = quadToCellFace->cellIndex(quadIdx); - { - double scalarValue = HUGE_VAL; - - if (cellCenterDataAccessObject.notNull()) - { - scalarValue = cellCenterDataAccessObject->cellScalar(cellIndex); - } + cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); if (scalarValue != HUGE_VAL) { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; // If we are dealing with wellcells, the default is transparent. // we need to make cells opaque if there are no wellpipe through them. @@ -211,17 +179,12 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); - size_t cubeFaceIdx; float edgeColor; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) { edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - double scalarValue = HUGE_VAL; - if (cellEdgeDataAccessObjects[cubeFaceIdx].notNull()) - { - scalarValue = cellEdgeDataAccessObjects[cubeFaceIdx]->cellScalar(cellIndex); - } + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) { @@ -241,7 +204,6 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - //faceIntAttribute->setIntegerTypeConversion(cvf::VertexAttribute::DIRECT_FLOAT); geo->setVertexAttribute(faceIntAttribute.p()); geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); @@ -252,6 +214,61 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 8fea369a1c..c670f414a6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -29,6 +29,8 @@ namespace cvf class RimCellEdgeResultSlot; class RimResultSlot; class RigGridBase; +class RigResultAccessor; +class RigCaseData; class RivCellEdgeGeometryGenerator @@ -41,6 +43,20 @@ class RivCellEdgeGeometryGenerator cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); + +private: + static cvf::ref createCellCenterResultAccessor( + RimResultSlot* cellResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); + + static cvf::ref createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); }; /* diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 38bb2cf17d..93cffaa93b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -138,6 +138,11 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa size_t timeStepIndex, size_t resultIndex) { + if (resultIndex == cvf::UNDEFINED_SIZE_T) + { + return new RigHugeValResultAccessor; + } + if (!eclipseCase) return NULL; RigGridBase* grid = eclipseCase->grid(gridIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 6c1d890dd7..55c8fff48f 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -45,6 +45,13 @@ class RigResultAccessorFactory const QString& uiResultName, RimDefines::ResultCatType resultType); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex); + // TO BE DELETED static cvf::ref @@ -63,12 +70,6 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& resultName); - static cvf::ref - createResultAccessor(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t resultIndex); }; From da5af154ab037c9f2d28cb8e49248d48e25a03b6 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 12 Aug 2014 15:02:19 +0200 Subject: [PATCH 120/346] fix build on my machine (openSUSE 13.1), it broke because the CheckCSourceCompiles CMake module was not included... --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a41fddb4da..1ed8203cdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required (VERSION 2.8) +include (CheckCSourceCompiles) project (ResInsight) set (VIZ_MODULES_FOLDER_NAME Fwk/VizFwk) From 536e39bd5e2f8ee90daaa413ff85545b96a6bf3a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 15:05:44 +0200 Subject: [PATCH 121/346] Cleaned up includes --- .../RivCellEdgeEffectGenerator.cpp | 55 ++++--------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 8714dbeaee..195f75f2aa 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -18,57 +18,24 @@ #include "RiaStdInclude.h" -#include "RivCellEdgeEffectGenerator.h" - -#include "cvfBase.h" -#include "cvfAssert.h" -#include "cvfDrawableGeo.h" -#include "cvfVertexAttribute.h" -#include "cvfStructGridGeometryGenerator.h" -#include "cvfScalarMapperUniformLevels.h" - -#include "cvfShaderProgramGenerator.h" -#include "cvfShaderSourceProvider.h" -#include "cvfqtUtils.h" -#include "cvfShaderProgram.h" -#include "cvfRenderStateCullFace.h" - -#include "cvfTextureImage.h" -#include "cvfTexture.h" -#include "cvfSampler.h" -#include "cvfScalarMapper.h" -#include "cafEffectGenerator.h" - -#include - -#include -#include +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigCellEdgeResultAccessor.h" +#include "RigGridBase.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "RimCase.h" - +#include "RimCellEdgeResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" +#include "RimWellCollection.h" -#include "RigGridBase.h" -#include "RigMainGrid.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RigActiveCellInfo.h" +#include "RivCellEdgeEffectGenerator.h" -#include "RimReservoirCellResultsStorage.h" +#include "cvfStructGridGeometryGenerator.h" +#include "cvfqtUtils.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "cvfStructGridScalarDataAccess.h" -#include "RigResultAccessor.h" -#include "RigResultAccessorFactory.h" -#include "RigCellEdgeResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// From 4bc03607f03bbabcfbb96ccc37096e29a66c698b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 09:19:47 +0200 Subject: [PATCH 122/346] Added cell edge with 2d texture coord support --- ApplicationCode/Resources/ResInsight.qrc | 1 + .../Resources/vs_2dTextureCellFace.glsl | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 ApplicationCode/Resources/vs_2dTextureCellFace.glsl diff --git a/ApplicationCode/Resources/ResInsight.qrc b/ApplicationCode/Resources/ResInsight.qrc index 73cb02a712..384db079ed 100644 --- a/ApplicationCode/Resources/ResInsight.qrc +++ b/ApplicationCode/Resources/ResInsight.qrc @@ -48,5 +48,6 @@ fs_CellFace.glsl vs_CellFace.glsl + vs_2dTextureCellFace.glsl diff --git a/ApplicationCode/Resources/vs_2dTextureCellFace.glsl b/ApplicationCode/Resources/vs_2dTextureCellFace.glsl new file mode 100644 index 0000000000..a42ba28a43 --- /dev/null +++ b/ApplicationCode/Resources/vs_2dTextureCellFace.glsl @@ -0,0 +1,130 @@ +uniform sampler2D u_edgeTexture2D; +uniform sampler2D u_cellTexture2D; + +attribute vec2 a_localCoord; +attribute float a_face; + +attribute vec2 a_cellTextureCoord; +attribute float a_colorPosI; +attribute float a_colorNegI; +attribute float a_colorPosJ; +attribute float a_colorNegJ; +attribute float a_colorPosK; +attribute float a_colorNegK; + +varying vec2 v_localCoord; +varying vec4 v_cellColor; +varying vec4 v_bottomColor; +varying vec4 v_rightColor; +varying vec4 v_topColor; +varying vec4 v_leftColor; + +// Native visualization lib stuff +uniform mat4 cvfu_modelViewProjectionMatrix; +uniform mat4 cvfu_modelViewMatrix; +uniform mat3 cvfu_normalMatrix; + +attribute vec4 cvfa_vertex; +attribute vec3 cvfa_normal; + +varying vec3 v_ecPosition; +varying vec3 v_ecNormal; +// End native vz stuff + +#define POS_I 0.0 +#define NEG_I 1.0 +#define POS_J 2.0 +#define NEG_J 3.0 +#define POS_K 4.0 +#define NEG_K 5.0 + +// +// 7---------6 +// /| /| |k +// / | / | | /j +// 4---------5 | |/ +// | 3------|--2 *---i +// | / | / +// |/ |/ +// 0---------1 +// +// Face layout expected +// POS_I 1, 2, 6, 5 +// NEG_I 0, 4, 7, 3 +// POS_J 3, 7, 6, 2 +// NEG_J 0, 1, 5, 4 +// POS_K 4, 5, 6, 7 +// NEG_K 0, 3, 2, 1 +// + +vec4 getColorFromTextureCoord(float textureCoord, vec4 cellColor) +{ + if (textureCoord < 0.0) + return cellColor; + else + return texture2D(u_edgeTexture2D, vec2(textureCoord, 0.5f )); +} + +void main() +{ + v_localCoord = a_localCoord; + + v_cellColor = texture2D(u_cellTexture2D, a_cellTextureCoord); + + if (a_face == POS_I) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + } + else if (a_face == NEG_I) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + } + else if (a_face == POS_J ) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + } + else if (a_face == NEG_J) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + } + else if (a_face == POS_K ) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + } + else if (a_face == NEG_K) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + } + else + { + v_bottomColor = v_cellColor; + v_rightColor = v_cellColor; + v_topColor = v_cellColor; + v_leftColor = v_cellColor; + } + + // Transforms vertex position and normal vector to eye space + v_ecPosition = (cvfu_modelViewMatrix * cvfa_vertex).xyz; + v_ecNormal = cvfu_normalMatrix * cvfa_normal; + + gl_Position = cvfu_modelViewProjectionMatrix*cvfa_vertex; +} + From 9428b72df4a3e730febab483ab0d27bd4f590c38 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 09:24:04 +0200 Subject: [PATCH 123/346] Cell edge now handles also ternary --- .../RivCellEdgeEffectGenerator.cpp | 324 +++++++++++++----- .../RivCellEdgeEffectGenerator.h | 21 +- .../ModelVisualization/RivGridPartMgr.cpp | 27 +- 3 files changed, 275 insertions(+), 97 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 195f75f2aa..c46ec71451 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -18,6 +18,8 @@ #include "RiaStdInclude.h" +#include "RivCellEdgeEffectGenerator.h" + #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigCellEdgeResultAccessor.h" @@ -31,10 +33,12 @@ #include "RimResultSlot.h" #include "RimWellCollection.h" -#include "RivCellEdgeEffectGenerator.h" +#include "RivTernaryScalarMapper.h" +#include "RimTernaryLegendConfig.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfqtUtils.h" +#include "RivTernaryTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -85,7 +89,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); } - cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); @@ -112,39 +116,42 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); - float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - size_t cellIndex = quadToCellFace->cellIndex(quadIdx); - { + size_t cellIndex = quadToCellFace->cellIndex(quadIdx); + { cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); - double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); - - if (scalarValue != HUGE_VAL) - { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - // If we are dealing with wellcells, the default is transparent. - // we need to make cells opaque if there are no wellpipe through them. - if (opacityLevel < 1.0f) - { - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !(*isWellPipeVisible)[wellIndex]) - { - cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" - } - } - } - } - else - { - cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. - } - } + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); + + { + float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color + if (scalarValue != HUGE_VAL) + { + cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + // If we are dealing with wellcells, the default is transparent. + // we need to make cells opaque if there are no wellpipe through them. + if (opacityLevel < 1.0f) + { + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if (!(*isWellPipeVisible)[wellIndex]) + { + cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" + } + } + } + } + else + { + cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. + } + + cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); + } + } - cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); float edgeColor; for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) @@ -181,32 +188,6 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) -{ - cvf::ref resultAccessor = NULL; - - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); - } - - if (resultAccessor.isNull()) - { - resultAccessor = new RigHugeValResultAccessor; - } - - return resultAccessor; -} //-------------------------------------------------------------------------------------------------- /// @@ -236,6 +217,134 @@ cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterRe return cellEdgeResultAccessor; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, cvf::StructGridGeometryGenerator* generator, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + const RigGridBase* grid = dynamic_cast(generator->activeGrid()); + CVF_ASSERT(grid != NULL); + + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); + + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper = generator->quadToCellFaceMapper(); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; + vCellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + grid->gridIndex(), + quadToCellFaceMapper); + + texturer.createTextureCoords(vCellColorTextureCoordArray.p()); + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + + @@ -244,11 +353,10 @@ cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterRe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper, const cvf::ScalarMapper* cellScalarMapper) +CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper) { CVF_ASSERT(edgeScalarMapper != NULL); - m_cellScalarMapper = cellScalarMapper; m_edgeScalarMapper = edgeScalarMapper; m_cullBackfaces = false; @@ -256,6 +364,21 @@ CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeSc m_defaultCellColor = cvf::Color3f(cvf::Color3::WHITE); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void CellEdgeEffectGenerator::setScalarMapper(const cvf::ScalarMapper* cellScalarMapper) +{ + m_cellScalarMapper = cellScalarMapper; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void CellEdgeEffectGenerator::setTernaryScalarMapper(const RivTernaryScalarMapper* ternaryScalarMapper) +{ + m_ternaryCellScalarMapper = ternaryScalarMapper; +} //-------------------------------------------------------------------------------------------------- /// @@ -267,7 +390,8 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const if (otherCellFaceEffectGenerator && m_cellScalarMapper.p() == otherCellFaceEffectGenerator->m_cellScalarMapper.p() && m_edgeScalarMapper.p() == otherCellFaceEffectGenerator->m_edgeScalarMapper.p() - && m_cullBackfaces == otherCellFaceEffectGenerator->m_cullBackfaces + && m_ternaryCellScalarMapper.p() == otherCellFaceEffectGenerator->m_ternaryCellScalarMapper.p() + && m_cullBackfaces == otherCellFaceEffectGenerator->m_cullBackfaces && m_opacityLevel == otherCellFaceEffectGenerator->m_opacityLevel && m_undefinedColor == otherCellFaceEffectGenerator->m_undefinedColor && m_defaultCellColor == otherCellFaceEffectGenerator->m_defaultCellColor @@ -300,7 +424,9 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const //-------------------------------------------------------------------------------------------------- caf::EffectGenerator* CellEdgeEffectGenerator::copy() const { - CellEdgeEffectGenerator * newEffect = new CellEdgeEffectGenerator(m_edgeScalarMapper.p(), m_cellScalarMapper.p()); + CellEdgeEffectGenerator * newEffect = new CellEdgeEffectGenerator(m_edgeScalarMapper.p()); + newEffect->setScalarMapper(m_cellScalarMapper.p()); + newEffect->setTernaryScalarMapper(m_ternaryCellScalarMapper.p()); newEffect->m_edgeTextureImage = m_edgeTextureImage; newEffect->m_cellTextureImage = m_cellTextureImage; @@ -317,36 +443,54 @@ caf::EffectGenerator* CellEdgeEffectGenerator::copy() const //-------------------------------------------------------------------------------------------------- void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) const { - cvf::ref eff = effect; + cvf::ref eff = effect; - // Set up shader program + // Set up shader program - cvf::ShaderProgramGenerator shaderGen("CellEdgeFaceShaderProgramGenerator", cvf::ShaderSourceProvider::instance()); - { - QFile data(":/Shader/fs_CellFace.glsl"); - if (data.open(QFile::ReadOnly)) - { - QTextStream in(&data); + cvf::ShaderProgramGenerator shaderGen("CellEdgeFaceShaderProgramGenerator", cvf::ShaderSourceProvider::instance()); + { + QFile data(":/Shader/fs_CellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); - QString data = in.readAll(); - cvf::String cvfString = cvfqt::Utils::toString(data); + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); - shaderGen.addFragmentCode(cvfString); - } - } + shaderGen.addFragmentCode(cvfString); + } + } - { - QFile data(":/Shader/vs_CellFace.glsl"); - if (data.open(QFile::ReadOnly)) - { - QTextStream in(&data); + if (m_ternaryCellScalarMapper.notNull()) + { + { + QFile data(":/Shader/vs_2dTextureCellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); - QString data = in.readAll(); - cvf::String cvfString = cvfqt::Utils::toString(data); + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); - shaderGen.addVertexCode(cvfString); - } - } + shaderGen.addVertexCode(cvfString); + } + } + } + else + { + { + QFile data(":/Shader/vs_CellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); + + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); + + shaderGen.addVertexCode(cvfString); + } + } + } shaderGen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); shaderGen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); @@ -361,7 +505,12 @@ void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) cvf::ref modifiedCellTextImage; m_edgeScalarMapper->updateTexture(m_edgeTextureImage.p()); - if (m_cellScalarMapper.notNull()) + if (m_ternaryCellScalarMapper.notNull()) + { + m_ternaryCellScalarMapper->updateTexture(m_cellTextureImage.p(), m_opacityLevel); + modifiedCellTextImage = m_cellTextureImage; + } + else if (m_cellScalarMapper.notNull()) { m_cellScalarMapper->updateTexture(m_cellTextureImage.p()); modifiedCellTextImage = caf::ScalarMapperEffectGenerator::addAlphaAndUndefStripes(m_cellTextureImage.p(), m_undefinedColor, m_opacityLevel); @@ -422,3 +571,4 @@ void CellEdgeEffectGenerator::updateForFixedFunctionRendering(cvf::Effect* effec surfaceGen.updateEffect(effect); } + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index c670f414a6..40e6fe4dfd 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -31,7 +31,7 @@ class RimResultSlot; class RigGridBase; class RigResultAccessor; class RigCaseData; - +class RivTernaryScalarMapper; class RivCellEdgeGeometryGenerator { @@ -44,6 +44,15 @@ class RivCellEdgeGeometryGenerator size_t gridIndex, float opacityLevel); + static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + cvf::StructGridGeometryGenerator* generator, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + private: static cvf::ref createCellCenterResultAccessor( RimResultSlot* cellResultSlot, @@ -134,7 +143,10 @@ class RivCellEdgeGeometryGenerator class CellEdgeEffectGenerator : public caf::EffectGenerator { public: - CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper, const cvf::ScalarMapper* cellScalarMapper); + CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper); + + void setScalarMapper(const cvf::ScalarMapper* cellScalarMapper); + void setTernaryScalarMapper(const RivTernaryScalarMapper* ternaryScalarMapper); void setOpacityLevel(float opacity) { m_opacityLevel = cvf::Math::clamp(opacity, 0.0f , 1.0f ); } void setUndefinedColor(cvf::Color3f color) { m_undefinedColor = color; } @@ -154,10 +166,11 @@ class CellEdgeEffectGenerator : public caf::EffectGenerator cvf::cref m_cellScalarMapper; mutable cvf::ref m_cellTextureImage; - float m_opacityLevel; + cvf::cref m_ternaryCellScalarMapper; + + float m_opacityLevel; bool m_cullBackfaces; cvf::Color3f m_undefinedColor; cvf::Color3f m_defaultCellColor; - }; diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ad4017a1d8..f941f86e8a 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -285,16 +285,31 @@ void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, { if (facePart) { - cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); + + cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); if (dg) { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); + if (cellResultSlot->isTernarySaturationSelected()) + { + RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); + } + else + { + if (cellResultSlot->hasResult()) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); + + cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cellFaceEffectGen.setScalarMapper(cellScalarMapper); + } + } - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); cellFaceEffectGen.setOpacityLevel(m_opacityLevel); cellFaceEffectGen.setDefaultCellColor(m_defaultColor); From 86d76b8145f36983c4269a3fca5a0672f092f7aa Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 10:45:09 +0200 Subject: [PATCH 124/346] Added support for cell edge on faults --- .../RivCellEdgeEffectGenerator.cpp | 102 ++++++++---------- .../RivCellEdgeEffectGenerator.h | 9 +- .../ModelVisualization/RivFaultPartMgr.cpp | 23 ++++ .../ModelVisualization/RivGridPartMgr.cpp | 59 ++-------- .../ModelVisualization/RivGridPartMgr.h | 6 +- .../RivReservoirPartMgr.cpp | 12 +++ .../ModelVisualization/RivReservoirPartMgr.h | 4 +- .../RivReservoirViewPartMgr.cpp | 11 +- .../RivReservoirViewPartMgr.h | 6 +- .../RivScalarMapperUtils.cpp | 51 ++++++++- .../ModelVisualization/RivScalarMapperUtils.h | 13 +++ .../ProjectDataModel/RimReservoirView.cpp | 16 ++- 12 files changed, 191 insertions(+), 121 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index c46ec71451..358110545d 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -20,6 +20,7 @@ #include "RivCellEdgeEffectGenerator.h" + #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigCellEdgeResultAccessor.h" @@ -31,14 +32,14 @@ #include "RimCellEdgeResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" #include "RimWellCollection.h" #include "RivTernaryScalarMapper.h" -#include "RimTernaryLegendConfig.h" +#include "RivTernaryTextureCoordsCreator.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfqtUtils.h" -#include "RivTernaryTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -48,26 +49,20 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, - cvf::DrawableGeo* geo, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) { RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); CVF_ASSERT(eclipseCase != NULL); - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - // Create result access objects - cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, grid); - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); - + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); - - size_t vertexCount = geo->vertexArray()->size(); + size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; cvf::ref localCoords = new cvf::Vec2fArray; @@ -111,14 +106,14 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx) ); - size_t cellIndex = quadToCellFace->cellIndex(quadIdx); + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); { - cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); { @@ -192,45 +187,14 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid) -{ - cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); - { - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); - cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); - } - } - - return cellEdgeResultAccessor; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, cvf::StructGridGeometryGenerator* generator, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) { RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); CVF_ASSERT(eclipseCase != NULL); - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); - - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper = generator->quadToCellFaceMapper(); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -261,7 +225,7 @@ void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, - grid->gridIndex(), + gridIndex, quadToCellFaceMapper); texturer.createTextureCoords(vCellColorTextureCoordArray.p()); @@ -317,6 +281,34 @@ void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 40e6fe4dfd..093243ad76 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -22,8 +22,8 @@ namespace cvf { - class StructGridGeometryGenerator; class DrawableGeo; + class StructGridQuadToCellFaceMapper; } class RimCellEdgeResultSlot; @@ -33,21 +33,22 @@ class RigResultAccessor; class RigCaseData; class RivTernaryScalarMapper; + class RivCellEdgeGeometryGenerator { public: static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, - cvf::DrawableGeo* geo, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index dc036eb046..6963f62674 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -182,7 +182,30 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* //-------------------------------------------------------------------------------------------------- void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { + if (m_nativeFaultFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_nativeFaultGenerator->quadToCellFaceMapper(), + m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + + m_nativeFaultFaces->setEffect(eff.p()); + } + } + if (m_oppositeFaultFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_oppositeFaultGenerator->quadToCellFaceMapper(), m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + + m_oppositeFaultFaces->setEffect(eff.p()); + } + } } const int priFaultGeo = 1; diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index f941f86e8a..6dc24bd149 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -268,56 +268,17 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { - updateCellEdgeResultColorOnPart( - m_surfaceFaces.p(), - &m_surfaceGenerator, - timeStepIndex, cellResultSlot, cellEdgeResultSlot); - -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, - cvf::StructGridGeometryGenerator* surfaceGenerator, - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot) -{ - if (facePart) - { - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); - - cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); - if (dg) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); - } - else - { - if (cellResultSlot->hasResult()) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - cellFaceEffectGen.setScalarMapper(cellScalarMapper); - } - } - - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); + if (m_surfaceFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_surfaceGenerator.quadToCellFaceMapper(), m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); - facePart->setEffect(eff.p()); - } - } + m_surfaceFaces->setEffect(eff.p()); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index ea79932791..ddd3b87a62 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -64,11 +64,7 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); - void updateCellEdgeResultColorOnPart(cvf::Part* facePart, - cvf::StructGridGeometryGenerator* surfaceGenerator, - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot); + private: size_t m_gridIdx; cvf::cref m_grid; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 60dae98bd0..90d573c7f7 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -197,3 +197,15 @@ void RivReservoirPartMgr::setFaultForceVisibility(bool isGeneratedByFilter) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirPartMgr::updateFaultCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + if (m_faultsPartMgr.notNull()) + { + m_faultsPartMgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); + } + +} + diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index 6f7075aeac..817fcb46fc 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -64,7 +64,9 @@ class RivReservoirPartMgr: public cvf::Object // Faults void updateFaultColors(size_t timeStepIndex, RimResultSlot* cellResultSlot); - void appendFaultPartsToModel(cvf::ModelBasicList* model); + void updateFaultCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); + void appendFaultPartsToModel(cvf::ModelBasicList* model); void appendFaultLabelPartsToModel(cvf::ModelBasicList* model); private: diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 461a90c7d0..2f13d9f2e6 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -795,7 +795,16 @@ void RivReservoirViewPartMgr::updateCellResultColor(ReservoirGeometryCacheType g void RivReservoirViewPartMgr::updateCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { RivReservoirPartMgr * pmgr = reservoirPartManager( geometryType, timeStepIndex ); - pmgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot ); + pmgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirViewPartMgr::updateFaultCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + RivReservoirPartMgr * pmgr = reservoirPartManager(geometryType, timeStepIndex); + pmgr->updateFaultCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h index 796835ad13..a499b6b683 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -66,12 +66,16 @@ class RivReservoirViewPartMgr: public cvf::Object void updateCellResultColor (ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot); void updateCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, - RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot); + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); // Faults void appendFaultsStaticGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType); void appendFaultsDynamicGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType, size_t frameIndex); void updateFaultColors(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot); + void updateFaultCellEdgeResultColor( ReservoirGeometryCacheType geometryType, size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); // Fault labels ReservoirGeometryCacheType geometryTypeForFaultLabels(const std::vector& geometryTypes) const; diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index e9620f6536..e3b01ebb51 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -18,8 +18,15 @@ #include "RivScalarMapperUtils.h" -#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RimCellEdgeResultSlot.h" +#include "RimLegendConfig.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" + +#include "RivCellEdgeEffectGenerator.h" #include "RivTernaryScalarMapper.h" +#include "RivTernaryScalarMapperEffectGenerator.h" #include "cafEffectGenerator.h" @@ -55,6 +62,47 @@ void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf part->setEffect(scalarEffect.p()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGeo* dg, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + size_t gridIndex, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + float opacityLevel, + cvf::Color3f defaultColor) +{ + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); + + if (cellResultSlot->isTernarySaturationSelected()) + { + RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + quadToCellFaceMapper, dg, gridIndex, opacityLevel); + + RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); + } + else + { + if (cellResultSlot->hasResult()) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + quadToCellFaceMapper, dg, gridIndex, opacityLevel); + + cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cellFaceEffectGen.setScalarMapper(cellScalarMapper); + } + } + + cellFaceEffectGen.setOpacityLevel(opacityLevel); + cellFaceEffectGen.setDefaultCellColor(defaultColor); + + cvf::ref eff = cellFaceEffectGen.generateEffect(); + return eff; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -84,3 +132,4 @@ cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(cons return scalarEffect; } + diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index f807585422..8e08965fde 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -26,9 +26,13 @@ namespace cvf class ScalarMapper; class Part; class Effect; + class StructGridQuadToCellFaceMapper; + class DrawableGeo; } class RivTernaryScalarMapper; +class RimResultSlot; +class RimCellEdgeResultSlot; //================================================================================================== /// @@ -39,6 +43,15 @@ class RivScalarMapperUtils static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel); static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel); + static cvf::ref createCellEdgeEffect(cvf::DrawableGeo* dg, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + size_t gridIndex, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + float opacityLevel, + cvf::Color3f defaultColor); + private: static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel); static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 063474c3f8..b1280f90b4 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -805,7 +805,7 @@ void RimReservoirView::updateCurrentTimeStep() { if (this->animationMode() && this->cellEdgeResult()->hasResult()) { - 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()) || this->cellResult()->isTernarySaturationSelected()) { @@ -2057,15 +2057,23 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = this->cellResult(); + RimResultSlot* faultResultSlot = this->cellResult(); if (this->faultResultSettings()->customFaultResult()) { - resultSlot = this->faultResultSettings()->customFaultResult(); + faultResultSlot = this->faultResultSettings()->customFaultResult(); } + for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, resultSlot); + if (this->animationMode() && this->cellEdgeResult()->hasResult()) + { + m_reservoirGridPartManager->updateFaultCellEdgeResultColor(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot, this->cellEdgeResult()); + } + else + { + m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot); + } } } From 0d411d374e5c399758066c3d6ced6eefa7d6c32f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 11:00:47 +0200 Subject: [PATCH 125/346] Renamed and restructured files and classes --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivCellEdgeEffectGenerator.cpp | 329 +---------------- .../RivCellEdgeEffectGenerator.h | 47 +-- .../RivCellEdgeGeometryUtils.cpp | 339 ++++++++++++++++++ .../RivCellEdgeGeometryUtils.h | 70 ++++ .../RivScalarMapperUtils.cpp | 5 +- 6 files changed, 426 insertions(+), 366 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp create mode 100644 ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 5079ead6ff..fec6bd6869 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -29,6 +29,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h ${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.h +${CEE_CURRENT_LIST_DIR}RivCellEdgeGeometryUtils.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -54,6 +55,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp ${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.cpp +${CEE_CURRENT_LIST_DIR}RivCellEdgeGeometryUtils.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 358110545d..ac493658cd 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -16,330 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" #include "RivCellEdgeEffectGenerator.h" - -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RigCellEdgeResultAccessor.h" -#include "RigGridBase.h" -#include "RigResultAccessor.h" -#include "RigResultAccessorFactory.h" - -#include "RimCase.h" -#include "RimCellEdgeResultSlot.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimTernaryLegendConfig.h" -#include "RimWellCollection.h" - #include "RivTernaryScalarMapper.h" -#include "RivTernaryTextureCoordsCreator.h" -#include "cvfStructGridGeometryGenerator.h" +#include "cvfRenderStateBlending.h" +#include "cvfRenderStateCullFace.h" +#include "cvfRenderStateTextureBindings.h" +#include "cvfSampler.h" +#include "cvfShaderProgram.h" +#include "cvfShaderProgramGenerator.h" +#include "cvfShaderSourceProvider.h" +#include "cvfTexture.h" #include "cvfqtUtils.h" - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel) -{ - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - // Create result access objects - - cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - - size_t vertexCount = geo->vertexArray()->size(); - size_t quadCount = vertexCount / 4; - - cvf::ref localCoords = new cvf::Vec2fArray; - localCoords->resize(vertexCount); - - cvf::ref faceIndexArray = new cvf::IntArray; - faceIndexArray->resize(vertexCount); - - cvf::ref cellColorTextureCoordArray = new cvf::FloatArray; - cellColorTextureCoordArray->resize(vertexCount); - - // Build six cell face color arrays - cvf::Collection cellEdgeColorTextureCoordsArrays; - size_t idx; - for (idx = 0; idx < 6; idx++) - { - cvf::ref colorArray = new cvf::FloatArray; - colorArray->resize(vertexCount); - cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); - } - - cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); - - const std::vector* isWellPipeVisible = NULL; - cvf::ref gridCellToWellindexMap; - - if (opacityLevel < 1.0f) - { - isWellPipeVisible = &(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex)); - gridCellToWellindexMap = eclipseCase->gridCellToWellIndex( gridIndex ); - } - -#pragma omp parallel for - for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) - { - localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); - localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); - localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); - localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx) ); - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - { - cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); - - { - float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - if (scalarValue != HUGE_VAL) - { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - // If we are dealing with wellcells, the default is transparent. - // we need to make cells opaque if there are no wellpipe through them. - if (opacityLevel < 1.0f) - { - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if (!(*isWellPipeVisible)[wellIndex]) - { - cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" - } - } - } - } - else - { - cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. - } - - cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); - } - } - - - float edgeColor; - for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - - double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) - { - edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - } - - cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); - - colArr->set(quadIdx * 4 + 0, edgeColor); - colArr->set(quadIdx * 4 + 1, edgeColor); - colArr->set(quadIdx * 4 + 2, edgeColor); - colArr->set(quadIdx * 4 + 3, edgeColor); - } - } - - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); - - cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - geo->setVertexAttribute(faceIntAttribute.p()); - - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) -{ - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - - size_t vertexCount = geo->vertexArray()->size(); - size_t quadCount = vertexCount / 4; - - cvf::ref localCoords = new cvf::Vec2fArray; - localCoords->resize(vertexCount); - - cvf::ref faceIndexArray = new cvf::IntArray; - faceIndexArray->resize(vertexCount); - - cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; - vCellColorTextureCoordArray->resize(vertexCount); - - // Build six cell face color arrays - cvf::Collection cellEdgeColorTextureCoordsArrays; - size_t idx; - for (idx = 0; idx < 6; idx++) - { - cvf::ref colorArray = new cvf::FloatArray; - colorArray->resize(vertexCount); - cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); - } - - RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); - - RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), - timeStepIndex, - gridIndex, - quadToCellFaceMapper); - - texturer.createTextureCoords(vCellColorTextureCoordArray.p()); - -#pragma omp parallel for - for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) - { - localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); - localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); - localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); - localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - - float edgeColor; - for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - - double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) - { - edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - } - - cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); - - colArr->set(quadIdx * 4 + 0, edgeColor); - colArr->set(quadIdx * 4 + 1, edgeColor); - colArr->set(quadIdx * 4 + 2, edgeColor); - colArr->set(quadIdx * 4 + 3, edgeColor); - } - } - - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); - - cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - geo->setVertexAttribute(faceIntAttribute.p()); - - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); - -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid) -{ - cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); - { - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); - cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); - } - } - - return cellEdgeResultAccessor; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) -{ - cvf::ref resultAccessor = NULL; - - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); - } - - if (resultAccessor.isNull()) - { - resultAccessor = new RigHugeValResultAccessor; - } - - return resultAccessor; -} - - - - - +#include +#include //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 093243ad76..118adce686 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -20,54 +20,9 @@ #include "cafEffectGenerator.h" -namespace cvf -{ - class DrawableGeo; - class StructGridQuadToCellFaceMapper; -} - -class RimCellEdgeResultSlot; -class RimResultSlot; -class RigGridBase; -class RigResultAccessor; -class RigCaseData; class RivTernaryScalarMapper; -class RivCellEdgeGeometryGenerator -{ -public: - static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel); - - static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel); - - -private: - static cvf::ref createCellCenterResultAccessor( - RimResultSlot* cellResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid); - - static cvf::ref createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid); -}; /* Thoughts on organizing the texture coords generation a bit. diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp new file mode 100644 index 0000000000..14b3d9f3a7 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp @@ -0,0 +1,339 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + + +#include "RivCellEdgeGeometryUtils.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigCellEdgeResultAccessor.h" +#include "RigGridBase.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RimCase.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" +#include "RivTernaryTextureCoordsCreator.h" + +#include "cvfDrawableGeo.h" +#include "cvfVertexAttribute.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + // Create result access objects + + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref cellColorTextureCoordArray = new cvf::FloatArray; + cellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + const std::vector* isWellPipeVisible = NULL; + cvf::ref gridCellToWellindexMap; + + if (opacityLevel < 1.0f) + { + isWellPipeVisible = &(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex)); + gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(gridIndex); + } + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + { + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); + + { + float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color + if (scalarValue != HUGE_VAL) + { + cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + // If we are dealing with wellcells, the default is transparent. + // we need to make cells opaque if there are no wellpipe through them. + if (opacityLevel < 1.0f) + { + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if (!(*isWellPipeVisible)[wellIndex]) + { + cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" + } + } + } + } + else + { + cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. + } + + cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); + } + } + + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; + vCellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + gridIndex, + quadToCellFaceMapper); + + texturer.createTextureCoords(vCellColorTextureCoordArray.p()); + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryUtils::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryUtils::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + + + + + + + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h new file mode 100644 index 0000000000..fdc96745a6 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" + +namespace cvf +{ + class DrawableGeo; + class StructGridQuadToCellFaceMapper; +} + +class RimCellEdgeResultSlot; +class RimResultSlot; +class RigGridBase; +class RigResultAccessor; +class RigCaseData; + + +class RivCellEdgeGeometryUtils +{ +public: + static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + +private: + static cvf::ref createCellCenterResultAccessor( + RimResultSlot* cellResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); + + static cvf::ref createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); +}; diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index e3b01ebb51..ea1e1b9707 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -25,6 +25,7 @@ #include "RimTernaryLegendConfig.h" #include "RivCellEdgeEffectGenerator.h" +#include "RivCellEdgeGeometryUtils.h" #include "RivTernaryScalarMapper.h" #include "RivTernaryScalarMapperEffectGenerator.h" @@ -78,7 +79,7 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe if (cellResultSlot->isTernarySaturationSelected()) { - RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, quadToCellFaceMapper, dg, gridIndex, opacityLevel); RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); @@ -88,7 +89,7 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe { if (cellResultSlot->hasResult()) { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, quadToCellFaceMapper, dg, gridIndex, opacityLevel); cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); From 549e61af7784fc03f20f5bce592ec8b7b5e0dca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 16:53:53 +0200 Subject: [PATCH 126/346] Fixed some compiler warnings --- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 5feeb2908c..819a65d5a5 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -73,6 +73,8 @@ bool readDoubleValues(RigCaseData* reservoir, size_t resultIndex, ecl_kw_type* e newPropertyData.push_back(std::vector()); newPropertyData[0].resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, newPropertyData[0].data()); + + return true; } //-------------------------------------------------------------------------------------------------- @@ -110,6 +112,8 @@ bool readDoubleValuesForActiveCells(RigCaseData* reservoir, size_t resultIndex, newPropertyData[0].resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, newPropertyData[0].data()); } + + return true; } From 710395bb8554a2ba522de4ea40a7c66e6b66247a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 17:19:30 +0200 Subject: [PATCH 127/346] Created StructGrid...ToCellFaceMapper Done to start refactoring to pave way for many new combined result properties --- .../RivCellEdgeEffectGenerator.cpp | 13 +- .../RivFaultGeometryGenerator.cpp | 67 ++-------- .../RivFaultGeometryGenerator.h | 23 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 33 ++--- .../ModelVisualization/RivGridPartMgr.cpp | 123 ++++++++++-------- .../ModelVisualization/RivGridPartMgr.h | 5 +- .../ModelVisualization/RivSourceInfo.cpp | 5 +- .../ModelVisualization/RivSourceInfo.h | 10 +- ApplicationCode/UserInterface/RiuViewer.cpp | 15 ++- .../cvfStructGridGeometryGenerator.cpp | 82 ++++++------ .../cvfStructGridGeometryGenerator.h | 49 +++++-- 11 files changed, 199 insertions(+), 226 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index b2e37f55bc..a195179b51 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -78,8 +78,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t gridIndex, float opacityLevel) { - const std::vector& quadToCell = generator->quadToGridCellIndices(); - const std::vector& quadToFace = generator->quadToFace(); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -166,13 +165,13 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - faceIndexArray->set(quadIdx * 4 + 0, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 1, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 2, quadToFace[quadIdx] ); - faceIndexArray->set(quadIdx * 4 + 3, quadToFace[quadIdx] ); + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - size_t cellIndex = quadToCell[quadIdx]; + size_t cellIndex = quadToCellFace->cellIndex(quadIdx); { double scalarValue = HUGE_VAL; diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index 0a8b3efe2f..e9ed113620 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -24,6 +24,8 @@ #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfOutlineEdgeExtractor.h" #include "cvfStructGridScalarDataAccess.h" +#include "cvfStructGridGeometryGenerator.h" + #include "cvfScalarMapper.h" #include "RigFault.h" @@ -38,6 +40,8 @@ RivFaultGeometryGenerator::RivFaultGeometryGenerator(const cvf::StructGridInterf m_fault(fault), m_computeNativeFaultFaces(computeNativeFaultFaces) { + m_quadMapper = new cvf::StructGridQuadToCellFaceMapper; + m_triangleMapper = new cvf::StuctGridTriangleToCellFaceMapper(m_quadMapper.p()); } //-------------------------------------------------------------------------------------------------- @@ -149,8 +153,8 @@ cvf::ref RivFaultGeometryGenerator::lineIndicesFromQuadVertexArr void RivFaultGeometryGenerator::computeArrays() { std::vector vertices; - m_quadsToGridCells.clear(); - m_quadsToFace.clear(); + m_quadMapper->quadToCellIndexMap().clear(); + m_quadMapper->quadToCellFaceMap().clear(); cvf::Vec3d offset = m_grid->displayModelOffset(); @@ -186,8 +190,8 @@ void RivFaultGeometryGenerator::computeArrays() } // Keep track of the source cell index per quad - m_quadsToGridCells.push_back(cellIndex); - m_quadsToFace.push_back(face); + m_quadMapper->quadToCellIndexMap().push_back(cellIndex); + m_quadMapper->quadToCellFaceMap().push_back(face); } } @@ -203,7 +207,7 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord { if (!dataAccessObject) return; - size_t numVertices = m_quadsToGridCells.size()*4; + size_t numVertices = m_quadMapper->quadCount()*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -212,9 +216,9 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadsToGridCells[i]); + cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -229,38 +233,6 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > RivFaultGeometryGenerator::triangleToSourceGridCellMap() const -{ - cvf::ref > triangles = new cvf::Array(2*m_quadsToGridCells.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) - { - triangles->set(i*2, m_quadsToGridCells[i]); - triangles->set(i*2+1, m_quadsToGridCells[i]); - } - - return triangles; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > RivFaultGeometryGenerator::triangleToFaceType() const -{ - cvf::ref > triangles = new cvf::Array(2*m_quadsToFace.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToFace.size()); i++) - { - triangles->set(i*2, m_quadsToFace[i]); - triangles->set(i*2+1, m_quadsToFace[i]); - } - - return triangles; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -268,20 +240,3 @@ void RivFaultGeometryGenerator::setCellVisibility(const cvf::UByteArray* cellVis { m_cellVisibility = cellVisibility; } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivFaultGeometryGenerator::quadToGridCellIndices() const -{ - return m_quadsToGridCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivFaultGeometryGenerator::quadToFace() const -{ - return m_quadsToFace; -} - diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index 43329a408d..81162a67c7 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -52,11 +52,9 @@ class RivFaultGeometryGenerator : public cvf::Object const cvf::ScalarMapper* mapper) const; // Mapping between cells and geometry - cvf::ref > triangleToSourceGridCellMap() const; - cvf::ref > triangleToFaceType() const; - const std::vector& quadToGridCellIndices() const; - const std::vector& quadToFace() const; + const cvf::StructGridQuadToCellFaceMapper * cellFromQuadMapper() { return m_quadMapper.p(); } + const cvf::StuctGridTriangleToCellFaceMapper * cellFromTriangleMapper() { return m_triangleMapper.p(); } // Generated geometry cvf::ref generateSurface(); @@ -70,18 +68,19 @@ class RivFaultGeometryGenerator : public cvf::Object private: // Input - cvf::cref m_grid; - cvf::cref m_fault; - cvf::cref m_cellVisibility; + cvf::cref m_grid; + cvf::cref m_fault; + cvf::cref m_cellVisibility; - bool m_computeNativeFaultFaces; + bool m_computeNativeFaultFaces; // Created arrays - cvf::ref m_vertices; + cvf::ref m_vertices; // Mappings - std::vector m_triangleIndexToGridCellIndex; - std::vector m_quadsToGridCells; + std::vector m_quadsToGridCells; std::vector m_quadsToFace; - std::vector m_triangleToFace; + + cvf::ref m_quadMapper; + cvf::ref m_triangleMapper; }; diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index e2df00d265..b33523952d 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -126,17 +126,15 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), + surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_nativeFaultGenerator->quadToFace(); - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_nativeFaultFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, + m_nativeFaultGenerator->cellFromQuadMapper()); } else { @@ -152,14 +150,15 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_nativeFaultGenerator->quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_nativeFaultFacesTextureCoords->size(); ++i) { if ((*m_nativeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -202,17 +201,13 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_oppositeFaultGenerator->quadToFace(); - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_oppositeFaultFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_oppositeFaultGenerator->cellFromQuadMapper()); } else { @@ -228,14 +223,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_oppositeFaultGenerator->quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) { if ((*m_oppositeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -311,8 +306,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = m_nativeFaultGenerator->triangleToSourceGridCellMap().p(); - si->m_faceTypes = m_nativeFaultGenerator->triangleToFaceType().p(); + si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->cellFromTriangleMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -365,8 +359,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = m_oppositeFaultGenerator->triangleToSourceGridCellMap().p(); - si->m_faceTypes = m_oppositeFaultGenerator->triangleToFaceType().p(); + si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->cellFromTriangleMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ddf67713c6..193571e2b8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -123,8 +123,8 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellIndices = geoBuilder.triangleToSourceGridCellMap().p(); - si->m_faceTypes = geoBuilder.triangleToFaceTypes().p(); + si->m_cellFaceFromTriangleMapper = geoBuilder.triangleToCellFaceMapper(); + part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -269,17 +269,12 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { surfaceFacesColorArray = new cvf::Color3ubArray; - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), quadsToGridCells); + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); } else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - const std::vector& quadsToFaceTypes = m_surfaceGenerator.quadToFace(); - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, quadsToFaceTypes, quadsToGridCells); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); } else { @@ -304,14 +299,14 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_surfaceGenerator.quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); for(size_t i = 0; i < m_surfaceFacesTextureCoords->size(); ++i) { if ((*m_surfaceFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -373,14 +368,15 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const std::vector& quadsToGridCells = m_faultGenerator.quadToGridCellIndices(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); for(size_t i = 0; i < m_faultFacesTextureCoords->size(); ++i) { if ((*m_faultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells[quadIdx]; + size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); if (wellIndex != cvf::UNDEFINED_UINT) { @@ -520,8 +516,7 @@ cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacit void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Vec2fArray* textureCoords, - const std::vector& quadsToFaceTypes, - const std::vector& quadsToGridCells) + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) { const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); if (!mapper) return; @@ -545,7 +540,8 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi cvf::ref dataAccessObjectTranZ = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); - size_t numVertices = quadsToGridCells.size()*4; + int quadCount = static_cast(quadToCellFaceMapper->quadCount()); + size_t numVertices = quadCount*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -554,53 +550,68 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int idx = 0; idx < static_cast(quadsToGridCells.size()); idx++) + for (int quadIdx = 0; quadIdx < quadCount; quadIdx++) { cellScalarValue = HUGE_VAL; - if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_I) - { - cellScalarValue = dataAccessObjectTranX->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_I) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + switch (cellFace) + { + case cvf::StructGridInterface::POS_I: { - cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranX->cellScalar(cellIndex); } - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_J) - { - cellScalarValue = dataAccessObjectTranY->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_J) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + break; + case cvf::StructGridInterface::NEG_I: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); + } + } + break; + case cvf::StructGridInterface::POS_J: { - cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranY->cellScalar(cellIndex); } - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::POS_K) - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(quadsToGridCells[idx]); - } - else if (quadsToFaceTypes[idx] == cvf::StructGridInterface::NEG_K) - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(quadsToGridCells[idx], &i, &j, &k); + break; + case cvf::StructGridInterface::NEG_J: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); + } + } + break; + case cvf::StructGridInterface::POS_K: { - cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); + cellScalarValue = dataAccessObjectTranZ->cellScalar(cellIndex); } + break; + case cvf::StructGridInterface::NEG_K: + { + size_t i, j, k, neighborGridCellIdx; + grid->ijkFromCellIndex(cellIndex, &i, &j, &k); + + if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + { + cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); + } + } + break; + default: + CVF_ASSERT(false); } + texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -610,7 +621,7 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi size_t j; for (j = 0; j < 4; j++) { - rawPtr[idx*4 + j] = texCoord; + rawPtr[quadIdx*4 + j] = texCoord; } } @@ -640,7 +651,9 @@ class ScalarDataAccessZeroForAllCells : public cvf::StructGridScalarDataAccess /// 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& quadsToGridCells) +void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t timeStepIndex, RimResultSlot* cellResultSlot, + const RigGridBase* grid, cvf::Color3ubArray* colorArray, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) { RimReservoirCellResultsStorage* gridCellResults = cellResultSlot->currentGridCellResults(); if (!gridCellResults) return; @@ -690,7 +703,7 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti double swatRange = swatMax - swatMin; double swatFactor = 255.0 / swatRange; - size_t numVertices = quadsToGridCells.size()*4; + size_t numVertices = quadToCellFaceMapper->quadCount()*4; colorArray->resize(numVertices); @@ -698,9 +711,9 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti double v, vNormalized; #pragma omp parallel for private(ternaryColorByte, v, vNormalized) - for (int idx = 0; idx < static_cast(quadsToGridCells.size()); idx++) + for (int quadIdx = 0; quadIdx < static_cast(quadToCellFaceMapper->quadCount()); quadIdx++) { - size_t gridCellIndex = quadsToGridCells[idx]; + size_t gridCellIndex = quadToCellFaceMapper->cellIndex(quadIdx); { v = dataAccessObjectSgas->cellScalar(gridCellIndex); @@ -729,7 +742,7 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti size_t j; for (j = 0; j < 4; j++) { - colorArray->set(idx*4 + j, ternaryColorByte); + colorArray->set(quadIdx*4 + j, ternaryColorByte); } } } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index d205256381..d866bd5f34 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -49,15 +49,14 @@ class RivTransmissibilityColorMapper RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Vec2fArray* textureCoords, - const std::vector& quadsToFaceTypes, - const std::vector& quadsToGridCells); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); static void updateTernarySaturationColorArray( size_t timeStepIndex, RimResultSlot* cellResultSlot, const RigGridBase* grid, cvf::Color3ubArray* colorArray, - const std::vector& quadsToGridCells); + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); }; diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp index 9df69e03a9..1e67105cde 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp @@ -17,14 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RivSourceInfo.h" +#include "cvfStructGridGeometryGenerator.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RivSourceInfo::hasCellIndices() const +bool RivSourceInfo::hasCellFaceMapping() const { - return m_cellIndices.notNull(); + return m_cellFaceFromTriangleMapper.notNull(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.h b/ApplicationCode/ModelVisualization/RivSourceInfo.h index de670c52a7..b4e5f1306c 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.h +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.h @@ -21,17 +21,15 @@ #include "cvfBase.h" #include "cvfObject.h" #include "cvfArray.h" -#include "cvfStructGrid.h" +#include "cvfStructGridGeometryGenerator.h" class RivSourceInfo : public cvf::Object { public: - bool hasCellIndices() const; + bool hasCellFaceMapping() const; bool hasNNCIndices() const; public: - cvf::ref > m_cellIndices; - cvf::ref > m_faceTypes; - - cvf::ref > m_NNCIndices; + cvf::cref m_cellFaceFromTriangleMapper; + cvf::ref > m_NNCIndices; }; diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 354cc30af3..e58a7bb8a7 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -274,10 +274,10 @@ void RiuViewer::mouseReleaseEvent(QMouseEvent* event) const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivSourceInfo) { - if (rivSourceInfo->hasCellIndices()) + if (rivSourceInfo->hasCellFaceMapping()) { m_currentGridIdx = firstHitPart->id(); - m_currentCellIndex = rivSourceInfo->m_cellIndices->get(faceIndex); + m_currentCellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); QMenu menu; menu.addAction(QString("I-slice range filter"), this, SLOT(slotRangeFilterI())); @@ -436,13 +436,14 @@ void RiuViewer::handlePickAction(int winPosX, int winPosY) const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); if (rivSourceInfo) { - if (rivSourceInfo->hasCellIndices()) + if (rivSourceInfo->hasCellFaceMapping()) { - size_t cellIndex = cvf::UNDEFINED_SIZE_T; - cellIndex = rivSourceInfo->m_cellIndices->get(faceIndex); + CVF_ASSERT(rivSourceInfo->m_cellFaceFromTriangleMapper.notNull()); - CVF_ASSERT(rivSourceInfo->m_faceTypes.notNull()); - cvf::StructGridInterface::FaceType face = rivSourceInfo->m_faceTypes->get(faceIndex); + size_t cellIndex = cvf::UNDEFINED_SIZE_T; + cellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); + + cvf::StructGridInterface::FaceType face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, &pickInfo); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index 977b451e63..a5dbdd0633 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -159,6 +159,8 @@ StructGridGeometryGenerator::StructGridGeometryGenerator(const StructGridInterfa : m_grid(grid) { CVF_ASSERT(grid); + m_quadMapper = new StructGridQuadToCellFaceMapper; + m_triangleMapper = new StuctGridTriangleToCellFaceMapper(m_quadMapper.p()); } @@ -309,8 +311,8 @@ bool StructGridGeometryGenerator::isCellFaceVisible(size_t i, size_t j, size_t k void StructGridGeometryGenerator::computeArrays() { std::vector vertices; - m_quadsToGridCells.clear(); - m_quadsToFace.clear(); + m_quadMapper->quadToCellIndexMap().clear(); + m_quadMapper->quadToCellFaceMap().clear(); cvf::Vec3d offset = m_grid->displayModelOffset(); @@ -362,8 +364,8 @@ void StructGridGeometryGenerator::computeArrays() } // Keep track of the source cell index per quad - m_quadsToGridCells.push_back(cellIndex); - m_quadsToFace.push_back(face); + m_quadMapper->quadToCellIndexMap().push_back(cellIndex); + m_quadMapper->quadToCellFaceMap().push_back(face); } } } @@ -385,7 +387,7 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, { if (!dataAccessObject) return; - size_t numVertices = m_quadsToGridCells.size()*4; + size_t numVertices = m_quadMapper->quadCount()*4; textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); @@ -394,9 +396,9 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, cvf::Vec2f texCoord; #pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadsToGridCells[i]); + cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -411,37 +413,43 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, } } +#if 0 //-------------------------------------------------------------------------------------------------- /// +/// //-------------------------------------------------------------------------------------------------- -ref > StructGridGeometryGenerator::triangleToSourceGridCellMap() const +void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* dataAccessObject) const { - ref > triangles = new Array(2*m_quadsToGridCells.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToGridCells.size()); i++) - { - triangles->set(i*2, m_quadsToGridCells[i]); - triangles->set(i*2+1, m_quadsToGridCells[i]); - } + if (!dataAccessObject) return; - return triangles; -} + textureCoords->resize(m_quadMapper->quadCount()*4); -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref > StructGridGeometryGenerator::triangleToFaceTypes() const -{ - ref > triangles = new Array(2*m_quadsToFace.size()); -#pragma omp parallel for - for (int i = 0; i < static_cast(m_quadsToFace.size()); i++) + cvf::Vec2f* rawPtr = textureCoords->ptr(); + + double cellFaceValue; + cvf::Vec2f texCoord; + int quadCount = static_cast(m_quadMapper->quadCount()); + +#pragma omp parallel for private(texCoord, cellFaceValue) + for (int qIdx = 0; qIdx < quadCount; qIdx++) { - triangles->set(i*2, m_quadsToFace[i]); - triangles->set(i*2+1, m_quadsToFace[i]); - } + cellFaceValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); + + texCoord = mapper->mapToTextureCoord(cellFaceValue); - return triangles; + if (cellFaceValue == HUGE_VAL || cellFaceValue != cellFaceValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + } + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[qIdx*4 + j] = texCoord; + } + } } +#endif //-------------------------------------------------------------------------------------------------- /// @@ -451,21 +459,5 @@ void StructGridGeometryGenerator::setCellVisibility(const UByteArray* cellVisibi m_cellVisibility = cellVisibility; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& StructGridGeometryGenerator::quadToGridCellIndices() const -{ - return m_quadsToGridCells; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& StructGridGeometryGenerator::quadToFace() const -{ - return m_quadsToFace; -} - } // namespace cvf diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index 9b95797a1d..32f0c2cafa 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -121,6 +121,37 @@ class CellFaceVisibilityFilter }; +class StructGridQuadToCellFaceMapper : public Object +{ +public: + size_t quadCount() const { return m_quadsToCells.size();} + + size_t cellIndex(size_t quadIdx) const {return m_quadsToCells[quadIdx]; } + StructGridInterface::FaceType cellFace(size_t quadIdx) const {return m_quadsToFace[quadIdx]; } + + // Interface for building the mappings + std::vector& quadToCellIndexMap() { return m_quadsToCells; } + std::vector& quadToCellFaceMap() { return m_quadsToFace; } + +private: + std::vector m_quadsToCells; + std::vector m_quadsToFace; +}; + + +class StuctGridTriangleToCellFaceMapper : public Object +{ +public: + StuctGridTriangleToCellFaceMapper(const StructGridQuadToCellFaceMapper* quadMapper) { m_quadMapper = quadMapper; } + size_t triangleCount() const { return 2* m_quadMapper->quadCount();} + + size_t cellIndex(size_t triangleIdx) const {return m_quadMapper->cellIndex(triangleIdx/2); } + StructGridInterface::FaceType cellFace(size_t triangleIdx) const {return m_quadMapper->cellFace(triangleIdx/2); } + +private: + cref m_quadMapper; +}; + //================================================================================================== // @@ -145,16 +176,9 @@ class StructGridGeometryGenerator : public Object void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const; // Mapping between cells and geometry - ref > - triangleToSourceGridCellMap() const; - - cvf::ref > - triangleToFaceTypes() const; - const std::vector& - quadToGridCellIndices() const; - const std::vector& - quadToFace() const; + const StructGridQuadToCellFaceMapper * quadToCellFaceMapper() { return m_quadMapper.p(); } + const StuctGridTriangleToCellFaceMapper * triangleToCellFaceMapper() { return m_triangleMapper.p(); } // Generated geometry ref generateSurface(); @@ -176,11 +200,10 @@ class StructGridGeometryGenerator : public Object // Created arrays cvf::ref m_vertices; + // Mappings - std::vector m_triangleIndexToGridCellIndex; - std::vector m_quadsToGridCells; - std::vector m_quadsToFace; - + ref m_quadMapper; + ref m_triangleMapper; }; } From fc1c7c0b0fc25564e961ed117b5caef052e917a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 24 Jun 2014 22:49:56 +0200 Subject: [PATCH 128/346] Wip - reactoring result texture handling --- .../RivCellEdgeEffectGenerator.h | 59 ++++++++++++- .../ModelVisualization/RivGridPartMgr.cpp | 86 +++++++++++++------ .../ModelVisualization/RivGridPartMgr.h | 7 +- 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index f05d7e1a49..0c37fb84bc 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -43,7 +43,64 @@ class RivCellEdgeGeometryGenerator float opacityLevel); }; - +/* + Thoughts on organizing the texture coords generation a bit. + + Conceptually several mappings takes place: + + 1. ResultValues to ResultPointValues <-- Eg. Cell Center values to CellFace Values + 2. ResultPointValues to GeometryPointValues <-- Eg. CellCenter Values to Triangle Vertex + 3. GeometryPointValues to TextureCoordinates/Colors <-- Handled by ScalarMapper + + When evaluating, we normally use the geometry as starting point, as that often is + a subset of the total results/geometry domain. + + To make this efficient, a minimum of internal storage should be used, so we want + to make the mappings as a set of functions called for each (or a few) texture + coordinate positions + + The mapping is then actually accessed in the opposite way of the above, while calculated in the 1-3 order + + Accessing correct values: + GeometryPointIdx->ResultPointIdx->ResultValueIdx + Calculating color: + ResultValue->ResultPointValue->GeometryPointValue->Texture/ColorValue + + In ResInsight (for now) + the ResultPointValue will be the same for all the corresponding GeometryPoints, + which means each quadvertex has the same texcoord for all corners. + + Proposal: + ---------- + Let the FaceValue to Face vertex texture coordinate mapping be the same for all. + Extract that from the code floating around. + + Create a PrimitiveFaceIdx to CellIdx with Face mapper class that handles the lookup, + created by the geometry generation + + Create separate calculators/mappers/Strategies to create FaceValues from results. + + Test Code + ----------- + // Example code + // 1. CellCenterToCellFace + // 2. CellFace to Quad Corners + // 3. Quad Corner Values to tex coords + + texCoords.resize(m_quadsToGridCells.size()*4); + for (i = 0; i < m_quadsToGridCells.size(); ++i) + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(dataAccessObject->cellScalar(m_quadsToGridCells[i])); + ResValue ResPoint To ResValue + texCoords[i*4 + 0] = texCoord; + texCoords[i*4 + 1] = texCoord; + texCoords[i*4 + 2] = texCoord; + texCoords[i*4 + 3] = texCoord; + } + + + +*/ //================================================================================================== // diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 193571e2b8..df5220b023 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -294,7 +294,13 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* // if this gridpart manager is set to have some transparency, we // interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but // we turn that off for particular cells, if the well pipe is not shown for that cell - + + setResultsTransparentForWellCells( + cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), + m_surfaceGenerator.quadToCellFaceMapper(), + m_surfaceFacesTextureCoords.p()); + /* if (m_opacityLevel < 1.0f ) { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); @@ -317,10 +323,11 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } - - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + + */ if (surfaceFacesColorArray.notNull()) { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); if (dg) { dg->setColorArray(surfaceFacesColorArray.p()); @@ -333,19 +340,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } 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 scalarEffect = scalarEffgen.generateEffect(); - - m_surfaceFaces->setEffect(scalarEffect.p()); + applyResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } @@ -363,7 +358,14 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (dataAccessObject.isNull()) return; m_faultGenerator.textureCoordinates(m_faultFacesTextureCoords.p(), dataAccessObject.p(), mapper); - + + setResultsTransparentForWellCells( + cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), + m_surfaceGenerator.quadToCellFaceMapper(), + m_faultFacesTextureCoords.p()); + + /* if (m_opacityLevel < 1.0f ) { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); @@ -387,18 +389,54 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } + */ + applyResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); + } +} - cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); - if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); +cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) +{ + caf::PolygonOffset polygonOffset = caf::PO_1; + caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + return scalarEffect; +} - caf::PolygonOffset polygonOffset = caf::PO_1; - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); +void RivGridPartMgr::applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) +{ + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); - scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = createScalarMapperEffect(mapper); + part->setEffect(scalarEffect.p()); +} - cvf::ref scalarEffect = scalarEffgen.generateEffect(); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap, + const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, + cvf::Vec2fArray* resultTextureCoords) +{ + if (m_opacityLevel < 1.0f ) + { + for(size_t i = 0; i < resultTextureCoords->size(); ++i) + { + if ((*resultTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - m_faultFaces->setEffect(scalarEffect.p()); + size_t quadIdx = i/4; + size_t cellIndex = quadsToCellFaceMapper->cellIndex(quadIdx); + cvf::uint wellIndex = gridCellToWellIndexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if ( !isWellPipeVisibleForWellIndex[wellIndex]) + { + (*resultTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture + } + } + } } } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index d866bd5f34..c395392902 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -90,7 +90,12 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); - + void applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); + cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); + void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap, + const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, + cvf::Vec2fArray* resultTextureCoords); private: size_t m_gridIdx; cvf::cref m_grid; From 066a2c57494145b43f509ba7327cda6d2036ecb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 25 Jun 2014 08:47:47 +0200 Subject: [PATCH 129/346] First step in refactoring result texture handling In order to support more derived reults properties more consistently across cell/fault/nnc and celledgevisualizations --- .../ModelVisualization/RivGridPartMgr.cpp | 75 +++++-------------- .../ModelVisualization/RivGridPartMgr.h | 2 +- 2 files changed, 18 insertions(+), 59 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index df5220b023..9bb2544180 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -291,40 +291,13 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), dataAccessObject.p(), mapper); } - // if this gridpart manager is set to have some transparency, we - // interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but - // we turn that off for particular cells, if the well pipe is not shown for that cell - + setResultsTransparentForWellCells( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), m_surfaceGenerator.quadToCellFaceMapper(), m_surfaceFacesTextureCoords.p()); - /* - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); - - for(size_t i = 0; i < m_surfaceFacesTextureCoords->size(); ++i) - { - if ((*m_surfaceFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_surfaceFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } - */ if (surfaceFacesColorArray.notNull()) { cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); @@ -340,7 +313,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - applyResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } @@ -365,35 +338,15 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.quadToCellFaceMapper(), m_faultFacesTextureCoords.p()); - /* - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_surfaceGenerator.quadToCellFaceMapper(); - - for(size_t i = 0; i < m_faultFacesTextureCoords->size(); ++i) - { - if ((*m_faultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_faultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } - */ - applyResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); + + applyTextureResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) { caf::PolygonOffset polygonOffset = caf::PO_1; @@ -403,17 +356,23 @@ cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::Scalar return scalarEffect; } -void RivGridPartMgr::applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) { cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); - if (dg) dg->setTextureCoordArray(m_faultFacesTextureCoords.p()); + if (dg) dg->setTextureCoordArray(textureCoords); cvf::ref scalarEffect = createScalarMapperEffect(mapper); part->setEffect(scalarEffect.p()); } //-------------------------------------------------------------------------------------------------- -/// +/// if this gridpart manager is set to have some transparency, we +/// interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but +/// we turn that off for particular cells, if the well pipe is not shown for that cell //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, const cvf::UIntArray* gridCellToWellIndexMap, diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index c395392902..eb656de4ab 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -90,7 +90,7 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); - void applyResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); + void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, const cvf::UIntArray* gridCellToWellIndexMap, From 34d62964d67fed2efe78c89aed99aa7f33662ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 09:12:42 +0200 Subject: [PATCH 130/346] FaultCelledge : Extracted a method from some duplicate code. --- .../ModelVisualization/RivGridPartMgr.cpp | 46 +++++++++++++++++++ .../ModelVisualization/RivGridPartMgr.h | 7 ++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 9bb2544180..16a213cbe0 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -404,6 +404,7 @@ void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector(m_surfaceFaces->drawable()); @@ -424,6 +425,20 @@ void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSl m_surfaceFaces->setEffect(eff.p()); } } + */ + updateCellEdgeResultColorOnPart( + m_surfaceFaces.p(), + &m_surfaceGenerator, + timeStepIndex, cellResultSlot, cellEdgeResultSlot); + + if (m_faultFaces.notNull()) + { + updateCellEdgeResultColorOnPart( + m_faultFaces.p(), + &m_faultGenerator, + timeStepIndex, cellResultSlot, cellEdgeResultSlot); + } + /* if (m_faultFaces.notNull()) { cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); @@ -444,6 +459,37 @@ void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSl m_faultFaces->setEffect(eff.p()); } } + */ +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, + cvf::StructGridGeometryGenerator* surfaceGenerator, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + if (facePart) + { + cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); + if (dg) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); + + cvf::ScalarMapper* cellScalarMapper = NULL; + if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); + cellFaceEffectGen.setOpacityLevel(m_opacityLevel); + cellFaceEffectGen.setDefaultCellColor(m_defaultColor); + + cvf::ref eff = cellFaceEffectGen.generateEffect(); + + facePart->setEffect(eff.p()); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index eb656de4ab..4ef7bb7e13 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -96,6 +96,11 @@ class RivGridPartMgr: public cvf::Object const cvf::UIntArray* gridCellToWellIndexMap, const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, cvf::Vec2fArray* resultTextureCoords); + void updateCellEdgeResultColorOnPart(cvf::Part* facePart, + cvf::StructGridGeometryGenerator* surfaceGenerator, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); private: size_t m_gridIdx; cvf::cref m_grid; @@ -112,7 +117,7 @@ class RivGridPartMgr: public cvf::Object cvf::ref m_surfaceGridLines; - // Fault visualization + // Fault visualization: Dead ?? JJS cvf::StructGridGeometryGenerator m_faultGenerator; RigFaultFaceVisibilityFilter m_faultFaceFilter; cvf::ref m_faultFaces; From aa8047a57dcc6119140db16d96b86d6d4e3c5d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 15:08:38 +0200 Subject: [PATCH 131/346] Set version text to development version 1.3.0-dev --- ResInsightVersion.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index 69e4286f37..f0906e5df6 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -1,8 +1,9 @@ set(CMAKE_MAJOR_VERSION 1) -set(CMAKE_MINOR_VERSION 2) +set(CMAKE_MINOR_VERSION 3) set(CMAKE_PATCH_VERSION 0) +set(DEV_VERSION "-dev") set(PRODUCTVER ${CMAKE_MAJOR_VERSION},${CMAKE_MINOR_VERSION},0,${CMAKE_PATCH_VERSION}) -set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}) +set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}${DEV_VERSION}) From 537a6ef7afa8454e818620bb515d21d4dcf5427a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 4 Jul 2014 15:09:26 +0200 Subject: [PATCH 132/346] Fixed bug/assert introduced after merge --- ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index b33523952d..b8de115c23 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -223,7 +223,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); + const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_oppositeFaultGenerator->cellFromQuadMapper(); for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) { From 1e7bde299d15c744ed24f9611bda27e183c1f367 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 10:14:36 +0200 Subject: [PATCH 133/346] Added build configuration description for Octave for Windows --- .../MinGWBuildConfigurationForOctave.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 OctavePlugin/MinGWBuildConfigurationForOctave.txt diff --git a/OctavePlugin/MinGWBuildConfigurationForOctave.txt b/OctavePlugin/MinGWBuildConfigurationForOctave.txt new file mode 100644 index 0000000000..f74b37cda3 --- /dev/null +++ b/OctavePlugin/MinGWBuildConfigurationForOctave.txt @@ -0,0 +1,17 @@ +Build configuration MinGW +================================== + +http://wiki.octave.org/Windows_Installer + +To be able to build with 64-bit indexing, run the following + +./configure --enable-64 + + + +// To get changes from server +hg pull +hg update + +http://hgbook.red-bean.com/read/a-tour-of-mercurial-the-basics.html + From d87c3da789cc1b6f958f58cbb8e9ef34f127565c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:09:15 +0200 Subject: [PATCH 134/346] Fwk: Allow label text on check box widget --- .../cafPdmUiCheckBoxEditor.cpp | 21 ++++++++++++------- .../cafUserInterface/cafPdmUiCheckBoxEditor.h | 7 +++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp index 748cf69a9a..7a8ac5dc30 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.cpp @@ -63,14 +63,24 @@ void PdmUiCheckBoxEditor::configureAndUpdateUi(const QString& uiConfigName) assert(!m_checkBox.isNull()); assert(!m_label.isNull()); - QIcon ic = field()->uiIcon(uiConfigName); - if (!ic.isNull()) + PdmUiCheckBoxEditorAttribute attributes; + field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); + + if (attributes.m_useNativeCheckBoxLabel) { - m_label->setPixmap(ic.pixmap(ic.actualSize(QSize(64, 64)))); + m_checkBox->setText(field()->uiName(uiConfigName)); } else { - m_label->setText(field()->uiName(uiConfigName)); + QIcon ic = field()->uiIcon(uiConfigName); + if (!ic.isNull()) + { + m_label->setPixmap(ic.pixmap(ic.actualSize(QSize(64, 64)))); + } + else + { + m_label->setText(field()->uiName(uiConfigName)); + } } m_label->setEnabled(!field()->isUiReadOnly(uiConfigName)); @@ -79,9 +89,6 @@ void PdmUiCheckBoxEditor::configureAndUpdateUi(const QString& uiConfigName) m_checkBox->setEnabled(!field()->isUiReadOnly(uiConfigName)); m_checkBox->setToolTip(field()->uiToolTip(uiConfigName)); - PdmUiCheckBoxEditorAttribute attributes; - field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); - m_checkBox->setChecked(field()->uiValue().toBool()); } diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h index 6b01f50e5a..bf67da9809 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiCheckBoxEditor.h @@ -52,7 +52,14 @@ namespace caf class PdmUiCheckBoxEditorAttribute : public PdmUiEditorAttribute { +public: + PdmUiCheckBoxEditorAttribute() + { + m_useNativeCheckBoxLabel = false; + } +public: + bool m_useNativeCheckBoxLabel; }; From 329ec921e8bf6418defb4e13d3dcf54ae89a1357 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:10:51 +0200 Subject: [PATCH 135/346] Preferences : Control if info text from Octave is displayed before executing scripts --- .../Application/RiaPreferences.cpp | 20 +++++++++++++++++-- ApplicationCode/Application/RiaPreferences.h | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 3e45619055..0acd148c48 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -21,6 +21,7 @@ #include "cafPdmUiFilePathEditor.h" #include "cafPdmFieldCvfColor.h" +#include "cafPdmUiCheckBoxEditor.h" CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- @@ -36,8 +37,12 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitField(&scriptEditorExecutable, "scriptEditorExecutable", QString("kate"), "Script Editor", "", "", ""); scriptEditorExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); - CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave", "", "", ""); + CAF_PDM_InitField(&octaveExecutable, "octaveExecutable", QString("octave"), "Octave executable location", "", "", ""); octaveExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); + octaveExecutable.setUiLabelPosition(caf::PdmUiItemInfo::TOP); + + CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", true, "Show text header when executing scripts", "", "", ""); + octaveShowHeaderInfoWhenExecutingScripts.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "ssihub Address", "", "", ""); @@ -84,6 +89,14 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt myAttr->m_appendUiSelectedFolderToText = true; } } + else if (field == &octaveShowHeaderInfoWhenExecutingScripts) + { + caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_useNativeCheckBoxLabel = true; + } + } } //-------------------------------------------------------------------------------------------------- @@ -96,7 +109,10 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* scriptGroup = uiOrdering.addNewGroup("Script configuration"); scriptGroup->add(&scriptDirectories); scriptGroup->add(&scriptEditorExecutable); - scriptGroup->add(&octaveExecutable); + + caf::PdmUiGroup* octaveGroup = uiOrdering.addNewGroup("Octave"); + octaveGroup->add(&octaveExecutable); + octaveGroup->add(&octaveShowHeaderInfoWhenExecutingScripts); caf::PdmUiGroup* defaultSettingsGroup = uiOrdering.addNewGroup("Default settings"); defaultSettingsGroup->add(&defaultScaleFactorZ); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 4623599926..4ee1873d49 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -40,7 +40,10 @@ class RiaPreferences : public caf::PdmObject caf::PdmField scriptDirectories; caf::PdmField scriptEditorExecutable; + caf::PdmField octaveExecutable; + caf::PdmField octaveShowHeaderInfoWhenExecutingScripts; + caf::PdmField ssihubAddress; caf::PdmField defaultScaleFactorZ; From 31274dbb0008fe203e41ceb72501aa6225d802cf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 22 Jul 2014 12:11:48 +0200 Subject: [PATCH 136/346] Aggregated common Octave argument list --- .../Application/RiaApplication.cpp | 28 +++++++++++++++ ApplicationCode/Application/RiaApplication.h | 2 ++ .../ProjectDataModel/RimCommandObject.cpp | 8 +---- .../ProjectDataModel/RimUiTreeView.cpp | 34 ++----------------- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 28c6de9612..79b9a501bf 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1066,6 +1066,34 @@ QString RiaApplication::octavePath() const return m_preferences->octaveExecutable(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RiaApplication::octaveArguments() const +{ + // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options + + // -p path + // Add path to the head of the search path for function files. The value of path specified on the command line + // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or + // user startup files that set the internal load path through one of the path functions. + + + QStringList arguments; + arguments.append("--path"); + arguments << QApplication::applicationDirPath(); + + if (!m_preferences->octaveShowHeaderInfoWhenExecutingScripts) + { + // -q + // Don't print the usual greeting and version message at startup. + + arguments.append("-q"); + } + + return arguments; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index f026d613b6..d15203870f 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -123,7 +123,9 @@ class RiaApplication : public QApplication RINavigationPolicy navigationPolicy() const; QString scriptDirectories() const; QString scriptEditorPath() const; + QString octavePath() const; + QStringList octaveArguments() const; bool launchProcess(const QString& program, const QStringList& arguments); bool launchProcessForMultipleCases(const QString& program, const QStringList& arguments, const std::vector& caseIds); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index f24c7bd956..858f936def 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -106,13 +106,7 @@ void RimCommandExecuteScript::redo() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - QStringList arguments; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); + QStringList arguments = app->octaveArguments(); arguments.append("--eval"); arguments << this->scriptText(); diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 690c0bdfa7..60bde2559f 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -538,29 +538,14 @@ void RimUiTreeView::slotExecuteScript() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - // -p path - // Add path to the head of the search path for function files. The value of path specified on the command line - // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or - // user startup files that set the internal load path through one of the path functions. - - // -q - // Don't print the usual greeting and version message at startup. - - // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); - QStringList arguments; + QStringList arguments = app->octaveArguments(); arguments.append("--path"); arguments << octaveFunctionSearchPath; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); arguments << calcScript->absolutePath(); RiaApplication::instance()->launchProcess(octavePath, arguments); @@ -593,29 +578,14 @@ void RimUiTreeView::slotExecuteScriptForSelectedCases() QString octavePath = app->octavePath(); if (!octavePath.isEmpty()) { - // http://www.gnu.org/software/octave/doc/interpreter/Command-Line-Options.html#Command-Line-Options - - // -p path - // Add path to the head of the search path for function files. The value of path specified on the command line - // will override any value of OCTAVE_PATH found in the environment, but not any commands in the system or - // user startup files that set the internal load path through one of the path functions. - - // -q - // Don't print the usual greeting and version message at startup. - - // TODO: Must rename RimCalcScript::absolutePath to absoluteFileName, as the code below is confusing // absolutePath() is a function in QFileInfo QFileInfo fi(calcScript->absolutePath()); QString octaveFunctionSearchPath = fi.absolutePath(); - QStringList arguments; + QStringList arguments = app->octaveArguments(); arguments.append("--path"); arguments << octaveFunctionSearchPath; - arguments.append("--path"); - arguments << QApplication::applicationDirPath(); - - arguments.append("-q"); arguments << calcScript->absolutePath(); // Get case ID from selected cases in selection model From 9236d27272db01c40b6f8aac5d9d02c81a426ef8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 12 Jun 2014 12:35:48 +0200 Subject: [PATCH 137/346] Removed obsolete includes --- ApplicationCode/ProjectDataModel/RimFault.cpp | 16 +--------------- .../ProjectDataModel/RimFaultCollection.cpp | 15 +++------------ .../ProjectDataModel/RimFaultCollection.h | 2 +- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFault.cpp b/ApplicationCode/ProjectDataModel/RimFault.cpp index 88a3686a19..cbb223c56c 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.cpp +++ b/ApplicationCode/ProjectDataModel/RimFault.cpp @@ -21,12 +21,6 @@ #include "RigFault.h" #include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimFault, "Fault"); @@ -72,17 +66,9 @@ void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const Q if (&showFault == changedField) { this->updateUiIconFromState(showFault); - - RimReservoirView* reservoirView = NULL; - this->firstAncestorOfType(reservoirView); - - if (reservoirView) - { - reservoirView->scheduleCreateDisplayModelAndRedraw(); - } } - if (&faultColor == changedField) + if (&faultColor == changedField || &showFault == changedField) { RimReservoirView* reservoirView = NULL; this->firstAncestorOfType(reservoirView); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index b6a201af09..2de8ac55df 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -21,23 +21,14 @@ #include "cafAppEnum.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirView.h" - -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellEdgeResultSlot.h" #include "RiaApplication.h" #include "RiaPreferences.h" - -#include "RimCase.h" -#include "RimReservoirCellResultsCacher.h" #include "RigCaseData.h" -#include "RivColorTableArray.h" +#include "RimCase.h" +#include "RimReservoirView.h" #include "RiuMainWindow.h" +#include "RivColorTableArray.h" namespace caf diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 632c3bd7c8..0d2cb37b66 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -27,7 +27,7 @@ #include "cvfBase.h" #include "cvfColor3.h" -#include "RimFault.h" +class RimFault; class RimReservoirView; From 7db9b83c451c23555513faa7a11ca51ab44c40bf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 23 Jul 2014 12:22:57 +0200 Subject: [PATCH 138/346] Added recent file list --- .../UserInterface/RiuMainWindow.cpp | 94 ++++++++++++++++++- ApplicationCode/UserInterface/RiuMainWindow.h | 12 ++- 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index a1fe0b204e..7a2d8f163d 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -214,7 +214,15 @@ void RiuMainWindow::createActions() m_saveProjectAsAction = new QAction(QIcon(":/Save.png"), "Save Project &As", this); m_closeProjectAction = new QAction("&Close Project", this); - m_exitAction = new QAction("E&xit", this); + + for (int i = 0; i < MaxRecentFiles; ++i) + { + m_recentFileActions[i] = new QAction(this); + m_recentFileActions[i]->setVisible(false); + connect(m_recentFileActions[i], SIGNAL(triggered()), this, SLOT(slotOpenRecentFile())); + } + + m_exitAction = new QAction("E&xit", this); connect(m_openProjectAction, SIGNAL(triggered()), SLOT(slotOpenProject())); connect(m_openLastUsedProjectAction, SIGNAL(triggered()), SLOT(slotOpenLastUsedProject())); @@ -352,6 +360,12 @@ void RiuMainWindow::createMenus() fileMenu->addAction(m_saveProjectAction); fileMenu->addAction(m_saveProjectAsAction); + m_recentFilesSeparatorAction = fileMenu->addSeparator(); + for (int i = 0; i < MaxRecentFiles; ++i) + fileMenu->addAction(m_recentFileActions[i]); + + updateRecentFileActions(); + fileMenu->addSeparator(); QMenu* testMenu = fileMenu->addMenu("&Testing"); @@ -763,7 +777,10 @@ void RiuMainWindow::slotImportEclipseCase() if (!fileNames.isEmpty()) { - app->openEclipseCaseFromFile(fileName); + if (app->openEclipseCaseFromFile(fileName)) + { + addRecentFiles(fileName); + } } } } @@ -807,7 +824,10 @@ void RiuMainWindow::slotOpenProject() // Remember the path to next time app->setDefaultFileDialogDirectory("BINARY_GRID", QFileInfo(fileName).absolutePath()); - app->loadProject(fileName); + if (app->loadProject(fileName)) + { + addRecentFiles(fileName); + } } } @@ -819,8 +839,11 @@ void RiuMainWindow::slotOpenLastUsedProject() { RiaApplication* app = RiaApplication::instance(); QString fileName = app->preferences()->lastUsedProjectFileName; - app->loadProject(fileName); - + + if (app->loadProject(fileName)) + { + addRecentFiles(fileName); + } } //-------------------------------------------------------------------------------------------------- @@ -937,6 +960,67 @@ void RiuMainWindow::slotCloseProject() bool ret = app->closeProject(true); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::slotOpenRecentFile() +{ + QAction *action = qobject_cast(sender()); + if (action) + { + QString filename = action->data().toString(); + + if (filename.contains(".rsp", Qt::CaseInsensitive) || filename.contains(".rip", Qt::CaseInsensitive) ) + { + RiaApplication::instance()->loadProject(action->data().toString()); + } + else if ( filename.contains(".egrid", Qt::CaseInsensitive) || filename.contains(".grid", Qt::CaseInsensitive) ) + { + RiaApplication::instance()->openEclipseCaseFromFile(filename); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::updateRecentFileActions() +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + + int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles); + + for (int i = 0; i < numRecentFiles; ++i) { + QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); + m_recentFileActions[i]->setText(text); + m_recentFileActions[i]->setData(files[i]); + m_recentFileActions[i]->setVisible(true); + } + for (int j = numRecentFiles; j < MaxRecentFiles; ++j) + m_recentFileActions[j]->setVisible(false); + + m_recentFilesSeparatorAction->setVisible(numRecentFiles > 0); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::addRecentFiles(const QString& file) +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(file); + files.prepend(file); + while (files.size() > MaxRecentFiles) + files.removeLast(); + + settings.setValue("recentFileList", files); + + updateRecentFileActions(); +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index ae3f922af3..54da53911b 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -111,7 +111,8 @@ class RiuMainWindow : public QMainWindow bool checkForDocumentModifications(); - void updateMRUList(const QString &fileName, bool remove = false); + void updateRecentFileActions(); + void addRecentFiles(const QString& file); QMdiSubWindow* findMdiSubWindow(RiuViewer* viewer); @@ -137,6 +138,13 @@ class RiuMainWindow : public QMainWindow QAction* m_closeProjectAction; QAction* m_exitAction; + // Recent files + enum { MaxRecentFiles = 5 }; + QAction* m_recentFilesSeparatorAction; + QMenu* m_recentFilesMenu; + QAction* m_recentFileActions[MaxRecentFiles]; + + // Edit actions QAction* m_editPreferences; QAction* m_newPropertyView; @@ -203,6 +211,8 @@ private slots: void slotSaveProjectAs(); void slotCloseProject(); + void slotOpenRecentFile(); + void slotRefreshFileActions(); // Edit slots From d21e532c6109fce4044230b81b64242912820adf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:11:43 +0200 Subject: [PATCH 139/346] Cleaned up includes for ProjectDataModel --- .../Application/RiaApplication.cpp | 2 + ApplicationCode/Application/RiaPreferences.h | 3 + .../ModelVisualization/RivFaultPartMgr.cpp | 1 + .../ModelVisualization/RivGridPartMgr.cpp | 1 + .../RivReservoirPipesPartMgr.cpp | 1 + .../RivReservoirViewPartMgr.cpp | 1 + .../RivWellPathCollectionPartMgr.cpp | 20 +----- .../RivWellPathCollectionPartMgr.h | 9 +++ .../ModelVisualization/RivWellPathPartMgr.h | 2 + .../RivWellPipesPartMgr.cpp | 1 + .../Rim3dOverlayInfoConfig.cpp | 17 ++--- .../ProjectDataModel/RimAnalysisModels.cpp | 30 ++------ .../ProjectDataModel/RimAnalysisModels.h | 6 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 50 ++++--------- .../ProjectDataModel/RimCaseCollection.cpp | 14 +--- .../RimCellEdgeResultSlot.cpp | 13 ++-- .../RimCellPropertyFilter.cpp | 10 +-- .../ProjectDataModel/RimCellPropertyFilter.h | 13 ---- .../RimCellPropertyFilterCollection.cpp | 7 -- .../ProjectDataModel/RimCellRangeFilter.cpp | 19 ++--- .../ProjectDataModel/RimCellRangeFilter.h | 10 +-- .../RimCellRangeFilterCollection.cpp | 12 +--- .../ProjectDataModel/RimCommandObject.cpp | 25 ++----- .../ProjectDataModel/RimCommandObject.h | 2 - ApplicationCode/ProjectDataModel/RimFault.h | 5 +- .../ProjectDataModel/RimFaultCollection.cpp | 7 +- .../ProjectDataModel/RimFaultCollection.h | 14 ++-- .../RimIdenticalGridCaseGroup.cpp | 28 +++----- .../RimIdenticalGridCaseGroup.h | 1 - .../ProjectDataModel/RimInputCase.cpp | 31 +++----- .../ProjectDataModel/RimInputProperty.cpp | 5 +- .../RimInputPropertyCollection.cpp | 5 +- .../RimInputPropertyCollection.h | 2 +- .../ProjectDataModel/RimOilField.cpp | 25 +------ .../ProjectDataModel/RimOilField.h | 14 ++-- .../ProjectDataModel/RimProject.cpp | 34 +++------ ApplicationCode/ProjectDataModel/RimProject.h | 4 +- .../RimReservoirCellResultsCacher.cpp | 37 +++------- .../RimReservoirCellResultsCacher.h | 10 +-- .../ProjectDataModel/RimReservoirView.cpp | 70 +++++++------------ .../ProjectDataModel/RimReservoirView.h | 36 +++++----- .../ProjectDataModel/RimResultCase.cpp | 44 ++++-------- .../ProjectDataModel/RimResultCase.h | 4 -- .../ProjectDataModel/RimResultDefinition.cpp | 20 ++---- .../ProjectDataModel/RimResultDefinition.h | 5 +- .../ProjectDataModel/RimResultSlot.cpp | 2 - .../ProjectDataModel/RimResultSlot.h | 3 - .../ProjectDataModel/RimScriptCollection.cpp | 13 ++-- .../ProjectDataModel/RimScriptCollection.h | 3 +- .../ProjectDataModel/RimStatisticsCase.cpp | 34 +++------ .../RimStatisticsCaseCollection.cpp | 16 +---- .../RimStatisticsCaseCollection.h | 6 +- .../RimStatisticsCaseEvaluator.cpp | 16 +---- .../RimStatisticsCaseEvaluator.h | 8 +-- ApplicationCode/ProjectDataModel/RimTools.cpp | 24 +------ ApplicationCode/ProjectDataModel/RimTools.h | 2 +- .../ProjectDataModel/RimUiTreeModelPdm.cpp | 45 +++++------- .../ProjectDataModel/RimUiTreeView.cpp | 2 + ApplicationCode/ProjectDataModel/RimWell.cpp | 15 +--- ApplicationCode/ProjectDataModel/RimWell.h | 8 ++- .../ProjectDataModel/RimWellCollection.cpp | 16 ++--- .../ProjectDataModel/RimWellCollection.h | 7 +- .../ProjectDataModel/RimWellPath.cpp | 33 ++------- .../ProjectDataModel/RimWellPath.h | 5 +- .../RimWellPathCollection.cpp | 34 +++------ .../ProjectDataModel/RimWellPathCollection.h | 12 +++- .../RiaPropertyDataCommands.cpp | 1 + .../UserInterface/RiuMainWindow.cpp | 55 ++++++--------- 68 files changed, 332 insertions(+), 698 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 79b9a501bf..61862f5b8c 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -39,6 +39,7 @@ #include "RimWellPathCollection.h" #include "RimOilField.h" #include "RimAnalysisModels.h" +#include "RimFaultCollection.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -78,6 +79,7 @@ #include "cvfProgramOptions.h" #include "cvfqtUtils.h" +#include "RimCommandObject.h" namespace caf diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 4ee1873d49..bb7d3f3354 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -24,6 +24,9 @@ #include "cafPdmField.h" #include "cafAppEnum.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + class RiaPreferences : public caf::PdmObject { diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index b8de115c23..7da6f4c85d 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -47,6 +47,7 @@ #include "RivGridPartMgr.h" #include "cvfRenderStateDepth.h" #include "RivSourceInfo.h" +#include "RimFaultCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 16a213cbe0..ee795b0004 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,6 +50,7 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" +#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp index 842990aed1..64e58e3b3e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp @@ -20,6 +20,7 @@ #include "RivReservoirPipesPartMgr.h" #include "RimReservoirView.h" +#include "RimWell.h" #include "RimWellCollection.h" #include "RivWellPipesPartMgr.h" #include "RivWellHeadPartMgr.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 3f78c6d111..4dbd4bb183 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -37,6 +37,7 @@ #include "RimCellEdgeResultSlot.h" #include "Rim3dOverlayInfoConfig.h" #include "RimReservoirCellResultsCacher.h" +#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp index ee443be4ee..4e34fcbf45 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp @@ -16,27 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" + +#include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RivWellPathPartMgr.h" -#include "RimWellPathCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index 8e5963d543..e5ac6a5d0e 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -21,11 +21,20 @@ #include "cvfCollection.h" #include "cafPdmPointer.h" +#include "cvfVector3.h" +#include "cvfBoundingBox.h" +#include "cvfTransform.h" class RimWellPathCollection; class RimProject; class RivWellPathPartMgr; +namespace cvf +{ + class ModelBasicList; +} + + class RivWellPathCollectionPartMgr : public cvf::Object { public: diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index b1dc9ed3c8..873c15296e 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -28,6 +28,8 @@ namespace cvf class ModelBasicList; class Transform; class Effect; + class DrawableGeo; + class ScalarMapper; } class RivPipeGeometryGenerator; diff --git a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp index 592da5a8a9..546c9ef627 100644 --- a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp @@ -36,6 +36,7 @@ #include "RimCase.h" #include "RimReservoirView.h" +#include "RimWell.h" #include "RimWellCollection.h" #include "RimReservoirCellResultsCacher.h" diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 347895c6a1..2ffb186033 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -18,20 +18,17 @@ #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirView.h" -#include "RiuViewer.h" -#include "RimCase.h" +#include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RimResultSlot.h" +#include "RimCase.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" - #include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" - +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RigCaseCellResultsData.h" +#include "RiuViewer.h" +#include "RimFaultCollection.h" CAF_PDM_SOURCE_INIT(Rim3dOverlayInfoConfig, "View3dOverlayInfoConfig"); diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp index e0968679fa..5d2bd3c368 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp @@ -16,37 +16,17 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimAnalysisModels.h" -#include "RiaApplication.h" -#include "RimProject.h" -#include "cafAppEnum.h" -#include "RimReservoirView.h" - -#include "RimIdenticalGridCaseGroup.h" #include "RiaApplication.h" - -#include "RigGridManager.h" #include "RigCaseData.h" -#include "RimResultCase.h" -#include "RimWellPathCollection.h" - - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" +#include "RigGridManager.h" +#include "RimCase.h" #include "RimCaseCollection.h" -#include "RimResultSlot.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimProject.h" #include "RimStatisticsCase.h" -#include "RimOilField.h" -#include "RimScriptCollection.h" + CAF_PDM_SOURCE_INIT(RimAnalysisModels, "ResInsightAnalysisModels"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h index b36cd1d28e..6a205d4778 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h @@ -18,7 +18,11 @@ #pragma once -#include "cafPdmDocument.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" + +#include "cvfObject.h" class RimCase; class RigGridManager; diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index e412c1557e..90f1115fc5 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -16,52 +16,26 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimCase.h" -#include -#include -#include -#include - -#include "RifReaderEclipseOutput.h" -#include "RifReaderMockModel.h" - -#include "RimReservoirView.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimCaseCollection.h" +#include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimWellCollection.h" -#include "RimWellPathCollection.h" - -#include "RimScriptCollection.h" - -#include "RigCaseData.h" -#include "RigMainGrid.h" -#include "RigCaseCellResultsData.h" - -#include "cvfAssert.h" - -#include "cafPdmFieldCvfColor.h" - -#include "cafPdmUiPushButtonEditor.h" - -#include -#include "RimProject.h" #include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCaseCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" + #include "cafProgressInfo.h" +#include +#include +#include +#include + + CAF_PDM_SOURCE_INIT(RimCase, "RimReservoir"); //------------------------------------------------------------------------------------------------ diff --git a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp index bf8064a8bb..630684c92c 100644 --- a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp @@ -17,22 +17,10 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCaseCollection.h" -#include "RimCase.h" -#include "RimReservoirView.h" +#include "RimCase.h" #include "RimIdenticalGridCaseGroup.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - -#include "RimReservoirCellResultsCacher.h" -#include "RimResultSlot.h" - -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCaseCollection, "RimCaseCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 93383d0522..51c17c1a5d 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -17,20 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RigCaseCellResultsData.h" #include "RimLegendConfig.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RigCaseCellResultsData.h" + #include "cafPdmUiListEditor.h" +#include "cvfMath.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCellEdgeResultSlot, "CellEdgeResultSlot"); diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index abb2b6d3fc..ecfa62dbe5 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -17,13 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCellPropertyFilter.h" -#include "RimResultDefinition.h" -#include "cvfMath.h" -#include "RimCellPropertyFilterCollection.h" #include "RigCaseCellResultsData.h" -#include "cafPdmUiDoubleSliderEditor.h" +#include "RimCellPropertyFilterCollection.h" #include "RimReservoirCellResultsCacher.h" +#include "RimResultDefinition.h" + +#include "cafPdmUiDoubleSliderEditor.h" +#include "cvfAssert.h" +#include "cvfMath.h" namespace caf diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h index 02c7677a60..71a942b3ee 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h @@ -18,14 +18,7 @@ #pragma once -#include "cafPdmObject.h" -#include "cafPdmField.h" -#include "cafPdmDocument.h" -#include "cafAppEnum.h" - -#include "RimDefines.h" #include "RimCellFilter.h" -//#include "cvfStructGridGeometryGenerator.h" class RimReservoirView; class RimCellPropertyFilterCollection; @@ -34,10 +27,6 @@ class RimResultDefinition; class RigGridBase; class RigCaseCellResultsData; -namespace cvf -{ - //enum CellRangeFilter::CellStateType; -} //================================================================================================== /// @@ -81,5 +70,3 @@ class RimCellPropertyFilter : public RimCellFilter double m_minimumResultValue, m_maximumResultValue; }; - - diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp index b12923b5c5..9c4b2bcfb3 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp @@ -22,13 +22,6 @@ #include "RimResultDefinition.h" #include "RimResultSlot.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimCellRangeFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCellEdgeResultSlot.h" - CAF_PDM_SOURCE_INIT(RimCellPropertyFilterCollection, "CellPropertyFilters"); diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp index 2bb0fc64cf..4bc3f601d2 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp @@ -16,26 +16,19 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" -#include "RimReservoirView.h" + +#include "RigActiveCellInfo.h" #include "RigCaseData.h" +#include "RigGridBase.h" +#include "RigMainGrid.h" #include "RimCase.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "cafPdmUiSliderEditor.h" - +#include "cvfAssert.h" CAF_PDM_SOURCE_INIT(RimCellRangeFilter, "CellRangeFilter"); diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h index acb2372a87..fe4bbbc10e 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h @@ -18,11 +18,11 @@ #pragma once -#include "cafPdmField.h" -#include "cafPdmObject.h" -#include "cafPdmPointer.h" #include "RimCellFilter.h" +class RigGridBase; +class RigMainGrid; +class RimCellRangeFilterCollection; class RimReservoirView; namespace cvf @@ -30,10 +30,6 @@ namespace cvf class CellRangeFilter; } -class RimCellRangeFilterCollection; -class RigMainGrid; -class RigGridBase; - //================================================================================================== /// /// diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp index eb9bc8bbba..7d1a6ec91f 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp @@ -16,20 +16,12 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimCellRangeFilterCollection.h" + #include "RimCase.h" +#include "RigGridBase.h" #include "RimReservoirView.h" #include "RigCaseData.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimWellCollection.h" CAF_PDM_SOURCE_INIT(RimCellRangeFilterCollection, "CellRangeFilterCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index 858f936def..554d8d926b 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -17,34 +17,17 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimCommandObject.h" + #include "RiaApplication.h" #include "RimCalcScript.h" #include "RimProject.h" +#include "RimStatisticsCase.h" -#include "cafPdmUiTextEditor.h" -#include "cafPdmUiPushButtonEditor.h" #include "cafPdmDocument.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTextEditor.h" #include -#include "RimStatisticsCase.h" - -// Included due to template use in pdm fields -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimScriptCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimAnalysisModels.h" -#include "RimWellPathCollection.h" -#include "RimCaseCollection.h" - - CAF_PDM_SOURCE_INIT(RimCommandObject, "RimCommandObject"); diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.h b/ApplicationCode/ProjectDataModel/RimCommandObject.h index 4123802cda..25e40878fb 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.h +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.h @@ -22,9 +22,7 @@ #include "cvfObject.h" #include "cafPdmField.h" #include "cafPdmObject.h" -#include "cafPdmDocument.h" -#include //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimFault.h b/ApplicationCode/ProjectDataModel/RimFault.h index b85c18d7da..22bac08bf6 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.h +++ b/ApplicationCode/ProjectDataModel/RimFault.h @@ -23,8 +23,9 @@ #include "cafPdmPointer.h" #include "cvfBase.h" -#include "cvfColor3.h" -#include "cafPdmFieldCvfColor.h" + +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" class RigFault; diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 2de8ac55df..e634f26644 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -18,10 +18,6 @@ #include "RimFaultCollection.h" -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - #include "RiaApplication.h" #include "RiaPreferences.h" #include "RigCaseData.h" @@ -30,6 +26,9 @@ #include "RiuMainWindow.h" #include "RivColorTableArray.h" +#include "cafAppEnum.h" +#include "cafPdmFieldCvfColor.h" +#include "cafPdmFieldCvfMat4d.h" namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 0d2cb37b66..aacb41cd51 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -18,19 +18,21 @@ #pragma once +#include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmPointer.h" -#include "cafAppEnum.h" -#include - #include "cvfBase.h" -#include "cvfColor3.h" -class RimFault; +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" -class RimReservoirView; +#include "RimReservoirCellResultsCacher.h" + +#include +class RimFault; +class RimReservoirView; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 0b1708f315..86a64b0b19 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -18,33 +18,21 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RimIdenticalGridCaseGroup.h" -#include "RimCaseCollection.h" +#include "RigActiveCellInfo.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigGridManager.h" #include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RigCaseData.h" -#include "RigCaseCellResultsData.h" - +#include "RimResultCase.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" #include "RimStatisticsCase.h" -#include "RimResultCase.h" #include "cafProgressInfo.h" -#include "RigActiveCellInfo.h" -#include "RigActiveCellInfo.h" - -#include "RigGridManager.h" -#include "RimReservoirCellResultsCacher.h" - - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" - CAF_PDM_SOURCE_INIT(RimIdenticalGridCaseGroup, "RimIdenticalGridCaseGroup"); diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h index e3da03cc8e..31c66c8211 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h @@ -25,7 +25,6 @@ #include "RifReaderInterface.h" -//#include "RimStatisticsCaseCollection.h" class RimCaseCollection; class RimStatisticsCase; diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index e9ab1a607f..b1a77bf364 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -16,34 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimInputCase.h" -#include "RimInputPropertyCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include -#include "RimReservoirView.h" +#include "RiaPreferences.h" +#include "RifEclipseInputFileTools.h" #include "RifReaderEclipseInput.h" -#include "RigCaseData.h" +#include "RifReaderInterface.h" +#include "RifReaderMockModel.h" #include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimDefines.h" +#include "RimInputProperty.h" +#include "RimInputPropertyCollection.h" +#include "RimReservoirCellResultsCacher.h" -#include "RifReaderMockModel.h" -#include "RifEclipseInputFileTools.h" #include "cafProgressInfo.h" -#include "RiaApplication.h" -#include "RiaPreferences.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" - -#include "RimCellEdgeResultSlot.h" -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" +#include CAF_PDM_SOURCE_INIT(RimInputCase, "RimInputReservoir"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp index 95936e5f54..3aed9d899f 100644 --- a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp @@ -16,13 +16,10 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimInputProperty.h" -#include "cvfAssert.h" - #include "cafPdmUiLineEditor.h" +#include "cvfAssert.h" #include diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp index 5798253f13..8250191135 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp @@ -16,10 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimInputPropertyCollection.h" +#include "RimInputProperty.h" + +#include CAF_PDM_SOURCE_INIT(RimInputPropertyCollection, "RimInputPropertyCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h index 2e865fda76..302e97a50b 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h @@ -23,7 +23,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimInputProperty.h" +class RimInputProperty; //================================================================================================== diff --git a/ApplicationCode/ProjectDataModel/RimOilField.cpp b/ApplicationCode/ProjectDataModel/RimOilField.cpp index 8f078071de..13855a3962 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.cpp +++ b/ApplicationCode/ProjectDataModel/RimOilField.cpp @@ -16,33 +16,10 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimOilField.h" -#include "cafAppEnum.h" -#include "RimReservoirView.h" - -#include "RimIdenticalGridCaseGroup.h" - -#include "RiaApplication.h" -#include "RigGridManager.h" -#include "RigCaseData.h" -#include "RimResultCase.h" -#include "RimWellPathCollection.h" #include "RimAnalysisModels.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimStatisticsCase.h" +#include "RimWellPathCollection.h" CAF_PDM_SOURCE_INIT(RimOilField, "ResInsightOilField"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimOilField.h b/ApplicationCode/ProjectDataModel/RimOilField.h index 9b296aad83..925c20b378 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.h +++ b/ApplicationCode/ProjectDataModel/RimOilField.h @@ -18,13 +18,10 @@ #pragma once -#include "cafPdmDocument.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" -class RimCase; -class RigGridManager; -class RimIdenticalGridCaseGroup; -class RigMainGrid; -class RigCaseData; class RimWellPathCollection; class RimAnalysisModels; @@ -40,7 +37,6 @@ class RimOilField : public caf::PdmObject RimOilField(void); virtual ~RimOilField(void); - caf::PdmField analysisModels; - caf::PdmField wellPathCollection; - + caf::PdmField analysisModels; + caf::PdmField wellPathCollection; }; diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 357a18bfdc..03bd43fcfe 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -16,38 +16,22 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimProject.h" -#include "cafAppEnum.h" - -#include "RimOilField.h" -#include "RimAnalysisModels.h" - -#include "RimReservoirView.h" -#include "RimScriptCollection.h" -#include "RimIdenticalGridCaseGroup.h" #include "RiaApplication.h" #include "RiaVersionInfo.h" - -#include "RigGridManager.h" #include "RigCaseData.h" -#include "RimResultCase.h" +#include "RimAnalysisModels.h" +#include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimOilField.h" +#include "RimReservoirView.h" +#include "RimScriptCollection.h" #include "RimWellPathCollection.h" +#include "RimWellPathImport.h" - -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellCollection.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimStatisticsCase.h" +#include CAF_PDM_SOURCE_INIT(RimProject, "ResInsightProject"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 28c6b5f9fa..3226a0ee1e 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -19,8 +19,6 @@ #pragma once #include "cafPdmDocument.h" -#include "RimWellPathImport.h" -#include "RimCommandObject.h" class RimOilField; class RimCase; @@ -29,6 +27,8 @@ class RimScriptCollection; class RimIdenticalGridCaseGroup; class RigMainGrid; class RigCaseData; +class RimWellPathImport; +class RimCommandObject; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp index 9b3357a8e1..25bbd9f503 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp @@ -16,39 +16,20 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" -#include -#include -#include -#include -#include - #include "RimReservoirCellResultsCacher.h" + #include "RigCaseCellResultsData.h" -#include "RiaApplication.h" #include "RigMainGrid.h" -#include "RigCell.h" -#include "cafProgressInfo.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimCaseCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" #include "RimTools.h" +#include "cafProgressInfo.h" + +#include +#include +#include +#include +#include + CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorage, "ReservoirCellResultStorage"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h index f6f7a567f3..7208bcd83e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h @@ -18,15 +18,17 @@ #pragma once -#include -#include "cvfBase.h" -#include "cvfObject.h" +#include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" -#include "cafAppEnum.h" +#include "cvfBase.h" +#include "cvfObject.h" + #include "RimDefines.h" +#include + class RimReservoirCellResultsStorageEntryInfo; class RigCaseCellResultsData; class RifReaderInterface; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 3438706133..ddbbf10f36 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -16,66 +16,44 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimReservoirView.h" -#include "RiuViewer.h" -#include "cvfViewport.h" -#include "cvfModelBasicList.h" -#include "cvfPart.h" -#include "cvfDrawable.h" -#include "cvfScene.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include - - -#include "RimProject.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCaseCollection.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" #include "RimOilField.h" -#include "RimAnalysisModels.h" +#include "RimProject.h" +#include "RimResultSlot.h" #include "RimTernaryLegendConfig.h" - +#include "RimWell.h" +#include "RimWellCollection.h" +#include "RimWellPathCollection.h" #include "RiuMainWindow.h" -#include "RigGridBase.h" -#include "RigCaseData.h" -#include "RiaApplication.h" -#include "RiaPreferences.h" +#include "RiuViewer.h" +#include "RivReservoirPipesPartMgr.h" +#include "RivWellPathCollectionPartMgr.h" -#include "cafEffectGenerator.h" +#include "cafCadNavigation.h" +#include "cafCeetronPlusNavigation.h" #include "cafFrameAnimationControl.h" -#include "cvfStructGridGeometryGenerator.h" -#include "RigCaseCellResultsData.h" -#include "RivCellEdgeEffectGenerator.h" +#include "cvfDrawable.h" +#include "cvfModelBasicList.h" +#include "cvfOverlayScalarMapperLegend.h" +#include "cvfPart.h" +#include "cvfScene.h" +#include "cvfViewport.h" #include "cvfqtUtils.h" -#include "RivReservoirViewPartMgr.h" -#include "RivReservoirPipesPartMgr.h" -#include "cafCadNavigation.h" -#include "cafCeetronNavigation.h" -#include "RimCase.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RigGridScalarDataAccess.h" -#include "RimReservoirCellResultsCacher.h" -#include "RivWellPathCollectionPartMgr.h" -#include "cvfOverlayScalarMapperLegend.h" +#include -#include -#include "cafCeetronPlusNavigation.h" -#include "RimFaultCollection.h" -#include "RivTernarySaturationOverlayItem.h" namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index a45a6c2e1d..95ae186b5a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -17,40 +17,38 @@ ///////////////////////////////////////////////////////////////////////////////// #pragma once -#include "cafPdmObject.h" -#include "cafPdmField.h" + #include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cvfArray.h" #include "cvfBase.h" #include "cvfObject.h" +// Includes to make Pdm work for cvf::Color and cvf:Mat +#include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" - -#include -#include -#include "RimFaultCollection.h" +#include "RivReservoirViewPartMgr.h" +class RigActiveCellInfo; +class RigGridBase; +class RigGridCellFaceVisibilityFilter; +class Rim3dOverlayInfoConfig; class RimCase; -class RimResultSlot; class RimCellEdgeResultSlot; -class RimCellRangeFilter; -class RimCellRangeFilterCollection; class RimCellPropertyFilter; class RimCellPropertyFilterCollection; -class Rim3dOverlayInfoConfig; +class RimCellRangeFilter; +class RimCellRangeFilterCollection; +class RimFaultCollection; +class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; +class RimResultSlot; class RimWellCollection; -class RigActiveCellInfo; - -#include "RivReservoirViewPartMgr.h" -class RivReservoirPipesPartMgr; - class RiuViewer; -class RigGridBase; -class RigGridCellFaceVisibilityFilter; -class RimReservoirCellResultsStorage; +class RivReservoirPipesPartMgr; namespace cvf { diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index d0d72587fa..626f4cf15a 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -16,41 +16,25 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "cafProgressInfo.h" -#include "cafPdmSettings.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmUiPropertyDialog.h" - #include "RimResultCase.h" -#include "RigCaseData.h" + +#include "RiaPreferences.h" +#include "RifEclipseOutputFileTools.h" #include "RifReaderEclipseOutput.h" -#include "RigCaseCellResultsData.h" -#include "RimReservoirView.h" #include "RifReaderMockModel.h" -#include "RifReaderEclipseInput.h" - +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RimMockModelSettings.h" #include "RimProject.h" -#include "RifEclipseOutputFileTools.h" -#include "RiaApplication.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCaseCollection.h" #include "RimReservoirCellResultsCacher.h" -#include "RimWellPathCollection.h" - -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include "RiaPreferences.h" -#include "RimMockModelSettings.h" + +#include "cafPdmSettings.h" +#include "cafPdmUiPropertyDialog.h" +#include "cafProgressInfo.h" + +#include +#include +#include CAF_PDM_SOURCE_INIT(RimResultCase, "EclipseCase"); //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.h b/ApplicationCode/ProjectDataModel/RimResultCase.h index 0463cdf508..9d768fc36b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.h +++ b/ApplicationCode/ProjectDataModel/RimResultCase.h @@ -18,10 +18,6 @@ #pragma once -#include "cvfBase.h" -#include "cvfObject.h" -#include "cafPdmField.h" -#include "cafPdmObject.h" #include "RimCase.h" class RifReaderInterface; diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 110036ffb8..4e5873dda3 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -16,27 +16,15 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" - #include "RimResultDefinition.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimReservoirView.h" -#include "RimCase.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigMainGrid.h" -#include "cafPdmUiListEditor.h" - +#include "RimCase.h" +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "cafPdmUiListEditor.h" CAF_PDM_SOURCE_INIT(RimResultDefinition, "ResultDefinition"); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index 3e7e463f7d..f399262ee2 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -18,10 +18,11 @@ #pragma once -#include "cafPdmObject.h" +#include "RimDefines.h" + #include "cafAppEnum.h" #include "cafPdmField.h" -#include "RimDefines.h" +#include "cafPdmObject.h" #include "cafPdmPointer.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index 38108eaf5f..dc7af09867 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -16,8 +16,6 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimResultSlot.h" #include "RimReservoirView.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index afa92bb3a3..390b3cc053 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -18,9 +18,6 @@ #pragma once -#include "cafAppEnum.h" -#include "cafPdmObject.h" - #include "RimDefines.h" #include "RimLegendConfig.h" #include "RimResultDefinition.h" diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 2e597e678e..17e3053bd6 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -16,15 +16,16 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - - #include "RimScriptCollection.h" -#include "cafPdmField.h" -#include "cafUtils.h" -#include "RiuMainWindow.h" + +#include "RimCalcScript.h" #include "RimUiTreeModelPdm.h" +#include "RiuMainWindow.h" + #include "cafPdmUiFilePathEditor.h" +#include "cafUtils.h" + +#include CAF_PDM_SOURCE_INIT(RimScriptCollection, "ScriptLocation"); diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.h b/ApplicationCode/ProjectDataModel/RimScriptCollection.h index 0c030e9be6..88c4bcffa3 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.h +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.h @@ -20,7 +20,8 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimCalcScript.h" + +class RimCalcScript; namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index e942b18b0d..dba119e9b7 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -16,35 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimStatisticsCase.h" -#include "RimReservoirView.h" -#include "cafPdmUiOrdering.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RigCaseData.h" + #include "RigCaseCellResultsData.h" -#include "RimStatisticsCaseEvaluator.h" -#include "RigMainGrid.h" -#include "cafPdmUiTextEditor.h" -#include "cafPdmUiLineEditor.h" -#include "cafPdmUiPushButtonEditor.h" -#include "RiuMainWindow.h" -#include "RimUiTreeModelPdm.h" -#include "cafProgressInfo.h" +#include "RigCaseData.h" #include "RimCaseCollection.h" - - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" +#include "RimIdenticalGridCaseGroup.h" +#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" +#include "RimStatisticsCaseEvaluator.h" +#include "RimUiTreeModelPdm.h" #include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "RiuMainWindow.h" -#include "RimReservoirCellResultsCacher.h" +#include "cafPdmUiPushButtonEditor.h" +#include "cafPdmUiTextEditor.h" +#include "cafProgressInfo.h" namespace caf { template<> diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp index 40daa70a63..a5fb4e94a6 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp @@ -16,23 +16,9 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "RimReservoirView.h" - #include "RimStatisticsCaseCollection.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimCaseCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimIdenticalGridCaseGroup.h" CAF_PDM_SOURCE_INIT(RimStatisticsCaseCollection, "RimStatisticalCollection"); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h index e7c0059363..699c28a5c6 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h @@ -23,8 +23,8 @@ #include "cafPdmField.h" #include "cafPdmObject.h" -#include "RimStatisticsCase.h" - +class RimStatisticsCase; +class RimIdenticalGridCaseGroup; //================================================================================================== @@ -44,6 +44,4 @@ class RimStatisticsCaseCollection : public caf::PdmObject RimIdenticalGridCaseGroup* parentCaseGroup(); -private: - }; diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 4d8a499d8c..6d49322ed4 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -15,29 +15,17 @@ // for more details. // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimStatisticsCaseEvaluator.h" + #include "RigCaseCellResultsData.h" -#include "RimReservoirView.h" -#include "RimCase.h" #include "RigCaseData.h" #include "RigStatisticsMath.h" #include "RimReservoirCellResultsCacher.h" +#include "cafProgressInfo.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" - -//#include "RigCaseData.h" #include -#include "cafProgressInfo.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 7c825c8b8d..906ad17c7d 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -18,15 +18,13 @@ #pragma once -#include "cvfBase.h" -#include "cvfObject.h" -#include "cvfCollection.h" +#include "RimDefines.h" +#include "RimStatisticsCase.h" + #include #include #include -#include "RimDefines.h" -#include "RimStatisticsCase.h" class RimCase; class RigCaseData; diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 3ab3439da0..453bc259ba 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -16,30 +16,12 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimTools.h" -#include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimWellPathCollection.h" -#include "RivWellPathPartMgr.h" -#include "RimWellPathCollection.h" -#include "RimCellRangeFilterCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" #include "RiaApplication.h" +#include "RimProject.h" + +#include //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimTools.h b/ApplicationCode/ProjectDataModel/RimTools.h index 0d301ff002..e39f961043 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.h +++ b/ApplicationCode/ProjectDataModel/RimTools.h @@ -18,7 +18,7 @@ #pragma once -class RimProject; +#include class RimTools { diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index 68ec961b7c..dc340cb014 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -16,47 +16,34 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - #include "RimUiTreeModelPdm.h" -#include "RimCellRangeFilter.h" -#include "RimCellRangeFilterCollection.h" - -#include "cafPdmObject.h" -#include "RimCellPropertyFilter.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimReservoirView.h" -#include "RiuViewer.h" -#include "RimCalcScript.h" #include "RiaApplication.h" -#include "RiuMainWindow.h" -#include "RimInputProperty.h" -#include "RimInputPropertyCollection.h" -#include "cafPdmField.h" -#include "RimInputCase.h" -#include "RimStatisticsCase.h" -#include "RimResultCase.h" #include "RigGridManager.h" +#include "RimAnalysisModels.h" #include "RimCase.h" -#include "RigCaseData.h" -#include "RimMimeData.h" #include "RimCaseCollection.h" +#include "RimCellPropertyFilterCollection.h" +#include "RimCellRangeFilterCollection.h" #include "RimIdenticalGridCaseGroup.h" +#include "RimInputCase.h" +#include "RimInputProperty.h" +#include "RimInputPropertyCollection.h" +#include "RimMimeData.h" +#include "RimOilField.h" #include "RimProject.h" +#include "RimReservoirView.h" +#include "RimResultCase.h" #include "RimScriptCollection.h" +#include "RimStatisticsCase.h" +#include "RimUiTreeView.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" #include "RimWellPathCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include "RimUiTreeView.h" +#include "cvfAssert.h" + +#include +#include //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 60bde2559f..2887bbd1c4 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -64,6 +64,8 @@ #include "RimProject.h" #include "RimOilField.h" #include "RimAnalysisModels.h" +#include "RimInputProperty.h" +#include "RigSingleWellResultsData.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWell.cpp b/ApplicationCode/ProjectDataModel/RimWell.cpp index 76f740cbe2..9a3a221ecc 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.cpp +++ b/ApplicationCode/ProjectDataModel/RimWell.cpp @@ -16,22 +16,13 @@ // ///////////////////////////////////////////////////////////////////////////////// -//#include "RiaStdInclude.h" #include "RimWell.h" - -#include "cafAppEnum.h" -#include "cafPdmField.h" -#include "RivReservoirViewPartMgr.h" +#include "RigSingleWellResultsData.h" #include "RimReservoirView.h" #include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimCellRangeFilterCollection.h" + +#include "cvfMath.h" CAF_PDM_SOURCE_INIT(RimWell, "Well"); diff --git a/ApplicationCode/ProjectDataModel/RimWell.h b/ApplicationCode/ProjectDataModel/RimWell.h index 32e724e536..1e591f85c7 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.h +++ b/ApplicationCode/ProjectDataModel/RimWell.h @@ -22,11 +22,15 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "RigSingleWellResultsData.h" +#include "cvfObject.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +class RigSingleWellResultsData; class RimReservoirView; + //================================================================================================== /// /// diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp index 0c9783a885..710e1948a3 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp @@ -18,19 +18,13 @@ #include "RimWellCollection.h" -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirView.h" - -#include "RimResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" - -#include "Rim3dOverlayInfoConfig.h" -#include "RimCellEdgeResultSlot.h" #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigSingleWellResultsData.h" +#include "RimReservoirView.h" +#include "RimWell.h" +#include "RivReservoirViewPartMgr.h" + namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.h b/ApplicationCode/ProjectDataModel/RimWellCollection.h index 515574bf41..8ca7232006 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.h @@ -22,11 +22,14 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include -#include "RimWell.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +#include class RimReservoirView; +class RimWell; //================================================================================================== /// diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 18e1b7bb2c..29ed5040b9 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -16,37 +16,16 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - - -#include "cafAppEnum.h" -#include "cafPdmField.h" -#include "RiaApplication.h" - #include "RimWellPath.h" -#include "RimWellPathCollection.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RivWellPathPartMgr.h" + #include "RifJsonEncodeDecode.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" - -#include -#include +#include "RimProject.h" #include "RimTools.h" +#include "RimWellPathCollection.h" +#include "RivWellPathPartMgr.h" +#include +#include CAF_PDM_SOURCE_INIT(RimWellPath, "WellPath"); diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 4d25a145b9..068f84d4f8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -22,7 +22,10 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" + +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + #include "RigWellPath.h" class RimProject; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index 5483feee76..c76a5f0df3 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -16,34 +16,20 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" - -#include "cafAppEnum.h" -#include "cafPdmFieldCvfColor.h" -#include "cafProgressInfo.h" - #include "RimWellPathCollection.h" -#include "RimWellPath.h" -#include "RivWellPathCollectionPartMgr.h" -#include "RimProject.h" -#include "RimCase.h" -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimReservoirView.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "RimOilField.h" -#include "RimAnalysisModels.h" -#include #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RivWellPathCollectionPartMgr.h" + +#include "cafProgressInfo.h" + +#include +#include + +#include namespace caf { diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h index b734bd5f97..7d30e10fca 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h @@ -22,12 +22,20 @@ #include "cafPdmObject.h" #include "cafPdmPointer.h" #include "cafAppEnum.h" -#include -#include "RimWellPath.h" +// Include to make Pdm work for cvf::Color +#include "cafPdmFieldCvfColor.h" + +#include "cvfObject.h" + +#include class RivWellPathCollectionPartMgr; class RimWellPathAsciiFileReader; +class RimWellPath; +class RimProject; +class RigWellPath; + //================================================================================================== /// diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index fa5fc419fd..043e18c5eb 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -43,6 +43,7 @@ #include "RiaApplication.h" #include "RiaPreferences.h" #include "RiaSocketDataTransfer.h" +#include "RimInputProperty.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 7a2d8f163d..18f509d09c 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -19,51 +19,42 @@ #include "RiaStdInclude.h" #include "RiuMainWindow.h" -#include "RiaApplication.h" -#include "RimProject.h" +#include "RiaApplication.h" +#include "RiaBaseDefs.h" +#include "RiaPreferences.h" +#include "RiaRegressionTest.h" +#include "RigCaseCellResultsData.h" #include "RimAnalysisModels.h" +#include "RimCase.h" +#include "RimCaseCollection.h" +#include "RimCellPropertyFilterCollection.h" +#include "RimCommandObject.h" +#include "RimFaultCollection.h" #include "RimOilField.h" +#include "RimProject.h" +#include "RimReservoirCellResultsCacher.h" #include "RimReservoirView.h" -#include "RimUiTreeView.h" -#include "RimCase.h" #include "RimResultSlot.h" -#include "RimCellPropertyFilterCollection.h" +#include "RimTools.h" +#include "RimUiTreeModelPdm.h" +#include "RimUiTreeView.h" #include "RimWellCollection.h" -#include "RimReservoirCellResultsCacher.h" -#include "RimCaseCollection.h" #include "RimWellPathCollection.h" - -#include "RimUiTreeModelPdm.h" - -#include "RiaBaseDefs.h" -#include "RiuViewer.h" -#include "RiuResultInfoPanel.h" -#include "RiuProcessMonitor.h" +#include "RimWellPathImport.h" #include "RiuMultiCaseImportDialog.h" +#include "RiuProcessMonitor.h" +#include "RiuResultInfoPanel.h" +#include "RiuViewer.h" +#include "RiuWellImportWizard.h" -#include "RiaPreferences.h" - -#include "RigCaseCellResultsData.h" - -#include "cafAnimationToolBar.h" -#include "cafPdmUiPropertyView.h" #include "cafAboutDialog.h" -#include "cvfTimer.h" - +#include "cafAnimationToolBar.h" #include "cafPdmFieldCvfMat4d.h" - -#include "RimIdenticalGridCaseGroup.h" -#include "RimScriptCollection.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RiuWellImportWizard.h" -#include "RimCalcScript.h" -#include "RimTools.h" -#include "RiaRegressionTest.h" #include "cafPdmUiPropertyDialog.h" +#include "cafPdmUiPropertyView.h" +#include "cvfTimer.h" //================================================================================================== From ecc7e9de59ae84973403df841d9d7a418e5353ee Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:26:26 +0200 Subject: [PATCH 140/346] Linux fix: Added missing include --- ApplicationCode/ProjectDataModel/RimCommandObject.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.h b/ApplicationCode/ProjectDataModel/RimCommandObject.h index 25e40878fb..81417ac7d5 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.h +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.h @@ -22,6 +22,7 @@ #include "cvfObject.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmDocument.h" //-------------------------------------------------------------------------------------------------- From 9ffb919fb5f1e74fb395e82e24581da2f9cb9a3b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 10:39:49 +0200 Subject: [PATCH 141/346] Linux fix: Added missing include --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ddbbf10f36..47f8977158 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -54,6 +54,8 @@ #include +#include + namespace caf { From b13c2621daa42731e69313b9a61cea2ab8f5468f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 02:01:02 -0700 Subject: [PATCH 142/346] Linux fixes: Added missing includes --- .../ModelVisualization/RivWellPathCollectionPartMgr.h | 4 +++- ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp | 1 + ApplicationCode/ReservoirDataModel/RigMainGrid.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index e5ac6a5d0e..88b6dd86ca 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -18,13 +18,15 @@ #pragma once - +#include "cvfBase.h" #include "cvfCollection.h" #include "cafPdmPointer.h" #include "cvfVector3.h" #include "cvfBoundingBox.h" #include "cvfTransform.h" +#include "cafPdmPointer.h" + class RimWellPathCollection; class RimProject; class RivWellPathPartMgr; diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index c76a5f0df3..edc4c74fcf 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -30,6 +30,7 @@ #include #include +#include namespace caf { diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 10d6ae9aaf..db11222984 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -296,7 +296,7 @@ void RigMainGrid::calculateFaults() // Add as fault face only if the grid index is less than the neighbors - if (gcIdx < neighborGlobalCellIdx) + if (static_cast(gcIdx) < neighborGlobalCellIdx) { { RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborGlobalCellIdx); From f259f21b32ff73aeebb853632e28052347e8e5b1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2014 14:03:17 +0200 Subject: [PATCH 143/346] Renamed file to match class name for RimReservoirCellResultStorage --- ApplicationCode/Application/RiaApplication.cpp | 2 +- ApplicationCode/Application/RiaProjectModifier.cpp | 2 +- .../ModelVisualization/RivCellEdgeEffectGenerator.cpp | 2 +- ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivGridPartMgr.cpp | 2 +- .../ModelVisualization/RivReservoirViewPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp | 2 +- ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp | 2 +- ApplicationCode/ProjectDataModel/CMakeLists_files.cmake | 4 ++-- ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp | 2 +- ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp | 2 +- ApplicationCode/ProjectDataModel/RimFaultCollection.h | 2 +- .../ProjectDataModel/RimIdenticalGridCaseGroup.cpp | 2 +- ApplicationCode/ProjectDataModel/RimInputCase.cpp | 2 +- ...llResultsCacher.cpp => RimReservoirCellResultsStorage.cpp} | 2 +- ...irCellResultsCacher.h => RimReservoirCellResultsStorage.h} | 0 ApplicationCode/ProjectDataModel/RimResultCase.cpp | 2 +- ApplicationCode/ProjectDataModel/RimResultDefinition.cpp | 2 +- ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp | 2 +- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 2 +- ApplicationCode/ProjectDataModel/RimUiTreeView.cpp | 2 +- ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaGeometryCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp | 2 +- ApplicationCode/SocketInterface/RiaSocketServer.cpp | 2 +- ApplicationCode/SocketInterface/RiaSocketTools.cpp | 2 +- ApplicationCode/SocketInterface/RiaWellDataCommands.cpp | 2 +- ApplicationCode/UserInterface/RiuMainWindow.cpp | 2 +- ApplicationCode/UserInterface/RiuViewer.cpp | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) rename ApplicationCode/ProjectDataModel/{RimReservoirCellResultsCacher.cpp => RimReservoirCellResultsStorage.cpp} (99%) rename ApplicationCode/ProjectDataModel/{RimReservoirCellResultsCacher.h => RimReservoirCellResultsStorage.h} (100%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 61862f5b8c..472a2b9a23 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -68,7 +68,7 @@ #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" diff --git a/ApplicationCode/Application/RiaProjectModifier.cpp b/ApplicationCode/Application/RiaProjectModifier.cpp index af5a1d57e2..0840d24be2 100644 --- a/ApplicationCode/Application/RiaProjectModifier.cpp +++ b/ApplicationCode/Application/RiaProjectModifier.cpp @@ -32,7 +32,7 @@ #include "RimScriptCollection.h" #include "RimCellPropertyFilterCollection.h" #include "RimCellPropertyFilter.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" #include "RimCellRangeFilterCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index a195179b51..8c1b6ed601 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -55,7 +55,7 @@ #include "RigCaseData.h" #include "RigActiveCellInfo.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafPdmFieldCvfMat4d.h" #include "cafPdmFieldCvfColor.h" diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 7da6f4c85d..731faf4dae 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -39,7 +39,7 @@ #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cvfDrawableText.h" #include "cvfqtUtils.h" #include "cvfPrimitiveSetIndexedUInt.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ee795b0004..d8edaca5b4 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -43,7 +43,7 @@ #include "RigCaseData.h" #include "RimCase.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimTernaryLegendConfig.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 4dbd4bb183..fc1fcddc26 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -36,7 +36,7 @@ #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp index 3878329c7c..cbd0d78d8d 100644 --- a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp @@ -41,7 +41,7 @@ #include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimLegendConfig.h" diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index 1ba6b3a2a1..f8b5542ab3 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -23,7 +23,7 @@ #include "RimCase.h" #include "RimProject.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimIdenticalGridCaseGroup.h" #include "RimScriptCollection.h" #include "RimCaseCollection.h" diff --git a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp index 546c9ef627..8c2eae1287 100644 --- a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp @@ -38,7 +38,7 @@ #include "RimReservoirView.h" #include "RimWell.h" #include "RimWellCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 1b265e3dd2..2abc7eacba 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -39,7 +39,7 @@ ${CEE_CURRENT_LIST_DIR}RimBinaryExportSettings.h ${CEE_CURRENT_LIST_DIR}Rim3dOverlayInfoConfig.h ${CEE_CURRENT_LIST_DIR}RimUiTreeModelPdm.h ${CEE_CURRENT_LIST_DIR}RimUiTreeView.h -${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsCacher.h +${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsStorage.h ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.h ${CEE_CURRENT_LIST_DIR}RimMimeData.h ${CEE_CURRENT_LIST_DIR}RimCommandObject.h @@ -85,7 +85,7 @@ ${CEE_CURRENT_LIST_DIR}RimBinaryExportSettings.cpp ${CEE_CURRENT_LIST_DIR}Rim3dOverlayInfoConfig.cpp ${CEE_CURRENT_LIST_DIR}RimUiTreeModelPdm.cpp ${CEE_CURRENT_LIST_DIR}RimUiTreeView.cpp -${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsCacher.cpp +${CEE_CURRENT_LIST_DIR}RimReservoirCellResultsStorage.cpp ${CEE_CURRENT_LIST_DIR}RimStatisticsCaseEvaluator.cpp ${CEE_CURRENT_LIST_DIR}RimMimeData.cpp ${CEE_CURRENT_LIST_DIR}RimCommandObject.cpp diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 2ffb186033..f08a803814 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -23,7 +23,7 @@ #include "RimCase.h" #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 90f1115fc5..c386fed410 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -24,7 +24,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilter.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 51c17c1a5d..48cbe7ffc2 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -20,7 +20,7 @@ #include "RigCaseCellResultsData.h" #include "RimLegendConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "cafPdmUiListEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index ecfa62dbe5..7d73bb92a8 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -20,7 +20,7 @@ #include "RigCaseCellResultsData.h" #include "RimCellPropertyFilterCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimResultDefinition.h" #include "cafPdmUiDoubleSliderEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index aacb41cd51..095a65f96b 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -27,7 +27,7 @@ // Include to make Pdm work for cvf::Color #include "cafPdmFieldCvfColor.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 86a64b0b19..442dd7886f 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -26,7 +26,7 @@ #include "RimCase.h" #include "RimCaseCollection.h" #include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultCase.h" #include "RimResultSlot.h" diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index b1a77bf364..adc91355bf 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -28,7 +28,7 @@ #include "RimDefines.h" #include "RimInputProperty.h" #include "RimInputPropertyCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp similarity index 99% rename from ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp rename to ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 25bbd9f503..c46fe8b347 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseCellResultsData.h" #include "RigMainGrid.h" diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h similarity index 100% rename from ApplicationCode/ProjectDataModel/RimReservoirCellResultsCacher.h rename to ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index 626f4cf15a..8d1041fa63 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -26,7 +26,7 @@ #include "RigCaseData.h" #include "RimMockModelSettings.h" #include "RimProject.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafPdmSettings.h" #include "cafPdmUiPropertyDialog.h" diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 4e5873dda3..7d16b522e6 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -21,7 +21,7 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimCase.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "cafPdmUiListEditor.h" diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index dba119e9b7..51e8d45859 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -22,7 +22,7 @@ #include "RigCaseData.h" #include "RimCaseCollection.h" #include "RimIdenticalGridCaseGroup.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimStatisticsCaseEvaluator.h" diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 6d49322ed4..ecb06dd92f 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -21,7 +21,7 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigStatisticsMath.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 2887bbd1c4..0b7331ce8a 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -59,7 +59,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimWellCollection.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "Rim3dOverlayInfoConfig.h" #include "RimProject.h" #include "RimOilField.h" diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index e81b9db3ea..a10762e2a6 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -30,7 +30,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index c76bc690ae..a682b5b3cb 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -27,7 +27,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp index 660effb8b5..35c221d4fd 100644 --- a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp @@ -27,7 +27,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RigCaseData.h" diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 043e18c5eb..85d154a2a4 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -26,7 +26,7 @@ #include "RigCaseData.h" #include "RigCaseCellResultsData.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.cpp b/ApplicationCode/SocketInterface/RiaSocketServer.cpp index 1258030bcf..f27c0679b0 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketServer.cpp @@ -41,7 +41,7 @@ #include "RimScriptCollection.h" #include "RimCaseCollection.h" #include "RimWellPathCollection.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseData.h" #include "RigCaseCellResultsData.h" diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.cpp b/ApplicationCode/SocketInterface/RiaSocketTools.cpp index 967c0b43b4..c275994254 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketTools.cpp @@ -34,7 +34,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp index 4c9d935206..83fc17b77e 100644 --- a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp @@ -25,7 +25,7 @@ #include "RigCaseData.h" #include "RigCaseCellResultsData.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" #include "RimInputPropertyCollection.h" diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 18f509d09c..e8f7ca5c10 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -33,7 +33,7 @@ #include "RimFaultCollection.h" #include "RimOilField.h" #include "RimProject.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimTools.h" diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index e58a7bb8a7..71489243e2 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -35,7 +35,7 @@ #include "RimUiTreeModelPdm.h" -#include "RimReservoirCellResultsCacher.h" +#include "RimReservoirCellResultsStorage.h" #include "RigCaseData.h" From 430f95d52a37d8cf7fcdb441e22ca74a1018129e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 07:27:00 +0200 Subject: [PATCH 144/346] Rename and simplified control of fault visibility --- .../RivReservoirFaultsPartMgr.cpp | 7 ++++- .../ProjectDataModel/RimReservoirView.cpp | 30 ++++++------------- .../ProjectDataModel/RimReservoirView.h | 2 +- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index edf8642a9c..ff01f2bd59 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -101,7 +101,12 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) CVF_ASSERT(rivFaultPart.notNull()); // Parts that is overridden by the grid settings - bool forceDisplayOfFault = isShowingGrid; + bool forceDisplayOfFault = false; + if (!m_faultCollection->showFaultsOutsideFilters()) + { + forceDisplayOfFault = isShowingGrid; + } + if (m_forceVisibility) { forceDisplayOfFault = true; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 47f8977158..73ee88346a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -615,7 +615,7 @@ void RimReservoirView::createDisplayModel() if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) { - std::vector faultGeometryTypesToAppend = visibleFaultParts(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); RivReservoirViewPartMgr::ReservoirGeometryCacheType faultLabelType = m_reservoirGridPartManager->geometryTypeForFaultLabels(faultGeometryTypesToAppend); @@ -630,7 +630,6 @@ void RimReservoirView::createDisplayModel() } updateFaultForcedVisibility(); - } // Compute triangle count, Debug only @@ -709,7 +708,7 @@ void RimReservoirView::updateCurrentTimeStep() if (faultCollection()->showFaultsOutsideFilters) { - std::vector faultGeometryTypesToAppend = visibleFaultParts(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); for (size_t i = 0; i < faultGeometryTypesToAppend.size(); i++) { @@ -1941,31 +1940,20 @@ void RimReservoirView::updateFaultForcedVisibility() // As fault geometry is visible in grid visualization mode, fault geometry must be forced visible // even if the fault item is disabled in project tree view - caf::FixedArray forceOn; - - for (size_t i = 0; i < RivReservoirViewPartMgr::PROPERTY_FILTERED; i++) - { - forceOn[i] = false; - } - - std::vector faultParts = visibleFaultParts(); - for (size_t i = 0; i < faultParts.size(); i++) + if (!faultCollection->showFaultCollection) { - forceOn[faultParts[i]]; + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::ALL_WELL_CELLS, true); } - for (size_t i = 0; i < RivReservoirViewPartMgr::PROPERTY_FILTERED; i++) - { - RivReservoirViewPartMgr::ReservoirGeometryCacheType cacheType = (RivReservoirViewPartMgr::ReservoirGeometryCacheType)i; - - m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(cacheType, forceOn[i]); - } + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::RANGE_FILTERED, true); + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::VISIBLE_WELL_FENCE_CELLS, true); + m_reservoirGridPartManager->setFaultForceVisibilityForGeometryType(RivReservoirViewPartMgr::VISIBLE_WELL_FENCE_CELLS_OUTSIDE_RANGE_FILTER, true); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RimReservoirView::visibleFaultParts() const +std::vector RimReservoirView::visibleFaultGeometryTypes() const { std::vector faultParts; @@ -2043,7 +2031,7 @@ std::vector RimReservoirVie void RimReservoirView::updateFaultColors() { // Update all fault geometry - std::vector faultGeometriesToRecolor = visibleFaultParts(); + std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 95ae186b5a..4c37031753 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -191,7 +191,7 @@ class RimReservoirView : public caf::PdmObject void updateStaticCellColors(unsigned short geometryType); void updateLegends(); - std::vector visibleFaultParts() const; + std::vector visibleFaultGeometryTypes() const; void updateFaultForcedVisibility(); void updateFaultColors(); From 4189719b87b73d9204fcc8338abd28026e633f1b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 18:25:00 +0200 Subject: [PATCH 145/346] Moved update for force visibility before retrieving display parts --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 73ee88346a..6d6c7ac57e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -615,6 +615,8 @@ void RimReservoirView::createDisplayModel() if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) { + updateFaultForcedVisibility(); + std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); RivReservoirViewPartMgr::ReservoirGeometryCacheType faultLabelType = m_reservoirGridPartManager->geometryTypeForFaultLabels(faultGeometryTypesToAppend); @@ -629,7 +631,6 @@ void RimReservoirView::createDisplayModel() m_reservoirGridPartManager->appendFaultLabelsStaticGeometryPartsToModel(frameModels[frameIdx].p(), faultLabelType); } - updateFaultForcedVisibility(); } // Compute triangle count, Debug only From cf14cc55fdfa81b7a64d0d112933187c8d9a6120 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 13 Jun 2014 18:25:48 +0200 Subject: [PATCH 146/346] Create geometry if needed before accessing fault parts --- .../ModelVisualization/RivReservoirViewPartMgr.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index fc1fcddc26..8f8e095c3e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -906,6 +906,10 @@ RivReservoirViewPartMgr::ReservoirGeometryCacheType RivReservoirViewPartMgr::geo //-------------------------------------------------------------------------------------------------- void RivReservoirViewPartMgr::appendFaultLabelsStaticGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType) { + if (m_geometriesNeedsRegen[geometryType]) + { + createGeometry(geometryType); + } m_geometries[geometryType].appendFaultLabelPartsToModel(model); } @@ -922,5 +926,9 @@ void RivReservoirViewPartMgr::appendFaultLabelsDynamicGeometryPartsToModel(cvf:: //-------------------------------------------------------------------------------------------------- void RivReservoirViewPartMgr::setFaultForceVisibilityForGeometryType(ReservoirGeometryCacheType geometryType, bool forceVisibility) { + if (m_geometriesNeedsRegen[geometryType]) + { + createGeometry(geometryType); + } m_geometries[geometryType].setFaultForceVisibility(forceVisibility); } From 9fd4c268d88181a8be1ed4801524be9aea664037 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 09:10:45 +0200 Subject: [PATCH 147/346] Adjusted file unit test --- .../RifReaderEclipseOutput-Test.cpp | 64 +++++++++++++++++-- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp index d1fbe43b49..59739e33b2 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp @@ -27,7 +27,7 @@ #include "ecl_file.h" #include "RifEclipseOutputFileTools.h" #include "RigCaseCellResultsData.h" - +#include "RifEclipseUnifiedRestartFileAccess.h" @@ -35,15 +35,14 @@ #if 0 + TEST(RigReservoirTest, FileOutputToolsTest) { - cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; - cvf::ref reservoir = new RigReservoir; - // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.EGRID"); - QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +// QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); - ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data()); + ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data(), ECL_FILE_CLOSE_STREAM); EXPECT_TRUE(ertFile); @@ -53,7 +52,6 @@ TEST(RigReservoirTest, FileOutputToolsTest) EXPECT_TRUE(keywords.size() == keywordDataItemCounts.size()); - qDebug() << "Keyword - Number of data items"; for (int i = 0; i < keywords.size(); i++) { @@ -66,6 +64,58 @@ TEST(RigReservoirTest, FileOutputToolsTest) } +TEST(RigReservoirTest, UnifiedTestFile) +{ + + // Location of test dataset received from Håkon Høgstøl in July 2011 with 10k active cells +#ifdef WIN32 + QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +#else + QString filename("/mnt/hgfs/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); +#endif + + { + cvf::ref restartFile = new RifEclipseUnifiedRestartFileAccess(); + + QStringList fileNameList; + fileNameList << filename; + restartFile->setRestartFiles(fileNameList); + restartFile->open(); + + QStringList resultNames; + std::vector resultDataItemCounts; + restartFile->resultNames(&resultNames, &resultDataItemCounts); + + for (int i = 0; i < resultNames.size(); i++) + { + qDebug() << "Result names\n" << resultNames[i] << " - " << resultDataItemCounts[i]; + } + + std::vector tsteps = restartFile->timeSteps(); + + qDebug() << "Time step texts\n"; + for (int i = 0; i < tsteps.size(); i++) + { + qDebug() << tsteps[i].toString(); + } + + /* + std::vector resultValues; + size_t timeStep = 0; + restartFile->results(resultNames[0], timeStep, &resultValues); + + size_t i; + for (i = 0; i < 500; i++) + { + qDebug() << resultValues[i]; + } + */ + } + +} + + + void buildResultInfoString(RigReservoir* reservoir, RifReaderInterface::PorosityModelResultType porosityModel, RimDefines::ResultCatType resultType) { RigCaseCellResultsData* matrixResults = reservoir->results(porosityModel); From 57f1da1675d3b7c78239cbc2a6257089c43c1981 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 12:36:22 +0200 Subject: [PATCH 148/346] Map result color on fault if fault is disabled by user --- .../RivReservoirFaultsPartMgr.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index ff01f2bd59..8616541032 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -166,16 +166,18 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { - if (m_faultCollection->showResultsOnFaults()) + for (size_t i = 0; i < m_faultCollection->faults.size(); i++) { - for (size_t i = 0; i < m_faultParts.size(); i++) + RimFault* rimFault = m_faultCollection->faults[i]; + + if (m_faultCollection->showFaultCollection && rimFault->showFault && !m_faultCollection->showResultsOnFaults()) { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + m_faultParts[i]->applySingleColorEffect(); + } + else + { + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } - } - else - { - applySingleColorEffect(); } } From ff674d8eb0d72dd9948a71c5b5a1b10a7ded345a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 13:26:43 +0200 Subject: [PATCH 149/346] Always show result color when showing grid --- .../RivReservoirFaultsPartMgr.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 8616541032..48e73ff06f 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -107,7 +107,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) forceDisplayOfFault = isShowingGrid; } - if (m_forceVisibility) + if (m_forceVisibility && isShowingGrid) { forceDisplayOfFault = true; } @@ -166,17 +166,26 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { + bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); + for (size_t i = 0; i < m_faultCollection->faults.size(); i++) { RimFault* rimFault = m_faultCollection->faults[i]; - if (m_faultCollection->showFaultCollection && rimFault->showFault && !m_faultCollection->showResultsOnFaults()) + if (isShowingGrid) { - m_faultParts[i]->applySingleColorEffect(); + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } else { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + if (m_faultCollection->showResultsOnFaults()) + { + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + } + else + { + m_faultParts[i]->applySingleColorEffect(); + } } } } From 9925556579bda5e9500120980a0f8228b4d3e4cb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 14:48:37 +0200 Subject: [PATCH 150/346] Added hide fault to context menu in 3D view --- .../ProjectDataModel/RimFaultCollection.h | 3 +- .../ProjectDataModel/RimReservoirView.cpp | 31 ++------------- .../ProjectDataModel/RimReservoirView.h | 2 +- .../ReservoirDataModel/RigMainGrid.cpp | 33 ++++++++++++++++ .../ReservoirDataModel/RigMainGrid.h | 1 + ApplicationCode/UserInterface/RiuViewer.cpp | 39 +++++++++++++++++-- ApplicationCode/UserInterface/RiuViewer.h | 3 ++ 7 files changed, 79 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 095a65f96b..39b1fe982a 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -75,13 +75,12 @@ class RimFaultCollection : public caf::PdmObject caf::PdmField showFaultCollection; caf::PdmPointersField faults; + RimFault* findFaultByName(QString name); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); virtual caf::PdmFieldHandle* objectToggleField(); private: - RimFault* findFaultByName(QString name); - virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); private: diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 6d6c7ac57e..750729323b 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -2043,39 +2043,16 @@ void RimReservoirView::updateFaultColors() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) +void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString) { if (grid->isMainGrid()) { RigMainGrid* mainGrid = grid->mainGrid(); - for (size_t i = 0; i < mainGrid->faults().size(); i++) + const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(cellIndex, face); + if (fault) { - const RigFault* rigFault = mainGrid->faults().at(i); - const std::vector& faultFaces = rigFault->faultFaces(); - - for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) - { - if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) - { - if (face == faultFaces[fIdx].m_nativeFace ) - { - resultInfoText->append(QString("Fault Name: %1\n").arg(rigFault->name())); - } - - return; - } - - if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) - { - if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) - { - resultInfoText->append(QString("Fault Name: %1\n").arg(rigFault->name())); - } - - return; - } - } + textString->append(QString("Fault Name: %1\n").arg(fault->name())); } } } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 4c37031753..178d17ecd5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -180,7 +180,7 @@ class RimReservoirView : public caf::PdmObject // Display model generation private: - void appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText); + void appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString); void createDisplayModel(); void updateDisplayModelVisibility(); diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index db11222984..4bbdea1cb9 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -369,3 +369,36 @@ bool RigMainGrid::faceNormalsIsOutwards() const { return m_flipXAxis ^ m_flipYAxis; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const +{ + for (size_t i = 0; i < m_faults.size(); i++) + { + const RigFault* rigFault = m_faults.at(i); + const std::vector& faultFaces = rigFault->faultFaces(); + + for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) + { + if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) + { + if (face == faultFaces[fIdx].m_nativeFace ) + { + return rigFault; + } + } + + if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) + { + if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) + { + return rigFault; + } + } + } + } + + return NULL; +} diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index f7fc927571..0cf0dc8286 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -51,6 +51,7 @@ class RigMainGrid : public RigGridBase void setFaults(const cvf::Collection& faults); const cvf::Collection& faults() { return m_faults; } void calculateFaults(); + const RigFault* findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const; bool faceNormalsIsOutwards() const; void computeCachedData(); diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 71489243e2..286058a707 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -25,12 +25,13 @@ #include "RimReservoirView.h" +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimResultSlot.h" #include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" #include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimResultSlot.h" #include "RimWellCollection.h" #include "RimUiTreeModelPdm.h" @@ -278,11 +279,24 @@ void RiuViewer::mouseReleaseEvent(QMouseEvent* event) { m_currentGridIdx = firstHitPart->id(); m_currentCellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); + m_currentFaceIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); QMenu menu; + menu.addAction(QString("I-slice range filter"), this, SLOT(slotRangeFilterI())); menu.addAction(QString("J-slice range filter"), this, SLOT(slotRangeFilterJ())); menu.addAction(QString("K-slice range filter"), this, SLOT(slotRangeFilterK())); + + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + menu.addSeparator(); + + QString faultName = fault->name(); + menu.addAction(QString("Hide ") + faultName, this, SLOT(slotHideFault())); + } + menu.exec(event->globalPos()); } } @@ -759,3 +773,22 @@ void RiuViewer::removeOverlayItem(cvf::OverlayItem* overlayItem) m_renderingSequence->firstRendering()->removeOverlayItem(overlayItem); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuViewer::slotHideFault() +{ + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + QString faultName = fault->name(); + + RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); + if (rimFault) + { + rimFault->showFault.setValueFromUi(!rimFault->showFault); + } + } +} + diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index 7e881a1464..a2f5c4de92 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -24,6 +24,7 @@ #include "cafPdmPointer.h" #include "cafMouseState.h" +#include "cvfStructGrid.h" class RimReservoirView; class QLabel; @@ -87,6 +88,7 @@ private slots: void slotRangeFilterI(); void slotRangeFilterJ(); void slotRangeFilterK(); + void slotHideFault(); private: void updateLegends(); @@ -114,6 +116,7 @@ private slots: size_t m_currentGridIdx; size_t m_currentCellIndex; + cvf::StructGridInterface::FaceType m_currentFaceIndex; QPoint m_lastMousePressPosition; }; From 23d44a0747873b8713fd30fa0012c7d654e70e98 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 14:58:54 +0200 Subject: [PATCH 151/346] Make sure grid view is active after a range filter is added --- ApplicationCode/UserInterface/RiuViewer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 286058a707..79a073f43c 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -338,6 +338,8 @@ void RiuViewer::slotRangeFilterI() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- @@ -371,6 +373,8 @@ void RiuViewer::slotRangeFilterJ() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- @@ -404,6 +408,8 @@ void RiuViewer::slotRangeFilterK() mainWindow->setCurrentObjectInTreeView(rangeFilter); } + + m_reservoirView->setShowFaultsOnly(false); } //-------------------------------------------------------------------------------------------------- From d8f412017e9bf6e265e8094751b5879de0753171 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 29 Jul 2014 08:49:54 +0200 Subject: [PATCH 152/346] Faults: Added fault result mapping management --- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimFaultResultSlot.cpp | 53 +++++++++++++++++++ .../ProjectDataModel/RimFaultResultSlot.h | 47 ++++++++++++++++ .../ProjectDataModel/RimReservoirView.cpp | 6 +++ .../ProjectDataModel/RimReservoirView.h | 2 + 5 files changed, 110 insertions(+) create mode 100644 ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimFaultResultSlot.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 2abc7eacba..c9cb08a878 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,6 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -94,6 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp new file mode 100644 index 0000000000..dbfebd4a46 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimFaultResultSlot.h" + + +namespace caf +{ + template<> + void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() + { + addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSlot::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); + addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSlot::CELL_RESULT_MAPPING); + } +} + +CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultResultSlot::RimFaultResultSlot() +{ + CAF_PDM_InitObject("Fault Result Slot", "", "", ""); + + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFaultResultSlot::~RimFaultResultSlot() +{ +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h new file mode 100644 index 0000000000..010ce4d474 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +//================================================================================================== +/// +/// +//================================================================================================== +class RimFaultResultSlot : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + enum FaultVisualizationMode + { + FAULT_COLOR, + CELL_RESULT_MAPPING, + CUSTOM_RESULT_MAPPING + }; + +public: + RimFaultResultSlot(); + virtual ~RimFaultResultSlot(); + +private: + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; +}; + diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 750729323b..0d893222a0 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,6 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" +#include "RimFaultResultSlot.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -101,6 +102,11 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); + CAF_PDM_InitFieldNoDefault(&cellFaultResult, "GridCellFaultResult", "Fault Cell Result", ":/CellResult.png", "", ""); + cellFaultResult = new RimFaultResultSlot(); + cellFaultResult.setUiHidden(true); + + CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); overlayInfoConfig->setReservoirView(this); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 178d17ecd5..f6a5ba96f5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -43,6 +43,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; +class RimFaultResultSlot; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -96,6 +97,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; + caf::PdmField cellFaultResult; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From 032a263685c325589d370a32fdbd6e15d26d17fb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 09:13:47 +0200 Subject: [PATCH 153/346] Performance: Control how much data to import from file User can control if faults, NNCs and simulation wells are to be imported from file. --- .../Application/RiaPreferences.cpp | 34 ++++++++-- ApplicationCode/Application/RiaPreferences.h | 4 +- .../FileInterface/CMakeLists_files.cmake | 3 + .../FileInterface_UnitTests/CMakeLists.txt | 1 + .../FileInterface/RifReaderEclipseOutput.cpp | 15 +++- .../FileInterface/RifReaderInterface.cpp | 68 +++++++++++++++++++ .../FileInterface/RifReaderInterface.h | 19 ++++-- .../FileInterface/RifReaderSettings.cpp | 59 ++++++++++++++++ .../FileInterface/RifReaderSettings.h | 46 +++++++++++++ ApplicationCode/ProjectDataModel/RimCase.cpp | 12 +++- .../ProjectDataModel/RimInputCase.cpp | 5 +- .../ProjectDataModel/RimResultCase.cpp | 3 +- 12 files changed, 246 insertions(+), 23 deletions(-) create mode 100644 ApplicationCode/FileInterface/RifReaderInterface.cpp create mode 100644 ApplicationCode/FileInterface/RifReaderSettings.cpp create mode 100644 ApplicationCode/FileInterface/RifReaderSettings.h diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 0acd148c48..337084d979 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -22,6 +22,7 @@ #include "cafPdmUiFilePathEditor.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmUiCheckBoxEditor.h" +#include "RifReaderSettings.h" CAF_PDM_SOURCE_INIT(RiaPreferences, "RiaPreferences"); //-------------------------------------------------------------------------------------------------- @@ -61,10 +62,16 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&lastUsedProjectFileName,"lastUsedProjectFileName", "Last Used Project File", "", "", ""); lastUsedProjectFileName.setUiHidden(true); - CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "SOIL", "", "SOIL = 1.0 - SGAS - SWAT", ""); - CAF_PDM_InitField(&autocomputeDepthRelatedProperties,"autocomputeDepth", true, "DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); + CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "SOIL", "", "SOIL = 1.0 - SGAS - SWAT", ""); + CAF_PDM_InitField(&autocomputeDepthRelatedProperties, "autocomputeDepth", true, "DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); + CAF_PDM_InitField(&autocomputeGridFaults, "autocomputeGridFaults", true, "Grid faults", "", "Detect all fault faces geometrically", ""); - CAF_PDM_InitField(&readFaultData, "readFaultData", true, "Read fault data", "", "", ""); + autocomputeDepthRelatedProperties.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + autocomputeSOIL.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + autocomputeGridFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + readerSettings = new RifReaderSettings; + CAF_PDM_InitFieldNoDefault(&readerSettings, "readerSettings", "Reader settings", "", "", ""); } //-------------------------------------------------------------------------------------------------- @@ -80,6 +87,8 @@ RiaPreferences::~RiaPreferences(void) //-------------------------------------------------------------------------------------------------- void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute * attribute) { + readerSettings->defineEditorAttribute(field, uiConfigName, attribute); + if (field == &scriptDirectories) { caf::PdmUiFilePathEditorAttribute* myAttr = static_cast(attribute); @@ -89,7 +98,10 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt myAttr->m_appendUiSelectedFolderToText = true; } } - else if (field == &octaveShowHeaderInfoWhenExecutingScripts) + else if (field == &octaveShowHeaderInfoWhenExecutingScripts || + field == &autocomputeSOIL || + field == &autocomputeDepthRelatedProperties || + field == &autocomputeGridFaults) { caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); if (myAttr) @@ -125,9 +137,16 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& caf::PdmUiGroup* autoComputeGroup = uiOrdering.addNewGroup("Compute when loading new case"); autoComputeGroup->add(&autocomputeSOIL); autoComputeGroup->add(&autocomputeDepthRelatedProperties); + autoComputeGroup->add(&autocomputeGridFaults); - caf::PdmUiGroup* faultsGroup = uiOrdering.addNewGroup("Faults"); - faultsGroup->add(&readFaultData); + + caf::PdmUiGroup* readerSettingsGroup = uiOrdering.addNewGroup("Reader settings"); + std::vector readerSettingsFields; + readerSettings->fields(readerSettingsFields); + for (size_t i = 0; i < readerSettingsFields.size(); i++) + { + readerSettingsGroup->add(readerSettingsFields[i]); + } } //-------------------------------------------------------------------------------------------------- @@ -142,6 +161,7 @@ void RiaPreferences::configureForRegressionTests() autocomputeSOIL = true; autocomputeDepthRelatedProperties = true; - readFaultData = false; + CVF_ASSERT(readerSettings); + readerSettings->importFaults = false; } diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index bb7d3f3354..78fd48e44e 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -27,6 +27,7 @@ // Include to make Pdm work for cvf::Color #include "cafPdmFieldCvfColor.h" +class RifReaderSettings; class RiaPreferences : public caf::PdmObject { @@ -63,8 +64,9 @@ class RiaPreferences : public caf::PdmObject caf::PdmField autocomputeSOIL; caf::PdmField autocomputeDepthRelatedProperties; + caf::PdmField autocomputeGridFaults; - caf::PdmField readFaultData; + caf::PdmField readerSettings; protected: virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); diff --git a/ApplicationCode/FileInterface/CMakeLists_files.cmake b/ApplicationCode/FileInterface/CMakeLists_files.cmake index 1ddd99f08a..34a6ec93be 100644 --- a/ApplicationCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationCode/FileInterface/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CEE_CURRENT_LIST_DIR}RifReaderEclipseOutput.h ${CEE_CURRENT_LIST_DIR}RifJsonEncodeDecode.h ${CEE_CURRENT_LIST_DIR}RifReaderInterface.h ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.h +${CEE_CURRENT_LIST_DIR}RifReaderSettings.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -26,7 +27,9 @@ ${CEE_CURRENT_LIST_DIR}RifEclipseUnifiedRestartFileAccess.cpp ${CEE_CURRENT_LIST_DIR}RifReaderEclipseInput.cpp ${CEE_CURRENT_LIST_DIR}RifReaderEclipseOutput.cpp ${CEE_CURRENT_LIST_DIR}RifJsonEncodeDecode.cpp +${CEE_CURRENT_LIST_DIR}RifReaderInterface.cpp ${CEE_CURRENT_LIST_DIR}RifReaderMockModel.cpp +${CEE_CURRENT_LIST_DIR}RifReaderSettings.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt index 475f353da7..092d8d9098 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/CMakeLists.txt @@ -59,6 +59,7 @@ set( UNIT_TEST_CPP_SOURCES ) set( LINK_LIBRARIES + cafProjectDataModel CommonCode LibViewing diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index e9cb4e2918..a620ce1893 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -434,17 +434,26 @@ bool RifReaderEclipseOutput::open(const QString& fileName, RigCaseData* eclipseC progInfo.setProgressDescription("Reading NNC data"); progInfo.setNextProgressIncrement(5); - transferNNCData(mainEclGrid, m_ecl_init_file, eclipseCase->mainGrid()); + if (isNNCsEnabled()) + { + transferNNCData(mainEclGrid, m_ecl_init_file, eclipseCase->mainGrid()); + } progInfo.incrementProgress(); progInfo.setProgressDescription("Processing NNC data"); progInfo.setNextProgressIncrement(20); - eclipseCase->mainGrid()->nncData()->processConnections( *(eclipseCase->mainGrid())); + if (isNNCsEnabled()) + { + eclipseCase->mainGrid()->nncData()->processConnections( *(eclipseCase->mainGrid())); + } progInfo.incrementProgress(); progInfo.setNextProgressIncrement(8); progInfo.setProgressDescription("Reading Well information"); - readWellCells(mainEclGrid); + if (isSimulationWellDataEnabled()) + { + readWellCells(mainEclGrid); + } progInfo.setProgressDescription("Releasing reader memory"); ecl_grid_free( mainEclGrid ); diff --git a/ApplicationCode/FileInterface/RifReaderInterface.cpp b/ApplicationCode/FileInterface/RifReaderInterface.cpp new file mode 100644 index 0000000000..c08eb619e5 --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderInterface.cpp @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifReaderInterface.h" + +#include "RifReaderSettings.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderInterface::setReaderSetting(RifReaderSettings* settings) +{ + m_settings = settings; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isFaultImportEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importFaults; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isSimulationWellDataEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importSimulationWellData; + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifReaderInterface::isNNCsEnabled() +{ + if (m_settings.notNull()) + { + return m_settings->importNNCs; + } + + return false; +} diff --git a/ApplicationCode/FileInterface/RifReaderInterface.h b/ApplicationCode/FileInterface/RifReaderInterface.h index b57a8d4976..6f66a4aeda 100644 --- a/ApplicationCode/FileInterface/RifReaderInterface.h +++ b/ApplicationCode/FileInterface/RifReaderInterface.h @@ -22,12 +22,16 @@ #include "cvfObject.h" #include "cvfLibCore.h" +#include "cafPdmPointer.h" + #include #include #include class RigCaseData; +class RifReaderSettings; + //================================================================================================== // @@ -44,11 +48,14 @@ class RifReaderInterface : public cvf::Object }; public: - RifReaderInterface() { m_readFaultData = false; } - virtual ~RifReaderInterface() {} + RifReaderInterface() { } + virtual ~RifReaderInterface() { } + + void setReaderSetting(RifReaderSettings* settings); - void readFaultData(bool readFaultData) { m_readFaultData = readFaultData; } - bool isFaultImportEnabled() { return m_readFaultData; } + bool isFaultImportEnabled(); + bool isSimulationWellDataEnabled(); + bool isNNCsEnabled(); virtual bool open(const QString& fileName, RigCaseData* eclipseCase) = 0; virtual void close() = 0; @@ -63,6 +70,6 @@ class RifReaderInterface : public cvf::Object private: - std::vector m_filenamesWithFaults; - bool m_readFaultData; + std::vector m_filenamesWithFaults; + caf::PdmPointer m_settings; }; diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp new file mode 100644 index 0000000000..e3a743d188 --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + + +#include "RifReaderSettings.h" +#include "cafPdmUiCheckBoxEditor.h" + + +CAF_PDM_SOURCE_INIT(RifReaderSettings, "RifReaderSettings"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifReaderSettings::RifReaderSettings() +{ + CAF_PDM_InitObject("RifReaderSettings", "", "", ""); + + CAF_PDM_InitField(&importFaults, "importFaults", false, "Import faults", "", "", ""); + importFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", false, "Import simulation wells", "", "", ""); + importSimulationWellData.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); + + CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", false, "Import NNCs", "", "", ""); + importNNCs.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderSettings::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) +{ + if (field == &importFaults || + field == &importSimulationWellData || + field == &importNNCs) + { + caf::PdmUiCheckBoxEditorAttribute* myAttr = static_cast(attribute); + if (myAttr) + { + myAttr->m_useNativeCheckBoxLabel = true; + } + } +} + diff --git a/ApplicationCode/FileInterface/RifReaderSettings.h b/ApplicationCode/FileInterface/RifReaderSettings.h new file mode 100644 index 0000000000..7bf3ed050e --- /dev/null +++ b/ApplicationCode/FileInterface/RifReaderSettings.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmField.h" +#include "cafPdmObject.h" + + +//================================================================================================== +/// +/// +//================================================================================================== +class RifReaderSettings : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + + friend class RiaPreferences; + +public: + RifReaderSettings(); + + caf::PdmField importFaults; + caf::PdmField importSimulationWellData; + caf::PdmField importNNCs; + +protected: + virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute); + +}; + diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index c386fed410..c58b36f476 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -18,6 +18,8 @@ #include "RimCase.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimCaseCollection.h" @@ -298,9 +300,13 @@ void RimCase::computeCachedData() rigEclipseCase->mainGrid()->computeCachedData(); pInf.incrementProgress(); - pInf.setProgressDescription("Calculating faults"); - rigEclipseCase->mainGrid()->calculateFaults(); - pInf.incrementProgress(); + RiaPreferences* prefs = RiaApplication::instance()->preferences(); + if (prefs->autocomputeGridFaults) + { + pInf.setProgressDescription("Calculating faults"); + rigEclipseCase->mainGrid()->calculateFaults(); + pInf.incrementProgress(); + } } } diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index adc91355bf..f003e5db0f 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -23,6 +23,7 @@ #include "RifReaderEclipseInput.h" #include "RifReaderInterface.h" #include "RifReaderMockModel.h" +#include "RifReaderSettings.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimDefines.h" @@ -96,7 +97,7 @@ void RimInputCase::openDataFileSet(const QStringList& fileNames) for (int i = 0; i < fileNames.size(); i++) { - if (RifEclipseInputFileTools::openGridFile(fileNames[i], this->reservoirData(), prefs->readFaultData())) + if (RifEclipseInputFileTools::openGridFile(fileNames[i], this->reservoirData(), prefs->readerSettings->importFaults())) { m_gridFileName = fileNames[i]; @@ -181,7 +182,7 @@ bool RimInputCase::openEclipseGridFile() { RiaPreferences* prefs = RiaApplication::instance()->preferences(); readerInterface = new RifReaderEclipseInput; - readerInterface->readFaultData(prefs->readFaultData()); + readerInterface->setReaderSetting(prefs->readerSettings()); cvf::ref eclipseCase = new RigCaseData; if (!readerInterface->open(m_gridFileName, eclipseCase.p())) diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index 8d1041fa63..da71221787 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -22,6 +22,7 @@ #include "RifEclipseOutputFileTools.h" #include "RifReaderEclipseOutput.h" #include "RifReaderMockModel.h" +#include "RifReaderSettings.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RimMockModelSettings.h" @@ -90,7 +91,7 @@ bool RimResultCase::openEclipseGridFile() RiaPreferences* prefs = RiaApplication::instance()->preferences(); readerInterface = new RifReaderEclipseOutput; - readerInterface->readFaultData(prefs->readFaultData()); + readerInterface->setReaderSetting(prefs->readerSettings()); readerInterface->setFilenamesWithFaults(this->filesContainingFaults()); cvf::ref eclipseCase = new RigCaseData; From ce58846584d1afc0d90a47865a1f8505249bf1cc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 09:14:54 +0200 Subject: [PATCH 154/346] Updates to tests --- .../RifReaderEclipseOutput-Test.cpp | 80 ++++++++++++++++--- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp index 59739e33b2..98bd5fbba8 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp @@ -28,19 +28,78 @@ #include "RifEclipseOutputFileTools.h" #include "RigCaseCellResultsData.h" #include "RifEclipseUnifiedRestartFileAccess.h" +#include "RifReaderSettings.h" +#if 0 -#if 0 +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(RigReservoirTest, DISABLED_BasicTest) +{ + + cvf::ref readerInterfaceEcl = new RifReaderEclipseOutput; + cvf::ref reservoir = new RigCaseData; + + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.EGRID"); + + RifReaderSettings readerSettings; + readerInterfaceEcl->setReaderSetting(&readerSettings); + + bool result = readerInterfaceEcl->open(filename, reservoir.p()); + EXPECT_TRUE(result); + + { +// QStringList staticResults = readerInterfaceEcl->staticResults(); +// EXPECT_EQ(42, staticResults.size()); +// qDebug() << "Static results\n" << staticResults; +// +// QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); +// EXPECT_EQ(23, dynamicResults.size()); +// qDebug() << "Dynamic results\n" << dynamicResults; +// +// int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); +// EXPECT_EQ(9, numTimeSteps); +// +// QStringList timeStepText = readerInterfaceEcl->timeStepText(); +// EXPECT_EQ(numTimeSteps, timeStepText.size()); +// qDebug() << "Time step texts\n" << timeStepText; + } + + + readerInterfaceEcl->close(); + { +// QStringList staticResults = readerInterfaceEcl->staticResults(); +// EXPECT_EQ(0, staticResults.size()); +// +// QStringList dynamicResults = readerInterfaceEcl->dynamicResults(); +// EXPECT_EQ(0, dynamicResults.size()); +// +// int numTimeSteps = static_cast(readerInterfaceEcl->numTimeSteps()); +// EXPECT_EQ(0, numTimeSteps); +// +// QStringList timeStepText = readerInterfaceEcl->timeStepText(); +// EXPECT_EQ(numTimeSteps, timeStepText.size()); + } -TEST(RigReservoirTest, FileOutputToolsTest) +} + + + +TEST(RigReservoirTest, DISABLED_FileOutputToolsTest) { + cvf::DebugTimer timer("test"); + + // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.EGRID"); // QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); - QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); +// QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); + QString filename("c:/tmp/troll_MSW/T07-4A-W2012-16-F3.UNRST"); + ecl_file_type* ertFile = ecl_file_open(filename.toAscii().data(), ECL_FILE_CLOSE_STREAM); EXPECT_TRUE(ertFile); @@ -61,18 +120,16 @@ TEST(RigReservoirTest, FileOutputToolsTest) ecl_file_close(ertFile); ertFile = NULL; + + timer.reportTime(); + //qDebug() << timer.lapt; } TEST(RigReservoirTest, UnifiedTestFile) { - - // Location of test dataset received from Håkon Høgstøl in July 2011 with 10k active cells -#ifdef WIN32 - QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); -#else - QString filename("/mnt/hgfs/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); -#endif + //QString filename("d:/Models/Statoil/testcase_juli_2011/data/TEST10K_FLT_LGR_NNC.UNRST"); + QString filename("d:/Models/Statoil/troll_MSW/T07-4A-W2012-16-F3.UNRST"); { cvf::ref restartFile = new RifEclipseUnifiedRestartFileAccess(); @@ -86,9 +143,10 @@ TEST(RigReservoirTest, UnifiedTestFile) std::vector resultDataItemCounts; restartFile->resultNames(&resultNames, &resultDataItemCounts); + qDebug() << "Result names\n"; for (int i = 0; i < resultNames.size(); i++) { - qDebug() << "Result names\n" << resultNames[i] << " - " << resultDataItemCounts[i]; + qDebug() << resultNames[i] << "\t" << resultDataItemCounts[i]; } std::vector tsteps = restartFile->timeSteps(); From 0d6c6f278512ef8135a513a5eb12c674aaf54675 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 10:54:46 +0200 Subject: [PATCH 155/346] Improved management of multiple legend overlay items --- .../ProjectDataModel/RimReservoirView.cpp | 59 +++++------ ApplicationCode/UserInterface/RiuViewer.cpp | 97 ++++++------------- ApplicationCode/UserInterface/RiuViewer.h | 11 +-- 3 files changed, 62 insertions(+), 105 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 0d893222a0..c4175aa2b5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -221,8 +221,10 @@ void RimReservoirView::updateViewerWidget() this->cellResult()->legendConfig->recreateLegend(); this->cellResult()->ternaryLegendConfig->recreateLegend(); this->cellEdgeResult()->legendConfig->recreateLegend(); - m_viewer->setColorLegend1(this->cellResult()->legendConfig->legend()); - m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); + + m_viewer->removeAllColorLegends(); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); if (RiaApplication::instance()->navigationPolicy() == RiaApplication::NAVIGATION_POLICY_CEETRON) { @@ -1370,6 +1372,11 @@ void RimReservoirView::indicesToVisibleGrids(std::vector* gridIndices) //-------------------------------------------------------------------------------------------------- void RimReservoirView::updateLegends() { + if (m_viewer) + { + m_viewer->removeAllColorLegends(); + } + if (!m_reservoir || !m_viewer || !m_reservoir->reservoirData() ) { return; @@ -1408,40 +1415,15 @@ void RimReservoirView::updateLegends() this->cellResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); this->cellResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); - m_viewer->setColorLegend1(this->cellResult()->legendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); this->cellResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Cell Results: \n") + this->cellResult()->resultVariable())); } else { this->cellResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); this->cellResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); - m_viewer->setColorLegend1(NULL); - } - - if (this->cellEdgeResult()->hasResult()) - { - double globalMin, globalMax; - double globalPosClosestToZero, globalNegClosestToZero; - this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); - this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); - - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); - - m_viewer->setColorLegend2(this->cellEdgeResult()->legendConfig->legend()); - this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); - - } - else - { - m_viewer->setColorLegend2(NULL); - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); } - - viewer()->removeOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); - size_t maxTimeStepCount = results->maxTimeStepCount(); if (this->cellResult()->isTernarySaturationSelected() && maxTimeStepCount > 1) { @@ -1496,9 +1478,28 @@ void RimReservoirView::updateLegends() if (this->cellResult()->ternaryLegendConfig->legend()) { - viewer()->addOverlayItem(this->cellResult()->ternaryLegendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->ternaryLegendConfig->legend()); } } + + if (this->cellEdgeResult()->hasResult()) + { + double globalMin, globalMax; + double globalPosClosestToZero, globalNegClosestToZero; + this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); + this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); + + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); + + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); + this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); + } + else + { + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 79a073f43c..29476f1678 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -146,55 +146,6 @@ RiuViewer::~RiuViewer() } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::setColorLegend1(cvf::OverlayScalarMapperLegend* legend) -{ - m_mainRendering->removeOverlayItem(m_legend1.p()); - - m_legend1 = legend; - - this->updateLegends(); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::setColorLegend2(cvf::OverlayScalarMapperLegend* legend) -{ - m_mainRendering->removeOverlayItem(m_legend2.p()); - - m_legend2 = legend; - - this->updateLegends(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RiuViewer::updateLegends() -{ - cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); - CVF_ASSERT(firstRendering); - - firstRendering->removeOverlayItem(m_legend1.p()); - firstRendering->removeOverlayItem(m_legend2.p()); - - if (m_legend1.notNull()) - { - m_legend1->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); - firstRendering->addOverlayItem(m_legend1.p()); - } - - if (m_legend2.notNull()) - { - m_legend2->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); - firstRendering->addOverlayItem(m_legend2.p()); - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -510,9 +461,6 @@ void RiuViewer::slotEndAnimation() cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); CVF_ASSERT(firstRendering); - firstRendering->removeOverlayItem(m_legend1.p()); - firstRendering->removeOverlayItem(m_legend2.p()); - if (m_reservoirView) m_reservoirView->endAnimation(); caf::Viewer::slotEndAnimation(); @@ -530,8 +478,6 @@ void RiuViewer::slotSetCurrentFrame(int frameIndex) if (m_reservoirView) m_reservoirView->setCurrentTimeStep(frameIndex); - this->updateLegends(); - caf::Viewer::slotSetCurrentFrame(frameIndex); } @@ -763,38 +709,53 @@ void RiuViewer::mousePressEvent(QMouseEvent* event) m_lastMousePressPosition = event->pos(); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::addOverlayItem(cvf::OverlayItem* overlayItem) +void RiuViewer::slotHideFault() { - m_renderingSequence->firstRendering()->addOverlayItem(overlayItem); + const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); + const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); + if (fault) + { + QString faultName = fault->name(); + + RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); + if (rimFault) + { + rimFault->showFault.setValueFromUi(!rimFault->showFault); + } + } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::removeOverlayItem(cvf::OverlayItem* overlayItem) +void RiuViewer::removeAllColorLegends() { - m_renderingSequence->firstRendering()->removeOverlayItem(overlayItem); + for (size_t i = 0; i < m_visibleLegends.size(); i++) + { + m_mainRendering->removeOverlayItem(m_visibleLegends[i].p()); + } + + m_visibleLegends.clear(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RiuViewer::slotHideFault() +void RiuViewer::addColorLegendToBottomLeftCorner(cvf::OverlayItem* legend) { - const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); - const RigFault* fault = reservoir->mainGrid()->findFaultFromCellIndexAndCellFace(m_currentCellIndex, m_currentFaceIndex); - if (fault) + cvf::Rendering* firstRendering = m_renderingSequence->firstRendering(); + CVF_ASSERT(firstRendering); + + if (legend) { - QString faultName = fault->name(); + legend->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::BOTTOM_LEFT); + firstRendering->addOverlayItem(legend); - RimFault* rimFault = m_reservoirView->faultCollection()->findFaultByName(faultName); - if (rimFault) - { - rimFault->showFault.setValueFromUi(!rimFault->showFault); - } + m_visibleLegends.push_back(legend); } } diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index a2f5c4de92..5dd21d8a0b 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -51,8 +51,6 @@ class RiuViewer : public caf::Viewer RiuViewer(const QGLFormat& format, QWidget* parent); ~RiuViewer(); - void setColorLegend1(cvf::OverlayScalarMapperLegend* legend); - void setColorLegend2(cvf::OverlayScalarMapperLegend* legend); void setDefaultView(); cvf::Vec3d pointOfInterest(); void setPointOfInterest(cvf::Vec3d poi); @@ -67,8 +65,8 @@ class RiuViewer : public caf::Viewer void showAnimationProgress(bool enable); - void addOverlayItem(cvf::OverlayItem* overlayItem); - void removeOverlayItem(cvf::OverlayItem* overlayItem); + void removeAllColorLegends(); + void addColorLegendToBottomLeftCorner(cvf::OverlayItem* legend); public slots: @@ -91,7 +89,6 @@ private slots: void slotHideFault(); private: - void updateLegends(); void ijkFromCellIndex(size_t gridIdx, size_t cellIndex, size_t* i, size_t* j, size_t* k); private: @@ -108,9 +105,7 @@ private slots: QCDEStyle* m_progressBarStyle; - cvf::ref m_legend1; - cvf::ref m_legend2; - + cvf::Collection m_visibleLegends; caf::PdmPointer m_reservoirView; From 710b9392ecceb88d09e3df2d3bfcff58c887f052 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 14:26:39 +0200 Subject: [PATCH 156/346] Fault result: Added custom result to fault result project model --- .../Application/RiaApplication.cpp | 4 ++ .../ProjectDataModel/RimFaultResultSlot.cpp | 55 +++++++++++++++++++ .../ProjectDataModel/RimFaultResultSlot.h | 14 +++++ .../ProjectDataModel/RimReservoirView.cpp | 5 +- 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 472a2b9a23..d95d7d6f02 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,6 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" +#include "RimFaultResultSlot.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -649,6 +650,9 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } + riv->cellFaultResult()->customResultSlot()->setResultVariable(RimDefines::undefinedResultName()); + + RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); uiModel->updateUiSubTree(analysisModels); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index dbfebd4a46..d78a3534d9 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -18,6 +18,11 @@ #include "RimFaultResultSlot.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RiuMainWindow.h" +#include "RimUiTreeModelPdm.h" + namespace caf { @@ -42,6 +47,10 @@ RimFaultResultSlot::RimFaultResultSlot() CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitFieldNoDefault(&customResultSlot, "CustomResultSlot", "Custom Cell Result", ":/CellResult.png", "", ""); + customResultSlot = new RimResultSlot(); + + updateVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -51,3 +60,49 @@ RimFaultResultSlot::~RimFaultResultSlot() { } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) +{ + customResultSlot->setReservoirView(ownerReservoirView); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +{ + if (changedField == &visualizationMode) + { + updateVisibility(); + + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::initAfterRead() +{ + updateVisibility(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSlot::updateVisibility() +{ + if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + { + this->customResultSlot.setUiHidden(true); + this->customResultSlot.setUiChildrenHidden(true); + } + else + { + this->customResultSlot.setUiHidden(false); + this->customResultSlot.setUiChildrenHidden(false); + } +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 010ce4d474..2fa532d58a 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -22,6 +22,9 @@ #include "cafPdmField.h" #include "cafPdmObject.h" +class RimResultSlot; +class RimReservoirView; + //================================================================================================== /// /// @@ -41,6 +44,17 @@ class RimFaultResultSlot : public caf::PdmObject RimFaultResultSlot(); virtual ~RimFaultResultSlot(); + void setReservoirView(RimReservoirView* ownerReservoirView); + + caf::PdmField customResultSlot; + +protected: + virtual void initAfterRead(); + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + +private: + void updateVisibility(); + private: caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index c4175aa2b5..bba2901cc8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -167,6 +167,8 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); + this->cellFaultResult()->setReservoirView(this); + m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); m_pipesPartManager = new RivReservoirPipesPartMgr(this); @@ -180,6 +182,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { + delete this->cellFaultResult(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -969,11 +972,11 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { + this->cellFaultResult()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); this->propertyFilterCollection()->setReservoirView(this); - } //-------------------------------------------------------------------------------------------------- From a5e928dec113e7af69d5122eca7952ab12f3a858 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 30 Jul 2014 14:52:32 +0200 Subject: [PATCH 157/346] Removed obsolete fault code --- .../ModelVisualization/RivGridPartMgr.cpp | 149 ++---------------- .../ModelVisualization/RivGridPartMgr.h | 15 +- .../RivReservoirPartMgr.cpp | 2 +- 3 files changed, 18 insertions(+), 148 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index d8edaca5b4..98145b17ad 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,27 +50,22 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" -#include "RimFaultCollection.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection) +RivGridPartMgr::RivGridPartMgr(const RigGridBase* grid, size_t gridIdx) : m_surfaceGenerator(grid), - m_faultGenerator(grid), m_gridIdx(gridIdx), m_grid(grid), m_surfaceFaceFilter(grid), - m_faultFaceFilter(grid), m_opacityLevel(1.0f), - m_defaultColor(cvf::Color3::WHITE), - m_rimFaultCollection(rimFaultCollection) + m_defaultColor(cvf::Color3::WHITE) { CVF_ASSERT(grid); m_cellVisibility = new cvf::UByteArray; m_surfaceFacesTextureCoords = new cvf::Vec2fArray; - m_faultFacesTextureCoords = new cvf::Vec2fArray; } //-------------------------------------------------------------------------------------------------- @@ -94,14 +89,10 @@ void RivGridPartMgr::setCellVisibility(cvf::UByteArray* cellVisibilities) m_surfaceGenerator.setCellVisibility(cellVisibilities); m_surfaceGenerator.addFaceVisibilityFilter(&m_surfaceFaceFilter); - m_faultGenerator.setCellVisibility(cellVisibilities); - m_faultGenerator.addFaceVisibilityFilter(&m_faultFaceFilter); - - generatePartGeometry(m_surfaceGenerator, false); - generatePartGeometry(m_faultGenerator, true); + generatePartGeometry(m_surfaceGenerator); } -void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry) +void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder) { bool useBufferObjects = true; // Surface geometry @@ -134,17 +125,8 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB caf::SurfaceEffectGenerator geometryEffgen(cvf::Color4f(cvf::Color3f::WHITE), caf::PO_1); cvf::ref geometryOnlyEffect = geometryEffgen.generateEffect(); part->setEffect(geometryOnlyEffect.p()); - - if (faultGeometry) - { - part->setEnableMask(faultBit); - m_faultFaces = part; - } - else - { - part->setEnableMask(surfaceBit); - m_surfaceFaces = part; - } + part->setEnableMask(surfaceBit); + m_surfaceFaces = part; } } @@ -168,30 +150,19 @@ void RivGridPartMgr::generatePartGeometry(cvf::StructGridGeometryGenerator& geoB RiaPreferences* prefs = RiaApplication::instance()->preferences(); cvf::ref eff; - if (faultGeometry) - { - caf::MeshEffectGenerator effGen(prefs->defaultFaultGridLineColors()); - eff = effGen.generateEffect(); - - part->setEnableMask(meshFaultBit); - part->setEffect(eff.p()); - m_faultGridLines = part; - } - else - { - caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); - eff = effGen.generateEffect(); + caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); + eff = effGen.generateEffect(); - // Set priority to make sure fault lines are rendered first - part->setPriority(10); + // Set priority to make sure fault lines are rendered first + part->setPriority(10); - part->setEnableMask(meshSurfaceBit); - part->setEffect(eff.p()); - m_surfaceGridLines = part; - } + part->setEnableMask(meshSurfaceBit); + part->setEffect(eff.p()); + m_surfaceGridLines = part; } } } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -201,12 +172,6 @@ void RivGridPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if(m_surfaceFaces.notNull() ) model->addPart(m_surfaceFaces.p() ); if(m_surfaceGridLines.notNull()) model->addPart(m_surfaceGridLines.p()); - - if (m_rimFaultCollection && m_rimFaultCollection->showGeometryDetectedFaults()) - { - if(m_faultFaces.notNull() ) model->addPart(m_faultFaces.p() ); - if(m_faultGridLines.notNull() ) model->addPart(m_faultGridLines.p() ); - } } //-------------------------------------------------------------------------------------------------- @@ -214,20 +179,18 @@ void RivGridPartMgr::appendPartsToModel(cvf::ModelBasicList* model) //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::updateCellColor(cvf::Color4f color) { - if (m_surfaceFaces.isNull() && m_faultFaces.isNull()) return; + if (m_surfaceFaces.isNull()) return; // Set default effect caf::SurfaceEffectGenerator geometryEffgen(color, caf::PO_1); cvf::ref geometryOnlyEffect = geometryEffgen.generateEffect(); if (m_surfaceFaces.notNull()) m_surfaceFaces->setEffect(geometryOnlyEffect.p()); - if (m_faultFaces.notNull()) m_faultFaces->setEffect(geometryOnlyEffect.p()); if (color.a() < 1.0f) { // Set priority to make sure this transparent geometry are rendered last if (m_surfaceFaces.notNull()) m_surfaceFaces->setPriority(100); - if (m_faultFaces.notNull()) m_faultFaces->setPriority(100); } m_opacityLevel = color.a(); @@ -237,12 +200,6 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) RiaPreferences* prefs = RiaApplication::instance()->preferences(); cvf::ref eff; - if (m_faultFaces.notNull()) - { - caf::MeshEffectGenerator faultEffGen(prefs->defaultFaultGridLineColors()); - eff = faultEffGen.generateEffect(); - m_faultGridLines->setEffect(eff.p()); - } if (m_surfaceFaces.notNull()) { caf::MeshEffectGenerator effGen(prefs->defaultGridLineColors()); @@ -317,31 +274,6 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); } } - - // Faults - if (m_faultFaces.notNull()) - { - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (dataAccessObject.isNull()) return; - - m_faultGenerator.textureCoordinates(m_faultFacesTextureCoords.p(), dataAccessObject.p(), mapper); - - setResultsTransparentForWellCells( - cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), - m_surfaceGenerator.quadToCellFaceMapper(), - m_faultFacesTextureCoords.p()); - - - applyTextureResultsToPart(m_faultFaces.p(), m_faultFacesTextureCoords.p(), mapper); - } } //-------------------------------------------------------------------------------------------------- @@ -405,62 +337,11 @@ void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector(m_surfaceFaces->drawable()); - if (dg) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - &m_surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); - - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); - - m_surfaceFaces->setEffect(eff.p()); - } - } - */ updateCellEdgeResultColorOnPart( m_surfaceFaces.p(), &m_surfaceGenerator, timeStepIndex, cellResultSlot, cellEdgeResultSlot); - if (m_faultFaces.notNull()) - { - updateCellEdgeResultColorOnPart( - m_faultFaces.p(), - &m_faultGenerator, - timeStepIndex, cellResultSlot, cellEdgeResultSlot); - } - /* - if (m_faultFaces.notNull()) - { - cvf::DrawableGeo* dg = dynamic_cast(m_faultFaces->drawable()); - if (dg) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - &m_faultGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); - - m_faultFaces->setEffect(eff.p()); - } - } - */ } //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 4ef7bb7e13..6e555300a6 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -34,7 +34,6 @@ namespace cvf class RimResultSlot; class RimCellEdgeResultSlot; -class RimFaultCollection; @@ -72,7 +71,7 @@ class RivTransmissibilityColorMapper class RivGridPartMgr: public cvf::Object { public: - RivGridPartMgr(const RigGridBase* grid, size_t gridIdx, const RimFaultCollection* rimFaultCollection); + RivGridPartMgr(const RigGridBase* grid, size_t gridIdx); ~RivGridPartMgr(); void setTransform(cvf::Transform* scaleTransform); void setCellVisibility(cvf::UByteArray* cellVisibilities ); @@ -89,7 +88,7 @@ class RivGridPartMgr: public cvf::Object static cvf::ref createPerVertexColoringEffect(float opacity); private: - void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder, bool faultGeometry); + void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, @@ -117,15 +116,5 @@ class RivGridPartMgr: public cvf::Object cvf::ref m_surfaceGridLines; - // Fault visualization: Dead ?? JJS - cvf::StructGridGeometryGenerator m_faultGenerator; - RigFaultFaceVisibilityFilter m_faultFaceFilter; - cvf::ref m_faultFaces; - cvf::ref m_faultFacesTextureCoords; - - cvf::ref m_faultGridLines; - cvf::ref m_cellVisibility; - - const RimFaultCollection* m_rimFaultCollection; }; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 5ac14e77ce..806bd08023 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -38,7 +38,7 @@ void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, c eclipseCase->allGrids(&grids); for (size_t i = 0; i < grids.size() ; ++i) { - m_allGrids.push_back(new RivGridPartMgr(grids[i], i, faultCollection)); + m_allGrids.push_back(new RivGridPartMgr(grids[i], i)); } if (eclipseCase->mainGrid()) From 0d14436b976750917eeb2b17d07eb28b9f453dc1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 08:46:30 +0200 Subject: [PATCH 158/346] Fault result: Added fault result legend --- .../Application/RiaApplication.cpp | 2 +- .../ProjectDataModel/RimFaultResultSlot.cpp | 36 ++-- .../ProjectDataModel/RimFaultResultSlot.h | 13 +- .../ProjectDataModel/RimReservoirView.cpp | 159 +++++++++++------- .../ProjectDataModel/RimReservoirView.h | 4 +- .../UserInterface/RiuMainWindow.cpp | 5 +- 6 files changed, 136 insertions(+), 83 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index d95d7d6f02..69a330e63f 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->cellFaultResult()->customResultSlot()->setResultVariable(RimDefines::undefinedResultName()); + riv->cellFaultResult()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index d78a3534d9..249216a6fb 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -45,10 +45,10 @@ RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&m_visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); - CAF_PDM_InitFieldNoDefault(&customResultSlot, "CustomResultSlot", "Custom Cell Result", ":/CellResult.png", "", ""); - customResultSlot = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); + m_customResultSlot = new RimResultSlot(); updateVisibility(); } @@ -65,7 +65,8 @@ RimFaultResultSlot::~RimFaultResultSlot() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { - customResultSlot->setReservoirView(ownerReservoirView); + m_reservoirView = ownerReservoirView; + m_customResultSlot->setReservoirView(ownerReservoirView); } //-------------------------------------------------------------------------------------------------- @@ -73,12 +74,14 @@ void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (changedField == &visualizationMode) + if (changedField == &m_visualizationMode) { updateVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } + + if (m_reservoirView) m_reservoirView->createDisplayModelAndRedraw(); } //-------------------------------------------------------------------------------------------------- @@ -94,15 +97,28 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::updateVisibility() { - if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + if (this->m_visualizationMode() == FAULT_COLOR || this->m_visualizationMode() == CELL_RESULT_MAPPING) { - this->customResultSlot.setUiHidden(true); - this->customResultSlot.setUiChildrenHidden(true); + this->m_customResultSlot.setUiHidden(true); + this->m_customResultSlot.setUiChildrenHidden(true); } else { - this->customResultSlot.setUiHidden(false); - this->customResultSlot.setUiChildrenHidden(false); + this->m_customResultSlot.setUiHidden(false); + this->m_customResultSlot.setUiChildrenHidden(false); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimResultSlot* RimFaultResultSlot::customResultSlot() +{ + if (this->m_visualizationMode() == CUSTOM_RESULT_MAPPING) + { + return this->m_customResultSlot(); } + + return NULL; } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 2fa532d58a..4ff776ed04 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSlot : public caf::PdmObject +class RimFaultResultSlot : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -45,17 +45,18 @@ class RimFaultResultSlot : public caf::PdmObject virtual ~RimFaultResultSlot(); void setReservoirView(RimReservoirView* ownerReservoirView); - - caf::PdmField customResultSlot; + + RimResultSlot* customResultSlot(); + void updateVisibility(); protected: virtual void initAfterRead(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - void updateVisibility(); + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > m_visualizationMode; + caf::PdmField m_customResultSlot; -private: - caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + caf::PdmPointer m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index bba2901cc8..42da59e136 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -102,10 +102,8 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&cellFaultResult, "GridCellFaultResult", "Fault Cell Result", ":/CellResult.png", "", ""); - cellFaultResult = new RimFaultResultSlot(); - cellFaultResult.setUiHidden(true); - + CAF_PDM_InitFieldNoDefault(&faultResult, "GridCellFaultResult", "Fault Result", ":/CellResult.png", "", ""); + faultResult = new RimFaultResultSlot(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); @@ -167,7 +165,7 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); - this->cellFaultResult()->setReservoirView(this); + this->faultResult()->setReservoirView(this); m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); @@ -182,7 +180,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { - delete this->cellFaultResult(); + delete this->faultResult(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -521,10 +519,7 @@ void RimReservoirView::createDisplayModel() // Find the number of time frames the animation needs to show the requested data. - if (this->cellResult()->hasDynamicResult() - || this->propertyFilterCollection()->hasActiveDynamicFilters() - || this->wellCollection->hasVisibleWellPipes() - || this->cellResult()->isTernarySaturationSelected()) + if (isTimeStepDependentDataVisible()) { CVF_ASSERT(currentGridCellResults()); @@ -972,7 +967,7 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { - this->cellFaultResult()->setReservoirView(this); + this->faultResult()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); @@ -1392,45 +1387,76 @@ void RimReservoirView::updateLegends() RigCaseCellResultsData* results = eclipseCase->results(porosityModel); CVF_ASSERT(results); - if (this->cellResult()->hasResult()) + updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); + if (this->faultResult()->customResultSlot()) + { + updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResult()->customResultSlot(), results); + } + + if (this->cellEdgeResult()->hasResult()) { double globalMin, globalMax; double globalPosClosestToZero, globalNegClosestToZero; - results->minMaxCellScalarValues(this->cellResult()->gridScalarIndex(), globalMin, globalMax); - results->posNegClosestToZero(this->cellResult()->gridScalarIndex(), globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); + this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); + + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); + + m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); + this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); + } + else + { + this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirView::updateMinMaxValuesAndAddLegendToView(QString legendLabel, RimResultSlot* resultSlot, RigCaseCellResultsData* cellResultsData) +{ + if (resultSlot->hasResult()) + { + double globalMin, globalMax; + double globalPosClosestToZero, globalNegClosestToZero; + cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), globalMin, globalMax); + cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), globalPosClosestToZero, globalNegClosestToZero); double localMin, localMax; double localPosClosestToZero, localNegClosestToZero; - if (this->cellResult()->hasDynamicResult()) + if (resultSlot->hasDynamicResult()) { - results->minMaxCellScalarValues(this->cellResult()->gridScalarIndex(), m_currentTimeStep, localMin, localMax); - results->posNegClosestToZero(this->cellResult()->gridScalarIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); + cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), m_currentTimeStep, localMin, localMax); + cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); } else { - localMin = globalMin; - localMax = globalMax; + localMin = globalMin; + localMax = globalMax; - localPosClosestToZero = globalPosClosestToZero; - localNegClosestToZero = globalNegClosestToZero; + localPosClosestToZero = globalPosClosestToZero; + localNegClosestToZero = globalNegClosestToZero; } - this->cellResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); - this->cellResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); + resultSlot->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero); + resultSlot->legendConfig->setAutomaticRanges(globalMin, globalMax, localMin, localMax); - m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->legendConfig->legend()); - this->cellResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Cell Results: \n") + this->cellResult()->resultVariable())); + m_viewer->addColorLegendToBottomLeftCorner(resultSlot->legendConfig->legend()); + resultSlot->legendConfig->legend()->setTitle(cvfqt::Utils::toString(legendLabel + resultSlot->resultVariable())); } else { - this->cellResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); + resultSlot->legendConfig->setClosestToZeroValues(0, 0, 0, 0); + resultSlot->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); } - size_t maxTimeStepCount = results->maxTimeStepCount(); - if (this->cellResult()->isTernarySaturationSelected() && maxTimeStepCount > 1) + size_t maxTimeStepCount = cellResultsData->maxTimeStepCount(); + if (resultSlot->isTernarySaturationSelected() && maxTimeStepCount > 1) { - RimReservoirCellResultsStorage* gridCellResults = this->cellResult()->currentGridCellResults(); + RimReservoirCellResultsStorage* gridCellResults = resultSlot->currentGridCellResults(); { double globalMin = 0.0; double globalMax = 1.0; @@ -1440,10 +1466,10 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SOIL_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SOIL_IDX, globalMin, globalMax, localMin, localMax); } } @@ -1456,10 +1482,10 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SGAS_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SGAS_IDX, globalMin, globalMax, localMin, localMax); } } @@ -1472,37 +1498,18 @@ void RimReservoirView::updateLegends() size_t scalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); if (scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - results->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); - results->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, globalMin, globalMax); + cellResultsData->minMaxCellScalarValues(scalarSetIndex, m_currentTimeStep, localMin, localMax); - this->cellResult()->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SWAT_IDX, globalMin, globalMax, localMin, localMax); + resultSlot->ternaryLegendConfig()->setAutomaticRanges(RimTernaryLegendConfig::TERNARY_SWAT_IDX, globalMin, globalMax, localMin, localMax); } } - if (this->cellResult()->ternaryLegendConfig->legend()) + if (resultSlot->ternaryLegendConfig->legend()) { - m_viewer->addColorLegendToBottomLeftCorner(this->cellResult()->ternaryLegendConfig->legend()); + m_viewer->addColorLegendToBottomLeftCorner(resultSlot->ternaryLegendConfig->legend()); } } - - if (this->cellEdgeResult()->hasResult()) - { - double globalMin, globalMax; - double globalPosClosestToZero, globalNegClosestToZero; - this->cellEdgeResult()->minMaxCellEdgeValues(globalMin, globalMax); - this->cellEdgeResult()->posNegClosestToZero(globalPosClosestToZero, globalNegClosestToZero); - - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(globalPosClosestToZero, globalNegClosestToZero, globalPosClosestToZero, globalNegClosestToZero); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(globalMin, globalMax, globalMin, globalMax); - - m_viewer->addColorLegendToBottomLeftCorner(this->cellEdgeResult()->legendConfig->legend()); - this->cellEdgeResult()->legendConfig->legend()->setTitle(cvfqt::Utils::toString(QString("Edge Results: \n") + this->cellEdgeResult()->resultVariable)); - } - else - { - this->cellEdgeResult()->legendConfig->setClosestToZeroValues(0, 0, 0, 0); - this->cellEdgeResult()->legendConfig->setAutomaticRanges(cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE, cvf::UNDEFINED_DOUBLE); - } } //-------------------------------------------------------------------------------------------------- @@ -2044,9 +2051,15 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); + RimResultSlot* resultSlot = this->faultResult()->customResultSlot(); + if (!resultSlot) + { + resultSlot = this->cellResult(); + } + for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, this->cellResult()); + m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, resultSlot); } } @@ -2066,3 +2079,27 @@ void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf: } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimReservoirView::isTimeStepDependentDataVisible() const +{ + if (this->cellResult()->hasDynamicResult()) return true; + + if (this->propertyFilterCollection()->hasActiveDynamicFilters()) return true; + + if (this->wellCollection->hasVisibleWellPipes()) return true; + + if (this->cellResult()->isTernarySaturationSelected()) return true; + + if (this->faultResult->customResultSlot()) + { + if (this->faultResult->customResultSlot()->hasDynamicResult()) return true; + + if (this->faultResult->customResultSlot()->isTernarySaturationSelected()) return true; + } + + return false; +} + diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index f6a5ba96f5..7d9cb3c9e5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -33,6 +33,7 @@ #include "RivReservoirViewPartMgr.h" class RigActiveCellInfo; +class RigCaseCellResultsData; class RigGridBase; class RigGridCellFaceVisibilityFilter; class Rim3dOverlayInfoConfig; @@ -170,6 +171,7 @@ class RimReservoirView : public caf::PdmObject void loadDataAndUpdate(); void createDisplayModelAndRedraw(); void scheduleCreateDisplayModelAndRedraw(); + bool isTimeStepDependentDataVisible() const; void scheduleGeometryRegen(unsigned short geometryType); void scheduleReservoirGridGeometryRegen(); @@ -192,12 +194,12 @@ class RimReservoirView : public caf::PdmObject void updateStaticCellColors(); void updateStaticCellColors(unsigned short geometryType); void updateLegends(); + void updateMinMaxValuesAndAddLegendToView(QString legendLabel, RimResultSlot* resultSlot, RigCaseCellResultsData* cellResultsData); std::vector visibleFaultGeometryTypes() const; void updateFaultForcedVisibility(); void updateFaultColors(); - cvf::ref m_reservoirGridPartManager; cvf::ref m_pipesPartManager; diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index e8f7ca5c10..323e1acc4a 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -666,10 +666,7 @@ void RiuMainWindow::refreshAnimationActions() if (app->activeReservoirView()->currentGridCellResults()) { - if (app->activeReservoirView()->cellResult()->hasDynamicResult() - || app->activeReservoirView()->propertyFilterCollection()->hasActiveDynamicFilters() - || app->activeReservoirView()->wellCollection()->hasVisibleWellPipes() - || app->activeReservoirView()->cellResult()->isTernarySaturationSelected()) + if (app->activeReservoirView()->isTimeStepDependentDataVisible()) { std::vector timeStepDates = app->activeReservoirView()->currentGridCellResults()->cellResults()->timeStepDates(0); bool showHoursAndMinutes = false; From 11967c516154fd4a600bcf677eb08d25068f529b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:05:16 +0200 Subject: [PATCH 159/346] Preferences : Added support for pdm objects recursively --- .../Application/RiaApplication.cpp | 45 ++++++++++++++++--- ApplicationCode/Application/RiaApplication.h | 4 +- .../ProjectDataModel/RimReservoirView.h | 2 +- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 69a330e63f..afbab6c1d6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->cellFaultResult()->updateVisibility(); + riv->faultResult()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); @@ -1236,7 +1236,7 @@ bool RiaApplication::launchProcessForMultipleCases(const QString& program, const //-------------------------------------------------------------------------------------------------- /// Read fields of a Pdm object using QSettings //-------------------------------------------------------------------------------------------------- -void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) +void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object, const QString context) { QSettings settings; std::vector fields; @@ -1247,10 +1247,24 @@ void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) { caf::PdmFieldHandle* fieldHandle = fields[i]; - if (settings.contains(fieldHandle->keyword())) + std::vector children; + fieldHandle->childObjects(&children); + for (size_t childIdx = 0; childIdx < children.size(); childIdx++) { - QVariant val = settings.value(fieldHandle->keyword()); - fieldHandle->setValueFromUi(val); + caf::PdmObject* child = children[childIdx]; + QString subContext = context + child->classKeyword() + "/"; + readFieldsFromApplicationStore(child, subContext); + } + + + if (children.size() == 0) + { + QString key = context + fieldHandle->keyword(); + if (settings.contains(key)) + { + QVariant val = settings.value(key); + fieldHandle->setValueFromUi(val); + } } } } @@ -1258,7 +1272,7 @@ void RiaApplication::readFieldsFromApplicationStore(caf::PdmObject* object) //-------------------------------------------------------------------------------------------------- /// Write fields of a Pdm object using QSettings //-------------------------------------------------------------------------------------------------- -void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object) +void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object, const QString context) { CVF_ASSERT(object); @@ -1272,7 +1286,24 @@ void RiaApplication::writeFieldsToApplicationStore(const caf::PdmObject* object) { caf::PdmFieldHandle* fieldHandle = fields[i]; - settings.setValue(fieldHandle->keyword(), fieldHandle->uiValue()); + std::vector children; + fieldHandle->childObjects(&children); + for (size_t childIdx = 0; childIdx < children.size(); childIdx++) + { + caf::PdmObject* child = children[childIdx]; + QString subContext; + if (context.isEmpty()) + { + subContext = context + child->classKeyword() + "/"; + } + + writeFieldsToApplicationStore(child, subContext); + } + + if (children.size() == 0) + { + settings.setValue(context + fieldHandle->keyword(), fieldHandle->uiValue()); + } } } diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index d15203870f..d724644b94 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -132,8 +132,8 @@ class RiaApplication : public QApplication void terminateProcess(); RiaPreferences* preferences(); - void readFieldsFromApplicationStore(caf::PdmObject* object); - void writeFieldsToApplicationStore(const caf::PdmObject* object); + void readFieldsFromApplicationStore(caf::PdmObject* object, const QString context = ""); + void writeFieldsToApplicationStore(const caf::PdmObject* object, const QString context = ""); void applyPreferences(); cvf::Font* standardFont(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 7d9cb3c9e5..8c7ac5efaa 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField cellFaultResult; + caf::PdmField faultResult; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From 6416a6d71dee244ea4bac97c3a8b6af27e3e27ac Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:49:23 +0200 Subject: [PATCH 160/346] Fault result: Moved result mapping from collection to fault result --- .../RivReservoirFaultsPartMgr.cpp | 70 ++++++++++--------- .../RivReservoirFaultsPartMgr.h | 6 +- .../RivReservoirPartMgr.cpp | 4 +- .../ModelVisualization/RivReservoirPartMgr.h | 4 +- .../RivReservoirViewPartMgr.cpp | 12 ++-- .../ProjectDataModel/RimFaultResultSlot.cpp | 8 +-- .../ProjectDataModel/RimFaultResultSlot.h | 7 +- 7 files changed, 57 insertions(+), 54 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 48e73ff06f..929baaae94 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -27,18 +27,21 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" +#include "RimReservoirView.h" +#include "RimFaultResultSlot.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, const RimFaultCollection* faultCollection) -: m_faultCollection(faultCollection) +RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, RimReservoirView* reservoirView) +: m_reservoirView(reservoirView) { CVF_ASSERT(grid); - if (faultCollection) + if (reservoirView) { + RimFaultCollection* faultCollection = reservoirView->faultCollection(); for (size_t i = 0; i < faultCollection->faults.size(); i++) { m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); @@ -83,26 +86,27 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) { CVF_ASSERT(model != NULL); - if (!m_faultCollection) return; + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + if (!faultCollection) return; - bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); - if (!m_faultCollection->showFaultCollection() && !isShowingGrid) return; + bool isShowingGrid = faultCollection->isGridVisualizationMode(); + if (!faultCollection->showFaultCollection() && !isShowingGrid) return; // Check match between model fault count and fault parts - CVF_ASSERT(m_faultCollection->faults.size() == m_faultParts.size()); + CVF_ASSERT(faultCollection->faults.size() == m_faultParts.size()); cvf::ModelBasicList parts; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - const RimFault* rimFault = m_faultCollection->faults[i]; + const RimFault* rimFault = faultCollection->faults[i]; cvf::ref rivFaultPart = m_faultParts[i]; CVF_ASSERT(rivFaultPart.notNull()); // Parts that is overridden by the grid settings bool forceDisplayOfFault = false; - if (!m_faultCollection->showFaultsOutsideFilters()) + if (!faultCollection->showFaultsOutsideFilters()) { forceDisplayOfFault = isShowingGrid; } @@ -114,17 +118,17 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if (rimFault->showFault() || forceDisplayOfFault) { - if (m_faultCollection->showFaultFaces() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || forceDisplayOfFault) { rivFaultPart->appendNativeFaultFacesToModel(&parts); } - if (m_faultCollection->showOppositeFaultFaces() || forceDisplayOfFault) + if (faultCollection->showOppositeFaultFaces() || forceDisplayOfFault) { rivFaultPart->appendOppositeFaultFacesToModel(&parts); } - if (m_faultCollection->showFaultFaces() || m_faultCollection->showOppositeFaultFaces() || m_faultCollection->showNNCs() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || faultCollection->showNNCs() || forceDisplayOfFault) { rivFaultPart->appendMeshLinePartsToModel(&parts); } @@ -132,9 +136,9 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) // Parts that is not overridden by the grid settings - if (rimFault->showFault() && m_faultCollection->showFaultCollection()) + if (rimFault->showFault() && faultCollection->showFaultCollection()) { - if (m_faultCollection->showNNCs()) + if (faultCollection->showNNCs()) { rivFaultPart->appendNNCFacesToModel(&parts); } @@ -166,26 +170,22 @@ void RivReservoirFaultsPartMgr::applySingleColorEffect() //-------------------------------------------------------------------------------------------------- void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot* cellResultSlot) { - bool isShowingGrid = m_faultCollection->isGridVisualizationMode(); + if (!m_reservoirView) return; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + CVF_ASSERT(faultCollection); + + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - RimFault* rimFault = m_faultCollection->faults[i]; + RimFault* rimFault = faultCollection->faults[i]; - if (isShowingGrid) + if (m_reservoirView->faultResult()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + m_faultParts[i]->applySingleColorEffect(); } else { - if (m_faultCollection->showResultsOnFaults()) - { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); - } - else - { - m_faultParts[i]->applySingleColorEffect(); - } + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } } } @@ -207,21 +207,23 @@ void RivReservoirFaultsPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, void RivReservoirFaultsPartMgr::appendLabelPartsToModel(cvf::ModelBasicList* model) { CVF_ASSERT(model != NULL); + if (!m_reservoirView) return; - if (!m_faultCollection) return; + RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); + CVF_ASSERT(faultCollection); - if (!m_faultCollection->showFaultCollection()) return; + if (!faultCollection->showFaultCollection()) return; - if (!m_faultCollection->showFaultLabel() ) return; + if (!faultCollection->showFaultLabel() ) return; // Check match between model fault count and fault parts - CVF_ASSERT(m_faultCollection->faults.size() == m_faultParts.size()); + CVF_ASSERT(faultCollection->faults.size() == m_faultParts.size()); cvf::ModelBasicList parts; - for (size_t i = 0; i < m_faultCollection->faults.size(); i++) + for (size_t i = 0; i < faultCollection->faults.size(); i++) { - const RimFault* rimFault = m_faultCollection->faults[i]; + const RimFault* rimFault = faultCollection->faults[i]; cvf::ref rivFaultPart = m_faultParts[i]; CVF_ASSERT(rivFaultPart.notNull()); diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h index 105b20468f..3bc9c23587 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h @@ -31,7 +31,7 @@ namespace cvf class RimResultSlot; class RimCellEdgeResultSlot; -class RimFaultCollection; +class RimReservoirView; //================================================================================================== /// @@ -39,7 +39,7 @@ class RimFaultCollection; class RivReservoirFaultsPartMgr : public cvf::Object { public: - RivReservoirFaultsPartMgr(const RigMainGrid* grid, const RimFaultCollection* faultCollection); + RivReservoirFaultsPartMgr(const RigMainGrid* grid, RimReservoirView* reservoirView); ~RivReservoirFaultsPartMgr(); void setTransform(cvf::Transform* scaleTransform); @@ -59,7 +59,7 @@ class RivReservoirFaultsPartMgr : public cvf::Object private: cvf::ref m_scaleTransform; - const RimFaultCollection* m_faultCollection; + caf::PdmPointer m_reservoirView; cvf::Collection m_faultParts; bool m_forceVisibility; }; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 806bd08023..60dae98bd0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -28,7 +28,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection) +void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, RimReservoirView* reservoirView) { m_allGrids.clear(); @@ -44,7 +44,7 @@ void RivReservoirPartMgr::clearAndSetReservoir(const RigCaseData* eclipseCase, c if (eclipseCase->mainGrid()) { // Faults read from file are present only on main grid - m_faultsPartMgr = new RivReservoirFaultsPartMgr(eclipseCase->mainGrid(), faultCollection); + m_faultsPartMgr = new RivReservoirFaultsPartMgr(eclipseCase->mainGrid(), reservoirView); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index 7f07979603..6f7075aeac 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -33,7 +33,7 @@ class RimResultSlot; class RimCellEdgeResultSlot; class RivGridPartMgr; class RigCaseData; -class RimFaultCollection; +class RimReservoirView; //================================================================================================== /// @@ -45,7 +45,7 @@ class RimFaultCollection; class RivReservoirPartMgr: public cvf::Object { public: - void clearAndSetReservoir(const RigCaseData* eclipseCase, const RimFaultCollection* faultCollection); + void clearAndSetReservoir(const RigCaseData* eclipseCase, RimReservoirView* reservoirView); void setTransform(cvf::Transform* scaleTransform); void setCellVisibility(size_t gridIndex, cvf::UByteArray* cellVisibilities ); void setFaultForceVisibility(bool isGeneratedByFilter); diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 8f8e095c3e..8346961b45 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -152,7 +152,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom m_propFilteredGeometryFramesNeedsRegen[i] = true; if (m_propFilteredGeometryFrames[i].notNull()) { - m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_propFilteredGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView); m_propFilteredGeometryFrames[i]->setTransform(m_scaleTransform.p()); } } @@ -164,7 +164,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom m_propFilteredWellGeometryFramesNeedsRegen[i] = true; if (m_propFilteredWellGeometryFrames[i].notNull()) { - m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_propFilteredWellGeometryFrames[i]->clearAndSetReservoir(eclipseCase, m_reservoirView); m_propFilteredWellGeometryFrames[i]->setTransform(m_scaleTransform.p()); } } @@ -172,7 +172,7 @@ void RivReservoirViewPartMgr::clearGeometryCache(ReservoirGeometryCacheType geom else { m_geometriesNeedsRegen[geomType] = true; - m_geometries[geomType].clearAndSetReservoir(eclipseCase, m_reservoirView->faultCollection()); + m_geometries[geomType].clearAndSetReservoir(eclipseCase, m_reservoirView); m_geometries[geomType].setTransform(m_scaleTransform.p()); } } @@ -239,7 +239,7 @@ void RivReservoirViewPartMgr::appendDynamicGeometryPartsToModel(cvf::ModelBasicL void RivReservoirViewPartMgr::createGeometry(ReservoirGeometryCacheType geometryType) { RigCaseData* res = m_reservoirView->eclipseCase()->reservoirData(); - m_geometries[geometryType].clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_geometries[geometryType].clearAndSetReservoir(res, m_reservoirView); m_geometries[geometryType].setTransform(m_scaleTransform.p()); std::vector grids; @@ -395,7 +395,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredNoneWellCellGeometry(size_t if ( m_propFilteredGeometryFrames[frameIndex].isNull()) m_propFilteredGeometryFrames[frameIndex] = new RivReservoirPartMgr; - m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_propFilteredGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView); m_propFilteredGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p()); std::vector grids; @@ -472,7 +472,7 @@ void RivReservoirViewPartMgr::createPropertyFilteredWellGeometry(size_t frameInd if ( m_propFilteredWellGeometryFrames[frameIndex].isNull()) m_propFilteredWellGeometryFrames[frameIndex] = new RivReservoirPartMgr; - m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView->faultCollection()); + m_propFilteredWellGeometryFrames[frameIndex]->clearAndSetReservoir(res, m_reservoirView); m_propFilteredWellGeometryFrames[frameIndex]->setTransform(m_scaleTransform.p()); std::vector grids; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 249216a6fb..bb459ed023 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -45,7 +45,7 @@ RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&m_visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); m_customResultSlot = new RimResultSlot(); @@ -74,7 +74,7 @@ void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (changedField == &m_visualizationMode) + if (changedField == &visualizationMode) { updateVisibility(); @@ -97,7 +97,7 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::updateVisibility() { - if (this->m_visualizationMode() == FAULT_COLOR || this->m_visualizationMode() == CELL_RESULT_MAPPING) + if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) { this->m_customResultSlot.setUiHidden(true); this->m_customResultSlot.setUiChildrenHidden(true); @@ -114,7 +114,7 @@ void RimFaultResultSlot::updateVisibility() //-------------------------------------------------------------------------------------------------- RimResultSlot* RimFaultResultSlot::customResultSlot() { - if (this->m_visualizationMode() == CUSTOM_RESULT_MAPPING) + if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) { return this->m_customResultSlot(); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 4ff776ed04..c8d57151b6 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -43,10 +43,12 @@ class RimFaultResultSlot : public caf::PdmObject public: RimFaultResultSlot(); virtual ~RimFaultResultSlot(); - + void setReservoirView(RimReservoirView* ownerReservoirView); - RimResultSlot* customResultSlot(); + caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + + RimResultSlot* customResultSlot(); void updateVisibility(); protected: @@ -54,7 +56,6 @@ class RimFaultResultSlot : public caf::PdmObject virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - caf::PdmField< caf::AppEnum< FaultVisualizationMode > > m_visualizationMode; caf::PdmField m_customResultSlot; caf::PdmPointer m_reservoirView; From 7f4e5b266b1f9eda2b4d7f82e4a856ebc1958b97 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 10:53:38 +0200 Subject: [PATCH 161/346] Added missing pointer check --- .../ModelVisualization/RivReservoirFaultsPartMgr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 929baaae94..797e6244a4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -42,9 +42,12 @@ RivReservoirFaultsPartMgr::RivReservoirFaultsPartMgr(const RigMainGrid* grid, R if (reservoirView) { RimFaultCollection* faultCollection = reservoirView->faultCollection(); - for (size_t i = 0; i < faultCollection->faults.size(); i++) + if (faultCollection) { - m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); + for (size_t i = 0; i < faultCollection->faults.size(); i++) + { + m_faultParts.push_back(new RivFaultPartMgr(grid, faultCollection, faultCollection->faults[i])); + } } } From cdbc5829ab66ed87715569919143873cdbe32148 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 11:09:48 +0200 Subject: [PATCH 162/346] Fault result : Renamed file and improved interface --- .../Application/RiaApplication.cpp | 4 +- .../RivReservoirFaultsPartMgr.cpp | 4 +- .../ProjectDataModel/CMakeLists_files.cmake | 4 +- ...ultSlot.cpp => RimFaultResultSettings.cpp} | 46 +++++++++---------- ...tResultSlot.h => RimFaultResultSettings.h} | 15 +++--- .../ProjectDataModel/RimReservoirView.cpp | 31 +++++++------ .../ProjectDataModel/RimReservoirView.h | 4 +- 7 files changed, 56 insertions(+), 52 deletions(-) rename ApplicationCode/ProjectDataModel/{RimFaultResultSlot.cpp => RimFaultResultSettings.cpp} (64%) rename ApplicationCode/ProjectDataModel/{RimFaultResultSlot.h => RimFaultResultSettings.h} (82%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index afbab6c1d6..b6c68ecdba 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,7 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" @@ -650,7 +650,7 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->faultResult()->updateVisibility(); + riv->faultResultSettings()->updateVisibility(); RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 797e6244a4..8176d31b1c 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -28,7 +28,7 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" #include "RimReservoirView.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" //-------------------------------------------------------------------------------------------------- @@ -182,7 +182,7 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot { RimFault* rimFault = faultCollection->faults[i]; - if (m_reservoirView->faultResult()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index c9cb08a878..656f19e48e 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,7 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h -${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -95,7 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp -${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp similarity index 64% rename from ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp rename to ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index bb459ed023..548b86f878 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -27,28 +27,28 @@ namespace caf { template<> - void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() + void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() { - addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSlot::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); - addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSlot::CELL_RESULT_MAPPING); + addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSettings::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); + addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSettings::CELL_RESULT_MAPPING); } } -CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); +CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSlot::RimFaultResultSlot() +RimFaultResultSettings::RimFaultResultSettings() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_customResultSlot, "CustomResultSlot", "Custom Fault Cell Result", ":/CellResult.png", "", ""); - m_customResultSlot = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); + m_customFaultResult = new RimResultSlot(); updateVisibility(); } @@ -56,23 +56,23 @@ RimFaultResultSlot::RimFaultResultSlot() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSlot::~RimFaultResultSlot() +RimFaultResultSettings::~RimFaultResultSettings() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) +void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; - m_customResultSlot->setReservoirView(ownerReservoirView); + m_customFaultResult->setReservoirView(ownerReservoirView); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { if (changedField == &visualizationMode) { @@ -87,7 +87,7 @@ void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::initAfterRead() +void RimFaultResultSettings::initAfterRead() { updateVisibility(); } @@ -95,28 +95,28 @@ void RimFaultResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSlot::updateVisibility() +void RimFaultResultSettings::updateVisibility() { if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) { - this->m_customResultSlot.setUiHidden(true); - this->m_customResultSlot.setUiChildrenHidden(true); + this->m_customFaultResult.setUiHidden(true); + this->m_customFaultResult.setUiChildrenHidden(true); } else { - this->m_customResultSlot.setUiHidden(false); - this->m_customResultSlot.setUiChildrenHidden(false); + this->m_customFaultResult.setUiHidden(false); + this->m_customFaultResult.setUiChildrenHidden(false); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimResultSlot* RimFaultResultSlot::customResultSlot() +RimResultSlot* RimFaultResultSettings::customFaultResult() { if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) { - return this->m_customResultSlot(); + return this->m_customFaultResult(); } return NULL; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h similarity index 82% rename from ApplicationCode/ProjectDataModel/RimFaultResultSlot.h rename to ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index c8d57151b6..6c3b68e462 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSlot : public caf::PdmObject +class RimFaultResultSettings : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -41,23 +41,22 @@ class RimFaultResultSlot : public caf::PdmObject }; public: - RimFaultResultSlot(); - virtual ~RimFaultResultSlot(); + RimFaultResultSettings(); + virtual ~RimFaultResultSettings(); void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; - RimResultSlot* customResultSlot(); - void updateVisibility(); + RimResultSlot* customFaultResult(); + void updateVisibility(); protected: virtual void initAfterRead(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: - caf::PdmField m_customResultSlot; - - caf::PdmPointer m_reservoirView; + caf::PdmField m_customFaultResult; + caf::PdmPointer m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 42da59e136..fa9b2a2ed9 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,7 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSlot.h" +#include "RimFaultResultSettings.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -102,8 +102,8 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResult, "GridCellFaultResult", "Fault Result", ":/CellResult.png", "", ""); - faultResult = new RimFaultResultSlot(); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/CellResult.png", "", ""); + faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); @@ -165,7 +165,7 @@ RimReservoirView::RimReservoirView() this->cellEdgeResult()->legendConfig()->setPosition(cvf::Vec2ui(10, 320)); this->cellEdgeResult()->legendConfig()->setColorRangeMode(RimLegendConfig::PINK_WHITE); - this->faultResult()->setReservoirView(this); + this->faultResultSettings()->setReservoirView(this); m_reservoirGridPartManager = new RivReservoirViewPartMgr(this); @@ -180,7 +180,7 @@ RimReservoirView::RimReservoirView() //-------------------------------------------------------------------------------------------------- RimReservoirView::~RimReservoirView() { - delete this->faultResult(); + delete this->faultResultSettings(); delete this->cellResult(); delete this->cellEdgeResult(); delete this->overlayInfoConfig(); @@ -967,7 +967,7 @@ void RimReservoirView::loadDataAndUpdate() //-------------------------------------------------------------------------------------------------- void RimReservoirView::initAfterRead() { - this->faultResult()->setReservoirView(this); + this->faultResultSettings()->setReservoirView(this); this->cellResult()->setReservoirView(this); this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); @@ -1388,9 +1388,10 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResult()->customResultSlot()) + if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) { - updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResult()->customResultSlot(), results); + CVF_ASSERT(this->faultResultSettings()->customFaultResult()); + updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } if (this->cellEdgeResult()->hasResult()) @@ -2051,8 +2052,12 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = this->faultResult()->customResultSlot(); - if (!resultSlot) + RimResultSlot* resultSlot = NULL; + if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + { + resultSlot = this->faultResultSettings()->customFaultResult(); + } + else { resultSlot = this->cellResult(); } @@ -2093,11 +2098,11 @@ bool RimReservoirView::isTimeStepDependentDataVisible() const if (this->cellResult()->isTernarySaturationSelected()) return true; - if (this->faultResult->customResultSlot()) + if (this->faultResultSettings->customFaultResult()) { - if (this->faultResult->customResultSlot()->hasDynamicResult()) return true; + if (this->faultResultSettings->customFaultResult()->hasDynamicResult()) return true; - if (this->faultResult->customResultSlot()->isTernarySaturationSelected()) return true; + if (this->faultResultSettings->customFaultResult()->isTernarySaturationSelected()) return true; } return false; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 8c7ac5efaa..4ae47bf513 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -44,7 +44,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; -class RimFaultResultSlot; +class RimFaultResultSettings; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField faultResult; + caf::PdmField faultResultSettings; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; From fe712222cebff2ecb67ff492918a59b7c8407283 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 11:54:07 +0200 Subject: [PATCH 163/346] Recent files : Set last opened file first, remove file if load fails --- .../UserInterface/RiuMainWindow.cpp | 28 +++++++++++++++++-- ApplicationCode/UserInterface/RiuMainWindow.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 323e1acc4a..5e2b857ac4 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -957,14 +957,24 @@ void RiuMainWindow::slotOpenRecentFile() if (action) { QString filename = action->data().toString(); + bool loadingSucceded = false; if (filename.contains(".rsp", Qt::CaseInsensitive) || filename.contains(".rip", Qt::CaseInsensitive) ) { - RiaApplication::instance()->loadProject(action->data().toString()); + loadingSucceded = RiaApplication::instance()->loadProject(action->data().toString()); } else if ( filename.contains(".egrid", Qt::CaseInsensitive) || filename.contains(".grid", Qt::CaseInsensitive) ) { - RiaApplication::instance()->openEclipseCaseFromFile(filename); + loadingSucceded = RiaApplication::instance()->openEclipseCaseFromFile(filename); + } + + if (loadingSucceded) + { + addRecentFiles(filename); + } + else + { + removeRecentFiles(filename); } } } @@ -1009,6 +1019,20 @@ void RiuMainWindow::addRecentFiles(const QString& file) } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::removeRecentFiles(const QString& file) +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(file); + + settings.setValue("recentFileList", files); + + updateRecentFileActions(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 54da53911b..0e2aa40bee 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -113,6 +113,7 @@ class RiuMainWindow : public QMainWindow void updateRecentFileActions(); void addRecentFiles(const QString& file); + void removeRecentFiles(const QString& file); QMdiSubWindow* findMdiSubWindow(RiuViewer* viewer); From 73f29bb1154a76dd594dfee10f370c3bbeb7b20b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 12:23:15 +0200 Subject: [PATCH 164/346] Recent files : Show full path in tooltip --- .../UserInterface/RiuMainWindow.cpp | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 5e2b857ac4..a5c475fcfe 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -323,13 +323,53 @@ void RiuMainWindow::createActions() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class ToolTipableMenu : public QMenu +{ +public: + ToolTipableMenu( QWidget * parent ) : QMenu( parent ) {}; + + bool event(QEvent* e) + { + if (e->type() == QEvent::ToolTip) + { + QHelpEvent* he = dynamic_cast(e); + QAction* act = actionAt(he->pos()); + if (act) + { + // Remove ampersand as this is used to define shortcut key + QString actionTextWithoutAmpersand = act->text().remove("&"); + + if (actionTextWithoutAmpersand != act->toolTip()) + { + QToolTip::showText(he->globalPos(), act->toolTip(), this); + } + + return true; + } + } + else if (e->type() == QEvent::Paint && QToolTip::isVisible()) + { + QToolTip::hideText(); + } + + return QMenu::event(e); + } +}; + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuMainWindow::createMenus() { // File menu - QMenu* fileMenu = menuBar()->addMenu("&File"); + QMenu* fileMenu = new ToolTipableMenu(menuBar()); + fileMenu->setTitle("&File"); + + menuBar()->addMenu(fileMenu); fileMenu->addAction(m_openProjectAction); fileMenu->addAction(m_openLastUsedProjectAction); @@ -993,6 +1033,7 @@ void RiuMainWindow::updateRecentFileActions() QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); m_recentFileActions[i]->setText(text); m_recentFileActions[i]->setData(files[i]); + m_recentFileActions[i]->setToolTip(files[i]); m_recentFileActions[i]->setVisible(true); } for (int j = numRecentFiles; j < MaxRecentFiles; ++j) From 07b25a2f60d2a2f788cf681af80392485b3dd48e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 14:04:37 +0200 Subject: [PATCH 165/346] Added special handling to expand an item in tree view --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 12 ++++++++++++ ApplicationCode/UserInterface/RiuMainWindow.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index a5c475fcfe..e6cab5e794 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -2010,3 +2010,15 @@ void RiuMainWindow::appendActionsContextMenuForPdmObject(caf::PdmObject* pdmObje menu->addAction(m_openMultipleEclipseCasesAction); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindow::setExpanded(const caf::PdmObject* pdmObject, bool expanded) +{ + QModelIndex mi = m_treeModelPdm->getModelIndexFromPdmObject(pdmObject); + if (m_treeView && mi.isValid()) + { + m_treeView->setExpanded(mi, expanded); + } +} diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 0e2aa40bee..42e1a7c8f2 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -97,7 +97,8 @@ class RiuMainWindow : public QMainWindow void appendActionsContextMenuForPdmObject(caf::PdmObject* pdmObject, QMenu* menu); void refreshDrawStyleActions(); - + + void setExpanded(const caf::PdmObject* pdmObject, bool expanded); protected: virtual void closeEvent(QCloseEvent* event); From 51d4bd602388e944fc8b4a70670b97f73c45fcf3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 31 Jul 2014 14:05:40 +0200 Subject: [PATCH 166/346] Fault result : Moved config from FaultCollection to FaultResultSettings --- ApplicationCode/Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 4 ++-- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 5 +++-- .../ProjectDataModel/RimFaultCollection.cpp | 14 ++------------ .../ProjectDataModel/RimFaultCollection.h | 4 ---- .../ProjectDataModel/RimFaultResultSettings.cpp | 11 +++++++---- .../ProjectDataModel/RimFaultResultSettings.h | 2 ++ 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index b6c68ecdba..665e3af43a 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2066,7 +2066,7 @@ void RiaApplication::regressionTestConfigureProject() } riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); - riv->faultCollection->showResultsOnFaults.setValueFromUi(true); + riv->faultResultSettings->visualizationMode.setValueFromUi(RimFaultResultSettings::CELL_RESULT_MAPPING); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 8176d31b1c..5fc6bcb431 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -131,7 +131,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) rivFaultPart->appendOppositeFaultFacesToModel(&parts); } - if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || faultCollection->showNNCs() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || m_reservoirView->faultResultSettings()->showNNCs() || forceDisplayOfFault) { rivFaultPart->appendMeshLinePartsToModel(&parts); } @@ -141,7 +141,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if (rimFault->showFault() && faultCollection->showFaultCollection()) { - if (faultCollection->showNNCs()) + if (m_reservoirView->faultResultSettings()->showNNCs()) { rivFaultPart->appendNNCFacesToModel(&parts); } diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index f08a803814..f35932f066 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -23,12 +23,13 @@ #include "RimCase.h" #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimFaultResultSettings.h" #include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" #include "RimWellCollection.h" #include "RiuViewer.h" -#include "RimFaultCollection.h" CAF_PDM_SOURCE_INIT(Rim3dOverlayInfoConfig, "View3dOverlayInfoConfig"); @@ -159,7 +160,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("" "
MinP10 Mean P90 Max
%1 %2 %3 %4 %5
").arg(min).arg(p10).arg(mean).arg(p90).arg(max); - if (m_reservoirView->faultCollection()->showResultsOnFaults()) + if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSettings::FAULT_COLOR) { QString faultMapping; bool isShowingGrid = m_reservoirView->faultCollection()->isGridVisualizationMode(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index e634f26644..8aac2a264f 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -57,13 +57,8 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showFaultCollection, "Active", true, "Active", "", "", ""); showFaultCollection.setUiHidden(true); - CAF_PDM_InitField(&showGeometryDetectedFaults, "ShowGeometryDetectedFaults", false, "Show geometry detected faults", "", "", ""); - showGeometryDetectedFaults.setUiHidden(true); - CAF_PDM_InitField(&showFaultFaces, "ShowFaultFaces", true, "Show defined faces", "", "", ""); CAF_PDM_InitField(&showOppositeFaultFaces, "ShowOppositeFaultFaces", true, "Show opposite faces", "", "", ""); - CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitField(&showResultsOnFaults, "ShowResultsOnFaults", true, "Show results on faults", "", "", ""); CAF_PDM_InitField(&showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); CAF_PDM_InitField(&faultResult, "FaultFaceCulling", caf::AppEnum(RimFaultCollection::FAULT_BACK_FACE_CULLING), "Dynamic Face Selection", "", "", ""); @@ -101,16 +96,13 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel m_reservoirView->scheduleReservoirGridGeometryRegen(); } - if (&showGeometryDetectedFaults == changedField || - &showFaultFaces == changedField || + if (&showFaultFaces == changedField || &showOppositeFaultFaces == changedField || - &showNNCs == changedField || &showFaultCollection == changedField || &showFaultLabel == changedField || &showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || - &faultResult == changedField || - &showResultsOnFaults == changedField + &faultResult == changedField ) { if (m_reservoirView) @@ -266,8 +258,6 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi caf::PdmUiGroup* adv = uiOrdering.addNewGroup("Fault Options"); adv->add(&showFaultsOutsideFilters); - adv->add(&showResultsOnFaults); - adv->add(&showNNCs); caf::PdmUiGroup* ffviz = uiOrdering.addNewGroup("Fault Face Visibility"); ffviz->add(&showFaultFaces); diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 39b1fe982a..b5fbc7b759 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -58,13 +58,9 @@ class RimFaultCollection : public caf::PdmObject bool isGridVisualizationMode() const; - caf::PdmField showGeometryDetectedFaults; // Obsolete, to be removed - caf::PdmField showFaultFaces; caf::PdmField showOppositeFaultFaces; caf::PdmField showFaultsOutsideFilters; - caf::PdmField showNNCs; - caf::PdmField showResultsOnFaults; caf::PdmField > faultResult; diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index 548b86f878..ab1bd59fe4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -46,11 +46,12 @@ RimFaultResultSettings::RimFaultResultSettings() CAF_PDM_InitObject("Fault Result Slot", "", "", ""); CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); - m_customFaultResult = new RimResultSlot(); + CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); + m_customFaultResult = new RimResultSlot(); - updateVisibility(); + updateVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -79,9 +80,11 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed updateVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + + RiuMainWindow::instance()->setExpanded(this, true); } - if (m_reservoirView) m_reservoirView->createDisplayModelAndRedraw(); + if (m_reservoirView) m_reservoirView->scheduleCreateDisplayModelAndRedraw(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 6c3b68e462..05aa4f0dad 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -47,6 +47,8 @@ class RimFaultResultSettings : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; + caf::PdmField showNNCs; + RimResultSlot* customFaultResult(); void updateVisibility(); From d7f569360c1b1d423eeaf4865ffd592d8661e399 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 07:53:15 +0200 Subject: [PATCH 167/346] Fault result: Updated icon --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index fa9b2a2ed9..c9472be7d4 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -102,7 +102,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/CellResult.png", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/draw_style_faults_24x24.png", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); From 09f7868eb561ae41f425862abd9f89f954732950 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 08:15:22 +0200 Subject: [PATCH 168/346] Preferences : Updated default values --- ApplicationCode/Application/RiaPreferences.cpp | 2 +- ApplicationCode/FileInterface/RifReaderSettings.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 337084d979..2e36180a84 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -42,7 +42,7 @@ RiaPreferences::RiaPreferences(void) octaveExecutable.setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); octaveExecutable.setUiLabelPosition(caf::PdmUiItemInfo::TOP); - CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", true, "Show text header when executing scripts", "", "", ""); + CAF_PDM_InitField(&octaveShowHeaderInfoWhenExecutingScripts, "octaveShowHeaderInfoWhenExecutingScripts", false, "Show text header when executing scripts", "", "", ""); octaveShowHeaderInfoWhenExecutingScripts.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); CAF_PDM_InitField(&ssihubAddress, "ssihubAddress", QString("http://"), "ssihub Address", "", "", ""); diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp index e3a743d188..c2b05aaa4e 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.cpp +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -30,13 +30,13 @@ RifReaderSettings::RifReaderSettings() { CAF_PDM_InitObject("RifReaderSettings", "", "", ""); - CAF_PDM_InitField(&importFaults, "importFaults", false, "Import faults", "", "", ""); + CAF_PDM_InitField(&importFaults, "importFaults", true, "Import faults", "", "", ""); importFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", false, "Import simulation wells", "", "", ""); + CAF_PDM_InitField(&importSimulationWellData, "importSimulationWellData", true, "Import simulation wells", "", "", ""); importSimulationWellData.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", false, "Import NNCs", "", "", ""); + CAF_PDM_InitField(&importNNCs, "importSimulationNNCs", true, "Import NNCs", "", "", ""); importNNCs.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); } From 8b04e2a2e8008e4f4e20982d8db9ee79ff9fa340 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 08:46:46 +0200 Subject: [PATCH 169/346] Ternary legend : Added title --- .../RivTernarySaturationOverlayItem.cpp | 41 +++++++++++++++---- .../RivTernarySaturationOverlayItem.h | 7 +++- .../ProjectDataModel/RimReservoirView.cpp | 2 + .../RimTernaryLegendConfig.cpp | 2 +- .../ProjectDataModel/RimTernaryLegendConfig.h | 3 +- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 651297c813..2160d0eb53 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -121,11 +121,25 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con cvf::TextDrawer textDrawer(m_font.p()); textDrawer.setTextColor(m_textColor); + float lineHeightInPixels = 10; + + float textPosY = static_cast(size.y() - 10); + for (size_t it = 0; it < m_titleStrings.size(); it++) + { + cvf::Vec2f pos(5, textPosY); + textDrawer.addText(m_titleStrings[it], pos); + + textPosY -= lineHeightInPixels; + } + + textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY)); + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY - lineHeightInPixels)); + textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); textDrawer.addText(m_swatRange, cvf::Vec2f(0.0, 0.0)); textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - 25), 10.0)); - + float soilRangePos = static_cast(size.x() - 40); if (m_soilRange.size() < 6) { @@ -133,12 +147,9 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con } textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); - textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), static_cast(size.y() - 10))); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), static_cast(size.y() - 20))); - textDrawer.renderSoftware(oglContext, camera); - renderAxisImmediateMode(oglContext); + renderAxisImmediateMode(textPosY - lineHeightInPixels, oglContext); CVF_CHECK_OGL(oglContext); } @@ -148,7 +159,7 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con //-------------------------------------------------------------------------------------------------- /// Draw the axis using immediate mode OpenGL //-------------------------------------------------------------------------------------------------- -void RivTernarySaturationOverlayItem::renderAxisImmediateMode(cvf::OpenGLContext* oglContext) +void RivTernarySaturationOverlayItem::renderAxisImmediateMode(float upperBoundY, cvf::OpenGLContext* oglContext) { #ifdef CVF_OPENGL_ES CVF_UNUSED(layout); @@ -166,7 +177,7 @@ void RivTernarySaturationOverlayItem::renderAxisImmediateMode(cvf::OpenGLContext cvf::Color3ub colC(cvf::Color3::RED); float lowerBoundY = 20; - float upperBoundY = static_cast(m_size.y() - 20); + //float upperBoundY = static_cast(m_size.y() - 20); cvf::Vec3f a(0, lowerBoundY, 0); cvf::Vec3f b(static_cast(m_size.x()), lowerBoundY, 0); @@ -219,4 +230,20 @@ void RivTernarySaturationOverlayItem::setRangeText(const cvf::String& soilRange, m_swatRange = swatRange; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernarySaturationOverlayItem::setTitle(const cvf::String& title) +{ + // Title + if (title.isEmpty()) + { + m_titleStrings.clear(); + } + else + { + m_titleStrings = title.split("\n"); + } +} + diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h index ca145cf496..a016060560 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h @@ -48,12 +48,13 @@ class RivTernarySaturationOverlayItem : public cvf::OverlayItem virtual void renderSoftware(cvf::OpenGLContext* oglContext, const cvf::Vec2i& position, const cvf::Vec2ui& size); void setSize(const cvf::Vec2ui& size); - void setAxisLabelsColor(const cvf::Color3f& color); + void setTitle(const cvf::String& title); + private: void render(cvf::OpenGLContext* oglContext, const cvf::Vec2i& position, const cvf::Vec2ui& size, bool software); - void renderAxisImmediateMode(cvf::OpenGLContext* oglContext); + void renderAxisImmediateMode(float upperY, cvf::OpenGLContext* oglContext); private: cvf::Color3f m_textColor; // Text color @@ -64,5 +65,7 @@ class RivTernarySaturationOverlayItem : public cvf::OverlayItem cvf::String m_swatRange; cvf::Vec2ui m_size; // Pixel size of draw area + + std::vector m_titleStrings; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index c9472be7d4..ca8ada6732 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -40,6 +40,7 @@ #include "RiuViewer.h" #include "RivReservoirPipesPartMgr.h" #include "RivWellPathCollectionPartMgr.h" +#include "RivTernarySaturationOverlayItem.h" #include "cafCadNavigation.h" #include "cafCeetronPlusNavigation.h" @@ -1508,6 +1509,7 @@ void RimReservoirView::updateMinMaxValuesAndAddLegendToView(QString legendLabel, if (resultSlot->ternaryLegendConfig->legend()) { + resultSlot->ternaryLegendConfig->legend()->setTitle(cvfqt::Utils::toString(legendLabel)); m_viewer->addColorLegendToBottomLeftCorner(resultSlot->ternaryLegendConfig->legend()); } } diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 4f5a9bcde6..6da31598c9 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -298,7 +298,7 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::OverlayItem* RimTernaryLegendConfig::legend() +RivTernarySaturationOverlayItem* RimTernaryLegendConfig::legend() { return m_legend.p(); } diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h index 6697441da9..79c94d5d11 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -69,7 +69,8 @@ class RimTernaryLegendConfig : public caf::PdmObject void ternaryRanges(double& soilLower, double& soilUpper, double& sgasLower, double& sgasUpper, double& swatLower, double& swatUpper) const; void recreateLegend(); - cvf::OverlayItem* legend(); + + RivTernarySaturationOverlayItem* legend(); protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); From b2f80c7ef9711605b57ae5f0126c4fa9a7bdf691 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 09:40:35 +0200 Subject: [PATCH 170/346] Fault result : Use checkbox to enable custom fault visualization When checkbox is disabled, faults are visualized using current cell visualization. When checkbox is activated, fault colors or custom fault result is active --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 3 ++- .../RimFaultResultSettings.cpp | 25 +++++++++++++++---- .../ProjectDataModel/RimFaultResultSettings.h | 9 ++++--- .../ProjectDataModel/RimReservoirView.cpp | 11 +++----- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 665e3af43a..023836cbd6 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2066,7 +2066,7 @@ void RiaApplication::regressionTestConfigureProject() } riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); - riv->faultResultSettings->visualizationMode.setValueFromUi(RimFaultResultSettings::CELL_RESULT_MAPPING); + riv->faultResultSettings->showCustomFaultResult.setValueFromUi(false); } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 5fc6bcb431..f1284c9a3f 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -182,7 +182,8 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot { RimFault* rimFault = faultCollection->faults[i]; - if (m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->showCustomFaultResult() && + m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index ab1bd59fe4..3da4e842c4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -30,9 +30,8 @@ namespace caf void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() { addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSettings::CELL_RESULT_MAPPING, "CELL_RESULT_MAPPING", "Grid Cell Results"); addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSettings::CELL_RESULT_MAPPING); + setDefault(RimFaultResultSettings::FAULT_COLOR); } } @@ -45,7 +44,10 @@ RimFaultResultSettings::RimFaultResultSettings() { CAF_PDM_InitObject("Fault Result Slot", "", "", ""); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::CELL_RESULT_MAPPING), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); + showCustomFaultResult.setUiHidden(true); + + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::FAULT_COLOR), "Fault Color Mapping", "", "", ""); CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); @@ -75,6 +77,11 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { + if (&showCustomFaultResult == changedField) + { + this->updateUiIconFromState(showCustomFaultResult); + } + if (changedField == &visualizationMode) { updateVisibility(); @@ -100,7 +107,7 @@ void RimFaultResultSettings::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::updateVisibility() { - if (this->visualizationMode() == FAULT_COLOR || this->visualizationMode() == CELL_RESULT_MAPPING) + if (this->visualizationMode() == FAULT_COLOR) { this->m_customFaultResult.setUiHidden(true); this->m_customFaultResult.setUiChildrenHidden(true); @@ -117,7 +124,7 @@ void RimFaultResultSettings::updateVisibility() //-------------------------------------------------------------------------------------------------- RimResultSlot* RimFaultResultSettings::customFaultResult() { - if (this->visualizationMode() == CUSTOM_RESULT_MAPPING) + if (showCustomFaultResult() && this->visualizationMode() == CUSTOM_RESULT_MAPPING) { return this->m_customFaultResult(); } @@ -125,3 +132,11 @@ RimResultSlot* RimFaultResultSettings::customFaultResult() return NULL; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() +{ + return &showCustomFaultResult; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 05aa4f0dad..85edd71fef 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -36,7 +36,6 @@ class RimFaultResultSettings : public caf::PdmObject enum FaultVisualizationMode { FAULT_COLOR, - CELL_RESULT_MAPPING, CUSTOM_RESULT_MAPPING }; @@ -47,15 +46,17 @@ class RimFaultResultSettings : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; - caf::PdmField showNNCs; + caf::PdmField showNNCs; + caf::PdmField showCustomFaultResult; RimResultSlot* customFaultResult(); void updateVisibility(); protected: - virtual void initAfterRead(); - virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + virtual void initAfterRead(); + virtual caf::PdmFieldHandle* objectToggleField(); + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); private: caf::PdmField m_customFaultResult; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ca8ada6732..d97ba1ec22 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1389,9 +1389,8 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + if (this->faultResultSettings()->customFaultResult()) { - CVF_ASSERT(this->faultResultSettings()->customFaultResult()); updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } @@ -2054,15 +2053,11 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = NULL; - if (this->faultResultSettings()->visualizationMode() == RimFaultResultSettings::CUSTOM_RESULT_MAPPING) + RimResultSlot* resultSlot = this->cellResult(); + if (this->faultResultSettings()->customFaultResult()) { resultSlot = this->faultResultSettings()->customFaultResult(); } - else - { - resultSlot = this->cellResult(); - } for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { From 86b74e383e54f4364ff2b6b4ab5c39cacc0a6281 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 12:07:26 +0200 Subject: [PATCH 171/346] Do nothing if no source tree can be created --- Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp b/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp index 5c5718e878..4e5832b608 100644 --- a/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafUiTreeModelPdm.cpp @@ -392,6 +392,7 @@ void UiTreeModelPdm::updateUiSubTree(PdmObject* pdmRoot) // Build the new "Correct" Tree PdmUiTreeItem* tempUpdatedPdmTree = UiTreeItemBuilderPdm::buildViewItems(NULL, -1, pdmRoot); + if (!tempUpdatedPdmTree) return; // Find the corresponding entry for "root" in the existing Ui tree From 79fbe6568683ce5165664d104e38f2b858b2cd37 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 12:55:43 +0200 Subject: [PATCH 172/346] Fault result: Moved fault result up one level in tree view --- .../Application/RiaApplication.cpp | 3 - .../RimFaultResultSettings.cpp | 68 +++++++++++++------ .../ProjectDataModel/RimFaultResultSettings.h | 5 +- .../ProjectDataModel/RimReservoirView.cpp | 13 ++-- .../ProjectDataModel/RimResultDefinition.cpp | 44 ++++++------ .../ProjectDataModel/RimResultDefinition.h | 5 +- .../ProjectDataModel/RimResultSlot.cpp | 2 + .../ProjectDataModel/RimResultSlot.h | 1 + 8 files changed, 91 insertions(+), 50 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 023836cbd6..9dfa6d43e7 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -650,9 +650,6 @@ bool RiaApplication::openEclipseCase(const QString& caseName, const QString& cas riv->cellResult()->setResultVariable(RimDefines::undefinedResultName()); } - riv->faultResultSettings()->updateVisibility(); - - RimUiTreeModelPdm* uiModel = RiuMainWindow::instance()->uiPdmModel(); uiModel->updateUiSubTree(analysisModels); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index 3da4e842c4..e709ec62df 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -42,7 +42,7 @@ CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- RimFaultResultSettings::RimFaultResultSettings() { - CAF_PDM_InitObject("Fault Result Slot", "", "", ""); + CAF_PDM_InitObject("Fault Result Slot", ":/draw_style_faults_24x24.png", "", ""); CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); @@ -52,8 +52,15 @@ RimFaultResultSettings::RimFaultResultSettings() CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); m_customFaultResult = new RimResultSlot(); + m_customFaultResult.setOwnerObject(this); + m_customFaultResult.setUiHidden(true); - updateVisibility(); + // Take ownership of the fields in RimResultDefinition to be able to trap fieldChangedByUi in this class + m_customFaultResult->m_resultTypeUiField.setOwnerObject(this); + m_customFaultResult->m_porosityModelUiField.setOwnerObject(this); + m_customFaultResult->m_resultVariableUiField.setOwnerObject(this); + + updateFieldVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -77,18 +84,20 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showCustomFaultResult == changedField) - { - this->updateUiIconFromState(showCustomFaultResult); - } + this->updateUiIconFromState(showCustomFaultResult); + + m_customFaultResult->fieldChangedByUi(changedField, oldValue, newValue); if (changedField == &visualizationMode) { - updateVisibility(); + updateFieldVisibility(); RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); + } - RiuMainWindow::instance()->setExpanded(this, true); + if (changedField == &m_customFaultResult->m_resultVariableUiField) + { + RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); } if (m_reservoirView) m_reservoirView->scheduleCreateDisplayModelAndRedraw(); @@ -99,24 +108,18 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::initAfterRead() { - updateVisibility(); + m_customFaultResult->initAfterRead(); + updateFieldVisibility(); + + this->updateUiIconFromState(showCustomFaultResult); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::updateVisibility() +void RimFaultResultSettings::updateFieldVisibility() { - if (this->visualizationMode() == FAULT_COLOR) - { - this->m_customFaultResult.setUiHidden(true); - this->m_customFaultResult.setUiChildrenHidden(true); - } - else - { - this->m_customFaultResult.setUiHidden(false); - this->m_customFaultResult.setUiChildrenHidden(false); - } + m_customFaultResult->updateFieldVisibility(); } //-------------------------------------------------------------------------------------------------- @@ -140,3 +143,28 @@ caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() return &showCustomFaultResult; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +{ + uiOrdering.add(&visualizationMode); + uiOrdering.add(&showNNCs); + + if (visualizationMode == CUSTOM_RESULT_MAPPING) + { + caf::PdmUiGroup* group1 = uiOrdering.addNewGroup("Result"); + group1->add(&(m_customFaultResult->m_resultTypeUiField)); + group1->add(&(m_customFaultResult->m_porosityModelUiField)); + group1->add(&(m_customFaultResult->m_resultVariableUiField)); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimFaultResultSettings::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +{ + return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h index 85edd71fef..3c07267547 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h @@ -51,12 +51,15 @@ class RimFaultResultSettings : public caf::PdmObject RimResultSlot* customFaultResult(); - void updateVisibility(); + void updateFieldVisibility(); + + virtual QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly ); protected: virtual void initAfterRead(); virtual caf::PdmFieldHandle* objectToggleField(); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); + virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) ; private: caf::PdmField m_customFaultResult; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index d97ba1ec22..2f5de1eab5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -103,7 +103,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", ":/draw_style_faults_24x24.png", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", "", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); @@ -933,14 +933,15 @@ void RimReservoirView::loadDataAndUpdate() CVF_ASSERT(this->cellResult() != NULL); this->cellResult()->loadResult(); - if (m_reservoir->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) - { - this->cellResult->setPorosityModelUiFieldHidden(true); - } - CVF_ASSERT(this->cellEdgeResult() != NULL); this->cellEdgeResult()->loadResult(); + if (this->faultResultSettings()->customFaultResult()) + { + this->faultResultSettings()->customFaultResult()->loadResult(); + } + this->faultResultSettings()->updateFieldVisibility(); + updateViewerWidget(); this->propertyFilterCollection()->loadAndInitializePropertyFilters(); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 7d16b522e6..52a64404d1 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -38,7 +38,7 @@ RimResultDefinition::RimResultDefinition() CAF_PDM_InitFieldNoDefault(&m_resultType, "ResultType", "Type", "", "", ""); m_resultType.setUiHidden(true); - CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Type", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_porosityModel, "PorosityModelType", "Porosity", "", "", ""); m_porosityModel.setUiHidden(true); CAF_PDM_InitField(&m_resultVariable, "ResultVariable", RimDefines::undefinedResultName(), "Variable", "", "", "" ); m_resultVariable.setUiHidden(true); @@ -46,7 +46,7 @@ RimResultDefinition::RimResultDefinition() CAF_PDM_InitFieldNoDefault(&m_resultTypeUiField, "MResultType", "Type", "", "", ""); m_resultTypeUiField.setIOReadable(false); m_resultTypeUiField.setIOWritable(false); - CAF_PDM_InitFieldNoDefault(&m_porosityModelUiField, "MPorosityModelType", "Type", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_porosityModelUiField, "MPorosityModelType", "Porosity", "", "", ""); m_porosityModelUiField.setIOReadable(false); m_porosityModelUiField.setIOWritable(false); CAF_PDM_InitField(&m_resultVariableUiField, "MResultVariable", RimDefines::undefinedResultName(), "Result property", "", "", "" ); @@ -72,16 +72,7 @@ void RimResultDefinition::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; - // TODO: This code is executed before reservoir is read, and then porosity model is never set to zero - if (m_reservoirView->eclipseCase() && - m_reservoirView->eclipseCase()->reservoirData() && - m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) - { - if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) - { - m_porosityModelUiField.setUiHidden(true); - } - } + updateFieldVisibility(); } QStringList RimResultDefinition::getResultVariableListForCurrentUIFieldSettings() @@ -220,6 +211,8 @@ void RimResultDefinition::loadResult() gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); } } + + updateFieldVisibility(); } @@ -332,18 +325,31 @@ void RimResultDefinition::setResultVariable(const QString& val) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimResultDefinition::setPorosityModelUiFieldHidden(bool hide) +bool RimResultDefinition::isTernarySaturationSelected() const { - m_porosityModelUiField.setUiHidden(true); + bool isTernary = (m_resultType() == RimDefines::DYNAMIC_NATIVE) && + (m_resultVariable().compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0); + + return isTernary; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimResultDefinition::isTernarySaturationSelected() const +void RimResultDefinition::updateFieldVisibility() { - bool isTernary = (m_resultType() == RimDefines::DYNAMIC_NATIVE) && - (m_resultVariable().compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0); - - return isTernary; + if (m_reservoirView && + m_reservoirView->eclipseCase() && + m_reservoirView->eclipseCase()->reservoirData() && + m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) + { + if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) + { + m_porosityModelUiField.setUiHidden(true); + } + else + { + m_porosityModelUiField.setUiHidden(false); + } + } } diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index f399262ee2..a725da96d8 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -49,7 +49,6 @@ class RimResultDefinition : public caf::PdmObject void setPorosityModel(RimDefines::PorosityModelType val); QString resultVariable() const { return m_resultVariable(); } virtual void setResultVariable(const QString& val); - void setPorosityModelUiFieldHidden(bool hide); void loadResult(); size_t gridScalarIndex() const; @@ -71,6 +70,7 @@ class RimResultDefinition : public caf::PdmObject caf::PdmField m_resultVariable; friend class RimCellPropertyFilter; + friend class RimFaultResultSettings; // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultTypeUiField; caf::PdmField< caf::AppEnum< RimDefines::PorosityModelType > > m_porosityModelUiField; @@ -81,6 +81,9 @@ class RimResultDefinition : public caf::PdmObject caf::PdmPointer m_reservoirView; +protected: + void updateFieldVisibility(); + private: QStringList getResultVariableListForCurrentUIFieldSettings(); }; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index dc7af09867..7ceb23ad01 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -154,6 +154,8 @@ void RimResultSlot::initAfterRead() //-------------------------------------------------------------------------------------------------- void RimResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { + RimResultDefinition::setReservoirView(ownerReservoirView); + m_reservoirView = ownerReservoirView; this->legendConfig()->setReservoirView(ownerReservoirView); std::list >::iterator it; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index 390b3cc053..da5a8b932c 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -44,6 +44,7 @@ class RimResultSlot : public RimResultDefinition virtual void setResultVariable(const QString& resultName); protected: + friend class RimFaultResultSettings; virtual void initAfterRead(); private: From e814246e2239286f3849d5192edb002533ff8ada Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:03:05 +0200 Subject: [PATCH 173/346] Fault result : Renamed in tree view --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 2f5de1eab5..0e17b8eca9 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -103,7 +103,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result Settings", "", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result", "", "", ""); faultResultSettings = new RimFaultResultSettings(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); From c579c614043655cefe1f6b6d3f8535d0961aace1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:35:28 +0200 Subject: [PATCH 174/346] Fwk: Update enabled state for icons based on object toggle field --- Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp | 12 ++++++++++++ Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp index d752765d8e..d32c20c4fa 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.cpp @@ -464,5 +464,17 @@ void PdmObject::addUiTreeChildren(PdmUiTreeOrdering* root, QString uiConfigName } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObject::updateUiIconFromToggleField() +{ + if (objectToggleField()) + { + bool active = objectToggleField()->uiValue().toBool(); + updateUiIconFromState(active); + } +} + } //End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 94eb759c48..457a8b1371 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -174,6 +174,8 @@ class PdmObject : public PdmUiItem /// Return object editor specific parameters used to customize the editor behavior. void objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute); + void updateUiIconFromToggleField(); + // Virtual interface to override in subclasses to support special behaviour if needed public: // Virtual virtual PdmFieldHandle* userDescriptionField() { return NULL; } @@ -196,7 +198,8 @@ class PdmObject : public PdmUiItem protected: // Virtual /// Method gets called from PdmDocument after all objects are read. /// Re-implement to set up internal pointers etc. in your data structure - virtual void initAfterRead() {}; + virtual void initAfterRead() { updateUiIconFromToggleField(); }; + /// Method gets called from PdmDocument before saving document. /// Re-implement to make sure your fields have correct data before saving virtual void setupBeforeSave() {}; From 0550f9df8c62e9d3ec387c579bcf42f7be617443 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 13:35:52 +0200 Subject: [PATCH 175/346] Improved handling of icon enabled state --- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 2 +- .../ProjectDataModel/RimCellPropertyFilterCollection.cpp | 4 +++- .../ProjectDataModel/RimCellRangeFilterCollection.cpp | 5 +++-- ApplicationCode/ProjectDataModel/RimFault.cpp | 5 +---- ApplicationCode/ProjectDataModel/RimFaultCollection.cpp | 7 ++----- .../ProjectDataModel/RimFaultResultSettings.cpp | 4 ++-- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimResultDefinition.cpp | 2 ++ ApplicationCode/ProjectDataModel/RimWellCollection.cpp | 2 +- ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp | 2 ++ 10 files changed, 20 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index f35932f066..250f5a00ee 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -82,7 +82,7 @@ void Rim3dOverlayInfoConfig::setPosition(cvf::Vec2ui position) //-------------------------------------------------------------------------------------------------- void Rim3dOverlayInfoConfig::update3DInfo() { - this->updateUiIconFromState(active); + this->updateUiIconFromToggleField(); if (!m_reservoirView) return; if (!m_reservoirView->viewer()) return; diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp index 9c4b2bcfb3..c1024f6c3a 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp @@ -76,7 +76,7 @@ RimReservoirView* RimCellPropertyFilterCollection::reservoirView() //-------------------------------------------------------------------------------------------------- void RimCellPropertyFilterCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - this->updateUiIconFromState(active); + this->updateUiIconFromToggleField(); m_reservoirView->fieldChangedByUi(&(m_reservoirView->propertyFilterCollection), oldValue, newValue); } @@ -131,6 +131,8 @@ void RimCellPropertyFilterCollection::loadAndInitializePropertyFilters() void RimCellPropertyFilterCollection::initAfterRead() { loadAndInitializePropertyFilters(); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp index 7d1a6ec91f..6c1a7bde75 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp @@ -138,7 +138,7 @@ RigActiveCellInfo* RimCellRangeFilterCollection::activeCellInfo() const //-------------------------------------------------------------------------------------------------- void RimCellRangeFilterCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - updateUiIconFromState(isActive); + this->updateUiIconFromToggleField(); CVF_ASSERT(m_reservoirView); @@ -184,8 +184,9 @@ void RimCellRangeFilterCollection::initAfterRead() RimCellRangeFilter* rangeFilter = *it; rangeFilter->setParentContainer(this); rangeFilter->updateIconState(); - } + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFault.cpp b/ApplicationCode/ProjectDataModel/RimFault.cpp index cbb223c56c..b0d1c99d4d 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.cpp +++ b/ApplicationCode/ProjectDataModel/RimFault.cpp @@ -63,10 +63,7 @@ caf::PdmFieldHandle* RimFault::userDescriptionField() //-------------------------------------------------------------------------------------------------- void RimFault::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showFault == changedField) - { - this->updateUiIconFromState(showFault); - } + this->updateUiIconFromToggleField(); if (&faultColor == changedField || &showFault == changedField) { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 8aac2a264f..87ad6441cc 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -86,11 +86,8 @@ RimFaultCollection::~RimFaultCollection() //-------------------------------------------------------------------------------------------------- void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - if (&showFaultCollection == changedField) - { - this->updateUiIconFromState(showFaultCollection); - } - + this->updateUiIconFromToggleField(); + if (&faultLabelColor == changedField) { m_reservoirView->scheduleReservoirGridGeometryRegen(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp index e709ec62df..9ba1391503 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp @@ -84,7 +84,7 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { - this->updateUiIconFromState(showCustomFaultResult); + this->updateUiIconFromToggleField(); m_customFaultResult->fieldChangedByUi(changedField, oldValue, newValue); @@ -111,7 +111,7 @@ void RimFaultResultSettings::initAfterRead() m_customFaultResult->initAfterRead(); updateFieldVisibility(); - this->updateUiIconFromState(showCustomFaultResult); + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 0e17b8eca9..345ec4d235 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -415,7 +415,7 @@ void RimReservoirView::fieldChangedByUi(const caf::PdmFieldHandle* changedField, } } - this->updateUiIconFromState(showWindow); + this->updateUiIconFromToggleField(); } else if (changedField == &backgroundColor ) { @@ -974,6 +974,8 @@ void RimReservoirView::initAfterRead() this->cellEdgeResult()->setReservoirView(this); this->rangeFilterCollection()->setReservoirView(this); this->propertyFilterCollection()->setReservoirView(this); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 52a64404d1..b61801dc61 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -293,6 +293,8 @@ void RimResultDefinition::initAfterRead() m_porosityModelUiField = m_porosityModel; m_resultTypeUiField = m_resultType; m_resultVariableUiField = m_resultVariable; + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp index 710e1948a3..a4efac4ea8 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp @@ -190,7 +190,7 @@ void RimWellCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField { if (&showWellLabel == changedField || &isActive == changedField) { - this->updateUiIconFromState(isActive); + this->updateUiIconFromToggleField(); if (m_reservoirView) { diff --git a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp index fa61910c5b..17d8fe61da 100644 --- a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp +++ b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp @@ -89,6 +89,8 @@ void RimOilFieldEntry::fieldChangedByUi(const caf::PdmFieldHandle* changedField, void RimOilFieldEntry::initAfterRead() { updateEnabledState(); + + this->updateUiIconFromToggleField(); } //-------------------------------------------------------------------------------------------------- From 39dc1421c45a20637d4534420316490572cfa496 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 1 Aug 2014 14:48:37 +0200 Subject: [PATCH 176/346] Fault visibility : Restructured code --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 2 +- .../ProjectDataModel/RimFaultCollection.cpp | 24 ++++++++++++++++--- .../ProjectDataModel/RimFaultCollection.h | 7 ++++-- .../ProjectDataModel/RimReservoirView.cpp | 10 ++++---- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9dfa6d43e7..0f84a4413e 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -2062,7 +2062,7 @@ void RiaApplication::regressionTestConfigureProject() riv->viewer()->setFixedSize(1000, 745); } - riv->faultCollection->showFaultsOutsideFilters.setValueFromUi(false); + riv->faultCollection->setShowFaultsOutsideFilters(false); riv->faultResultSettings->showCustomFaultResult.setValueFromUi(false); } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index f1284c9a3f..fcf3c7d7f7 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -119,7 +119,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) forceDisplayOfFault = true; } - if (rimFault->showFault() || forceDisplayOfFault) + if ( (faultCollection->showFaultCollection() && rimFault->showFault()) || forceDisplayOfFault) { if (faultCollection->showFaultFaces() || forceDisplayOfFault) { diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 87ad6441cc..dbdda464e4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -59,7 +59,7 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showFaultFaces, "ShowFaultFaces", true, "Show defined faces", "", "", ""); CAF_PDM_InitField(&showOppositeFaultFaces, "ShowOppositeFaultFaces", true, "Show opposite faces", "", "", ""); - CAF_PDM_InitField(&showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); + CAF_PDM_InitField(&m_showFaultsOutsideFilters,"ShowFaultsOutsideFilters", true, "Show faults outside filters", "", "", ""); CAF_PDM_InitField(&faultResult, "FaultFaceCulling", caf::AppEnum(RimFaultCollection::FAULT_BACK_FACE_CULLING), "Dynamic Face Selection", "", "", ""); @@ -97,7 +97,7 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel &showOppositeFaultFaces == changedField || &showFaultCollection == changedField || &showFaultLabel == changedField || - &showFaultsOutsideFilters == changedField || + &m_showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || &faultResult == changedField ) @@ -254,7 +254,7 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi labs->add(&faultLabelColor); caf::PdmUiGroup* adv = uiOrdering.addNewGroup("Fault Options"); - adv->add(&showFaultsOutsideFilters); + adv->add(&m_showFaultsOutsideFilters); caf::PdmUiGroup* ffviz = uiOrdering.addNewGroup("Fault Face Visibility"); ffviz->add(&showFaultFaces); @@ -262,3 +262,21 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi ffviz->add(&faultResult); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultCollection::showFaultsOutsideFilters() const +{ + if (!showFaultCollection) return false; + + return m_showFaultsOutsideFilters; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultCollection::setShowFaultsOutsideFilters(bool enableState) +{ + m_showFaultsOutsideFilters = enableState; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index b5fbc7b759..f940209d77 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -57,10 +57,12 @@ class RimFaultCollection : public caf::PdmObject void syncronizeFaults(); bool isGridVisualizationMode() const; + + bool showFaultsOutsideFilters() const; + void setShowFaultsOutsideFilters(bool enableState); caf::PdmField showFaultFaces; caf::PdmField showOppositeFaultFaces; - caf::PdmField showFaultsOutsideFilters; caf::PdmField > faultResult; @@ -80,6 +82,7 @@ class RimFaultCollection : public caf::PdmObject virtual void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ); private: - RimReservoirView* m_reservoirView; + caf::PdmField m_showFaultsOutsideFilters; + RimReservoirView* m_reservoirView; }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 345ec4d235..e0eecb863d 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -620,7 +620,7 @@ void RimReservoirView::createDisplayModel() m_visibleGridParts = geometryTypesToAdd; } - if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters) + if (!this->propertyFilterCollection()->hasActiveFilters() || faultCollection()->showFaultsOutsideFilters()) { updateFaultForcedVisibility(); @@ -714,7 +714,7 @@ void RimReservoirView::updateCurrentTimeStep() geometriesToRecolor.push_back( RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS); m_reservoirGridPartManager->appendDynamicGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS, m_currentTimeStep, gridIndices); - if (faultCollection()->showFaultsOutsideFilters) + if (faultCollection()->showFaultsOutsideFilters()) { std::vector faultGeometryTypesToAppend = visibleFaultGeometryTypes(); @@ -748,7 +748,7 @@ void RimReservoirView::updateCurrentTimeStep() { m_reservoirGridPartManager->appendStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE, gridIndices); - if (!faultCollection()->showFaultsOutsideFilters) + if (!faultCollection()->showFaultsOutsideFilters()) { m_reservoirGridPartManager->appendFaultsStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::RANGE_FILTERED_INACTIVE); } @@ -757,7 +757,7 @@ void RimReservoirView::updateCurrentTimeStep() { m_reservoirGridPartManager->appendStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::INACTIVE, gridIndices); - if (!faultCollection()->showFaultsOutsideFilters) + if (!faultCollection()->showFaultsOutsideFilters()) { m_reservoirGridPartManager->appendFaultsStaticGeometryPartsToModel(frameParts.p(), RivReservoirViewPartMgr::INACTIVE); } @@ -1980,7 +1980,7 @@ std::vector RimReservoirVie { std::vector faultParts; - if (this->propertyFilterCollection()->hasActiveFilters() && !faultCollection()->showFaultsOutsideFilters) + if (this->propertyFilterCollection()->hasActiveFilters() && !faultCollection()->showFaultsOutsideFilters()) { faultParts.push_back(RivReservoirViewPartMgr::PROPERTY_FILTERED); faultParts.push_back(RivReservoirViewPartMgr::PROPERTY_FILTERED_WELL_CELLS); From eec7f59c495b49cdca112276de0eb047811f2001 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:39:52 +0200 Subject: [PATCH 177/346] Rename --- .../ReservoirDataModel/RigGridScalarDataAccess.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp index 655e8939ae..1a83658480 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp @@ -84,10 +84,10 @@ void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, d //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -class RigGridMatrixActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess { public: - RigGridMatrixActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + RigGridActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_activeCellInfo(activeCellInfo) @@ -186,7 +186,7 @@ cvf::ref RigGridScalarDataAccessFactory::create bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigGridMatrixActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + cvf::ref object = new RigGridActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); return object; } else From b5d1c639666d4c6e58dcbd11a70b15a1c4d1cd9e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:47:27 +0200 Subject: [PATCH 178/346] Renamed to RimFaultResultSlot --- .../Application/RiaApplication.cpp | 2 +- .../RivReservoirFaultsPartMgr.cpp | 4 +-- .../ProjectDataModel/CMakeLists_files.cmake | 4 +-- .../Rim3dOverlayInfoConfig.cpp | 4 +-- ...ultSettings.cpp => RimFaultResultSlot.cpp} | 34 +++++++++---------- ...tResultSettings.h => RimFaultResultSlot.h} | 6 ++-- .../ProjectDataModel/RimReservoirView.cpp | 4 +-- .../ProjectDataModel/RimReservoirView.h | 4 +-- .../ProjectDataModel/RimResultDefinition.h | 2 +- .../ProjectDataModel/RimResultSlot.h | 2 +- 10 files changed, 33 insertions(+), 33 deletions(-) rename ApplicationCode/ProjectDataModel/{RimFaultResultSettings.cpp => RimFaultResultSlot.cpp} (80%) rename ApplicationCode/ProjectDataModel/{RimFaultResultSettings.h => RimFaultResultSlot.h} (94%) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 0f84a4413e..9c9e323a52 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -40,7 +40,7 @@ #include "RimOilField.h" #include "RimAnalysisModels.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "cafCeetronNavigation.h" #include "cafCadNavigation.h" diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index fcf3c7d7f7..7a418eb3ba 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -28,7 +28,7 @@ #include "RimFaultCollection.h" #include "RigMainGrid.h" #include "RimReservoirView.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" //-------------------------------------------------------------------------------------------------- @@ -183,7 +183,7 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot RimFault* rimFault = faultCollection->faults[i]; if (m_reservoirView->faultResultSettings()->showCustomFaultResult() && - m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSettings::FAULT_COLOR) + m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) { m_faultParts[i]->applySingleColorEffect(); } diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 656f19e48e..c9cb08a878 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -48,7 +48,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.h ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h -${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.h +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -95,7 +95,7 @@ ${CEE_CURRENT_LIST_DIR}RimFault.cpp ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp -${CEE_CURRENT_LIST_DIR}RimFaultResultSettings.cpp +${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 250f5a00ee..752f4894f7 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -24,7 +24,7 @@ #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -160,7 +160,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("" "
MinP10 Mean P90 Max
%1 %2 %3 %4 %5
").arg(min).arg(p10).arg(mean).arg(p90).arg(max); - if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSettings::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSlot::FAULT_COLOR) { QString faultMapping; bool isShowingGrid = m_reservoirView->faultCollection()->isGridVisualizationMode(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp similarity index 80% rename from ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp rename to ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 9ba1391503..dfdbcadf48 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" @@ -27,27 +27,27 @@ namespace caf { template<> - void AppEnum< RimFaultResultSettings::FaultVisualizationMode >::setUp() + void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() { - addItem(RimFaultResultSettings::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSettings::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSettings::FAULT_COLOR); + addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); + addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); + setDefault(RimFaultResultSlot::FAULT_COLOR); } } -CAF_PDM_SOURCE_INIT(RimFaultResultSettings, "RimFaultResultSlot"); +CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSettings::RimFaultResultSettings() +RimFaultResultSlot::RimFaultResultSlot() { CAF_PDM_InitObject("Fault Result Slot", ":/draw_style_faults_24x24.png", "", ""); CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSettings::FAULT_COLOR), "Fault Color Mapping", "", "", ""); + CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::FAULT_COLOR), "Fault Color Mapping", "", "", ""); CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); @@ -66,14 +66,14 @@ RimFaultResultSettings::RimFaultResultSettings() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFaultResultSettings::~RimFaultResultSettings() +RimFaultResultSlot::~RimFaultResultSlot() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirView) +void RimFaultResultSlot::setReservoirView(RimReservoirView* ownerReservoirView) { m_reservoirView = ownerReservoirView; m_customFaultResult->setReservoirView(ownerReservoirView); @@ -82,7 +82,7 @@ void RimFaultResultSettings::setReservoirView(RimReservoirView* ownerReservoirVi //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) +void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { this->updateUiIconFromToggleField(); @@ -106,7 +106,7 @@ void RimFaultResultSettings::fieldChangedByUi(const caf::PdmFieldHandle* changed //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::initAfterRead() +void RimFaultResultSlot::initAfterRead() { m_customFaultResult->initAfterRead(); updateFieldVisibility(); @@ -117,7 +117,7 @@ void RimFaultResultSettings::initAfterRead() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::updateFieldVisibility() +void RimFaultResultSlot::updateFieldVisibility() { m_customFaultResult->updateFieldVisibility(); } @@ -125,7 +125,7 @@ void RimFaultResultSettings::updateFieldVisibility() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimResultSlot* RimFaultResultSettings::customFaultResult() +RimResultSlot* RimFaultResultSlot::customFaultResult() { if (showCustomFaultResult() && this->visualizationMode() == CUSTOM_RESULT_MAPPING) { @@ -138,7 +138,7 @@ RimResultSlot* RimFaultResultSettings::customFaultResult() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() +caf::PdmFieldHandle* RimFaultResultSlot::objectToggleField() { return &showCustomFaultResult; } @@ -146,7 +146,7 @@ caf::PdmFieldHandle* RimFaultResultSettings::objectToggleField() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) +void RimFaultResultSlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { uiOrdering.add(&visualizationMode); uiOrdering.add(&showNNCs); @@ -163,7 +163,7 @@ void RimFaultResultSettings::defineUiOrdering(QString uiConfigName, caf::PdmUiOr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList RimFaultResultSettings::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +QList RimFaultResultSlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h similarity index 94% rename from ApplicationCode/ProjectDataModel/RimFaultResultSettings.h rename to ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 3c07267547..07d4be9a53 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSettings.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -29,7 +29,7 @@ class RimReservoirView; /// /// //================================================================================================== -class RimFaultResultSettings : public caf::PdmObject +class RimFaultResultSlot : public caf::PdmObject { CAF_PDM_HEADER_INIT; public: @@ -40,8 +40,8 @@ class RimFaultResultSettings : public caf::PdmObject }; public: - RimFaultResultSettings(); - virtual ~RimFaultResultSettings(); + RimFaultResultSlot(); + virtual ~RimFaultResultSlot(); void setReservoirView(RimReservoirView* ownerReservoirView); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index e0eecb863d..fe969de1ac 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -28,7 +28,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimCellRangeFilterCollection.h" #include "RimFaultCollection.h" -#include "RimFaultResultSettings.h" +#include "RimFaultResultSlot.h" #include "RimOilField.h" #include "RimProject.h" #include "RimResultSlot.h" @@ -104,7 +104,7 @@ RimReservoirView::RimReservoirView() cellEdgeResult = new RimCellEdgeResultSlot(); CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result", "", "", ""); - faultResultSettings = new RimFaultResultSettings(); + faultResultSettings = new RimFaultResultSlot(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); overlayInfoConfig = new Rim3dOverlayInfoConfig(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 4ae47bf513..36568bc8f0 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -44,7 +44,7 @@ class RimCellPropertyFilterCollection; class RimCellRangeFilter; class RimCellRangeFilterCollection; class RimFaultCollection; -class RimFaultResultSettings; +class RimFaultResultSlot; class RimReservoirCellResultsStorage; class RimReservoirCellResultsStorage; class RimResultSlot; @@ -98,7 +98,7 @@ class RimReservoirView : public caf::PdmObject caf::PdmField cellResult; caf::PdmField cellEdgeResult; - caf::PdmField faultResultSettings; + caf::PdmField faultResultSettings; caf::PdmField rangeFilterCollection; caf::PdmField propertyFilterCollection; diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index a725da96d8..462709a898 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -70,7 +70,7 @@ class RimResultDefinition : public caf::PdmObject caf::PdmField m_resultVariable; friend class RimCellPropertyFilter; - friend class RimFaultResultSettings; + friend class RimFaultResultSlot; // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultTypeUiField; caf::PdmField< caf::AppEnum< RimDefines::PorosityModelType > > m_porosityModelUiField; diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index da5a8b932c..f39250f7ad 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -44,7 +44,7 @@ class RimResultSlot : public RimResultDefinition virtual void setResultVariable(const QString& resultName); protected: - friend class RimFaultResultSettings; + friend class RimFaultResultSlot; virtual void initAfterRead(); private: From 75541e92fbe2c48ad62c53a7c15a5eac4ee7180b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 12:56:41 +0200 Subject: [PATCH 179/346] Renamed to RigResultAccessObjectFactory --- .../RivReservoirViewPartMgr.cpp | 2 +- .../ReservoirDataModel/CMakeLists_files.cmake | 4 +- .../ReservoirDataModel/RigCaseData.cpp | 4 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../RigGridScalarDataAccess.cpp | 4 +- .../RigResultAccessObjectFactory.cpp | 198 ++++++++++++++++++ ...ccess.h => RigResultAccessObjectFactory.h} | 4 +- 7 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp rename ApplicationCode/ReservoirDataModel/{RigGridScalarDataAccess.h => RigResultAccessObjectFactory.h} (92%) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 8346961b45..284985349c 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -23,7 +23,7 @@ #include "RigCaseData.h" #include "RigGridBase.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "RimCase.h" #include "RimCellRangeFilterCollection.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index aace5df653..fb9614f179 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,7 +10,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h -${CEE_CURRENT_LIST_DIR}RigGridScalarDataAccess.h +${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -30,7 +30,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp -${CEE_CURRENT_LIST_DIR}RigGridScalarDataAccess.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index c9483020e0..741dc86ee8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -19,7 +19,7 @@ #include "RigCaseData.h" #include "RigMainGrid.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" //-------------------------------------------------------------------------------------------------- /// @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigGridScalarDataAccessFactory::createPerGridDataAccessObject( this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessObjectFactory::createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index dc602d41ed..4c195270da 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -20,7 +20,7 @@ #include "RigMainGrid.h" #include "RigCell.h" #include "RigCaseCellResultsData.h" -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "cvfAssert.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp index 1a83658480..218d8fb2f2 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigGridScalarDataAccess.h" +#include "RigResultAccessObjectFactory.h" #include "cvfLibCore.h" #include "cvfBase.h" @@ -146,7 +146,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigGridScalarDataAccessFactory::createPerGridDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp new file mode 100644 index 0000000000..218d8fb2f2 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -0,0 +1,198 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultAccessObjectFactory.h" + +#include "cvfLibCore.h" +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfAssert.h" + +#include "RigMainGrid.h" +#include "RigCaseCellResultsData.h" +#include "RigActiveCellInfo.h" +#include "RigGridBase.h" +#include "RigCaseData.h" +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RigGridAllCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +{ +public: + RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues); + + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual void setCellScalar(size_t cellIndex, double value); + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigGridAllCellsScalarDataAccess::RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues) +{ + CVF_ASSERT(reservoirResultValues != NULL); + CVF_ASSERT(grid != NULL); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) const +{ + if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(globalGridCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess +{ +public: + RigGridActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo) + { + + CVF_ASSERT(grid != NULL); + } + + virtual double cellScalar(size_t gridLocalCellIndex) const + { + if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; + + CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(resultValueIndex); + } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; + } + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + + + +class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess +{ +public: + virtual double cellScalar(size_t cellIndex) const + { + return HUGE_VAL; + } + virtual void setCellScalar(size_t cellIndex, double value) + { + } +}; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarSetIndex) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); + + // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps + // See RiaSetGridProperty command in RiaPropertyDataCommands + // + // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) + { + cvf::ref object = new StructGridScalarDataAccessHugeVal; + + return object; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigGridActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigGridAllCellsScalarDataAccess(grid, resultValues); + return object; + } +} + diff --git a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h similarity index 92% rename from ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index d098829f66..2183cd0fd1 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridScalarDataAccess.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -25,11 +25,11 @@ class RigActiveCellInfo; class RigGridBase; -class RigGridScalarDataAccessFactory +class RigResultAccessObjectFactory { public: static cvf::ref - createPerGridDataAccessObject(RigCaseData* eclipseCase, + createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From fa7e50526237a9ee8e8836dfa48abd43c12b1322 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 13:14:38 +0200 Subject: [PATCH 180/346] Added RigResultAccessObject --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigResultAccessObject.cpp | 19 +++++ .../RigResultAccessObject.h | 75 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index fb9614f179..66f639fd08 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,6 +10,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h +${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h @@ -30,6 +31,7 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp new file mode 100644 index 0000000000..6d732c7309 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp @@ -0,0 +1,19 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultAccessObject.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h new file mode 100644 index 0000000000..021efe6846 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" + + +class RigResultAccessObject : public cvf::Object +{ +public: + virtual double cellScalar(size_t localCellIndex) const = 0; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + + virtual void setCellScalar(size_t cellIndex, double value) = 0; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ From cb8edaffdef459ebe7257abd16715630f9827a66 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 13:47:15 +0200 Subject: [PATCH 181/346] Added data access objects for native results --- .../ReservoirDataModel/CMakeLists_files.cmake | 4 + .../RigActiveCellsResultAccessObject.cpp | 76 +++++++++++++++++ .../RigActiveCellsResultAccessObject.h | 83 +++++++++++++++++++ .../RigAllGridCellsResultAccessObject.cpp | 72 ++++++++++++++++ .../RigAllGridCellsResultAccessObject.h | 81 ++++++++++++++++++ .../RigResultAccessObject.h | 5 +- .../RigResultAccessObjectFactory.cpp | 2 +- .../RigResultAccessObjectFactory.h | 2 +- 8 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h create mode 100644 ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 66f639fd08..31552802cb 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -12,6 +12,8 @@ ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -33,6 +35,8 @@ ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp new file mode 100644 index 0000000000..3cfddaf58f --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigActiveCellsResultAccessObject.h" + +#include "RigGridBase.h" +#include "RigActiveCellInfo.h" + +RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo), + m_resultName(resultName) +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const +{ + if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; + + CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(resultValueIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(localCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigActiveCellsResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigActiveCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; +} diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h new file mode 100644 index 0000000000..1bcb18d66a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +class RigGridBase; +class RigActiveCellInfo; + + +//================================================================================================== +/// +//================================================================================================== +class RigActiveCellsResultAccessObject : public RigResultAccessObject +{ +public: + RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; + QString m_resultName; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp new file mode 100644 index 0000000000..1d7b0ff8f1 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigAllGridCellsResultAccessObject.h" + +#include "RigGridBase.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_resultName(resultName) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) const +{ + if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; + + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + return m_reservoirResultValues->at(globalGridCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(localCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigAllGridCellsResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigAllGridCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; +} diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h new file mode 100644 index 0000000000..c503960ef5 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigActiveCellsResultAccessObject.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigAllGridCellsResultAccessObject : public RigResultAccessObject +{ +public: + RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; + QString m_resultName; +}; + + +/* + +class CellFaceScalarDataAccess : public Object +{ +public: + virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; +}; + +class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess +{ +public: + PlainCellFaceScalarDataAccess() + { + cellEdgeDataAccessObjects.resize(6); + } + + void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) + { + cellEdgeDataAccessObjects[faceId] = dataAccessObject; + } + + virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const + { + cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; + if (dataAccessObj != NULL) + { + return dataAccessObj->cellScalar(cellIndex); + } + + return HUGE_VAL; + } +private: + cvf::Collection cellEdgeDataAccessObjects; +}; + +*/ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 021efe6846..caf9640931 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -25,6 +25,9 @@ #include "cvfStructGrid.h" +//================================================================================================== +/// +//================================================================================================== class RigResultAccessObject : public cvf::Object { public: @@ -33,7 +36,7 @@ class RigResultAccessObject : public cvf::Object virtual QString resultName() const = 0; - virtual void setCellScalar(size_t cellIndex, double value) = 0; + virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index 218d8fb2f2..e47a35e2d5 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index 2183cd0fd1..d19a8ff386 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 1d3ba4637d1728890be5bf87660029700c9fec23 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 14:04:26 +0200 Subject: [PATCH 182/346] Added RigCellFaceResultAccessObject --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigActiveCellsResultAccessObject.h | 37 --------- .../RigAllGridCellsResultAccessObject.h | 36 -------- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../RigCellFaceResultAccessObject.cpp | 82 +++++++++++++++++++ .../RigCellFaceResultAccessObject.h | 45 ++++++++++ .../RigResultAccessObject.h | 37 --------- .../RigResultAccessObjectFactory.cpp | 2 +- .../RigResultAccessObjectFactory.h | 10 ++- 9 files changed, 140 insertions(+), 113 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 31552802cb..154b885bd0 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -14,6 +14,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -37,6 +38,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 1bcb18d66a..901fe90638 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -44,40 +44,3 @@ class RigActiveCellsResultAccessObject : public RigResultAccessObject QString m_resultName; }; - -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h index c503960ef5..86eb65ecb5 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -43,39 +43,3 @@ class RigAllGridCellsResultAccessObject : public RigResultAccessObject }; -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 741dc86ee8..3b1dfebeca 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigResultAccessObjectFactory::createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp new file mode 100644 index 0000000000..808d8b7708 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCellFaceResultAccessObject.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resultName) + : m_resultName(resultName) +{ + m_resultAccessObjects.resize(6); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +{ + m_resultAccessObjects[faceId] = resultAccessObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const +{ + + // TODO: How to handle when we get here? + CVF_ASSERT(false); + + return cvf::UNDEFINED_DOUBLE; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(faceId); + if (resultAccessObj != NULL) + { + return resultAccessObj->cellFaceScalar(localCellIndex, faceId); + } + + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigCellFaceResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCellFaceResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + // TODO: How to handle when we get here? + CVF_ASSERT(false); + +} + diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h new file mode 100644 index 0000000000..27afad5aea --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +#include "cvfCollection.h" + + +//================================================================================================== +/// +//================================================================================================== +class RigCellFaceResultAccessObject : public RigResultAccessObject +{ +public: + RigCellFaceResultAccessObject(const QString& resultName); + + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + cvf::Collection m_resultAccessObjects; + + QString m_resultName; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index caf9640931..8d723b567b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -39,40 +39,3 @@ class RigResultAccessObject : public cvf::Object virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; - -/* - -class CellFaceScalarDataAccess : public Object -{ -public: - virtual double cellFaceScalar(size_t cellIndex, cvf::StructGridInterface faceId) const = 0; -}; - -class PlainCellFaceScalarDataAccess : public CellFaceScalarDataAccess -{ -public: - PlainCellFaceScalarDataAccess() - { - cellEdgeDataAccessObjects.resize(6); - } - - void setDataAccessObjectForFace(cvf::StructGridInterface faceId, cvf::StructGridScalarDataAccess* dataAccessObject) - { - cellEdgeDataAccessObjects[faceId] = dataAccessObject; - } - - virtual double cellFaceScalar( size_t cellIndex, cvf::StructGridInterface faceId ) const - { - cvf::StructGridScalarDataAccess* dataAccessObj = cellEdgeDataAccessObjects[faceId]; - if (dataAccessObj != NULL) - { - return dataAccessObj->cellScalar(cellIndex); - } - - return HUGE_VAL; - } -private: - cvf::Collection cellEdgeDataAccessObjects; -}; - -*/ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index e47a35e2d5..d093fca77b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -146,7 +146,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index d19a8ff386..b50adc5240 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -28,8 +28,16 @@ class RigGridBase; class RigResultAccessObjectFactory { public: + + + + + + + + // TO BE DELETED static cvf::ref - createNativeDataAccessObject(RigCaseData* eclipseCase, + TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From cba742d44c9c915d6623ed3ae7543f44b76c1071 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 14:18:02 +0200 Subject: [PATCH 183/346] Linux: Added include of cmath for define of HUGE_VAL --- .../ReservoirDataModel/RigActiveCellsResultAccessObject.cpp | 3 +++ .../ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp index 3cfddaf58f..6552f938f7 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -21,6 +21,9 @@ #include "RigGridBase.h" #include "RigActiveCellInfo.h" +#include + + RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp index 1d7b0ff8f1..37eaa0ffa6 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -20,6 +20,8 @@ #include "RigGridBase.h" +#include + //-------------------------------------------------------------------------------------------------- /// From 57494c4bfe65a0e65f5e0c5ca48e14a1877ad1cf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:14:01 +0200 Subject: [PATCH 184/346] Added ResultAccessObject for combined transmissibility --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigCellFaceResultAccessObject.cpp | 2 + .../RigCombTransResultAccessObject.cpp | 157 ++++++++++++++++++ .../RigCombTransResultAccessObject.h | 48 ++++++ .../ReservoirDataModel/RigGridBase.h | 1 - .../RigResultAccessObjectFactory.cpp | 142 ++++++++++++++++ .../RigResultAccessObjectFactory.h | 29 +++- 7 files changed, 372 insertions(+), 9 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 154b885bd0..123e156828 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -15,6 +15,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -39,6 +40,7 @@ ${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index 808d8b7708..86b8bbbfaa 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -18,6 +18,8 @@ #include "RigCellFaceResultAccessObject.h" +#include + //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp new file mode 100644 index 0000000000..60786a606a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCombTransResultAccessObject.h" + +#include "RigGridBase.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName) + : m_grid(grid), + m_resultName(resultName) +{ + m_resultAccessObjects.resize(6); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +{ + m_resultAccessObjects[faceId] = resultAccessObject; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const +{ + + // TODO: How to handle when we get here? + CVF_ASSERT(false); + + return cvf::UNDEFINED_DOUBLE; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + switch (faceId) + { + case cvf::StructGridInterface::POS_I: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_I: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + case cvf::StructGridInterface::POS_J: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_J: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + case cvf::StructGridInterface::POS_K: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + if (resultAccessObj) + { + return resultAccessObj->cellScalar(localCellIndex); + } + } + break; + case cvf::StructGridInterface::NEG_K: + { + const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + if (resultAccessObj) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) + { + return resultAccessObj->cellScalar(neighborGridCellIdx); + } + } + } + break; + } + + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RigCombTransResultAccessObject::resultName() const +{ + return m_resultName; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombTransResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +{ + // TODO: How to handle when we get here? + CVF_ASSERT(false); + +} + diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h new file mode 100644 index 0000000000..19e27b487a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessObject.h" + +#include "cvfCollection.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigCombTransResultAccessObject : public RigResultAccessObject +{ +public: + RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName); + + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + + virtual double cellScalar(size_t localCellIndex) const; + virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual QString resultName() const; + virtual void setCellScalar(size_t localCellIndex, double scalarValue); + +private: + cvf::Collection m_resultAccessObjects; + + const RigGridBase* m_grid; + QString m_resultName; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index cc061c18fa..a8285ad227 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -37,7 +37,6 @@ class RigMainGrid; class RigCell; -class RigGridScalarDataAccess; class RigActiveCellInfo; class RigGridBase : public cvf::StructGridInterface diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index d093fca77b..052aa35a6a 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -18,6 +18,10 @@ #include "RigResultAccessObjectFactory.h" +#include "RigResultAccessObject.h" +#include "RigActiveCellsResultAccessObject.h" +#include "RigAllGridCellsResultAccessObject.h" + #include "cvfLibCore.h" #include "cvfBase.h" #include "cvfObject.h" @@ -29,6 +33,84 @@ #include "RigGridBase.h" #include "RigCaseData.h" #include +#include "RigCombTransResultAccessObject.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(uiResultName); + if (scalarSetIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); + + // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps + // See RiaSetGridProperty command in RiaPropertyDataCommands + // + // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultAccessObject(grid, resultValues, uiResultName); + return object; + } +} + + + + + + + + + + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +// Rest of this file is to be deleted +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- /// @@ -196,3 +278,63 @@ cvf::ref RigResultAccessObjectFactory::TO_BE_DE } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + // Ternary + if (uiResultName == RimDefines::ternarySaturationResultName()) + { + return NULL; + } + else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + // TODO + // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates + // + + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); + } + } + + return cellFaceAccessObject; + } + + + return NULL; +} + diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index b50adc5240..aa54258936 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -24,24 +24,37 @@ class RigActiveCellInfo; class RigGridBase; +class RigResultAccessObject; class RigResultAccessObjectFactory { public: + static cvf::ref + createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName); + // TO BE DELETED + static cvf::ref + TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarSetIndex); +private: + static cvf::ref + createNativeDataAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& resultName); - - // TO BE DELETED - static cvf::ref - TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex); }; From 8a1611c14c993f00c4e3fb0d42fe5dc0c4ea8c98 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:52:59 +0200 Subject: [PATCH 185/346] Improved visual appearance of legend --- .../RivTernarySaturationOverlayItem.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 2160d0eb53..761f4bb6fb 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -41,7 +41,7 @@ RivTernarySaturationOverlayItem::RivTernarySaturationOverlayItem(cvf::Font* font) : m_textColor(cvf::Color3::BLACK), m_font(font), - m_size(100, 120) + m_size(100, 140) { } @@ -132,20 +132,31 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textPosY -= lineHeightInPixels; } - textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY)); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - 17 ), textPosY - lineHeightInPixels)); + cvf::Vec2f pos(5, textPosY); + textDrawer.addText("TERNARY", pos); + textPosY -= lineHeightInPixels; + textPosY -= 2; + + { + cvf::uint sgasTextWidth = m_font->textExtent("SGAS").x(); + textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - sgasTextWidth / 2 ), textPosY)); + + cvf::uint sgasRangeTextWidth = m_font->textExtent(m_sgasRange).x(); + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY - lineHeightInPixels)); + } textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); textDrawer.addText(m_swatRange, cvf::Vec2f(0.0, 0.0)); - textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - 25), 10.0)); - - float soilRangePos = static_cast(size.x() - 40); - if (m_soilRange.size() < 6) { - soilRangePos += 15; + cvf::uint soilTextWidth = m_font->textExtent("SOIL").x(); + textDrawer.addText("SOIL", cvf::Vec2f(static_cast(size.x() - soilTextWidth), 10.0)); + + cvf::uint soilRangeTextWidth = m_font->textExtent(m_soilRange).x(); + float soilRangePos = static_cast(size.x()) - soilRangeTextWidth; + + textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); } - textDrawer.addText(m_soilRange, cvf::Vec2f(soilRangePos, 0.0)); textDrawer.renderSoftware(oglContext, camera); From 3c521374811ca9925cd6ef0cd1359f6b936309cf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 6 Aug 2014 15:53:08 +0200 Subject: [PATCH 186/346] Reordered UI --- .../ProjectDataModel/RimTernaryLegendConfig.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 6da31598c9..dab84420e6 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -264,12 +264,6 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr if (rangeMode == USER_DEFINED) { caf::PdmUiOrdering* ternaryGroupContainer = uiOrdering.addNewGroup("Ternary "); - { - caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SOIL"); - ternaryGroup->add(&userDefinedMinValueSoil); - ternaryGroup->add(&userDefinedMaxValueSoil); - } - { caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SGAS"); ternaryGroup->add(&userDefinedMinValueSgas); @@ -282,6 +276,12 @@ void RimTernaryLegendConfig::defineUiOrdering(QString uiConfigName, caf::PdmUiOr ternaryGroup->add(&userDefinedMaxValueSwat); } + { + caf::PdmUiOrdering* ternaryGroup = ternaryGroupContainer->addNewGroup("SOIL"); + ternaryGroup->add(&userDefinedMinValueSoil); + ternaryGroup->add(&userDefinedMaxValueSoil); + } + ternaryGroupContainer->add(&applyLocalMinMax); ternaryGroupContainer->add(&applyGlobalMinMax); ternaryGroupContainer->add(&applyFullRangeMinMax); From aff8d8fd2a5f4b3384b6f510ac12713f106eed24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 6 Aug 2014 16:51:09 +0200 Subject: [PATCH 187/346] Moved needed code to above "delete" mark --- .../RivCellEdgeEffectGenerator.h | 8 ++ .../RigResultAccessObjectFactory.cpp | 117 +++++++++--------- 2 files changed, 64 insertions(+), 61 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 0c37fb84bc..ba2a6018a6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -98,6 +98,14 @@ class RivCellEdgeGeometryGenerator texCoords[i*4 + 3] = texCoord; } + Texturing needs in ResInsight: + * ScalarMapper + * Handle HugeVal/nan + * PipeCellTransparency + - includes geometry point to cell mapping + * Modify the Scalarmapper Texture + * The domain values to convert pr geometry point + */ diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index 052aa35a6a..b2f724a114 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -95,9 +95,65 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + RigGridBase* grid = eclipseCase->grid(gridIndex); + // Ternary + if (uiResultName == RimDefines::ternarySaturationResultName()) + { + return NULL; + } + else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + // TODO + // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates + // + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); + } + } + + { + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + if (nativeAccessObject.notNull()) + { + cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); + } + } + + return cellFaceAccessObject; + } + + + return NULL; +} @@ -277,64 +333,3 @@ cvf::ref RigResultAccessObjectFactory::TO_BE_DE return object; } } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - QString& uiResultName) -{ - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); - - RigGridBase* grid = eclipseCase->grid(gridIndex); - - // Ternary - if (uiResultName == RimDefines::ternarySaturationResultName()) - { - return NULL; - } - else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) - { - // TODO - // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates - // - - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); - } - } - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); - } - } - - { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); - } - } - - return cellFaceAccessObject; - } - - - return NULL; -} - From e31d3c8807d0527df40b3f3656bd9f196efe1dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 6 Aug 2014 16:54:12 +0200 Subject: [PATCH 188/346] Added comments and asserts related to neg. faces Negative face results is not applicable for this result access object, as they are never used (by intention) --- .../ReservoirDataModel/RigCombTransResultAccessObject.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp index 60786a606a..a7bb5fdf6d 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -34,10 +34,13 @@ RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase } //-------------------------------------------------------------------------------------------------- -/// +/// Only sensible to provide the positive values, as the negative ones will never be used. +/// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) { + CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); + m_resultAccessObjects[faceId] = resultAccessObject; } From da108bfb033f4000d33813726e5325e8e79d3c34 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 07:28:46 +0200 Subject: [PATCH 189/346] Fwk: Moved function call out of initAfterRead --- Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp | 1 + Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp index d6c3c5504b..2de957026c 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp @@ -113,6 +113,7 @@ void PdmObjectGroup::initAfterReadTraversal(PdmObject* object) } object->initAfterRead(); + object->updateUiIconFromToggleField(); } diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h index 457a8b1371..8bb9410b87 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmObject.h @@ -198,7 +198,7 @@ class PdmObject : public PdmUiItem protected: // Virtual /// Method gets called from PdmDocument after all objects are read. /// Re-implement to set up internal pointers etc. in your data structure - virtual void initAfterRead() { updateUiIconFromToggleField(); }; + virtual void initAfterRead() {}; /// Method gets called from PdmDocument before saving document. /// Re-implement to make sure your fields have correct data before saving From 70a98ab8fd95c788c17dac421285af90687f74d2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 25 Jul 2014 03:07:27 -0700 Subject: [PATCH 190/346] Linux fix: No default cast from QString to QString& --- .../ReservoirDataModel/RigResultAccessObjectFactory.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index b2f724a114..bede69dffe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -125,7 +125,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANX")); + QString resultName = "TRANX"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); @@ -133,7 +134,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess } { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANY")); + QString resultName = "TRANY"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); @@ -141,7 +143,8 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess } { - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, QString("TRANZ")); + QString resultName = "TRANZ"; + cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); From cac1cc8040df756e349a313fdb4997857d62538f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 12:17:04 +0200 Subject: [PATCH 191/346] Prototyping of new resultAccessor/texture system To make it simlier to add all the combined results MULTXYZ/riMULTXYZ etc --- .../RigResultAccessObject.h | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 8d723b567b..0b6ef234bd 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -39,3 +39,208 @@ class RigResultAccessObject : public cvf::Object virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; +#if 0 + +//================================================================================================== +/// +//================================================================================================== +class RigResultAccessor2d : public cvf::Object +{ +public: + virtual cvf::Vec2d cellScalar(size_t localCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + +}; + +//================================================================================================== +/// +//================================================================================================== +class RigTernaryResultAccessor : public Rig2DResultAccessor +{ +public: + /// Requires two of the arguments to be present + void setTernaryResultAccessors(RigResultAccessObject* soil, RigResultAccessObject* sgas, RigResultAccessObject* swat); + + /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// based on the two others + virtual cvf::Vec2d cellScalar(size_t localCellIndex) { }; + virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t localCellIndex); }; + + virtual QString resultName() const = 0; + +}; + +class RivTernaryScalarMapper : public cvf::Object +{ +public: + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) : m_undefScalarColor(undefScalarColor), m_opacityLevel(opacityLevel) + { + + } + + /// Calculate texture coords into an image produced by updateTexture, from the scalarValue + Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent) {} + + /// Update the supplied TextureImage to be addressable by the texture coords delivered by mapToTextureCoord + bool updateTexture(TextureImage* image){} + +private: + cvf::Color3f m_undefScalarColor; + float m_opacityLevel; +}; + +class RigPipeInCellEvaluator: public cvf::Object +{ +public: + RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap) + : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), + m_gridCellToWellIndexMap(gridCellToWellIndexMap) + { + } + + bool isWellPipeInCell( size_t cellIndex) + { + cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); + + if (wellIndex == cvf::UNDEFINED_UINT) + { + return false; + } + + return m_isWellPipeVisibleForWellIndex[wellIndex]; + } + +private: + + const std::vector& m_isWellPipeVisibleForWellIndex; + const cvf::UIntArray* m_gridCellToWellIndexMap; +}; + +class RivResultToTextureMapper : public cvf::Object +{ + + RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, + const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + Vec2f getTexCoord(double resultValue, size_t cellIndex) + { + Vec2f texCoord(0,0); + + if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + return texCoord; + } + + texCoord = m_scalarMapper->mapToTexCoord(resultValue); + + if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) + { + texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture + } + + return texCoord; + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) +{ + CVF_ASSERT(cellResultSlot); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + cvf::ref surfaceFacesColorArray; + + // Outer surface + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { + surfaceFacesColorArray = new cvf::Color3ubArray; + + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + } + else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); + RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); + } + else + { + // If the result is static, only read that. + size_t resTimeStepIdx = timeStepIndex; + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + cvf::ref dataAccessObject = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + + if (dataAccessObject.isNull()) return; + + RivResultToTextureMapper texMapper(mapper, + RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex()))); + + const StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); + + size_t numVertices = quadMapper->quadCount()*4; + m_surfaceFacesTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); + + double cellScalarValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, cellScalarValue) + for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) + { + StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); + + cellScalarValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); + + texCoord = texMapper->mapToTextureCoord(cellScalarValue); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } + } + + + if (surfaceFacesColorArray.notNull()) // Ternary result + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + dg->setColorArray(surfaceFacesColorArray.p()); + } + + cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); + m_surfaceFaces->setEffect(perVertexColorEffect.p()); + + m_surfaceFaces->setPriority(100); + } + else + { + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + } + } +} + +#endif From 2bfcfc16b125f7223f0c26071a88458b79482311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 13:22:09 +0200 Subject: [PATCH 192/346] Class Rename: ResultAccessObject to ResultAccessor --- .../RigActiveCellsResultAccessObject.h | 2 +- .../RigAllGridCellsResultAccessObject.cpp | 10 ++++---- .../RigAllGridCellsResultAccessObject.h | 4 ++-- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../RigCellFaceResultAccessObject.cpp | 14 +++++------ .../RigCellFaceResultAccessObject.h | 8 +++---- .../RigCombTransResultAccessObject.cpp | 24 +++++++++---------- .../RigCombTransResultAccessObject.h | 8 +++---- .../RigResultAccessObject.h | 2 +- .../RigResultAccessObjectFactory.cpp | 18 +++++++------- .../RigResultAccessObjectFactory.h | 12 +++++----- 11 files changed, 52 insertions(+), 52 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 901fe90638..14fb8c1dfe 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -27,7 +27,7 @@ class RigActiveCellInfo; //================================================================================================== /// //================================================================================================== -class RigActiveCellsResultAccessObject : public RigResultAccessObject +class RigActiveCellsResultAccessObject : public RigResultAccessor { public: RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp index 37eaa0ffa6..8e240d2f09 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) +RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_resultName(resultName) @@ -36,7 +36,7 @@ RigAllGridCellsResultAccessObject::RigAllGridCellsResultAccessObject(const RigGr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) const +double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; @@ -49,7 +49,7 @@ double RigAllGridCellsResultAccessObject::cellScalar(size_t localCellIndex) cons //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(localCellIndex); } @@ -57,7 +57,7 @@ double RigAllGridCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigAllGridCellsResultAccessObject::resultName() const +QString RigAllGridCellsResultAccessor::resultName() const { return m_resultName; } @@ -65,7 +65,7 @@ QString RigAllGridCellsResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigAllGridCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigAllGridCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h index 86eb65ecb5..2af694fa50 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h @@ -26,10 +26,10 @@ class RigGridBase; //================================================================================================== /// //================================================================================================== -class RigAllGridCellsResultAccessObject : public RigResultAccessObject +class RigAllGridCellsResultAccessor : public RigResultAccessor { public: - RigAllGridCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 3b1dfebeca..1b2d8b18bc 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -496,7 +496,7 @@ cvf::ref RigCaseData::dataAccessObject(const Ri if (timeStepIndex != cvf::UNDEFINED_SIZE_T && scalarSetIndex != cvf::UNDEFINED_SIZE_T) { - cvf::ref dataAccess = RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); + cvf::ref dataAccess = RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); return dataAccess; } diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index 86b8bbbfaa..fe2327d835 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -24,7 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resultName) +RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) : m_resultName(resultName) { m_resultAccessObjects.resize(6); @@ -33,7 +33,7 @@ RigCellFaceResultAccessObject::RigCellFaceResultAccessObject(const QString& resu //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { m_resultAccessObjects[faceId] = resultAccessObject; } @@ -41,7 +41,7 @@ void RigCellFaceResultAccessObject::setDataAccessObjectForFace(cvf::StructGridIn //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const +double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -53,9 +53,9 @@ double RigCellFaceResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(faceId); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); if (resultAccessObj != NULL) { return resultAccessObj->cellFaceScalar(localCellIndex, faceId); @@ -67,7 +67,7 @@ double RigCellFaceResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCellFaceResultAccessObject::resultName() const +QString RigCellFaceResultAccessor::resultName() const { return m_resultName; } @@ -75,7 +75,7 @@ QString RigCellFaceResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCellFaceResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h index 27afad5aea..bbb64cc8e9 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -26,12 +26,12 @@ //================================================================================================== /// //================================================================================================== -class RigCellFaceResultAccessObject : public RigResultAccessObject +class RigCellFaceResultAccessor : public RigResultAccessor { public: - RigCellFaceResultAccessObject(const QString& resultName); + RigCellFaceResultAccessor(const QString& resultName); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; @@ -39,7 +39,7 @@ class RigCellFaceResultAccessObject : public RigResultAccessObject virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: - cvf::Collection m_resultAccessObjects; + cvf::Collection m_resultAccessObjects; QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp index a7bb5fdf6d..6e651c55f2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName) +RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName) : m_grid(grid), m_resultName(resultName) { @@ -37,7 +37,7 @@ RigCombTransResultAccessObject::RigCombTransResultAccessObject(const RigGridBase /// Only sensible to provide the positive values, as the negative ones will never be used. /// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject) +void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); @@ -47,7 +47,7 @@ void RigCombTransResultAccessObject::setDataAccessObjectForFace(cvf::StructGridI //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const +double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -59,13 +59,13 @@ double RigCombTransResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { switch (faceId) { case cvf::StructGridInterface::POS_I: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -74,7 +74,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_I: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -89,7 +89,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::POS_J: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -98,7 +98,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_J: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -113,7 +113,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::POS_K: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); if (resultAccessObj) { return resultAccessObj->cellScalar(localCellIndex); @@ -122,7 +122,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf break; case cvf::StructGridInterface::NEG_K: { - const RigResultAccessObject* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); if (resultAccessObj) { size_t i, j, k, neighborGridCellIdx; @@ -143,7 +143,7 @@ double RigCombTransResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCombTransResultAccessObject::resultName() const +QString RigCombTransResultAccessor::resultName() const { return m_resultName; } @@ -151,7 +151,7 @@ QString RigCombTransResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCombTransResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h index 19e27b487a..5830f410ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h @@ -28,12 +28,12 @@ class RigGridBase; //================================================================================================== /// //================================================================================================== -class RigCombTransResultAccessObject : public RigResultAccessObject +class RigCombTransResultAccessor : public RigResultAccessor { public: - RigCombTransResultAccessObject(const RigGridBase* grid, const QString& resultName); + RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessObject* resultAccessObject); + void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; @@ -41,7 +41,7 @@ class RigCombTransResultAccessObject : public RigResultAccessObject virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: - cvf::Collection m_resultAccessObjects; + cvf::Collection m_resultAccessObjects; const RigGridBase* m_grid; QString m_resultName; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h index 0b6ef234bd..af60714385 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h @@ -28,7 +28,7 @@ //================================================================================================== /// //================================================================================================== -class RigResultAccessObject : public cvf::Object +class RigResultAccessor : public cvf::Object { public: virtual double cellScalar(size_t localCellIndex) const = 0; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index bede69dffe..bcbc705706 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -39,7 +39,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -83,12 +83,12 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); return object; } else { - cvf::ref object = new RigAllGridCellsResultAccessObject(grid, resultValues, uiResultName); + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues, uiResultName); return object; } } @@ -98,7 +98,7 @@ cvf::ref RigResultAccessObjectFactory::createNativeDataAc //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::createResultAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -122,11 +122,11 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessObject(grid, uiResultName); + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid, uiResultName); { QString resultName = "TRANX"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); @@ -135,7 +135,7 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess { QString resultName = "TRANY"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); @@ -144,7 +144,7 @@ cvf::ref RigResultAccessObjectFactory::createResultAccess { QString resultName = "TRANZ"; - cvf::ref nativeAccessObject = RigResultAccessObjectFactory::createNativeDataAccessObject(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); + cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); if (nativeAccessObject.notNull()) { cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); @@ -287,7 +287,7 @@ class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessObjectFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, +cvf::ref RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h index aa54258936..8a6ca4bd89 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h @@ -24,13 +24,13 @@ class RigActiveCellInfo; class RigGridBase; -class RigResultAccessObject; +class RigResultAccessor; -class RigResultAccessObjectFactory +class RigResultAccessorFactory { public: - static cvf::ref - createResultAccessObject(RigCaseData* eclipseCase, + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, @@ -47,8 +47,8 @@ class RigResultAccessObjectFactory private: - static cvf::ref - createNativeDataAccessObject(RigCaseData* eclipseCase, + static cvf::ref + createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, From 1514b98c7a83439916dd199b252ee5d263712f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 13:32:31 +0200 Subject: [PATCH 193/346] More renaming : AccessObject-Accessor And CellFaceAccessor to CellEdgeAccessor --- .../RigActiveCellsResultAccessObject.cpp | 10 +++++----- .../RigActiveCellsResultAccessObject.h | 4 ++-- .../RigCellFaceResultAccessObject.cpp | 12 ++++++------ .../RigCellFaceResultAccessObject.h | 4 ++-- .../RigResultAccessObjectFactory.cpp | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp index 6552f938f7..643d834575 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp @@ -24,7 +24,7 @@ #include -RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) +RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), m_activeCellInfo(activeCellInfo), @@ -36,7 +36,7 @@ RigActiveCellsResultAccessObject::RigActiveCellsResultAccessObject(const RigGrid //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const +double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; @@ -52,7 +52,7 @@ double RigActiveCellsResultAccessObject::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(localCellIndex); } @@ -60,7 +60,7 @@ double RigActiveCellsResultAccessObject::cellFaceScalar(size_t localCellIndex, c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigActiveCellsResultAccessObject::resultName() const +QString RigActiveCellsResultAccessor::resultName() const { return m_resultName; } @@ -68,7 +68,7 @@ QString RigActiveCellsResultAccessObject::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellsResultAccessObject::setCellScalar(size_t localCellIndex, double scalarValue) +void RigActiveCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h index 14fb8c1dfe..47f640a17d 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h @@ -27,10 +27,10 @@ class RigActiveCellInfo; //================================================================================================== /// //================================================================================================== -class RigActiveCellsResultAccessObject : public RigResultAccessor +class RigActiveCellsResultAccessor : public RigResultAccessor { public: - RigActiveCellsResultAccessObject(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp index fe2327d835..eabe99cb33 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp @@ -24,7 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) +RigCellEdgeResultAccessor::RigCellEdgeResultAccessor(const QString& resultName) : m_resultName(resultName) { m_resultAccessObjects.resize(6); @@ -33,7 +33,7 @@ RigCellFaceResultAccessor::RigCellFaceResultAccessor(const QString& resultName) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) +void RigCellEdgeResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) { m_resultAccessObjects[faceId] = resultAccessObject; } @@ -41,7 +41,7 @@ void RigCellFaceResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const +double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const { // TODO: How to handle when we get here? @@ -53,7 +53,7 @@ double RigCellFaceResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); if (resultAccessObj != NULL) @@ -67,7 +67,7 @@ double RigCellFaceResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::Str //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QString RigCellFaceResultAccessor::resultName() const +QString RigCellEdgeResultAccessor::resultName() const { return m_resultName; } @@ -75,7 +75,7 @@ QString RigCellFaceResultAccessor::resultName() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCellFaceResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) +void RigCellEdgeResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) { // TODO: How to handle when we get here? CVF_ASSERT(false); diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h index bbb64cc8e9..7d0ead9536 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h @@ -26,10 +26,10 @@ //================================================================================================== /// //================================================================================================== -class RigCellFaceResultAccessor : public RigResultAccessor +class RigCellEdgeResultAccessor : public RigResultAccessor { public: - RigCellFaceResultAccessor(const QString& resultName); + RigCellEdgeResultAccessor(const QString& resultName); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp index bcbc705706..dccfd0fed9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp @@ -83,7 +83,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessObject(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); return object; } else From 7ebe9b17b980bc286b96e2d5951b50ada476d640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 14:20:20 +0200 Subject: [PATCH 194/346] Renamed files to reflect new classnames --- .../RivReservoirViewPartMgr.cpp | 2 +- .../ReservoirDataModel/CMakeLists_files.cmake | 24 +++++++++---------- ...t.cpp => RigActiveCellsResultAccessor.cpp} | 2 +- ...bject.h => RigActiveCellsResultAccessor.h} | 2 +- ....cpp => RigAllGridCellsResultAccessor.cpp} | 2 +- ...ject.h => RigAllGridCellsResultAccessor.h} | 2 +- .../ReservoirDataModel/RigCaseData.cpp | 2 +- ...ject.cpp => RigCellEdgeResultAccessor.cpp} | 2 +- ...ssObject.h => RigCellEdgeResultAccessor.h} | 2 +- ...ect.cpp => RigCombTransResultAccessor.cpp} | 2 +- ...sObject.h => RigCombTransResultAccessor.h} | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- ...AccessObject.cpp => RigResultAccessor.cpp} | 2 +- ...sultAccessObject.h => RigResultAccessor.h} | 0 ...ctory.cpp => RigResultAccessorFactory.cpp} | 10 ++++---- ...ctFactory.h => RigResultAccessorFactory.h} | 0 16 files changed, 29 insertions(+), 29 deletions(-) rename ApplicationCode/ReservoirDataModel/{RigActiveCellsResultAccessObject.cpp => RigActiveCellsResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigActiveCellsResultAccessObject.h => RigActiveCellsResultAccessor.h} (98%) rename ApplicationCode/ReservoirDataModel/{RigAllGridCellsResultAccessObject.cpp => RigAllGridCellsResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigAllGridCellsResultAccessObject.h => RigAllGridCellsResultAccessor.h} (97%) rename ApplicationCode/ReservoirDataModel/{RigCellFaceResultAccessObject.cpp => RigCellEdgeResultAccessor.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigCellFaceResultAccessObject.h => RigCellEdgeResultAccessor.h} (97%) rename ApplicationCode/ReservoirDataModel/{RigCombTransResultAccessObject.cpp => RigCombTransResultAccessor.cpp} (99%) rename ApplicationCode/ReservoirDataModel/{RigCombTransResultAccessObject.h => RigCombTransResultAccessor.h} (98%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObject.cpp => RigResultAccessor.cpp} (95%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObject.h => RigResultAccessor.h} (100%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObjectFactory.cpp => RigResultAccessorFactory.cpp} (98%) rename ApplicationCode/ReservoirDataModel/{RigResultAccessObjectFactory.h => RigResultAccessorFactory.h} (100%) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 284985349c..abc229ffa0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -23,7 +23,7 @@ #include "RigCaseData.h" #include "RigGridBase.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" #include "RimCase.h" #include "RimCellRangeFilterCollection.h" #include "RimWellCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 123e156828..53420405e8 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -10,12 +10,12 @@ ${CEE_CURRENT_LIST_DIR}RigCell.h ${CEE_CURRENT_LIST_DIR}RigCaseData.h ${CEE_CURRENT_LIST_DIR}RigGridBase.h ${CEE_CURRENT_LIST_DIR}RigGridManager.h -${CEE_CURRENT_LIST_DIR}RigResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.h -${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.h -${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.h +${CEE_CURRENT_LIST_DIR}RigResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigResultAccessorFactory.h +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -35,12 +35,12 @@ ${CEE_CURRENT_LIST_DIR}RigCell.cpp ${CEE_CURRENT_LIST_DIR}RigCaseData.cpp ${CEE_CURRENT_LIST_DIR}RigGridBase.cpp ${CEE_CURRENT_LIST_DIR}RigGridManager.cpp -${CEE_CURRENT_LIST_DIR}RigResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigResultAccessObjectFactory.cpp -${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigCellFaceResultAccessObject.cpp -${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessObject.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigResultAccessorFactory.cpp +${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index 643d834575..edd5ae168c 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigActiveCellsResultAccessObject.h" +#include "RigActiveCellsResultAccessor.h" #include "RigGridBase.h" #include "RigActiveCellInfo.h" diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 47f640a17d..306b70fcda 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" class RigGridBase; class RigActiveCellInfo; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 8e240d2f09..7e5762a184 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigAllGridCellsResultAccessObject.h" +#include "RigAllGridCellsResultAccessor.h" #include "RigGridBase.h" diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h similarity index 97% rename from ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 2af694fa50..1c4473daa0 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigActiveCellsResultAccessObject.h" +#include "RigActiveCellsResultAccessor.h" class RigGridBase; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 1b2d8b18bc..8a9192f107 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -19,7 +19,7 @@ #include "RigCaseData.h" #include "RigMainGrid.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index eabe99cb33..a5dfc0ee28 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigCellFaceResultAccessObject.h" +#include "RigCellEdgeResultAccessor.h" #include diff --git a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h similarity index 97% rename from ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index 7d0ead9536..73ea161fb8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellFaceResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" #include "cvfCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp similarity index 99% rename from ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 6e651c55f2..86a27788b2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -16,7 +16,7 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigCombTransResultAccessObject.h" +#include "RigCombTransResultAccessor.h" #include "RigGridBase.h" diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index 5830f410ad..e99002d799 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessObject.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -18,7 +18,7 @@ #pragma once -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" #include "cvfCollection.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 4c195270da..1342059660 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -20,7 +20,7 @@ #include "RigMainGrid.h" #include "RigCell.h" #include "RigCaseCellResultsData.h" -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" #include "cvfAssert.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp similarity index 95% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp rename to ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp index 6d732c7309..160c2b9abe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp @@ -16,4 +16,4 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigResultAccessObject.h" +#include "RigResultAccessor.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObject.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h similarity index 100% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObject.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessor.h diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp similarity index 98% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp rename to ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index dccfd0fed9..0e6fba79b9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -16,11 +16,11 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RigResultAccessObjectFactory.h" +#include "RigResultAccessorFactory.h" -#include "RigResultAccessObject.h" -#include "RigActiveCellsResultAccessObject.h" -#include "RigAllGridCellsResultAccessObject.h" +#include "RigResultAccessor.h" +#include "RigActiveCellsResultAccessor.h" +#include "RigAllGridCellsResultAccessor.h" #include "cvfLibCore.h" #include "cvfBase.h" @@ -33,7 +33,7 @@ #include "RigGridBase.h" #include "RigCaseData.h" #include -#include "RigCombTransResultAccessObject.h" +#include "RigCombTransResultAccessor.h" //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h similarity index 100% rename from ApplicationCode/ReservoirDataModel/RigResultAccessObjectFactory.h rename to ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h From 9288b766e21548db314a7e5f944892fcb3872af8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:44:28 +0200 Subject: [PATCH 195/346] Ternary legend: Minor layout tweaks --- .../ModelVisualization/RivTernarySaturationOverlayItem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 761f4bb6fb..85404d9cd2 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -142,7 +142,8 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textDrawer.addText("SGAS", cvf::Vec2f(static_cast( (size.x() / 2) - sgasTextWidth / 2 ), textPosY)); cvf::uint sgasRangeTextWidth = m_font->textExtent(m_sgasRange).x(); - textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY - lineHeightInPixels)); + textPosY -= lineHeightInPixels; + textDrawer.addText(m_sgasRange, cvf::Vec2f(static_cast( (size.x() / 2) - sgasRangeTextWidth / 2 ), textPosY)); } textDrawer.addText("SWAT", cvf::Vec2f(0.0, 10.0)); @@ -160,7 +161,8 @@ void RivTernarySaturationOverlayItem::render(cvf::OpenGLContext* oglContext, con textDrawer.renderSoftware(oglContext, camera); - renderAxisImmediateMode(textPosY - lineHeightInPixels, oglContext); + textPosY -= 3; + renderAxisImmediateMode(textPosY, oglContext); CVF_CHECK_OGL(oglContext); } From 824ea81b992fae51265ad1735e0fa73c4f52b7fd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:48:38 +0200 Subject: [PATCH 196/346] Added RigResultModifier --- .../ReservoirDataModel/CMakeLists_files.cmake | 1 + .../ReservoirDataModel/RigResultModifier.h | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifier.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 53420405e8..1da15926a7 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -16,6 +16,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigResultModifier.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h new file mode 100644 index 0000000000..3ab82e3462 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +//================================================================================================== +/// +//================================================================================================== +class RigResultModifier : public cvf::Object +{ +public: + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) = 0; +}; + + + +//================================================================================================== +/// +//================================================================================================== +class RigAllGridCellsResultModifier : public RigResultModifier +{ +public: + RigAllGridCellsResultModifier(const RigGridBase* grid, std::vector* reservoirResultValues) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues) + { + } + + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + } + +private: + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + + +//================================================================================================== +/// +//================================================================================================== +class RigActiveCellsResultModifier : public RigResultModifier +{ +public: + RigActiveCellsResultModifier(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) + : m_grid(grid), + m_reservoirResultValues(reservoirResultValues), + m_activeCellInfo(activeCellInfo) + { + } + + virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) + { + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + + CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); + + (*m_reservoirResultValues)[resultValueIndex] = scalarValue; + } + + +private: + const RigActiveCellInfo* m_activeCellInfo; + const RigGridBase* m_grid; + std::vector* m_reservoirResultValues; +}; + From 322823754b54f76c16f234deb68d18bdb110ba86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 14:55:33 +0200 Subject: [PATCH 197/346] Replaced dataAccessObject with resultAccessor --- .../RifEclipseInputFileTools.cpp | 6 ++-- .../RivCellEdgeEffectGenerator.cpp | 4 +-- .../RivCellEdgeEffectGenerator.h | 2 +- .../RivFaultGeometryGenerator.cpp | 6 ++-- .../RivFaultGeometryGenerator.h | 2 +- .../ModelVisualization/RivFaultPartMgr.cpp | 10 +++---- .../ModelVisualization/RivGridPartMgr.cpp | 18 +++++------ .../RivReservoirViewPartMgr.cpp | 6 ++-- .../ProjectDataModel/RimReservoirView.cpp | 30 +++++++++---------- .../RimStatisticsCaseEvaluator.cpp | 16 +++++----- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../ReservoirDataModel/RigCaseData.h | 2 +- .../ReservoirDataModel/RigResultAccessor.h | 6 ++-- .../RiaPropertyDataCommands.cpp | 4 +-- .../cvfStructGridGeometryGenerator.cpp | 12 ++++---- .../cvfStructGridGeometryGenerator.h | 2 +- 16 files changed, 64 insertions(+), 64 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 819a65d5a5..74a7892560 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -500,8 +500,8 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa return false; } - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); - if (dataAccessObject.isNull()) + cvf::ref resultAccessor = eclipseCase->resultAccessor(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); + if (resultAccessor.isNull()) { return false; } @@ -514,7 +514,7 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa { for (i = 0; i < eclipseCase->mainGrid()->cellCountI(); i++) { - double resultValue = dataAccessObject->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); + double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); if (resultValue == HUGE_VAL) { resultValue = undefinedValue; diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 8c1b6ed601..0dd9043c09 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -121,7 +121,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( } RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); + cellCenterDataAccessObject = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); } CVF_ASSERT(cellEdgeResultSlot->hasResult()); @@ -140,7 +140,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( { // Assuming static values to be mapped onto cell edge, always using time step zero // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->dataAccessObject(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); + daObj = eclipseCase->resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); } cellEdgeDataAccessObjects.push_back(daObj.p()); diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index ba2a6018a6..8fea369a1c 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -90,7 +90,7 @@ class RivCellEdgeGeometryGenerator texCoords.resize(m_quadsToGridCells.size()*4); for (i = 0; i < m_quadsToGridCells.size(); ++i) { - cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(dataAccessObject->cellScalar(m_quadsToGridCells[i])); + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(resultAccessor->cellScalar(m_quadsToGridCells[i])); ResValue ResPoint To ResValue texCoords[i*4 + 0] = texCoord; texCoords[i*4 + 1] = texCoord; diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index e9ed113620..a45a4dad3e 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -203,9 +203,9 @@ void RivFaultGeometryGenerator::computeArrays() /// Calculates the texture coordinates in a "nearly" one dimensional texture. /// Undefined values are coded with a y-texture coordinate value of 1.0 instead of the normal 0.5 //-------------------------------------------------------------------------------------------------- -void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* dataAccessObject, const cvf::ScalarMapper* mapper) const +void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* resultAccessor, const cvf::ScalarMapper* mapper) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; size_t numVertices = m_quadMapper->quadCount()*4; @@ -218,7 +218,7 @@ void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoord #pragma omp parallel for private(texCoord, cellScalarValue) for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); + cellScalarValue = resultAccessor->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index 81162a67c7..f0e8fd1cc2 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -48,7 +48,7 @@ class RivFaultGeometryGenerator : public cvf::Object void setCellVisibility(const cvf::UByteArray* cellVisibilities ); void textureCoordinates(cvf::Vec2fArray* textureCoords, - const cvf::StructGridScalarDataAccess* dataAccessObject, + const cvf::StructGridScalarDataAccess* resultAccessor, const cvf::ScalarMapper* mapper) const; // Mapping between cells and geometry diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 731faf4dae..2d261dfc0c 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -117,7 +117,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); + cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); // Faults if (m_nativeFaultFaces.notNull()) @@ -139,11 +139,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - if (dataAccessObject.isNull()) + if (resultAccessor.isNull()) { return; } - m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); } @@ -212,12 +212,12 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - if (dataAccessObject.isNull()) + if (resultAccessor.isNull()) { return; } - m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); } if (m_opacityLevel < 1.0f ) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 98145b17ad..47fe6765b8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -243,10 +243,10 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (dataAccessObject.isNull()) return; + cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); + if (resultAccessor.isNull()) return; - m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), dataAccessObject.p(), mapper); + m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), resultAccessor.p(), mapper); } @@ -460,9 +460,9 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObjectTranX = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->dataAccessObject(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); + cvf::ref dataAccessObjectTranX = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); + cvf::ref dataAccessObjectTranY = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); + cvf::ref dataAccessObjectTranZ = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); int quadCount = static_cast(quadToCellFaceMapper->quadCount()); @@ -601,19 +601,19 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - cvf::ref dataAccessObjectSoil = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectSoil = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); if (dataAccessObjectSoil.isNull()) { dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSgas = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectSgas = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); if (dataAccessObjectSgas.isNull()) { dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSwat = eclipseCase->dataAccessObject(grid, porosityModel, timeStepIndex, swatScalarSetIndex); + cvf::ref dataAccessObjectSwat = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); if (dataAccessObjectSwat.isNull()) { dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index abc229ffa0..e3fa51f9af 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -728,8 +728,8 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); - CVF_ASSERT(dataAccessObject.notNull()); + cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) for (int cellIndex = 0; cellIndex < static_cast(grid->cellCount()); cellIndex++) @@ -738,7 +738,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis { size_t resultValueIndex = cellIndex; - double scalarValue = dataAccessObject->cellScalar(resultValueIndex); + double scalarValue = resultAccessor->cellScalar(resultValueIndex); if (lowerBound <= scalarValue && scalarValue <= upperBound) { if (filterType == RimCellFilter::EXCLUDE) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index fe969de1ac..d7cb997020 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1105,7 +1105,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, RigGridBase* grid = eclipseCase->grid(gridIndex); RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject; + cvf::ref resultAccessor; if (this->cellResult()->isTernarySaturationSelected()) { @@ -1116,9 +1116,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - cvf::ref dataAccessObjectX = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); + cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); + cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); double scalarValue = 0.0; @@ -1138,7 +1138,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, else if (this->cellResult()->hasResult()) { RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject; + cvf::ref resultAccessor; if (cellResult->hasStaticResult()) { @@ -1147,9 +1147,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t tranX, tranY, tranZ; if (eclipseCase->results(porosityModel)->findTransmissibilityResults(tranX, tranY, tranZ)) { - cvf::ref dataAccessObjectX = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranX); - cvf::ref dataAccessObjectY = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranY); - cvf::ref dataAccessObjectZ = eclipseCase->dataAccessObject(grid, porosityModel, 0, tranZ); + cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, 0, tranX); + cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, 0, tranY); + cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, 0, tranZ); double scalarValue = dataAccessObjectX->cellScalar(cellIndex); resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); @@ -1163,17 +1163,17 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, } else { - dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); } } else { - dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); } - if (dataAccessObject.notNull()) + if (resultAccessor.notNull()) { - double scalarValue = dataAccessObject->cellScalar(cellIndex); + double scalarValue = resultAccessor->cellScalar(cellIndex); resultInfoText->append(QString("Cell result : %1\n").arg(scalarValue)); } } @@ -1191,10 +1191,10 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref dataAccessObject = eclipseCase->dataAccessObject(grid, porosityModel, 0, resultIndices[idx]); - if (dataAccessObject.notNull()) + cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, resultIndices[idx]); + if (resultAccessor.notNull()) { - double scalarValue = dataAccessObject->cellScalar(cellIndex); + double scalarValue = resultAccessor->cellScalar(cellIndex); resultInfoText->append(QString("%1 : %2\n").arg(resultNames[idx]).arg(scalarValue)); } } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index ecb06dd92f..ae6f742925 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -194,15 +194,15 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - cvf::ref dataAccessObject = sourceCase->reservoirData()->dataAccessObject(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); - if (dataAccessObject.notNull()) + cvf::ref resultAccessor = sourceCase->reservoirData()->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + if (resultAccessor.notNull()) { - sourceDataAccessList.push_back(dataAccessObject.p()); + sourceDataAccessList.push_back(resultAccessor.p()); } } // Build data access objects for destination scalar results - // Find the created result container, if any, and put its dataAccessObject into the enum indexed destination collection + // Find the created result container, if any, and put its resultAccessor into the enum indexed destination collection cvf::Collection destinationDataAccessList; std::vector statisticalResultNames(STAT_PARAM_COUNT); @@ -221,7 +221,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = destCellResultsData->findScalarResultIndex(resultType, statisticalResultNames[stIdx]); if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) { - destinationDataAccessList.push_back(m_destinationCase->dataAccessObject(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); + destinationDataAccessList.push_back(m_destinationCase->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); } else { @@ -351,12 +351,12 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - cvf::ref dataAccessObject = m_destinationCase->dataAccessObject(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); - if (dataAccessObject.isNull()) return; + cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); + if (resultAccessor.isNull()) return; for (size_t cellIdx = 0; cellIdx < m_globalCellCount; cellIdx++) { - qDebug() << dataAccessObject->cellScalar(cellIdx); + qDebug() << resultAccessor->cellScalar(cellIdx); } } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 8a9192f107..34830722fd 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -488,7 +488,7 @@ const RigCaseCellResultsData* RigCaseData::results(RifReaderInterface::PorosityM //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigCaseData::dataAccessObject(const RigGridBase* grid, +cvf::ref RigCaseData::resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index 2ab3432815..68960b381a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -54,7 +54,7 @@ class RigCaseData: public cvf::Object void setActiveCellInfo(RifReaderInterface::PorosityModelResultType porosityModel, RigActiveCellInfo* activeCellInfo); - cvf::ref dataAccessObject(const RigGridBase* grid, + cvf::ref resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index af60714385..fb1837c3bb 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -188,9 +188,9 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObject = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + cvf::ref resultAccessor = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - if (dataAccessObject.isNull()) return; + if (resultAccessor.isNull()) return; RivResultToTextureMapper texMapper(mapper, RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), @@ -210,7 +210,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); - cellScalarValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); + cellScalarValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); texCoord = texMapper->mapToTextureCoord(cellScalarValue); diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 85d154a2a4..01073c5cc8 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -322,7 +322,7 @@ class RiaGetGridProperty: public RiaSocketCommand for (size_t tsIdx = 0; tsIdx < timestepCount; tsIdx++) { - cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->dataAccessObject(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); + cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->resultAccessor(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); if (cellCenterDataAccessObject.isNull()) { continue; @@ -935,7 +935,7 @@ class RiaSetGridProperty : public RiaSocketCommand } cvf::ref cellCenterDataAccessObject = - m_currentReservoir->reservoirData()->dataAccessObject(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); + m_currentReservoir->reservoirData()->resultAccessor(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); if (!cellCenterDataAccessObject.isNull()) { diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index a5dbdd0633..3af8efd688 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -383,9 +383,9 @@ void StructGridGeometryGenerator::computeArrays() /// Calculates the texture coordinates in a "nearly" one dimentional texture. /// Undefined values are coded with a y-texturecoordinate value of 1.0 instead of the normal 0.5 //-------------------------------------------------------------------------------------------------- -void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const +void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* resultAccessor, const ScalarMapper* mapper) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; size_t numVertices = m_quadMapper->quadCount()*4; @@ -398,7 +398,7 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, #pragma omp parallel for private(texCoord, cellScalarValue) for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) { - cellScalarValue = dataAccessObject->cellScalar(m_quadMapper->cellIndex(i)); + cellScalarValue = resultAccessor->cellScalar(m_quadMapper->cellIndex(i)); texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { @@ -418,9 +418,9 @@ void StructGridGeometryGenerator::textureCoordinates(Vec2fArray* textureCoords, /// /// //-------------------------------------------------------------------------------------------------- -void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* dataAccessObject) const +void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fArray* textureCoords, const ScalarMapper* mapper, const CellFaceValueCalculator* resultAccessor) const { - if (!dataAccessObject) return; + if (!resultAccessor) return; textureCoords->resize(m_quadMapper->quadCount()*4); @@ -433,7 +433,7 @@ void StructGridGeometryGenerator::textureCoordinatesFromSingleFaceValues(Vec2fAr #pragma omp parallel for private(texCoord, cellFaceValue) for (int qIdx = 0; qIdx < quadCount; qIdx++) { - cellFaceValue = dataAccessObject->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); + cellFaceValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(qIdx), m_quadMapper->faceType(qIdx)); texCoord = mapper->mapToTextureCoord(cellFaceValue); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index 32f0c2cafa..cced178fe9 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -173,7 +173,7 @@ class StructGridGeometryGenerator : public Object const StructGridInterface* activeGrid() { return m_grid.p(); } - void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* dataAccessObject, const ScalarMapper* mapper) const; + void textureCoordinates(Vec2fArray* textureCoords, const StructGridScalarDataAccess* resultAccessor, const ScalarMapper* mapper) const; // Mapping between cells and geometry From b4d8067a74609f3b10e63f43cce5e1fbe729bb09 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 7 Aug 2014 14:56:29 +0200 Subject: [PATCH 198/346] Removed setCellScalar and resultName from Resultaccessor --- .../RigActiveCellsResultAccessor.cpp | 25 ++----------------- .../RigActiveCellsResultAccessor.h | 5 +--- .../RigAllGridCellsResultAccessor.cpp | 23 ++--------------- .../RigAllGridCellsResultAccessor.h | 5 +--- .../RigCellEdgeResultAccessor.cpp | 21 +--------------- .../RigCellEdgeResultAccessor.h | 6 +---- .../RigCombTransResultAccessor.cpp | 23 ++--------------- .../RigCombTransResultAccessor.h | 5 +--- .../ReservoirDataModel/RigResultAccessor.h | 4 --- .../RigResultAccessorFactory.cpp | 6 ++--- 10 files changed, 14 insertions(+), 109 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index edd5ae168c..a72a3b1ec4 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -24,11 +24,10 @@ #include -RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName) +RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) : m_grid(grid), m_reservoirResultValues(reservoirResultValues), - m_activeCellInfo(activeCellInfo), - m_resultName(resultName) + m_activeCellInfo(activeCellInfo) { } @@ -57,23 +56,3 @@ double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf:: return cellScalar(localCellIndex); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigActiveCellsResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigActiveCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); - - CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[resultValueIndex] = scalarValue; -} diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 306b70fcda..9647033722 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -30,17 +30,14 @@ class RigActiveCellInfo; class RigActiveCellsResultAccessor : public RigResultAccessor { public: - RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo, const QString& resultName); + RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: const RigActiveCellInfo* m_activeCellInfo; const RigGridBase* m_grid; std::vector* m_reservoirResultValues; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 7e5762a184..5ba549176f 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -26,10 +26,9 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName) +RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues) : m_grid(grid), - m_reservoirResultValues(reservoirResultValues), - m_resultName(resultName) + m_reservoirResultValues(reservoirResultValues) { } @@ -54,21 +53,3 @@ double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf: return cellScalar(localCellIndex); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigAllGridCellsResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigAllGridCellsResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; -} diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 1c4473daa0..840e3f46a7 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -29,17 +29,14 @@ class RigGridBase; class RigAllGridCellsResultAccessor : public RigResultAccessor { public: - RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const QString& resultName); + RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: const RigGridBase* m_grid; std::vector* m_reservoirResultValues; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index a5dfc0ee28..f94aebe8c2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -24,8 +24,7 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCellEdgeResultAccessor::RigCellEdgeResultAccessor(const QString& resultName) - : m_resultName(resultName) +RigCellEdgeResultAccessor::RigCellEdgeResultAccessor() { m_resultAccessObjects.resize(6); } @@ -64,21 +63,3 @@ double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::Str return HUGE_VAL; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigCellEdgeResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCellEdgeResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - // TODO: How to handle when we get here? - CVF_ASSERT(false); - -} - diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index 73ea161fb8..cdc70c0937 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -29,17 +29,13 @@ class RigCellEdgeResultAccessor : public RigResultAccessor { public: - RigCellEdgeResultAccessor(const QString& resultName); + RigCellEdgeResultAccessor(); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: cvf::Collection m_resultAccessObjects; - - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 86a27788b2..af7b992e7f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -26,9 +26,8 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName) - : m_grid(grid), - m_resultName(resultName) +RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid) + : m_grid(grid) { m_resultAccessObjects.resize(6); } @@ -140,21 +139,3 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St return HUGE_VAL; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RigCombTransResultAccessor::resultName() const -{ - return m_resultName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessor::setCellScalar(size_t localCellIndex, double scalarValue) -{ - // TODO: How to handle when we get here? - CVF_ASSERT(false); - -} - diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index e99002d799..6a7a0b5cda 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -31,18 +31,15 @@ class RigGridBase; class RigCombTransResultAccessor : public RigResultAccessor { public: - RigCombTransResultAccessor(const RigGridBase* grid, const QString& resultName); + RigCombTransResultAccessor(const RigGridBase* grid); void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; - virtual QString resultName() const; - virtual void setCellScalar(size_t localCellIndex, double scalarValue); private: cvf::Collection m_resultAccessObjects; const RigGridBase* m_grid; - QString m_resultName; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index fb1837c3bb..a49bdc62da 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -33,10 +33,6 @@ class RigResultAccessor : public cvf::Object public: virtual double cellScalar(size_t localCellIndex) const = 0; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - - virtual void setCellScalar(size_t localCellIndex, double scalarValue) = 0; }; #if 0 diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 0e6fba79b9..66096010cd 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -83,12 +83,12 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); if (useGlobalActiveIndex) { - cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel), uiResultName); + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); return object; } else { - cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues, uiResultName); + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); return object; } } @@ -122,7 +122,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid, uiResultName); + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); { QString resultName = "TRANX"; From 0f26b6e22ffb7ded128e162262d87dad6a53a32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 15:30:12 +0200 Subject: [PATCH 199/346] Trimmed CombTransResultAccessor interface setTransResultAccessors --- .../RigCombTransResultAccessor.cpp | 49 +++++++++---------- .../RigCombTransResultAccessor.h | 11 +++-- .../RigResultAccessorFactory.cpp | 39 +++------------ .../RigResultAccessorFactory.h | 4 +- 4 files changed, 39 insertions(+), 64 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index af7b992e7f..2e67ac5b6f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -29,18 +29,21 @@ RigCombTransResultAccessor::RigCombTransResultAccessor(const RigGridBase* grid) : m_grid(grid) { - m_resultAccessObjects.resize(6); + } //-------------------------------------------------------------------------------------------------- /// Only sensible to provide the positive values, as the negative ones will never be used. /// The negative faces gets their value from the neighbor cell in that direction //-------------------------------------------------------------------------------------------------- -void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject) -{ - CVF_ASSERT(faceId == cvf::StructGridInterface::POS_I || faceId == cvf::StructGridInterface::POS_J || faceId == cvf::StructGridInterface::POS_K ); +void RigCombTransResultAccessor::setTransResultAccessors(RigResultAccessor* xTransAccessor, + RigResultAccessor* yTransAccessor, + RigResultAccessor* zTransAccessor) - m_resultAccessObjects[faceId] = resultAccessObject; +{ + m_xTransAccessor = xTransAccessor; + m_yTransAccessor = yTransAccessor; + m_zTransAccessor = zTransAccessor; } //-------------------------------------------------------------------------------------------------- @@ -48,11 +51,9 @@ void RigCombTransResultAccessor::setDataAccessObjectForFace(cvf::StructGridInter //-------------------------------------------------------------------------------------------------- double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const { + CVF_TIGHT_ASSERT(false); - // TODO: How to handle when we get here? - CVF_ASSERT(false); - - return cvf::UNDEFINED_DOUBLE; + return HUGE_VAL; } //-------------------------------------------------------------------------------------------------- @@ -64,72 +65,66 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { case cvf::StructGridInterface::POS_I: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); - if (resultAccessObj) + if (m_xTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_xTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_I: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_I); - if (resultAccessObj) + if (m_xTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_xTransAccessor->cellScalar(neighborGridCellIdx); } } } break; case cvf::StructGridInterface::POS_J: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); - if (resultAccessObj) + if (m_yTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_yTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_J: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_J); - if (resultAccessObj) + if (m_yTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_yTransAccessor->cellScalar(neighborGridCellIdx); } } } break; case cvf::StructGridInterface::POS_K: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); - if (resultAccessObj) + if (m_zTransAccessor.notNull()) { - return resultAccessObj->cellScalar(localCellIndex); + return m_zTransAccessor->cellScalar(localCellIndex); } } break; case cvf::StructGridInterface::NEG_K: { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(cvf::StructGridInterface::POS_K); - if (resultAccessObj) + if (m_zTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) { - return resultAccessObj->cellScalar(neighborGridCellIdx); + return m_zTransAccessor->cellScalar(neighborGridCellIdx); } } } diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index 6a7a0b5cda..fe9b89128f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -33,13 +33,18 @@ class RigCombTransResultAccessor : public RigResultAccessor public: RigCombTransResultAccessor(const RigGridBase* grid); - void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); + void setTransResultAccessors(RigResultAccessor* xTransAccessor, + RigResultAccessor* yTransAccessor, + RigResultAccessor* zTransAccessor); virtual double cellScalar(size_t localCellIndex) const; virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: - cvf::Collection m_resultAccessObjects; - + + cvf::ref m_xTransAccessor; + cvf::ref m_yTransAccessor; + cvf::ref m_zTransAccessor; + const RigGridBase* m_grid; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 66096010cd..ff735d47a9 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -43,7 +43,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName) + const QString& uiResultName) { CVF_ASSERT(gridIndex < eclipseCase->gridCount()); CVF_ASSERT(eclipseCase); @@ -102,7 +102,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName) + const QString& uiResultName) { CVF_ASSERT(gridIndex < eclipseCase->gridCount()); CVF_ASSERT(eclipseCase); @@ -118,38 +118,13 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa } else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) { - // TODO - // Taken from RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates - // - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - { - QString resultName = "TRANX"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_I, nativeAccessObject.p()); - } - } - - { - QString resultName = "TRANY"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_J, nativeAccessObject.p()); - } - } - - { - QString resultName = "TRANZ"; - cvf::ref nativeAccessObject = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultName); - if (nativeAccessObject.notNull()) - { - cellFaceAccessObject->setDataAccessObjectForFace(cvf::StructGridInterface::POS_K, nativeAccessObject.p()); - } - } + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); + + cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); return cellFaceAccessObject; } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 8a6ca4bd89..6a4a414865 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -34,7 +34,7 @@ class RigResultAccessorFactory size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& uiResultName); + const QString& uiResultName); // TO BE DELETED @@ -52,7 +52,7 @@ class RigResultAccessorFactory size_t gridIndex, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, - QString& resultName); + const QString& resultName); }; From 7a3d90daa42916bbe35b99995eb0f42391f39f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 7 Aug 2014 15:53:05 +0200 Subject: [PATCH 200/346] Removed fvector and replaced with FixedArray. Needs replacing with std::array when we get to c++11 --- .../ProjectDataModel/RimCellEdgeResultSlot.cpp | 10 +++++----- .../ProjectDataModel/RimCellEdgeResultSlot.h | 15 ++------------- .../RigResultAccessorFactory.cpp | 6 +----- Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h | 4 ++-- 4 files changed, 10 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 48cbe7ffc2..b52e9f0cec 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -144,7 +144,7 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const QList optionList; - std::map > varBaseNameToVarsMap; + std::map > varBaseNameToVarsMap; int i; for (i = 0; i < varList.size(); ++i) @@ -164,7 +164,7 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const } } - std::map >::iterator it; + std::map >::iterator it; for (it = varBaseNameToVarsMap.begin(); it != varBaseNameToVarsMap.end(); ++it) { @@ -174,16 +174,16 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const bool firstText = true; for (cubeFaceIdx = 0; cubeFaceIdx < 6; ++cubeFaceIdx) { - if (!it->second.v[cubeFaceIdx].isEmpty()) + if (!it->second[cubeFaceIdx].isEmpty()) { if (firstText) { - optionUiName += it->second.v[cubeFaceIdx]; + optionUiName += it->second[cubeFaceIdx]; firstText = false; } else { - optionUiName += QString(", ") + it->second.v[cubeFaceIdx]; + optionUiName += QString(", ") + it->second[cubeFaceIdx]; } } } diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h index 4bf0bd1ef1..51ebce253a 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h @@ -22,23 +22,12 @@ #include "cafPdmField.h" #include "cafAppEnum.h" #include "RimDefines.h" +#include "cafFixedArray.h" class RigCaseCellResultsData; class RimLegendConfig; class RimReservoirView; -namespace caf -{ -template -class fvector -{ -public: - T v[vectorSize]; - T& operator[] (size_t idx) { return v[idx]; } -const T& operator[] (size_t idx) const { return v[idx]; } - -}; -} //================================================================================================== /// @@ -86,7 +75,7 @@ class RimCellEdgeResultSlot : public caf::PdmObject void resetResultIndices(); void updateIgnoredScalarValue(); protected: - caf::fvector, 6 > m_resultNameToIndexPairs; + caf::FixedArray, 6 > m_resultNameToIndexPairs; caf::PdmPointer m_reservoirView; double m_ignoredResultScalar; }; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index ff735d47a9..4b45c963b0 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -64,11 +64,7 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor } std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); - - // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps - // See RiaSetGridProperty command in RiaPropertyDataCommands - // - // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL + if (timeStepIndex >= scalarSetResults.size()) { return NULL; diff --git a/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h b/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h index 56a8c83393..6602c333cb 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafFixedArray.h @@ -55,8 +55,8 @@ class FixedArray FixedArray& operator=(const T* ptr) { for (size_t i = 0; i < size ; ++i) m_array[i] = ptr[i]; return *this;} - template T& operator[](const IndexType& index) { CVF_TIGHT_ASSERT(static_cast(index) < size); return m_array[index]; } - template const T& operator[](const IndexType& index) const { CVF_TIGHT_ASSERT(static_cast(index) < size); return m_array[index]; } + template T& operator[](const IndexType& index) { return m_array[index]; } + template const T& operator[](const IndexType& index) const { return m_array[index]; } }; typedef FixedArray IntArray3; From d9e9a173e44e2d1c7666bb4f53f65bb4d890337b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 8 Aug 2014 08:37:56 +0200 Subject: [PATCH 201/346] Added RigResultModifier and use this object for result modifications --- .../RimStatisticsCaseEvaluator.cpp | 16 ++- .../RimStatisticsCaseEvaluator.h | 1 - .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigResultAccessorFactory.cpp | 2 +- .../ReservoirDataModel/RigResultModifier.h | 3 + .../RigResultModifierFactory.cpp | 102 ++++++++++++++++++ .../RigResultModifierFactory.h | 44 ++++++++ .../RiaPropertyDataCommands.cpp | 37 +++---- 8 files changed, 175 insertions(+), 32 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index ae6f742925..5693b69ec9 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,7 +20,10 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultModifier.h" +#include "RigResultModifierFactory.h" #include "RigStatisticsMath.h" + #include "RimReservoirCellResultsStorage.h" #include "cafProgressInfo.h" @@ -204,7 +207,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result // Build data access objects for destination scalar results // Find the created result container, if any, and put its resultAccessor into the enum indexed destination collection - cvf::Collection destinationDataAccessList; + cvf::Collection destinationDataAccessList; std::vector statisticalResultNames(STAT_PARAM_COUNT); statisticalResultNames[MIN] = createResultNameMin(resultName); @@ -219,14 +222,9 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result for (size_t stIdx = 0; stIdx < statisticalResultNames.size(); ++stIdx) { size_t scalarResultIndex = destCellResultsData->findScalarResultIndex(resultType, statisticalResultNames[stIdx]); - if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) - { - destinationDataAccessList.push_back(m_destinationCase->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex).p()); - } - else - { - destinationDataAccessList.push_back(NULL); - } + + cvf::ref resultModifier = RigResultModifierFactory::createResultModifier(m_destinationCase, grid->gridIndex(), poroModel, dataAccessTimeStepIndex, scalarResultIndex); + destinationDataAccessList.push_back(resultModifier.p()); } std::vector statParams(STAT_PARAM_COUNT, HUGE_VAL); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 906ad17c7d..6e3392ef7a 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -24,7 +24,6 @@ #include #include -#include class RimCase; class RigCaseData; diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 1da15926a7..950bbb3f0d 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -17,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigResultModifier.h +${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h ${CEE_CURRENT_LIST_DIR}RigMainGrid.h ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.h @@ -42,6 +43,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp ${CEE_CURRENT_LIST_DIR}RigReservoirBuilderMock.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 4b45c963b0..41c30f3fc7 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -37,7 +37,7 @@ //-------------------------------------------------------------------------------------------------- -/// +/// This function must be harmonized with RigResultModifierFactory::createResultModifier() //-------------------------------------------------------------------------------------------------- cvf::ref RigResultAccessorFactory::createNativeResultAccessor(RigCaseData* eclipseCase, size_t gridIndex, diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h index 3ab82e3462..4c9d8d7dc1 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifier.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -18,6 +18,9 @@ #pragma once +#include "RigGridBase.h" +#include "RigActiveCellInfo.h" + //================================================================================================== /// diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp new file mode 100644 index 0000000000..80efe51c5a --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigResultModifierFactory.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultModifier.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// This function must be harmonized with RigResultAccessorFactory::createNativeResultAccessor() +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultModifierFactory::createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(uiResultName); + + return createResultModifier(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultModifierFactory::createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, size_t scalarResultIndex) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarResultIndex); + + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarResultIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultModifier(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultModifier(grid, resultValues); + return object; + } +} diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h new file mode 100644 index 0000000000..18f7dbd3f3 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifReaderInterface.h" + +class RigCaseData; +class RigResultModifier; + +class RigResultModifierFactory +{ +public: + static cvf::ref + createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + QString& uiResultName); + + static cvf::ref + createResultModifier(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t scalarResultIndex); +}; + + diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 01073c5cc8..101f9edcea 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -16,34 +16,31 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaStdInclude.h" + #include "RiaSocketCommand.h" +#include "RiaSocketDataTransfer.h" #include "RiaSocketServer.h" #include "RiaSocketTools.h" -#include "RiuMainWindow.h" -#include "RiuProcessMonitor.h" +#include "RifReaderInterface.h" -#include "RigCaseData.h" +#include "RigActiveCellInfo.h" #include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultModifier.h" +#include "RigResultModifierFactory.h" -#include "RimReservoirCellResultsStorage.h" #include "RimCase.h" #include "RimInputCase.h" +#include "RimInputProperty.h" #include "RimInputPropertyCollection.h" -#include "RimUiTreeModelPdm.h" +#include "RimReservoirCellResultsStorage.h" #include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" - -#include -#include "RiaApplication.h" -#include "RiaPreferences.h" -#include "RiaSocketDataTransfer.h" -#include "RimInputProperty.h" +#include "RimUiTreeModelPdm.h" + +#include "RiuMainWindow.h" +#include "RiuProcessMonitor.h" //-------------------------------------------------------------------------------------------------- @@ -934,14 +931,12 @@ class RiaSetGridProperty : public RiaSocketCommand return true; } - cvf::ref cellCenterDataAccessObject = - m_currentReservoir->reservoirData()->resultAccessor(grid, m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); - - if (!cellCenterDataAccessObject.isNull()) + cvf::ref resultModifier = RigResultModifierFactory::createResultModifier(m_currentReservoir->reservoirData(), grid->gridIndex(), m_porosityModelEnum, m_requestedTimesteps[m_currentTimeStepNumberToRead], m_currentScalarIndex); + if (!resultModifier.isNull()) { for (size_t cellIdx = 0; static_cast(cellIdx) < cellCountFromOctave; cellIdx++) { - cellCenterDataAccessObject->setCellScalar(cellIdx, doubleValues[cellIdx]); + resultModifier->setCellScalar(cellIdx, doubleValues[cellIdx]); } } From 6fcc50de20067496cb923e505613ccf367898ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 08:38:12 +0200 Subject: [PATCH 202/346] cellEdgeAccessor : Use FixedArray instead of collection --- .../ReservoirDataModel/RigCellEdgeResultAccessor.cpp | 4 ++-- .../ReservoirDataModel/RigCellEdgeResultAccessor.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index f94aebe8c2..52f1c136da 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -26,7 +26,7 @@ //-------------------------------------------------------------------------------------------------- RigCellEdgeResultAccessor::RigCellEdgeResultAccessor() { - m_resultAccessObjects.resize(6); + } //-------------------------------------------------------------------------------------------------- @@ -54,7 +54,7 @@ double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const { - const RigResultAccessor* resultAccessObj = m_resultAccessObjects.at(faceId); + const RigResultAccessor* resultAccessObj = m_resultAccessObjects[faceId].p(); if (resultAccessObj != NULL) { return resultAccessObj->cellFaceScalar(localCellIndex, faceId); diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index cdc70c0937..b6fb3d8534 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -20,7 +20,7 @@ #include "RigResultAccessor.h" -#include "cvfCollection.h" +#include "cafFixedArray.h" //================================================================================================== @@ -37,5 +37,5 @@ class RigCellEdgeResultAccessor : public RigResultAccessor virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: - cvf::Collection m_resultAccessObjects; + caf::FixedArray, 6> m_resultAccessObjects; }; From 0ea794a1a862fe98de62838346acefeaf43ff442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 09:50:57 +0200 Subject: [PATCH 203/346] Renamed localCellIndex to gridLocalCellIndex --- .../FileInterface/RifReaderEclipseOutput.cpp | 24 +++++++++---------- .../ProjectDataModel/RimReservoirView.cpp | 8 +++---- .../RigActiveCellsResultAccessor.cpp | 8 +++---- .../RigActiveCellsResultAccessor.h | 4 ++-- .../RigAllGridCellsResultAccessor.cpp | 8 +++---- .../RigAllGridCellsResultAccessor.h | 4 ++-- .../RigCellEdgeResultAccessor.cpp | 6 ++--- .../RigCellEdgeResultAccessor.h | 4 ++-- .../RigCombTransResultAccessor.cpp | 16 ++++++------- .../RigCombTransResultAccessor.h | 4 ++-- .../ReservoirDataModel/RigFault.cpp | 6 ++--- .../ReservoirDataModel/RigResultAccessor.h | 12 +++++----- .../SocketInterface/RiaGeometryCommands.cpp | 8 +++---- 13 files changed, 56 insertions(+), 56 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index a620ce1893..a5650aa826 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -112,29 +112,29 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn // Loop over cells and fill them with data #pragma omp parallel for - for (int localCellIdx = 0; localCellIdx < cellCount; ++localCellIdx) + for (int gridLocalCellIndex = 0; gridLocalCellIndex < cellCount; ++gridLocalCellIndex) { - RigCell& cell = mainGrid->cells()[cellStartIndex + localCellIdx]; + RigCell& cell = mainGrid->cells()[cellStartIndex + gridLocalCellIndex]; - cell.setCellIndex(localCellIdx); + cell.setCellIndex(gridLocalCellIndex); // Active cell index - int matrixActiveIndex = ecl_grid_get_active_index1(localEclGrid, localCellIdx); + int matrixActiveIndex = ecl_grid_get_active_index1(localEclGrid, gridLocalCellIndex); if (matrixActiveIndex != -1) { - activeCellInfo->setCellResultIndex(cellStartIndex + localCellIdx, matrixActiveStartIndex + matrixActiveIndex); + activeCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, matrixActiveStartIndex + matrixActiveIndex); } - int fractureActiveIndex = ecl_grid_get_active_fracture_index1(localEclGrid, localCellIdx); + int fractureActiveIndex = ecl_grid_get_active_fracture_index1(localEclGrid, gridLocalCellIndex); if (fractureActiveIndex != -1) { - fractureActiveCellInfo->setCellResultIndex(cellStartIndex + localCellIdx, fractureActiveStartIndex + fractureActiveIndex); + fractureActiveCellInfo->setCellResultIndex(cellStartIndex + gridLocalCellIndex, fractureActiveStartIndex + fractureActiveIndex); } // Parent cell index - int parentCellIndex = ecl_grid_get_parent_cell1(localEclGrid, localCellIdx); + int parentCellIndex = ecl_grid_get_parent_cell1(localEclGrid, gridLocalCellIndex); if (parentCellIndex == -1) { cell.setParentCellIndex(cvf::UNDEFINED_SIZE_T); @@ -148,14 +148,14 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn int cIdx; for (cIdx = 0; cIdx < 8; ++cIdx) { - double * point = mainGrid->nodes()[nodeStartIndex + localCellIdx * 8 + cellMappingECLRi[cIdx]].ptr(); - ecl_grid_get_corner_xyz1(localEclGrid, localCellIdx, cIdx, &(point[0]), &(point[1]), &(point[2])); + double * point = mainGrid->nodes()[nodeStartIndex + gridLocalCellIndex * 8 + cellMappingECLRi[cIdx]].ptr(); + ecl_grid_get_corner_xyz1(localEclGrid, gridLocalCellIndex, cIdx, &(point[0]), &(point[1]), &(point[2])); point[2] = -point[2]; // Flipping Z making depth become negative z values - cell.cornerIndices()[cIdx] = nodeStartIndex + localCellIdx*8 + cIdx; + cell.cornerIndices()[cIdx] = nodeStartIndex + gridLocalCellIndex*8 + cIdx; } // Sub grid in cell - const ecl_grid_type* subGrid = ecl_grid_get_cell_lgr1(localEclGrid, localCellIdx); + const ecl_grid_type* subGrid = ecl_grid_get_cell_lgr1(localEclGrid, gridLocalCellIndex); if (subGrid != NULL) { int subGridId = ecl_grid_get_lgr_nr(subGrid); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index d7cb997020..39492f74ec 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1899,10 +1899,10 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t localCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.cellIndex(); size_t i, j, k; - if (hostGrid->ijkFromCellIndex(localCellIndex, &i, &j, &k)) + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) { // Adjust to 1-based Eclipse indexing i++; @@ -1921,10 +1921,10 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c2GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t localCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.cellIndex(); size_t i, j, k; - if (hostGrid->ijkFromCellIndex(localCellIndex, &i, &j, &k)) + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) { // Adjust to 1-based Eclipse indexing i++; diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index a72a3b1ec4..7555ad8c4d 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -35,11 +35,11 @@ RigActiveCellsResultAccessor::RigActiveCellsResultAccessor(const RigGridBase* gr //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const +double RigActiveCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; @@ -51,8 +51,8 @@ double RigActiveCellsResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigActiveCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigActiveCellsResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { - return cellScalar(localCellIndex); + return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 9647033722..4cd7ae73f0 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -32,8 +32,8 @@ class RigActiveCellsResultAccessor : public RigResultAccessor public: RigActiveCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: const RigActiveCellInfo* m_activeCellInfo; diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 5ba549176f..14b7b30a3c 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -35,11 +35,11 @@ RigAllGridCellsResultAccessor::RigAllGridCellsResultAccessor(const RigGridBase* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const +double RigAllGridCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(localCellIndex); + size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); return m_reservoirResultValues->at(globalGridCellIndex); @@ -48,8 +48,8 @@ double RigAllGridCellsResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigAllGridCellsResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigAllGridCellsResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { - return cellScalar(localCellIndex); + return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 840e3f46a7..194b591d4d 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -31,8 +31,8 @@ class RigAllGridCellsResultAccessor : public RigResultAccessor public: RigAllGridCellsResultAccessor(const RigGridBase* grid, std::vector* reservoirResultValues); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: const RigGridBase* m_grid; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index 52f1c136da..f21876d427 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -40,7 +40,7 @@ void RigCellEdgeResultAccessor::setDataAccessObjectForFace(cvf::StructGridInterf //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const +double RigCellEdgeResultAccessor::cellScalar(size_t gridLocalCellIndex) const { // TODO: How to handle when we get here? @@ -52,12 +52,12 @@ double RigCellEdgeResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCellEdgeResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCellEdgeResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { const RigResultAccessor* resultAccessObj = m_resultAccessObjects[faceId].p(); if (resultAccessObj != NULL) { - return resultAccessObj->cellFaceScalar(localCellIndex, faceId); + return resultAccessObj->cellFaceScalar(gridLocalCellIndex, faceId); } return HUGE_VAL; diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index b6fb3d8534..4ca4d0a09a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -33,8 +33,8 @@ class RigCellEdgeResultAccessor : public RigResultAccessor void setDataAccessObjectForFace(cvf::StructGridInterface::FaceType faceId, RigResultAccessor* resultAccessObject); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: caf::FixedArray, 6> m_resultAccessObjects; diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 2e67ac5b6f..715a073137 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -49,7 +49,7 @@ void RigCombTransResultAccessor::setTransResultAccessors(RigResultAccessor* xTra //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const +double RigCombTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const { CVF_TIGHT_ASSERT(false); @@ -59,7 +59,7 @@ double RigCombTransResultAccessor::cellScalar(size_t localCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCombTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { switch (faceId) { @@ -67,7 +67,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_xTransAccessor.notNull()) { - return m_xTransAccessor->cellScalar(localCellIndex); + return m_xTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -76,7 +76,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_xTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) { @@ -89,7 +89,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_yTransAccessor.notNull()) { - return m_yTransAccessor->cellScalar(localCellIndex); + return m_yTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -98,7 +98,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_yTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) { @@ -111,7 +111,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St { if (m_zTransAccessor.notNull()) { - return m_zTransAccessor->cellScalar(localCellIndex); + return m_zTransAccessor->cellScalar(gridLocalCellIndex); } } break; @@ -120,7 +120,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t localCellIndex, cvf::St if (m_zTransAccessor.notNull()) { size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(localCellIndex, &i, &j, &k); + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) { diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index fe9b89128f..2ecdc6202c 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -37,8 +37,8 @@ class RigCombTransResultAccessor : public RigResultAccessor RigResultAccessor* yTransAccessor, RigResultAccessor* zTransAccessor); - virtual double cellScalar(size_t localCellIndex) const; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const; + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 6bfaba0dca..8d9cfc5560 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,16 +115,16 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t globalCellIndex = grid->globalGridCellIndex(localCellIndex); + //size_t globalCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); if (ni < mainGrid->cellCountI() && nj < mainGrid->cellCountJ() && nk < mainGrid->cellCountK()) { - size_t localCellIndex = mainGrid->cellIndexFromIJK(i, j, k); + size_t gridLocalCellIndex = mainGrid->cellIndexFromIJK(i, j, k); size_t oppositeCellIndex = mainGrid->cellIndexFromIJK(ni, nj, nk); - m_faultFaces.push_back(FaultFace(localCellIndex, faceEnum, oppositeCellIndex)); + m_faultFaces.push_back(FaultFace(gridLocalCellIndex, faceEnum, oppositeCellIndex)); } else { diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index a49bdc62da..1113695e22 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -31,8 +31,8 @@ class RigResultAccessor : public cvf::Object { public: - virtual double cellScalar(size_t localCellIndex) const = 0; - virtual double cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + virtual double cellScalar(size_t gridLocalCellIndex) const = 0; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; #if 0 @@ -43,8 +43,8 @@ class RigResultAccessor : public cvf::Object class RigResultAccessor2d : public cvf::Object { public: - virtual cvf::Vec2d cellScalar(size_t localCellIndex) const = 0; - virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; virtual QString resultName() const = 0; @@ -61,8 +61,8 @@ class RigTernaryResultAccessor : public Rig2DResultAccessor /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others - virtual cvf::Vec2d cellScalar(size_t localCellIndex) { }; - virtual cvf::Vec2d cellFaceScalar(size_t localCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t localCellIndex); }; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) { }; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t gridLocalCellIndex); }; virtual QString resultName() const = 0; diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index a682b5b3cb..567dc990eb 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -101,8 +101,8 @@ class RiaGetCellCenters : public RiaSocketCommand { for (size_t i = 0; i < cellCountI; i++) { - size_t localCellIdx = rigGrid->cellIndexFromIJK(i, j, k); - cvf::Vec3d center = rigGrid->cell(localCellIdx).center(); + size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK(i, j, k); + cvf::Vec3d center = rigGrid->cell(gridLocalCellIndex).center(); doubleValues[valueIndex++] = center[coordIdx]; } @@ -268,8 +268,8 @@ class RiaGetCellCorners : public RiaSocketCommand { for (size_t i = 0; i < cellCountI; i++) { - size_t localCellIdx = rigGrid->cellIndexFromIJK(i, j, k); - rigGrid->cellCornerVertices(localCellIdx, cornerVerts); + size_t gridLocalCellIndex = rigGrid->cellIndexFromIJK(i, j, k); + rigGrid->cellCornerVertices(gridLocalCellIndex, cornerVerts); doubleValues[valueIndex++] = cornerVerts[cornerIndexMapping][coordIdx]; } From 37ef1cf71c4615aae25290c014a6fdbfe17d2ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:02:26 +0200 Subject: [PATCH 204/346] Renamed globalCellIndex to reservoirCellIndex --- .../RivReservoirViewPartMgr.cpp | 6 +++--- .../RimIdenticalGridCaseGroup.cpp | 12 ++++++------ .../ReservoirDataModel/RigActiveCellInfo.cpp | 18 +++++++++--------- .../ReservoirDataModel/RigActiveCellInfo.h | 6 +++--- .../ReservoirDataModel/RigFault.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigFault.h | 8 ++++---- .../ReservoirDataModel/RigNNCData.cpp | 4 ++-- .../ReservoirDataModel/RigNNCData.h | 2 +- .../SocketInterface/RiaGeometryCommands.cpp | 12 ++++++------ 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index e3fa51f9af..7c31d28ce4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -562,11 +562,11 @@ void RivReservoirViewPartMgr::computeNativeVisibility(cvf::UByteArray* cellVisib for (int cellIndex = 0; cellIndex < static_cast(grid->cellCount()); cellIndex++) { const RigCell& cell = grid->cell(cellIndex); - size_t globalCellIndex = cell.mainGridCellIndex(); + size_t reservoirCellIndex = cell.mainGridCellIndex(); if ( !invalidCellsIsVisible && cell.isInvalid() - || !inactiveCellsIsVisible && !activeCellInfo->isActive(globalCellIndex) - || !activeCellsIsVisible && activeCellInfo->isActive(globalCellIndex) + || !inactiveCellsIsVisible && !activeCellInfo->isActive(reservoirCellIndex) + || !activeCellsIsVisible && activeCellInfo->isActive(reservoirCellIndex) //|| mainGridIsVisible && (cell.subGrid() != NULL) // this is handled on global level instead || (*cellIsInWellStatuses)[cellIndex] ) diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 442dd7886f..91c67b2af9 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -254,11 +254,11 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t globalCellIdx = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); if (activeM[localGridCellIdx] == 0) { - if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(globalCellIdx)) + if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(reservoirCellIndex)) { activeM[localGridCellIdx] = 1; } @@ -266,7 +266,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() if (activeF[localGridCellIdx] == 0) { - if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(globalCellIdx)) + if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(reservoirCellIndex)) { activeF[localGridCellIdx] = 1; } @@ -279,17 +279,17 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) { - size_t globalCellIdx = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); if (activeM[localGridCellIdx] != 0) { - m_unionOfMatrixActiveCells->setCellResultIndex(globalCellIdx, globalActiveMatrixIndex++); + m_unionOfMatrixActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveMatrixIndex++); activeMatrixIndex++; } if (activeF[localGridCellIdx] != 0) { - m_unionOfFractureActiveCells->setCellResultIndex(globalCellIdx, globalActiveFractureIndex++); + m_unionOfFractureActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveFractureIndex++); activeFractureIndex++; } } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index b58b17c5d4..7e9c07b5a3 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -58,41 +58,41 @@ size_t RigActiveCellInfo::globalCellResultCount() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RigActiveCellInfo::isActive(size_t globalCellIndex) const +bool RigActiveCellInfo::isActive(size_t reservoirCellIndex) const { if (m_cellIndexToResultIndex.size() == 0) { return true; } - CVF_TIGHT_ASSERT(globalCellIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_cellIndexToResultIndex.size()); - return m_cellIndexToResultIndex[globalCellIndex] != cvf::UNDEFINED_SIZE_T; + return m_cellIndexToResultIndex[reservoirCellIndex] != cvf::UNDEFINED_SIZE_T; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::cellResultIndex(size_t globalCellIndex) const +size_t RigActiveCellInfo::cellResultIndex(size_t reservoirCellIndex) const { if (m_cellIndexToResultIndex.size() == 0) { - return globalCellIndex; + return reservoirCellIndex; } - CVF_TIGHT_ASSERT(globalCellIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_cellIndexToResultIndex.size()); - return m_cellIndexToResultIndex[globalCellIndex]; + return m_cellIndexToResultIndex[reservoirCellIndex]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setCellResultIndex(size_t globalCellIndex, size_t globalCellResultIndex) +void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t globalCellResultIndex) { CVF_TIGHT_ASSERT(globalCellResultIndex < m_cellIndexToResultIndex.size()); - m_cellIndexToResultIndex[globalCellIndex] = globalCellResultIndex; + m_cellIndexToResultIndex[reservoirCellIndex] = globalCellResultIndex; if (globalCellResultIndex >= m_globalCellResultCount) { diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index cbe11c9b8c..562d4e1074 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -38,9 +38,9 @@ class RigActiveCellInfo : public cvf::Object size_t globalCellResultCount() const; bool isCoarseningActive() const; - bool isActive(size_t globalCellIndex) const; - size_t cellResultIndex(size_t globalCellIndex) const; - void setCellResultIndex(size_t globalCellIndex, size_t globalResultCellIndex); + bool isActive(size_t reservoirCellIndex) const; + size_t cellResultIndex(size_t reservoirCellIndex) const; + void setCellResultIndex(size_t reservoirCellIndex, size_t globalResultCellIndex); void setGridCount(size_t gridCount); void setGridActiveCellCounts(size_t gridIndex, size_t activeCellCount); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 8d9cfc5560..476f2d1f4c 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,7 +115,7 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t globalCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + //size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 39198b5feb..b4a31c9ad3 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -46,14 +46,14 @@ class RigFaultsPrCellAccumulator : public cvf::Object m_faultIdxForCellFace.resize(globalCellCount, initVal); } - inline int faultIdx(size_t globalCellIdx, cvf::StructGridInterface::FaceType face) + inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) { - return m_faultIdxForCellFace[globalCellIdx][face]; + return m_faultIdxForCellFace[reservoirCellIndex][face]; } - inline void setFaultIdx(size_t globalCellIdx, cvf::StructGridInterface::FaceType face, int faultIdx) + inline void setFaultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face, int faultIdx) { - m_faultIdxForCellFace[globalCellIdx][face] = faultIdx; + m_faultIdxForCellFace[reservoirCellIndex][face] = faultIdx; } private: diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index c5da5e45de..f6b619fbdc 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -164,12 +164,12 @@ void RigNNCData::processConnections(const RigMainGrid& mainGrid) //-------------------------------------------------------------------------------------------------- /// TODO: Possibly not needed ! //-------------------------------------------------------------------------------------------------- -const std::vector& RigNNCData::findConnectionIndices( size_t globalCellIndex, cvf::StructGridInterface::FaceType face) const +const std::vector& RigNNCData::findConnectionIndices( size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const { ConnectionSearchMap::const_iterator it; static std::vector empty; - it = m_cellIdxToFaceToConnectionIdxMap.find(globalCellIndex); + it = m_cellIdxToFaceToConnectionIdxMap.find(reservoirCellIndex); if (it != m_cellIdxToFaceToConnectionIdxMap.end()) { return it->second[face]; diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index ca4b9bf54d..bbad5e3fe7 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -63,7 +63,7 @@ class RigNNCData : public cvf::Object const std::vector& connections() const { return m_connections; }; private: // This section is possibly not needed - //const std::vector& findConnectionIndices(size_t globalCellIndex, cvf::StructGridInterface::FaceType face) const; + //const std::vector& findConnectionIndices(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; //typedef std::map, 7 > > ConnectionSearchMap; //ConnectionSearchMap m_cellIdxToFaceToConnectionIdxMap; diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index 567dc990eb..7a07f09d4a 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -177,11 +177,11 @@ class RiaGetActiveCellCenters : public RiaSocketCommand { quint64 valueIndex = 0; - for (size_t globalCellIdx = 0; globalCellIdx < mainGrid->cells().size(); globalCellIdx++) + for (size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->cells().size(); reservoirCellIndex++) { - if (!actCellInfo->isActive(globalCellIdx)) continue; + if (!actCellInfo->isActive(reservoirCellIndex)) continue; - cvf::Vec3d center = mainGrid->cells()[globalCellIdx].center(); + cvf::Vec3d center = mainGrid->cells()[reservoirCellIndex].center(); doubleValues[valueIndex++] = center[coordIdx]; } @@ -351,11 +351,11 @@ class RiaGetActiveCellCorners : public RiaSocketCommand quint64 valueIndex = 0; - for (size_t globalCellIdx = 0; globalCellIdx < mainGrid->cells().size(); globalCellIdx++) + for (size_t reservoirCellIndex = 0; reservoirCellIndex < mainGrid->cells().size(); reservoirCellIndex++) { - if (!actCellInfo->isActive(globalCellIdx)) continue; + if (!actCellInfo->isActive(reservoirCellIndex)) continue; - mainGrid->cellCornerVertices(globalCellIdx, cornerVerts); + mainGrid->cellCornerVertices(reservoirCellIndex, cornerVerts); doubleValues[valueIndex++] = cornerVerts[cornerIndexMapping][coordIdx]; } From 16f762984ece0c22e0d4095dd1fda7abf0e3f693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:07:32 +0200 Subject: [PATCH 205/346] Renamed more stuff to gridLocalCellIndex --- .../RimIdenticalGridCaseGroup.cpp | 20 +++++++++---------- .../ReservoirDataModel/RigGridBase.cpp | 4 ++-- .../ReservoirDataModel/RigGridBase.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 91c67b2af9..45f83d47ea 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -250,25 +250,25 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() std::vector activeM(grid->cellCount(), 0); std::vector activeF(grid->cellCount(), 0); - for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) + for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); - if (activeM[localGridCellIdx] == 0) + if (activeM[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->isActive(reservoirCellIndex)) { - activeM[localGridCellIdx] = 1; + activeM[gridLocalCellIndex] = 1; } } - if (activeF[localGridCellIdx] == 0) + if (activeF[gridLocalCellIndex] == 0) { if (caseCollection->reservoirs[caseIdx]->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->isActive(reservoirCellIndex)) { - activeF[localGridCellIdx] = 1; + activeF[gridLocalCellIndex] = 1; } } } @@ -277,17 +277,17 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() size_t activeMatrixIndex = 0; size_t activeFractureIndex = 0; - for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++) + for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(localGridCellIdx); + size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); - if (activeM[localGridCellIdx] != 0) + if (activeM[gridLocalCellIndex] != 0) { m_unionOfMatrixActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveMatrixIndex++); activeMatrixIndex++; } - if (activeF[localGridCellIdx] != 0) + if (activeF[gridLocalCellIndex] != 0) { m_unionOfFractureActiveCells->setCellResultIndex(reservoirCellIndex, globalActiveFractureIndex++); activeFractureIndex++; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 1342059660..42036ff6a0 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -368,9 +368,9 @@ double RigGridBase::characteristicIJCellSize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigGridBase::globalGridCellIndex(size_t localGridCellIndex) const +size_t RigGridBase::globalGridCellIndex(size_t gridLocalCellIndex) const { - return m_indexToStartOfCells + localGridCellIndex; + return m_indexToStartOfCells + gridLocalCellIndex; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index a8285ad227..e2819dec68 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -52,7 +52,7 @@ class RigGridBase : public cvf::StructGridInterface RigCell& cell(size_t gridCellIndex); const RigCell& cell(size_t gridCellIndex) const; - size_t globalGridCellIndex(size_t localGridCellIndex) const; + size_t globalGridCellIndex(size_t gridLocalCellIndex) const; void setIndexToStartOfCells(size_t indexToStartOfCells) { m_indexToStartOfCells = indexToStartOfCells; } void setGridIndex(size_t index) { m_gridIndex = index; } From 6cdd9cfdc53aec77cd240622a5adeda473e14588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:16:54 +0200 Subject: [PATCH 206/346] Renamed globalGridCellIndex to reservoirCellIndex --- .../FileInterface/RifReaderEclipseOutput.cpp | 4 ++-- .../RimIdenticalGridCaseGroup.cpp | 4 ++-- .../ProjectDataModel/RimReservoirView.cpp | 8 ++++---- .../RimStatisticsCaseEvaluator.cpp | 4 ++-- .../RigActiveCellsResultAccessor.cpp | 4 ++-- .../RigAllGridCellsResultAccessor.cpp | 6 +++--- .../ReservoirDataModel/RigCaseData.cpp | 6 +++--- .../ReservoirDataModel/RigFault.cpp | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../ReservoirDataModel/RigGridBase.h | 2 +- .../ReservoirDataModel/RigMainGrid.cpp | 2 +- .../RigResultAccessorFactory.cpp | 20 +++++++++---------- .../ReservoirDataModel/RigResultModifier.h | 10 +++++----- 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index a5650aa826..3018d29dd4 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -482,9 +482,9 @@ void RifReaderEclipseOutput::transferNNCData( const ecl_grid_type * mainEclGrid for (int nIdx = 0; nIdx < numNNC; ++nIdx) { RigGridBase* grid1 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr1); - mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->globalGridCellIndex(eclNNCData[nIdx].global_index1); + mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->reservoirCellIndex(eclNNCData[nIdx].global_index1); RigGridBase* grid2 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr2); - mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->globalGridCellIndex(eclNNCData[nIdx].global_index2); + mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->reservoirCellIndex(eclNNCData[nIdx].global_index2); mainGrid->nncData()->connections()[nIdx].m_transmissibility = eclNNCData[nIdx].trans; } diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 45f83d47ea..0ac3651308 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -254,7 +254,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { for (size_t caseIdx = 0; caseIdx < caseCollection->reservoirs.size(); caseIdx++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] == 0) { @@ -279,7 +279,7 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() for (size_t gridLocalCellIndex = 0; gridLocalCellIndex < grid->cellCount(); gridLocalCellIndex++) { - size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); if (activeM[gridLocalCellIndex] != 0) { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 39492f74ec..65a8f6706a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1641,9 +1641,9 @@ void RimReservoirView::calculateVisibleWellCellsIncFence(cvf::UByteArray* visibl if (wellResFrames[wfIdx].m_wellHead.m_gridIndex == grid->gridIndex()) { size_t gridCellIndex = wellResFrames[wfIdx].m_wellHead.m_gridCellIndex; - size_t globalGridCellIndex = grid->globalGridCellIndex(gridCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(gridCellIndex); - if (activeCellInfo->isActive(globalGridCellIndex)) + if (activeCellInfo->isActive(reservoirCellIndex)) { (*visibleCells)[gridCellIndex] = true; } @@ -1698,9 +1698,9 @@ void RimReservoirView::calculateVisibleWellCellsIncFence(cvf::UByteArray* visibl for ( fIdx = 0; fIdx < cellCountFenceDirection; ++fIdx) { size_t fenceCellIndex = grid->cellIndexFromIJK(*pI,*pJ,*pK); - size_t globalGridCellIndex = grid->globalGridCellIndex(fenceCellIndex); + size_t reservoirCellIndex = grid->reservoirCellIndex(fenceCellIndex); - if (activeCellInfo && activeCellInfo->isActive(globalGridCellIndex)) + if (activeCellInfo && activeCellInfo->isActive(reservoirCellIndex)) { (*visibleCells)[fenceCellIndex] = true; } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 5693b69ec9..85f7c999e9 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -234,8 +234,8 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result for (int cellIdx = 0; static_cast(cellIdx) < grid->cellCount(); cellIdx++) { - size_t globalGridCellIdx = grid->globalGridCellIndex(cellIdx); - if (m_destinationCase->activeCellInfo(poroModel)->isActive(globalGridCellIdx)) + size_t reservoirCellIndex = grid->reservoirCellIndex(cellIdx); + if (m_destinationCase->activeCellInfo(poroModel)->isActive(reservoirCellIndex)) { // Extract the cell values from each of the cases and assemble them into one vector diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index 7555ad8c4d..29c563a25e 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -39,8 +39,8 @@ double RigActiveCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) const { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 14b7b30a3c..247ef7f953 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -39,10 +39,10 @@ double RigAllGridCellsResultAccessor::cellScalar(size_t gridLocalCellIndex) cons { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - return m_reservoirResultValues->at(globalGridCellIndex); + return m_reservoirResultValues->at(reservoirCellIndex); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 34830722fd..1d5619f87b 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -166,9 +166,9 @@ void RigCaseData::computeWellCellsPrGrid() if (gridIndex < m_wellCellsInGrid.size() && gridCellIndex < m_wellCellsInGrid[gridIndex]->size()) { - size_t globalGridCellIndex = grids[gridIndex]->globalGridCellIndex(gridCellIndex); - if (m_activeCellInfo->isActive(globalGridCellIndex) - || m_fractureActiveCellInfo->isActive(globalGridCellIndex)) + size_t reservoirCellIndex = grids[gridIndex]->reservoirCellIndex(gridCellIndex); + if (m_activeCellInfo->isActive(reservoirCellIndex) + || m_fractureActiveCellInfo->isActive(reservoirCellIndex)) { m_wellCellsInGrid[gridIndex]->set(gridCellIndex, true); m_gridCellToWellIndex[gridIndex]->set(gridCellIndex, static_cast(wIdx)); diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 476f2d1f4c..0db6f08c90 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -115,7 +115,7 @@ void RigFault::computeFaultFacesFromCellRanges(const RigMainGrid* mainGrid) } // Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex - //size_t reservoirCellIndex = grid->globalGridCellIndex(gridLocalCellIndex); + //size_t reservoirCellIndex = grid->reservoirCellIndex(gridLocalCellIndex); size_t ni, nj, nk; mainGrid->neighborIJKAtCellFace(i, j, k, faceEnum, &ni, &nj, &nk); diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 42036ff6a0..6f145298a4 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -368,7 +368,7 @@ double RigGridBase::characteristicIJCellSize() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigGridBase::globalGridCellIndex(size_t gridLocalCellIndex) const +size_t RigGridBase::reservoirCellIndex(size_t gridLocalCellIndex) const { return m_indexToStartOfCells + gridLocalCellIndex; } diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index e2819dec68..c9ce6d8c54 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -52,7 +52,7 @@ class RigGridBase : public cvf::StructGridInterface RigCell& cell(size_t gridCellIndex); const RigCell& cell(size_t gridCellIndex) const; - size_t globalGridCellIndex(size_t gridLocalCellIndex) const; + size_t reservoirCellIndex(size_t gridLocalCellIndex) const; void setIndexToStartOfCells(size_t indexToStartOfCells) { m_indexToStartOfCells = indexToStartOfCells; } void setGridIndex(size_t index) { m_gridIndex = index; } diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 4bbdea1cb9..dc58bf21c3 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -259,7 +259,7 @@ void RigMainGrid::calculateFaults() continue; } - neighborGlobalCellIdx = hostGrid->globalGridCellIndex(neighborGridCellIdx); + neighborGlobalCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); if (m_cells[neighborGlobalCellIdx].isInvalid()) { continue; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 41c30f3fc7..d44ffc0dfb 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -176,10 +176,10 @@ double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) co { if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - return m_reservoirResultValues->at(globalGridCellIndex); + return m_reservoirResultValues->at(reservoirCellIndex); } //-------------------------------------------------------------------------------------------------- @@ -187,10 +187,10 @@ double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) co //-------------------------------------------------------------------------------------------------- void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + (*m_reservoirResultValues)[reservoirCellIndex] = scalarValue; } //-------------------------------------------------------------------------------------------------- @@ -212,8 +212,8 @@ class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAcces { if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); @@ -226,8 +226,8 @@ class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAcces //-------------------------------------------------------------------------------------------------- virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h index 4c9d8d7dc1..651d12c4fe 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifier.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -47,10 +47,10 @@ class RigAllGridCellsResultModifier : public RigResultModifier virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(globalGridCellIndex < m_reservoirResultValues->size()); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - (*m_reservoirResultValues)[globalGridCellIndex] = scalarValue; + (*m_reservoirResultValues)[reservoirCellIndex] = scalarValue; } private: @@ -74,8 +74,8 @@ class RigActiveCellsResultModifier : public RigResultModifier virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) { - size_t globalGridCellIndex = m_grid->globalGridCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(globalGridCellIndex); + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); From 3022a402042996bb72084e2803749e5c951bde5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:27:29 +0200 Subject: [PATCH 207/346] Renamed globalCell to reservoirCell etc. --- .../RifEclipseInputFileTools.cpp | 6 ++-- .../FileInterface/RifReaderEclipseOutput.cpp | 28 +++++++++---------- .../Rim3dOverlayInfoConfig.cpp | 4 +-- .../RimIdenticalGridCaseGroup.cpp | 6 ++-- .../ProjectDataModel/RimResultDefinition.cpp | 2 +- .../RimStatisticsCaseEvaluator.cpp | 4 +-- .../RigActiveCellInfo-Test.cpp | 6 ++-- .../ReservoirDataModel/RigActiveCellInfo.cpp | 8 +++--- .../ReservoirDataModel/RigActiveCellInfo.h | 8 +++--- .../RigReservoirBuilderMock.cpp | 2 +- .../SocketInterface/RiaCaseInfoCommands.cpp | 2 +- .../SocketInterface/RiaGeometryCommands.cpp | 4 +-- .../RiaPropertyDataCommands.cpp | 12 ++++---- 13 files changed, 46 insertions(+), 46 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 74a7892560..1211dc9208 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -88,17 +88,17 @@ bool readDoubleValuesForActiveCells(RigCaseData* reservoir, size_t resultIndex, newPropertyData.push_back(std::vector()); RigActiveCellInfo* activeCellInfo = reservoir->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); - if (activeCellInfo->globalCellCount() > 0 && activeCellInfo->globalCellCount() != activeCellInfo->globalActiveCellCount()) + if (activeCellInfo->reservoirCellCount() > 0 && activeCellInfo->reservoirCellCount() != activeCellInfo->reservoirActiveCellCount()) { std::vector valuesAllCells; valuesAllCells.resize(ecl_kw_get_size(eclKeyWordData), HUGE_VAL); ecl_kw_get_data_as_double(eclKeyWordData, valuesAllCells.data()); - newPropertyData[0].resize(activeCellInfo->globalActiveCellCount(), HUGE_VAL); + newPropertyData[0].resize(activeCellInfo->reservoirActiveCellCount(), HUGE_VAL); std::vector& valuesActiveCells = newPropertyData[0]; size_t acIdx = 0; - for (size_t gcIdx = 0; gcIdx < activeCellInfo->globalCellCount(); gcIdx++) + for (size_t gcIdx = 0; gcIdx < activeCellInfo->reservoirCellCount(); gcIdx++) { size_t activeCellResultIndex = activeCellInfo->cellResultIndex(gcIdx); if (activeCellResultIndex != cvf::UNDEFINED_SIZE_T) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 3018d29dd4..f96e70bba3 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -287,8 +287,8 @@ bool RifReaderEclipseOutput::transferGeometry(const ecl_grid_type* mainEclGrid, totalCellCount += ecl_grid_get_global_size(localEclGrid); } - activeCellInfo->setGlobalCellCount(totalCellCount); - fractureActiveCellInfo->setGlobalCellCount(totalCellCount); + activeCellInfo->setReservoirCellCount(totalCellCount); + fractureActiveCellInfo->setReservoirCellCount(totalCellCount); // Reserve room for the cells and nodes and fill them with data @@ -570,8 +570,8 @@ bool RifReaderEclipseOutput::readActiveCellInfo() RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - activeCellInfo->setGlobalCellCount(globalCellCount); - fractureActiveCellInfo->setGlobalCellCount(globalCellCount); + activeCellInfo->setReservoirCellCount(globalCellCount); + fractureActiveCellInfo->setReservoirCellCount(globalCellCount); activeCellInfo->setGridCount(actnumKeywordCount); fractureActiveCellInfo->setGridCount(actnumKeywordCount); @@ -773,7 +773,7 @@ bool RifReaderEclipseOutput::staticResult(const QString& result, PorosityModelRe if (result.compare("ACTNUM", Qt::CaseInsensitive) == 0) { RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(matrixOrFracture); - values->resize(activeCellInfo->globalActiveCellCount(), 1.0); + values->resize(activeCellInfo->reservoirActiveCellCount(), 1.0); return true; } @@ -1551,7 +1551,7 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL if (matrixOrFracture == RifReaderInterface::FRACTURE_RESULTS) { - if (fractureActiveCellInfo->globalActiveCellCount() == 0) + if (fractureActiveCellInfo->reservoirActiveCellCount() == 0) { return QStringList(); } @@ -1564,16 +1564,16 @@ QStringList RifReaderEclipseOutput::validKeywordsForPorosityModel(const QStringL QString keyword = keywords[i]; size_t keywordDataCount = keywordDataItemCounts[i]; - if (activeCellInfo->globalActiveCellCount() > 0) + if (activeCellInfo->reservoirActiveCellCount() > 0) { - size_t timeStepsAllCells = keywordDataItemCounts[i] / activeCellInfo->globalCellCount(); - size_t timeStepsAllCellsRest = keywordDataItemCounts[i] % activeCellInfo->globalCellCount(); + size_t timeStepsAllCells = keywordDataItemCounts[i] / activeCellInfo->reservoirCellCount(); + size_t timeStepsAllCellsRest = keywordDataItemCounts[i] % activeCellInfo->reservoirCellCount(); - size_t timeStepsMatrix = keywordDataItemCounts[i] / activeCellInfo->globalActiveCellCount(); - size_t timeStepsMatrixRest = keywordDataItemCounts[i] % activeCellInfo->globalActiveCellCount(); + size_t timeStepsMatrix = keywordDataItemCounts[i] / activeCellInfo->reservoirActiveCellCount(); + size_t timeStepsMatrixRest = keywordDataItemCounts[i] % activeCellInfo->reservoirActiveCellCount(); - size_t timeStepsMatrixAndFracture = keywordDataItemCounts[i] / (activeCellInfo->globalActiveCellCount() + fractureActiveCellInfo->globalActiveCellCount()); - size_t timeStepsMatrixAndFractureRest = keywordDataItemCounts[i] % (activeCellInfo->globalActiveCellCount() + fractureActiveCellInfo->globalActiveCellCount()); + size_t timeStepsMatrixAndFracture = keywordDataItemCounts[i] / (activeCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount()); + size_t timeStepsMatrixAndFractureRest = keywordDataItemCounts[i] % (activeCellInfo->reservoirActiveCellCount() + fractureActiveCellInfo->reservoirActiveCellCount()); if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS) { @@ -1620,7 +1620,7 @@ void RifReaderEclipseOutput::extractResultValuesBasedOnPorosityModel(PorosityMod RigActiveCellInfo* fracActCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS && fracActCellInfo->globalActiveCellCount() == 0) + if (matrixOrFracture == RifReaderInterface::MATRIX_RESULTS && fracActCellInfo->reservoirActiveCellCount() == 0) { destinationResultValues->insert(destinationResultValues->end(), sourceResultValues.begin(), sourceResultValues.end()); } diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 752f4894f7..3bc4c76a18 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -117,8 +117,8 @@ void Rim3dOverlayInfoConfig::update3DInfo() { caseName = m_reservoirView->eclipseCase()->caseUserDescription(); totCellCount = QString::number(m_reservoirView->eclipseCase()->reservoirData()->mainGrid()->cells().size()); - size_t mxActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->globalActiveCellCount(); - size_t frActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount(); + size_t mxActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::MATRIX_RESULTS)->reservoirActiveCellCount(); + size_t frActCellCount = m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->reservoirActiveCellCount(); if (frActCellCount > 0) activeCellCountText += "Matrix : "; activeCellCountText += QString::number(mxActCellCount); if (frActCellCount > 0) activeCellCountText += " Fracture : " + QString::number(frActCellCount); diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 0ac3651308..1dec69908d 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -223,7 +223,7 @@ void RimIdenticalGridCaseGroup::loadMainCaseAndActiveCellInfo() //-------------------------------------------------------------------------------------------------- void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() { - if (m_unionOfMatrixActiveCells->globalActiveCellCount() > 0) + if (m_unionOfMatrixActiveCells->reservoirActiveCellCount() > 0) { return; } @@ -235,8 +235,8 @@ void RimIdenticalGridCaseGroup::computeUnionOfActiveCells() return; } - m_unionOfMatrixActiveCells->setGlobalCellCount(m_mainGrid->cells().size()); - m_unionOfFractureActiveCells->setGlobalCellCount(m_mainGrid->cells().size()); + m_unionOfMatrixActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); + m_unionOfFractureActiveCells->setReservoirCellCount(m_mainGrid->cells().size()); m_unionOfMatrixActiveCells->setGridCount(m_mainGrid->gridCount()); m_unionOfFractureActiveCells->setGridCount(m_mainGrid->gridCount()); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index b61801dc61..a15c100d9b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -345,7 +345,7 @@ void RimResultDefinition::updateFieldVisibility() m_reservoirView->eclipseCase()->reservoirData() && m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS) ) { - if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->globalActiveCellCount() == 0) + if (m_reservoirView->eclipseCase()->reservoirData()->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS)->reservoirActiveCellCount() == 0) { m_porosityModelUiField.setUiHidden(true); } diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 85f7c999e9..147db21832 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -103,7 +103,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result RimDefines::ResultCatType resultType = resultSpecification[i].m_resType; QString resultName = resultSpecification[i].m_resVarName; - size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->globalActiveCellCount(); + size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->reservoirActiveCellCount(); RigCaseCellResultsData* destCellResultsData = m_destinationCase->results(poroModel); // Special handling if SOIL is asked for @@ -172,7 +172,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result RimDefines::ResultCatType resultType = resultSpecification[resSpecIdx].m_resType; QString resultName = resultSpecification[resSpecIdx].m_resVarName; - size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->globalActiveCellCount(); + size_t activeCellCount = m_destinationCase->activeCellInfo(poroModel)->reservoirActiveCellCount(); if (activeCellCount == 0) continue; diff --git a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp index 57e99d4ec0..5252bbac88 100644 --- a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp +++ b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp @@ -32,7 +32,7 @@ TEST(RigActiveCellInfo, BasicTest) RigActiveCellInfo rigActiveCellInfo; size_t globalActiveCellCount = 10; - rigActiveCellInfo.setGlobalCellCount(globalActiveCellCount); + rigActiveCellInfo.setReservoirCellCount(globalActiveCellCount); for (size_t i = 0; i < globalActiveCellCount; i++) { @@ -57,7 +57,7 @@ TEST(RigActiveCellInfo, GridCellCounts) rigActiveCellInfo.setGridActiveCellCounts(2, 2); rigActiveCellInfo.computeDerivedData(); - EXPECT_TRUE(rigActiveCellInfo.globalActiveCellCount() == 3); + EXPECT_TRUE(rigActiveCellInfo.reservoirActiveCellCount() == 3); } { @@ -68,6 +68,6 @@ TEST(RigActiveCellInfo, GridCellCounts) rigActiveCellInfo.setGridActiveCellCounts(2, 5 ); rigActiveCellInfo.computeDerivedData(); - EXPECT_TRUE(rigActiveCellInfo.globalActiveCellCount() == 12); + EXPECT_TRUE(rigActiveCellInfo.reservoirActiveCellCount() == 12); } } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index 7e9c07b5a3..0013a2da44 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -34,7 +34,7 @@ RigActiveCellInfo::RigActiveCellInfo() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setGlobalCellCount(size_t globalCellCount) +void RigActiveCellInfo::setReservoirCellCount(size_t globalCellCount) { m_cellIndexToResultIndex.resize(globalCellCount, cvf::UNDEFINED_SIZE_T); } @@ -42,7 +42,7 @@ void RigActiveCellInfo::setGlobalCellCount(size_t globalCellCount) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalCellCount() const +size_t RigActiveCellInfo::reservoirCellCount() const { return m_cellIndexToResultIndex.size(); } @@ -50,7 +50,7 @@ size_t RigActiveCellInfo::globalCellCount() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalCellResultCount() const +size_t RigActiveCellInfo::reservoirCellResultCount() const { return m_globalCellResultCount; } @@ -134,7 +134,7 @@ void RigActiveCellInfo::computeDerivedData() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RigActiveCellInfo::globalActiveCellCount() const +size_t RigActiveCellInfo::reservoirActiveCellCount() const { return m_globalActiveCellCount; } diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index 562d4e1074..a1118f1d54 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -32,10 +32,10 @@ class RigActiveCellInfo : public cvf::Object public: RigActiveCellInfo(); - void setGlobalCellCount(size_t globalCellCount); - size_t globalCellCount() const; - size_t globalActiveCellCount() const; - size_t globalCellResultCount() const; + void setReservoirCellCount(size_t globalCellCount); + size_t reservoirCellCount() const; + size_t reservoirActiveCellCount() const; + size_t reservoirCellResultCount() const; bool isCoarseningActive() const; bool isActive(size_t reservoirCellIndex) const; diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index ec981ebc21..bca46da76c 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -247,7 +247,7 @@ void RigReservoirBuilderMock::populateReservoir(RigCaseData* eclipseCase) // Set all cells active RigActiveCellInfo* activeCellInfo = eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); - activeCellInfo->setGlobalCellCount(eclipseCase->mainGrid()->cells().size()); + activeCellInfo->setReservoirCellCount(eclipseCase->mainGrid()->cells().size()); for (size_t i = 0; i < eclipseCase->mainGrid()->cells().size(); i++) { activeCellInfo->setCellResultIndex(i, i); diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index a10762e2a6..f80a0c54b7 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -158,7 +158,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } RigActiveCellInfo* actCellInfo = reservoirCase->reservoirData()->activeCellInfo(porosityModel); - size_t numMatrixModelActiveCells = actCellInfo->globalActiveCellCount(); + size_t numMatrixModelActiveCells = actCellInfo->reservoirActiveCellCount(); gridNumber.reserve(numMatrixModelActiveCells); cellI.reserve(numMatrixModelActiveCells); diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index 7a07f09d4a..d7784f1997 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -152,7 +152,7 @@ class RiaGetActiveCellCenters : public RiaSocketCommand RigActiveCellInfo* actCellInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); RigMainGrid* mainGrid = rimCase->reservoirData()->mainGrid(); - size_t activeCellCount = actCellInfo->globalActiveCellCount(); + size_t activeCellCount = actCellInfo->reservoirActiveCellCount(); size_t doubleValueCount = activeCellCount * 3; socketStream << (quint64)activeCellCount; @@ -321,7 +321,7 @@ class RiaGetActiveCellCorners : public RiaSocketCommand RigActiveCellInfo* actCellInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); RigMainGrid* mainGrid = rimCase->reservoirData()->mainGrid(); - size_t activeCellCount = actCellInfo->globalActiveCellCount(); + size_t activeCellCount = actCellInfo->reservoirActiveCellCount(); size_t doubleValueCount = activeCellCount * 3 * 8; socketStream << (quint64)activeCellCount; diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 101f9edcea..fa98846c15 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -138,7 +138,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand // then the byte-size of the result values in one timestep const RigActiveCellInfo* activeInfo = rimCase->reservoirData()->activeCellInfo(porosityModelEnum); - size_t timestepResultCount = activeInfo->globalActiveCellCount(); + size_t timestepResultCount = activeInfo->reservoirActiveCellCount(); quint64 timestepByteCount = (quint64)(timestepResultCount*sizeof(double)); socketStream << timestepByteCount ; @@ -148,7 +148,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand std::vector values(valueCount); size_t valueIndex = 0; - size_t globalCellCount = activeInfo->globalCellCount(); + size_t globalCellCount = activeInfo->reservoirCellCount(); for (size_t tIdx = 0; tIdx < requestedTimesteps.size(); ++tIdx) { std::vector& doubleValues = scalarResultFrames->at(requestedTimesteps[tIdx]); @@ -159,7 +159,7 @@ class RiaGetActiveCellProperty: public RiaSocketCommand if (resultIdx < doubleValues.size()) { - if (doubleValues.size() == activeInfo->globalCellCount()) + if (doubleValues.size() == activeInfo->reservoirCellCount()) { // When reading data from input text files, result data is read for all grid cells // Read out values from data vector using global cell index instead of active cell result index @@ -528,9 +528,9 @@ class RiaSetActiveCellProperty: public RiaSocketCommand RigActiveCellInfo* activeCellInfo = m_currentReservoir->reservoirData()->activeCellInfo(m_porosityModelEnum); - size_t globalActiveCellCount = activeCellInfo->globalActiveCellCount(); - size_t totalCellCount = activeCellInfo->globalCellCount(); - size_t globalCellResultCount = activeCellInfo->globalCellResultCount(); + size_t globalActiveCellCount = activeCellInfo->reservoirActiveCellCount(); + size_t totalCellCount = activeCellInfo->reservoirCellCount(); + size_t globalCellResultCount = activeCellInfo->reservoirCellResultCount(); bool isCoarseningActive = globalCellResultCount != globalActiveCellCount; From 09313c6caa4e5c58fea54205ad2502d8374a3510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:45:52 +0200 Subject: [PATCH 208/346] More Rename of globalCell to reservoirCell --- .../FileInterface/RifReaderEclipseOutput.cpp | 10 +++---- .../RimStatisticsCaseEvaluator.cpp | 6 ++-- .../RimStatisticsCaseEvaluator.h | 2 +- .../ReservoirDataModel/RigActiveCellInfo.cpp | 30 +++++++++---------- .../ReservoirDataModel/RigActiveCellInfo.h | 6 ++-- ApplicationCode/ReservoirDataModel/RigFault.h | 6 ++-- .../SocketInterface/RiaCaseInfoCommands.cpp | 12 ++++---- .../RiaPropertyDataCommands.cpp | 16 +++++----- 8 files changed, 44 insertions(+), 44 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index f96e70bba3..48b56da2ae 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -553,16 +553,16 @@ bool RifReaderEclipseOutput::readActiveCellInfo() std::vector > actnumValuesPerGrid; actnumValuesPerGrid.resize(actnumKeywordCount); - size_t globalCellCount = 0; + size_t reservoirCellCount = 0; for (size_t gridIdx = 0; gridIdx < static_cast(actnumKeywordCount); gridIdx++) { RifEclipseOutputFileTools::keywordData(ecl_file, ACTNUM_KW, gridIdx, &actnumValuesPerGrid[gridIdx]); - globalCellCount += actnumValuesPerGrid[gridIdx].size(); + reservoirCellCount += actnumValuesPerGrid[gridIdx].size(); } // Check if number of cells is matching - if (m_eclipseCase->mainGrid()->cells().size() != globalCellCount) + if (m_eclipseCase->mainGrid()->cells().size() != reservoirCellCount) { return false; } @@ -570,8 +570,8 @@ bool RifReaderEclipseOutput::readActiveCellInfo() RigActiveCellInfo* activeCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::MATRIX_RESULTS); RigActiveCellInfo* fractureActiveCellInfo = m_eclipseCase->activeCellInfo(RifReaderInterface::FRACTURE_RESULTS); - activeCellInfo->setReservoirCellCount(globalCellCount); - fractureActiveCellInfo->setReservoirCellCount(globalCellCount); + activeCellInfo->setReservoirCellCount(reservoirCellCount); + fractureActiveCellInfo->setReservoirCellCount(reservoirCellCount); activeCellInfo->setGridCount(actnumKeywordCount); fractureActiveCellInfo->setGridCount(actnumKeywordCount); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 147db21832..0225d62e56 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -352,7 +352,7 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); if (resultAccessor.isNull()) return; - for (size_t cellIdx = 0; cellIdx < m_globalCellCount; cellIdx++) + for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) { qDebug() << resultAccessor->cellScalar(cellIdx); } @@ -365,12 +365,12 @@ RimStatisticsCaseEvaluator::RimStatisticsCaseEvaluator(const std::vector 0) { - m_globalCellCount = sourceCases[0]->reservoirData()->mainGrid()->cells().size(); + m_reservoirCellCount = sourceCases[0]->reservoirData()->mainGrid()->cells().size(); } CVF_ASSERT(m_destinationCase); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 6e3392ef7a..87b21c7aae 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -85,7 +85,7 @@ class RimStatisticsCaseEvaluator std::vector m_sourceCases; std::vector m_timeStepIndices; - size_t m_globalCellCount; + size_t m_reservoirCellCount; RimStatisticsConfig m_statisticsConfig; RigCaseData* m_destinationCase; }; diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index 0013a2da44..2c631b2d16 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -23,8 +23,8 @@ /// //-------------------------------------------------------------------------------------------------- RigActiveCellInfo::RigActiveCellInfo() - : m_globalActiveCellCount(0), - m_globalCellResultCount(0), + : m_reservoirActiveCellCount(0), + m_reservoirCellResultCount(0), m_activeCellPositionMin(cvf::Vec3d::ZERO), m_activeCellPositionMax(cvf::Vec3d::ZERO) { @@ -34,9 +34,9 @@ RigActiveCellInfo::RigActiveCellInfo() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setReservoirCellCount(size_t globalCellCount) +void RigActiveCellInfo::setReservoirCellCount(size_t reservoirCellCount) { - m_cellIndexToResultIndex.resize(globalCellCount, cvf::UNDEFINED_SIZE_T); + m_cellIndexToResultIndex.resize(reservoirCellCount, cvf::UNDEFINED_SIZE_T); } //-------------------------------------------------------------------------------------------------- @@ -52,7 +52,7 @@ size_t RigActiveCellInfo::reservoirCellCount() const //-------------------------------------------------------------------------------------------------- size_t RigActiveCellInfo::reservoirCellResultCount() const { - return m_globalCellResultCount; + return m_reservoirCellResultCount; } //-------------------------------------------------------------------------------------------------- @@ -88,15 +88,15 @@ size_t RigActiveCellInfo::cellResultIndex(size_t reservoirCellIndex) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t globalCellResultIndex) +void RigActiveCellInfo::setCellResultIndex(size_t reservoirCellIndex, size_t reservoirCellResultIndex) { - CVF_TIGHT_ASSERT(globalCellResultIndex < m_cellIndexToResultIndex.size()); + CVF_TIGHT_ASSERT(reservoirCellResultIndex < m_cellIndexToResultIndex.size()); - m_cellIndexToResultIndex[reservoirCellIndex] = globalCellResultIndex; + m_cellIndexToResultIndex[reservoirCellIndex] = reservoirCellResultIndex; - if (globalCellResultIndex >= m_globalCellResultCount) + if (reservoirCellResultIndex >= m_reservoirCellResultCount) { - m_globalCellResultCount = globalCellResultIndex + 1; + m_reservoirCellResultCount = reservoirCellResultIndex + 1; } } @@ -123,11 +123,11 @@ void RigActiveCellInfo::setGridActiveCellCounts(size_t gridIndex, size_t activeC //-------------------------------------------------------------------------------------------------- void RigActiveCellInfo::computeDerivedData() { - m_globalActiveCellCount = 0; + m_reservoirActiveCellCount = 0; for (size_t i = 0; i < m_perGridActiveCellInfo.size(); i++) { - m_globalActiveCellCount += m_perGridActiveCellInfo[i].activeCellCount(); + m_reservoirActiveCellCount += m_perGridActiveCellInfo[i].activeCellCount(); } } @@ -136,7 +136,7 @@ void RigActiveCellInfo::computeDerivedData() //-------------------------------------------------------------------------------------------------- size_t RigActiveCellInfo::reservoirActiveCellCount() const { - return m_globalActiveCellCount; + return m_reservoirActiveCellCount; } //-------------------------------------------------------------------------------------------------- @@ -187,7 +187,7 @@ void RigActiveCellInfo::clear() { m_perGridActiveCellInfo.clear(); m_cellIndexToResultIndex.clear(); - m_globalActiveCellCount = 0; + m_reservoirActiveCellCount = 0; m_activeCellPositionMin = cvf::Vec3st(0,0,0); m_activeCellPositionMax = cvf::Vec3st(0,0,0); m_activeCellsBoundingBox.reset(); @@ -198,7 +198,7 @@ void RigActiveCellInfo::clear() //-------------------------------------------------------------------------------------------------- bool RigActiveCellInfo::isCoarseningActive() const { - return m_globalCellResultCount != m_globalActiveCellCount; + return m_reservoirCellResultCount != m_reservoirActiveCellCount; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index a1118f1d54..8002f5bbb7 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -32,7 +32,7 @@ class RigActiveCellInfo : public cvf::Object public: RigActiveCellInfo(); - void setReservoirCellCount(size_t globalCellCount); + void setReservoirCellCount(size_t reservoirCellCount); size_t reservoirCellCount() const; size_t reservoirActiveCellCount() const; size_t reservoirCellResultCount() const; @@ -72,8 +72,8 @@ class RigActiveCellInfo : public cvf::Object std::vector m_cellIndexToResultIndex; - size_t m_globalActiveCellCount; - size_t m_globalCellResultCount; + size_t m_reservoirActiveCellCount; + size_t m_reservoirCellResultCount; cvf::Vec3st m_activeCellPositionMin; cvf::Vec3st m_activeCellPositionMax; diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index b4a31c9ad3..0d310bce35 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -38,12 +38,12 @@ class RigFaultsPrCellAccumulator : public cvf::Object enum { NO_FAULT = -1, UNKNOWN_FAULT = -2 }; public: - RigFaultsPrCellAccumulator(size_t globalCellCount) + RigFaultsPrCellAccumulator(size_t reservoirCellCount) { const int initVals[6] = { NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT}; caf::IntArray6 initVal; initVal = initVals; - m_faultIdxForCellFace.resize(globalCellCount, initVal); + m_faultIdxForCellFace.resize(reservoirCellCount, initVal); } inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) @@ -95,7 +95,7 @@ class RigFault : public cvf::Object const std::vector& connectionIndices() const { return m_connectionIndices; } static RigFaultsPrCellAccumulator* faultsPrCellAccumulator() { CVF_ASSERT(m_faultsPrCellAcc.notNull()); return m_faultsPrCellAcc.p();} - static void initFaultsPrCellAccumulator(size_t globalCellCount) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(globalCellCount); } + static void initFaultsPrCellAccumulator(size_t reservoirCellCount) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(reservoirCellCount); } private: QString m_name; diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index f80a0c54b7..793cebdc1c 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -170,7 +170,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand hostCellK.reserve(numMatrixModelActiveCells); globalCoarseningBoxIdx.reserve(numMatrixModelActiveCells); - const std::vector& globalCells = reservoirCase->reservoirData()->mainGrid()->cells(); + const std::vector& reservoirCells = reservoirCase->reservoirData()->mainGrid()->cells(); std::vector globalCoarseningBoxIndexStart; @@ -190,13 +190,13 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } - for (size_t cIdx = 0; cIdx < globalCells.size(); ++cIdx) + for (size_t cIdx = 0; cIdx < reservoirCells.size(); ++cIdx) { if (actCellInfo->isActive(cIdx)) { - RigGridBase* grid = globalCells[cIdx].hostGrid(); + RigGridBase* grid = reservoirCells[cIdx].hostGrid(); CVF_ASSERT(grid != NULL); - size_t cellIndex = globalCells[cIdx].cellIndex(); + size_t cellIndex = reservoirCells[cIdx].cellIndex(); size_t i, j, k; grid->ijkFromCellIndex(cellIndex, &i, &j, &k); @@ -213,7 +213,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand } else { - size_t parentCellIdx = globalCells[cIdx].parentCellIndex(); + size_t parentCellIdx = reservoirCells[cIdx].parentCellIndex(); parentGrid = (static_cast(grid))->parentGrid(); CVF_ASSERT(parentGrid != NULL); parentGrid->ijkFromCellIndex(parentCellIdx, &pi, &pj, &pk); @@ -229,7 +229,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand hostCellJ.push_back(static_cast(pj + 1)); // NB: 1-based index in Octave hostCellK.push_back(static_cast(pk + 1)); // NB: 1-based index in Octave - size_t coarseningIdx = globalCells[cIdx].coarseningBoxIndex(); + size_t coarseningIdx = reservoirCells[cIdx].coarseningBoxIndex(); if (coarseningIdx != cvf::UNDEFINED_SIZE_T) { size_t globalCoarseningIdx = globalCoarseningBoxIndexStart[grid->gridIndex()] + coarseningIdx; diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index fa98846c15..9edfad2c82 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -148,11 +148,11 @@ class RiaGetActiveCellProperty: public RiaSocketCommand std::vector values(valueCount); size_t valueIndex = 0; - size_t globalCellCount = activeInfo->reservoirCellCount(); + size_t reservoirCellCount = activeInfo->reservoirCellCount(); for (size_t tIdx = 0; tIdx < requestedTimesteps.size(); ++tIdx) { std::vector& doubleValues = scalarResultFrames->at(requestedTimesteps[tIdx]); - for (size_t gcIdx = 0; gcIdx < globalCellCount; ++gcIdx) + for (size_t gcIdx = 0; gcIdx < reservoirCellCount; ++gcIdx) { size_t resultIdx = activeInfo->cellResultIndex(gcIdx); if (resultIdx == cvf::UNDEFINED_SIZE_T) continue; @@ -528,18 +528,18 @@ class RiaSetActiveCellProperty: public RiaSocketCommand RigActiveCellInfo* activeCellInfo = m_currentReservoir->reservoirData()->activeCellInfo(m_porosityModelEnum); - size_t globalActiveCellCount = activeCellInfo->reservoirActiveCellCount(); + size_t activeCellCountReservoir = activeCellInfo->reservoirActiveCellCount(); size_t totalCellCount = activeCellInfo->reservoirCellCount(); - size_t globalCellResultCount = activeCellInfo->reservoirCellResultCount(); + size_t reservoirCellResultCount = activeCellInfo->reservoirCellResultCount(); - bool isCoarseningActive = globalCellResultCount != globalActiveCellCount; + bool isCoarseningActive = reservoirCellResultCount != activeCellCountReservoir; - if (cellCountFromOctave != globalActiveCellCount ) + if (cellCountFromOctave != activeCellCountReservoir ) { server->errorMessageDialog()->showMessage(RiaSocketServer::tr("ResInsight SocketServer: \n") + RiaSocketServer::tr("The number of cells in the data coming from octave does not match the case") + ":\"" + m_currentReservoir->caseUserDescription() + "\"\n" " Octave: " + QString::number(cellCountFromOctave) + "\n" - " " + m_currentReservoir->caseUserDescription() + ": Active cell count: " + QString::number(globalActiveCellCount) + " Total cell count: " + QString::number(totalCellCount)) ; + " " + m_currentReservoir->caseUserDescription() + ": Active cell count: " + QString::number(activeCellCountReservoir) + " Total cell count: " + QString::number(totalCellCount)) ; cellCountFromOctave = 0; m_invalidActiveCellCountDetected = true; @@ -554,7 +554,7 @@ class RiaSetActiveCellProperty: public RiaSocketCommand for (size_t tIdx = 0; tIdx < m_timeStepCountToRead; ++tIdx) { size_t tsId = m_requestedTimesteps[tIdx]; - m_scalarResultsToAdd->at(tsId).resize(globalCellResultCount, HUGE_VAL); + m_scalarResultsToAdd->at(tsId).resize(reservoirCellResultCount, HUGE_VAL); } std::vector readBuffer; From e1b67b15e0215eae48aefea2fb8d7bd451f0b31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 10:51:39 +0200 Subject: [PATCH 209/346] Rename of GlobalCell to ReservoirCell --- .../RivFaultGeometryGenerator.cpp | 4 ++-- .../ReservoirDataModel/RigFault.cpp | 6 +++--- ApplicationCode/ReservoirDataModel/RigFault.h | 10 +++++----- .../ReservoirDataModel/RigMainGrid.cpp | 20 +++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index a45a4dad3e..a0ef33d344 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -163,12 +163,12 @@ void RivFaultGeometryGenerator::computeArrays() #pragma omp parallel for for (int fIdx = 0; fIdx < static_cast(faultFaces.size()); fIdx++) { - size_t cellIndex = faultFaces[fIdx].m_nativeGlobalCellIndex; + size_t cellIndex = faultFaces[fIdx].m_nativeReservoirCellIndex; cvf::StructGridInterface::FaceType face = faultFaces[fIdx].m_nativeFace; if (!m_computeNativeFaultFaces) { - cellIndex = faultFaces[fIdx].m_oppositeGlobalCellIndex; + cellIndex = faultFaces[fIdx].m_oppositeReservoirCellIndex; face = cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace); } diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 0db6f08c90..82e5c35eb3 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -145,10 +145,10 @@ void RigFault::accumulateFaultsPrCell(RigFaultsPrCellAccumulator* faultsPrCellA { const FaultFace& ff = m_faultFaces[ffIdx]; - // Could detect overlapping faults here .... if (faultsPrCellAcc->faultIdx(ff.m_nativeGlobalCellIndex, ff.m_nativeFace) >= 0) + // Could detect overlapping faults here .... if (faultsPrCellAcc->faultIdx(ff.m_nativeReservoirCellIndex, ff.m_nativeFace) >= 0) - faultsPrCellAcc->setFaultIdx(ff.m_nativeGlobalCellIndex, ff.m_nativeFace, faultIdx); - faultsPrCellAcc->setFaultIdx(ff.m_oppositeGlobalCellIndex, cvf::StructGridInterface::oppositeFace(ff.m_nativeFace), faultIdx); + faultsPrCellAcc->setFaultIdx(ff.m_nativeReservoirCellIndex, ff.m_nativeFace, faultIdx); + faultsPrCellAcc->setFaultIdx(ff.m_oppositeReservoirCellIndex, cvf::StructGridInterface::oppositeFace(ff.m_nativeFace), faultIdx); } } diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 0d310bce35..44d232bd7d 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -66,15 +66,15 @@ class RigFault : public cvf::Object struct FaultFace { - FaultFace(size_t nativeGlobalCellIndex, cvf::StructGridInterface::FaceType nativeFace, size_t oppositeGlobalCellIndex) : - m_nativeGlobalCellIndex(nativeGlobalCellIndex), + FaultFace(size_t nativeReservoirCellIndex, cvf::StructGridInterface::FaceType nativeFace, size_t oppositeReservoirCellIndex) : + m_nativeReservoirCellIndex(nativeReservoirCellIndex), m_nativeFace(nativeFace), - m_oppositeGlobalCellIndex(oppositeGlobalCellIndex) + m_oppositeReservoirCellIndex(oppositeReservoirCellIndex) { } - size_t m_nativeGlobalCellIndex; + size_t m_nativeReservoirCellIndex; cvf::StructGridInterface::FaceType m_nativeFace; - size_t m_oppositeGlobalCellIndex; + size_t m_oppositeReservoirCellIndex; }; public: diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index dc58bf21c3..21a8645632 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -234,7 +234,7 @@ void RigMainGrid::calculateFaults() continue; } - size_t neighborGlobalCellIdx; + size_t neighborReservoirCellIdx; size_t neighborGridCellIdx; size_t i, j, k; RigGridBase* hostGrid = NULL; @@ -259,8 +259,8 @@ void RigMainGrid::calculateFaults() continue; } - neighborGlobalCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); - if (m_cells[neighborGlobalCellIdx].isInvalid()) + neighborReservoirCellIdx = hostGrid->reservoirCellIndex(neighborGridCellIdx); + if (m_cells[neighborReservoirCellIdx].isInvalid()) { continue; } @@ -271,7 +271,7 @@ void RigMainGrid::calculateFaults() caf::SizeTArray4 faceIdxs; m_cells[gcIdx].faceIndices(face, &faceIdxs); caf::SizeTArray4 nbFaceIdxs; - m_cells[neighborGlobalCellIdx].faceIndices(StructGridInterface::oppositeFace(face), &nbFaceIdxs); + m_cells[neighborReservoirCellIdx].faceIndices(StructGridInterface::oppositeFace(face), &nbFaceIdxs); const std::vector& vxs = m_mainGrid->nodes(); @@ -289,17 +289,17 @@ void RigMainGrid::calculateFaults() // To avoid doing this calculation for the opposite face faultsPrCellAcc->setFaultIdx(gcIdx, face, unNamedFaultIdx); - faultsPrCellAcc->setFaultIdx(neighborGlobalCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); + faultsPrCellAcc->setFaultIdx(neighborReservoirCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); //m_cells[gcIdx].setCellFaceFault(face); - //m_cells[neighborGlobalCellIdx].setCellFaceFault(StructGridInterface::oppositeFace(face)); + //m_cells[neighborReservoirCellIdx].setCellFaceFault(StructGridInterface::oppositeFace(face)); // Add as fault face only if the grid index is less than the neighbors - if (static_cast(gcIdx) < neighborGlobalCellIdx) + if (static_cast(gcIdx) < neighborReservoirCellIdx) { { - RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborGlobalCellIdx); + RigFault::FaultFace ff(gcIdx, cvf::StructGridInterface::FaceType(faceIdx), neighborReservoirCellIdx); unNamedFault->faultFaces().push_back(ff); } @@ -382,7 +382,7 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, for (size_t fIdx = 0; fIdx < faultFaces.size(); fIdx++) { - if (faultFaces[fIdx].m_nativeGlobalCellIndex == cellIndex) + if (faultFaces[fIdx].m_nativeReservoirCellIndex == cellIndex) { if (face == faultFaces[fIdx].m_nativeFace ) { @@ -390,7 +390,7 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, } } - if (faultFaces[fIdx].m_oppositeGlobalCellIndex == cellIndex) + if (faultFaces[fIdx].m_oppositeReservoirCellIndex == cellIndex) { if (face == cvf::StructGridInterface::oppositeFace(faultFaces[fIdx].m_nativeFace)) { From 33ab16f7d78b07388956f639a3a2209d3de46d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:07:05 +0200 Subject: [PATCH 210/346] New classes for the generalized texturing --- .../RivResultToTextureMapper.h | 64 +++++++++++++ .../RivTextureCoordsCreator.cpp | 89 +++++++++++++++++++ .../RivTextureCoordsCreator.h | 62 +++++++++++++ .../RigPipeInCellEvaluator.h | 52 +++++++++++ 4 files changed, 267 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/RivResultToTextureMapper.h create mode 100644 ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h create mode 100644 ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h diff --git a/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h new file mode 100644 index 0000000000..06dff66b72 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigPipeInCellEvaluator.h" + +#include "cvfVector2.h" +#include "cvfScalarMapper.h" +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" + +#include + +class RivResultToTextureMapper : public cvf::Object +{ +public: + RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, + const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + cvf::Vec2f getTexCoord(double resultValue, size_t cellIndex) const + { + cvf::Vec2f texCoord(0,0); + + if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's + { + texCoord[1] = 1.0f; + return texCoord; + } + + texCoord = m_scalarMapper->mapToTextureCoord(resultValue); + + if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) + { + texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture + } + + return texCoord; + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp new file mode 100644 index 0000000000..59163d5fdb --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -0,0 +1,89 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTextureCoordsCreator.h" + +#include "RimResultSlot.h" +#include "RigCaseData.h" +#include "RimReservoirView.h" +#include "RimCase.h" +#include "RigCaseCellResultsData.h" +#include "RigResultAccessorFactory.h" +#include "RigPipeInCellEvaluator.h" +#include "RivResultToTextureMapper.h" +#include "RimWellCollection.h" +#include "RigResultAccessor.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, size_t timeStepIndex, size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + m_quadMapper = quadMapper; + CVF_ASSERT(quadMapper && eclipseCase ); + + size_t resTimeStepIdx = timeStepIndex; + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + CVF_ASSERT(m_resultAccessor.notNull()); + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(gridIndex)); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + + m_texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); + CVF_ASSERT(m_texMapper.notNull()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords, const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper) +{ + CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); + + size_t numVertices = quadMapper->quadCount()*4; + quadTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = quadTextureCoords->ptr(); + + double resultValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, resultValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + resultValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(resultValue, cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } +} diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h new file mode 100644 index 0000000000..c08d647b0a --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RimResultSlot; +class RigResultAccessor; +class RivResultToTextureMapper; + +namespace cvf{ +class StructGridQuadToCellFaceMapper; + +} + + +class RivTextureCoordsCreator +{ +public: + RivTextureCoordsCreator(RimResultSlot* cellResultSlot, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) + { + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); + } + +private: + + static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigResultAccessor* resultAccessor, + const RivResultToTextureMapper* texMapper); + + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; +}; + + + + diff --git a/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h new file mode 100644 index 0000000000..5a65f69475 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RigPipeInCellEvaluator: public cvf::Object +{ +public: + RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, + const cvf::UIntArray* gridCellToWellIndexMap) + : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), + m_gridCellToWellIndexMap(gridCellToWellIndexMap) + { + } + + bool isWellPipeInCell( size_t cellIndex) const + { + cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); + + if (wellIndex == cvf::UNDEFINED_UINT) + { + return false; + } + + return m_isWellPipeVisibleForWellIndex[wellIndex]; + } + +private: + + const std::vector& m_isWellPipeVisibleForWellIndex; + const cvf::UIntArray* m_gridCellToWellIndexMap; +}; From 38d2000e29d68e3a3a2844d02aa7c79fbeac3f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:08:11 +0200 Subject: [PATCH 211/346] Wip: New generalized texturing in play Only on GridParts --- .../ModelVisualization/CMakeLists_files.cmake | 3 + .../ModelVisualization/RivGridPartMgr.cpp | 97 ++++++++++- .../ReservoirDataModel/CMakeLists_files.cmake | 1 + .../ReservoirDataModel/RigResultAccessor.h | 153 +----------------- .../RigResultAccessorFactory.cpp | 10 +- 5 files changed, 103 insertions(+), 161 deletions(-) diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 02509f21c9..9ca5bb10e4 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -22,6 +22,8 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h +${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h +${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -42,6 +44,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp +${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 47fe6765b8..9a018b8ed4 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -50,6 +50,11 @@ #include "RimWellCollection.h" #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" +#include "cvfStructGridGeometryGenerator.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RivResultToTextureMapper.h" +#include "RivTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -207,7 +212,7 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) m_surfaceGridLines->setEffect(eff.p()); } } - +#if 0 //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -275,6 +280,96 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } } } +#endif +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) +{ + CVF_ASSERT(cellResultSlot); + + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + cvf::ref surfaceFacesColorArray; + + // Outer surface + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { + surfaceFacesColorArray = new cvf::Color3ubArray; + + RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); + /* + // If the result is static, only read that. + size_t resTimeStepIdx = timeStepIndex; + const cvf::StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, m_grid->gridIndex(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); + + if (resultAccessor.isNull()) return; + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(m_grid->gridIndex())); + + cvf::ref texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); + + + + size_t numVertices = quadMapper->quadCount()*4; + m_surfaceFacesTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); + + double cellScalarValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, cellScalarValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + cellScalarValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(cellScalarValue, cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } + */ + } + + + if (surfaceFacesColorArray.notNull()) // Ternary result + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + dg->setColorArray(surfaceFacesColorArray.p()); + } + + cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); + m_surfaceFaces->setEffect(perVertexColorEffect.p()); + + m_surfaceFaces->setPriority(100); + } + else + { + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); + } + } +} //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 950bbb3f0d..4a23c7302f 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -29,6 +29,7 @@ ${CEE_CURRENT_LIST_DIR}RigFault.h ${CEE_CURRENT_LIST_DIR}RigNNCData.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.inl +${CEE_CURRENT_LIST_DIR}RigPipeInCellEvaluator.h ) set (SOURCE_GROUP_SOURCE_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index 1113695e22..dc248b7c73 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -87,156 +87,5 @@ class RivTernaryScalarMapper : public cvf::Object float m_opacityLevel; }; -class RigPipeInCellEvaluator: public cvf::Object -{ -public: - RigPipeInCellEvaluator(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap) - : m_isWellPipeVisibleForWellIndex(isWellPipeVisibleForWellIndex), - m_gridCellToWellIndexMap(gridCellToWellIndexMap) - { - } - - bool isWellPipeInCell( size_t cellIndex) - { - cvf::uint wellIndex = m_gridCellToWellIndexMap->get(cellIndex); - - if (wellIndex == cvf::UNDEFINED_UINT) - { - return false; - } - - return m_isWellPipeVisibleForWellIndex[wellIndex]; - } - -private: - - const std::vector& m_isWellPipeVisibleForWellIndex; - const cvf::UIntArray* m_gridCellToWellIndexMap; -}; - -class RivResultToTextureMapper : public cvf::Object -{ - - RivResultToTextureMapper(const cvf::ScalarMapper* scalarMapper, - const RigPipeInCellEvaluator* pipeInCellEvaluator) - : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) - {} - - Vec2f getTexCoord(double resultValue, size_t cellIndex) - { - Vec2f texCoord(0,0); - - if (resultValue == HUGE_VAL || resultValue != resultValue) // a != a is true for NAN's - { - texCoord[1] = 1.0f; - return texCoord; - } - - texCoord = m_scalarMapper->mapToTexCoord(resultValue); - - if (!m_pipeInCellEvaluator->isWellPipeInCell(cellIndex)) - { - texCoord[1] = 0; // Set the Y texture coordinate to the opaque line in the texture - } - - return texCoord; - } - -private: - cvf::cref m_scalarMapper; - cvf::cref m_pipeInCellEvaluator; -}; - - - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) -{ - CVF_ASSERT(cellResultSlot); - - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - - cvf::ref surfaceFacesColorArray; - - // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); - } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); - } - else - { - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = RigResultAccessObjectFactory::createResultAccessObject(eclipseCase, m_grid->gridIdx(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - - if (resultAccessor.isNull()) return; - - RivResultToTextureMapper texMapper(mapper, - RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()))); - - const StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); - - size_t numVertices = quadMapper->quadCount()*4; - m_surfaceFacesTextureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) - { - StructGridInterface::FaceType faceId = m_quadMapper->cellFace(i); - - cellScalarValue = resultAccessor->cellFaceScalar(m_quadMapper->cellIndex(i), faceId); - - texCoord = texMapper->mapToTextureCoord(cellScalarValue); - - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[i*4 + j] = texCoord; - } - } - } - - - if (surfaceFacesColorArray.notNull()) // Ternary result - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } - } -} #endif diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index d44ffc0dfb..de23da6f87 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -107,12 +107,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa RigGridBase* grid = eclipseCase->grid(gridIndex); - // Ternary - if (uiResultName == RimDefines::ternarySaturationResultName()) - { - return NULL; - } - else if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + if (uiResultName == RimDefines::combinedTransmissibilityResultName()) { cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); @@ -125,8 +120,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } - - return NULL; + return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From 419ad87cebff77fbf1548979eb3203af87ad6e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 8 Aug 2014 16:44:21 +0200 Subject: [PATCH 212/346] Used new texturing on faults --- .../ModelVisualization/RivFaultPartMgr.cpp | 85 ++-------- .../ModelVisualization/RivGridPartMgr.cpp | 146 +----------------- .../ModelVisualization/RivGridPartMgr.h | 4 - 3 files changed, 19 insertions(+), 216 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 2d261dfc0c..47195d7d3b 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -32,6 +32,8 @@ #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigResultAccessor.h" + #include "RimCase.h" #include "RimWellCollection.h" #include "cafPdmFieldCvfMat4d.h" @@ -48,8 +50,9 @@ #include "cvfRenderStateDepth.h" #include "RivSourceInfo.h" #include "RimFaultCollection.h" +#include "RivTextureCoordsCreator.h" - +#include "RivResultToTextureMapper.h" @@ -130,45 +133,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_nativeFaultFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, - m_nativeFaultGenerator->cellFromQuadMapper()); - } else { - if (resultAccessor.isNull()) - { - return; - } - m_nativeFaultGenerator->textureCoordinates(m_nativeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); - - } - - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_nativeFaultGenerator->cellFromQuadMapper(); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_nativeFaultGenerator->cellFromQuadMapper()); - for(size_t i = 0; i < m_nativeFaultFacesTextureCoords->size(); ++i) - { - if ((*m_nativeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_nativeFaultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); } cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); @@ -204,43 +176,14 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_oppositeFaultFacesTextureCoords.p(); - - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_oppositeFaultGenerator->cellFromQuadMapper()); - } else { - if (resultAccessor.isNull()) - { - return; - } - - m_oppositeFaultGenerator->textureCoordinates(m_oppositeFaultFacesTextureCoords.p(), resultAccessor.p(), mapper); - } - - if (m_opacityLevel < 1.0f ) - { - const std::vector& isWellPipeVisible = cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex); - cvf::ref gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(m_grid->gridIndex()); - const cvf::StructGridQuadToCellFaceMapper* quadsToGridCells = m_oppositeFaultGenerator->cellFromQuadMapper(); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); - for(size_t i = 0; i < m_oppositeFaultFacesTextureCoords->size(); ++i) - { - if ((*m_oppositeFaultFacesTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToGridCells->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisible[wellIndex]) - { - (*m_oppositeFaultFacesTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); } cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 9a018b8ed4..51bd6e77c0 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -212,75 +212,7 @@ void RivGridPartMgr::updateCellColor(cvf::Color4f color) m_surfaceGridLines->setEffect(eff.p()); } } -#if 0 -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot) -{ - CVF_ASSERT(cellResultSlot); - - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - - cvf::ref surfaceFacesColorArray; - - // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); - } - else if (cellResultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::Vec2fArray* textureCoords = m_surfaceFacesTextureCoords.p(); - RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(cellResultSlot, m_grid.p(), textureCoords, m_surfaceGenerator.quadToCellFaceMapper()); - } - else - { - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); - if (resultAccessor.isNull()) return; - - m_surfaceGenerator.textureCoordinates(m_surfaceFacesTextureCoords.p(), resultAccessor.p(), mapper); - } - - - setResultsTransparentForWellCells( - cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex()), - m_surfaceGenerator.quadToCellFaceMapper(), - m_surfaceFacesTextureCoords.p()); - - if (surfaceFacesColorArray.notNull()) - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } - } -} -#endif //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -304,50 +236,12 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } else { - RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); - texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - /* - // If the result is static, only read that. - size_t resTimeStepIdx = timeStepIndex; - const cvf::StructGridQuadToCellFaceMapper* quadMapper = m_surfaceGenerator.quadToCellFaceMapper(); - - if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, m_grid->gridIndex(), porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - - if (resultAccessor.isNull()) return; - - cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), - eclipseCase->gridCellToWellIndex(m_grid->gridIndex())); - - cvf::ref texMapper = new RivResultToTextureMapper(mapper, pipeInCellEval.p()); - - - - size_t numVertices = quadMapper->quadCount()*4; - m_surfaceFacesTextureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = m_surfaceFacesTextureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) - { - cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); - size_t cellIdx = quadMapper->cellIndex(i); - - cellScalarValue = resultAccessor->cellFaceScalar(cellIdx, faceId); - texCoord = texMapper->getTexCoord(cellScalarValue, cellIdx); + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[i*4 + j] = texCoord; - } - } - */ + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); } @@ -397,36 +291,6 @@ void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* part->setEffect(scalarEffect.p()); } -//-------------------------------------------------------------------------------------------------- -/// if this gridpart manager is set to have some transparency, we -/// interpret it as we are displaying beeing wellcells. The cells are then transparent by default, but -/// we turn that off for particular cells, if the well pipe is not shown for that cell -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap, - const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, - cvf::Vec2fArray* resultTextureCoords) -{ - if (m_opacityLevel < 1.0f ) - { - for(size_t i = 0; i < resultTextureCoords->size(); ++i) - { - if ((*resultTextureCoords)[i].y() == 1.0f) continue; // Do not touch undefined values - - size_t quadIdx = i/4; - size_t cellIndex = quadsToCellFaceMapper->cellIndex(quadIdx); - cvf::uint wellIndex = gridCellToWellIndexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !isWellPipeVisibleForWellIndex[wellIndex]) - { - (*resultTextureCoords)[i].y() = 0; // Set the Y texture coordinate to the opaque line in the texture - } - } - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 6e555300a6..ed6efb4c11 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -91,10 +91,6 @@ class RivGridPartMgr: public cvf::Object void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); - void setResultsTransparentForWellCells(const std::vector& isWellPipeVisibleForWellIndex, - const cvf::UIntArray* gridCellToWellIndexMap, - const cvf::StructGridQuadToCellFaceMapper* quadsToCellFaceMapper, - cvf::Vec2fArray* resultTextureCoords); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, cvf::StructGridGeometryGenerator* surfaceGenerator, size_t timeStepIndex, From e2f2cf4f24ee9396bb27df0481ccad4220d79d92 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:45:21 +0200 Subject: [PATCH 213/346] Removed asserts and simplified code --- .../RigResultModifierFactory.cpp | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp index 80efe51c5a..8d04aa6bcf 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp @@ -34,12 +34,9 @@ cvf::ref RigResultModifierFactory::createResultModifier(RigCa size_t timeStepIndex, QString& uiResultName) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + if (!eclipseCase) return NULL; - if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + if (!eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) { return NULL; } @@ -58,23 +55,24 @@ cvf::ref RigResultModifierFactory::createResultModifier(RigCa RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarResultIndex) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + if (!eclipseCase) return NULL; - RigGridBase* grid = eclipseCase->grid(gridIndex); - - if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) - { - return NULL; - } + if (!eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { return NULL; } + RigGridBase* grid = eclipseCase->grid(gridIndex); + if (!grid) + { + return NULL; + } + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarResultIndex); if (timeStepIndex >= scalarSetResults.size()) From a500c68efee9cb2b1cd130bac2f848589024df49 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:46:27 +0200 Subject: [PATCH 214/346] Use RigResultAccessFactory --- .../SocketInterface/RiaPropertyDataCommands.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 9edfad2c82..df9106bcf8 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -41,6 +41,8 @@ #include "RiuMainWindow.h" #include "RiuProcessMonitor.h" +#include "RigResultAccessorFactory.h" +#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- @@ -319,8 +321,9 @@ class RiaGetGridProperty: public RiaSocketCommand for (size_t tsIdx = 0; tsIdx < timestepCount; tsIdx++) { - cvf::ref cellCenterDataAccessObject = rimCase->reservoirData()->resultAccessor(rigGrid, porosityModelEnum, requestedTimesteps[tsIdx], scalarResultIndex); - if (cellCenterDataAccessObject.isNull()) + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(rimCase->reservoirData(), gridIdx, porosityModelEnum, requestedTimesteps[tsIdx], propertyName); + + if (resultAccessor.isNull()) { continue; } @@ -330,7 +333,7 @@ class RiaGetGridProperty: public RiaSocketCommand size_t valueIndex = 0; for (size_t cellIdx = 0; cellIdx < rigGrid->cellCount(); cellIdx++) { - double cellValue = cellCenterDataAccessObject->cellScalar(cellIdx); + double cellValue = resultAccessor->cellScalar(cellIdx); if (cellValue == HUGE_VAL) { cellValue = 0.0; From cb1407a86b944ba33226d778e1b5921f742e32fd Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:46:48 +0200 Subject: [PATCH 215/346] Use RigResultAccessFactory --- .../FileInterface/RifEclipseInputFileTools.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 1211dc9208..63c50908f3 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -21,6 +21,8 @@ #include "RifReaderEclipseOutput.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "cafProgressInfo.h" @@ -500,8 +502,8 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa return false; } - cvf::ref resultAccessor = eclipseCase->resultAccessor(eclipseCase->mainGrid(), porosityModel, timeStep, resultIndex); - if (resultAccessor.isNull()) + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, eclipseCase->mainGrid()->gridIndex(), porosityModel, timeStep, resultName); + if (resultAccessor.isNull()) { return false; } @@ -514,7 +516,7 @@ bool RifEclipseInputFileTools::writeBinaryResultToTextFile(const QString& fileNa { for (i = 0; i < eclipseCase->mainGrid()->cellCountI(); i++) { - double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); + double resultValue = resultAccessor->cellScalar(eclipseCase->mainGrid()->cellIndexFromIJK(i, j, k)); if (resultValue == HUGE_VAL) { resultValue = undefinedValue; From 24ff71d23ee555ed146772b2dd88e4db99a73b01 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:47:36 +0200 Subject: [PATCH 216/346] Prefix function to be deleted to easily spot the function in code --- .../RivCellEdgeEffectGenerator.cpp | 4 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 1 - .../ModelVisualization/RivGridPartMgr.cpp | 12 ++++++------ .../RivReservoirViewPartMgr.cpp | 2 +- .../ProjectDataModel/RimReservoirView.cpp | 18 +++++++++--------- .../RimStatisticsCaseEvaluator.cpp | 4 ++-- .../ReservoirDataModel/RigCaseData.cpp | 2 +- .../ReservoirDataModel/RigCaseData.h | 2 +- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 0dd9043c09..67ce43d69d 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -121,7 +121,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( } RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); + cellCenterDataAccessObject = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); } CVF_ASSERT(cellEdgeResultSlot->hasResult()); @@ -140,7 +140,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( { // Assuming static values to be mapped onto cell edge, always using time step zero // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); + daObj = eclipseCase->TO_BE_DELETED_resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); } cellEdgeDataAccessObjects.push_back(daObj.p()); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 47195d7d3b..ba9cc67315 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -120,7 +120,6 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->resultAccessor(m_grid.p(), porosityModel, resTimeStepIdx, scalarSetIndex); // Faults if (m_nativeFaultFaces.notNull()) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 51bd6e77c0..21ef0d7169 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -419,9 +419,9 @@ void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordi RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cvf::ref dataAccessObjectTranX = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); + cvf::ref dataAccessObjectTranX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); + cvf::ref dataAccessObjectTranY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); + cvf::ref dataAccessObjectTranZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); int quadCount = static_cast(quadToCellFaceMapper->quadCount()); @@ -560,19 +560,19 @@ void RivTransmissibilityColorMapper::updateTernarySaturationColorArray(size_t ti cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - cvf::ref dataAccessObjectSoil = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectSoil = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); if (dataAccessObjectSoil.isNull()) { dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSgas = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectSgas = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); if (dataAccessObjectSgas.isNull()) { dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; } - cvf::ref dataAccessObjectSwat = eclipseCase->resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); + cvf::ref dataAccessObjectSwat = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); if (dataAccessObjectSwat.isNull()) { dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 7c31d28ce4..4e7e4598d4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -728,7 +728,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 65a8f6706a..21782dbcc7 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1116,9 +1116,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); + cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); + cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); double scalarValue = 0.0; @@ -1147,9 +1147,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t tranX, tranY, tranZ; if (eclipseCase->results(porosityModel)->findTransmissibilityResults(tranX, tranY, tranZ)) { - cvf::ref dataAccessObjectX = eclipseCase->resultAccessor(grid, porosityModel, 0, tranX); - cvf::ref dataAccessObjectY = eclipseCase->resultAccessor(grid, porosityModel, 0, tranY); - cvf::ref dataAccessObjectZ = eclipseCase->resultAccessor(grid, porosityModel, 0, tranZ); + cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranX); + cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranY); + cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranZ); double scalarValue = dataAccessObjectX->cellScalar(cellIndex); resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); @@ -1163,12 +1163,12 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, } else { - resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); } } else { - resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); + resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); } if (resultAccessor.notNull()) @@ -1191,7 +1191,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor = eclipseCase->resultAccessor(grid, porosityModel, 0, resultIndices[idx]); + cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, resultIndices[idx]); if (resultAccessor.notNull()) { double scalarValue = resultAccessor->cellScalar(cellIndex); diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 0225d62e56..0be78814ba 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -197,7 +197,7 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - cvf::ref resultAccessor = sourceCase->reservoirData()->resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = sourceCase->reservoirData()->TO_BE_DELETED_resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); if (resultAccessor.notNull()) { sourceDataAccessList.push_back(resultAccessor.p()); @@ -349,7 +349,7 @@ void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultTyp size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - cvf::ref resultAccessor = m_destinationCase->resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); + cvf::ref resultAccessor = m_destinationCase->TO_BE_DELETED_resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); if (resultAccessor.isNull()) return; for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 1d5619f87b..4aa6af1889 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -488,7 +488,7 @@ const RigCaseCellResultsData* RigCaseData::results(RifReaderInterface::PorosityM //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RigCaseData::resultAccessor(const RigGridBase* grid, +cvf::ref RigCaseData::TO_BE_DELETED_resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index 68960b381a..9177e5d7ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -54,7 +54,7 @@ class RigCaseData: public cvf::Object void setActiveCellInfo(RifReaderInterface::PorosityModelResultType porosityModel, RigActiveCellInfo* activeCellInfo); - cvf::ref resultAccessor(const RigGridBase* grid, + cvf::ref TO_BE_DELETED_resultAccessor(const RigGridBase* grid, RifReaderInterface::PorosityModelResultType porosityModel, size_t timeStepIndex, size_t scalarSetIndex); From 2ab2838e8861d14adf4c30c49325ee69fe569ff4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 14:51:00 +0200 Subject: [PATCH 217/346] Removed obsolete code --- .../ModelVisualization/RivGridPartMgr.cpp | 118 ------------------ .../ModelVisualization/RivGridPartMgr.h | 5 - 2 files changed, 123 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 21ef0d7169..712c4e1e45 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -394,124 +394,6 @@ cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacit } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivTransmissibilityColorMapper::updateCombinedTransmissibilityTextureCoordinates(RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Vec2fArray* textureCoords, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) -{ - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - if (!mapper) return; - - const RimReservoirCellResultsStorage* gridCellResults = cellResultSlot->currentGridCellResults(); - if (!gridCellResults) return; - - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - if (!eclipseCase) return; - - size_t tranPosXScalarSetIndex, tranPosYScalarSetIndex, tranPosZScalarSetIndex; - if (!gridCellResults->cellResults()->findTransmissibilityResults(tranPosXScalarSetIndex, tranPosYScalarSetIndex, tranPosZScalarSetIndex)) return; - - // If the result is static, only read that. - size_t resTimeStepIdx = 0; - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - cvf::ref dataAccessObjectTranX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosXScalarSetIndex); - cvf::ref dataAccessObjectTranY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosYScalarSetIndex); - cvf::ref dataAccessObjectTranZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, resTimeStepIdx, tranPosZScalarSetIndex); - - - int quadCount = static_cast(quadToCellFaceMapper->quadCount()); - size_t numVertices = quadCount*4; - - textureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = textureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int quadIdx = 0; quadIdx < quadCount; quadIdx++) - { - cellScalarValue = HUGE_VAL; - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - - switch (cellFace) - { - case cvf::StructGridInterface::POS_I: - { - cellScalarValue = dataAccessObjectTranX->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_I: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranX->cellScalar(neighborGridCellIdx); - } - } - break; - case cvf::StructGridInterface::POS_J: - { - cellScalarValue = dataAccessObjectTranY->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_J: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranY->cellScalar(neighborGridCellIdx); - } - } - break; - case cvf::StructGridInterface::POS_K: - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(cellIndex); - } - break; - case cvf::StructGridInterface::NEG_K: - { - size_t i, j, k, neighborGridCellIdx; - grid->ijkFromCellIndex(cellIndex, &i, &j, &k); - - if(grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) - { - cellScalarValue = dataAccessObjectTranZ->cellScalar(neighborGridCellIdx); - } - } - break; - default: - CVF_ASSERT(false); - } - - - texCoord = mapper->mapToTextureCoord(cellScalarValue); - if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's - { - texCoord[1] = 1.0f; - } - - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[quadIdx*4 + j] = texCoord; - } - } - -} - - //-------------------------------------------------------------------------------------------------- /// 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. diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index ed6efb4c11..4985a360bf 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -44,11 +44,6 @@ class RimCellEdgeResultSlot; class RivTransmissibilityColorMapper { public: - static void updateCombinedTransmissibilityTextureCoordinates( - RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Vec2fArray* textureCoords, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); static void updateTernarySaturationColorArray( size_t timeStepIndex, From ca7f61d3ff6731dbac01f3a6423728a24b2ad413 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:08:30 +0200 Subject: [PATCH 218/346] Added overload to result accessor factory --- .../RigResultAccessorFactory.cpp | 147 ++++++++++++------ .../RigResultAccessorFactory.h | 17 +- 2 files changed, 112 insertions(+), 52 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index de23da6f87..71f20f5083 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -36,6 +36,69 @@ #include "RigCombTransResultAccessor.h" +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase* grid = eclipseCase->grid(gridIndex); + + if (uiResultName == RimDefines::combinedTransmissibilityResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); + + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); + + cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); + + return cellFaceAccessObject; + } + + return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName, + RimDefines::ResultCatType resultType) +{ + CVF_ASSERT(gridIndex < eclipseCase->gridCount()); + CVF_ASSERT(eclipseCase); + CVF_ASSERT(eclipseCase->results(porosityModel)); + CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); + + RigGridBase *grid = eclipseCase->grid(gridIndex); + + if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) + { + return NULL; + } + + size_t scalarSetIndex = eclipseCase->results(porosityModel)->findScalarResultIndex(resultType, uiResultName); + if (scalarSetIndex == cvf::UNDEFINED_SIZE_T) + { + return NULL; + } + + return createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); +} + //-------------------------------------------------------------------------------------------------- /// This function must be harmonized with RigResultModifierFactory::createResultModifier() //-------------------------------------------------------------------------------------------------- @@ -63,64 +126,46 @@ cvf::ref RigResultAccessorFactory::createNativeResultAccessor return NULL; } - std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); - - if (timeStepIndex >= scalarSetResults.size()) - { - return NULL; - } - - std::vector* resultValues = NULL; - if (timeStepIndex < scalarSetResults.size()) - { - resultValues = &(scalarSetResults[timeStepIndex]); - } - - bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); - if (useGlobalActiveIndex) - { - cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); - return object; - } - else - { - cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); - return object; - } + return createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, scalarSetIndex); } - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RigResultAccessorFactory::createResultAccessor(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - const QString& uiResultName) + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex) { - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); - - RigGridBase* grid = eclipseCase->grid(gridIndex); - - if (uiResultName == RimDefines::combinedTransmissibilityResultName()) - { - cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - - cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANX"); - cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANY"); - cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "TRANZ"); - - cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); - - return cellFaceAccessObject; - } - - return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); + if (!eclipseCase) return NULL; + + RigGridBase* grid = eclipseCase->grid(gridIndex); + if (!grid) return NULL; + + std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(resultIndex); + if (timeStepIndex >= scalarSetResults.size()) + { + return NULL; + } + + std::vector* resultValues = NULL; + if (timeStepIndex < scalarSetResults.size()) + { + resultValues = &(scalarSetResults[timeStepIndex]); + } + + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(resultIndex); + if (useGlobalActiveIndex) + { + cvf::ref object = new RigActiveCellsResultAccessor(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); + return object; + } + else + { + cvf::ref object = new RigAllGridCellsResultAccessor(grid, resultValues); + return object; + } } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 6a4a414865..15d2ebd99f 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -18,9 +18,10 @@ #pragma once -#include "cvfStructGridScalarDataAccess.h" #include "RifReaderInterface.h" +#include "RimDefines.h" +#include "cvfStructGridScalarDataAccess.h" class RigActiveCellInfo; class RigGridBase; @@ -36,6 +37,14 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& uiResultName); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + const QString& uiResultName, + RimDefines::ResultCatType resultType); + // TO BE DELETED static cvf::ref @@ -54,6 +63,12 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& resultName); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex); }; From ee939c8377a8087d789520ed3b8ec89cb3f2dfe9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:10:10 +0200 Subject: [PATCH 219/346] Use RigResultAccessor --- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 0be78814ba..f6bbada699 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,6 +20,8 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "RigResultModifier.h" #include "RigResultModifierFactory.h" #include "RigStatisticsMath.h" @@ -190,14 +192,12 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result // Build data access objects for source scalar results - cvf::Collection sourceDataAccessList; + cvf::Collection sourceDataAccessList; for (size_t caseIdx = 0; caseIdx < m_sourceCases.size(); caseIdx++) { RimCase* sourceCase = m_sourceCases.at(caseIdx); - size_t scalarResultIndex = sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); - - cvf::ref resultAccessor = sourceCase->reservoirData()->TO_BE_DELETED_resultAccessor(grid, poroModel, dataAccessTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(sourceCase->reservoirData(), gridIdx, poroModel, dataAccessTimeStepIndex, resultName, resultType); if (resultAccessor.notNull()) { sourceDataAccessList.push_back(resultAccessor.p()); From 0bef6369e195a5cab497579ffb605a241318ecef Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:11:30 +0200 Subject: [PATCH 220/346] Deleted unused code --- .../RimStatisticsCaseEvaluator.cpp | 19 ------------------- .../RimStatisticsCaseEvaluator.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index f6bbada699..83af15a0dc 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -338,25 +338,6 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimStatisticsCaseEvaluator::debugOutput(RimDefines::ResultCatType resultType, const QString& resultName, size_t timeStepIdx) -{ - CVF_ASSERT(m_destinationCase); - - qDebug() << resultName << "timeIdx : " << timeStepIdx; - - size_t scalarResultIndex = m_destinationCase->results(RifReaderInterface::MATRIX_RESULTS)->findScalarResultIndex(resultType, resultName); - - cvf::ref resultAccessor = m_destinationCase->TO_BE_DELETED_resultAccessor(m_destinationCase->mainGrid(), RifReaderInterface::MATRIX_RESULTS, timeStepIdx, scalarResultIndex); - if (resultAccessor.isNull()) return; - - for (size_t cellIdx = 0; cellIdx < m_reservoirCellCount; cellIdx++) - { - qDebug() << resultAccessor->cellScalar(cellIdx); - } -} //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 87b21c7aae..62f4ca36cc 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -73,8 +73,6 @@ class RimStatisticsCaseEvaluator void evaluateForResults(const QList& resultSpecification); - void debugOutput(RimDefines::ResultCatType resultType, const QString& resultName, size_t timeStepIdx); - private: void addNamedResult(RigCaseCellResultsData* cellResults, RimDefines::ResultCatType resultType, const QString& resultName, size_t activeCellCount); void buildSourceMetaData(RifReaderInterface::PorosityModelResultType poroModel, RimDefines::ResultCatType resultType, const QString& resultName); From 8451ffc2fb829a67b61a6a1745e1746c744ffb03 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:21:46 +0200 Subject: [PATCH 221/346] Added include to RigResultAccessor in factory --- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 1 - ApplicationCode/ModelVisualization/RivGridPartMgr.cpp | 1 - ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp | 1 - ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 1 - ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h | 2 +- ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 63c50908f3..dedd0e78f0 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -21,7 +21,6 @@ #include "RifReaderEclipseOutput.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "cafProgressInfo.h" diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 712c4e1e45..99fa9bf715 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -51,7 +51,6 @@ #include "RivCellEdgeEffectGenerator.h" #include "RivSourceInfo.h" #include "cvfStructGridGeometryGenerator.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "RivResultToTextureMapper.h" #include "RivTextureCoordsCreator.h" diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index 59163d5fdb..ff97711e3d 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -27,7 +27,6 @@ #include "RigPipeInCellEvaluator.h" #include "RivResultToTextureMapper.h" #include "RimWellCollection.h" -#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 83af15a0dc..778b4d19c0 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -20,7 +20,6 @@ #include "RigCaseCellResultsData.h" #include "RigCaseData.h" -#include "RigResultAccessor.h" #include "RigResultAccessorFactory.h" #include "RigResultModifier.h" #include "RigResultModifierFactory.h" diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 15d2ebd99f..6c1d890dd7 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -19,13 +19,13 @@ #pragma once #include "RifReaderInterface.h" +#include "RigResultAccessor.h" #include "RimDefines.h" #include "cvfStructGridScalarDataAccess.h" class RigActiveCellInfo; class RigGridBase; -class RigResultAccessor; class RigResultAccessorFactory { diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index df9106bcf8..a8257f834b 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -42,7 +42,6 @@ #include "RiuMainWindow.h" #include "RiuProcessMonitor.h" #include "RigResultAccessorFactory.h" -#include "RigResultAccessor.h" //-------------------------------------------------------------------------------------------------- From 897ed240c52c20769ba174ff7e8c967e49a0a659 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:22:00 +0200 Subject: [PATCH 222/346] Use RigResultAccessor --- .../RivReservoirViewPartMgr.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 4e7e4598d4..461a90c7d0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -17,27 +17,27 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaStdInclude.h" + #include "RivReservoirViewPartMgr.h" -#include "RivGridPartMgr.h" -#include "RimReservoirView.h" + +#include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigGridBase.h" -#include "RigCaseCellResultsData.h" #include "RigResultAccessorFactory.h" + +#include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" -#include "RimCellRangeFilterCollection.h" -#include "RimWellCollection.h" +#include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilterCollection.h" +#include "RimCellRangeFilterCollection.h" +#include "RimFaultCollection.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimReservoirView.h" #include "RimResultDefinition.h" - -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" - #include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsStorage.h" -#include "RimFaultCollection.h" +#include "RimWellCollection.h" + +#include "RivGridPartMgr.h" //-------------------------------------------------------------------------------------------------- /// @@ -728,7 +728,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel((*pfIt)->resultDefinition()->porosityModel()); RigCaseData* eclipseCase = propFilterColl->reservoirView()->eclipseCase()->reservoirData(); - cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, adjustedTimeStepIndex, scalarResultIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, adjustedTimeStepIndex, (*pfIt)->resultDefinition->resultVariable(), (*pfIt)->resultDefinition->resultType()); CVF_ASSERT(resultAccessor.notNull()); //#pragma omp parallel for schedule(dynamic) From 1b3be87074c18e82ae15e2c53ead75cad3beb7fc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 15:26:50 +0200 Subject: [PATCH 223/346] Moved include from header to cpp --- .../ModelVisualization/RivCellEdgeEffectGenerator.cpp | 1 + ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 1 + ApplicationCode/ReservoirDataModel/RigGridBase.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 67ce43d69d..bbaf9eafb6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -65,6 +65,7 @@ #include "RimCellPropertyFilterCollection.h" #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" +#include "cvfStructGridScalarDataAccess.h" //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 21782dbcc7..063474c3f8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -51,6 +51,7 @@ #include "cvfOverlayScalarMapperLegend.h" #include "cvfPart.h" #include "cvfScene.h" +#include "cvfStructGridScalarDataAccess.h" #include "cvfViewport.h" #include "cvfqtUtils.h" diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index c9ce6d8c54..0197cd0405 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -24,7 +24,6 @@ #include "cvfBoundingBox.h" #include "cvfStructGrid.h" #include "cvfStructGridGeometryGenerator.h" -#include "cvfStructGridScalarDataAccess.h" #include "cafFixedArray.h" From e9b67a9599d809c7358d139c3a6c7758279cd361 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 9 Aug 2014 22:23:41 +0200 Subject: [PATCH 224/346] Added RivTernaryScalarMapper and unit test --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../CMakeLists.txt | 5 + .../RivTernaryScalarMapper-Test.cpp | 49 +++++++++ .../RivTernaryScalarMapper.cpp | 102 ++++++++++++++++++ .../RivTernaryScalarMapper.h | 47 ++++++++ 5 files changed, 205 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 9ca5bb10e4..ee8779f9c2 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -24,6 +24,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h ${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -45,6 +46,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt index 0b0bb00ce8..97e839bfc1 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/CMakeLists.txt @@ -19,6 +19,7 @@ include_directories( set( MODEL_VISUALIZATION_CPP_SOURCES ../RivPipeGeometryGenerator.cpp + ../RivTernaryScalarMapper.cpp ) @@ -29,6 +30,7 @@ set( CPP_SOURCES set( UNIT_TEST_CPP_SOURCES main.cpp RivPipeGeometryGenerator-Test.cpp + RivTernaryScalarMapper-Test.cpp ) @@ -37,10 +39,13 @@ set( LINK_LIBRARIES LibRender LibGeometry LibCore + LibGuiQt CommonCode ${OPENGL_LIBRARIES} + ${QT_LIBRARIES} + ) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp new file mode 100644 index 0000000000..f39cedfb77 --- /dev/null +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +// #include "cvfLibCore.h" +// #include "cvfLibViewing.h" +// #include "cvfLibRender.h" +// #include "cvfLibGeometry.h" +// +// #include "RivPipeGeometryGenerator.h" + +#include "RivTernaryScalarMapper.h" +#include "cvfTextureImage.h" + +#include +#include "cvfqtUtils.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(TernaryScalarMapperTest, BasicFunctions) +{ + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + + cvf::ref texImage = new cvf::TextureImage; + scalarMapper->updateTexture(texImage.p()); + + QImage img = cvfqt::Utils::toQImage(*(texImage.p())); + + img.save("c:/tmp/test.bmp"); + +} + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp new file mode 100644 index 0000000000..0f0f1ed9cf --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryScalarMapper.h" +#include "cvfTextureImage.h" + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) +: m_undefScalarColor(undefScalarColor), + m_opacityLevel(opacityLevel), + m_textureSize(128, 256) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) +{ + cvf::Vec2f texCoord; + + return texCoord; +} + +//-------------------------------------------------------------------------------------------------- +/// F * +/// * * +/// * * +/// * * Texture in this region is assigned the given opacity level +/// * * +/// D *********** E +/// C * +/// * * +/// * * Texture in this region is opaque +/// * * +/// * * +/// A *********** B +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) +{ + CVF_ASSERT(image); + image->allocate(m_textureSize.x(), m_textureSize.y()); + + // For now fill with white so we can see any errors more easily + image->fill(cvf::Color4ub(cvf::Color3::WHITE)); + + + + cvf::uint halfTextureHeight = m_textureSize.y() / 2; + + // Create texture + + float xStride = static_cast(1.0f / m_textureSize.x()); + float yStride = static_cast(1.0f / halfTextureHeight); + + float sgas_red = 0.0f; + for (int yPos = 0; yPos < halfTextureHeight; yPos++) + { + float soil_green = 0.0f; + for (int xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) + { + float swat_blue = 1.0f - sgas_red - soil_green; + + cvf::Color3f floatCol(sgas_red, soil_green, swat_blue); + + cvf::ubyte rByteCol = floatCol.rByte(); + cvf::ubyte gByteCol = floatCol.gByte(); + cvf::ubyte bByteCol = floatCol.bByte(); + + const cvf::Color4ub clr(rByteCol, gByteCol, bByteCol, 255); + image->setPixel(xPos, yPos, clr); + + // Set opacity + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, 255 * m_opacityLevel); + image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); + + soil_green += xStride; + } + sgas_red += yStride; + } + + return true; +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h new file mode 100644 index 0000000000..8da5bf112e --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector2.h" +#include "cvfColor3.h" + +namespace cvf +{ + class TextureImage; +} + +//================================================================================================== +/// +//================================================================================================== +class RivTernaryScalarMapper : public cvf::Object +{ +public: + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + + cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); + bool updateTexture(cvf::TextureImage* image); + +private: + cvf::Color3f m_undefScalarColor; + float m_opacityLevel; + cvf::Vec2ui m_textureSize; +}; + From 0440e21f276cd42bbe7af954b0d76ee8db987fae Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 10 Aug 2014 09:50:50 +0200 Subject: [PATCH 225/346] Created texture and texture coord calculations --- .../RivTernaryScalarMapper-Test.cpp | 73 ++++++++++++++++--- .../RivTernaryScalarMapper.cpp | 34 ++++++++- .../RivTernaryScalarMapper.h | 10 +++ 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index f39cedfb77..dc7f62b9a6 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -18,18 +18,12 @@ #include "gtest/gtest.h" -// #include "cvfLibCore.h" -// #include "cvfLibViewing.h" -// #include "cvfLibRender.h" -// #include "cvfLibGeometry.h" -// -// #include "RivPipeGeometryGenerator.h" - #include "RivTernaryScalarMapper.h" + #include "cvfTextureImage.h" +#include "cvfqtUtils.h" #include -#include "cvfqtUtils.h" //-------------------------------------------------------------------------------------------------- /// @@ -43,7 +37,66 @@ TEST(TernaryScalarMapperTest, BasicFunctions) QImage img = cvfqt::Utils::toQImage(*(texImage.p())); - img.save("c:/tmp/test.bmp"); - + img.save("c:/tmp/test.png"); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST(TernaryScalarMapperTest, TextureMapping) +{ + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + + // Without opacity + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 0.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(1.0, 0.0, false); + EXPECT_DOUBLE_EQ(1.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 1.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.5, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(3.0, 3.0, false); + EXPECT_DOUBLE_EQ(1.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(-1.0, -1.0, false); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.0, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.5, 3.0, false); + EXPECT_DOUBLE_EQ(0.5, texCoord.x()); + EXPECT_DOUBLE_EQ(0.25, texCoord.y()); + } + + + + + // Opacity + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 0.0, true); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(0.5, texCoord.y()); + } + + { + cvf::Vec2f texCoord = scalarMapper->mapToTextureCoord(0.0, 1.0, true); + EXPECT_DOUBLE_EQ(0.0, texCoord.x()); + EXPECT_DOUBLE_EQ(1.0, texCoord.y()); + } +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 0f0f1ed9cf..33561806dc 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -29,6 +29,7 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo m_opacityLevel(opacityLevel), m_textureSize(128, 256) { + setTernaryRanges(0.0, 1.0, 0.0, 1.0); } //-------------------------------------------------------------------------------------------------- @@ -36,8 +37,19 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo //-------------------------------------------------------------------------------------------------- cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) { - cvf::Vec2f texCoord; + double soilNormalized = (soil - m_rangeMinSoil) * m_soilFactor; + soilNormalized = cvf::Math::clamp(soilNormalized, 0.0, 1.0); + double swatNormalized = (swat - m_rangeMinSwat) * m_swatFactor; + swatNormalized = cvf::Math::clamp(swatNormalized, 0.0, 1.0 - soilNormalized); + swatNormalized /= 2.0; + + if (isTransparent) + { + swatNormalized += 0.5; + } + + cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(swatNormalized)); return texCoord; } @@ -73,10 +85,10 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) float yStride = static_cast(1.0f / halfTextureHeight); float sgas_red = 0.0f; - for (int yPos = 0; yPos < halfTextureHeight; yPos++) + for (cvf::uint yPos = 0; yPos < halfTextureHeight; yPos++) { float soil_green = 0.0f; - for (int xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) + for (cvf::uint xPos = 0; xPos < m_textureSize.x() - yPos; xPos++) { float swat_blue = 1.0f - sgas_red - soil_green; @@ -90,7 +102,7 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) image->setPixel(xPos, yPos, clr); // Set opacity - const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, 255 * m_opacityLevel); + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * m_opacityLevel)); image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); soil_green += xStride; @@ -100,3 +112,17 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) return true; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper) +{ + m_rangeMinSoil = soilLower; + m_rangeMaxSoil = soilUpper; + m_soilFactor = 1.0 / (soilUpper - soilLower); + + m_rangeMinSwat = swatLower; + m_rangeMaxSwat = swatUpper; + m_swatFactor = 1.0 / (swatUpper - swatLower); +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 8da5bf112e..5c952782a5 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -36,6 +36,8 @@ class RivTernaryScalarMapper : public cvf::Object public: RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + void setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper); + cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); bool updateTexture(cvf::TextureImage* image); @@ -43,5 +45,13 @@ class RivTernaryScalarMapper : public cvf::Object cvf::Color3f m_undefScalarColor; float m_opacityLevel; cvf::Vec2ui m_textureSize; + + double m_rangeMaxSoil; + double m_rangeMinSoil; + double m_soilFactor; + + double m_rangeMaxSwat; + double m_rangeMinSwat; + double m_swatFactor; }; From 85d4de674655ffa8331ebe7adace86597b975ed1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 10 Aug 2014 14:55:27 +0200 Subject: [PATCH 226/346] Added RigResultAccessor2d --- .../ReservoirDataModel/CMakeLists_files.cmake | 3 + .../ReservoirDataModel/RigResultAccessor2d.h | 39 +++++++++ .../RigTernaryResultAccessor2d.cpp | 86 +++++++++++++++++++ .../RigTernaryResultAccessor2d.h | 46 ++++++++++ 4 files changed, 174 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h create mode 100644 ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 4a23c7302f..25f9be656d 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -30,6 +30,8 @@ ${CEE_CURRENT_LIST_DIR}RigNNCData.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.h ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.inl ${CEE_CURRENT_LIST_DIR}RigPipeInCellEvaluator.h +${CEE_CURRENT_LIST_DIR}RigResultAccessor2d.h +${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -55,6 +57,7 @@ ${CEE_CURRENT_LIST_DIR}RigWellPath.cpp ${CEE_CURRENT_LIST_DIR}RigFault.cpp ${CEE_CURRENT_LIST_DIR}RigNNCData.cpp ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.cpp +${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h new file mode 100644 index 0000000000..87e0e2b3f5 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector2.h" +#include "cvfStructGrid.h" + +//================================================================================================== +/// +//================================================================================================== +class RigResultAccessor2d : public cvf::Object +{ +public: + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; + + virtual QString resultName() const = 0; + +}; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp new file mode 100644 index 0000000000..ef3b02d8ad --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigTernaryResultAccessor2d.h" + +#include "RigResultAccessor.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigTernaryResultAccessor::RigTernaryResultAccessor() +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// Requires at least two data objects present, asserts if more than one data accessor is NULL +//-------------------------------------------------------------------------------------------------- +void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat) +{ + m_soilAccessor = soil; + m_sgasAccessor = sgas; + m_swatAccessor = swat; + + int nullPointerCount = 0; + if (!soil) nullPointerCount++; + if (!sgas) nullPointerCount++; + if (!swat) nullPointerCount++; + + CVF_ASSERT(nullPointerCount <= 1); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) +{ + double soil = 0.0; + double swat = 0.0; + + if (m_soilAccessor.notNull()) + { + soil = m_soilAccessor->cellScalar(gridLocalCellIndex); + + if (m_swatAccessor.notNull()) + { + swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + } + else + { + swat = 1.0 - soil - m_sgasAccessor->cellScalar(gridLocalCellIndex); + } + } + else + { + swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + + soil = 1.0 - swat - m_sgasAccessor->cellScalar(gridLocalCellIndex); + } + + return cvf::Vec2d(soil, swat); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +{ + return cellScalar(gridLocalCellIndex); +} diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h new file mode 100644 index 0000000000..d1e85bcade --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessor2d.h" + +class RigResultAccessor; + +//================================================================================================== +/// +//================================================================================================== +class RigTernaryResultAccessor : public RigResultAccessor2d +{ +public: + RigTernaryResultAccessor(); + + /// Requires two of the arguments to be present + void setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat); + + /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// based on the two others + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex); + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId);; + +private: + cvf::ref m_soilAccessor; + cvf::ref m_sgasAccessor; + cvf::ref m_swatAccessor; +}; + From 68bc378abe5d9531d33aa29526c5eb00f737c8e1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:41:28 +0200 Subject: [PATCH 227/346] Minor fixes for result accessors --- .../ReservoirDataModel/RigResultAccessor.h | 54 ------------------- .../ReservoirDataModel/RigResultAccessor2d.h | 3 -- .../RigTernaryResultAccessor2d.cpp | 4 +- .../RigTernaryResultAccessor2d.h | 7 ++- 4 files changed, 5 insertions(+), 63 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index dc248b7c73..7bf45e048c 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -35,57 +35,3 @@ class RigResultAccessor : public cvf::Object virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; -#if 0 - -//================================================================================================== -/// -//================================================================================================== -class RigResultAccessor2d : public cvf::Object -{ -public: - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - -}; - -//================================================================================================== -/// -//================================================================================================== -class RigTernaryResultAccessor : public Rig2DResultAccessor -{ -public: - /// Requires two of the arguments to be present - void setTernaryResultAccessors(RigResultAccessObject* soil, RigResultAccessObject* sgas, RigResultAccessObject* swat); - - /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated - /// based on the two others - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) { }; - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) { return cellScalar(size_t gridLocalCellIndex); }; - - virtual QString resultName() const = 0; - -}; - -class RivTernaryScalarMapper : public cvf::Object -{ -public: - RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) : m_undefScalarColor(undefScalarColor), m_opacityLevel(opacityLevel) - { - - } - - /// Calculate texture coords into an image produced by updateTexture, from the scalarValue - Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent) {} - - /// Update the supplied TextureImage to be addressable by the texture coords delivered by mapToTextureCoord - bool updateTexture(TextureImage* image){} - -private: - cvf::Color3f m_undefScalarColor; - float m_opacityLevel; -}; - - -#endif diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h index 87e0e2b3f5..c3b568be20 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h @@ -33,7 +33,4 @@ class RigResultAccessor2d : public cvf::Object public: virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const = 0; virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; - - virtual QString resultName() const = 0; - }; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index ef3b02d8ad..fbb01f2bf4 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -49,7 +49,7 @@ void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) +cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { double soil = 0.0; double swat = 0.0; @@ -80,7 +80,7 @@ cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +cvf::Vec2d RigTernaryResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { return cellScalar(gridLocalCellIndex); } diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h index d1e85bcade..47ff642b2e 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -19,8 +19,7 @@ #pragma once #include "RigResultAccessor2d.h" - -class RigResultAccessor; +#include "RigResultAccessor.h" //================================================================================================== /// @@ -35,8 +34,8 @@ class RigTernaryResultAccessor : public RigResultAccessor2d /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others - virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex); - virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId);; + virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const; + virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: cvf::ref m_soilAccessor; From b414ba0ee3d39d43115e8cbb65cc2901b7eff42a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:42:54 +0200 Subject: [PATCH 228/346] Created setter for opacity --- .../RivTernaryScalarMapper-Test.cpp | 4 +- .../RivTernaryScalarMapper.cpp | 39 ++++++++++++------- .../RivTernaryScalarMapper.h | 14 ++++--- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index dc7f62b9a6..6f50cb5717 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -30,7 +30,7 @@ //-------------------------------------------------------------------------------------------------- TEST(TernaryScalarMapperTest, BasicFunctions) { - cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); cvf::ref texImage = new cvf::TextureImage; scalarMapper->updateTexture(texImage.p()); @@ -45,7 +45,7 @@ TEST(TernaryScalarMapperTest, BasicFunctions) //-------------------------------------------------------------------------------------------------- TEST(TernaryScalarMapperTest, TextureMapping) { - cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY, 0.8f); + cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); // Without opacity { diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 33561806dc..0ea8fe889b 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -24,32 +24,41 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel) +RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor) : m_undefScalarColor(undefScalarColor), - m_opacityLevel(opacityLevel), m_textureSize(128, 256) { + m_opacityLevel = 1.0; + setTernaryRanges(0.0, 1.0, 0.0, 1.0); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, bool isTransparent) +void RivTernaryScalarMapper::setOpacityLevel(float opacityLevel) +{ + m_opacityLevel = opacityLevel; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, bool isTransparent) const { double soilNormalized = (soil - m_rangeMinSoil) * m_soilFactor; soilNormalized = cvf::Math::clamp(soilNormalized, 0.0, 1.0); - double swatNormalized = (swat - m_rangeMinSwat) * m_swatFactor; - swatNormalized = cvf::Math::clamp(swatNormalized, 0.0, 1.0 - soilNormalized); - swatNormalized /= 2.0; + double sgasNormalized = (sgas - m_rangeMinSgas) * m_sgasFactor; + sgasNormalized = cvf::Math::clamp(sgasNormalized, 0.0, 1.0 - soilNormalized); + sgasNormalized /= 2.0; if (isTransparent) { - swatNormalized += 0.5; + sgasNormalized += 0.5; } - cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(swatNormalized)); + cvf::Vec2f texCoord(static_cast(soilNormalized), static_cast(sgasNormalized)); return texCoord; } @@ -60,12 +69,13 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double swat, b /// * * Texture in this region is assigned the given opacity level /// * * /// D *********** E -/// C * +/// C * SGAS /// * * /// * * Texture in this region is opaque /// * * /// * * -/// A *********** B +/// A *********** B +/// SWAT SOIL //-------------------------------------------------------------------------------------------------- bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) { @@ -116,13 +126,14 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper) +void RivTernaryScalarMapper::setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper) { m_rangeMinSoil = soilLower; m_rangeMaxSoil = soilUpper; m_soilFactor = 1.0 / (soilUpper - soilLower); - m_rangeMinSwat = swatLower; - m_rangeMaxSwat = swatUpper; - m_swatFactor = 1.0 / (swatUpper - swatLower); + m_rangeMinSgas = sgasLower; + m_rangeMaxSgas = sgasUpper; + m_sgasFactor = 1.0 / (sgasUpper - sgasLower); } + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 5c952782a5..9ba59cefa4 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -34,11 +34,13 @@ namespace cvf class RivTernaryScalarMapper : public cvf::Object { public: - RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor, float opacityLevel); + RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor); - void setTernaryRanges(double soilLower, double soilUpper, double swatLower, double swatUpper); + void setOpacityLevel(float opacityLevel); - cvf::Vec2f mapToTextureCoord(double soil, double swat, bool isTransparent); + void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); + + cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; bool updateTexture(cvf::TextureImage* image); private: @@ -50,8 +52,8 @@ class RivTernaryScalarMapper : public cvf::Object double m_rangeMinSoil; double m_soilFactor; - double m_rangeMaxSwat; - double m_rangeMinSwat; - double m_swatFactor; + double m_rangeMaxSgas; + double m_rangeMinSgas; + double m_sgasFactor; }; From 5e478d833645cdb2f0587beecb957e0f57bc31ad Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 07:46:08 +0200 Subject: [PATCH 229/346] Layout cleanup --- .../RivTextureCoordsCreator.cpp | 8 ++++++-- .../RivTextureCoordsCreator.h | 17 +++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index ff97711e3d..e3bca13c4e 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -47,7 +47,7 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); CVF_ASSERT(m_resultAccessor.notNull()); - cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(gridIndex)); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); @@ -59,7 +59,11 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords, const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper) +void RivTextureCoordsCreator::createTextureCoords( + cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigResultAccessor* resultAccessor, + const RivResultToTextureMapper* texMapper) { CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h index c08d647b0a..0e1a543982 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -26,9 +26,9 @@ class RimResultSlot; class RigResultAccessor; class RivResultToTextureMapper; -namespace cvf{ -class StructGridQuadToCellFaceMapper; - +namespace cvf +{ + class StructGridQuadToCellFaceMapper; } @@ -38,7 +38,7 @@ class RivTextureCoordsCreator RivTextureCoordsCreator(RimResultSlot* cellResultSlot, size_t timeStepIndex, size_t gridIndex, - const cvf::StructGridQuadToCellFaceMapper* quadMapper); + const cvf::StructGridQuadToCellFaceMapper* quadMapper); void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) { @@ -52,11 +52,8 @@ class RivTextureCoordsCreator const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper); - cvf::cref m_quadMapper; - cvf::ref m_resultAccessor; - cvf::ref m_texMapper; + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; }; - - - From 1161ff7c73973a5030139dc633a96513ef7344f2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 08:10:07 +0200 Subject: [PATCH 230/346] Added ternary texture and scalar mappers --- .../ModelVisualization/CMakeLists_files.cmake | 3 + .../RivTernaryResultToTextureMapper.h | 51 +++++++++ .../RivTernaryTextureCoordsCreator.cpp | 106 ++++++++++++++++++ .../RivTernaryTextureCoordsCreator.h | 59 ++++++++++ .../RimTernaryLegendConfig.cpp | 15 ++- .../ProjectDataModel/RimTernaryLegendConfig.h | 5 +- 6 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h create mode 100644 ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index ee8779f9c2..4197e8e99f 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -23,8 +23,10 @@ ${CEE_CURRENT_LIST_DIR}RivWellPathCollectionPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.h ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.h ${CEE_CURRENT_LIST_DIR}RivResultToTextureMapper.h +${CEE_CURRENT_LIST_DIR}RivTernaryResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h +${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -47,6 +49,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellPipesPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h new file mode 100644 index 0000000000..a93e8e95c2 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigPipeInCellEvaluator.h" + +#include "RivTernaryScalarMapper.h" + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfStructGrid.h" +#include "cvfVector2.h" + +#include + +class RivTernaryResultToTextureMapper : public cvf::Object +{ +public: + RivTernaryResultToTextureMapper(const RivTernaryScalarMapper* scalarMapper, const RigPipeInCellEvaluator* pipeInCellEvaluator) + : m_scalarMapper(scalarMapper), m_pipeInCellEvaluator(pipeInCellEvaluator) + {} + + cvf::Vec2f getTexCoord(double soil, double sgas, size_t cellIndex) const + { + bool isTransparent = m_pipeInCellEvaluator->isWellPipeInCell(cellIndex); + + return m_scalarMapper->mapToTextureCoord(soil, sgas, isTransparent); + } + +private: + cvf::cref m_scalarMapper; + cvf::cref m_pipeInCellEvaluator; +}; + + diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp new file mode 100644 index 0000000000..9a8826ec03 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryTextureCoordsCreator.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigPipeInCellEvaluator.h" +#include "RigResultAccessorFactory.h" +#include "RigTernaryResultAccessor2d.h" + +#include "RimCase.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" + +#include "RivTernaryResultToTextureMapper.h" +#include "RivTernaryScalarMapper.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryTextureCoordsCreator::RivTernaryTextureCoordsCreator( + RimResultSlot* cellResultSlot, + RimTernaryLegendConfig* ternaryLegendConfig, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + + m_quadMapper = quadMapper; + CVF_ASSERT(quadMapper && eclipseCase ); + + size_t resTimeStepIdx = timeStepIndex; + + if (cellResultSlot->hasStaticResult()) resTimeStepIdx = 0; + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + cvf::ref soil = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SOIL"); + cvf::ref sgas = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SGAS"); + cvf::ref swat = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, "SWAT"); + + m_resultAccessor = new RigTernaryResultAccessor(); + m_resultAccessor->setTernaryResultAccessors(soil.p(), sgas.p(), swat.p()); + + cvf::ref pipeInCellEval = new RigPipeInCellEvaluator( cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), + eclipseCase->gridCellToWellIndex(gridIndex)); + + const RivTernaryScalarMapper* mapper = ternaryLegendConfig->scalarMapper(); + + m_texMapper = new RivTernaryResultToTextureMapper(mapper, pipeInCellEval.p()); + CVF_ASSERT(m_texMapper.notNull()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryTextureCoordsCreator::createTextureCoords( + cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigTernaryResultAccessor* resultAccessor, + const RivTernaryResultToTextureMapper* texMapper) +{ + CVF_ASSERT(quadTextureCoords && quadMapper && resultAccessor && texMapper); + + size_t numVertices = quadMapper->quadCount()*4; + quadTextureCoords->resize(numVertices); + cvf::Vec2f* rawPtr = quadTextureCoords->ptr(); + + cvf::Vec2d resultValue; + cvf::Vec2f texCoord; + +#pragma omp parallel for private(texCoord, resultValue) + for (int i = 0; i < static_cast(quadMapper->quadCount()); i++) + { + cvf::StructGridInterface::FaceType faceId = quadMapper->cellFace(i); + size_t cellIdx = quadMapper->cellIndex(i); + + resultValue = resultAccessor->cellFaceScalar(cellIdx, faceId); + texCoord = texMapper->getTexCoord(resultValue.x(), resultValue.y(), cellIdx); + + size_t j; + for (j = 0; j < 4; j++) + { + rawPtr[i*4 + j] = texCoord; + } + } +} diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h new file mode 100644 index 0000000000..fcf41f8eb7 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfArray.h" + +class RimResultSlot; +class RigTernaryResultAccessor; +class RivTernaryResultToTextureMapper; +class RimTernaryLegendConfig; + +namespace cvf +{ + class StructGridQuadToCellFaceMapper; +} + + +class RivTernaryTextureCoordsCreator +{ +public: + RivTernaryTextureCoordsCreator( RimResultSlot* cellResultSlot, + RimTernaryLegendConfig* ternaryLegendConfig, + size_t timeStepIndex, + size_t gridIndex, + const cvf::StructGridQuadToCellFaceMapper* quadMapper); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) + { + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); + } + +private: + static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, + const cvf::StructGridQuadToCellFaceMapper* quadMapper, + const RigTernaryResultAccessor* resultAccessor, + const RivTernaryResultToTextureMapper* texMapper); + + cvf::cref m_quadMapper; + cvf::ref m_resultAccessor; + cvf::ref m_texMapper; +}; diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index dab84420e6..5ee3e364a3 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -25,10 +25,12 @@ #include "RimReservoirView.h" #include "RivTernarySaturationOverlayItem.h" +#include "RivTernaryScalarMapper.h" -#include #include "cvfqtUtils.h" +#include + CAF_PDM_SOURCE_INIT(RimTernaryLegendConfig, "RimTernaryLegendConfig"); @@ -93,6 +95,8 @@ RimTernaryLegendConfig::RimTernaryLegendConfig() m_localAutoMin.resize(3, 0.0); m_localAutoMax.resize(3, 1.0); + m_scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); + recreateLegend(); updateLegend(); } @@ -163,6 +167,7 @@ void RimTernaryLegendConfig::updateLegend() double swatUpper = 1.0; ternaryRanges(soilLower, soilUpper, sgasLower, sgasUpper, swatLower, swatUpper); + m_scalarMapper->setTernaryRanges(soilLower, soilUpper, sgasLower, sgasUpper); cvf::String soilRange; cvf::String sgasRange; @@ -438,3 +443,11 @@ void RimTernaryLegendConfig::updateLabelText() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapper* RimTernaryLegendConfig::scalarMapper() +{ + return m_scalarMapper.p(); +} + diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h index 79c94d5d11..7567867752 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -27,6 +27,7 @@ class RimReservoirView; class RivTernarySaturationOverlayItem; +class RivTernaryScalarMapper; namespace cvf { @@ -70,7 +71,8 @@ class RimTernaryLegendConfig : public caf::PdmObject void recreateLegend(); - RivTernarySaturationOverlayItem* legend(); + RivTernarySaturationOverlayItem* legend(); + RivTernaryScalarMapper* scalarMapper(); protected: virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); @@ -106,4 +108,5 @@ class RimTernaryLegendConfig : public caf::PdmObject caf::PdmPointer m_reservoirView; cvf::ref m_legend; + cvf::ref m_scalarMapper; }; From 1b69f93a11b77a79f8798cefd9ed20649577b62f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 10:49:42 +0200 Subject: [PATCH 231/346] Added ternary scalar mapper effect generator --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivTernaryScalarMapper.cpp | 2 +- .../RivTernaryScalarMapper.h | 2 +- .../RivTernaryScalarMapperEffectGenerator.cpp | 244 ++++++++++++++++++ .../RivTernaryScalarMapperEffectGenerator.h | 68 +++++ 5 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp create mode 100644 ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 4197e8e99f..fc4c22bbe0 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -27,6 +27,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryResultToTextureMapper.h ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -50,6 +51,7 @@ ${CEE_CURRENT_LIST_DIR}RivWellHeadPartMgr.cpp ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp +${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 0ea8fe889b..2c5eb14efc 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -77,7 +77,7 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, b /// A *********** B /// SWAT SOIL //-------------------------------------------------------------------------------------------------- -bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const { CVF_ASSERT(image); image->allocate(m_textureSize.x(), m_textureSize.y()); diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 9ba59cefa4..5e0c827635 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -41,7 +41,7 @@ class RivTernaryScalarMapper : public cvf::Object void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; - bool updateTexture(cvf::TextureImage* image); + bool updateTexture(cvf::TextureImage* image) const; private: cvf::Color3f m_undefScalarColor; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp new file mode 100644 index 0000000000..092929f43b --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp @@ -0,0 +1,244 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivTernaryScalarMapperEffectGenerator.h" + +#include "RivTernaryScalarMapper.h" + +#include "cvfRenderStateBlending.h" +#include "cvfRenderStateCullFace.h" +#include "cvfRenderStateDepth.h" +#include "cvfRenderStateTextureBindings.h" +#include "cvfRenderState_FF.h" +#include "cvfSampler.h" +#include "cvfShaderProgram.h" +#include "cvfShaderProgramGenerator.h" +#include "cvfShaderSourceProvider.h" +#include "cvfTexture.h" +#include "cvfTexture2D_FF.h" + + + +//================================================================================================== +// +// RivTernaryScalarMapperEffectGenerator +// +//================================================================================================== + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivTernaryScalarMapperEffectGenerator::RivTernaryScalarMapperEffectGenerator(const RivTernaryScalarMapper* scalarMapper, caf::PolygonOffset polygonOffset) + : m_undefinedColor(cvf::Color3::GRAY) +{ + m_scalarMapper = scalarMapper; + m_polygonOffset = polygonOffset; + m_opacityLevel = 1.0f; + m_faceCulling = caf::FC_NONE; + m_enableDepthWrite = true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) const +{ + cvf::ref eff = effect; + + cvf::ShaderProgramGenerator gen("ScalarMapperMeshEffectGenerator", cvf::ShaderSourceProvider::instance()); + gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); + gen.addFragmentCode(cvf::ShaderSourceRepository::src_Texture); + gen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); + gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); + + cvf::ref prog = gen.generate(); + eff->setShaderProgram(prog.p()); + + // Result mapping texture + + m_textureImage = new cvf::TextureImage(); + m_scalarMapper->updateTexture(m_textureImage.p()); + + cvf::ref texture = new cvf::Texture(m_textureImage.p()); + cvf::ref sampler = new cvf::Sampler; + sampler->setWrapMode(cvf::Sampler::CLAMP_TO_EDGE); + sampler->setMinFilter(cvf::Sampler::NEAREST); + sampler->setMagFilter(cvf::Sampler::NEAREST); + + cvf::ref texBind = new cvf::RenderStateTextureBindings; + texBind->addBinding(texture.p(), sampler.p(), "u_texture2D"); + eff->setRenderState(texBind.p()); + + // Hardware independent: + + updateCommonEffect(eff.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateForFixedFunctionRendering(cvf::Effect* effect) const +{ + cvf::ref eff = effect; + + cvf::ref mat = new cvf::RenderStateMaterial_FF(cvf::Color3::WHITE); + eff->setRenderState(mat.p()); + + cvf::ref lighting = new cvf::RenderStateLighting_FF; + lighting->enableTwoSided(true); + eff->setRenderState(lighting.p()); + + // Result mapping texture + + m_textureImage = new cvf::TextureImage; + m_scalarMapper->updateTexture(m_textureImage.p()); + + cvf::ref texture = new cvf::Texture2D_FF(m_textureImage.p()); + texture->setWrapMode(cvf::Texture2D_FF::CLAMP); + texture->setMinFilter(cvf::Texture2D_FF::NEAREST); + texture->setMagFilter(cvf::Texture2D_FF::NEAREST); + cvf::ref texMapping = new cvf::RenderStateTextureMapping_FF(texture.p()); + eff->setRenderState(texMapping.p()); + + // Hardware independent: + + updateCommonEffect(eff.p()); + +} + +//-------------------------------------------------------------------------------------------------- +/// It also modifies the texture, and adds two more pixel lines +/// one with a transparent version of the legend color, and one with color for undefined values +//-------------------------------------------------------------------------------------------------- +void RivTernaryScalarMapperEffectGenerator::updateCommonEffect(cvf::Effect* effect) const +{ + CVF_ASSERT(effect); + + if (m_polygonOffset != caf::PO_NONE) + { + cvf::ref polyOffset = EffectGenerator::createAndConfigurePolygonOffsetRenderState(m_polygonOffset); + effect->setRenderState(polyOffset.p()); + } + + // Simple transparency + if (m_opacityLevel < 1.0f) + { + cvf::ref blender = new cvf::RenderStateBlending; + blender->configureTransparencyBlending(); + effect->setRenderState(blender.p()); + } + + // Backface culling + if (m_faceCulling != caf::FC_NONE) + { + cvf::ref faceCulling = new cvf::RenderStateCullFace; + if (m_faceCulling == caf::FC_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::BACK); + } + else if (m_faceCulling == caf::FC_FRONT) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT); + } + else if (m_faceCulling == caf::FC_FRONT_AND_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT_AND_BACK); + } + + effect->setRenderState(faceCulling.p()); + } + + if (!m_enableDepthWrite) + { + cvf::ref depth = new cvf::RenderStateDepth; + depth->enableDepthWrite(false); + effect->setRenderState(depth.p()); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapperEffectGenerator::isEqual(const EffectGenerator* other) const +{ + const RivTernaryScalarMapperEffectGenerator* otherTextureResultEffect = dynamic_cast(other); + + if (otherTextureResultEffect) + { + if (m_scalarMapper.p() == otherTextureResultEffect->m_scalarMapper + && m_polygonOffset == otherTextureResultEffect->m_polygonOffset + && m_opacityLevel == otherTextureResultEffect->m_opacityLevel + && m_undefinedColor == otherTextureResultEffect->m_undefinedColor + && m_faceCulling == otherTextureResultEffect->m_faceCulling + && m_enableDepthWrite == otherTextureResultEffect->m_enableDepthWrite) + { + cvf::ref texImg2 = new cvf::TextureImage; + otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p()); + + return RivTernaryScalarMapperEffectGenerator::isImagesEqual(m_textureImage.p(), texImg2.p()); + } + } + + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::EffectGenerator* RivTernaryScalarMapperEffectGenerator::copy() const +{ + RivTernaryScalarMapperEffectGenerator* scEffGen = new RivTernaryScalarMapperEffectGenerator(m_scalarMapper.p(), m_polygonOffset); + scEffGen->m_textureImage = m_textureImage; + scEffGen->m_opacityLevel = m_opacityLevel; + scEffGen->m_undefinedColor = m_undefinedColor; + scEffGen->m_faceCulling = m_faceCulling; + scEffGen->m_enableDepthWrite = m_enableDepthWrite; + + return scEffGen; +} + + +//-------------------------------------------------------------------------------------------------- +/// Tests whether two texture images are equal. It might in some rare cases not detect the difference +/// but to make the comparison fast only some sampling points are used. If both pointers are NULL, +/// they are considered equal. +//-------------------------------------------------------------------------------------------------- +bool RivTernaryScalarMapperEffectGenerator::isImagesEqual(const cvf::TextureImage* texImg1, const cvf::TextureImage* texImg2) +{ + if (texImg1 == NULL && texImg2 == NULL) return true; + + if (texImg1 != NULL && texImg2 != NULL + && texImg1->height() == texImg2->height() + && texImg1->width() == texImg2->width() + && texImg1->width() > 0 && texImg1->height() > 0 + && texImg1->pixel(0, 0) == texImg2->pixel(0, 0) + && texImg1->pixel(texImg1->width() - 1, texImg1->height() - 1) == texImg2->pixel(texImg1->width() - 1, texImg1->height() - 1) + && texImg1->pixel(texImg1->width() / 2, texImg1->height() / 2) == texImg2->pixel(texImg1->width() / 2, texImg1->height() / 2) + && texImg1->pixel(texImg1->width() / 4, texImg1->height() / 4) == texImg2->pixel(texImg1->width() / 4, texImg1->height() / 4) + && texImg1->pixel(texImg1->width() / 2 + texImg1->width() / 4, texImg1->height() / 2 + texImg1->height() / 4) == texImg2->pixel(texImg1->width() / 2 + texImg1->width() / 4, texImg1->height() / 2 + texImg1->height() / 4) + ) + { + return true; + } + + return false; +} + diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h new file mode 100644 index 0000000000..3d953ef8df --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafEffectGenerator.h" + +class RivTernaryScalarMapper; + +namespace cvf +{ + class TextureImage; +} + +//================================================================================================== +// +// ScalarMapperEffectGenerator +// +//================================================================================================== +class RivTernaryScalarMapperEffectGenerator : public caf::EffectGenerator +{ +public: + RivTernaryScalarMapperEffectGenerator(const RivTernaryScalarMapper* scalarMapper, caf::PolygonOffset polygonOffset); + + void setOpacityLevel(float opacity) { m_opacityLevel = cvf::Math::clamp(opacity, 0.0f, 1.0f); } + void setUndefinedColor(cvf::Color3f color) { m_undefinedColor = color; } + void setFaceCulling(caf::FaceCulling faceCulling) { m_faceCulling = faceCulling; } + void enableDepthWrite(bool enableWrite) { m_enableDepthWrite = enableWrite; } + + +public: + static bool isImagesEqual(const cvf::TextureImage* texImg1, const cvf::TextureImage* texImg2); + +protected: + virtual bool isEqual(const caf::EffectGenerator* other) const; + virtual caf::EffectGenerator* copy() const; + + virtual void updateForShaderBasedRendering(cvf::Effect* effect) const; + virtual void updateForFixedFunctionRendering(cvf::Effect* effect) const; + +private: + void updateCommonEffect(cvf::Effect* effect) const; + +private: + cvf::cref m_scalarMapper; + mutable cvf::ref m_textureImage; + caf::PolygonOffset m_polygonOffset; + float m_opacityLevel; + cvf::Color3f m_undefinedColor; + caf::FaceCulling m_faceCulling; + bool m_enableDepthWrite; +}; + From 24a464ecf9afa7c83c58fffb5d3bb37db471beb1 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 10:50:31 +0200 Subject: [PATCH 232/346] Use texture based ternary visualization --- .../ModelVisualization/RivGridPartMgr.cpp | 63 +++++++++++++------ .../RivTernaryTextureCoordsCreator.cpp | 8 +++ .../RivTernaryTextureCoordsCreator.h | 14 +++-- .../RigTernaryResultAccessor2d.cpp | 14 ++--- .../RigTernaryResultAccessor2d.h | 2 +- 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 99fa9bf715..ee88d87002 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -54,6 +54,8 @@ #include "RigResultAccessorFactory.h" #include "RivResultToTextureMapper.h" #include "RivTextureCoordsCreator.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTernaryScalarMapperEffectGenerator.h" //-------------------------------------------------------------------------------------------------- @@ -229,9 +231,28 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* { if (cellResultSlot->isTernarySaturationSelected()) { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_surfaceGenerator.quadToCellFaceMapper()); + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); + + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); + + //void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces.p()->drawable()); + if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p()); + } + + // void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) + { + caf::PolygonOffset polygonOffset = caf::PO_1; + RivTernaryScalarMapperEffectGenerator scalarEffgen(cellResultSlot->ternaryLegendConfig()->scalarMapper(), polygonOffset); + scalarEffgen.setOpacityLevel(m_opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + m_surfaceFaces->setEffect(scalarEffect.p()); + } } else { @@ -241,26 +262,28 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_surfaceGenerator.quadToCellFaceMapper()); texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - } + applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); + } - if (surfaceFacesColorArray.notNull()) // Ternary result - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_surfaceFaces->setEffect(perVertexColorEffect.p()); - m_surfaceFaces->setPriority(100); - } - else - { - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper ); - } +// if (surfaceFacesColorArray.notNull()) // Ternary result +// { +// cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); +// if (dg) +// { +// dg->setColorArray(surfaceFacesColorArray.p()); +// } +// +// cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); +// m_surfaceFaces->setEffect(perVertexColorEffect.p()); +// +// m_surfaceFaces->setPriority(100); +// } +// else +// { +// applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); +// } } } diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp index 9a8826ec03..10b8bc3aad 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp @@ -70,6 +70,14 @@ RivTernaryTextureCoordsCreator::RivTernaryTextureCoordsCreator( CVF_ASSERT(m_texMapper.notNull()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTernaryTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords) +{ + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h index fcf41f8eb7..751cd51b73 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h @@ -18,13 +18,14 @@ #pragma once +#include "RigTernaryResultAccessor2d.h" +#include "RivTernaryResultToTextureMapper.h" + #include "cvfBase.h" #include "cvfObject.h" #include "cvfArray.h" class RimResultSlot; -class RigTernaryResultAccessor; -class RivTernaryResultToTextureMapper; class RimTernaryLegendConfig; namespace cvf @@ -33,6 +34,9 @@ namespace cvf } +//================================================================================================== +/// +//================================================================================================== class RivTernaryTextureCoordsCreator { public: @@ -42,10 +46,7 @@ class RivTernaryTextureCoordsCreator size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper); - void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) - { - createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); - } + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords); private: static void createTextureCoords(cvf::Vec2fArray* quadTextureCoords, @@ -53,6 +54,7 @@ class RivTernaryTextureCoordsCreator const RigTernaryResultAccessor* resultAccessor, const RivTernaryResultToTextureMapper* texMapper); +private: cvf::cref m_quadMapper; cvf::ref m_resultAccessor; cvf::ref m_texMapper; diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index fbb01f2bf4..d58fe8486a 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -52,29 +52,29 @@ void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { double soil = 0.0; - double swat = 0.0; + double sgas = 0.0; if (m_soilAccessor.notNull()) { soil = m_soilAccessor->cellScalar(gridLocalCellIndex); - if (m_swatAccessor.notNull()) + if (m_sgasAccessor.notNull()) { - swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); } else { - swat = 1.0 - soil - m_sgasAccessor->cellScalar(gridLocalCellIndex); + sgas = 1.0 - soil - m_swatAccessor->cellScalar(gridLocalCellIndex); } } else { - swat = m_swatAccessor->cellScalar(gridLocalCellIndex); + sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); - soil = 1.0 - swat - m_sgasAccessor->cellScalar(gridLocalCellIndex); + soil = 1.0 - sgas - m_swatAccessor->cellScalar(gridLocalCellIndex); } - return cvf::Vec2d(soil, swat); + return cvf::Vec2d(soil, sgas); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h index 47ff642b2e..14f71a72ae 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -32,7 +32,7 @@ class RigTernaryResultAccessor : public RigResultAccessor2d /// Requires two of the arguments to be present void setTernaryResultAccessors(RigResultAccessor* soil, RigResultAccessor* sgas, RigResultAccessor* swat); - /// Returns [SOil, SWat] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated + /// Returns [SOIL, SGAS] regardless of which one of the three is missing. if Soil or SWat is missing, it is calculated /// based on the two others virtual cvf::Vec2d cellScalar(size_t gridLocalCellIndex) const; virtual cvf::Vec2d cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; From 4c00a48a251276e923020414073fc72146d49891 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 11:02:16 +0200 Subject: [PATCH 233/346] Fixed viz bug introduced by new texturing method SHA: a9794815c7bd58b89a94adecf7bd80dddaaad18b --- .../ModelVisualization/RivFaultPartMgr.cpp | 10 ++++++++ .../ModelVisualization/RivGridPartMgr.cpp | 4 ++++ .../RivTextureCoordsCreator.cpp | 23 ++++++++++++++++++- .../RivTextureCoordsCreator.h | 8 +++---- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index ba9cc67315..7421b51684 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -139,6 +139,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_grid->gridIndex(), m_nativeFaultGenerator->cellFromQuadMapper()); + if (!texturer.isValid()) + { + return; + } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); } @@ -182,6 +187,11 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* m_grid->gridIndex(), m_oppositeFaultGenerator->cellFromQuadMapper()); + if (!texturer.isValid()) + { + return; + } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ee88d87002..cb5283ab27 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -260,6 +260,10 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* timeStepIndex, m_grid->gridIndex(), m_surfaceGenerator.quadToCellFaceMapper()); + if (!texturer.isValid()) + { + return; + } texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index e3bca13c4e..2f2ec89591 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -45,7 +45,6 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); m_resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, resTimeStepIdx, cellResultSlot->resultVariable()); - CVF_ASSERT(m_resultAccessor.notNull()); cvf::ref pipeInCellEval = new RigPipeInCellEvaluator(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex), eclipseCase->gridCellToWellIndex(gridIndex)); @@ -56,6 +55,27 @@ RivTextureCoordsCreator::RivTextureCoordsCreator(RimResultSlot* cellResultSlot, CVF_ASSERT(m_texMapper.notNull()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivTextureCoordsCreator::isValid() +{ + if (m_quadMapper.isNull() || m_resultAccessor.isNull() || m_texMapper.isNull()) + { + return false; + } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivTextureCoordsCreator::createTextureCoords(cvf::Vec2fArray* quadTextureCoords) +{ + createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -90,3 +110,4 @@ void RivTextureCoordsCreator::createTextureCoords( } } } + diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h index 0e1a543982..f73cbf8315 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -40,10 +40,9 @@ class RivTextureCoordsCreator size_t gridIndex, const cvf::StructGridQuadToCellFaceMapper* quadMapper); - void createTextureCoords(cvf::Vec2fArray* quadTextureCoords) - { - createTextureCoords(quadTextureCoords, m_quadMapper.p(), m_resultAccessor.p(), m_texMapper.p()); - } + bool isValid(); + + void createTextureCoords(cvf::Vec2fArray* quadTextureCoords); private: @@ -51,7 +50,6 @@ class RivTextureCoordsCreator const cvf::StructGridQuadToCellFaceMapper* quadMapper, const RigResultAccessor* resultAccessor, const RivResultToTextureMapper* texMapper); - cvf::cref m_quadMapper; cvf::ref m_resultAccessor; cvf::ref m_texMapper; From c67b75e992a04ec365a8d97864a8f1bcfe146c6c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:17:09 +0200 Subject: [PATCH 234/346] Fixed transparency for ternary well cells --- .../RivTernaryScalarMapper-Test.cpp | 2 +- .../ModelVisualization/RivTernaryScalarMapper.cpp | 14 ++------------ .../ModelVisualization/RivTernaryScalarMapper.h | 5 +---- .../RivTernaryScalarMapperEffectGenerator.cpp | 6 +++--- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index 6f50cb5717..f9ac412145 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -33,7 +33,7 @@ TEST(TernaryScalarMapperTest, BasicFunctions) cvf::ref scalarMapper = new RivTernaryScalarMapper(cvf::Color3f::GRAY); cvf::ref texImage = new cvf::TextureImage; - scalarMapper->updateTexture(texImage.p()); + scalarMapper->updateTexture(texImage.p(), 1.0); QImage img = cvfqt::Utils::toQImage(*(texImage.p())); diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index 2c5eb14efc..a81a16d2f2 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -28,19 +28,9 @@ RivTernaryScalarMapper::RivTernaryScalarMapper(const cvf::Color3f& undefScalarCo : m_undefScalarColor(undefScalarColor), m_textureSize(128, 256) { - m_opacityLevel = 1.0; - setTernaryRanges(0.0, 1.0, 0.0, 1.0); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivTernaryScalarMapper::setOpacityLevel(float opacityLevel) -{ - m_opacityLevel = opacityLevel; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -77,7 +67,7 @@ cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, b /// A *********** B /// SWAT SOIL //-------------------------------------------------------------------------------------------------- -bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const +bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image, float opacityLevel) const { CVF_ASSERT(image); image->allocate(m_textureSize.x(), m_textureSize.y()); @@ -112,7 +102,7 @@ bool RivTernaryScalarMapper::updateTexture(cvf::TextureImage* image) const image->setPixel(xPos, yPos, clr); // Set opacity - const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * m_opacityLevel)); + const cvf::Color4ub clrOpacity(rByteCol, gByteCol, bByteCol, static_cast(255 * opacityLevel)); image->setPixel(xPos, yPos + halfTextureHeight, clrOpacity); soil_green += xStride; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 5e0c827635..566f499e01 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -36,16 +36,13 @@ class RivTernaryScalarMapper : public cvf::Object public: RivTernaryScalarMapper(const cvf::Color3f& undefScalarColor); - void setOpacityLevel(float opacityLevel); - void setTernaryRanges(double soilLower, double soilUpper, double sgasLower, double sgasUpper); cvf::Vec2f mapToTextureCoord(double soil, double sgas, bool isTransparent) const; - bool updateTexture(cvf::TextureImage* image) const; + bool updateTexture(cvf::TextureImage* image, float opacityLevel) const; private: cvf::Color3f m_undefScalarColor; - float m_opacityLevel; cvf::Vec2ui m_textureSize; double m_rangeMaxSoil; diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp index 092929f43b..76041518bb 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp @@ -74,7 +74,7 @@ void RivTernaryScalarMapperEffectGenerator::updateForShaderBasedRendering(cvf::E // Result mapping texture m_textureImage = new cvf::TextureImage(); - m_scalarMapper->updateTexture(m_textureImage.p()); + m_scalarMapper->updateTexture(m_textureImage.p(), m_opacityLevel); cvf::ref texture = new cvf::Texture(m_textureImage.p()); cvf::ref sampler = new cvf::Sampler; @@ -108,7 +108,7 @@ void RivTernaryScalarMapperEffectGenerator::updateForFixedFunctionRendering(cvf: // Result mapping texture m_textureImage = new cvf::TextureImage; - m_scalarMapper->updateTexture(m_textureImage.p()); + m_scalarMapper->updateTexture(m_textureImage.p(), m_opacityLevel); cvf::ref texture = new cvf::Texture2D_FF(m_textureImage.p()); texture->setWrapMode(cvf::Texture2D_FF::CLAMP); @@ -191,7 +191,7 @@ bool RivTernaryScalarMapperEffectGenerator::isEqual(const EffectGenerator* other && m_enableDepthWrite == otherTextureResultEffect->m_enableDepthWrite) { cvf::ref texImg2 = new cvf::TextureImage; - otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p()); + otherTextureResultEffect->m_scalarMapper->updateTexture(texImg2.p(), m_opacityLevel); return RivTernaryScalarMapperEffectGenerator::isImagesEqual(m_textureImage.p(), texImg2.p()); } From eca4276adbaf7fd8af92d4055de24c0c1b5d7e3a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:55:53 +0200 Subject: [PATCH 235/346] Added scalarMapperUtils for code sharing between grids/faults --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivScalarMapperUtils.cpp | 86 +++++++++++++++++++ .../ModelVisualization/RivScalarMapperUtils.h | 45 ++++++++++ 3 files changed, 133 insertions(+) create mode 100644 ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp create mode 100644 ApplicationCode/ModelVisualization/RivScalarMapperUtils.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index fc4c22bbe0..5079ead6ff 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -28,6 +28,7 @@ ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h +${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -52,6 +53,7 @@ ${CEE_CURRENT_LIST_DIR}RivTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp +${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp new file mode 100644 index 0000000000..e9620f6536 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivScalarMapperUtils.h" + +#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RivTernaryScalarMapper.h" + +#include "cafEffectGenerator.h" + +#include "cvfDrawableGeo.h" +#include "cvfPart.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivScalarMapperUtils::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(part && textureCoords && mapper); + + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(textureCoords); + + cvf::ref scalarEffect = RivScalarMapperUtils::createScalarMapperEffect(mapper, opacityLevel); + part->setEffect(scalarEffect.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(part && textureCoords && mapper); + + cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); + if (dg) dg->setTextureCoordArray(textureCoords); + + cvf::ref scalarEffect = RivScalarMapperUtils::createTernaryScalarMapperEffect(mapper, opacityLevel); + part->setEffect(scalarEffect.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(mapper); + + caf::PolygonOffset polygonOffset = caf::PO_1; + caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + return scalarEffect; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel) +{ + CVF_ASSERT(mapper); + + caf::PolygonOffset polygonOffset = caf::PO_1; + RivTernaryScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); + scalarEffgen.setOpacityLevel(opacityLevel); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); + + return scalarEffect; +} diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h new file mode 100644 index 0000000000..de92c033b0 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -0,0 +1,45 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfArray.h" + +namespace cvf +{ + class ScalarMapper; + class Part; + class Effect; +} + +class RivTernaryScalarMapper; + +//================================================================================================== +/// +//================================================================================================== +class RivScalarMapperUtils +{ +public: + static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel); + static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel); + +private: + static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel); + static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel); +}; + From 03b68e08c3cca0628ba6aeba4e796f54ec9cde1e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 13:59:12 +0200 Subject: [PATCH 236/346] Use RivScalarMapperUtils --- .../ModelVisualization/RivGridPartMgr.cpp | 138 ++++++------------ .../ModelVisualization/RivGridPartMgr.h | 2 - 2 files changed, 42 insertions(+), 98 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index cb5283ab27..b4a3068d13 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -18,11 +18,34 @@ #include "RivGridPartMgr.h" +#include "RiaApplication.h" +#include "RiaPreferences.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigResultAccessorFactory.h" + +#include "RimCase.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" + +#include "RivCellEdgeEffectGenerator.h" +#include "RivResultToTextureMapper.h" +#include "RivScalarMapperUtils.h" +#include "RivSourceInfo.h" +#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTextureCoordsCreator.h" #include "cafEffectGenerator.h" #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" #include "cafProgressInfo.h" + #include "cvfDrawableGeo.h" #include "cvfMath.h" #include "cvfModelBasicList.h" @@ -35,27 +58,8 @@ #include "cvfShaderSourceProvider.h" #include "cvfShaderSourceRepository.h" #include "cvfStructGrid.h" -#include "cvfUniform.h" - -#include "RiaApplication.h" -#include "RiaPreferences.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RimCase.h" -#include "RimCellEdgeResultSlot.h" -#include "RimReservoirCellResultsStorage.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimTernaryLegendConfig.h" -#include "RimWellCollection.h" -#include "RivCellEdgeEffectGenerator.h" -#include "RivSourceInfo.h" #include "cvfStructGridGeometryGenerator.h" -#include "RigResultAccessorFactory.h" -#include "RivResultToTextureMapper.h" -#include "RivTextureCoordsCreator.h" -#include "RivTernaryTextureCoordsCreator.h" -#include "RivTernaryScalarMapperEffectGenerator.h" +#include "cvfUniform.h" //-------------------------------------------------------------------------------------------------- @@ -221,16 +225,15 @@ 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 surfaceFacesColorArray; // Outer surface - if (m_surfaceFaces.notNull()) - { - if (cellResultSlot->isTernarySaturationSelected()) - { + if (m_surfaceFaces.notNull()) + { + if (cellResultSlot->isTernarySaturationSelected()) + { RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), @@ -238,83 +241,26 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - //void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) - { - cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces.p()->drawable()); - if (dg) dg->setTextureCoordArray(m_surfaceFacesTextureCoords.p()); - } - - // void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) - { - caf::PolygonOffset polygonOffset = caf::PO_1; - RivTernaryScalarMapperEffectGenerator scalarEffgen(cellResultSlot->ternaryLegendConfig()->scalarMapper(), polygonOffset); - scalarEffgen.setOpacityLevel(m_opacityLevel); - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - - m_surfaceFaces->setEffect(scalarEffect.p()); - } - } - else - { - RivTextureCoordsCreator texturer(cellResultSlot, - timeStepIndex, - m_grid->gridIndex(), - m_surfaceGenerator.quadToCellFaceMapper()); + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_surfaceGenerator.quadToCellFaceMapper()); if (!texturer.isValid()) { return; } - texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - - applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); - } - - -// if (surfaceFacesColorArray.notNull()) // Ternary result -// { -// cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); -// if (dg) -// { -// dg->setColorArray(surfaceFacesColorArray.p()); -// } -// -// cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); -// m_surfaceFaces->setEffect(perVertexColorEffect.p()); -// -// m_surfaceFaces->setPriority(100); -// } -// else -// { -// applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper); -// } - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -cvf::ref RivGridPartMgr::createScalarMapperEffect(const cvf::ScalarMapper* mapper) -{ - caf::PolygonOffset polygonOffset = caf::PO_1; - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); - scalarEffgen.setOpacityLevel(m_opacityLevel); - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - return scalarEffect; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- - -void RivGridPartMgr::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) -{ - cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); - if (dg) dg->setTextureCoordArray(textureCoords); + texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); - cvf::ref scalarEffect = createScalarMapperEffect(mapper); - part->setEffect(scalarEffect.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 4985a360bf..54bde9110c 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -84,8 +84,6 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); - void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper); - cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, cvf::StructGridGeometryGenerator* surfaceGenerator, size_t timeStepIndex, From 206937555593afb002f94c44b94a7fc1ee363fbb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:28:32 +0200 Subject: [PATCH 237/346] Use shared grid/fault visualization code --- .../ModelVisualization/RivFaultPartMgr.cpp | 160 ++++++------------ .../ModelVisualization/RivFaultPartMgr.h | 1 - 2 files changed, 50 insertions(+), 111 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 7421b51684..eabf868769 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -18,42 +18,32 @@ #include "RivFaultPartMgr.h" -#include "cvfPart.h" -#include "cafEffectGenerator.h" -#include "cvfStructGrid.h" -#include "cvfDrawableGeo.h" -#include "cvfModelBasicList.h" -#include "RivCellEdgeEffectGenerator.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" #include "RiaApplication.h" #include "RiaPreferences.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" #include "RigResultAccessor.h" #include "RimCase.h" -#include "RimWellCollection.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "RimReservoirCellResultsStorage.h" -#include "cvfDrawableText.h" -#include "cvfqtUtils.h" -#include "cvfPrimitiveSetIndexedUInt.h" -#include "cvfPrimitiveSetDirect.h" -#include "RivGridPartMgr.h" -#include "cvfRenderStateDepth.h" -#include "RivSourceInfo.h" #include "RimFaultCollection.h" -#include "RivTextureCoordsCreator.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" #include "RivResultToTextureMapper.h" +#include "RivScalarMapperUtils.h" +#include "RivSourceInfo.h" +#include "RivTernaryScalarMapper.h" +#include "RivTernaryTextureCoordsCreator.h" +#include "RivTextureCoordsCreator.h" +#include "cvfDrawableGeo.h" +#include "cvfDrawableText.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfPrimitiveSetDirect.h" +#include "cvfqtUtils.h" //-------------------------------------------------------------------------------------------------- @@ -109,9 +99,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* updateNNCColors(cellResultSlot); - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); - const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); // If the result is static, only read that. size_t resTimeStepIdx = timeStepIndex; @@ -124,14 +112,18 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* // Faults if (m_nativeFaultFaces.notNull()) { - cvf::ref surfaceFacesColorArray; if (cellResultSlot->isTernarySaturationSelected()) { - surfaceFacesColorArray = new cvf::Color3ubArray; + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_nativeFaultGenerator->cellFromQuadMapper()); - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), - surfaceFacesColorArray.p(), m_nativeFaultGenerator->cellFromQuadMapper()); - } + texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); + + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } else { RivTextureCoordsCreator texturer(cellResultSlot, @@ -145,80 +137,44 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* } texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); - } - - cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); - if (surfaceFacesColorArray.notNull()) - { - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_nativeFaultFaces->setEffect(perVertexColorEffect.p()); - - m_nativeFaultFaces->setPriority(100); - } - else - { - if (dg) dg->setTextureCoordArray(m_nativeFaultFacesTextureCoords.p()); - - cvf::ref scalarEffect = cellResultEffect(mapper, caf::PO_1); - m_nativeFaultFaces->setEffect(scalarEffect.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); } } - if (m_oppositeFaultFaces.notNull()) { - cvf::ref surfaceFacesColorArray; - - if (cellResultSlot->isTernarySaturationSelected()) - { - surfaceFacesColorArray = new cvf::Color3ubArray; - - RivTransmissibilityColorMapper::updateTernarySaturationColorArray(timeStepIndex, cellResultSlot, m_grid.p(), surfaceFacesColorArray.p(), m_oppositeFaultGenerator->cellFromQuadMapper()); - } - else - { - RivTextureCoordsCreator texturer(cellResultSlot, - timeStepIndex, - m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + if (cellResultSlot->isTernarySaturationSelected()) + { + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); + + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); + + const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } + else + { + RivTextureCoordsCreator texturer(cellResultSlot, + timeStepIndex, + m_grid->gridIndex(), + m_oppositeFaultGenerator->cellFromQuadMapper()); if (!texturer.isValid()) { return; } - texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); - } - - cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); - if (surfaceFacesColorArray.notNull()) - { - if (dg) - { - dg->setColorArray(surfaceFacesColorArray.p()); - } - - cvf::ref perVertexColorEffect = RivGridPartMgr::createPerVertexColoringEffect(m_opacityLevel); - m_oppositeFaultFaces->setEffect(perVertexColorEffect.p()); - - m_oppositeFaultFaces->setPriority(100); - } - else - { - if (dg) dg->setTextureCoordArray(m_oppositeFaultFacesTextureCoords.p()); - - // Use a different offset than native fault faces to avoid z-fighting - cvf::ref scalarEffect = cellResultEffect(mapper, caf::PO_2); - - m_oppositeFaultFaces->setEffect(scalarEffect.p()); - } - } + texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); + RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + } + } } //-------------------------------------------------------------------------------------------------- @@ -619,22 +575,6 @@ void RivFaultPartMgr::appendNNCFacesToModel(cvf::ModelBasicList* model) if (m_NNCFaces.notNull()) model->addPart(m_NNCFaces.p()); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivFaultPartMgr::cellResultEffect(const cvf::ScalarMapper* mapper, caf::PolygonOffset polygonOffset) const -{ - CVF_ASSERT(mapper); - - caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); - scalarEffgen.setFaceCulling(faceCullingMode()); - scalarEffgen.setOpacityLevel(m_opacityLevel); - - cvf::ref scalarEffect = scalarEffgen.generateEffect(); - - return scalarEffect; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h index d4a01e8736..44f2a66538 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h @@ -69,7 +69,6 @@ class RivFaultPartMgr : public cvf::Object void updateNNCColors(RimResultSlot* cellResultSlot); - cvf::ref cellResultEffect(const cvf::ScalarMapper* mapper, caf::PolygonOffset polygonOffset) const; caf::FaceCulling faceCullingMode() const; void createLabelWithAnchorLine(const cvf::Part* part); From 301d274eed48406dd37fae76e433fe126e5d4313 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:38:36 +0200 Subject: [PATCH 238/346] Rename --- .../ModelVisualization/RivFaultGeometryGenerator.h | 4 ++-- .../ModelVisualization/RivFaultPartMgr.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index f0e8fd1cc2..f6ec717715 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -53,8 +53,8 @@ class RivFaultGeometryGenerator : public cvf::Object // Mapping between cells and geometry - const cvf::StructGridQuadToCellFaceMapper * cellFromQuadMapper() { return m_quadMapper.p(); } - const cvf::StuctGridTriangleToCellFaceMapper * cellFromTriangleMapper() { return m_triangleMapper.p(); } + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper() { return m_quadMapper.p(); } + const cvf::StuctGridTriangleToCellFaceMapper* triangleToCellFaceMapper() { return m_triangleMapper.p(); } // Generated geometry cvf::ref generateSurface(); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index eabf868769..dc036eb046 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -117,7 +117,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), - m_nativeFaultGenerator->cellFromQuadMapper()); + m_nativeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); @@ -129,7 +129,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), - m_nativeFaultGenerator->cellFromQuadMapper()); + m_nativeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { @@ -150,7 +150,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + m_oppositeFaultGenerator->quadToCellFaceMapper()); texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); @@ -162,7 +162,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* RivTextureCoordsCreator texturer(cellResultSlot, timeStepIndex, m_grid->gridIndex(), - m_oppositeFaultGenerator->cellFromQuadMapper()); + m_oppositeFaultGenerator->quadToCellFaceMapper()); if (!texturer.isValid()) { @@ -215,7 +215,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->cellFromTriangleMapper(); + si->m_cellFaceFromTriangleMapper = m_nativeFaultGenerator->triangleToCellFaceMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); @@ -268,7 +268,7 @@ void RivFaultPartMgr::generatePartGeometry() // Set mapping from triangle face index to cell index cvf::ref si = new RivSourceInfo; - si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->cellFromTriangleMapper(); + si->m_cellFaceFromTriangleMapper = m_oppositeFaultGenerator->triangleToCellFaceMapper(); part->setSourceInfo(si.p()); part->updateBoundingBox(); From 3582d2e30b1262a9e53e042b53655bdad7a97c32 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 14:51:27 +0200 Subject: [PATCH 239/346] Removed unused code --- .../ModelVisualization/RivGridPartMgr.cpp | 101 ------------------ .../ModelVisualization/RivGridPartMgr.h | 18 ---- 2 files changed, 119 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index b4a3068d13..f06db186b1 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -383,104 +383,3 @@ class ScalarDataAccessZeroForAllCells : public cvf::StructGridScalarDataAccess }; -//-------------------------------------------------------------------------------------------------- -/// 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 cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper) -{ - 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()); - - double soilMin = 0.0; - double soilMax = 1.0; - double sgasMin = 0.0; - double sgasMax = 1.0; - double swatMin = 0.0; - double swatMax = 1.0; - - cellResultSlot->ternaryLegendConfig()->ternaryRanges(soilMin, soilMax, sgasMin, sgasMax, swatMin, swatMax); - - cvf::ref dataAccessObjectSoil = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, soilScalarSetIndex); - if (dataAccessObjectSoil.isNull()) - { - dataAccessObjectSoil = new ScalarDataAccessZeroForAllCells; - } - - cvf::ref dataAccessObjectSgas = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, sgasScalarSetIndex); - if (dataAccessObjectSgas.isNull()) - { - dataAccessObjectSgas = new ScalarDataAccessZeroForAllCells; - } - - cvf::ref dataAccessObjectSwat = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, swatScalarSetIndex); - if (dataAccessObjectSwat.isNull()) - { - dataAccessObjectSwat = new ScalarDataAccessZeroForAllCells; - } - - double soilRange = soilMax - soilMin; - double soilFactor = 255.0 / soilRange; - - double sgasRange = sgasMax - sgasMin; - double sgasFactor = 255.0 / sgasRange; - - double swatRange = swatMax - swatMin; - double swatFactor = 255.0 / swatRange; - - size_t numVertices = quadToCellFaceMapper->quadCount()*4; - - colorArray->resize(numVertices); - - cvf::Color3ub ternaryColorByte; - double v, vNormalized; - -#pragma omp parallel for private(ternaryColorByte, v, vNormalized) - for (int quadIdx = 0; quadIdx < static_cast(quadToCellFaceMapper->quadCount()); quadIdx++) - { - size_t gridCellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - - { - v = dataAccessObjectSgas->cellScalar(gridCellIndex); - vNormalized = (v - sgasMin) * sgasFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.r() = vNormalized; - } - - { - v = dataAccessObjectSoil->cellScalar(gridCellIndex); - vNormalized = (v - soilMin) * soilFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.g() = vNormalized; - } - - { - v = dataAccessObjectSwat->cellScalar(gridCellIndex); - vNormalized = (v - swatMin) * swatFactor; - - vNormalized = cvf::Math::clamp(vNormalized, 0.0, 255.0); - ternaryColorByte.b() = vNormalized; - } - - size_t j; - for (j = 0; j < 4; j++) - { - colorArray->set(quadIdx*4 + j, ternaryColorByte); - } - } -} diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 54bde9110c..711d276135 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -37,24 +37,6 @@ class RimCellEdgeResultSlot; -//================================================================================================== -/// -/// -//================================================================================================== -class RivTransmissibilityColorMapper -{ -public: - - static void updateTernarySaturationColorArray( - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - const RigGridBase* grid, - cvf::Color3ubArray* colorArray, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper); -}; - - - //================================================================================================== /// /// RivGridGeometry: Class to handle visualization structures that embodies a specific grid at a specific time step. From 6e2dffc399f89707285ddd112eaf9439f21b5d58 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 11 Aug 2014 15:21:37 +0200 Subject: [PATCH 240/346] Linux include fix --- ApplicationCode/ModelVisualization/RivScalarMapperUtils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index de92c033b0..f807585422 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -18,6 +18,7 @@ #pragma once +#include "cvfBase.h" #include "cvfArray.h" namespace cvf From 20d70d05655be7658592d4e38873b872fcb78d91 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 10:54:46 +0200 Subject: [PATCH 241/346] Bugfix statistics: Trigger loading of dataset before creating a result accessor --- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 778b4d19c0..66b6f25a30 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -196,6 +196,9 @@ void RimStatisticsCaseEvaluator::evaluateForResults(const QList& result { RimCase* sourceCase = m_sourceCases.at(caseIdx); + // Trigger loading of dataset + sourceCase->results(poroModel)->findOrLoadScalarResultForTimeStep(resultType, resultName, dataAccessTimeStepIndex); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(sourceCase->reservoirData(), gridIdx, poroModel, dataAccessTimeStepIndex, resultName, resultType); if (resultAccessor.notNull()) { From 0941834da90f7856b87893541d3aa554e794e758 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 11:16:46 +0200 Subject: [PATCH 242/346] Added RigHugeValResultAccessor Linux: Added include of cmath for define of HUGE_VAL --- .../ReservoirDataModel/RigResultAccessor.cpp | 18 ++++++++++++++++++ .../ReservoirDataModel/RigResultAccessor.h | 9 +++++++++ .../RigResultAccessorFactory.cpp | 8 +++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp index 160c2b9abe..aed929abea 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp @@ -17,3 +17,21 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RigResultAccessor.h" + +#include // Needed for HUGE_VAL on Linux + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigHugeValResultAccessor::cellScalar(size_t gridLocalCellIndex) const +{ + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigHugeValResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + return cellScalar(gridLocalCellIndex); +} diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index 7bf45e048c..92f860037d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -35,3 +35,12 @@ class RigResultAccessor : public cvf::Object virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const = 0; }; +//================================================================================================== +/// +//================================================================================================== +class RigHugeValResultAccessor : public RigResultAccessor +{ +public: + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 71f20f5083..38bb2cf17d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -144,9 +144,10 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa if (!grid) return NULL; std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(resultIndex); + if (timeStepIndex >= scalarSetResults.size()) { - return NULL; + return new RigHugeValResultAccessor; } std::vector* resultValues = NULL; @@ -155,6 +156,11 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa resultValues = &(scalarSetResults[timeStepIndex]); } + if (!resultValues || resultValues->size() == 0) + { + return new RigHugeValResultAccessor; + } + bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(resultIndex); if (useGlobalActiveIndex) { From debd17a3abc57a9d43e871bcc171e76376012c3d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 12:58:03 +0200 Subject: [PATCH 243/346] Removed unused code --- .../ModelVisualization/RivGridPartMgr.cpp | 47 ------------------- .../ModelVisualization/RivGridPartMgr.h | 2 - 2 files changed, 49 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index f06db186b1..ad4017a1d8 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -318,53 +318,6 @@ RivGridPartMgr::~RivGridPartMgr() #endif } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivGridPartMgr::createPerVertexColoringEffect(float opacity) -{ - cvf::ref colorArrayEffect = new cvf::Effect; - - if (RiaApplication::instance()->useShaders()) - { - cvf::ShaderProgramGenerator gen("PerVertexColor", cvf::ShaderSourceProvider::instance()); - gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); - gen.addFragmentCode(cvf::ShaderSourceRepository::src_VaryingColorGlobalAlpha); - gen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); - gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); - - cvf::ref m_shaderProg = gen.generate(); - m_shaderProg->setDefaultUniform(new cvf::UniformFloat("u_alpha", opacity)); - - colorArrayEffect->setShaderProgram(m_shaderProg.p()); - } - else - { - cvf::ref mat = new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE); - mat->setAlpha(opacity); - mat->enableColorMaterial(true); - colorArrayEffect->setRenderState(mat.p()); - - cvf::ref lighting = new cvf::RenderStateLighting_FF; - lighting->enableTwoSided(true); - colorArrayEffect->setRenderState(lighting.p()); - } - - // Simple transparency - if (opacity < 1.0f) - { - cvf::ref blender = new cvf::RenderStateBlending; - blender->configureTransparencyBlending(); - colorArrayEffect->setRenderState(blender.p()); - } - - caf::PolygonOffset polygonOffset = caf::PO_1; - cvf::ref polyOffset = caf::EffectGenerator::createAndConfigurePolygonOffsetRenderState(polygonOffset); - colorArrayEffect->setRenderState(polyOffset.p()); - - return colorArrayEffect; -} - //-------------------------------------------------------------------------------------------------- /// Helper class used to provide zero for all cells diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index 711d276135..ea79932791 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -62,8 +62,6 @@ class RivGridPartMgr: public cvf::Object void appendPartsToModel(cvf::ModelBasicList* model); - static cvf::ref createPerVertexColoringEffect(float opacity); - private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); void updateCellEdgeResultColorOnPart(cvf::Part* facePart, From 245573e03c5d64d52b95a386cc6be4981ee1beb2 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 14:36:15 +0200 Subject: [PATCH 244/346] Cell edge visualization can now handle individual per face center values --- .../RivCellEdgeEffectGenerator.cpp | 135 ++++++++++-------- .../RivCellEdgeEffectGenerator.h | 16 +++ .../RigResultAccessorFactory.cpp | 5 + .../RigResultAccessorFactory.h | 13 +- 4 files changed, 104 insertions(+), 65 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index bbaf9eafb6..8714dbeaee 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -66,6 +66,9 @@ #include "RimWellCollection.h" #include "Rim3dOverlayInfoConfig.h" #include "cvfStructGridScalarDataAccess.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RigCellEdgeResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// @@ -79,7 +82,19 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t gridIndex, float opacityLevel) { - const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + const RigGridBase* grid = dynamic_cast(generator->activeGrid()); + CVF_ASSERT(grid != NULL); + + // Create result access objects + + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, grid); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); + + + const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -105,48 +120,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - cvf::ref cellCenterDataAccessObject = NULL; - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - cellCenterDataAccessObject = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, timeStepIndex, cellResultSlot->gridScalarIndex()); - } - - CVF_ASSERT(cellEdgeResultSlot->hasResult()); - - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - - cvf::Collection cellEdgeDataAccessObjects; - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - cvf::ref daObj; - - if (resultIndices[cubeFaceIdx] != cvf::UNDEFINED_SIZE_T) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - // TODO: Now hardcoded matrix results, should it be possible to use fracture results? - daObj = eclipseCase->TO_BE_DELETED_resultAccessor(grid, RifReaderInterface::MATRIX_RESULTS, 0, resultIndices[cubeFaceIdx]); - } - - cellEdgeDataAccessObjects.push_back(daObj.p()); - } - + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); const std::vector* isWellPipeVisible = NULL; @@ -173,18 +147,12 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color size_t cellIndex = quadToCellFace->cellIndex(quadIdx); - { - double scalarValue = HUGE_VAL; - - if (cellCenterDataAccessObject.notNull()) - { - scalarValue = cellCenterDataAccessObject->cellScalar(cellIndex); - } + cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); if (scalarValue != HUGE_VAL) { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; // If we are dealing with wellcells, the default is transparent. // we need to make cells opaque if there are no wellpipe through them. @@ -211,17 +179,12 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); - size_t cubeFaceIdx; float edgeColor; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) { edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - double scalarValue = HUGE_VAL; - if (cellEdgeDataAccessObjects[cubeFaceIdx].notNull()) - { - scalarValue = cellEdgeDataAccessObjects[cubeFaceIdx]->cellScalar(cellIndex); - } + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) { @@ -241,7 +204,6 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - //faceIntAttribute->setIntegerTypeConversion(cvf::VertexAttribute::DIRECT_FLOAT); geo->setVertexAttribute(faceIntAttribute.p()); geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); @@ -252,6 +214,61 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 8fea369a1c..c670f414a6 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -29,6 +29,8 @@ namespace cvf class RimCellEdgeResultSlot; class RimResultSlot; class RigGridBase; +class RigResultAccessor; +class RigCaseData; class RivCellEdgeGeometryGenerator @@ -41,6 +43,20 @@ class RivCellEdgeGeometryGenerator cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); + +private: + static cvf::ref createCellCenterResultAccessor( + RimResultSlot* cellResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); + + static cvf::ref createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); }; /* diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 38bb2cf17d..93cffaa93b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -138,6 +138,11 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa size_t timeStepIndex, size_t resultIndex) { + if (resultIndex == cvf::UNDEFINED_SIZE_T) + { + return new RigHugeValResultAccessor; + } + if (!eclipseCase) return NULL; RigGridBase* grid = eclipseCase->grid(gridIndex); diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 6c1d890dd7..55c8fff48f 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -45,6 +45,13 @@ class RigResultAccessorFactory const QString& uiResultName, RimDefines::ResultCatType resultType); + static cvf::ref + createResultAccessor(RigCaseData* eclipseCase, + size_t gridIndex, + RifReaderInterface::PorosityModelResultType porosityModel, + size_t timeStepIndex, + size_t resultIndex); + // TO BE DELETED static cvf::ref @@ -63,12 +70,6 @@ class RigResultAccessorFactory size_t timeStepIndex, const QString& resultName); - static cvf::ref - createResultAccessor(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t resultIndex); }; From d8cefc1023b114dd5b075fc0cb3d69206c0f06f1 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Tue, 12 Aug 2014 15:02:19 +0200 Subject: [PATCH 245/346] fix build on my machine (openSUSE 13.1), it broke because the CheckCSourceCompiles CMake module was not included... --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a41fddb4da..1ed8203cdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required (VERSION 2.8) +include (CheckCSourceCompiles) project (ResInsight) set (VIZ_MODULES_FOLDER_NAME Fwk/VizFwk) From 67e12e3f718c7393c985ca800c79f6bbc627888a Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 12 Aug 2014 15:05:44 +0200 Subject: [PATCH 246/346] Cleaned up includes --- .../RivCellEdgeEffectGenerator.cpp | 55 ++++--------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 8714dbeaee..195f75f2aa 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -18,57 +18,24 @@ #include "RiaStdInclude.h" -#include "RivCellEdgeEffectGenerator.h" - -#include "cvfBase.h" -#include "cvfAssert.h" -#include "cvfDrawableGeo.h" -#include "cvfVertexAttribute.h" -#include "cvfStructGridGeometryGenerator.h" -#include "cvfScalarMapperUniformLevels.h" - -#include "cvfShaderProgramGenerator.h" -#include "cvfShaderSourceProvider.h" -#include "cvfqtUtils.h" -#include "cvfShaderProgram.h" -#include "cvfRenderStateCullFace.h" - -#include "cvfTextureImage.h" -#include "cvfTexture.h" -#include "cvfSampler.h" -#include "cvfScalarMapper.h" -#include "cafEffectGenerator.h" - -#include - -#include -#include +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigCellEdgeResultAccessor.h" +#include "RigGridBase.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "RimCase.h" - +#include "RimCellEdgeResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" +#include "RimWellCollection.h" -#include "RigGridBase.h" -#include "RigMainGrid.h" -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RigActiveCellInfo.h" +#include "RivCellEdgeEffectGenerator.h" -#include "RimReservoirCellResultsStorage.h" +#include "cvfStructGridGeometryGenerator.h" +#include "cvfqtUtils.h" -#include "cafPdmFieldCvfMat4d.h" -#include "cafPdmFieldCvfColor.h" -#include "RimResultSlot.h" -#include "RimCellEdgeResultSlot.h" -#include "RimCellRangeFilterCollection.h" -#include "RimCellPropertyFilterCollection.h" -#include "RimWellCollection.h" -#include "Rim3dOverlayInfoConfig.h" -#include "cvfStructGridScalarDataAccess.h" -#include "RigResultAccessor.h" -#include "RigResultAccessorFactory.h" -#include "RigCellEdgeResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// From ef3c4631289cb8b433e0f9d64f1ec8a132462734 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 09:19:47 +0200 Subject: [PATCH 247/346] Added cell edge with 2d texture coord support --- ApplicationCode/Resources/ResInsight.qrc | 1 + .../Resources/vs_2dTextureCellFace.glsl | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 ApplicationCode/Resources/vs_2dTextureCellFace.glsl diff --git a/ApplicationCode/Resources/ResInsight.qrc b/ApplicationCode/Resources/ResInsight.qrc index 73cb02a712..384db079ed 100644 --- a/ApplicationCode/Resources/ResInsight.qrc +++ b/ApplicationCode/Resources/ResInsight.qrc @@ -48,5 +48,6 @@ fs_CellFace.glsl vs_CellFace.glsl + vs_2dTextureCellFace.glsl diff --git a/ApplicationCode/Resources/vs_2dTextureCellFace.glsl b/ApplicationCode/Resources/vs_2dTextureCellFace.glsl new file mode 100644 index 0000000000..a42ba28a43 --- /dev/null +++ b/ApplicationCode/Resources/vs_2dTextureCellFace.glsl @@ -0,0 +1,130 @@ +uniform sampler2D u_edgeTexture2D; +uniform sampler2D u_cellTexture2D; + +attribute vec2 a_localCoord; +attribute float a_face; + +attribute vec2 a_cellTextureCoord; +attribute float a_colorPosI; +attribute float a_colorNegI; +attribute float a_colorPosJ; +attribute float a_colorNegJ; +attribute float a_colorPosK; +attribute float a_colorNegK; + +varying vec2 v_localCoord; +varying vec4 v_cellColor; +varying vec4 v_bottomColor; +varying vec4 v_rightColor; +varying vec4 v_topColor; +varying vec4 v_leftColor; + +// Native visualization lib stuff +uniform mat4 cvfu_modelViewProjectionMatrix; +uniform mat4 cvfu_modelViewMatrix; +uniform mat3 cvfu_normalMatrix; + +attribute vec4 cvfa_vertex; +attribute vec3 cvfa_normal; + +varying vec3 v_ecPosition; +varying vec3 v_ecNormal; +// End native vz stuff + +#define POS_I 0.0 +#define NEG_I 1.0 +#define POS_J 2.0 +#define NEG_J 3.0 +#define POS_K 4.0 +#define NEG_K 5.0 + +// +// 7---------6 +// /| /| |k +// / | / | | /j +// 4---------5 | |/ +// | 3------|--2 *---i +// | / | / +// |/ |/ +// 0---------1 +// +// Face layout expected +// POS_I 1, 2, 6, 5 +// NEG_I 0, 4, 7, 3 +// POS_J 3, 7, 6, 2 +// NEG_J 0, 1, 5, 4 +// POS_K 4, 5, 6, 7 +// NEG_K 0, 3, 2, 1 +// + +vec4 getColorFromTextureCoord(float textureCoord, vec4 cellColor) +{ + if (textureCoord < 0.0) + return cellColor; + else + return texture2D(u_edgeTexture2D, vec2(textureCoord, 0.5f )); +} + +void main() +{ + v_localCoord = a_localCoord; + + v_cellColor = texture2D(u_cellTexture2D, a_cellTextureCoord); + + if (a_face == POS_I) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + } + else if (a_face == NEG_I) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + } + else if (a_face == POS_J ) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + } + else if (a_face == NEG_J) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegK, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosK, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + } + else if (a_face == POS_K ) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + } + else if (a_face == NEG_K) + { + v_bottomColor = getColorFromTextureCoord(a_colorNegI, v_cellColor); + v_rightColor = getColorFromTextureCoord(a_colorPosJ, v_cellColor); + v_topColor = getColorFromTextureCoord(a_colorPosI, v_cellColor); + v_leftColor = getColorFromTextureCoord(a_colorNegJ, v_cellColor); + } + else + { + v_bottomColor = v_cellColor; + v_rightColor = v_cellColor; + v_topColor = v_cellColor; + v_leftColor = v_cellColor; + } + + // Transforms vertex position and normal vector to eye space + v_ecPosition = (cvfu_modelViewMatrix * cvfa_vertex).xyz; + v_ecNormal = cvfu_normalMatrix * cvfa_normal; + + gl_Position = cvfu_modelViewProjectionMatrix*cvfa_vertex; +} + From 2c903a0d188ee9b2f5616a935dd9b6db27d79007 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 09:24:04 +0200 Subject: [PATCH 248/346] Cell edge now handles also ternary --- .../RivCellEdgeEffectGenerator.cpp | 324 +++++++++++++----- .../RivCellEdgeEffectGenerator.h | 21 +- .../ModelVisualization/RivGridPartMgr.cpp | 27 +- 3 files changed, 275 insertions(+), 97 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 195f75f2aa..c46ec71451 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -18,6 +18,8 @@ #include "RiaStdInclude.h" +#include "RivCellEdgeEffectGenerator.h" + #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigCellEdgeResultAccessor.h" @@ -31,10 +33,12 @@ #include "RimResultSlot.h" #include "RimWellCollection.h" -#include "RivCellEdgeEffectGenerator.h" +#include "RivTernaryScalarMapper.h" +#include "RimTernaryLegendConfig.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfqtUtils.h" +#include "RivTernaryTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -85,7 +89,7 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); } - cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); @@ -112,39 +116,42 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); - float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - size_t cellIndex = quadToCellFace->cellIndex(quadIdx); - { + size_t cellIndex = quadToCellFace->cellIndex(quadIdx); + { cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); - double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); - - if (scalarValue != HUGE_VAL) - { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - // If we are dealing with wellcells, the default is transparent. - // we need to make cells opaque if there are no wellpipe through them. - if (opacityLevel < 1.0f) - { - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if ( !(*isWellPipeVisible)[wellIndex]) - { - cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" - } - } - } - } - else - { - cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. - } - } + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); + + { + float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color + if (scalarValue != HUGE_VAL) + { + cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + // If we are dealing with wellcells, the default is transparent. + // we need to make cells opaque if there are no wellpipe through them. + if (opacityLevel < 1.0f) + { + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if (!(*isWellPipeVisible)[wellIndex]) + { + cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" + } + } + } + } + else + { + cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. + } + + cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); + } + } - cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); float edgeColor; for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) @@ -181,32 +188,6 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) -{ - cvf::ref resultAccessor = NULL; - - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); - } - - if (resultAccessor.isNull()) - { - resultAccessor = new RigHugeValResultAccessor; - } - - return resultAccessor; -} //-------------------------------------------------------------------------------------------------- /// @@ -236,6 +217,134 @@ cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterRe return cellEdgeResultAccessor; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, cvf::StructGridGeometryGenerator* generator, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + const RigGridBase* grid = dynamic_cast(generator->activeGrid()); + CVF_ASSERT(grid != NULL); + + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); + + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper = generator->quadToCellFaceMapper(); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; + vCellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + grid->gridIndex(), + quadToCellFaceMapper); + + texturer.createTextureCoords(vCellColorTextureCoordArray.p()); + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + + @@ -244,11 +353,10 @@ cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterRe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper, const cvf::ScalarMapper* cellScalarMapper) +CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper) { CVF_ASSERT(edgeScalarMapper != NULL); - m_cellScalarMapper = cellScalarMapper; m_edgeScalarMapper = edgeScalarMapper; m_cullBackfaces = false; @@ -256,6 +364,21 @@ CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeSc m_defaultCellColor = cvf::Color3f(cvf::Color3::WHITE); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void CellEdgeEffectGenerator::setScalarMapper(const cvf::ScalarMapper* cellScalarMapper) +{ + m_cellScalarMapper = cellScalarMapper; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void CellEdgeEffectGenerator::setTernaryScalarMapper(const RivTernaryScalarMapper* ternaryScalarMapper) +{ + m_ternaryCellScalarMapper = ternaryScalarMapper; +} //-------------------------------------------------------------------------------------------------- /// @@ -267,7 +390,8 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const if (otherCellFaceEffectGenerator && m_cellScalarMapper.p() == otherCellFaceEffectGenerator->m_cellScalarMapper.p() && m_edgeScalarMapper.p() == otherCellFaceEffectGenerator->m_edgeScalarMapper.p() - && m_cullBackfaces == otherCellFaceEffectGenerator->m_cullBackfaces + && m_ternaryCellScalarMapper.p() == otherCellFaceEffectGenerator->m_ternaryCellScalarMapper.p() + && m_cullBackfaces == otherCellFaceEffectGenerator->m_cullBackfaces && m_opacityLevel == otherCellFaceEffectGenerator->m_opacityLevel && m_undefinedColor == otherCellFaceEffectGenerator->m_undefinedColor && m_defaultCellColor == otherCellFaceEffectGenerator->m_defaultCellColor @@ -300,7 +424,9 @@ bool CellEdgeEffectGenerator::isEqual(const EffectGenerator* other) const //-------------------------------------------------------------------------------------------------- caf::EffectGenerator* CellEdgeEffectGenerator::copy() const { - CellEdgeEffectGenerator * newEffect = new CellEdgeEffectGenerator(m_edgeScalarMapper.p(), m_cellScalarMapper.p()); + CellEdgeEffectGenerator * newEffect = new CellEdgeEffectGenerator(m_edgeScalarMapper.p()); + newEffect->setScalarMapper(m_cellScalarMapper.p()); + newEffect->setTernaryScalarMapper(m_ternaryCellScalarMapper.p()); newEffect->m_edgeTextureImage = m_edgeTextureImage; newEffect->m_cellTextureImage = m_cellTextureImage; @@ -317,36 +443,54 @@ caf::EffectGenerator* CellEdgeEffectGenerator::copy() const //-------------------------------------------------------------------------------------------------- void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) const { - cvf::ref eff = effect; + cvf::ref eff = effect; - // Set up shader program + // Set up shader program - cvf::ShaderProgramGenerator shaderGen("CellEdgeFaceShaderProgramGenerator", cvf::ShaderSourceProvider::instance()); - { - QFile data(":/Shader/fs_CellFace.glsl"); - if (data.open(QFile::ReadOnly)) - { - QTextStream in(&data); + cvf::ShaderProgramGenerator shaderGen("CellEdgeFaceShaderProgramGenerator", cvf::ShaderSourceProvider::instance()); + { + QFile data(":/Shader/fs_CellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); - QString data = in.readAll(); - cvf::String cvfString = cvfqt::Utils::toString(data); + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); - shaderGen.addFragmentCode(cvfString); - } - } + shaderGen.addFragmentCode(cvfString); + } + } - { - QFile data(":/Shader/vs_CellFace.glsl"); - if (data.open(QFile::ReadOnly)) - { - QTextStream in(&data); + if (m_ternaryCellScalarMapper.notNull()) + { + { + QFile data(":/Shader/vs_2dTextureCellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); - QString data = in.readAll(); - cvf::String cvfString = cvfqt::Utils::toString(data); + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); - shaderGen.addVertexCode(cvfString); - } - } + shaderGen.addVertexCode(cvfString); + } + } + } + else + { + { + QFile data(":/Shader/vs_CellFace.glsl"); + if (data.open(QFile::ReadOnly)) + { + QTextStream in(&data); + + QString data = in.readAll(); + cvf::String cvfString = cvfqt::Utils::toString(data); + + shaderGen.addVertexCode(cvfString); + } + } + } shaderGen.addFragmentCode(caf::CommonShaderSources::light_AmbientDiffuse()); shaderGen.addFragmentCode(cvf::ShaderSourceRepository::fs_Standard); @@ -361,7 +505,12 @@ void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) cvf::ref modifiedCellTextImage; m_edgeScalarMapper->updateTexture(m_edgeTextureImage.p()); - if (m_cellScalarMapper.notNull()) + if (m_ternaryCellScalarMapper.notNull()) + { + m_ternaryCellScalarMapper->updateTexture(m_cellTextureImage.p(), m_opacityLevel); + modifiedCellTextImage = m_cellTextureImage; + } + else if (m_cellScalarMapper.notNull()) { m_cellScalarMapper->updateTexture(m_cellTextureImage.p()); modifiedCellTextImage = caf::ScalarMapperEffectGenerator::addAlphaAndUndefStripes(m_cellTextureImage.p(), m_undefinedColor, m_opacityLevel); @@ -422,3 +571,4 @@ void CellEdgeEffectGenerator::updateForFixedFunctionRendering(cvf::Effect* effec surfaceGen.updateEffect(effect); } + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index c670f414a6..40e6fe4dfd 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -31,7 +31,7 @@ class RimResultSlot; class RigGridBase; class RigResultAccessor; class RigCaseData; - +class RivTernaryScalarMapper; class RivCellEdgeGeometryGenerator { @@ -44,6 +44,15 @@ class RivCellEdgeGeometryGenerator size_t gridIndex, float opacityLevel); + static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + cvf::StructGridGeometryGenerator* generator, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + private: static cvf::ref createCellCenterResultAccessor( RimResultSlot* cellResultSlot, @@ -134,7 +143,10 @@ class RivCellEdgeGeometryGenerator class CellEdgeEffectGenerator : public caf::EffectGenerator { public: - CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper, const cvf::ScalarMapper* cellScalarMapper); + CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeScalarMapper); + + void setScalarMapper(const cvf::ScalarMapper* cellScalarMapper); + void setTernaryScalarMapper(const RivTernaryScalarMapper* ternaryScalarMapper); void setOpacityLevel(float opacity) { m_opacityLevel = cvf::Math::clamp(opacity, 0.0f , 1.0f ); } void setUndefinedColor(cvf::Color3f color) { m_undefinedColor = color; } @@ -154,10 +166,11 @@ class CellEdgeEffectGenerator : public caf::EffectGenerator cvf::cref m_cellScalarMapper; mutable cvf::ref m_cellTextureImage; - float m_opacityLevel; + cvf::cref m_ternaryCellScalarMapper; + + float m_opacityLevel; bool m_cullBackfaces; cvf::Color3f m_undefinedColor; cvf::Color3f m_defaultCellColor; - }; diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index ad4017a1d8..f941f86e8a 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -285,16 +285,31 @@ void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, { if (facePart) { - cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); + + cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); if (dg) { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel ); + if (cellResultSlot->isTernarySaturationSelected()) + { + RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - cvf::ScalarMapper* cellScalarMapper = NULL; - if (cellResultSlot->hasResult()) cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); + } + else + { + if (cellResultSlot->hasResult()) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); + + cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cellFaceEffectGen.setScalarMapper(cellScalarMapper); + } + } - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper(), cellScalarMapper); cellFaceEffectGen.setOpacityLevel(m_opacityLevel); cellFaceEffectGen.setDefaultCellColor(m_defaultColor); From 7e5c46cf59b7f8f22d4a0f760c23a4f1ec034bb0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 10:45:09 +0200 Subject: [PATCH 249/346] Added support for cell edge on faults --- .../RivCellEdgeEffectGenerator.cpp | 102 ++++++++---------- .../RivCellEdgeEffectGenerator.h | 9 +- .../ModelVisualization/RivFaultPartMgr.cpp | 23 ++++ .../ModelVisualization/RivGridPartMgr.cpp | 59 ++-------- .../ModelVisualization/RivGridPartMgr.h | 6 +- .../RivReservoirPartMgr.cpp | 12 +++ .../ModelVisualization/RivReservoirPartMgr.h | 4 +- .../RivReservoirViewPartMgr.cpp | 11 +- .../RivReservoirViewPartMgr.h | 6 +- .../RivScalarMapperUtils.cpp | 51 ++++++++- .../ModelVisualization/RivScalarMapperUtils.h | 13 +++ .../ProjectDataModel/RimReservoirView.cpp | 16 ++- 12 files changed, 191 insertions(+), 121 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index c46ec71451..358110545d 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -20,6 +20,7 @@ #include "RivCellEdgeEffectGenerator.h" + #include "RigCaseCellResultsData.h" #include "RigCaseData.h" #include "RigCellEdgeResultAccessor.h" @@ -31,14 +32,14 @@ #include "RimCellEdgeResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" #include "RimWellCollection.h" #include "RivTernaryScalarMapper.h" -#include "RimTernaryLegendConfig.h" +#include "RivTernaryTextureCoordsCreator.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfqtUtils.h" -#include "RivTernaryTextureCoordsCreator.h" //-------------------------------------------------------------------------------------------------- @@ -48,26 +49,20 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, - cvf::DrawableGeo* geo, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) { RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); CVF_ASSERT(eclipseCase != NULL); - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - // Create result access objects - cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, grid); - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); - + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - const cvf::StructGridQuadToCellFaceMapper* quadToCellFace = generator->quadToCellFaceMapper(); - - size_t vertexCount = geo->vertexArray()->size(); + size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; cvf::ref localCoords = new cvf::Vec2fArray; @@ -111,14 +106,14 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFace->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFace->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx) ); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx) ); - size_t cellIndex = quadToCellFace->cellIndex(quadIdx); + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); { - cvf::StructGridInterface::FaceType cellFace = quadToCellFace->cellFace(quadIdx); + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); { @@ -192,45 +187,14 @@ void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid) -{ - cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); - { - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); - cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); - } - } - - return cellEdgeResultAccessor; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, cvf::StructGridGeometryGenerator* generator, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) { RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); CVF_ASSERT(eclipseCase != NULL); - const RigGridBase* grid = dynamic_cast(generator->activeGrid()); - CVF_ASSERT(grid != NULL); - - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, grid); - - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper = generator->quadToCellFaceMapper(); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); size_t vertexCount = geo->vertexArray()->size(); size_t quadCount = vertexCount / 4; @@ -261,7 +225,7 @@ void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), timeStepIndex, - grid->gridIndex(), + gridIndex, quadToCellFaceMapper); texturer.createTextureCoords(vCellColorTextureCoordArray.p()); @@ -317,6 +281,34 @@ void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 40e6fe4dfd..093243ad76 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -22,8 +22,8 @@ namespace cvf { - class StructGridGeometryGenerator; class DrawableGeo; + class StructGridQuadToCellFaceMapper; } class RimCellEdgeResultSlot; @@ -33,21 +33,22 @@ class RigResultAccessor; class RigCaseData; class RivTernaryScalarMapper; + class RivCellEdgeGeometryGenerator { public: static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, - cvf::DrawableGeo* geo, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - cvf::StructGridGeometryGenerator* generator, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel); diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index dc036eb046..6963f62674 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -182,7 +182,30 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* //-------------------------------------------------------------------------------------------------- void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { + if (m_nativeFaultFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_nativeFaultGenerator->quadToCellFaceMapper(), + m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + + m_nativeFaultFaces->setEffect(eff.p()); + } + } + if (m_oppositeFaultFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_oppositeFaultFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_oppositeFaultGenerator->quadToCellFaceMapper(), m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + + m_oppositeFaultFaces->setEffect(eff.p()); + } + } } const int priFaultGeo = 1; diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index f941f86e8a..6dc24bd149 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -268,56 +268,17 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* //-------------------------------------------------------------------------------------------------- void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { - updateCellEdgeResultColorOnPart( - m_surfaceFaces.p(), - &m_surfaceGenerator, - timeStepIndex, cellResultSlot, cellEdgeResultSlot); - -} -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivGridPartMgr::updateCellEdgeResultColorOnPart( cvf::Part* facePart, - cvf::StructGridGeometryGenerator* surfaceGenerator, - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot) -{ - if (facePart) - { - CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); - - cvf::DrawableGeo* dg = dynamic_cast(facePart->drawable()); - if (dg) - { - if (cellResultSlot->isTernarySaturationSelected()) - { - RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); - } - else - { - if (cellResultSlot->hasResult()) - { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - surfaceGenerator, dg, m_grid->gridIndex(), m_opacityLevel); - - cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - cellFaceEffectGen.setScalarMapper(cellScalarMapper); - } - } - - cellFaceEffectGen.setOpacityLevel(m_opacityLevel); - cellFaceEffectGen.setDefaultCellColor(m_defaultColor); - - cvf::ref eff = cellFaceEffectGen.generateEffect(); + if (m_surfaceFaces.notNull()) + { + cvf::DrawableGeo* dg = dynamic_cast(m_surfaceFaces->drawable()); + if (dg) + { + cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_surfaceGenerator.quadToCellFaceMapper(), m_grid->gridIndex(), + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); - facePart->setEffect(eff.p()); - } - } + m_surfaceFaces->setEffect(eff.p()); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index ea79932791..ddd3b87a62 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -64,11 +64,7 @@ class RivGridPartMgr: public cvf::Object private: void generatePartGeometry(cvf::StructGridGeometryGenerator& geoBuilder); - void updateCellEdgeResultColorOnPart(cvf::Part* facePart, - cvf::StructGridGeometryGenerator* surfaceGenerator, - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot); + private: size_t m_gridIdx; cvf::cref m_grid; diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 60dae98bd0..90d573c7f7 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -197,3 +197,15 @@ void RivReservoirPartMgr::setFaultForceVisibility(bool isGeneratedByFilter) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirPartMgr::updateFaultCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + if (m_faultsPartMgr.notNull()) + { + m_faultsPartMgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); + } + +} + diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index 6f7075aeac..817fcb46fc 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -64,7 +64,9 @@ class RivReservoirPartMgr: public cvf::Object // Faults void updateFaultColors(size_t timeStepIndex, RimResultSlot* cellResultSlot); - void appendFaultPartsToModel(cvf::ModelBasicList* model); + void updateFaultCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); + void appendFaultPartsToModel(cvf::ModelBasicList* model); void appendFaultLabelPartsToModel(cvf::ModelBasicList* model); private: diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 461a90c7d0..2f13d9f2e6 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -795,7 +795,16 @@ void RivReservoirViewPartMgr::updateCellResultColor(ReservoirGeometryCacheType g void RivReservoirViewPartMgr::updateCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { RivReservoirPartMgr * pmgr = reservoirPartManager( geometryType, timeStepIndex ); - pmgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot ); + pmgr->updateCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivReservoirViewPartMgr::updateFaultCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) +{ + RivReservoirPartMgr * pmgr = reservoirPartManager(geometryType, timeStepIndex); + pmgr->updateFaultCellEdgeResultColor(timeStepIndex, cellResultSlot, cellEdgeResultSlot); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h index 796835ad13..a499b6b683 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -66,12 +66,16 @@ class RivReservoirViewPartMgr: public cvf::Object void updateCellResultColor (ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot); void updateCellEdgeResultColor(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, - RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot); + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); // Faults void appendFaultsStaticGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType); void appendFaultsDynamicGeometryPartsToModel(cvf::ModelBasicList* model, ReservoirGeometryCacheType geometryType, size_t frameIndex); void updateFaultColors(ReservoirGeometryCacheType geometryType, size_t timeStepIndex, RimResultSlot* cellResultSlot); + void updateFaultCellEdgeResultColor( ReservoirGeometryCacheType geometryType, size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot); // Fault labels ReservoirGeometryCacheType geometryTypeForFaultLabels(const std::vector& geometryTypes) const; diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index e9620f6536..e3b01ebb51 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -18,8 +18,15 @@ #include "RivScalarMapperUtils.h" -#include "RivTernaryScalarMapperEffectGenerator.h" +#include "RimCellEdgeResultSlot.h" +#include "RimLegendConfig.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" + +#include "RivCellEdgeEffectGenerator.h" #include "RivTernaryScalarMapper.h" +#include "RivTernaryScalarMapperEffectGenerator.h" #include "cafEffectGenerator.h" @@ -55,6 +62,47 @@ void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf part->setEffect(scalarEffect.p()); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGeo* dg, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + size_t gridIndex, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + float opacityLevel, + cvf::Color3f defaultColor) +{ + CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); + + if (cellResultSlot->isTernarySaturationSelected()) + { + RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + quadToCellFaceMapper, dg, gridIndex, opacityLevel); + + RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cellFaceEffectGen.setTernaryScalarMapper(ternaryCellScalarMapper); + } + else + { + if (cellResultSlot->hasResult()) + { + RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + quadToCellFaceMapper, dg, gridIndex, opacityLevel); + + cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cellFaceEffectGen.setScalarMapper(cellScalarMapper); + } + } + + cellFaceEffectGen.setOpacityLevel(opacityLevel); + cellFaceEffectGen.setDefaultCellColor(defaultColor); + + cvf::ref eff = cellFaceEffectGen.generateEffect(); + return eff; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -84,3 +132,4 @@ cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(cons return scalarEffect; } + diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index f807585422..8e08965fde 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -26,9 +26,13 @@ namespace cvf class ScalarMapper; class Part; class Effect; + class StructGridQuadToCellFaceMapper; + class DrawableGeo; } class RivTernaryScalarMapper; +class RimResultSlot; +class RimCellEdgeResultSlot; //================================================================================================== /// @@ -39,6 +43,15 @@ class RivScalarMapperUtils static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel); static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel); + static cvf::ref createCellEdgeEffect(cvf::DrawableGeo* dg, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + size_t gridIndex, + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + float opacityLevel, + cvf::Color3f defaultColor); + private: static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel); static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 063474c3f8..b1280f90b4 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -805,7 +805,7 @@ void RimReservoirView::updateCurrentTimeStep() { if (this->animationMode() && this->cellEdgeResult()->hasResult()) { - 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()) || this->cellResult()->isTernarySaturationSelected()) { @@ -2057,15 +2057,23 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* resultSlot = this->cellResult(); + RimResultSlot* faultResultSlot = this->cellResult(); if (this->faultResultSettings()->customFaultResult()) { - resultSlot = this->faultResultSettings()->customFaultResult(); + faultResultSlot = this->faultResultSettings()->customFaultResult(); } + for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, resultSlot); + if (this->animationMode() && this->cellEdgeResult()->hasResult()) + { + m_reservoirGridPartManager->updateFaultCellEdgeResultColor(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot, this->cellEdgeResult()); + } + else + { + m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot); + } } } From 2a55b47e9a3fff9f09c77e9821d793e0667387b8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 13 Aug 2014 11:00:47 +0200 Subject: [PATCH 250/346] Renamed and restructured files and classes --- .../ModelVisualization/CMakeLists_files.cmake | 2 + .../RivCellEdgeEffectGenerator.cpp | 329 +---------------- .../RivCellEdgeEffectGenerator.h | 47 +-- .../RivCellEdgeGeometryUtils.cpp | 339 ++++++++++++++++++ .../RivCellEdgeGeometryUtils.h | 70 ++++ .../RivScalarMapperUtils.cpp | 5 +- 6 files changed, 426 insertions(+), 366 deletions(-) create mode 100644 ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp create mode 100644 ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h diff --git a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake index 5079ead6ff..fec6bd6869 100644 --- a/ApplicationCode/ModelVisualization/CMakeLists_files.cmake +++ b/ApplicationCode/ModelVisualization/CMakeLists_files.cmake @@ -29,6 +29,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.h ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.h ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.h ${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.h +${CEE_CURRENT_LIST_DIR}RivCellEdgeGeometryUtils.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -54,6 +55,7 @@ ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapper.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryTextureCoordsCreator.cpp ${CEE_CURRENT_LIST_DIR}RivTernaryScalarMapperEffectGenerator.cpp ${CEE_CURRENT_LIST_DIR}RivScalarMapperUtils.cpp +${CEE_CURRENT_LIST_DIR}RivCellEdgeGeometryUtils.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 358110545d..ac493658cd 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -16,330 +16,23 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "RiaStdInclude.h" #include "RivCellEdgeEffectGenerator.h" - -#include "RigCaseCellResultsData.h" -#include "RigCaseData.h" -#include "RigCellEdgeResultAccessor.h" -#include "RigGridBase.h" -#include "RigResultAccessor.h" -#include "RigResultAccessorFactory.h" - -#include "RimCase.h" -#include "RimCellEdgeResultSlot.h" -#include "RimReservoirView.h" -#include "RimResultSlot.h" -#include "RimTernaryLegendConfig.h" -#include "RimWellCollection.h" - #include "RivTernaryScalarMapper.h" -#include "RivTernaryTextureCoordsCreator.h" -#include "cvfStructGridGeometryGenerator.h" +#include "cvfRenderStateBlending.h" +#include "cvfRenderStateCullFace.h" +#include "cvfRenderStateTextureBindings.h" +#include "cvfSampler.h" +#include "cvfShaderProgram.h" +#include "cvfShaderProgramGenerator.h" +#include "cvfShaderSourceProvider.h" +#include "cvfTexture.h" #include "cvfqtUtils.h" - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo( - size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel) -{ - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - // Create result access objects - - cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - - size_t vertexCount = geo->vertexArray()->size(); - size_t quadCount = vertexCount / 4; - - cvf::ref localCoords = new cvf::Vec2fArray; - localCoords->resize(vertexCount); - - cvf::ref faceIndexArray = new cvf::IntArray; - faceIndexArray->resize(vertexCount); - - cvf::ref cellColorTextureCoordArray = new cvf::FloatArray; - cellColorTextureCoordArray->resize(vertexCount); - - // Build six cell face color arrays - cvf::Collection cellEdgeColorTextureCoordsArrays; - size_t idx; - for (idx = 0; idx < 6; idx++) - { - cvf::ref colorArray = new cvf::FloatArray; - colorArray->resize(vertexCount); - cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); - } - - cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); - - const std::vector* isWellPipeVisible = NULL; - cvf::ref gridCellToWellindexMap; - - if (opacityLevel < 1.0f) - { - isWellPipeVisible = &(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex)); - gridCellToWellindexMap = eclipseCase->gridCellToWellIndex( gridIndex ); - } - -#pragma omp parallel for - for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) - { - localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); - localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); - localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); - localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx) ); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx) ); - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - { - cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); - double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); - - { - float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color - if (scalarValue != HUGE_VAL) - { - cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - // If we are dealing with wellcells, the default is transparent. - // we need to make cells opaque if there are no wellpipe through them. - if (opacityLevel < 1.0f) - { - cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); - if (wellIndex != cvf::UNDEFINED_UINT) - { - if (!(*isWellPipeVisible)[wellIndex]) - { - cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" - } - } - } - } - else - { - cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. - } - - cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); - cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); - } - } - - - float edgeColor; - for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - - double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) - { - edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - } - - cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); - - colArr->set(quadIdx * 4 + 0, edgeColor); - colArr->set(quadIdx * 4 + 1, edgeColor); - colArr->set(quadIdx * 4 + 2, edgeColor); - colArr->set(quadIdx * 4 + 3, edgeColor); - } - } - - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); - - cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - geo->setVertexAttribute(faceIntAttribute.p()); - - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) -{ - RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); - CVF_ASSERT(eclipseCase != NULL); - - cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); - - size_t vertexCount = geo->vertexArray()->size(); - size_t quadCount = vertexCount / 4; - - cvf::ref localCoords = new cvf::Vec2fArray; - localCoords->resize(vertexCount); - - cvf::ref faceIndexArray = new cvf::IntArray; - faceIndexArray->resize(vertexCount); - - cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; - vCellColorTextureCoordArray->resize(vertexCount); - - // Build six cell face color arrays - cvf::Collection cellEdgeColorTextureCoordsArrays; - size_t idx; - for (idx = 0; idx < 6; idx++) - { - cvf::ref colorArray = new cvf::FloatArray; - colorArray->resize(vertexCount); - cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); - } - - RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); - - double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); - - RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), - timeStepIndex, - gridIndex, - quadToCellFaceMapper); - - texturer.createTextureCoords(vCellColorTextureCoordArray.p()); - -#pragma omp parallel for - for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) - { - localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); - localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); - localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); - localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); - - faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); - faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); - - size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); - - float edgeColor; - for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - edgeColor = -1.0f; // Undefined texture coord. Shader handles this. - - double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) - { - edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; - } - - cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); - - colArr->set(quadIdx * 4 + 0, edgeColor); - colArr->set(quadIdx * 4 + 1, edgeColor); - colArr->set(quadIdx * 4 + 2, edgeColor); - colArr->set(quadIdx * 4 + 3, edgeColor); - } - } - - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); - geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); - - cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); - geo->setVertexAttribute(faceIntAttribute.p()); - - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); - geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); - -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid) -{ - cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); - { - size_t resultIndices[6]; - cellEdgeResultSlot->gridScalarIndices(resultIndices); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - - size_t cubeFaceIdx; - for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) - { - // Assuming static values to be mapped onto cell edge, always using time step zero - cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); - cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); - } - } - - return cellEdgeResultAccessor; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RivCellEdgeGeometryGenerator::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) -{ - cvf::ref resultAccessor = NULL; - - if (cellResultSlot->hasResult()) - { - if (!cellResultSlot->hasDynamicResult()) - { - // Static result values are located at time step 0 - timeStepIndex = 0; - } - - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); - } - - if (resultAccessor.isNull()) - { - resultAccessor = new RigHugeValResultAccessor; - } - - return resultAccessor; -} - - - - - +#include +#include //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 093243ad76..118adce686 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA, Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -20,54 +20,9 @@ #include "cafEffectGenerator.h" -namespace cvf -{ - class DrawableGeo; - class StructGridQuadToCellFaceMapper; -} - -class RimCellEdgeResultSlot; -class RimResultSlot; -class RigGridBase; -class RigResultAccessor; -class RigCaseData; class RivTernaryScalarMapper; -class RivCellEdgeGeometryGenerator -{ -public: - static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel); - - static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, - cvf::DrawableGeo* geo, - size_t gridIndex, - float opacityLevel); - - -private: - static cvf::ref createCellCenterResultAccessor( - RimResultSlot* cellResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid); - - static cvf::ref createCellEdgeCenterResultAccessor( - RimResultSlot* cellResultSlot, - RimCellEdgeResultSlot* cellEdgeResultSlot, - size_t timeStepIndex, - RigCaseData* eclipseCase, - const RigGridBase* grid); -}; /* Thoughts on organizing the texture coords generation a bit. diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp new file mode 100644 index 0000000000..14b3d9f3a7 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp @@ -0,0 +1,339 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + + +#include "RivCellEdgeGeometryUtils.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigCellEdgeResultAccessor.h" +#include "RigGridBase.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RimCase.h" +#include "RimCellEdgeResultSlot.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" +#include "RimTernaryLegendConfig.h" +#include "RimWellCollection.h" +#include "RivTernaryTextureCoordsCreator.h" + +#include "cvfDrawableGeo.h" +#include "cvfVertexAttribute.h" + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( + size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + // Create result access objects + + cvf::ref cellCenterDataAccessObject = createCellCenterResultAccessor(cellResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref cellColorTextureCoordArray = new cvf::FloatArray; + cellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + cvf::ScalarMapper* cellResultScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + const std::vector* isWellPipeVisible = NULL; + cvf::ref gridCellToWellindexMap; + + if (opacityLevel < 1.0f) + { + isWellPipeVisible = &(cellResultSlot->reservoirView()->wellCollection()->isWellPipesVisible(timeStepIndex)); + gridCellToWellindexMap = eclipseCase->gridCellToWellIndex(gridIndex); + } + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + { + cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace(quadIdx); + double scalarValue = cellCenterDataAccessObject->cellFaceScalar(cellIndex, cellFace); + + { + float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color + if (scalarValue != HUGE_VAL) + { + cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + // If we are dealing with wellcells, the default is transparent. + // we need to make cells opaque if there are no wellpipe through them. + if (opacityLevel < 1.0f) + { + cvf::uint wellIndex = gridCellToWellindexMap->get(cellIndex); + if (wellIndex != cvf::UNDEFINED_UINT) + { + if (!(*isWellPipeVisible)[wellIndex]) + { + cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as "opaque" + } + } + } + } + else + { + cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this. + } + + cellColorTextureCoordArray->set(quadIdx * 4 + 0, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 1, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 2, cellColorTextureCoord); + cellColorTextureCoordArray->set(quadIdx * 4 + 3, cellColorTextureCoord); + } + } + + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorCell", cellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, size_t gridIndex, float opacityLevel) +{ + RigCaseData* eclipseCase = cellResultSlot->reservoirView()->eclipseCase()->reservoirData(); + CVF_ASSERT(eclipseCase != NULL); + + cvf::ref cellEdgeResultAccessor = createCellEdgeCenterResultAccessor(cellResultSlot, cellEdgeResultSlot, timeStepIndex, eclipseCase, eclipseCase->grid(gridIndex)); + + size_t vertexCount = geo->vertexArray()->size(); + size_t quadCount = vertexCount / 4; + + cvf::ref localCoords = new cvf::Vec2fArray; + localCoords->resize(vertexCount); + + cvf::ref faceIndexArray = new cvf::IntArray; + faceIndexArray->resize(vertexCount); + + cvf::ref vCellColorTextureCoordArray = new cvf::Vec2fArray; + vCellColorTextureCoordArray->resize(vertexCount); + + // Build six cell face color arrays + cvf::Collection cellEdgeColorTextureCoordsArrays; + size_t idx; + for (idx = 0; idx < 6; idx++) + { + cvf::ref colorArray = new cvf::FloatArray; + colorArray->resize(vertexCount); + cellEdgeColorTextureCoordsArrays.push_back(colorArray.p()); + } + + RivTernaryScalarMapper* ternaryCellResultScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); + cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultSlot->legendConfig()->scalarMapper(); + + double ignoredScalarValue = cellEdgeResultSlot->ignoredScalarValue(); + + RivTernaryTextureCoordsCreator texturer(cellResultSlot, cellResultSlot->ternaryLegendConfig(), + timeStepIndex, + gridIndex, + quadToCellFaceMapper); + + texturer.createTextureCoords(vCellColorTextureCoordArray.p()); + +#pragma omp parallel for + for (int quadIdx = 0; quadIdx < static_cast(quadCount); quadIdx++) + { + localCoords->set(quadIdx * 4 + 0, cvf::Vec2f(0, 0)); + localCoords->set(quadIdx * 4 + 1, cvf::Vec2f(1, 0)); + localCoords->set(quadIdx * 4 + 2, cvf::Vec2f(1, 1)); + localCoords->set(quadIdx * 4 + 3, cvf::Vec2f(0, 1)); + + faceIndexArray->set(quadIdx * 4 + 0, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 1, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 2, quadToCellFaceMapper->cellFace(quadIdx)); + faceIndexArray->set(quadIdx * 4 + 3, quadToCellFaceMapper->cellFace(quadIdx)); + + size_t cellIndex = quadToCellFaceMapper->cellIndex(quadIdx); + + float edgeColor; + for (size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + edgeColor = -1.0f; // Undefined texture coord. Shader handles this. + + double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); + + if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + { + edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; + } + + cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at(cubeFaceIdx); + + colArr->set(quadIdx * 4 + 0, edgeColor); + colArr->set(quadIdx * 4 + 1, edgeColor); + colArr->set(quadIdx * 4 + 2, edgeColor); + colArr->set(quadIdx * 4 + 3, edgeColor); + } + } + + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_localCoord", localCoords.p())); + geo->setVertexAttribute(new cvf::Vec2fVertexAttribute("a_cellTextureCoord", vCellColorTextureCoordArray.p())); + + cvf::ref faceIntAttribute = new cvf::IntVertexAttributeDirect("a_face", faceIndexArray.p()); + geo->setVertexAttribute(faceIntAttribute.p()); + + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosI", cellEdgeColorTextureCoordsArrays.at(0))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegI", cellEdgeColorTextureCoordsArrays.at(1))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosJ", cellEdgeColorTextureCoordsArrays.at(2))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegJ", cellEdgeColorTextureCoordsArrays.at(3))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorPosK", cellEdgeColorTextureCoordsArrays.at(4))); + geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryUtils::createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid) +{ + cvf::ref cellEdgeResultAccessor = new RigCellEdgeResultAccessor(); + { + size_t resultIndices[6]; + cellEdgeResultSlot->gridScalarIndices(resultIndices); + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + + size_t cubeFaceIdx; + for (cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++) + { + // Assuming static values to be mapped onto cell edge, always using time step zero + cvf::ref daObj = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, 0, resultIndices[cubeFaceIdx]); + cellEdgeResultAccessor->setDataAccessObjectForFace(static_cast(cubeFaceIdx), daObj.p()); + } + } + + return cellEdgeResultAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RivCellEdgeGeometryUtils::createCellCenterResultAccessor(RimResultSlot* cellResultSlot, size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid) +{ + cvf::ref resultAccessor = NULL; + + if (cellResultSlot->hasResult()) + { + if (!cellResultSlot->hasDynamicResult()) + { + // Static result values are located at time step 0 + timeStepIndex = 0; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResultSlot->porosityModel()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, grid->gridIndex(), porosityModel, timeStepIndex, cellResultSlot->resultVariable()); + } + + if (resultAccessor.isNull()) + { + resultAccessor = new RigHugeValResultAccessor; + } + + return resultAccessor; +} + + + + + + + diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h new file mode 100644 index 0000000000..fdc96745a6 --- /dev/null +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" + +namespace cvf +{ + class DrawableGeo; + class StructGridQuadToCellFaceMapper; +} + +class RimCellEdgeResultSlot; +class RimResultSlot; +class RigGridBase; +class RigResultAccessor; +class RigCaseData; + + +class RivCellEdgeGeometryUtils +{ +public: + static void addCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + static void addTernaryCellEdgeResultsToDrawableGeo(size_t timeStepIndex, + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, + cvf::DrawableGeo* geo, + size_t gridIndex, + float opacityLevel); + + +private: + static cvf::ref createCellCenterResultAccessor( + RimResultSlot* cellResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); + + static cvf::ref createCellEdgeCenterResultAccessor( + RimResultSlot* cellResultSlot, + RimCellEdgeResultSlot* cellEdgeResultSlot, + size_t timeStepIndex, + RigCaseData* eclipseCase, + const RigGridBase* grid); +}; diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index e3b01ebb51..ea1e1b9707 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -25,6 +25,7 @@ #include "RimTernaryLegendConfig.h" #include "RivCellEdgeEffectGenerator.h" +#include "RivCellEdgeGeometryUtils.h" #include "RivTernaryScalarMapper.h" #include "RivTernaryScalarMapperEffectGenerator.h" @@ -78,7 +79,7 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe if (cellResultSlot->isTernarySaturationSelected()) { - RivCellEdgeGeometryGenerator::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, quadToCellFaceMapper, dg, gridIndex, opacityLevel); RivTernaryScalarMapper* ternaryCellScalarMapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); @@ -88,7 +89,7 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe { if (cellResultSlot->hasResult()) { - RivCellEdgeGeometryGenerator::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, quadToCellFaceMapper, dg, gridIndex, opacityLevel); cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); From 8e332366ac02e0167e9641d425a0417746acd472 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 14 Aug 2014 11:45:13 +0200 Subject: [PATCH 251/346] Execute initAfterRead when a reservoir view is created Updates visibility of application icons --- ApplicationCode/ProjectDataModel/RimCase.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index c58b36f476..66178129ec 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -20,8 +20,10 @@ #include "RiaApplication.h" #include "RiaPreferences.h" + #include "RigCaseCellResultsData.h" #include "RigCaseData.h" + #include "RimCaseCollection.h" #include "RimCellEdgeResultSlot.h" #include "RimCellPropertyFilter.h" @@ -30,6 +32,7 @@ #include "RimReservoirView.h" #include "RimResultSlot.h" +#include "cafPdmDocument.h" #include "cafProgressInfo.h" #include @@ -135,6 +138,8 @@ RimReservoirView* RimCase::createAndAddReservoirView() RimReservoirView* riv = new RimReservoirView(); riv->setEclipseCase(this); + caf::PdmDocument::initAfterReadTraversal(riv); + size_t i = reservoirViews().size(); riv->name = QString("View %1").arg(i + 1); From ab483fee81fe1cd287fad474c3f20d71387c35bf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 14 Aug 2014 12:12:07 +0200 Subject: [PATCH 252/346] Made ternary result accessor more robust --- .../RigTernaryResultAccessor2d.cpp | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index d58fe8486a..bfb431b1b0 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -37,17 +37,10 @@ void RigTernaryResultAccessor::setTernaryResultAccessors(RigResultAccessor* soil m_soilAccessor = soil; m_sgasAccessor = sgas; m_swatAccessor = swat; - - int nullPointerCount = 0; - if (!soil) nullPointerCount++; - if (!sgas) nullPointerCount++; - if (!swat) nullPointerCount++; - - CVF_ASSERT(nullPointerCount <= 1); } //-------------------------------------------------------------------------------------------------- -/// +/// If only swat is present, soil is set to (1.0 - swat) and sgas to 0 //-------------------------------------------------------------------------------------------------- cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { @@ -62,16 +55,34 @@ cvf::Vec2d RigTernaryResultAccessor::cellScalar(size_t gridLocalCellIndex) const { sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); } - else + else if (m_swatAccessor.notNull()) { sgas = 1.0 - soil - m_swatAccessor->cellScalar(gridLocalCellIndex); } + else + { + sgas = 1.0 - soil; + } } else { - sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); + if (m_sgasAccessor.notNull()) + { + sgas = m_sgasAccessor->cellScalar(gridLocalCellIndex); - soil = 1.0 - sgas - m_swatAccessor->cellScalar(gridLocalCellIndex); + if (m_swatAccessor.notNull()) + { + soil = 1.0 - sgas - m_swatAccessor->cellScalar(gridLocalCellIndex); + } + else + { + soil = 1.0 - sgas; + } + } + else if (m_swatAccessor.notNull()) + { + soil = 1.0 - m_swatAccessor->cellScalar(gridLocalCellIndex); + } } return cvf::Vec2d(soil, sgas); From 147fbffe551411eda52a8c5dfd42fc447a46a58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 18 Aug 2014 18:30:52 +0200 Subject: [PATCH 253/346] riTRANXYZ: Paving the way: Renaming, Removing obsolete code, Store fault index for each cell face, Added prototype code for the calculation --- .../ReservoirDataModel/RigCell.cpp | 12 +- ApplicationCode/ReservoirDataModel/RigCell.h | 2 +- .../RigCombRiTransResultAccessor.cpp | 144 ++++++++++++++++++ .../RigCombRiTransResultAccessor.h | 62 ++++++++ ApplicationCode/ReservoirDataModel/RigFault.h | 5 +- .../ReservoirDataModel/RigGridBase.cpp | 15 -- .../ReservoirDataModel/RigGridBase.h | 14 -- .../ReservoirDataModel/RigMainGrid.cpp | 31 ++-- .../ReservoirDataModel/RigMainGrid.h | 3 +- .../ReservoirDataModel/RigNNCData.cpp | 2 +- .../ReservoirDataModel/cvfGeometryTools.cpp | 6 +- .../ReservoirDataModel/cvfGeometryTools.h | 2 +- 12 files changed, 241 insertions(+), 57 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h diff --git a/ApplicationCode/ReservoirDataModel/RigCell.cpp b/ApplicationCode/ReservoirDataModel/RigCell.cpp index 5385d7150a..e2b6f49427 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCell.cpp @@ -243,16 +243,20 @@ cvf::Vec3d RigCell::faceCenter(cvf::StructGridInterface::FaceType face) const } //-------------------------------------------------------------------------------------------------- -/// +/// Returns an area vector for the cell face. The direction is the face normal, and the length is +/// equal to the face area (projected to the plane represented by the diagonal in case of warp) +/// The components of this area vector are equal to the area of the face projection onto +/// the corresponding plane. +/// See http://geomalgorithms.com/a01-_area.html //-------------------------------------------------------------------------------------------------- -cvf::Vec3d RigCell::faceNormal(cvf::StructGridInterface::FaceType face) const +cvf::Vec3d RigCell::faceNormalWithAreaLenght(cvf::StructGridInterface::FaceType face) const { cvf::ubyte faceVertexIndices[4]; cvf::StructGridInterface::cellFaceVertexIndices(face, faceVertexIndices); const std::vector& nodeCoords = m_hostGrid->mainGrid()->nodes(); - return ( nodeCoords[m_cornerIndices[faceVertexIndices[2]]] - nodeCoords[m_cornerIndices[faceVertexIndices[0]]]) ^ - ( nodeCoords[m_cornerIndices[faceVertexIndices[3]]] - nodeCoords[m_cornerIndices[faceVertexIndices[1]]]); + return 0.5*( nodeCoords[m_cornerIndices[faceVertexIndices[2]]] - nodeCoords[m_cornerIndices[faceVertexIndices[0]]]) ^ + ( nodeCoords[m_cornerIndices[faceVertexIndices[3]]] - nodeCoords[m_cornerIndices[faceVertexIndices[1]]]); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCell.h b/ApplicationCode/ReservoirDataModel/RigCell.h index 0f5761c3ad..1a7475594d 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.h +++ b/ApplicationCode/ReservoirDataModel/RigCell.h @@ -63,7 +63,7 @@ class RigCell cvf::Vec3d center() const; cvf::Vec3d faceCenter(cvf::StructGridInterface::FaceType face) const; - cvf::Vec3d faceNormal(cvf::StructGridInterface::FaceType face) const; + cvf::Vec3d faceNormalWithAreaLenght(cvf::StructGridInterface::FaceType face) const; int firstIntersectionPoint(const cvf::Ray& ray, cvf::Vec3d* intersectionPoint) const; bool isLongPyramidCell(double maxHeightFactor = 5, double nodeNearTolerance = 1e-3 ) const; diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp new file mode 100644 index 0000000000..42fb536878 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp @@ -0,0 +1,144 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCombRiTransResultAccessor.h" + +#include "RigGridBase.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCombRiTransResultAccessor::RigCombRiTransResultAccessor(const RigGridBase* grid) + : m_grid(grid) +{ + m_cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) +} + +//-------------------------------------------------------------------------------------------------- +/// Only sensible to provide the positive values, as the negative ones will never be used. +/// The negative faces gets their value from the neighbor cell in that direction +//-------------------------------------------------------------------------------------------------- +void RigCombRiTransResultAccessor::setPermResultAccessors( RigResultAccessor* xPermAccessor, + RigResultAccessor* yPermAccessor, + RigResultAccessor* zPermAccessor) + +{ + m_xPermAccessor = xPermAccessor; + m_yPermAccessor = yPermAccessor; + m_zPermAccessor = zPermAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombRiTransResultAccessor::setNTGResultAccessor(RigResultAccessor* ntgAccessor) +{ + m_ntgAccessor = ntgAccessor; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombRiTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const +{ + CVF_TIGHT_ASSERT(false); + + return HUGE_VAL; +} + +double RigCombRiTransResultAccessor::getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +{ + switch (faceId) + { + case cvf::StructGridInterface::POS_I: + case cvf::StructGridInterface::NEG_I: + { + return m_xPermAccessor->cellScalar(gridLocalCellIndex); + } + break; + case cvf::StructGridInterface::POS_J: + case cvf::StructGridInterface::NEG_J: + { + return m_yPermAccessor->cellScalar(gridLocalCellIndex); + } + break; + case cvf::StructGridInterface::POS_K: + case cvf::StructGridInterface::NEG_K: + { + return zPermAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombRiTransResultAccessor::calculateHalfCellTrans( size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +{ + double perm = getPermValue(gridLocalCellIndex, faceId); + double ntg = 1.0; + + if (faceId != cvf::StructGridInterface::POS_K && faceId != cvf::StructGridInterface::NEG_K) + { + m_ntgAccessor->cellScalar(gridLocalCellIndex); + } + + RigCell& cell = m_grid->cell(gridLocalCellIndex); + + cvf::Vec3d centerToFace = cell.faceCenter(faceId) - cell.center(); + cvf::Vec3d faceAreaVec = cell.faceNormalWithAreaLenght(faceId); + + double halfCellTrans = perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); + + return halfCellTrans; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombRiTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace(reservoirCellIndex, faceId); + + if (fault) + { + + } + else + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) + { + double halfCellTrans = calculateHalfCellTrans(gridLocalCellIndex, faceId); + double neighborHalfCellTrans = calculateHalfCellTrans(neighborGridCellIdx, cvf::StructGridInterface::oppositeFace(faceId)); + + return m_cdarchy/ ( ( 1 / halfCellTrans) + (1 / neighborHalfCellTrans) ); + } + } + + return HUGE_VAL; +} \ No newline at end of file diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h new file mode 100644 index 0000000000..e2974e8ef4 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessor.h" + +#include "cvfCollection.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigCombRiTransResultAccessor : public RigResultAccessor +{ +public: + RigCombRiTransResultAccessor(const RigGridBase* grid); + + void setPermResultAccessors(RigResultAccessor* xPermAccessor, + RigResultAccessor* yPermAccessor, + RigResultAccessor* zPermAccessor); + void setNTGResultAccessor( RigResultAccessor* ntgAccessor); + + /// CDARCY Darcy’s constant + /// = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC) + /// = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD) + /// = 3.6 (LAB) + /// = 0.00864 (PVT-M) + void setCDARCHY(double cDarchy) { m_cdarchy = cDarchy;} + + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; + +private: + + cvf::ref m_xPermAccessor; + cvf::ref m_yPermAccessor; + cvf::ref m_zPermAccessor; + + cvf::ref m_ntgAccessor; + + double m_cdarchy; + + const RigGridBase* m_grid; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 44d232bd7d..8a935365e4 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -46,7 +46,7 @@ class RigFaultsPrCellAccumulator : public cvf::Object m_faultIdxForCellFace.resize(reservoirCellCount, initVal); } - inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) + inline int faultIdx(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const { return m_faultIdxForCellFace[reservoirCellIndex][face]; } @@ -94,9 +94,6 @@ class RigFault : public cvf::Object std::vector& connectionIndices() { return m_connectionIndices; } const std::vector& connectionIndices() const { return m_connectionIndices; } - static RigFaultsPrCellAccumulator* faultsPrCellAccumulator() { CVF_ASSERT(m_faultsPrCellAcc.notNull()); return m_faultsPrCellAcc.p();} - static void initFaultsPrCellAccumulator(size_t reservoirCellCount) { m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(reservoirCellCount); } - private: QString m_name; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index 6f145298a4..a7ab0b6391 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -490,18 +490,3 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible(size_t i, size_t j, size_t k return false; } - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigFaultFaceVisibilityFilter::isFaceVisible(size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility) const -{ - size_t cellIndex = m_grid->cellIndexFromIJK(i, j, k); - if (m_grid->cell(cellIndex).isCellFaceFault(face)) - { - return true; - } - - return false; -} diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index 0197cd0405..2ce18bd867 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -133,17 +133,3 @@ class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter private: const RigGridBase* m_grid; }; - -class RigFaultFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter -{ -public: - RigFaultFaceVisibilityFilter(const RigGridBase* grid) - : m_grid(grid) - { - } - - virtual bool isFaceVisible( size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility ) const; - -private: - const RigGridBase* m_grid; -}; diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 21a8645632..b5e79a750d 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -20,6 +20,8 @@ #include "cvfAssert.h" #include "RimDefines.h" +#include "RigFault.h" + RigMainGrid::RigMainGrid(void) : RigGridBase(this) @@ -213,13 +215,12 @@ void RigMainGrid::setFaults(const cvf::Collection& faults) //-------------------------------------------------------------------------------------------------- void RigMainGrid::calculateFaults() { - //RigFault::initFaultsPrCellAccumulator(m_cells.size()); - cvf::ref faultsPrCellAcc = new RigFaultsPrCellAccumulator(m_cells.size()); + m_faultsPrCellAcc = new RigFaultsPrCellAccumulator(m_cells.size()); // Spread fault idx'es on the cells from the faults for (size_t fIdx = 0 ; fIdx < m_faults.size(); ++fIdx) { - m_faults[fIdx]->accumulateFaultsPrCell(faultsPrCellAcc.p(), static_cast(fIdx)); + m_faults[fIdx]->accumulateFaultsPrCell(m_faultsPrCellAcc.p(), static_cast(fIdx)); } // Find the geometrical faults that is in addition @@ -244,7 +245,7 @@ void RigMainGrid::calculateFaults() { cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::FaceType(faceIdx); - if (faultsPrCellAcc->faultIdx(gcIdx, face) == RigFaultsPrCellAccumulator::NO_FAULT) + if (m_faultsPrCellAcc->faultIdx(gcIdx, face) == RigFaultsPrCellAccumulator::NO_FAULT) { // Find neighbor cell if (firstNO_FAULTFaceForCell) // To avoid doing this for every face, and only when detecting a NO_FAULT @@ -288,11 +289,8 @@ void RigMainGrid::calculateFaults() // To avoid doing this calculation for the opposite face - faultsPrCellAcc->setFaultIdx(gcIdx, face, unNamedFaultIdx); - faultsPrCellAcc->setFaultIdx(neighborReservoirCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); - - //m_cells[gcIdx].setCellFaceFault(face); - //m_cells[neighborReservoirCellIdx].setCellFaceFault(StructGridInterface::oppositeFace(face)); + m_faultsPrCellAcc->setFaultIdx(gcIdx, face, unNamedFaultIdx); + m_faultsPrCellAcc->setFaultIdx(neighborReservoirCellIdx, StructGridInterface::oppositeFace(face), unNamedFaultIdx); // Add as fault face only if the grid index is less than the neighbors @@ -330,8 +328,8 @@ void RigMainGrid::calculateFaults() if (conn.m_c1Face != StructGridInterface::NO_FACE) { - fIdx1 = faultsPrCellAcc->faultIdx(conn.m_c1GlobIdx, conn.m_c1Face); - fIdx2 = faultsPrCellAcc->faultIdx(conn.m_c2GlobIdx, StructGridInterface::oppositeFace(conn.m_c1Face)); + fIdx1 = m_faultsPrCellAcc->faultIdx(conn.m_c1GlobIdx, conn.m_c1Face); + fIdx2 = m_faultsPrCellAcc->faultIdx(conn.m_c2GlobIdx, StructGridInterface::oppositeFace(conn.m_c1Face)); } if (fIdx1 < 0 && fIdx2 < 0) @@ -373,8 +371,15 @@ bool RigMainGrid::faceNormalsIsOutwards() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const +const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const { + int faultIdx = m_faultsPrCellAcc->faultIdx(reservoirCellIndex, face); + if (faultIdx != RigFaultsPrCellAccumulator::NO_FAULT ) + { + return m_faults.at(faultIdx); + } + +#if 0 for (size_t i = 0; i < m_faults.size(); i++) { const RigFault* rigFault = m_faults.at(i); @@ -399,6 +404,6 @@ const RigFault* RigMainGrid::findFaultFromCellIndexAndCellFace(size_t cellIndex, } } } - +#endif return NULL; } diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index 0cf0dc8286..525293239b 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -51,7 +51,7 @@ class RigMainGrid : public RigGridBase void setFaults(const cvf::Collection& faults); const cvf::Collection& faults() { return m_faults; } void calculateFaults(); - const RigFault* findFaultFromCellIndexAndCellFace(size_t cellIndex, cvf::StructGridInterface::FaceType face) const; + const RigFault* findFaultFromCellIndexAndCellFace(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; bool faceNormalsIsOutwards() const; void computeCachedData(); @@ -76,6 +76,7 @@ class RigMainGrid : public RigGridBase cvf::Collection m_faults; cvf::ref m_nncData; + cvf::ref m_faultsPrCellAcc; cvf::Vec3d m_displayModelOffset; diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index f6b619fbdc..128c4f66b9 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -95,7 +95,7 @@ void RigNNCData::processConnections(const RigMainGrid& mainGrid) cvf::Vec3d fc1 = c1.faceCenter((cvf::StructGridInterface::FaceType)(fIdx)); cvf::Vec3d fc2 = c2.faceCenter(cvf::StructGridInterface::oppositeFace((cvf::StructGridInterface::FaceType)(fIdx))); cvf::Vec3d fc1ToFc2 = fc2 - fc1; - normal = c1.faceNormal((cvf::StructGridInterface::FaceType)(fIdx)); + normal = c1.faceNormalWithAreaLenght((cvf::StructGridInterface::FaceType)(fIdx)); normal.normalize(); // Check that face centers are approx in the face plane if (normal.dot(fc1ToFc2) < 0.01*fc1ToFc2.length()) diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp index ad850323c6..fc75916c6a 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp @@ -599,7 +599,7 @@ bool EarClipTesselator::calculateTriangles( std::vector* triangleIndices // We want m_polygonIndices to be a counter-clockwise polygon to make the validation test work - if (calculatePolygonArea() < 0 ) + if (calculateProjectedPolygonArea() < 0 ) { m_polygonIndices.reverse(); } @@ -732,7 +732,7 @@ bool EarClipTesselator::isPointInsideTriangle(const cvf::Vec3d& A, const cvf::Ve /// Computes area of the currently stored 2D polygon/contour //-------------------------------------------------------------------------------------------------- -double EarClipTesselator::calculatePolygonArea() const +double EarClipTesselator::calculateProjectedPolygonArea() const { CVF_ASSERT(m_X > -1 && m_Y > -1); @@ -834,7 +834,7 @@ bool FanEarClipTesselator::calculateTriangles(std::vector* triangles) // We want m_polygonIndices to be a counter-clockwise polygon to make the validation test work - if (calculatePolygonArea() < 0 ) + if (calculateProjectedPolygonArea() < 0 ) { m_polygonIndices.reverse(); } diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h index c124762ddd..46e3725673 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h @@ -138,7 +138,7 @@ class EarClipTesselator protected: bool isTriangleValid( std::list::const_iterator u, std::list::const_iterator v, std::list::const_iterator w) const; bool isPointInsideTriangle(const cvf::Vec3d& A, const cvf::Vec3d& B, const cvf::Vec3d& C, const cvf::Vec3d& P) const; - double calculatePolygonArea() const; + double calculateProjectedPolygonArea() const; protected: std::list m_polygonIndices; From 06df5ba1da81743d8e7bf13b22b697a7f2594b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 18 Aug 2014 18:32:55 +0200 Subject: [PATCH 254/346] riTRANXYZ: removed strange character --- .../ReservoirDataModel/RigCombRiTransResultAccessor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h index e2974e8ef4..4b80ba6bbc 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h @@ -38,7 +38,7 @@ class RigCombRiTransResultAccessor : public RigResultAccessor RigResultAccessor* zPermAccessor); void setNTGResultAccessor( RigResultAccessor* ntgAccessor); - /// CDARCY Darcy’s constant + /// CDARCY Darcy's constant /// = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC) /// = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD) /// = 3.6 (LAB) From d5e911d01b68c2b044ebc576ff8b1c095f1e3302 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 18 Aug 2014 12:03:21 +0200 Subject: [PATCH 255/346] Added RigStatisticsDataCache and RigStatisticsCalculator Moved cache from RigCaseCellResultsData to RigStatisticsDataCache Moved statistics computations from RigCaseCellResultsData to RigStatisticsCalculator --- .../ReservoirDataModel/CMakeLists_files.cmake | 4 + .../RigCaseCellResultsData.cpp | 417 ++---------------- .../RigCaseCellResultsData.h | 19 +- .../RigStatisticsCalculator.cpp | 240 ++++++++++ .../RigStatisticsCalculator.h | 87 ++++ .../RigStatisticsDataCache.cpp | 205 +++++++++ .../RigStatisticsDataCache.h | 65 +++ .../RiaPropertyDataCommands.cpp | 4 +- 8 files changed, 659 insertions(+), 382 deletions(-) create mode 100644 ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h create mode 100644 ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 25f9be656d..78e6bbc52a 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -32,6 +32,8 @@ ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.inl ${CEE_CURRENT_LIST_DIR}RigPipeInCellEvaluator.h ${CEE_CURRENT_LIST_DIR}RigResultAccessor2d.h ${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.h +${CEE_CURRENT_LIST_DIR}RigStatisticsDataCache.h +${CEE_CURRENT_LIST_DIR}RigStatisticsCalculator.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -58,6 +60,8 @@ ${CEE_CURRENT_LIST_DIR}RigFault.cpp ${CEE_CURRENT_LIST_DIR}RigNNCData.cpp ${CEE_CURRENT_LIST_DIR}cvfGeometryTools.cpp ${CEE_CURRENT_LIST_DIR}RigTernaryResultAccessor2d.cpp +${CEE_CURRENT_LIST_DIR}RigStatisticsDataCache.cpp +${CEE_CURRENT_LIST_DIR}RigStatisticsCalculator.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index ea168688b6..9438237e6e 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -17,10 +17,11 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RigCaseCellResultsData.h" -#include "RifReaderInterface.h" -#include "RigMainGrid.h" +#include "RigMainGrid.h" +#include "RigStatisticsDataCache.h" #include "RigStatisticsMath.h" +#include "RigStatisticsCalculator.h" #include #include @@ -33,11 +34,8 @@ RigCaseCellResultsData::RigCaseCellResultsData(RigMainGrid* ownerGrid) { CVF_ASSERT(ownerGrid != NULL); m_ownerMainGrid = ownerGrid; - - m_combinedTransmissibilityResultIndex = cvf::UNDEFINED_SIZE_T; } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -49,39 +47,9 @@ void RigCaseCellResultsData::setMainGrid(RigMainGrid* ownerGrid) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::minMaxCellScalarValues( size_t scalarResultIndex, double& min, double& max ) +void RigCaseCellResultsData::minMaxCellScalarValues(size_t scalarResultIndex, double& min, double& max) { - min = HUGE_VAL; - max = -HUGE_VAL; - - CVF_ASSERT(scalarResultIndex < resultCount()); - - // Extend array and cache vars - - if (scalarResultIndex >= m_maxMinValues.size() ) - { - m_maxMinValues.resize(scalarResultIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL)); - } - - if (m_maxMinValues[scalarResultIndex].first != HUGE_VAL) - { - min = m_maxMinValues[scalarResultIndex].first; - max = m_maxMinValues[scalarResultIndex].second; - - return; - } - - size_t i; - for (i = 0; i < timeStepCount(scalarResultIndex); i++) - { - double tsmin, tsmax; - minMaxCellScalarValues(scalarResultIndex, i, tsmin, tsmax); - if (tsmin < min) min = tsmin; - if (tsmax > max) max = tsmax; - } - - m_maxMinValues[scalarResultIndex].first = min; - m_maxMinValues[scalarResultIndex].second= max; + m_statisticsDataCache[scalarResultIndex]->minMaxCellScalarValues(min, max); } //-------------------------------------------------------------------------------------------------- @@ -89,80 +57,23 @@ void RigCaseCellResultsData::minMaxCellScalarValues( size_t scalarResultIndex, d //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max) { - min = HUGE_VAL; - max = -HUGE_VAL; - - CVF_ASSERT(scalarResultIndex < resultCount()); - - if (timeStepIndex >= m_cellScalarResults[scalarResultIndex].size()) - { - return; - } - - if (scalarResultIndex >= m_maxMinValuesPrTs.size()) - { - m_maxMinValuesPrTs.resize(scalarResultIndex+1); - } - - if (timeStepIndex >= m_maxMinValuesPrTs[scalarResultIndex].size()) - { - m_maxMinValuesPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL)); - } - - if (m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL) - { - min = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first; - max = m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second; - - return; - } - - if (scalarResultIndex == m_combinedTransmissibilityResultIndex) - { - size_t tranX, tranY, tranZ; - if (!findTransmissibilityResults(tranX, tranY, tranZ)) return; - - double tranMin; - double tranMax; - - minMaxCellScalarValues(tranX, timeStepIndex, tranMin, tranMax); - min = CVF_MIN(tranMin, min); - max = CVF_MAX(tranMax, max); - - minMaxCellScalarValues(tranY, timeStepIndex, tranMin, tranMax); - min = CVF_MIN(tranMin, min); - max = CVF_MAX(tranMax, max); - - minMaxCellScalarValues(tranZ, timeStepIndex, tranMin, tranMax); - min = CVF_MIN(tranMin, min); - max = CVF_MAX(tranMax, max); - - return; - } - - std::vector& values = m_cellScalarResults[scalarResultIndex][timeStepIndex]; - - size_t i; - for (i = 0; i < values.size(); i++) - { - if (values[i] == HUGE_VAL) - { - continue; - } - - if (values[i] < min) - { - min = values[i]; - } + m_statisticsDataCache[scalarResultIndex]->minMaxCellScalarValues(timeStepIndex, min, max); +} - if (values[i] > max) - { - max = values[i]; - } - } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, double& pos, double& neg) +{ + m_statisticsDataCache[scalarResultIndex]->posNegClosestToZero(pos, neg); +} - m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].first = min; - m_maxMinValuesPrTs[scalarResultIndex][timeStepIndex].second= max; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, size_t timeStepIndex, double& pos, double& neg) +{ + m_statisticsDataCache[scalarResultIndex]->posNegClosestToZero(timeStepIndex, pos, neg); } //-------------------------------------------------------------------------------------------------- @@ -170,68 +81,15 @@ void RigCaseCellResultsData::minMaxCellScalarValues(size_t scalarResultIndex, si //-------------------------------------------------------------------------------------------------- const std::vector& RigCaseCellResultsData::cellScalarValuesHistogram(size_t scalarResultIndex) { - CVF_ASSERT(scalarResultIndex < resultCount()); - - // Extend array and cache vars - - if (scalarResultIndex >= m_histograms.size() ) - { - m_histograms.resize(resultCount()); - m_p10p90.resize(resultCount(), std::make_pair(HUGE_VAL, HUGE_VAL)); - } - - if (m_histograms[scalarResultIndex].size()) - { - return m_histograms[scalarResultIndex]; - - } - - double min; - double max; - size_t nBins = 100; - this->minMaxCellScalarValues( scalarResultIndex, min, max ); - RigHistogramCalculator histCalc(min, max, nBins, &m_histograms[scalarResultIndex]); - - if (scalarResultIndex == m_combinedTransmissibilityResultIndex) - { - size_t tranX, tranY, tranZ; - if (findTransmissibilityResults(tranX, tranY, tranZ)) - { - for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++) - { - histCalc.addData(m_cellScalarResults[tranX][tsIdx]); - histCalc.addData(m_cellScalarResults[tranY][tsIdx]); - histCalc.addData(m_cellScalarResults[tranZ][tsIdx]); - } - } - } - else - { - for (size_t tsIdx = 0; tsIdx < this->timeStepCount(scalarResultIndex); tsIdx++) - { - std::vector& values = m_cellScalarResults[scalarResultIndex][tsIdx]; - - histCalc.addData(values); - } - } - - m_p10p90[scalarResultIndex].first = histCalc.calculatePercentil(0.1); - m_p10p90[scalarResultIndex].second = histCalc.calculatePercentil(0.9); - - return m_histograms[scalarResultIndex]; + return m_statisticsDataCache[scalarResultIndex]->cellScalarValuesHistogram(); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::p10p90CellScalarValues(size_t scalarResultIndex, double& p10, double& p90) { - // First make sure they are calculated - const std::vector& histogr = cellScalarValuesHistogram( scalarResultIndex); - // Then return them - p10 = m_p10p90[scalarResultIndex].first; - p90 = m_p10p90[scalarResultIndex].second; + m_statisticsDataCache[scalarResultIndex]->p10p90CellScalarValues(p10, p90); } //-------------------------------------------------------------------------------------------------- @@ -239,73 +97,7 @@ void RigCaseCellResultsData::p10p90CellScalarValues(size_t scalarResultIndex, do //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::meanCellScalarValues(size_t scalarResultIndex, double& meanValue) { - CVF_ASSERT(scalarResultIndex < resultCount()); - - // Extend array and cache vars - - if (scalarResultIndex >= m_meanValues.size() ) - { - m_meanValues.resize(scalarResultIndex+1, HUGE_VAL); - } - - if (m_meanValues[scalarResultIndex] != HUGE_VAL) - { - meanValue = m_meanValues[scalarResultIndex]; - return; - } - - double valueSum = 0.0; - size_t count = 0; - - if (scalarResultIndex == m_combinedTransmissibilityResultIndex) - { - size_t tranX, tranY, tranZ; - if (findTransmissibilityResults(tranX, tranY, tranZ)) - { - for (size_t tIdx = 0; tIdx < timeStepCount(tranX); tIdx++) - { - { - std::vector& values = m_cellScalarResults[tranX][tIdx]; - for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) - { - valueSum += values[cIdx]; - } - count += values.size(); - } - { - std::vector& values = m_cellScalarResults[tranY][tIdx]; - for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) - { - valueSum += values[cIdx]; - } - count += values.size(); - } - { - std::vector& values = m_cellScalarResults[tranZ][tIdx]; - for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) - { - valueSum += values[cIdx]; - } - count += values.size(); - } - } - } - } - else - { - for (size_t tIdx = 0; tIdx < timeStepCount(scalarResultIndex); tIdx++) - { - std::vector& values = m_cellScalarResults[scalarResultIndex][tIdx]; - for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) - { - valueSum += values[cIdx]; - } - count += values.size(); - } - } - - m_meanValues[scalarResultIndex] = valueSum/count; - meanValue = m_meanValues[scalarResultIndex]; + m_statisticsDataCache[scalarResultIndex]->meanCellScalarValues(meanValue); } //-------------------------------------------------------------------------------------------------- @@ -435,6 +227,29 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty m_cellScalarResults.push_back(std::vector >()); ResultInfo resInfo(type, needsToBeStored, false, resultName, scalarResultIndex); m_resultInfos.push_back(resInfo); + + // Create statistics calculator and add cache object + if (resultName == RimDefines::combinedTransmissibilityResultName()) + { + size_t tranX = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANX"); + size_t tranY = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANY"); + size_t tranZ = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANZ"); + + cvf::ref calc = new RigMultipleDatasetStatCalc(); + calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranX)); + calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranY)); + calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranZ)); + + cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); + m_statisticsDataCache.push_back(dataCache.p()); + } + else + { + cvf::ref calc = new RigNativeStatCalc(this, scalarResultIndex); + + cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); + m_statisticsDataCache.push_back(dataCache.p()); + } } return scalarResultIndex; @@ -460,20 +275,9 @@ QStringList RigCaseCellResultsData::resultNames(RimDefines::ResultCatType resTyp //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::recalculateMinMax(size_t scalarResultIndex) +void RigCaseCellResultsData::recalculateStatistics(size_t scalarResultIndex) { - // Make sure cached max min values are recalculated next time asked for, since - // the data could be changed. - - if (scalarResultIndex < m_maxMinValues.size()) - { - m_maxMinValues[scalarResultIndex] = std::make_pair(HUGE_VAL, -HUGE_VAL); - } - - if (scalarResultIndex < m_maxMinValuesPrTs.size()) - { - m_maxMinValuesPrTs[scalarResultIndex].clear(); - } + m_statisticsDataCache[scalarResultIndex]->clearAllStatistics(); } //-------------------------------------------------------------------------------------------------- @@ -592,15 +396,9 @@ void RigCaseCellResultsData::removeResult(const QString& resultName) void RigCaseCellResultsData::clearAllResults() { m_cellScalarResults.clear(); - m_maxMinValues.clear(); - m_histograms.clear(); - m_p10p90.clear(); - m_meanValues.clear(); - m_maxMinValuesPrTs.clear(); m_resultInfos.clear(); } - //-------------------------------------------------------------------------------------------------- /// Removes all the actual numbers put into this object, and frees up the memory. /// Does not touch the metadata in any way @@ -673,122 +471,6 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, double& pos, double& neg) -{ - pos = HUGE_VAL; - neg = -HUGE_VAL; - - CVF_ASSERT(scalarResultIndex < resultCount()); - - // Extend array and cache vars - - if (scalarResultIndex >= m_posNegClosestToZero.size() ) - { - m_posNegClosestToZero.resize(scalarResultIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL)); - } - - if (m_posNegClosestToZero[scalarResultIndex].first != HUGE_VAL) - { - pos = m_posNegClosestToZero[scalarResultIndex].first; - neg = m_posNegClosestToZero[scalarResultIndex].second; - - return; - } - - size_t i; - for (i = 0; i < timeStepCount(scalarResultIndex); i++) - { - double tsNeg, tsPos; - posNegClosestToZero(scalarResultIndex, i, tsPos, tsNeg); - if (tsNeg > neg && tsNeg < 0) neg = tsNeg; - if (tsPos < pos && tsPos > 0) pos = tsPos; - } - - m_posNegClosestToZero[scalarResultIndex].first = pos; - m_posNegClosestToZero[scalarResultIndex].second= neg; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::posNegClosestToZero(size_t scalarResultIndex, size_t timeStepIndex, double& pos, double& neg) -{ - pos = HUGE_VAL; - neg = -HUGE_VAL; - - CVF_ASSERT(scalarResultIndex < resultCount()); - - if (timeStepIndex >= m_cellScalarResults[scalarResultIndex].size()) - { - return; - } - - if (scalarResultIndex >= m_posNegClosestToZeroPrTs.size()) - { - m_posNegClosestToZeroPrTs.resize(scalarResultIndex+1); - } - - if (timeStepIndex >= m_posNegClosestToZeroPrTs[scalarResultIndex].size()) - { - m_posNegClosestToZeroPrTs[scalarResultIndex].resize(timeStepIndex+1, std::make_pair(HUGE_VAL, -HUGE_VAL)); - } - - if (m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first != HUGE_VAL) - { - pos = m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first; - neg = m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].second; - - return; - } - - if (scalarResultIndex == m_combinedTransmissibilityResultIndex) - { - size_t tranX, tranY, tranZ; - if (findTransmissibilityResults(tranX, tranY, tranZ)) - { - double traPos, traNeg; - posNegClosestToZero(tranX, timeStepIndex, traPos, traNeg); - if ( 0 < traPos && traPos < pos ) pos = traPos; - if ( neg < traNeg && traNeg < 0 ) neg = traNeg; - posNegClosestToZero(tranY, timeStepIndex, traPos, traNeg); - if ( 0 < traPos && traPos < pos ) pos = traPos; - if ( neg < traNeg && traNeg < 0 ) neg = traNeg; - posNegClosestToZero(tranZ, timeStepIndex, traPos, traNeg); - if ( 0 < traPos && traPos < pos ) pos = traPos; - if ( neg < traNeg && traNeg < 0 ) neg = traNeg; - } - - return; - } - - std::vector& values = m_cellScalarResults[scalarResultIndex][timeStepIndex]; - - size_t i; - for (i = 0; i < values.size(); i++) - { - if (values[i] == HUGE_VAL) - { - continue; - } - - if (values[i] < pos && values[i] > 0) - { - pos = values[i]; - } - - if (values[i] > neg && values[i] < 0) - { - neg = values[i]; - } - } - - m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].first = pos; - m_posNegClosestToZeroPrTs[scalarResultIndex][timeStepIndex].second= neg; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -800,8 +482,7 @@ void RigCaseCellResultsData::createCombinedTransmissibilityResult() size_t tranX, tranY, tranZ; if (!findTransmissibilityResults(tranX, tranY, tranZ)) return; - - m_combinedTransmissibilityResultIndex = addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index ec88739efa..603fb41b4f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -18,14 +18,18 @@ #pragma once +#include "RifReaderInterface.h" + #include "RimDefines.h" + #include + #include #include -#include "RifReaderInterface.h" class RifReaderInterface; class RigMainGrid; +class RigStatisticsDataCache; //================================================================================================== /// Class containing the results for the complete number of active cells. Both main grid and LGR's @@ -38,7 +42,7 @@ class RigCaseCellResultsData : public cvf::Object void setMainGrid(RigMainGrid* ownerGrid); // Max and min values of the results - void recalculateMinMax(size_t scalarResultIndex); + void recalculateStatistics(size_t scalarResultIndex); void minMaxCellScalarValues(size_t scalarResultIndex, double& min, double& max); void minMaxCellScalarValues(size_t scalarResultIndex, size_t timeStepIndex, double& min, double& max); void posNegClosestToZero(size_t scalarResultIndex, double& pos, double& neg); @@ -113,16 +117,7 @@ class RigCaseCellResultsData : public cvf::Object private: std::vector< std::vector< std::vector > > m_cellScalarResults; ///< Scalar results on the complete reservoir for each Result index (ResultVariable) and timestep - std::vector< std::pair > m_maxMinValues; ///< Max min values for each Result index - std::vector< std::pair > m_posNegClosestToZero; - std::vector< std::vector > m_histograms; ///< Histogram for each Result Index - std::vector< std::pair > m_p10p90; ///< P10 and p90 values for each Result Index - std::vector< double > m_meanValues; ///< Mean value for each Result Index - - std::vector< std::vector< std::pair > > m_maxMinValuesPrTs; ///< Max min values for each Result index and timestep - std::vector< std::vector< std::pair > > m_posNegClosestToZeroPrTs; - - size_t m_combinedTransmissibilityResultIndex; + cvf::Collection m_statisticsDataCache; private: std::vector m_resultInfos; diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp new file mode 100644 index 0000000000..48d98e035c --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp @@ -0,0 +1,240 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigStatisticsCalculator.h" + +#include "RigStatisticsMath.h" +#include "RigCaseCellResultsData.h" + +#include // Needed for HUGE_VAL on Linux + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsCalculator::meanCellScalarValue(double& meanValue) +{ + double valueSum = 0.0; + size_t sampleCount = 0; + + this->valueSumAndSampleCount(valueSum, sampleCount); + + if (sampleCount == 0) + { + meanValue = HUGE_VAL; + } + else + { + meanValue = valueSum / sampleCount; + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigNativeStatCalc::RigNativeStatCalc(RigCaseCellResultsData* cellResultsData, size_t scalarResultIndex) + : m_resultsData(cellResultsData), + m_scalarResultIndex(scalarResultIndex) +{ + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigNativeStatCalc::minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max) +{ + std::vector& values = m_resultsData->cellScalarResults(m_scalarResultIndex, timeStepIndex); + + size_t i; + for (i = 0; i < values.size(); i++) + { + if (values[i] == HUGE_VAL) + { + continue; + } + + if (values[i] < min) + { + min = values[i]; + } + + if (values[i] > max) + { + max = values[i]; + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigNativeStatCalc::posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg) +{ + std::vector& values = m_resultsData->cellScalarResults(m_scalarResultIndex, timeStepIndex); + + size_t i; + for (i = 0; i < values.size(); i++) + { + if (values[i] == HUGE_VAL) + { + continue; + } + + if (values[i] < pos && values[i] > 0) + { + pos = values[i]; + } + + if (values[i] > neg && values[i] < 0) + { + neg = values[i]; + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigNativeStatCalc::addDataToHistogramCalculator(RigHistogramCalculator& histogramCalculator) +{ + for (size_t tIdx = 0; tIdx < m_resultsData->timeStepCount(m_scalarResultIndex); tIdx++) + { + std::vector& values = m_resultsData->cellScalarResults(m_scalarResultIndex, tIdx); + + histogramCalculator.addData(values); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigNativeStatCalc::valueSumAndSampleCount(double& valueSum, size_t& sampleCount) +{ + for (size_t tIdx = 0; tIdx < m_resultsData->timeStepCount(m_scalarResultIndex); tIdx++) + { + std::vector& values = m_resultsData->cellScalarResults(m_scalarResultIndex, tIdx); + for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) + { + valueSum += values[cIdx]; + } + sampleCount += values.size(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigNativeStatCalc::timeStepCount() +{ + return m_resultsData->timeStepCount(m_scalarResultIndex); +} + + + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigMultipleDatasetStatCalc::RigMultipleDatasetStatCalc() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::addStatisticsCalculator(RigStatisticsCalculator* statisticsCalculator) +{ + if (statisticsCalculator) + { + m_nativeStatisticsCalculators.push_back(statisticsCalculator); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max) +{ + for (size_t i = 0; i < m_nativeStatisticsCalculators.size(); i++) + { + if (m_nativeStatisticsCalculators.at(i)) + { + m_nativeStatisticsCalculators.at(i)->minMaxCellScalarValues(timeStepIndex, min, max); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg) +{ + for (size_t i = 0; i < m_nativeStatisticsCalculators.size(); i++) + { + if (m_nativeStatisticsCalculators.at(i)) + { + m_nativeStatisticsCalculators.at(i)->posNegClosestToZero(timeStepIndex, pos, neg); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::valueSumAndSampleCount(double& valueSum, size_t& sampleCount) +{ + for (size_t i = 0; i < m_nativeStatisticsCalculators.size(); i++) + { + if (m_nativeStatisticsCalculators.at(i)) + { + m_nativeStatisticsCalculators.at(i)->valueSumAndSampleCount(valueSum, sampleCount); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::addDataToHistogramCalculator(RigHistogramCalculator& histogramCalculator) +{ + for (size_t i = 0; i < m_nativeStatisticsCalculators.size(); i++) + { + if (m_nativeStatisticsCalculators.at(i)) + { + m_nativeStatisticsCalculators.at(i)->addDataToHistogramCalculator(histogramCalculator); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigMultipleDatasetStatCalc::timeStepCount() +{ + if (m_nativeStatisticsCalculators.size() > 0) + { + return m_nativeStatisticsCalculators[0]->timeStepCount(); + } + + return 0; +} + diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h new file mode 100644 index 0000000000..fbd4a43270 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfCollection.h" + +#include + +class RigHistogramCalculator; +class RigCaseCellResultsData; + +//================================================================================================== +/// +//================================================================================================== +class RigStatisticsCalculator : public cvf::Object +{ +public: + virtual void minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max) = 0; + virtual void posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg) = 0; + + void meanCellScalarValue(double& meanValue); + virtual void valueSumAndSampleCount(double& valueSum, size_t& sampleCount) = 0; + virtual void addDataToHistogramCalculator(RigHistogramCalculator& histogramCalculator) = 0; + + virtual size_t timeStepCount() = 0; +}; + + +//================================================================================================== +/// +//================================================================================================== +class RigNativeStatCalc : public RigStatisticsCalculator +{ +public: + RigNativeStatCalc(RigCaseCellResultsData* cellResultsData, size_t scalarResultIndex); + + virtual void minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max); + virtual void posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg); + virtual void valueSumAndSampleCount(double& valueSum, size_t& sampleCount); + + virtual void addDataToHistogramCalculator(RigHistogramCalculator& histogramCalculator); + virtual size_t timeStepCount(); + +private: + cvf::ref m_resultsData; + size_t m_scalarResultIndex; +}; + + +//================================================================================================== +/// +//================================================================================================== +class RigMultipleDatasetStatCalc : public RigStatisticsCalculator +{ +public: + RigMultipleDatasetStatCalc(); + void addStatisticsCalculator(RigStatisticsCalculator* statisticsCalculator); + + virtual void minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max); + virtual void posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg); + + virtual void valueSumAndSampleCount(double& valueSum, size_t& sampleCount); + virtual void addDataToHistogramCalculator(RigHistogramCalculator& histogramCalculator); + + virtual size_t timeStepCount(); + +private: + cvf::Collection m_nativeStatisticsCalculators; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp new file mode 100644 index 0000000000..f0dc353920 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp @@ -0,0 +1,205 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigStatisticsDataCache.h" + +#include "RigStatisticsCalculator.h" +#include "RigStatisticsMath.h" + +#include // Needed for HUGE_VAL on Linux + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigStatisticsDataCache::RigStatisticsDataCache(RigStatisticsCalculator* statisticsCalculator) + : m_statisticsCalculator(statisticsCalculator) +{ + clearAllStatistics(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::clearAllStatistics() +{ + m_minValue = HUGE_VAL; + m_maxValue = -HUGE_VAL; + m_posClosestToZero = -HUGE_VAL; + m_negClosestToZero = HUGE_VAL; + m_p10 = HUGE_VAL; + m_p90 = HUGE_VAL; + m_meanValue = HUGE_VAL; + + m_histogram.clear(); + m_maxMinValuesPrTs.clear(); + m_posNegClosestToZeroPrTs.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::minMaxCellScalarValues(double& min, double& max) +{ + if (m_minValue == HUGE_VAL) + { + min = HUGE_VAL; + max = -HUGE_VAL; + + size_t i; + for (i = 0; i < m_statisticsCalculator->timeStepCount(); i++) + { + double tsmin, tsmax; + this->minMaxCellScalarValues(i, tsmin, tsmax); + if (tsmin < min) min = tsmin; + if (tsmax > max) max = tsmax; + } + + m_minValue = min; + m_maxValue = max; + } + + min = m_minValue; + max = m_maxValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max) +{ + if (timeStepIndex >= m_maxMinValuesPrTs.size()) + { + m_maxMinValuesPrTs.resize(timeStepIndex + 1, std::make_pair(HUGE_VAL, -HUGE_VAL)); + } + + if (m_maxMinValuesPrTs[timeStepIndex].first == HUGE_VAL) + { + min = HUGE_VAL; + max = -HUGE_VAL; + + m_statisticsCalculator->minMaxCellScalarValues(timeStepIndex, min, max); + + m_maxMinValuesPrTs[timeStepIndex].first = min; + m_maxMinValuesPrTs[timeStepIndex].second = max; + } + + min = m_maxMinValuesPrTs[timeStepIndex].first; + max = m_maxMinValuesPrTs[timeStepIndex].second; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::posNegClosestToZero(double& pos, double& neg) +{ + if (m_posClosestToZero == HUGE_VAL) + { + pos = HUGE_VAL; + neg = -HUGE_VAL; + + size_t i; + for (i = 0; i < m_statisticsCalculator->timeStepCount(); i++) + { + double tsNeg, tsPos; + this->posNegClosestToZero(i, tsPos, tsNeg); + if (tsNeg > neg && tsNeg < 0) neg = tsNeg; + if (tsPos < pos && tsPos > 0) pos = tsPos; + } + + m_posClosestToZero = pos; + m_negClosestToZero = neg; + } + + pos = m_posClosestToZero; + neg = m_negClosestToZero; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg) +{ + if (timeStepIndex >= m_posNegClosestToZeroPrTs.size()) + { + m_posNegClosestToZeroPrTs.resize(timeStepIndex + 1, std::make_pair(HUGE_VAL, -HUGE_VAL)); + } + + if (m_posNegClosestToZeroPrTs[timeStepIndex].first == HUGE_VAL) + { + pos = HUGE_VAL; + neg = -HUGE_VAL; + + m_statisticsCalculator->posNegClosestToZero(timeStepIndex, pos, neg); + + m_posNegClosestToZeroPrTs[timeStepIndex].first = pos; + m_posNegClosestToZeroPrTs[timeStepIndex].second = neg; + } + + pos = m_posNegClosestToZeroPrTs[timeStepIndex].first; + neg = m_posNegClosestToZeroPrTs[timeStepIndex].second; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RigStatisticsDataCache::cellScalarValuesHistogram() +{ + if (m_histogram.size() == 0) + { + double min; + double max; + size_t nBins = 100; + this->minMaxCellScalarValues(min, max); + + RigHistogramCalculator histCalc(min, max, nBins, &m_histogram); + + m_statisticsCalculator->addDataToHistogramCalculator(histCalc); + + m_p10 = histCalc.calculatePercentil(0.1); + m_p90 = histCalc.calculatePercentil(0.9); + } + + return m_histogram; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::p10p90CellScalarValues(double& p10, double& p90) +{ + // First make sure they are calculated + const std::vector& histogr = this->cellScalarValuesHistogram(); + + p10 = m_p10; + p90 = m_p90; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsDataCache::meanCellScalarValues(double& meanValue) +{ + if (m_meanValue == HUGE_VAL) + { + m_statisticsCalculator->meanCellScalarValue(m_meanValue); + } + + meanValue = m_meanValue; +} + diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h new file mode 100644 index 0000000000..b588a8f511 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigStatisticsCalculator.h" + +#include "cvfBase.h" +#include "cvfObject.h" + +#include + + +//================================================================================================== +/// +//================================================================================================== +class RigStatisticsDataCache : public cvf::Object +{ +public: + RigStatisticsDataCache(RigStatisticsCalculator* statisticsCalculator); + + void clearAllStatistics(); + + void minMaxCellScalarValues(double& min, double& max); + void minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max); + void posNegClosestToZero(double& pos, double& neg); + void posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg); + + void p10p90CellScalarValues(double& p10, double& p90); + void meanCellScalarValues(double& meanValue); + const std::vector& cellScalarValuesHistogram(); + +private: + double m_minValue; + double m_maxValue; + double m_posClosestToZero; + double m_negClosestToZero; + + double m_p10; + double m_p90; + double m_meanValue; + + std::vector m_histogram; + + std::vector > m_maxMinValuesPrTs; ///< Max min values for each time step + std::vector > m_posNegClosestToZeroPrTs; ///< PosNeg values for each time step + + cvf::ref m_statisticsCalculator; +}; + diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index a8257f834b..7a7e83bf8e 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -640,7 +640,7 @@ class RiaSetActiveCellProperty: public RiaSocketCommand m_currentReservoir->reservoirData() && m_currentReservoir->reservoirData()->results(m_porosityModelEnum) ) { - m_currentReservoir->reservoirData()->results(m_porosityModelEnum)->recalculateMinMax(m_currentScalarIndex); + m_currentReservoir->reservoirData()->results(m_porosityModelEnum)->recalculateStatistics(m_currentScalarIndex); } for (size_t i = 0; i < m_currentReservoir->reservoirViews.size(); ++i) @@ -974,7 +974,7 @@ class RiaSetGridProperty : public RiaSocketCommand m_currentReservoir->reservoirData() && m_currentReservoir->reservoirData()->results(m_porosityModelEnum) ) { - m_currentReservoir->reservoirData()->results(m_porosityModelEnum)->recalculateMinMax(m_currentScalarIndex); + m_currentReservoir->reservoirData()->results(m_porosityModelEnum)->recalculateStatistics(m_currentScalarIndex); } for (size_t i = 0; i < m_currentReservoir->reservoirViews.size(); ++i) From 6418928bd2544f7c24e457e5472122b16432ee1f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 10:33:29 +0200 Subject: [PATCH 256/346] Faults: Skip out of range cell index --- .../ModelVisualization/RivFaultGeometryGenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index a0ef33d344..1ba2678115 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -166,6 +166,8 @@ void RivFaultGeometryGenerator::computeArrays() size_t cellIndex = faultFaces[fIdx].m_nativeReservoirCellIndex; cvf::StructGridInterface::FaceType face = faultFaces[fIdx].m_nativeFace; + if (cellIndex >= m_cellVisibility->size()) continue; + if (!m_computeNativeFaultFaces) { cellIndex = faultFaces[fIdx].m_oppositeReservoirCellIndex; From 659c90e3e9f7b9db2aa432a006e4345e0854808e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 10:38:35 +0200 Subject: [PATCH 257/346] Fwk: Created a separate update function for uiIconState --- .../cafProjectDataModel/cafPdmDocument.cpp | 26 +++++++++++++++++++ .../cafProjectDataModel/cafPdmDocument.h | 1 + 2 files changed, 27 insertions(+) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp index 2de957026c..420b1df072 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp @@ -113,6 +113,31 @@ void PdmObjectGroup::initAfterReadTraversal(PdmObject* object) } object->initAfterRead(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmObjectGroup::updateUiIconStateRecursively(PdmObject* object) +{ + if (object == NULL) return; + + std::vector fields; + object->fields(fields); + + std::vector children; + size_t fIdx; + for (fIdx = 0; fIdx < fields.size(); ++fIdx) + { + if (fields[fIdx]) fields[fIdx]->childObjects(&children); + } + + size_t cIdx; + for (cIdx = 0; cIdx < children.size(); ++cIdx) + { + PdmObjectGroup::updateUiIconStateRecursively(children[cIdx]); + } + object->updateUiIconFromToggleField(); } @@ -167,6 +192,7 @@ void PdmDocument::readFile(QIODevice* xmlFile) // after everything is read from file PdmDocument::initAfterReadTraversal(this); + PdmDocument::updateUiIconStateRecursively(this); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h index bdd8ff8e4e..3df3fe60e5 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h @@ -63,6 +63,7 @@ class PdmObjectGroup : public PdmObject void addObject(PdmObject * obj); static void initAfterReadTraversal(PdmObject * root); + static void updateUiIconStateRecursively(PdmObject * root); template void objectsByType(std::vector >* typedObjects ) const From 786f3bbd9cbd8cd51971bdeb9676d691c7bc985b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 10:57:08 +0200 Subject: [PATCH 258/346] Fwk: Moved static functions to pdmDocument --- .../cafProjectDataModel/cafPdmDocument.cpp | 107 +++++++++--------- .../cafProjectDataModel/cafPdmDocument.h | 6 +- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp index 420b1df072..0dec597148 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.cpp @@ -89,57 +89,6 @@ void PdmObjectGroup::addObject(PdmObject * obj) objects.push_back(obj); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void PdmObjectGroup::initAfterReadTraversal(PdmObject* object) -{ - if (object == NULL) return; - - std::vector fields; - object->fields(fields); - - std::vector children; - size_t fIdx; - for (fIdx = 0; fIdx < fields.size(); ++fIdx) - { - if (fields[fIdx]) fields[fIdx]->childObjects(&children); - } - - size_t cIdx; - for (cIdx = 0; cIdx < children.size(); ++cIdx) - { - PdmObjectGroup::initAfterReadTraversal(children[cIdx]); - } - - object->initAfterRead(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void PdmObjectGroup::updateUiIconStateRecursively(PdmObject* object) -{ - if (object == NULL) return; - - std::vector fields; - object->fields(fields); - - std::vector children; - size_t fIdx; - for (fIdx = 0; fIdx < fields.size(); ++fIdx) - { - if (fields[fIdx]) fields[fIdx]->childObjects(&children); - } - - size_t cIdx; - for (cIdx = 0; cIdx < children.size(); ++cIdx) - { - PdmObjectGroup::updateUiIconStateRecursively(children[cIdx]); - } - - object->updateUiIconFromToggleField(); -} @@ -228,7 +177,9 @@ void PdmDocument::writeFile(QIODevice* xmlFile) xmlStream.writeEndDocument(); } - +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- void PdmDocument::setupBeforeSaveTraversal(PdmObject * object) { if (object == NULL) return; @@ -252,5 +203,57 @@ void PdmDocument::setupBeforeSaveTraversal(PdmObject * object) object->setupBeforeSave(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmDocument::initAfterReadTraversal(PdmObject* object) +{ + if (object == NULL) return; + + std::vector fields; + object->fields(fields); + + std::vector children; + size_t fIdx; + for (fIdx = 0; fIdx < fields.size(); ++fIdx) + { + if (fields[fIdx]) fields[fIdx]->childObjects(&children); + } + + size_t cIdx; + for (cIdx = 0; cIdx < children.size(); ++cIdx) + { + PdmDocument::initAfterReadTraversal(children[cIdx]); + } + + object->initAfterRead(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmDocument::updateUiIconStateRecursively(PdmObject* object) +{ + if (object == NULL) return; + + std::vector fields; + object->fields(fields); + + std::vector children; + size_t fIdx; + for (fIdx = 0; fIdx < fields.size(); ++fIdx) + { + if (fields[fIdx]) fields[fIdx]->childObjects(&children); + } + + size_t cIdx; + for (cIdx = 0; cIdx < children.size(); ++cIdx) + { + PdmDocument::updateUiIconStateRecursively(children[cIdx]); + } + + object->updateUiIconFromToggleField(); +} + } //End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h index 3df3fe60e5..c1a519ef90 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h @@ -62,9 +62,6 @@ class PdmObjectGroup : public PdmObject void removeNullPtrs(); void addObject(PdmObject * obj); - static void initAfterReadTraversal(PdmObject * root); - static void updateUiIconStateRecursively(PdmObject * root); - template void objectsByType(std::vector >* typedObjects ) const { @@ -129,8 +126,11 @@ class PdmDocument: public PdmObjectGroup void readFile(QIODevice* device); void writeFile(QIODevice* device); + static void updateUiIconStateRecursively(PdmObject * root); + private: static void setupBeforeSaveTraversal(PdmObject * root); + static void initAfterReadTraversal(PdmObject * root); }; From af89f3e45eef72319fdd696d3a2f71af6b8107e0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 10:57:55 +0200 Subject: [PATCH 259/346] Use icon update functions from pdmDocument --- ApplicationCode/ProjectDataModel/RimCase.cpp | 2 +- ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 66178129ec..f7561fb37d 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -138,7 +138,7 @@ RimReservoirView* RimCase::createAndAddReservoirView() RimReservoirView* riv = new RimReservoirView(); riv->setEclipseCase(this); - caf::PdmDocument::initAfterReadTraversal(riv); + caf::PdmDocument::updateUiIconStateRecursively(riv); size_t i = reservoirViews().size(); riv->name = QString("View %1").arg(i + 1); diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index dc340cb014..14f14e9ed1 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -678,7 +678,7 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG RimAnalysisModels* analysisModels = (activeOilField) ? activeOilField->analysisModels() : NULL; if (analysisModels) analysisModels->insertCaseInCaseGroup(gridCaseGroup, rimResultReservoir); - caf::PdmObjectGroup::initAfterReadTraversal(rimResultReservoir); + caf::PdmDocument::updateUiIconStateRecursively(rimResultReservoir); { QModelIndex rootIndex = getModelIndexFromPdmObject(gridCaseGroup->caseCollection()); @@ -723,7 +723,7 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG // Delete all wells to be able to copy/paste between cases, as the wells differ between cases rimReservoirView->wellCollection()->wells().deleteAllChildObjects(); - caf::PdmObjectGroup::initAfterReadTraversal(rimReservoirView); + caf::PdmDocument::updateUiIconStateRecursively(rimReservoirView); rimReservoirView->loadDataAndUpdate(); rimCase->reservoirViews().push_back(rimReservoirView); From e6358a12890f41578ae9b5ffd877601494162e74 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 11:57:31 +0200 Subject: [PATCH 260/346] Added MULTXYZ result accessor --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigCombMultResultAccessor.cpp | 142 ++++++++++++++++++ .../RigCombMultResultAccessor.h | 59 ++++++++ 3 files changed, 203 insertions(+) create mode 100644 ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp create mode 100644 ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 78e6bbc52a..06835f0e32 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -16,6 +16,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigResultModifier.h ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h @@ -48,6 +49,7 @@ ${CEE_CURRENT_LIST_DIR}RigAllGridCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp new file mode 100644 index 0000000000..fc6917ab96 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigCombMultResultAccessor.h" + +#include "RigGridBase.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigCombMultResultAccessor::RigCombMultResultAccessor(const RigGridBase* grid) + : m_grid(grid) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCombMultResultAccessor::setMultResultAccessors( + RigResultAccessor* multXPosAccessor, RigResultAccessor* multXNegAccessor, + RigResultAccessor* multYPosAccessor, RigResultAccessor* multYNegAccessor, + RigResultAccessor* multZPosAccessor, RigResultAccessor* multZNegAccessor) +{ + m_multXPosAccessor = multXPosAccessor; + m_multXNegAccessor = multXNegAccessor; + m_multYPosAccessor = multYPosAccessor; + m_multYNegAccessor = multYNegAccessor; + m_multZPosAccessor = multZPosAccessor; + m_multZNegAccessor = multZNegAccessor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombMultResultAccessor::cellScalar(size_t gridLocalCellIndex) const +{ + CVF_TIGHT_ASSERT(false); + + return HUGE_VAL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombMultResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); + + double faceScalarThisCell = nativeMultScalar(gridLocalCellIndex, faceId); + + double faceScalarNeighborCell = 1.0; + if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) + { + faceScalarNeighborCell = nativeMultScalar(neighborGridCellIdx, cvf::StructGridInterface::oppositeFace(faceId)); + } + + return faceScalarThisCell * faceScalarNeighborCell; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigCombMultResultAccessor::nativeMultScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + double faceScalar = 1.0; + + switch (faceId) + { + case cvf::StructGridInterface::POS_I: + { + if (m_multXPosAccessor.notNull()) + { + faceScalar = m_multXPosAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + case cvf::StructGridInterface::NEG_I: + { + if (m_multXNegAccessor.notNull()) + { + faceScalar = m_multXNegAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + + case cvf::StructGridInterface::POS_J: + { + if (m_multYPosAccessor.notNull()) + { + faceScalar = m_multYPosAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + case cvf::StructGridInterface::NEG_J: + { + if (m_multYNegAccessor.notNull()) + { + faceScalar = m_multYNegAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + + case cvf::StructGridInterface::POS_K: + { + if (m_multZPosAccessor.notNull()) + { + faceScalar = m_multZPosAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + case cvf::StructGridInterface::NEG_K: + { + if (m_multZNegAccessor.notNull()) + { + faceScalar = m_multZNegAccessor->cellScalar(gridLocalCellIndex); + } + break; + } + } + + return faceScalar; +} + diff --git a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h new file mode 100644 index 0000000000..b24604f7a3 --- /dev/null +++ b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigResultAccessor.h" + +#include "cvfCollection.h" + +class RigGridBase; + + +//================================================================================================== +/// +//================================================================================================== +class RigCombMultResultAccessor : public RigResultAccessor +{ +public: + RigCombMultResultAccessor(const RigGridBase* grid); + + void setMultResultAccessors( + RigResultAccessor* multXPosAccessor, + RigResultAccessor* multXNegAccessor, + RigResultAccessor* multYPosAccessor, + RigResultAccessor* multYNegAccessor, + RigResultAccessor* multZPosAccessor, + RigResultAccessor* multZNegAccessor); + + virtual double cellScalar(size_t gridLocalCellIndex) const; + virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; + +private: + double nativeMultScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; + +private: + cvf::ref m_multXPosAccessor; + cvf::ref m_multXNegAccessor; + cvf::ref m_multYPosAccessor; + cvf::ref m_multYNegAccessor; + cvf::ref m_multZPosAccessor; + cvf::ref m_multZNegAccessor; + + const RigGridBase* m_grid; +}; From be224149f01265dc9330cbb7378e2d5d30973a7e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 13:20:12 +0200 Subject: [PATCH 261/346] Added riMULTXYZ to result selection UI --- ApplicationCode/ProjectDataModel/RimDefines.h | 5 ++- .../ProjectDataModel/RimResultDefinition.cpp | 43 +++++++++++++------ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index c55a7b04e4..c95cf6ebf5 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -39,10 +39,11 @@ class RimDefines FRACTURE_MODEL }; - static QString undefinedResultName() { return "None"; } - static QString undefinedGridFaultName() { return "Undefined grid faults"; } + static QString undefinedResultName() { return "None"; } + static QString undefinedGridFaultName() { return "Undefined grid faults"; } static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } static QString ternarySaturationResultName() { return "TERNARY"; } + static QString combinedMultResultName() { return "riMULTXYZ"; } // Mock model text identifiers diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index a15c100d9b..480850b22e 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -145,16 +145,16 @@ QList RimResultDefinition::calculateValueOptions(const c { if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - hasCombinedTransmissibility = true; - continue; + optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedTransmissibilityResultName(), RimDefines::combinedTransmissibilityResultName())); + } + else if (varList[i].compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedMultResultName(), RimDefines::combinedMultResultName())); + } + else + { + optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i])); } - - optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i])); - } - - if (hasCombinedTransmissibility) - { - optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedTransmissibilityResultName(), RimDefines::combinedTransmissibilityResultName())); } bool hasAtLeastOneTernaryComponent = false; @@ -199,12 +199,27 @@ void RimResultDefinition::loadResult() RimReservoirCellResultsStorage* gridCellResults = this->currentGridCellResults(); if (gridCellResults) { - if (m_resultType() == RimDefines::STATIC_NATIVE && - m_resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + if (m_resultType() == RimDefines::STATIC_NATIVE) { - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANX"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANY"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANZ"); + if (m_resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANX"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANY"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANZ"); + } + else if (m_resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTX"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTX-"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTY"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTY-"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTZ"); + gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTZ-"); + } + else + { + gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); + } } else { From a2f4887d56396c9786ee3d0a45981bdf0bb20095 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 13:20:44 +0200 Subject: [PATCH 262/346] Added riMULTXYZ to statistics and result factory --- .../RigCaseCellResultsData.cpp | 56 +++++++++++++++++-- .../RigResultAccessorFactory.cpp | 35 ++++++++---- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 9438237e6e..40643ed329 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -243,6 +243,38 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); m_statisticsDataCache.push_back(dataCache.p()); } + else if (resultName == RimDefines::combinedMultResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX-"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY-"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + { + size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ-"); + if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); + } + + cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); + m_statisticsDataCache.push_back(dataCache.p()); + } else { cvf::ref calc = new RigNativeStatCalc(this, scalarResultIndex); @@ -476,13 +508,25 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::createCombinedTransmissibilityResult() { - size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); - if (combinedTransmissibilityIndex != cvf::UNDEFINED_SIZE_T) return; - - size_t tranX, tranY, tranZ; - if (!findTransmissibilityResults(tranX, tranY, tranZ)) return; + { + size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); + if (combinedTransmissibilityIndex == cvf::UNDEFINED_SIZE_T) + { + size_t tranX, tranY, tranZ; + if (findTransmissibilityResults(tranX, tranY, tranZ)) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); + } + } + } - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); + { + size_t combinedMultIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedMultResultName()); + if (combinedMultIndex == cvf::UNDEFINED_SIZE_T) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedMultResultName(), false, 0); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 93cffaa93b..328a8c7151 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -18,23 +18,23 @@ #include "RigResultAccessorFactory.h" -#include "RigResultAccessor.h" +#include "RigActiveCellInfo.h" #include "RigActiveCellsResultAccessor.h" #include "RigAllGridCellsResultAccessor.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigCombMultResultAccessor.h" +#include "RigCombTransResultAccessor.h" +#include "RigGridBase.h" +#include "RigMainGrid.h" +#include "RigResultAccessor.h" -#include "cvfLibCore.h" +#include "cvfAssert.h" #include "cvfBase.h" +#include "cvfLibCore.h" #include "cvfObject.h" -#include "cvfAssert.h" -#include "RigMainGrid.h" -#include "RigCaseCellResultsData.h" -#include "RigActiveCellInfo.h" -#include "RigGridBase.h" -#include "RigCaseData.h" #include -#include "RigCombTransResultAccessor.h" - //-------------------------------------------------------------------------------------------------- /// @@ -64,6 +64,21 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } + else if (uiResultName == RimDefines::combinedMultResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombMultResultAccessor(grid); + + cvf::ref multXPos = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTX"); + cvf::ref multXNeg = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTX-"); + cvf::ref multYPos = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTY"); + cvf::ref multYNeg = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTY-"); + cvf::ref multZPos = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTZ"); + cvf::ref multZNeg = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "MULTZ-"); + + cellFaceAccessObject->setMultResultAccessors(multXPos.p(), multXNeg.p(), multYPos.p(), multYNeg.p(), multZPos.p(), multZNeg.p()); + + return cellFaceAccessObject; + } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From eb96c5a7ed17cfc6f310f872f07a7c26041cbd17 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 13:35:10 +0200 Subject: [PATCH 263/346] Property filer: Do not show (combined) per face results --- .../RimCellPropertyFilter.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index 7d73bb92a8..88cd58281b 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -128,21 +128,31 @@ QList RimCellPropertyFilter::calculateValueOptions(const { QList optionItems = resultDefinition->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); - // Remove ternary from list, as it is not supported to perform filtering on a ternary result - int ternaryIndex = -1; + std::vector indicesToRemove; for (int i = 0; i < optionItems.size(); i++) { QString text = optionItems[i].optionUiText; if (text.compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0) { - ternaryIndex = i; + indicesToRemove.push_back(i); + } + else if (text.compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + indicesToRemove.push_back(i); + } + else if (text.compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + indicesToRemove.push_back(i); } } - if (ternaryIndex != -1) + std::sort(indicesToRemove.begin(), indicesToRemove.end()); + + std::vector::reverse_iterator rit; + for (rit = indicesToRemove.rbegin(); rit != indicesToRemove.rend(); ++rit) { - optionItems.takeAt(ternaryIndex); + optionItems.takeAt(*rit); } return optionItems; From 72daff665db8695b1ca5b004da56f83c8bd66acc Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 13:56:17 +0200 Subject: [PATCH 264/346] Added function used to filter out per cell results by result name --- .../RimCellEdgeResultSlot.cpp | 4 ++-- .../RimCellPropertyFilter.cpp | 10 +-------- .../ProjectDataModel/RimDefines.cpp | 21 +++++++++++++++++++ ApplicationCode/ProjectDataModel/RimDefines.h | 2 ++ .../ProjectDataModel/RimResultDefinition.cpp | 9 +++----- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index b52e9f0cec..5ef2e8ba73 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -149,7 +149,7 @@ QList RimCellEdgeResultSlot::calculateValueOptions(const int i; for (i = 0; i < varList.size(); ++i) { - if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) continue; + if (RimDefines::isPerCellFaceResult(varList[i])) continue; size_t cubeFaceIdx; for (cubeFaceIdx = 0; cubeFaceIdx < EdgeFaceEnum::size(); ++cubeFaceIdx) @@ -220,7 +220,7 @@ QStringList RimCellEdgeResultSlot::findResultVariableNames() int i; for (i = 0; i < varList.size(); ++i) { - if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) continue; + if (RimDefines::isPerCellFaceResult(varList[i])) continue; if (varList[i].contains(resultVariable)) { diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index 88cd58281b..5db902ff18 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -133,15 +133,7 @@ QList RimCellPropertyFilter::calculateValueOptions(const { QString text = optionItems[i].optionUiText; - if (text.compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0) - { - indicesToRemove.push_back(i); - } - else if (text.compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) - { - indicesToRemove.push_back(i); - } - else if (text.compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + if (RimDefines::isPerCellFaceResult(text)) { indicesToRemove.push_back(i); } diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index 9fce926af4..d0b426a023 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -46,3 +46,24 @@ namespace caf } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimDefines::isPerCellFaceResult(const QString& resultName) +{ + if (resultName.compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } + else if (resultName.compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } + else if (resultName.compare(RimDefines::ternarySaturationResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } + + return false; +} diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index c95cf6ebf5..87649fe8f7 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -39,6 +39,8 @@ class RimDefines FRACTURE_MODEL }; + static bool isPerCellFaceResult(const QString& resultName); + static QString undefinedResultName() { return "None"; } static QString undefinedGridFaultName() { return "Undefined grid faults"; } static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 480850b22e..fa4fbd1d3c 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -143,13 +143,10 @@ QList RimResultDefinition::calculateValueOptions(const c QList optionList; for (int i = 0; i < varList.size(); ++i) { - if (varList[i].compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + if (RimDefines::isPerCellFaceResult(varList[i])) { - optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedTransmissibilityResultName(), RimDefines::combinedTransmissibilityResultName())); - } - else if (varList[i].compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) - { - optionList.push_front(caf::PdmOptionItemInfo(RimDefines::combinedMultResultName(), RimDefines::combinedMultResultName())); + // Move combined per cell face results to top of list + optionList.push_front(caf::PdmOptionItemInfo(varList[i], varList[i])); } else { From f98a909e51c879077241292100fa4b4279eb7646 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 14:02:21 +0200 Subject: [PATCH 265/346] Removed obsolete code and renamed functions --- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 9 --------- .../ProjectDataModel/RimReservoirCellResultsStorage.h | 1 - ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 4 ++-- .../ReservoirDataModel/RigCaseCellResultsData.cpp | 2 +- .../ReservoirDataModel/RigCaseCellResultsData.h | 2 +- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index c46fe8b347..e34bcba704 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -720,15 +720,6 @@ size_t RimReservoirCellResultsStorage::storedResultsCount() return m_resultCacheMetaData.size(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimReservoirCellResultsStorage::createCombinedTransmissibilityResults() -{ - if (!m_cellResults) return; - - m_cellResults->createCombinedTransmissibilityResult(); -} CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorageEntryInfo, "ResultStorageEntryInfo"); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 7208bcd83e..aa90e062e8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -53,7 +53,6 @@ class RimReservoirCellResultsStorage : public caf::PdmObject RifReaderInterface* readerInterface(); void loadOrComputeSOIL(); - void createCombinedTransmissibilityResults(); void computeDepthRelatedResults(); size_t findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index b1280f90b4..0c503c5a9e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -920,12 +920,12 @@ void RimReservoirView::loadDataAndUpdate() { RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::MATRIX_RESULTS); results->loadOrComputeSOIL(); - results->createCombinedTransmissibilityResults(); + if (results->cellResults()) results->cellResults()->createPerFaceCombinedResults(); } { RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::FRACTURE_RESULTS); results->loadOrComputeSOIL(); - results->createCombinedTransmissibilityResults(); + if (results->cellResults()) results->cellResults()->createPerFaceCombinedResults(); } } } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 40643ed329..a726f5b0bb 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -506,7 +506,7 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::createCombinedTransmissibilityResult() +void RigCaseCellResultsData::createPerFaceCombinedResults() { { size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index 603fb41b4f..b2116f1713 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -70,7 +70,7 @@ class RigCaseCellResultsData : public cvf::Object size_t addEmptyScalarResult(RimDefines::ResultCatType type, const QString& resultName, bool needsToBeStored); QString makeResultNameUnique(const QString& resultNameProposal) const; - void createCombinedTransmissibilityResult(); + void createPerFaceCombinedResults(); void removeResult(const QString& resultName); void clearAllResults(); From 2fe63ece50fcd95d9bcc4a61f3dea0c852c36081 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 14:30:12 +0200 Subject: [PATCH 266/346] Use result accessors instead of StructGridScalarDataAccess --- .../ProjectDataModel/RimReservoirView.cpp | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 0c503c5a9e..77150dc4c6 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -22,6 +22,8 @@ #include "RiaPreferences.h" #include "RigCaseCellResultsData.h" #include "RigCaseData.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" #include "Rim3dOverlayInfoConfig.h" #include "RimCase.h" #include "RimCellEdgeResultSlot.h" @@ -39,8 +41,8 @@ #include "RiuMainWindow.h" #include "RiuViewer.h" #include "RivReservoirPipesPartMgr.h" -#include "RivWellPathCollectionPartMgr.h" #include "RivTernarySaturationOverlayItem.h" +#include "RivWellPathCollectionPartMgr.h" #include "cafCadNavigation.h" #include "cafCeetronPlusNavigation.h" @@ -51,7 +53,6 @@ #include "cvfOverlayScalarMapperLegend.h" #include "cvfPart.h" #include "cvfScene.h" -#include "cvfStructGridScalarDataAccess.h" #include "cvfViewport.h" #include "cvfqtUtils.h" @@ -1106,7 +1107,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, RigGridBase* grid = eclipseCase->grid(gridIndex); RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor; + cvf::ref resultAccessor; if (this->cellResult()->isTernarySaturationSelected()) { @@ -1117,9 +1118,9 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, size_t sgasScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); size_t swatScalarSetIndex = gridCellResults->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, swatScalarSetIndex); + cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, soilScalarSetIndex); + cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, swatScalarSetIndex); double scalarValue = 0.0; @@ -1139,37 +1140,54 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, else if (this->cellResult()->hasResult()) { RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor; + cvf::ref resultAccessor; if (cellResult->hasStaticResult()) { if (this->cellResult()->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) { - size_t tranX, tranY, tranZ; - if (eclipseCase->results(porosityModel)->findTransmissibilityResults(tranX, tranY, tranZ)) + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedTransmissibilityResultName()); { - cvf::ref dataAccessObjectX = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranX); - cvf::ref dataAccessObjectY = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranY); - cvf::ref dataAccessObjectZ = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, tranZ); - - double scalarValue = dataAccessObjectX->cellScalar(cellIndex); + double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); - scalarValue = dataAccessObjectY->cellScalar(cellIndex); + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); resultInfoText->append(QString("Tran Y : %1\n").arg(scalarValue)); - scalarValue = dataAccessObjectZ->cellScalar(cellIndex); + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); resultInfoText->append(QString("Tran Z : %1\n").arg(scalarValue)); } } + else if (this->cellResult()->resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref multResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedMultResultName()); + { + double scalarValue = 0.0; + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("MULTX : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_I); + resultInfoText->append(QString("MULTX- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("MULTY : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_J); + resultInfoText->append(QString("MULTY- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("MULTZ : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_K); + resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); + } + } else { - resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, this->cellResult()->gridScalarIndex()); } } else { - resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); } if (resultAccessor.notNull()) @@ -1192,7 +1210,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor = eclipseCase->TO_BE_DELETED_resultAccessor(grid, porosityModel, 0, resultIndices[idx]); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultIndices[idx]); if (resultAccessor.notNull()) { double scalarValue = resultAccessor->cellScalar(cellIndex); From cdf2b07118cdfe437adf47a6b73aaa4cd404f15d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 14:56:20 +0200 Subject: [PATCH 267/346] Removed use of cvfStructGridScalarDataAccess --- .../RivFaultGeometryGenerator.cpp | 35 ---- .../RivFaultGeometryGenerator.h | 4 - .../ModelVisualization/RivGridPartMgr.cpp | 18 -- .../ReservoirDataModel/RigCaseData.cpp | 20 -- .../ReservoirDataModel/RigCaseData.h | 6 - .../RigResultAccessorFactory.cpp | 178 ------------------ .../RigResultAccessorFactory.h | 10 - 7 files changed, 271 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index 1ba2678115..eccc672ccf 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -23,7 +23,6 @@ #include "cvfDrawableGeo.h" #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfOutlineEdgeExtractor.h" -#include "cvfStructGridScalarDataAccess.h" #include "cvfStructGridGeometryGenerator.h" #include "cvfScalarMapper.h" @@ -201,40 +200,6 @@ void RivFaultGeometryGenerator::computeArrays() m_vertices->assign(vertices); } -//-------------------------------------------------------------------------------------------------- -/// Calculates the texture coordinates in a "nearly" one dimensional texture. -/// Undefined values are coded with a y-texture coordinate value of 1.0 instead of the normal 0.5 -//-------------------------------------------------------------------------------------------------- -void RivFaultGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::StructGridScalarDataAccess* resultAccessor, const cvf::ScalarMapper* mapper) const -{ - if (!resultAccessor) return; - - size_t numVertices = m_quadMapper->quadCount()*4; - - textureCoords->resize(numVertices); - cvf::Vec2f* rawPtr = textureCoords->ptr(); - - double cellScalarValue; - cvf::Vec2f texCoord; - -#pragma omp parallel for private(texCoord, cellScalarValue) - for (int i = 0; i < static_cast(m_quadMapper->quadCount()); i++) - { - cellScalarValue = resultAccessor->cellScalar(m_quadMapper->cellIndex(i)); - texCoord = mapper->mapToTextureCoord(cellScalarValue); - if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's - { - texCoord[1] = 1.0f; - } - - size_t j; - for (j = 0; j < 4; j++) - { - rawPtr[i*4 + j] = texCoord; - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index f6ec717715..987b26a0dd 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -47,10 +47,6 @@ class RivFaultGeometryGenerator : public cvf::Object void setCellVisibility(const cvf::UByteArray* cellVisibilities ); - void textureCoordinates(cvf::Vec2fArray* textureCoords, - const cvf::StructGridScalarDataAccess* resultAccessor, - const cvf::ScalarMapper* mapper) const; - // Mapping between cells and geometry const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper() { return m_quadMapper.p(); } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 6dc24bd149..d92e033a3d 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -58,7 +58,6 @@ #include "cvfShaderSourceProvider.h" #include "cvfShaderSourceRepository.h" #include "cvfStructGrid.h" -#include "cvfStructGridGeometryGenerator.h" #include "cvfUniform.h" @@ -295,20 +294,3 @@ RivGridPartMgr::~RivGridPartMgr() } -//-------------------------------------------------------------------------------------------------- -/// 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) - { - } -}; - - diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 4aa6af1889..2d7b204c48 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -485,26 +485,6 @@ const RigCaseCellResultsData* RigCaseData::results(RifReaderInterface::PorosityM return m_fractureModelResults.p(); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RigCaseData::TO_BE_DELETED_resultAccessor(const RigGridBase* grid, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex) -{ - if (timeStepIndex != cvf::UNDEFINED_SIZE_T && - scalarSetIndex != cvf::UNDEFINED_SIZE_T) - { - cvf::ref dataAccess = RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(this, grid->gridIndex(), porosityModel, timeStepIndex, scalarSetIndex); - return dataAccess; - } - - return NULL; - -} - - /* //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index 9177e5d7ad..d69ab9f1cd 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -53,12 +53,6 @@ class RigCaseData: public cvf::Object const RigActiveCellInfo* activeCellInfo(RifReaderInterface::PorosityModelResultType porosityModel) const; void setActiveCellInfo(RifReaderInterface::PorosityModelResultType porosityModel, RigActiveCellInfo* activeCellInfo); - - cvf::ref TO_BE_DELETED_resultAccessor(const RigGridBase* grid, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex); - void setWellResults(const cvf::Collection& data); const cvf::Collection& wellResults() { return m_wellResults; } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 328a8c7151..a9d092b63d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -194,181 +194,3 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa } } - - - -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -// Rest of this file is to be deleted -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class RigGridAllCellsScalarDataAccess : public cvf::StructGridScalarDataAccess -{ -public: - RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues); - - virtual double cellScalar(size_t gridLocalCellIndex) const; - virtual void setCellScalar(size_t cellIndex, double value); - -private: - const RigGridBase* m_grid; - std::vector* m_reservoirResultValues; -}; - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RigGridAllCellsScalarDataAccess::RigGridAllCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues) - : m_grid(grid), - m_reservoirResultValues(reservoirResultValues) -{ - CVF_ASSERT(reservoirResultValues != NULL); - CVF_ASSERT(grid != NULL); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigGridAllCellsScalarDataAccess::cellScalar(size_t gridLocalCellIndex) const -{ - if (m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - - return m_reservoirResultValues->at(reservoirCellIndex); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigGridAllCellsScalarDataAccess::setCellScalar(size_t gridLocalCellIndex, double scalarValue) -{ - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - CVF_TIGHT_ASSERT(reservoirCellIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[reservoirCellIndex] = scalarValue; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -class RigGridActiveCellsScalarDataAccess : public cvf::StructGridScalarDataAccess -{ -public: - RigGridActiveCellsScalarDataAccess(const RigGridBase* grid, std::vector* reservoirResultValues, const RigActiveCellInfo* activeCellInfo) - : m_grid(grid), - m_reservoirResultValues(reservoirResultValues), - m_activeCellInfo(activeCellInfo) - { - - CVF_ASSERT(grid != NULL); - } - - virtual double cellScalar(size_t gridLocalCellIndex) const - { - if (m_reservoirResultValues == NULL || m_reservoirResultValues->size() == 0 ) return HUGE_VAL; - - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); - if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL; - - CVF_TIGHT_ASSERT(resultValueIndex < m_reservoirResultValues->size()); - - return m_reservoirResultValues->at(resultValueIndex); - } - - //-------------------------------------------------------------------------------------------------- - /// - //-------------------------------------------------------------------------------------------------- - virtual void setCellScalar(size_t gridLocalCellIndex, double scalarValue) - { - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex); - - CVF_TIGHT_ASSERT(m_reservoirResultValues != NULL && resultValueIndex < m_reservoirResultValues->size()); - - (*m_reservoirResultValues)[resultValueIndex] = scalarValue; - } - -private: - const RigActiveCellInfo* m_activeCellInfo; - const RigGridBase* m_grid; - std::vector* m_reservoirResultValues; -}; - - - -class StructGridScalarDataAccessHugeVal : public cvf::StructGridScalarDataAccess -{ -public: - virtual double cellScalar(size_t cellIndex) const - { - return HUGE_VAL; - } - virtual void setCellScalar(size_t cellIndex, double value) - { - } -}; - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref RigResultAccessorFactory::TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex) -{ - CVF_ASSERT(gridIndex < eclipseCase->gridCount()); - CVF_ASSERT(eclipseCase); - CVF_ASSERT(eclipseCase->results(porosityModel)); - CVF_ASSERT(eclipseCase->activeCellInfo(porosityModel)); - - RigGridBase *grid = eclipseCase->grid(gridIndex); - - if (!eclipseCase || !eclipseCase->results(porosityModel) || !eclipseCase->activeCellInfo(porosityModel)) - { - return NULL; - } - - std::vector< std::vector >& scalarSetResults = eclipseCase->results(porosityModel)->cellScalarResults(scalarSetIndex); - - // A generated result with a generated results for a subset of time steps, will end up with a result container with less entries than time steps - // See RiaSetGridProperty command in RiaPropertyDataCommands - // - // Some functions requires a valid data access object to be present, these might be rewritten to avoid this dummy object always returning HUGE_VAL - if (timeStepIndex >= scalarSetResults.size()) - { - cvf::ref object = new StructGridScalarDataAccessHugeVal; - - return object; - } - - std::vector* resultValues = NULL; - if (timeStepIndex < scalarSetResults.size()) - { - resultValues = &(scalarSetResults[timeStepIndex]); - } - - bool useGlobalActiveIndex = eclipseCase->results(porosityModel)->isUsingGlobalActiveIndex(scalarSetIndex); - if (useGlobalActiveIndex) - { - cvf::ref object = new RigGridActiveCellsScalarDataAccess(grid, resultValues, eclipseCase->activeCellInfo(porosityModel)); - return object; - } - else - { - cvf::ref object = new RigGridAllCellsScalarDataAccess(grid, resultValues); - return object; - } -} diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index 55c8fff48f..a0b27e8412 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -22,8 +22,6 @@ #include "RigResultAccessor.h" #include "RimDefines.h" -#include "cvfStructGridScalarDataAccess.h" - class RigActiveCellInfo; class RigGridBase; @@ -53,14 +51,6 @@ class RigResultAccessorFactory size_t resultIndex); - // TO BE DELETED - static cvf::ref - TO_BE_DELETED_createNativeDataAccessObject(RigCaseData* eclipseCase, - size_t gridIndex, - RifReaderInterface::PorosityModelResultType porosityModel, - size_t timeStepIndex, - size_t scalarSetIndex); - private: static cvf::ref From 7e815a86414a59be6a9338b1e16b760eab6872a0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 19 Aug 2014 14:57:36 +0200 Subject: [PATCH 268/346] Corrected combined mult result name --- ApplicationCode/ProjectDataModel/RimDefines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 87649fe8f7..69f3823818 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -45,7 +45,7 @@ class RimDefines static QString undefinedGridFaultName() { return "Undefined grid faults"; } static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } static QString ternarySaturationResultName() { return "TERNARY"; } - static QString combinedMultResultName() { return "riMULTXYZ"; } + static QString combinedMultResultName() { return "MULTXYZ"; } // Mock model text identifiers From a3af1001898443cf35c2e7da6eb3d58e77b9806b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 19 Aug 2014 14:30:26 +0200 Subject: [PATCH 269/346] riTRANXYZ: Added to build system. First implementation. --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../RigCombRiTransResultAccessor.cpp | 153 +++++++++++++++--- .../RigCombRiTransResultAccessor.h | 6 + .../ReservoirDataModel/cvfGeometryTools.cpp | 54 +++++++ .../ReservoirDataModel/cvfGeometryTools.h | 2 + 5 files changed, 192 insertions(+), 25 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index 06835f0e32..b840aa81f7 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -17,6 +17,7 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.h +${CEE_CURRENT_LIST_DIR}RigCombRiTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigResultModifier.h ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h @@ -50,6 +51,7 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.cpp +${CEE_CURRENT_LIST_DIR}RigCombRiTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp index 42fb536878..78b72b8d34 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp @@ -18,10 +18,12 @@ #include "RigCombRiTransResultAccessor.h" +#include "RigMainGrid.h" #include "RigGridBase.h" +#include "RigCell.h" #include - +#include "cvfGeometryTools.h" //-------------------------------------------------------------------------------------------------- /// @@ -65,7 +67,7 @@ double RigCombRiTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const return HUGE_VAL; } -double RigCombRiTransResultAccessor::getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +double RigCombRiTransResultAccessor::getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const { switch (faceId) { @@ -84,61 +86,162 @@ double RigCombRiTransResultAccessor::getPermValue(size_t gridLocalCellIndex, cvf case cvf::StructGridInterface::POS_K: case cvf::StructGridInterface::NEG_K: { - return zPermAccessor->cellScalar(gridLocalCellIndex); + return m_zPermAccessor->cellScalar(gridLocalCellIndex); } break; } return HUGE_VAL; } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::calculateHalfCellTrans( size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) +double RigCombRiTransResultAccessor::getNtgValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId ) const { - double perm = getPermValue(gridLocalCellIndex, faceId); double ntg = 1.0; - - if (faceId != cvf::StructGridInterface::POS_K && faceId != cvf::StructGridInterface::NEG_K) + + if (faceId != cvf::StructGridInterface::POS_K && faceId != cvf::StructGridInterface::NEG_K) { m_ntgAccessor->cellScalar(gridLocalCellIndex); } - RigCell& cell = m_grid->cell(gridLocalCellIndex); - - cvf::Vec3d centerToFace = cell.faceCenter(faceId) - cell.center(); - cvf::Vec3d faceAreaVec = cell.faceNormalWithAreaLenght(faceId); + return ntg; +} - double halfCellTrans = perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double halfCellTransmissibility( double perm , double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) +{ + return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); +} - return halfCellTrans; +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) +{ + return cdarchy * mult / ( ( 1 / halfCellTrans) + (1 / neighborHalfCellTrans) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +double RigCombRiTransResultAccessor::calculateHalfCellTrans(size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, bool isFaultFace) const { - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace(reservoirCellIndex, faceId); + const RigCell& cell = m_grid->cell(gridLocalCellIndex); - if (fault) - { + + cvf::Vec3d faceAreaVec; + cvf::Vec3d faceCenter; + if (isFaultFace) + { + + calculateConnectionGeometry( gridLocalCellIndex, neighborGridCellIdx, faceId, &faceCenter, &faceAreaVec); } else { - size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); + const RigCell& cell = m_grid->cell(gridLocalCellIndex); + faceCenter = cell.faceCenter(faceId); + + faceAreaVec = cell.faceNormalWithAreaLenght(faceId); + } + + cvf::Vec3d centerToFace = faceCenter - cell.center(); + + double perm = getPermValue(gridLocalCellIndex, faceId); + double ntg = getNtgValue(gridLocalCellIndex, faceId ); + + return halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); +} + +void RigCombRiTransResultAccessor::calculateConnectionGeometry( size_t gridLocalCellIndex, size_t neighborGridCellIdx, + cvf::StructGridInterface::FaceType faceId, + cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) const +{ + CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); + + *faceCenter = cvf::Vec3d::ZERO; + *faceAreaVec = cvf::Vec3d::ZERO; + const RigMainGrid* mainGrid = m_grid->mainGrid(); + + const RigCell& c1 = m_grid->cell(gridLocalCellIndex); + const RigCell& c2 = m_grid->cell(neighborGridCellIdx); + + std::vector polygon; + std::vector intersections; + caf::SizeTArray4 face1; + caf::SizeTArray4 face2; + c1.faceIndices(faceId, &face1); + c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); + + bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( + &polygon, + &intersections, + (cvf::EdgeIntersectStorage*)NULL, + cvf::wrapArrayConst(&(mainGrid->nodes())), + face1.data(), + face2.data(), + 1e-6); + + + if (foundOverlap) + { + std::vector realPolygon; - if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) + for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) { - double halfCellTrans = calculateHalfCellTrans(gridLocalCellIndex, faceId); - double neighborHalfCellTrans = calculateHalfCellTrans(neighborGridCellIdx, cvf::StructGridInterface::oppositeFace(faceId)); + if (polygon[pIdx] < m_grid->mainGrid()->nodes().size()) + realPolygon.push_back(m_grid->mainGrid()->nodes()[polygon[pIdx]]); + else + realPolygon.push_back(intersections[polygon[pIdx] - m_grid->mainGrid()->nodes().size()]); + } - return m_cdarchy/ ( ( 1 / halfCellTrans) + (1 / neighborHalfCellTrans) ); + // Polygon center + for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) + { + *faceCenter += realPolygon[pIdx]; } + + *faceCenter *= 1.0/realPolygon.size(); + + // Polygon area vector + + *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); + + } + +} +//-------------------------------------------------------------------------------------------------- +/// +/// Neighbour cell transmisibilities only is calculated here +/// Not NNC transmisibilities. Thart has to be done separatly elsewhere +/// +/// Todo: What about Grid to Grid connections ? +/// Todo: needs optimization. Things are done several times. Caching of the results should be considered. etc. +/// +//-------------------------------------------------------------------------------------------------- +double RigCombRiTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const +{ + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) + { + size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); + const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace(reservoirCellIndex, faceId); + bool isOnFault = fault; + + double halfCellTrans = 0; + double neighborHalfCellTrans = 0; + + halfCellTrans = calculateHalfCellTrans(gridLocalCellIndex, neighborGridCellIdx, faceId, isOnFault); + neighborHalfCellTrans = calculateHalfCellTrans(neighborGridCellIdx, gridLocalCellIndex, cvf::StructGridInterface::oppositeFace(faceId), isOnFault); + + return newtran(m_cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); } return HUGE_VAL; -} \ No newline at end of file +} diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h index 4b80ba6bbc..7576272976 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h @@ -49,6 +49,12 @@ class RigCombRiTransResultAccessor : public RigResultAccessor virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; private: + double getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; + double calculateHalfCellTrans( size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, bool isFaultFace) const; + + double getNtgValue( size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId ) const; + void calculateConnectionGeometry( size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* centerToFace, cvf::Vec3d* faceAreaVec) const; + cvf::ref m_xPermAccessor; cvf::ref m_yPermAccessor; diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp index fc75916c6a..5363af7c00 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp @@ -517,6 +517,60 @@ void GeometryTools::addMidEdgeNodes(std::list >* poly } } +//-------------------------------------------------------------------------------------------------- +/// Based on http://geomalgorithms.com/a01-_area.html +/// This method returns the polygon normal with length equal to the polygon area. +/// The components of the normal is thus the size of projected area into each of the main axis planes +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d GeometryTools::polygonAreaNormal3D(const std::vector& polygon) +{ + size_t pSize = polygon.size(); + switch (pSize) + { + case 0: + case 1: + case 2: + { + return cvf::Vec3d::ZERO; + } + break; + case 3: + { + return 0.5 * ((polygon[1]-polygon[0]) ^ (polygon[2] - polygon[0])); + } + break; + case 4: + { + // Cross product of diagonal = 2*A + return 0.5* ((polygon[2]-polygon[0]) ^ (polygon[3] - polygon[1])); + } + break; + default: + { + /// JJS: + // This is possibly not the fastest approach with large polygons, where a scaled projections approach would be better, + // but I suspect this (simpler) approach is faster for small polygons, as long as we do not have the polygon normal up front. + // + cvf::Vec3d areaNormal(cvf::Vec3d::ZERO); + size_t h = (pSize - 1)/2; + size_t k = (pSize % 2) ? 0 : pSize - 1; + + // First quads + for (size_t i = 1; i < h; ++i) + { + areaNormal += ( (polygon[2*i] - polygon[0]) ^ (polygon[2*i + 1] - polygon[2*i-1] ) ); + } + + // Last triangle or quad + areaNormal += ( (polygon[2*h] - polygon[0]) ^ (polygon[k] - polygon[2*h-1] ) ); + + areaNormal *= 0.5; + + return areaNormal; + } + } +} + diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h index 46e3725673..97d26c549b 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h @@ -27,6 +27,8 @@ class GeometryTools static double getAngle(const cvf::Vec3d& positiveNormalAxis, const cvf::Vec3d& v1, const cvf::Vec3d& v2); static double getAngle(const cvf::Vec3d& v1, const cvf::Vec3d& v2); + static cvf::Vec3d polygonAreaNormal3D(const std::vector& polygon); + enum IntersectionStatus { NO_INTERSECTION, From 83965a4f7bc132b3193b0fb2898f8f6c7d223504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 20 Aug 2014 09:51:55 +0200 Subject: [PATCH 270/346] riTRANXYZ: Started to add it to the rest of the system --- .../ProjectDataModel/RimDefines.cpp | 4 ++++ ApplicationCode/ProjectDataModel/RimDefines.h | 2 +- .../RigCaseCellResultsData.cpp | 20 +++++++++++-------- .../RigResultAccessorFactory.cpp | 16 +++++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index d0b426a023..f312b6aca6 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -64,6 +64,10 @@ bool RimDefines::isPerCellFaceResult(const QString& resultName) { return true; } + else if (resultName.compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } return false; } diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 69f3823818..68c16695ec 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -46,7 +46,7 @@ class RimDefines static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } static QString ternarySaturationResultName() { return "TERNARY"; } static QString combinedMultResultName() { return "MULTXYZ"; } - + static QString combinedRiTransResultName() { return "riTRANSXYZ"; } // Mock model text identifiers static QString mockModelBasic() { return "Result Mock Debug Model Simple"; } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index a726f5b0bb..c008039c77 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -228,6 +228,8 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty ResultInfo resInfo(type, needsToBeStored, false, resultName, scalarResultIndex); m_resultInfos.push_back(resInfo); + cvf::ref statisticsCalculator; + // Create statistics calculator and add cache object if (resultName == RimDefines::combinedTransmissibilityResultName()) { @@ -240,8 +242,7 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranY)); calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranZ)); - cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); - m_statisticsDataCache.push_back(dataCache.p()); + statisticsCalculator = calc; } else if (resultName == RimDefines::combinedMultResultName()) { @@ -272,16 +273,19 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); } - cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); - m_statisticsDataCache.push_back(dataCache.p()); + statisticsCalculator = calc; } - else + else if (resultName == RimDefines::combinedRiTransResultName()) { - cvf::ref calc = new RigNativeStatCalc(this, scalarResultIndex); - cvf::ref dataCache = new RigStatisticsDataCache(calc.p()); - m_statisticsDataCache.push_back(dataCache.p()); } + else + { + statisticsCalculator = new RigNativeStatCalc(this, scalarResultIndex); + } + + cvf::ref dataCache = new RigStatisticsDataCache(statisticsCalculator.p()); + m_statisticsDataCache.push_back(dataCache.p()); } return scalarResultIndex; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index a9d092b63d..895b3798d4 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -35,6 +35,7 @@ #include "cvfObject.h" #include +#include "RigCombRiTransResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// @@ -79,6 +80,21 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } + else if (uiResultName == RimDefines::combinedRiTransResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombRiTransResultAccessor(grid); + + cvf::ref permX = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMX"); + cvf::ref permY = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMY"); + cvf::ref permZ = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMZ"); + cvf::ref ntg = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "NTG"); + + cellFaceAccessObject->setPermResultAccessors(permX.p(), permY.p(), permZ.p()); + cellFaceAccessObject->setNTGResultAccessor(ntg.p()); + // todo : cellFaceAccessObject->setCDARCHY(); + + return cellFaceAccessObject; + } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From b7693f449bc154dc880fce8214b1895858818dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 20 Aug 2014 11:32:50 +0200 Subject: [PATCH 271/346] Fixed missing result names when auto SOIL is off --- .../ProjectDataModel/RimReservoirView.cpp | 17 ++++++++++++----- .../RigCaseCellResultsData.cpp | 2 +- .../ReservoirDataModel/RigCaseCellResultsData.h | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 77150dc4c6..9edd98f1a7 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -916,19 +916,26 @@ void RimReservoirView::loadDataAndUpdate() else { RiaApplication* app = RiaApplication::instance(); - if (app->preferences()->autocomputeSOIL) + { + RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::MATRIX_RESULTS); + if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + + if (app->preferences()->autocomputeSOIL) { - RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::MATRIX_RESULTS); results->loadOrComputeSOIL(); - if (results->cellResults()) results->cellResults()->createPerFaceCombinedResults(); } + } + { + RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::FRACTURE_RESULTS); + if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + + if (app->preferences()->autocomputeSOIL) { - RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::FRACTURE_RESULTS); results->loadOrComputeSOIL(); - if (results->cellResults()) results->cellResults()->createPerFaceCombinedResults(); } } + } } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index c008039c77..331aa53c55 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -510,7 +510,7 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigCaseCellResultsData::createPerFaceCombinedResults() +void RigCaseCellResultsData::createPlaceholderResultEntries() { { size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index b2116f1713..b236bc4b1b 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -70,7 +70,7 @@ class RigCaseCellResultsData : public cvf::Object size_t addEmptyScalarResult(RimDefines::ResultCatType type, const QString& resultName, bool needsToBeStored); QString makeResultNameUnique(const QString& resultNameProposal) const; - void createPerFaceCombinedResults(); + void createPlaceholderResultEntries(); void removeResult(const QString& resultName); void clearAllResults(); From 9e4c39627da8481585fb918950da2f07ff6c1b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 20 Aug 2014 11:33:03 +0200 Subject: [PATCH 272/346] Rename variable --- .../RimReservoirCellResultsStorage.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index e34bcba704..42be9598c7 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -302,16 +302,16 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result { if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; - size_t resultGridIndex = m_cellResults->findScalarResultIndex(type, resultName); - if (resultGridIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; + size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; // If we have any results on any timestep, assume we have loaded results already - for (size_t tsIdx = 0; tsIdx < m_cellResults->timeStepCount(resultGridIndex); ++tsIdx) + for (size_t tsIdx = 0; tsIdx < m_cellResults->timeStepCount(scalarResultIndex); ++tsIdx) { - if (m_cellResults->cellScalarResults(resultGridIndex, tsIdx).size()) + if (m_cellResults->cellScalarResults(scalarResultIndex, tsIdx).size()) { - return resultGridIndex; + return scalarResultIndex; } } @@ -323,18 +323,18 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result if (m_readerInterface.notNull()) { // Add one more result to result container - size_t timeStepCount = m_cellResults->infoForEachResultIndex()[resultGridIndex].m_timeStepDates.size(); + size_t timeStepCount = m_cellResults->infoForEachResultIndex()[scalarResultIndex].m_timeStepDates.size(); bool resultLoadingSucess = true; if (type == RimDefines::DYNAMIC_NATIVE && timeStepCount > 0) { - m_cellResults->cellScalarResults(resultGridIndex).resize(timeStepCount); + m_cellResults->cellScalarResults(scalarResultIndex).resize(timeStepCount); size_t i; for (i = 0; i < timeStepCount; i++) { - std::vector& values = m_cellResults->cellScalarResults(resultGridIndex)[i]; + std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[i]; if (!m_readerInterface->dynamicResult(resultName, RifReaderInterface::MATRIX_RESULTS, i, &values)) { resultLoadingSucess = false; @@ -343,9 +343,9 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result } else if (type == RimDefines::STATIC_NATIVE) { - m_cellResults->cellScalarResults(resultGridIndex).resize(1); + m_cellResults->cellScalarResults(scalarResultIndex).resize(1); - std::vector& values = m_cellResults->cellScalarResults(resultGridIndex)[0]; + std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[0]; if (!m_readerInterface->staticResult(resultName, RifReaderInterface::MATRIX_RESULTS, &values)) { resultLoadingSucess = false; @@ -355,11 +355,11 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result if (!resultLoadingSucess) { // Remove last scalar result because loading of result failed - m_cellResults->cellScalarResults(resultGridIndex).clear(); + m_cellResults->cellScalarResults(scalarResultIndex).clear(); } } - return resultGridIndex; + return scalarResultIndex; } @@ -422,20 +422,20 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex } } - size_t soilResultGridIndex = findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); - if (soilResultGridIndex == cvf::UNDEFINED_SIZE_T) + size_t soilResultScalarIndex = findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); + if (soilResultScalarIndex == cvf::UNDEFINED_SIZE_T) { - soilResultGridIndex = m_cellResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); - CVF_ASSERT(soilResultGridIndex != cvf::UNDEFINED_SIZE_T); + soilResultScalarIndex = m_cellResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); + CVF_ASSERT(soilResultScalarIndex != cvf::UNDEFINED_SIZE_T); // Set this result to be calculated - m_cellResults->setMustBeCalculated(soilResultGridIndex); + m_cellResults->setMustBeCalculated(soilResultScalarIndex); - m_cellResults->cellScalarResults(soilResultGridIndex).resize(soilTimeStepCount); + m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); for (size_t timeStepIdx = 0; timeStepIdx < soilTimeStepCount; timeStepIdx++) { - m_cellResults->cellScalarResults(soilResultGridIndex, timeStepIdx).resize(soilResultValueCount); + m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIdx).resize(soilResultValueCount); } } @@ -461,7 +461,7 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex } } - std::vector& soilForTimeStep = m_cellResults->cellScalarResults(soilResultGridIndex, timeStepIndex); + std::vector& soilForTimeStep = m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex); #pragma omp parallel for for (int idx = 0; idx < static_cast(soilResultValueCount); idx++) From f61f7f1fd19aa51be87a290fab3ad23d8f3e86d0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 20 Aug 2014 11:55:11 +0200 Subject: [PATCH 273/346] Result statistics: Fixed computation of scalar values close to zero --- ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp index f0dc353920..01534e3455 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp @@ -40,8 +40,8 @@ void RigStatisticsDataCache::clearAllStatistics() { m_minValue = HUGE_VAL; m_maxValue = -HUGE_VAL; - m_posClosestToZero = -HUGE_VAL; - m_negClosestToZero = HUGE_VAL; + m_posClosestToZero = HUGE_VAL; + m_negClosestToZero = -HUGE_VAL; m_p10 = HUGE_VAL; m_p90 = HUGE_VAL; m_meanValue = HUGE_VAL; From e4e3cca05fd703e86c9e97ad04bd09dfa9b7f744 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 21 Aug 2014 08:39:19 +0200 Subject: [PATCH 274/346] Moved creation of placeholder results to to RimCase --- ApplicationCode/ProjectDataModel/RimCase.cpp | 23 +++++ ApplicationCode/ProjectDataModel/RimCase.h | 3 +- .../RimReservoirCellResultsStorage.cpp | 99 +++++++++---------- .../RimReservoirCellResultsStorage.h | 3 +- .../ProjectDataModel/RimReservoirView.cpp | 26 +---- .../RigCaseCellResultsData.cpp | 14 +++ 6 files changed, 91 insertions(+), 77 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index f7561fb37d..aa0aeec7b8 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -539,3 +539,26 @@ QString RimCase::relocateFile(const QString& orgFileName, const QString& orgNew return fileName; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimCase::openReserviorCase() +{ + if (!openEclipseGridFile()) + { + return false; + } + + { + RimReservoirCellResultsStorage* results = this->results(RifReaderInterface::MATRIX_RESULTS); + if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + + } + { + RimReservoirCellResultsStorage* results = this->results(RifReaderInterface::FRACTURE_RESULTS); + if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + } + + return true; +} diff --git a/ApplicationCode/ProjectDataModel/RimCase.h b/ApplicationCode/ProjectDataModel/RimCase.h index efb5801ba5..3de3d04c49 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.h +++ b/ApplicationCode/ProjectDataModel/RimCase.h @@ -57,7 +57,8 @@ class RimCase : public caf::PdmObject caf::PdmField > filesContainingFaults; - virtual bool openEclipseGridFile() { return false;}; // Should be pure virtual but PDM does not allow that. + bool openReserviorCase(); + virtual bool openEclipseGridFile() { return false; }; // Should be pure virtual but PDM does not allow that. RigCaseData* reservoirData(); const RigCaseData* reservoirData() const; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 42be9598c7..c4f2e8a7a5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -226,24 +226,12 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefi if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") { size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); - - // If SOIL is not found, try to compute and return computed scalar index - // Will return cvf::UNDEFINED_SIZE_T if no SGAS/SWAT is found - if (soilScalarResultIndex == cvf::UNDEFINED_SIZE_T) + if (!isDataPresent(soilScalarResultIndex)) { computeSOILForTimeStep(timeStepIndex); - - soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); - return soilScalarResultIndex; } - // If we have found SOIL and SOIL must be calculated, calculate and return - if (soilScalarResultIndex != cvf::UNDEFINED_SIZE_T && m_cellResults->mustBeCalculated(soilScalarResultIndex)) - { - computeSOILForTimeStep(timeStepIndex); - - return soilScalarResultIndex; - } + return soilScalarResultIndex; } size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); @@ -305,14 +293,24 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; - // If we have any results on any timestep, assume we have loaded results already + // If we have any results on any time step, assume we have loaded results already + if (isDataPresent(scalarResultIndex)) + { + return scalarResultIndex; + } - for (size_t tsIdx = 0; tsIdx < m_cellResults->timeStepCount(scalarResultIndex); ++tsIdx) + if (resultName == "SOIL") { - if (m_cellResults->cellScalarResults(scalarResultIndex, tsIdx).size()) + // Trigger loading of SWAT, SGAS to establish time step count if no data has been loaded from file at this point + findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); + findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); + + for (size_t timeStepIdx = 0; timeStepIdx < m_cellResults->maxTimeStepCount(); timeStepIdx++) { - return scalarResultIndex; + computeSOILForTimeStep(timeStepIdx); } + + return scalarResultIndex; } if (type == RimDefines::GENERATED) @@ -362,25 +360,6 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result return scalarResultIndex; } - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimReservoirCellResultsStorage::loadOrComputeSOIL() -{ - size_t scalarIndexSOIL = findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); - if (scalarIndexSOIL != cvf::UNDEFINED_SIZE_T) - { - return; - } - - for (size_t timeStepIdx = 0; timeStepIdx < m_cellResults->maxTimeStepCount(); timeStepIdx++) - { - computeSOILForTimeStep(timeStepIdx); - } -} - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -422,21 +401,18 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex } } - size_t soilResultScalarIndex = findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL"); - if (soilResultScalarIndex == cvf::UNDEFINED_SIZE_T) + size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); + if (m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).size() == 0) { - soilResultScalarIndex = m_cellResults->addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); - CVF_ASSERT(soilResultScalarIndex != cvf::UNDEFINED_SIZE_T); - - // Set this result to be calculated - m_cellResults->setMustBeCalculated(soilResultScalarIndex); - - m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); +// // Set this result to be calculated +// m_cellResults->setMustBeCalculated(soilResultScalarIndex); +// +// m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); - for (size_t timeStepIdx = 0; timeStepIdx < soilTimeStepCount; timeStepIdx++) - { - m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIdx).resize(soilResultValueCount); - } +// for (size_t timeStepIdx = 0; timeStepIdx < soilTimeStepCount; timeStepIdx++) +// { + m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); +// } } @@ -720,6 +696,29 @@ size_t RimReservoirCellResultsStorage::storedResultsCount() return m_resultCacheMetaData.size(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimReservoirCellResultsStorage::isDataPresent(size_t scalarResultIndex) const +{ + if (scalarResultIndex >= m_cellResults->resultCount()) + { + return false; + } + + const std::vector< std::vector > data = m_cellResults->cellScalarResults(scalarResultIndex); + + for (size_t tsIdx = 0; tsIdx < data.size(); ++tsIdx) + { + if (data[tsIdx].size()) + { + return true; + } + } + + return false; +} + CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorageEntryInfo, "ResultStorageEntryInfo"); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index aa90e062e8..55713ce290 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -52,8 +52,8 @@ class RimReservoirCellResultsStorage : public caf::PdmObject void setReaderInterface(RifReaderInterface* readerInterface); RifReaderInterface* readerInterface(); - void loadOrComputeSOIL(); void computeDepthRelatedResults(); + bool isDataPresent(size_t scalarResultIndex) const; size_t findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex); size_t findOrLoadScalarResult(RimDefines::ResultCatType type, const QString& resultName); @@ -65,6 +65,7 @@ class RimReservoirCellResultsStorage : public caf::PdmObject private: void computeSOILForTimeStep(size_t timeStepIndex); + void computeSOILForAllTimeStep(); QString getValidCacheFileName(); QString getCacheDirectoryPath(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 9edd98f1a7..6f6b6bd678 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -905,7 +905,7 @@ void RimReservoirView::loadDataAndUpdate() if (m_reservoir) { - if (!m_reservoir->openEclipseGridFile()) + if (!m_reservoir->openReserviorCase()) { QMessageBox::warning(RiuMainWindow::instance(), "Error when opening project file", @@ -913,30 +913,6 @@ void RimReservoirView::loadDataAndUpdate() m_reservoir = NULL; return; } - else - { - RiaApplication* app = RiaApplication::instance(); - - { - RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::MATRIX_RESULTS); - if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); - - if (app->preferences()->autocomputeSOIL) - { - results->loadOrComputeSOIL(); - } - } - { - RimReservoirCellResultsStorage* results = m_reservoir->results(RifReaderInterface::FRACTURE_RESULTS); - if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); - - if (app->preferences()->autocomputeSOIL) - { - results->loadOrComputeSOIL(); - } - } - - } } CVF_ASSERT(this->cellResult() != NULL); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 331aa53c55..97f80208d9 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -512,6 +512,20 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::createPlaceholderResultEntries() { + { + size_t soilIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); + if (soilIndex == cvf::UNDEFINED_SIZE_T) + { + size_t swatIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SWAT"); + size_t sgasIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SGAS"); + + if (swatIndex != cvf::UNDEFINED_SIZE_T || sgasIndex != cvf::UNDEFINED_SIZE_T) + { + addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); + } + } + } + { size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); if (combinedTransmissibilityIndex == cvf::UNDEFINED_SIZE_T) From f29d3c2876261e693f5d3ddb0567026f4a4042df Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 21 Aug 2014 12:06:18 +0200 Subject: [PATCH 275/346] Result Info: Write out result values for fault in addition to grid --- .../ProjectDataModel/RimReservoirView.cpp | 204 ++++++++++-------- .../ProjectDataModel/RimReservoirView.h | 3 +- 2 files changed, 118 insertions(+), 89 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 6f6b6bd678..3b1c29816a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1089,95 +1089,23 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, RigCaseData* eclipseCase = m_reservoir->reservoirData(); RigGridBase* grid = eclipseCase->grid(gridIndex); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor; + appendTextFromResultSlot(eclipseCase, gridIndex, cellIndex, this->m_currentTimeStep, this->cellResult(), resultInfoText); - if (this->cellResult()->isTernarySaturationSelected()) + // Fault text data + if (grid->isMainGrid()) { - RimReservoirCellResultsStorage* gridCellResults = this->cellResult()->currentGridCellResults(); - if (gridCellResults) - { - 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"); - - cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, soilScalarSetIndex); - cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, swatScalarSetIndex); - - double scalarValue = 0.0; - - if (dataAccessObjectX.notNull()) scalarValue = dataAccessObjectX->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SOIL : %1\n").arg(scalarValue)); + RigMainGrid* mainGrid = grid->mainGrid(); - if (dataAccessObjectY.notNull()) scalarValue = dataAccessObjectY->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SGAS : %1\n").arg(scalarValue)); - - if (dataAccessObjectZ.notNull()) scalarValue = dataAccessObjectZ->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SWAT : %1\n").arg(scalarValue)); - } - } - else if (this->cellResult()->hasResult()) - { - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor; - - if (cellResult->hasStaticResult()) + const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(cellIndex, face); + if (fault) { - if (this->cellResult()->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedTransmissibilityResultName()); - { - double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("Tran Y : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("Tran Z : %1\n").arg(scalarValue)); - } - } - else if (this->cellResult()->resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref multResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedMultResultName()); - { - double scalarValue = 0.0; - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("MULTX : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_I); - resultInfoText->append(QString("MULTX- : %1\n").arg(scalarValue)); - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("MULTY : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_J); - resultInfoText->append(QString("MULTY- : %1\n").arg(scalarValue)); - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("MULTZ : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_K); - resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); - } - } - else + resultInfoText->append(QString("\nFault Name: %1\n").arg(fault->name())); + if (this->faultResultSettings()->customFaultResult()) { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, this->cellResult()->gridScalarIndex()); + resultInfoText->push_back("Fault result data:\n"); + appendTextFromResultSlot(eclipseCase, gridIndex, cellIndex, this->m_currentTimeStep, this->faultResultSettings()->customFaultResult(), resultInfoText); } } - else - { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, m_currentTimeStep, this->cellResult()->gridScalarIndex()); - } - - if (resultAccessor.notNull()) - { - double scalarValue = resultAccessor->cellScalar(cellIndex); - resultInfoText->append(QString("Cell result : %1\n").arg(scalarValue)); - } } if (this->cellEdgeResult()->hasResult()) @@ -1187,13 +1115,14 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, this->cellEdgeResult()->gridScalarIndices(resultIndices); this->cellEdgeResult()->gridScalarResultNames(&resultNames); + resultInfoText->push_back("\nCell edge result data:\n"); for (int idx = 0; idx < 6; idx++) { if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; // Cell edge results are static, results are loaded for first time step only RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultIndices[idx]); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultIndices[idx]); if (resultAccessor.notNull()) { double scalarValue = resultAccessor->cellScalar(cellIndex); @@ -1219,8 +1148,6 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, resultInfoText->append(QString("Well-cell connection info: Well Name: %1 Branch Id: %2 Segment Id: %3\n").arg(singleWellResultData->m_wellName).arg(wellResultCell->m_ertBranchId).arg(wellResultCell->m_ertSegmentId)); } } - - appendFaultName(grid, cellIndex, face, resultInfoText); } } @@ -1914,7 +1841,7 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) QString gridName = QString::fromStdString(hostGrid->gridName()); resultInfo->append(QString("NNC 1 : cell [%1, %2, %3] face %4 (%5)\n").arg(i).arg(j).arg(k).arg(face.text()).arg(gridName)); - appendFaultName(hostGrid, conn.m_c1GlobIdx, conn.m_c1Face, &faultName); + appendTextFromFault(hostGrid, conn.m_c1GlobIdx, conn.m_c1Face, &faultName); } } @@ -1941,7 +1868,7 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) if (faultName.isEmpty()) { - appendFaultName(hostGrid, conn.m_c2GlobIdx, cvf::StructGridInterface::oppositeFace(conn.m_c1Face), &faultName); + appendTextFromFault(hostGrid, conn.m_c2GlobIdx, cvf::StructGridInterface::oppositeFace(conn.m_c1Face), &faultName); } } } @@ -2081,7 +2008,7 @@ void RimReservoirView::updateFaultColors() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString) +void RimReservoirView::appendTextFromFault(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString) { if (grid->isMainGrid()) { @@ -2118,3 +2045,104 @@ bool RimReservoirView::isTimeStepDependentDataVisible() const return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText) +{ + if (!resultSlot) + { + return; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); + if (resultSlot->isTernarySaturationSelected()) + { + RimReservoirCellResultsStorage* gridCellResults = resultSlot->currentGridCellResults(); + if (gridCellResults) + { + 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"); + + cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, swatScalarSetIndex); + + double scalarValue = 0.0; + + if (dataAccessObjectX.notNull()) scalarValue = dataAccessObjectX->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SOIL : %1\n").arg(scalarValue)); + + if (dataAccessObjectY.notNull()) scalarValue = dataAccessObjectY->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SGAS : %1\n").arg(scalarValue)); + + if (dataAccessObjectZ.notNull()) scalarValue = dataAccessObjectZ->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SWAT : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->hasResult()) + { + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); + cvf::ref resultAccessor; + + if (resultSlot->hasStaticResult()) + { + if (resultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedTransmissibilityResultName()); + { + double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("Tran Y : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("Tran Z : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref multResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedMultResultName()); + { + double scalarValue = 0.0; + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("MULTX : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_I); + resultInfoText->append(QString("MULTX- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("MULTY : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_J); + resultInfoText->append(QString("MULTY- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("MULTZ : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_K); + resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); + } + } + else + { + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->gridScalarIndex()); + } + } + else + { + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultSlot->gridScalarIndex()); + } + + if (resultAccessor.notNull()) + { + double scalarValue = resultAccessor->cellScalar(cellIndex); + resultInfoText->append(resultSlot->resultVariable()); + resultInfoText->append(QString(" : %1\n").arg(scalarValue)); + } + } +} + diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 36568bc8f0..261df2cbad 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -162,6 +162,7 @@ class RimReservoirView : public caf::PdmObject bool pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString* pickInfoText) const; void appendCellResultInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) ; void appendNNCResultInfo(size_t nncIndex, QString* resultInfo); + static void appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText); // Does this belong here, really ? void calculateVisibleWellCellsIncFence(cvf::UByteArray* visibleCells, RigGridBase * grid); @@ -184,7 +185,7 @@ class RimReservoirView : public caf::PdmObject // Display model generation private: - void appendFaultName(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString); + void appendTextFromFault(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString); void createDisplayModel(); void updateDisplayModelVisibility(); From f3c7c3017cbaebe3b979564848728aad8a492bff Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 21 Aug 2014 12:16:18 +0200 Subject: [PATCH 276/346] Info window in 3D: Added fault property name --- ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 3bc4c76a18..33a7f6a880 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -186,6 +186,11 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("Fault results: %1
").arg(faultMapping); } + + if (m_reservoirView->faultResultSettings()->customFaultResult()) + { + infoText += QString("Fault Property: %1
").arg(m_reservoirView->faultResultSettings()->customFaultResult()->resultVariable()); + } } else { From ecfea98e20d9143c1728e39769d8bf51b9c2e3b7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 21 Aug 2014 13:16:08 +0200 Subject: [PATCH 277/346] Fault results: Show fault color if color mode is selected --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 3b1c29816a..8cdfe90c12 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1994,7 +1994,11 @@ void RimReservoirView::updateFaultColors() for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - if (this->animationMode() && this->cellEdgeResult()->hasResult()) + if (this->faultResultSettings()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) + { + m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot); + } + else if (this->animationMode() && this->cellEdgeResult()->hasResult()) { m_reservoirGridPartManager->updateFaultCellEdgeResultColor(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot, this->cellEdgeResult()); } From b9a5d5b74331c6bce0ae884811d507b2c820efe6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 21 Aug 2014 14:41:03 +0200 Subject: [PATCH 278/346] Bugfix: Apply face culling mode when creating effects --- .../RivCellEdgeEffectGenerator.cpp | 25 ++++++++++++++----- .../RivCellEdgeEffectGenerator.h | 4 +-- .../ModelVisualization/RivFaultPartMgr.cpp | 12 ++++----- .../ModelVisualization/RivGridPartMgr.cpp | 6 ++--- .../RivScalarMapperUtils.cpp | 19 ++++++++------ .../ModelVisualization/RivScalarMapperUtils.h | 13 ++++++---- 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index ac493658cd..0110826514 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -44,7 +44,7 @@ CellEdgeEffectGenerator::CellEdgeEffectGenerator(const cvf::ScalarMapper* edgeSc m_edgeScalarMapper = edgeScalarMapper; - m_cullBackfaces = false; + m_cullBackfaces = caf::FC_NONE; m_opacityLevel = 1.0f; m_defaultCellColor = cvf::Color3f(cvf::Color3::WHITE); } @@ -116,7 +116,7 @@ caf::EffectGenerator* CellEdgeEffectGenerator::copy() const newEffect->m_cellTextureImage = m_cellTextureImage; newEffect->setOpacityLevel(m_opacityLevel); - newEffect->setCullBackfaces(m_cullBackfaces); + newEffect->setFaceCulling(m_cullBackfaces); newEffect->setUndefinedColor(m_undefinedColor); newEffect->setDefaultCellColor(m_defaultCellColor); @@ -237,15 +237,28 @@ void CellEdgeEffectGenerator::updateForShaderBasedRendering(cvf::Effect* effect) eff->setRenderState(blender.p()); } - // Backface culling - - if (m_cullBackfaces) + // Face culling + if (m_cullBackfaces != caf::FC_NONE) { cvf::ref faceCulling = new cvf::RenderStateCullFace; - eff->setRenderState(faceCulling.p()); + if (m_cullBackfaces == caf::FC_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::BACK); + } + else if (m_cullBackfaces == caf::FC_FRONT) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT); + } + else if (m_cullBackfaces == caf::FC_FRONT_AND_BACK) + { + faceCulling->setMode(cvf::RenderStateCullFace::FRONT_AND_BACK); + } + + effect->setRenderState(faceCulling.p()); } } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 118adce686..8167250dcc 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -106,7 +106,7 @@ class CellEdgeEffectGenerator : public caf::EffectGenerator void setOpacityLevel(float opacity) { m_opacityLevel = cvf::Math::clamp(opacity, 0.0f , 1.0f ); } void setUndefinedColor(cvf::Color3f color) { m_undefinedColor = color; } - void setCullBackfaces(bool cullBackFaces) { m_cullBackfaces = cullBackFaces; } + void setFaceCulling(caf::FaceCulling faceCulling) { m_cullBackfaces = faceCulling; } void setDefaultCellColor(cvf::Color3f color) { m_defaultCellColor = color; } protected: @@ -125,7 +125,7 @@ class CellEdgeEffectGenerator : public caf::EffectGenerator cvf::cref m_ternaryCellScalarMapper; float m_opacityLevel; - bool m_cullBackfaces; + caf::FaceCulling m_cullBackfaces; cvf::Color3f m_undefinedColor; cvf::Color3f m_defaultCellColor; }; diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 6963f62674..51385f94b8 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -122,7 +122,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode()); } else { @@ -139,7 +139,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_nativeFaultFacesTextureCoords.p()); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTextureResultsToPart(m_nativeFaultFaces.p(), m_nativeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode()); } } @@ -155,7 +155,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode()); } else { @@ -172,7 +172,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_oppositeFaultFacesTextureCoords.p()); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTextureResultsToPart(m_oppositeFaultFaces.p(), m_oppositeFaultFacesTextureCoords.p(), mapper, m_opacityLevel, this->faceCullingMode()); } } } @@ -189,7 +189,7 @@ void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultS { cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_nativeFaultGenerator->quadToCellFaceMapper(), m_grid->gridIndex(), - timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor, this->faceCullingMode()); m_nativeFaultFaces->setEffect(eff.p()); } @@ -201,7 +201,7 @@ void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultS if (dg) { cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_oppositeFaultGenerator->quadToCellFaceMapper(), m_grid->gridIndex(), - timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor, this->faceCullingMode()); m_oppositeFaultFaces->setEffect(eff.p()); } diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index d92e033a3d..5d85e3c457 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -241,7 +241,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); const RivTernaryScalarMapper* mapper = cellResultSlot->ternaryLegendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTernaryTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel, caf::FC_NONE); } else { @@ -257,7 +257,7 @@ void RivGridPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* texturer.createTextureCoords(m_surfaceFacesTextureCoords.p()); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - RivScalarMapperUtils::applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel); + RivScalarMapperUtils::applyTextureResultsToPart(m_surfaceFaces.p(), m_surfaceFacesTextureCoords.p(), mapper, m_opacityLevel, caf::FC_NONE); } } } @@ -273,7 +273,7 @@ void RivGridPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSl if (dg) { cvf::ref eff = RivScalarMapperUtils::createCellEdgeEffect(dg, m_surfaceGenerator.quadToCellFaceMapper(), m_grid->gridIndex(), - timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor); + timeStepIndex, cellResultSlot, cellEdgeResultSlot, m_opacityLevel, m_defaultColor, caf::FC_NONE); m_surfaceFaces->setEffect(eff.p()); } diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index ea1e1b9707..5a1622a90f 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -38,28 +38,28 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivScalarMapperUtils::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel) +void RivScalarMapperUtils::applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling) { CVF_ASSERT(part && textureCoords && mapper); cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); if (dg) dg->setTextureCoordArray(textureCoords); - cvf::ref scalarEffect = RivScalarMapperUtils::createScalarMapperEffect(mapper, opacityLevel); + cvf::ref scalarEffect = RivScalarMapperUtils::createScalarMapperEffect(mapper, opacityLevel, faceCulling); part->setEffect(scalarEffect.p()); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel) +void RivScalarMapperUtils::applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling) { CVF_ASSERT(part && textureCoords && mapper); cvf::DrawableGeo* dg = dynamic_cast(part->drawable()); if (dg) dg->setTextureCoordArray(textureCoords); - cvf::ref scalarEffect = RivScalarMapperUtils::createTernaryScalarMapperEffect(mapper, opacityLevel); + cvf::ref scalarEffect = RivScalarMapperUtils::createTernaryScalarMapperEffect(mapper, opacityLevel, faceCulling); part->setEffect(scalarEffect.p()); } @@ -73,7 +73,8 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, float opacityLevel, - cvf::Color3f defaultColor) + cvf::Color3f defaultColor, + caf::FaceCulling faceCulling) { CellEdgeEffectGenerator cellFaceEffectGen(cellEdgeResultSlot->legendConfig()->scalarMapper()); @@ -99,6 +100,7 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe cellFaceEffectGen.setOpacityLevel(opacityLevel); cellFaceEffectGen.setDefaultCellColor(defaultColor); + cellFaceEffectGen.setFaceCulling(faceCulling); cvf::ref eff = cellFaceEffectGen.generateEffect(); return eff; @@ -107,13 +109,15 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RivScalarMapperUtils::createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel) +cvf::ref RivScalarMapperUtils::createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling) { CVF_ASSERT(mapper); caf::PolygonOffset polygonOffset = caf::PO_1; caf::ScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); scalarEffgen.setOpacityLevel(opacityLevel); + scalarEffgen.setFaceCulling(faceCulling); + cvf::ref scalarEffect = scalarEffgen.generateEffect(); return scalarEffect; @@ -122,13 +126,14 @@ cvf::ref RivScalarMapperUtils::createScalarMapperEffect(const cvf:: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel) +cvf::ref RivScalarMapperUtils::createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling) { CVF_ASSERT(mapper); caf::PolygonOffset polygonOffset = caf::PO_1; RivTernaryScalarMapperEffectGenerator scalarEffgen(mapper, polygonOffset); scalarEffgen.setOpacityLevel(opacityLevel); + scalarEffgen.setFaceCulling(faceCulling); cvf::ref scalarEffect = scalarEffgen.generateEffect(); return scalarEffect; diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index 8e08965fde..09d84e663b 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -18,6 +18,8 @@ #pragma once +#include "cafEffectGenerator.h" + #include "cvfBase.h" #include "cvfArray.h" @@ -40,8 +42,8 @@ class RimCellEdgeResultSlot; class RivScalarMapperUtils { public: - static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel); - static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel); + static void applyTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling); + static void applyTernaryTextureResultsToPart(cvf::Part* part, cvf::Vec2fArray* textureCoords, const RivTernaryScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling); static cvf::ref createCellEdgeEffect(cvf::DrawableGeo* dg, const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper, @@ -50,10 +52,11 @@ class RivScalarMapperUtils RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot, float opacityLevel, - cvf::Color3f defaultColor); + cvf::Color3f defaultColor, + caf::FaceCulling faceCulling); private: - static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel); - static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel); + static cvf::ref createScalarMapperEffect(const cvf::ScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling); + static cvf::ref createTernaryScalarMapperEffect(const RivTernaryScalarMapper* mapper, float opacityLevel, caf::FaceCulling faceCulling); }; From 314d07e7334b161d0ebde3c7e426502ec3ca45a4 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 22 Aug 2014 07:45:16 +0200 Subject: [PATCH 279/346] SOIL is loaded/computed on demand, removed autocompute from prefs --- ApplicationCode/Application/RiaPreferences.cpp | 5 ----- ApplicationCode/Application/RiaPreferences.h | 1 - 2 files changed, 6 deletions(-) diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index 2e36180a84..f26603352f 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -62,12 +62,10 @@ RiaPreferences::RiaPreferences(void) CAF_PDM_InitFieldNoDefault(&lastUsedProjectFileName,"lastUsedProjectFileName", "Last Used Project File", "", "", ""); lastUsedProjectFileName.setUiHidden(true); - CAF_PDM_InitField(&autocomputeSOIL, "autocomputeSOIL", true, "SOIL", "", "SOIL = 1.0 - SGAS - SWAT", ""); CAF_PDM_InitField(&autocomputeDepthRelatedProperties, "autocomputeDepth", true, "DEPTH related properties", "", "DEPTH, DX, DY, DZ, TOP, BOTTOM", ""); CAF_PDM_InitField(&autocomputeGridFaults, "autocomputeGridFaults", true, "Grid faults", "", "Detect all fault faces geometrically", ""); autocomputeDepthRelatedProperties.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); - autocomputeSOIL.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); autocomputeGridFaults.setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN); readerSettings = new RifReaderSettings; @@ -99,7 +97,6 @@ void RiaPreferences::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt } } else if (field == &octaveShowHeaderInfoWhenExecutingScripts || - field == &autocomputeSOIL || field == &autocomputeDepthRelatedProperties || field == &autocomputeGridFaults) { @@ -135,7 +132,6 @@ void RiaPreferences::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& defaultSettingsGroup->add(&defaultWellLabelColor); caf::PdmUiGroup* autoComputeGroup = uiOrdering.addNewGroup("Compute when loading new case"); - autoComputeGroup->add(&autocomputeSOIL); autoComputeGroup->add(&autocomputeDepthRelatedProperties); autoComputeGroup->add(&autocomputeGridFaults); @@ -158,7 +154,6 @@ void RiaPreferences::configureForRegressionTests() useShaders = true; showHud = false; - autocomputeSOIL = true; autocomputeDepthRelatedProperties = true; CVF_ASSERT(readerSettings); diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 78fd48e44e..4f3eed0b87 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -62,7 +62,6 @@ class RiaPreferences : public caf::PdmObject caf::PdmField lastUsedProjectFileName; - caf::PdmField autocomputeSOIL; caf::PdmField autocomputeDepthRelatedProperties; caf::PdmField autocomputeGridFaults; From 03df28282c0f83f89a4c0ae77903719cd6075c03 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 22 Aug 2014 09:28:25 +0200 Subject: [PATCH 280/346] Show NNCs with no common area in folder below Faults --- .../ProjectDataModel/CMakeLists_files.cmake | 4 ++ .../ProjectDataModel/RimFaultCollection.cpp | 42 +++++++++++++++++- .../ProjectDataModel/RimFaultCollection.h | 5 +++ .../ProjectDataModel/RimNoCommonAreaNNC.cpp | 41 +++++++++++++++++ .../ProjectDataModel/RimNoCommonAreaNNC.h | 40 +++++++++++++++++ .../RimNoCommonAreaNncCollection.cpp | 40 +++++++++++++++++ .../RimNoCommonAreaNncCollection.h | 39 ++++++++++++++++ .../ReservoirDataModel/RigNNCData.h | 6 ++- .../RigReservoirBuilderMock.cpp | 44 ++++++++++++++++++- .../RigReservoirBuilderMock.h | 2 + 10 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h create mode 100644 ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index c9cb08a878..acfb39020e 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -49,6 +49,8 @@ ${CEE_CURRENT_LIST_DIR}RimFaultCollection.h ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.h ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.h ${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.h +${CEE_CURRENT_LIST_DIR}RimNoCommonAreaNNC.h +${CEE_CURRENT_LIST_DIR}RimNoCommonAreaNncCollection.h ) set (SOURCE_GROUP_SOURCE_FILES @@ -96,6 +98,8 @@ ${CEE_CURRENT_LIST_DIR}RimFaultCollection.cpp ${CEE_CURRENT_LIST_DIR}RimMockModelSettings.cpp ${CEE_CURRENT_LIST_DIR}RimTernaryLegendConfig.cpp ${CEE_CURRENT_LIST_DIR}RimFaultResultSlot.cpp +${CEE_CURRENT_LIST_DIR}RimNoCommonAreaNNC.cpp +${CEE_CURRENT_LIST_DIR}RimNoCommonAreaNncCollection.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index dbdda464e4..996a8c2038 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -22,6 +22,8 @@ #include "RiaPreferences.h" #include "RigCaseData.h" #include "RimCase.h" +#include "RimNoCommonAreaNNC.h" +#include "RimNoCommonAreaNncCollection.h" #include "RimReservoirView.h" #include "RiuMainWindow.h" #include "RivColorTableArray.h" @@ -67,7 +69,10 @@ RimFaultCollection::RimFaultCollection() cvf::Color3f defWellLabelColor = RiaApplication::instance()->preferences()->defaultWellLabelColor(); CAF_PDM_InitField(&faultLabelColor, "FaultLabelColor", defWellLabelColor, "Label color", "", "", ""); - CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", ""); + CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&noCommonAreaNnncCollection, "NoCommonAreaNnncCollection", "NNCs With No Common Area", "", "", ""); + noCommonAreaNnncCollection = new RimNoCommonAreaNncCollection; m_reservoirView = NULL; } @@ -78,6 +83,8 @@ RimFaultCollection::RimFaultCollection() RimFaultCollection::~RimFaultCollection() { faults.deleteAllChildObjects(); + + delete noCommonAreaNnncCollection(); } @@ -226,6 +233,30 @@ void RimFaultCollection::syncronizeFaults() QString toolTip = QString("Fault count (%1)").arg(newFaults.size()); setUiToolTip(toolTip); + + // NNCs + this->noCommonAreaNnncCollection()->noCommonAreaNncs().deleteAllChildObjects(); + + RigMainGrid* mainGrid = m_reservoirView->eclipseCase()->reservoirData()->mainGrid(); + std::vector& nncConnections = mainGrid->nncData()->connections(); + for (size_t i = 0; i < nncConnections.size(); i++) + { + if (!nncConnections[i].hasCommonArea()) + { + RimNoCommonAreaNNC* noCommonAreaNnc = new RimNoCommonAreaNNC(); + + size_t i1, j1, k1; + mainGrid->ijkFromCellIndex(nncConnections[i].m_c1GlobIdx, &i1, &j1, &k1); + + size_t i2, j2, k2; + mainGrid->ijkFromCellIndex(nncConnections[i].m_c2GlobIdx, &i2, &j2, &k2); + + QString txt = QString("[%1 %2 %3] - [%4 %5 %6]").arg(i1).arg(j1).arg(k1).arg(i2).arg(j2).arg(k2); + + noCommonAreaNnc->name = txt; + this->noCommonAreaNnncCollection()->noCommonAreaNncs().push_back(noCommonAreaNnc); + } + } } //-------------------------------------------------------------------------------------------------- @@ -280,3 +311,12 @@ void RimFaultCollection::setShowFaultsOutsideFilters(bool enableState) m_showFaultsOutsideFilters = enableState; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultCollection::addMockData() +{ + if (!(m_reservoirView && m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData() && m_reservoirView->eclipseCase()->reservoirData()->mainGrid())) return; + +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index f940209d77..bef8d05656 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -33,6 +33,7 @@ class RimFault; class RimReservoirView; +class RimNoCommonAreaNncCollection; //================================================================================================== /// @@ -56,6 +57,8 @@ class RimFaultCollection : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); void syncronizeFaults(); + void addMockData(); + bool isGridVisualizationMode() const; bool showFaultsOutsideFilters() const; @@ -75,6 +78,8 @@ class RimFaultCollection : public caf::PdmObject caf::PdmPointersField faults; RimFault* findFaultByName(QString name); + caf::PdmField noCommonAreaNnncCollection; + virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); virtual caf::PdmFieldHandle* objectToggleField(); diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp new file mode 100644 index 0000000000..7a20063789 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimNoCommonAreaNNC.h" + +CAF_PDM_SOURCE_INIT(RimNoCommonAreaNNC, "NoCommonAreaNNC"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimNoCommonAreaNNC::RimNoCommonAreaNNC() +{ + CAF_PDM_InitObject("RimNoCommonAreaNNC", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&name, "Name", "Name", "", "", ""); + name.setUiReadOnly(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimNoCommonAreaNNC::userDescriptionField() +{ + return &name; +} + diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h new file mode 100644 index 0000000000..100789c2a2 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" + + +//================================================================================================== +/// +/// +//================================================================================================== +class RimNoCommonAreaNNC : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + RimNoCommonAreaNNC(); + + caf::PdmField name; + + caf::PdmFieldHandle* userDescriptionField(); + +}; diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp new file mode 100644 index 0000000000..70799990f6 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimNoCommonAreaNncCollection.h" + +CAF_PDM_SOURCE_INIT(RimNoCommonAreaNncCollection, "RimNoCommonAreaNncCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimNoCommonAreaNncCollection::RimNoCommonAreaNncCollection() +{ + CAF_PDM_InitObject("RimNoCommonAreaNncCollection", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&noCommonAreaNncs, "NoCommonAreaNncs", "NoCommonAreaNncs", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimNoCommonAreaNncCollection::~RimNoCommonAreaNncCollection() +{ + noCommonAreaNncs.deleteAllChildObjects(); +} + diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h new file mode 100644 index 0000000000..f7bcd24737 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmPointer.h" + +class RimNoCommonAreaNNC; + +//================================================================================================== +/// Placeholder class used to create a folder in the tree view. +/// TODO: Remove this class when new tree view is integrated +//================================================================================================== +class RimNoCommonAreaNncCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; +public: + RimNoCommonAreaNncCollection(); + virtual ~RimNoCommonAreaNncCollection(); + + caf::PdmPointersField noCommonAreaNncs; +}; diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index bbad5e3fe7..f574106d34 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -40,6 +40,11 @@ class RigConnection m_transmissibility(0.0) {} + bool hasCommonArea() const + { + return m_polygon.size() > 0; + } + size_t m_c1GlobIdx; cvf::StructGridInterface::FaceType m_c1Face; size_t m_c2GlobIdx; @@ -47,7 +52,6 @@ class RigConnection double m_transmissibility; std::vector m_polygon; - }; diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index bca46da76c..3aaf9469f7 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -499,7 +499,7 @@ void RigReservoirBuilderMock::addFaults(RigCaseData* eclipseCase) if (cellDimension().x() > 5) { min.x() = cellDimension().x() / 2; - max.x() = min.x() + 1; + max.x() = min.x() + 2; } if (cellDimension().y() > 5) @@ -515,6 +515,32 @@ void RigReservoirBuilderMock::addFaults(RigCaseData* eclipseCase) } grid->setFaults(faults); + + // NNCs + std::vector& nncConnections = grid->nncData()->connections(); + { + size_t i1 = 2; + size_t j1 = 2; + size_t k1 = 3; + + size_t i2 = 2; + size_t j2 = 3; + size_t k2 = 4; + + addNnc(grid, i1, j1, k1, i2, j2, k2, nncConnections); + } + + { + size_t i1 = 2; + size_t j1 = 2; + size_t k1 = 3; + + size_t i2 = 2; + size_t j2 = 5; + size_t k2 = 4; + + addNnc(grid, i1, j1, k1, i2, j2, k2, nncConnections); + } } //-------------------------------------------------------------------------------------------------- @@ -525,3 +551,19 @@ void RigReservoirBuilderMock::enableWellData(bool enableWellData) m_enableWellData = false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigReservoirBuilderMock::addNnc(RigMainGrid* grid, size_t i1, size_t j1, size_t k1, size_t i2, size_t j2, size_t k2, std::vector &nncConnections) +{ + size_t c1GlobalIndex = grid->cellIndexFromIJK(i1, j1, k1); + size_t c2GlobalIndex = grid->cellIndexFromIJK(i2, j2, k2); + + RigConnection conn; + conn.m_c1GlobIdx = c1GlobalIndex; + conn.m_c2GlobIdx = c2GlobalIndex; + conn.m_transmissibility = 0.2; + + nncConnections.push_back(conn); +} + diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h index 7076027264..9200788ed5 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h @@ -64,6 +64,8 @@ class RigReservoirBuilderMock private: void addFaults(RigCaseData* eclipseCase); + + static void addNnc(RigMainGrid* grid, size_t i1, size_t j1, size_t k1, size_t i2, size_t j2, size_t k2, std::vector &nncConnections); void addWellData(RigCaseData* eclipseCase, RigGridBase* grid); static void appendCells(size_t nodeStartIndex, size_t cellCount, RigGridBase* hostGrid, std::vector& cells); From 9e22c90a4a643d964d9831c4036aeaff828f60d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 22 Aug 2014 08:01:31 +0200 Subject: [PATCH 281/346] Renamed cellindex to gridLocalCellIndex --- ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp | 2 +- .../ModelVisualization/RivNNCGeometryGenerator.cpp | 4 ++-- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 4 ++-- ApplicationCode/ReservoirDataModel/RigCell.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigCell.h | 6 +++--- ApplicationCode/ReservoirDataModel/RigMainGrid.cpp | 2 +- ApplicationCode/ReservoirDataModel/RigNNCData.cpp | 4 ++-- .../ReservoirDataModel/RigReservoirBuilderMock.cpp | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 48b56da2ae..a004f1aedb 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -116,7 +116,7 @@ bool transferGridCellData(RigMainGrid* mainGrid, RigActiveCellInfo* activeCellIn { RigCell& cell = mainGrid->cells()[cellStartIndex + gridLocalCellIndex]; - cell.setCellIndex(gridLocalCellIndex); + cell.setGridLocalCellIndex(gridLocalCellIndex); // Active cell index diff --git a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp index f146190167..2e70f368d2 100644 --- a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp @@ -98,13 +98,13 @@ void RivNNCGeometryGenerator::computeArrays() if ((*allCells)[conn.m_c1GlobIdx].hostGrid() == m_grid.p()) { - size_t cell1GridLocalIdx = (*allCells)[conn.m_c1GlobIdx].cellIndex(); + size_t cell1GridLocalIdx = (*allCells)[conn.m_c1GlobIdx].gridLocalCellIndex(); cell1Visible = (*m_cellVisibility)[cell1GridLocalIdx]; } if ((*allCells)[conn.m_c2GlobIdx].hostGrid() == m_grid.p()) { - size_t cell2GridLocalIdx = (*allCells)[conn.m_c2GlobIdx].cellIndex(); + size_t cell2GridLocalIdx = (*allCells)[conn.m_c2GlobIdx].gridLocalCellIndex(); cell2Visible = (*m_cellVisibility)[cell2GridLocalIdx]; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 8cdfe90c12..ca375bfcbd 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1828,7 +1828,7 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t gridLocalCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); size_t i, j, k; if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) @@ -1850,7 +1850,7 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigCell& cell = grid->cells()[conn.m_c2GlobIdx]; RigGridBase* hostGrid = cell.hostGrid(); - size_t gridLocalCellIndex = cell.cellIndex(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); size_t i, j, k; if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) diff --git a/ApplicationCode/ReservoirDataModel/RigCell.cpp b/ApplicationCode/ReservoirDataModel/RigCell.cpp index e2b6f49427..730328b7db 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCell.cpp @@ -41,7 +41,7 @@ RigCell::RigCell() : m_subGrid(NULL), m_hostGrid(NULL), m_isInvalid(false), - m_cellIndex(cvf::UNDEFINED_SIZE_T), + m_gridLocalCellIndex(cvf::UNDEFINED_SIZE_T), m_coarseningBoxIndex(cvf::UNDEFINED_SIZE_T) { memcpy(m_cornerIndices.data(), undefinedCornersArray, 8*sizeof(size_t)); diff --git a/ApplicationCode/ReservoirDataModel/RigCell.h b/ApplicationCode/ReservoirDataModel/RigCell.h index 1a7475594d..7108a12452 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.h +++ b/ApplicationCode/ReservoirDataModel/RigCell.h @@ -41,8 +41,8 @@ class RigCell bool isInvalid() const { return m_isInvalid; } void setInvalid( bool val ) { m_isInvalid = val; } - size_t cellIndex() const { return m_cellIndex; } - void setCellIndex(size_t val) { m_cellIndex = val; } + size_t gridLocalCellIndex() const { return m_gridLocalCellIndex; } + void setGridLocalCellIndex(size_t val) { m_gridLocalCellIndex = val; } RigLocalGrid* subGrid() const { return m_subGrid; } void setSubGrid(RigLocalGrid* subGrid) { m_subGrid = subGrid; } @@ -70,7 +70,7 @@ class RigCell private: caf::SizeTArray8 m_cornerIndices; - size_t m_cellIndex; ///< This cells index in the grid it belongs to. + size_t m_gridLocalCellIndex; ///< This cells index in the grid it belongs to. RigGridBase* m_hostGrid; RigLocalGrid* m_subGrid; diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index b5e79a750d..0c1916477b 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -251,7 +251,7 @@ void RigMainGrid::calculateFaults() if (firstNO_FAULTFaceForCell) // To avoid doing this for every face, and only when detecting a NO_FAULT { hostGrid = m_cells[gcIdx].hostGrid(); - hostGrid->ijkFromCellIndex(m_cells[gcIdx].cellIndex(), &i,&j, &k); + hostGrid->ijkFromCellIndex(m_cells[gcIdx].gridLocalCellIndex(), &i,&j, &k); firstNO_FAULTFaceForCell = false; } diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index 128c4f66b9..b45f81b289 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -50,9 +50,9 @@ void RigNNCData::processConnections(const RigMainGrid& mainGrid) if (c1.hostGrid() == c2.hostGrid()) { size_t i1, j1, k1; - c1.hostGrid()->ijkFromCellIndex(c1.cellIndex(), &i1, &j1, &k1); + c1.hostGrid()->ijkFromCellIndex(c1.gridLocalCellIndex(), &i1, &j1, &k1); size_t i2, j2, k2; - c2.hostGrid()->ijkFromCellIndex(c2.cellIndex(), &i2, &j2, &k2); + c2.hostGrid()->ijkFromCellIndex(c2.gridLocalCellIndex(), &i2, &j2, &k2); isPossibleNeighborInDirection[cvf::StructGridInterface::POS_I] = ((i1 + 1) == i2); diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index 3aaf9469f7..05b3f5c651 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -146,7 +146,7 @@ void RigReservoirBuilderMock::appendCells(size_t nodeStartIndex, size_t cellCoun RigCell& riCell = cells[cellIndexStart + i]; riCell.setHostGrid(hostGrid); - riCell.setCellIndex(i); + riCell.setGridLocalCellIndex(i); riCell.cornerIndices()[0] = nodeStartIndex + i * 8 + 0; riCell.cornerIndices()[1] = nodeStartIndex + i * 8 + 1; From 57a049d39f92f23a4cee6bdd2180fa912f130633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 22 Aug 2014 08:07:00 +0200 Subject: [PATCH 282/346] riTRANSXYZ: Moving the calculation to ReservoirCellResultsStorage Create stored native riTRANX,Y,Z results instead of doing everyting in one go. This makes the statistics calculation work automatically instead of beeing custoized and require a compplete calculation of its own. --- .../RimReservoirCellResultsStorage.cpp | 241 ++++++++++++++++++ .../RimReservoirCellResultsStorage.h | 2 +- .../RigCaseCellResultsData.h | 5 + .../ReservoirDataModel/RigCaseData.cpp | 5 + .../RigCombRiTransResultAccessor.cpp | 27 +- .../RigCombRiTransResultAccessor.h | 4 +- 6 files changed, 269 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index c4f2e8a7a5..5baa428661 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -19,7 +19,9 @@ #include "RimReservoirCellResultsStorage.h" #include "RigCaseCellResultsData.h" +#include "RigActiveCellInfo.h" #include "RigMainGrid.h" +#include "RigCell.h" #include "RimTools.h" #include "cafProgressInfo.h" @@ -29,6 +31,7 @@ #include #include #include +#include "cvfGeometryTools.h" CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorage, "ReservoirCellResultStorage"); @@ -564,6 +567,242 @@ void RimReservoirCellResultsStorage::computeDepthRelatedResults() } } +#if 1 + +void calculateConnectionGeometry(const RigCell& c1, const RigCell& c2 , const std::vector& nodes, + cvf::StructGridInterface::FaceType faceId, + cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) +{ + CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); + + *faceCenter = cvf::Vec3d::ZERO; + *faceAreaVec = cvf::Vec3d::ZERO; + + std::vector polygon; + std::vector intersections; + caf::SizeTArray4 face1; + caf::SizeTArray4 face2; + c1.faceIndices(faceId, &face1); + c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); + + bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( + &polygon, + &intersections, + (cvf::EdgeIntersectStorage*)NULL, + cvf::wrapArrayConst(&nodes), + face1.data(), + face2.data(), + 1e-6); + + + if (foundOverlap) + { + std::vector realPolygon; + + for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) + { + if (polygon[pIdx] < nodes.size()) + realPolygon.push_back(nodes[polygon[pIdx]]); + else + realPolygon.push_back(intersections[polygon[pIdx] - nodes.size()]); + } + + // Polygon center + for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) + { + *faceCenter += realPolygon[pIdx]; + } + + *faceCenter *= 1.0 / realPolygon.size(); + + // Polygon area vector + + *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); + + } + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) +{ + return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) +{ + return cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +typedef size_t (*ResultIndexFunction)(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +size_t directReservoirCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) +{ + return reservoirCellIndex; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- + +size_t reservoirActiveCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) +{ + return activeCellinfo->cellResultIndex(reservoirCellIndex); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeRiTransX() +{ + if (!m_cellResults) return; + + cvf::StructGridInterface::FaceType faceId = cvf::StructGridInterface::POS_I; + QString riTRANName = "riTRANX"; + QString permName = "PERMX"; + + double cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) + + // Get the needed result indices we depend on + + size_t permResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMX"); + size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); + + + // Get the result count, to handle that one of them might be globally defined + + size_t permxResultValueCount = m_cellResults->cellScalarResults(permResultIdx)[0].size(); + size_t ntgResultValueCount = m_cellResults->cellScalarResults(ntgResultIdx)[0].size(); + + size_t resultValueCount = CVF_MIN(permxResultValueCount, ntgResultValueCount); + + // Check if we need to create a placeholder result, or if it exists already + + size_t riTransResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, riTRANName); + + if (riTransResultIdx == cvf::UNDEFINED_SIZE_T) + { + riTransResultIdx = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, riTRANName, false, resultValueCount); + } + + // Prepare how to index the result values: + + bool isPermUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permResultIdx); + bool isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); + bool isTransUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(riTransResultIdx); + + // Set up result index function pointers + + ResultIndexFunction riTranIdxFunc = isTransUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction permIdxFunc = isPermUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + + // Get all the actual result values + + std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; + std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; + std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; + + const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); + const std::vector& nodes = m_ownerMainGrid->nodes(); + + for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->cells().size(); nativeResvCellIndex++) + { + // Do nothing if we are only dealing with active cells, and this cell is not active: + if ((*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex) == cvf::UNDEFINED_SIZE_T) continue; + + const RigCell& nativeCell = m_ownerMainGrid->cells()[nativeResvCellIndex]; + RigGridBase* grid = nativeCell.hostGrid(); + + size_t gridLocalNativeCellIndex = nativeCell.gridLocalCellIndex(); + + size_t i, j, k, gridLocalNeighborCellIdx; + + grid->ijkFromCellIndex(gridLocalNativeCellIndex, &i, &j, &k); + + if (grid->cellIJKNeighbor(i, j, k, faceId, &gridLocalNeighborCellIdx)) + { + size_t neighborResvCellIdx = grid->reservoirCellIndex(gridLocalNeighborCellIdx); + const RigCell& neighborCell = m_ownerMainGrid->cells()[neighborResvCellIdx]; + + // Connection geometry + + const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); + bool isOnFault = fault; + + + cvf::Vec3d faceAreaVec; + cvf::Vec3d faceCenter; + + if (isOnFault) + { + calculateConnectionGeometry( nativeCell, neighborCell, nodes,faceId, + &faceCenter, &faceAreaVec); + } + else + { + faceCenter = nativeCell.faceCenter(faceId); + faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); + } + + double halfCellTrans = 0; + double neighborHalfCellTrans = 0; + + // Native cell half cell transm + { + cvf::Vec3d centerToFace = faceCenter - nativeCell.center(); + + size_t permResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); + double perm = permResults[permResIdx]; + + double ntg = 1.0; + if (faceId != cvf::StructGridInterface::POS_K) + { + size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, nativeResvCellIndex); + ntg = ntgResults[ntgResIdx]; + } + + halfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); + } + + // Neighbor cell half cell transm + { + cvf::Vec3d centerToFace = faceCenter - neighborCell.center(); + + size_t permResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); + double perm = permResults[permResIdx]; + + double ntg = 1.0; + if (faceId != cvf::StructGridInterface::POS_K) + { + size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, neighborResvCellIdx); + ntg = ntgResults[ntgResIdx]; + } + + neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); + } + + size_t tranResIdx = (*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex); + riTransResults[tranResIdx] = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans);; + } + + } + +} + +#endif //-------------------------------------------------------------------------------------------------- /// @@ -594,6 +833,8 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(const QString& res return scalarResultIndex; } + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 55713ce290..78631bfe41 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -69,7 +69,7 @@ class RimReservoirCellResultsStorage : public caf::PdmObject QString getValidCacheFileName(); QString getCacheDirectoryPath(); - + void computeRiTransX(); // Fields caf::PdmField m_resultCacheFileName; caf::PdmPointersField diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index b236bc4b1b..30cf5c3ac6 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -30,6 +30,7 @@ class RifReaderInterface; class RigMainGrid; class RigStatisticsDataCache; +class RigActiveCellInfo; //================================================================================================== /// Class containing the results for the complete number of active cells. Both main grid and LGR's @@ -40,6 +41,9 @@ class RigCaseCellResultsData : public cvf::Object RigCaseCellResultsData(RigMainGrid* ownerGrid); void setMainGrid(RigMainGrid* ownerGrid); + void setActiveCellInfo(RigActiveCellInfo* activeCellInfo) { m_activeCellInfo = activeCellInfo;} + RigActiveCellInfo* activeCellInfo() { return m_activeCellInfo;} + const RigActiveCellInfo* activeCellInfo() const { return m_activeCellInfo;} // Max and min values of the results void recalculateStatistics(size_t scalarResultIndex); @@ -123,5 +127,6 @@ class RigCaseCellResultsData : public cvf::Object std::vector m_resultInfos; RigMainGrid* m_ownerMainGrid; + RigActiveCellInfo* m_activeCellInfo; }; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 2d7b204c48..3dd84a69b8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -33,6 +33,9 @@ RigCaseData::RigCaseData() m_activeCellInfo = new RigActiveCellInfo; m_fractureActiveCellInfo = new RigActiveCellInfo; + + m_matrixModelResults->setActiveCellInfo(m_activeCellInfo.p()); + m_fractureModelResults->setActiveCellInfo(m_fractureActiveCellInfo.p()); } //-------------------------------------------------------------------------------------------------- @@ -397,10 +400,12 @@ void RigCaseData::setActiveCellInfo(RifReaderInterface::PorosityModelResultType if (porosityModel == RifReaderInterface::MATRIX_RESULTS) { m_activeCellInfo = activeCellInfo; + m_matrixModelResults->setActiveCellInfo(m_activeCellInfo.p()); } else { m_fractureActiveCellInfo = activeCellInfo; + m_fractureModelResults->setActiveCellInfo(m_fractureActiveCellInfo.p()); } } diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp index 78b72b8d34..5f95b1eb1f 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp @@ -112,7 +112,7 @@ double RigCombRiTransResultAccessor::getNtgValue(size_t gridLocalCellIndex, cvf: //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double halfCellTransmissibility( double perm , double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) +double RigCombRiTransResultAccessor::halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) { return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); } @@ -120,11 +120,12 @@ double halfCellTransmissibility( double perm , double ntg, const cvf::Vec3d& cen //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) +double RigCombRiTransResultAccessor::newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) { return cdarchy * mult / ( ( 1 / halfCellTrans) + (1 / neighborHalfCellTrans) ); } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -139,7 +140,7 @@ double RigCombRiTransResultAccessor::calculateHalfCellTrans(size_t gridLocalCell if (isFaultFace) { - calculateConnectionGeometry( gridLocalCellIndex, neighborGridCellIdx, faceId, &faceCenter, &faceAreaVec); + calculateConnectionGeometry( m_grid, gridLocalCellIndex, neighborGridCellIdx, faceId, &faceCenter, &faceAreaVec); } else { @@ -157,18 +158,18 @@ double RigCombRiTransResultAccessor::calculateHalfCellTrans(size_t gridLocalCell return halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); } -void RigCombRiTransResultAccessor::calculateConnectionGeometry( size_t gridLocalCellIndex, size_t neighborGridCellIdx, +void RigCombRiTransResultAccessor::calculateConnectionGeometry( const RigGridBase* grid, size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, - cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) const + cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) { CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); *faceCenter = cvf::Vec3d::ZERO; *faceAreaVec = cvf::Vec3d::ZERO; - const RigMainGrid* mainGrid = m_grid->mainGrid(); + const RigMainGrid* mainGrid = grid->mainGrid(); - const RigCell& c1 = m_grid->cell(gridLocalCellIndex); - const RigCell& c2 = m_grid->cell(neighborGridCellIdx); + const RigCell& c1 = grid->cell(gridLocalCellIndex); + const RigCell& c2 = grid->cell(neighborGridCellIdx); std::vector polygon; std::vector intersections; @@ -193,10 +194,10 @@ void RigCombRiTransResultAccessor::calculateConnectionGeometry( size_t gridLocal for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) { - if (polygon[pIdx] < m_grid->mainGrid()->nodes().size()) - realPolygon.push_back(m_grid->mainGrid()->nodes()[polygon[pIdx]]); + if (polygon[pIdx] < grid->mainGrid()->nodes().size()) + realPolygon.push_back(grid->mainGrid()->nodes()[polygon[pIdx]]); else - realPolygon.push_back(intersections[polygon[pIdx] - m_grid->mainGrid()->nodes().size()]); + realPolygon.push_back(intersections[polygon[pIdx] - grid->mainGrid()->nodes().size()]); } // Polygon center @@ -216,8 +217,8 @@ void RigCombRiTransResultAccessor::calculateConnectionGeometry( size_t gridLocal } //-------------------------------------------------------------------------------------------------- /// -/// Neighbour cell transmisibilities only is calculated here -/// Not NNC transmisibilities. Thart has to be done separatly elsewhere +/// Neighbor cell transmisibilities only is calculated here +/// Not NNC transmisibilities. That has to be done separately elsewhere /// /// Todo: What about Grid to Grid connections ? /// Todo: needs optimization. Things are done several times. Caching of the results should be considered. etc. diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h index 7576272976..9ffe227112 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h @@ -53,8 +53,10 @@ class RigCombRiTransResultAccessor : public RigResultAccessor double calculateHalfCellTrans( size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, bool isFaultFace) const; double getNtgValue( size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId ) const; - void calculateConnectionGeometry( size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* centerToFace, cvf::Vec3d* faceAreaVec) const; + static void calculateConnectionGeometry( const RigGridBase* grid, size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* centerToFace, cvf::Vec3d* faceAreaVec); + static double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec); + static double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans); cvf::ref m_xPermAccessor; cvf::ref m_yPermAccessor; From 11c01af61ab220d410fc34c117d7d2d8c227b311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Fri, 22 Aug 2014 13:38:03 +0200 Subject: [PATCH 283/346] riTRANSXYZ: First version working Not yet extensively tested, but seems ok for complete match faces --- ApplicationCode/ProjectDataModel/RimDefines.h | 4 + .../RimReservoirCellResultsStorage.cpp | 94 +++++++--- .../RimReservoirCellResultsStorage.h | 4 +- .../ProjectDataModel/RimReservoirView.cpp | 14 ++ .../RigCaseCellResultsData.cpp | 161 +++++++++--------- .../ReservoirDataModel/RigMainGrid.cpp | 2 +- .../RigResultAccessorFactory.cpp | 11 ++ .../RigStatisticsCalculator.cpp | 11 ++ .../RigStatisticsCalculator.h | 1 + 9 files changed, 192 insertions(+), 110 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 68c16695ec..5d97f36820 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -47,6 +47,10 @@ class RimDefines static QString ternarySaturationResultName() { return "TERNARY"; } static QString combinedMultResultName() { return "MULTXYZ"; } static QString combinedRiTransResultName() { return "riTRANSXYZ"; } + static QString riTransXResultName() { return "riTRANSX"; } + static QString riTransYResultName() { return "riTRANSY"; } + static QString riTransZResultName() { return "riTRANSZ"; } + // Mock model text identifiers static QString mockModelBasic() { return "Result Mock Debug Model Simple"; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 5baa428661..62e8a444ed 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -219,7 +219,8 @@ RifReaderInterface* RimReservoirCellResultsStorage::readerInterface() } //-------------------------------------------------------------------------------------------------- -/// +/// This method is intended to be used for multicase cross statistical calculations, when +/// we need process one timestep at a time, freeing memory as we go. //-------------------------------------------------------------------------------------------------- size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex) { @@ -296,7 +297,7 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; - // If we have any results on any time step, assume we have loaded results already + if (isDataPresent(scalarResultIndex)) { return scalarResultIndex; @@ -316,6 +317,20 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result return scalarResultIndex; } + if (resultName == RimDefines::combinedRiTransResultName()) + { + computeRiTransComponent(RimDefines::riTransXResultName()); + computeRiTransComponent(RimDefines::riTransYResultName()); + computeRiTransComponent(RimDefines::riTransZResultName()); + } + + if ( resultName == RimDefines::riTransXResultName() + || resultName == RimDefines::riTransYResultName() + || resultName == RimDefines::riTransZResultName()) + { + computeRiTransComponent(resultName); + } + if (type == RimDefines::GENERATED) { return cvf::UNDEFINED_SIZE_T; @@ -665,21 +680,47 @@ size_t reservoirActiveCellIndex(const RigActiveCellInfo* activeCellinfo, size_t //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimReservoirCellResultsStorage::computeRiTransX() +void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTransComponentResultName) { if (!m_cellResults) return; - - cvf::StructGridInterface::FaceType faceId = cvf::StructGridInterface::POS_I; - QString riTRANName = "riTRANX"; - QString permName = "PERMX"; + // Set up which component to compute + + cvf::StructGridInterface::FaceType faceId; + QString permCompName; + + if (riTransComponentResultName == RimDefines::riTransXResultName()) + { + permCompName = "PERMX"; + faceId = cvf::StructGridInterface::POS_I; + } + else if (riTransComponentResultName == RimDefines::riTransYResultName()) + { + permCompName = "PERMY"; + faceId = cvf::StructGridInterface::POS_J; + } + else if (riTransComponentResultName == RimDefines::riTransZResultName()) + { + permCompName = "PERMZ"; + faceId = cvf::StructGridInterface::POS_K; + } + else + { + CVF_ASSERT(false); + } + + // Todo: Get the correct one from Unit set read by ERT double cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) // Get the needed result indices we depend on - size_t permResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMX"); - size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); + size_t permResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, permCompName); + size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); + + // Get the result index of the output + size_t riTransResultIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riTransComponentResultName); + CVF_ASSERT(riTransResultIdx != cvf::UNDEFINED_SIZE_T); // Get the result count, to handle that one of them might be globally defined @@ -688,14 +729,15 @@ void RimReservoirCellResultsStorage::computeRiTransX() size_t resultValueCount = CVF_MIN(permxResultValueCount, ntgResultValueCount); - // Check if we need to create a placeholder result, or if it exists already + // Get all the actual result values + + std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; + std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; + std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; - size_t riTransResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, riTRANName); + // Set up output container to correct number of results - if (riTransResultIdx == cvf::UNDEFINED_SIZE_T) - { - riTransResultIdx = m_cellResults->addStaticScalarResult(RimDefines::STATIC_NATIVE, riTRANName, false, resultValueCount); - } + riTransResults.resize(resultValueCount); // Prepare how to index the result values: @@ -709,19 +751,17 @@ void RimReservoirCellResultsStorage::computeRiTransX() ResultIndexFunction permIdxFunc = isPermUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; ResultIndexFunction ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; - // Get all the actual result values - - std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; - std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; - std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); + bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->cells().size(); nativeResvCellIndex++) { // Do nothing if we are only dealing with active cells, and this cell is not active: - if ((*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex) == cvf::UNDEFINED_SIZE_T) continue; + size_t tranResIdx = (*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex); + + if (tranResIdx == cvf::UNDEFINED_SIZE_T) continue; const RigCell& nativeCell = m_ownerMainGrid->cells()[nativeResvCellIndex]; RigGridBase* grid = nativeCell.hostGrid(); @@ -737,6 +777,10 @@ void RimReservoirCellResultsStorage::computeRiTransX() size_t neighborResvCellIdx = grid->reservoirCellIndex(gridLocalNeighborCellIdx); const RigCell& neighborCell = m_ownerMainGrid->cells()[neighborResvCellIdx]; + // Do nothing if neighbor cell has no results + size_t neighborCellPermResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); + if (neighborCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; + // Connection geometry const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); @@ -757,6 +801,8 @@ void RimReservoirCellResultsStorage::computeRiTransX() faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); } + if (!isFaceNormalsOutwards) faceAreaVec = -faceAreaVec; + double halfCellTrans = 0; double neighborHalfCellTrans = 0; @@ -781,8 +827,7 @@ void RimReservoirCellResultsStorage::computeRiTransX() { cvf::Vec3d centerToFace = faceCenter - neighborCell.center(); - size_t permResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); - double perm = permResults[permResIdx]; + double perm = permResults[neighborCellPermResIdx]; double ntg = 1.0; if (faceId != cvf::StructGridInterface::POS_K) @@ -794,7 +839,6 @@ void RimReservoirCellResultsStorage::computeRiTransX() neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); } - size_t tranResIdx = (*riTranIdxFunc)(activeCellInfo, nativeResvCellIndex); riTransResults[tranResIdx] = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans);; } @@ -938,7 +982,7 @@ size_t RimReservoirCellResultsStorage::storedResultsCount() } //-------------------------------------------------------------------------------------------------- -/// +/// If we have any results on any time step, assume we have loaded results //-------------------------------------------------------------------------------------------------- bool RimReservoirCellResultsStorage::isDataPresent(size_t scalarResultIndex) const { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 78631bfe41..56136624c8 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -65,11 +65,11 @@ class RimReservoirCellResultsStorage : public caf::PdmObject private: void computeSOILForTimeStep(size_t timeStepIndex); - void computeSOILForAllTimeStep(); + void computeRiTransComponent(const QString& riTransComponentResultName); QString getValidCacheFileName(); QString getCacheDirectoryPath(); - void computeRiTransX(); + // Fields caf::PdmField m_resultCacheFileName; caf::PdmPointersField diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ca375bfcbd..ad6dcd7d65 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -2131,6 +2131,20 @@ void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); } } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiTransResultName()); + { + double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riTran X : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riTran Y : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riTran Z : %1\n").arg(scalarValue)); + } + } else { resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->gridScalarIndex()); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 97f80208d9..a7df18f536 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -214,79 +214,70 @@ size_t RigCaseCellResultsData::findScalarResultIndex(const QString& resultName) //-------------------------------------------------------------------------------------------------- /// Adds an empty scalar set, and returns the scalarResultIndex to it. -/// if resultName already exists, it returns the scalarResultIndex to the existing result. +/// if resultName already exists, it just returns the scalarResultIndex to the existing result. //-------------------------------------------------------------------------------------------------- size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType type, const QString& resultName, bool needsToBeStored) { - size_t scalarResultIndex = cvf::UNDEFINED_SIZE_T; + size_t scalarResultIndex = this->findScalarResultIndex(type, resultName); - scalarResultIndex = this->findScalarResultIndex(type, resultName); - if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) + // If the result exists, do nothing + + if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) { - scalarResultIndex = this->resultCount(); - m_cellScalarResults.push_back(std::vector >()); - ResultInfo resInfo(type, needsToBeStored, false, resultName, scalarResultIndex); - m_resultInfos.push_back(resInfo); + return scalarResultIndex; + } - cvf::ref statisticsCalculator; + // Create the new empty result with metadata - // Create statistics calculator and add cache object - if (resultName == RimDefines::combinedTransmissibilityResultName()) - { - size_t tranX = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANX"); - size_t tranY = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANY"); - size_t tranZ = findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANZ"); + scalarResultIndex = this->resultCount(); + m_cellScalarResults.push_back(std::vector >()); + ResultInfo resInfo(type, needsToBeStored, false, resultName, scalarResultIndex); + m_resultInfos.push_back(resInfo); - cvf::ref calc = new RigMultipleDatasetStatCalc(); - calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranX)); - calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranY)); - calc->addStatisticsCalculator(new RigNativeStatCalc(this, tranZ)); + // Create statistics calculator and add statistics cache object + // Todo: Move to a "factory" method - statisticsCalculator = calc; - } - else if (resultName == RimDefines::combinedMultResultName()) - { - cvf::ref calc = new RigMultipleDatasetStatCalc(); - - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX-"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY-"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - { - size_t scalarIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ-"); - if (scalarIdx != cvf::UNDEFINED_SIZE_T) calc->addStatisticsCalculator(new RigNativeStatCalc(this, scalarIdx)); - } - - statisticsCalculator = calc; - } - else if (resultName == RimDefines::combinedRiTransResultName()) - { + cvf::ref statisticsCalculator; - } - else - { - statisticsCalculator = new RigNativeStatCalc(this, scalarResultIndex); - } + if (resultName == RimDefines::combinedTransmissibilityResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANX")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANY")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANZ")); - cvf::ref dataCache = new RigStatisticsDataCache(statisticsCalculator.p()); - m_statisticsDataCache.push_back(dataCache.p()); + statisticsCalculator = calc; } + else if (resultName == RimDefines::combinedMultResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTX-")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTY-")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ")); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, "MULTZ-")); + + statisticsCalculator = calc; + } + else if (resultName == RimDefines::combinedRiTransResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName())); + statisticsCalculator = calc; + } + else + { + statisticsCalculator = new RigNativeStatCalc(this, scalarResultIndex); + } + + cvf::ref dataCache = new RigStatisticsDataCache(statisticsCalculator.p()); + m_statisticsDataCache.push_back(dataCache.p()); + return scalarResultIndex; } @@ -453,13 +444,14 @@ void RigCaseCellResultsData::freeAllocatedResultsData() } //-------------------------------------------------------------------------------------------------- -/// Add a result with given type and name, and allocate one result vector for the static result values +/// Make sure we have a result with given type and name, and make sure one "timestep" result vector +// for the static result values are allocated //-------------------------------------------------------------------------------------------------- size_t RigCaseCellResultsData::addStaticScalarResult(RimDefines::ResultCatType type, const QString& resultName, bool needsToBeStored, size_t resultValueCount) { size_t resultIdx = addEmptyScalarResult(type, resultName, needsToBeStored); - m_cellScalarResults[resultIdx].push_back(std::vector()); + m_cellScalarResults[resultIdx].resize(1, std::vector()); m_cellScalarResults[resultIdx][0].resize(resultValueCount, HUGE_VAL); return resultIdx; @@ -512,37 +504,42 @@ void RigCaseCellResultsData::setMustBeCalculated(size_t scalarResultIndex) //-------------------------------------------------------------------------------------------------- void RigCaseCellResultsData::createPlaceholderResultEntries() { + // SOIL { - size_t soilIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); - if (soilIndex == cvf::UNDEFINED_SIZE_T) - { - size_t swatIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SWAT"); - size_t sgasIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SGAS"); + size_t swatIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SWAT"); + size_t sgasIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SGAS"); - if (swatIndex != cvf::UNDEFINED_SIZE_T || sgasIndex != cvf::UNDEFINED_SIZE_T) - { - addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); - } + if (swatIndex != cvf::UNDEFINED_SIZE_T || sgasIndex != cvf::UNDEFINED_SIZE_T) + { + addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); } } + // TRANSXYZ { - size_t combinedTransmissibilityIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); - if (combinedTransmissibilityIndex == cvf::UNDEFINED_SIZE_T) + size_t tranX, tranY, tranZ; + if (findTransmissibilityResults(tranX, tranY, tranZ)) { - size_t tranX, tranY, tranZ; - if (findTransmissibilityResults(tranX, tranY, tranZ)) - { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); - } + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName(), false, 0); } } + // MULTXYZ + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedMultResultName(), false, 0); + } + // riTRANSXYZ and X,Y,Z { - size_t combinedMultIndex = findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedMultResultName()); - if (combinedMultIndex == cvf::UNDEFINED_SIZE_T) + size_t ntgResIdx = findScalarResultIndex(RimDefines::STATIC_NATIVE, "NTG"); + if ( findScalarResultIndex(RimDefines::STATIC_NATIVE, "NTG") != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, "PERMX") != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, "PERMY") != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, "PERMZ") != cvf::UNDEFINED_SIZE_T) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedMultResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName(), false, 0); } } } diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 0c1916477b..118f22fb3b 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -361,7 +361,7 @@ void RigMainGrid::calculateFaults() //-------------------------------------------------------------------------------------------------- /// The cell is normally inverted due to Depth becoming -Z at import, -/// but if (only) one of the flipX/Y is done, the cell is back to nomal +/// but if (only) one of the flipX/Y is done, the cell is back to normal //-------------------------------------------------------------------------------------------------- bool RigMainGrid::faceNormalsIsOutwards() const { diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 895b3798d4..15c6665f8b 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -82,6 +82,16 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa } else if (uiResultName == RimDefines::combinedRiTransResultName()) { + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); + + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransXResultName()); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransYResultName()); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransZResultName()); + + cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); + + return cellFaceAccessObject; +#if 0 cvf::ref cellFaceAccessObject = new RigCombRiTransResultAccessor(grid); cvf::ref permX = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMX"); @@ -94,6 +104,7 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa // todo : cellFaceAccessObject->setCDARCHY(); return cellFaceAccessObject; +#endif } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp index 48d98e035c..a35bac926e 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp @@ -238,3 +238,14 @@ size_t RigMultipleDatasetStatCalc::timeStepCount() return 0; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigMultipleDatasetStatCalc::addNativeStatisticsCalculator(RigCaseCellResultsData* cellResultsData, size_t scalarResultIndex) +{ + if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) + { + this->addStatisticsCalculator(new RigNativeStatCalc(cellResultsData, scalarResultIndex)); + } +} + diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h index fbd4a43270..5edeb22196 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h @@ -73,6 +73,7 @@ class RigMultipleDatasetStatCalc : public RigStatisticsCalculator public: RigMultipleDatasetStatCalc(); void addStatisticsCalculator(RigStatisticsCalculator* statisticsCalculator); + void addNativeStatisticsCalculator(RigCaseCellResultsData* cellResultsData, size_t scalarResultIndices); virtual void minMaxCellScalarValues(size_t timeStepIndex, double& min, double& max); virtual void posNegClosestToZero(size_t timeStepIndex, double& pos, double& neg); From 1b2b0d85606736b9a0ad58e66a2cf2c372591b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Mon, 25 Aug 2014 08:04:31 +0200 Subject: [PATCH 284/346] Fixed compile error introduced by rename The dependency was not detected by CMAKE/msvbuild. ... Strange Needed a complete make clean to find it. --- ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index 793cebdc1c..5d25d52fb9 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -196,7 +196,7 @@ class RiaGetActiveCellInfo: public RiaSocketCommand { RigGridBase* grid = reservoirCells[cIdx].hostGrid(); CVF_ASSERT(grid != NULL); - size_t cellIndex = reservoirCells[cIdx].cellIndex(); + size_t cellIndex = reservoirCells[cIdx].gridLocalCellIndex(); size_t i, j, k; grid->ijkFromCellIndex(cellIndex, &i, &j, &k); From 4d1d2215c29c257708a9f4d65f5f924e380121d6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 25 Aug 2014 10:31:36 +0200 Subject: [PATCH 285/346] Fixed memory allocation issues when computing SOIL --- .../RimReservoirCellResultsStorage.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 62e8a444ed..3f22bee88d 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -419,19 +419,12 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex } } - size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); - if (m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).size() == 0) - { -// // Set this result to be calculated -// m_cellResults->setMustBeCalculated(soilResultScalarIndex); -// -// m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); -// for (size_t timeStepIdx = 0; timeStepIdx < soilTimeStepCount; timeStepIdx++) -// { - m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); -// } - } + // Make sure memory is allocated for the new SOIL results + + size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); + m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); + m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); std::vector* swatForTimeStep = NULL; From 8dc2eed3c030df7992bece1e4de9f456e21ce742 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 25 Aug 2014 13:20:58 +0200 Subject: [PATCH 286/346] Moved loading of dependent datasets --- .../RimReservoirCellResultsStorage.cpp | 31 +++++++++++++++++-- .../ProjectDataModel/RimResultDefinition.cpp | 27 +--------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 3f22bee88d..27454e2b69 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -230,7 +230,6 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefi if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") { size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); - if (!isDataPresent(soilScalarResultIndex)) { computeSOILForTimeStep(timeStepIndex); } @@ -297,7 +296,28 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; - + // Load dependency data sets + + if (type == RimDefines::STATIC_NATIVE) + { + if (resultName == RimDefines::combinedTransmissibilityResultName()) + { + this->findOrLoadScalarResult(type, "TRANX"); + this->findOrLoadScalarResult(type, "TRANY"); + this->findOrLoadScalarResult(type, "TRANZ"); + } + else if (resultName == RimDefines::combinedMultResultName()) + { + this->findOrLoadScalarResult(type, "MULTX"); + this->findOrLoadScalarResult(type, "MULTX-"); + this->findOrLoadScalarResult(type, "MULTY"); + this->findOrLoadScalarResult(type, "MULTY-"); + this->findOrLoadScalarResult(type, "MULTZ"); + this->findOrLoadScalarResult(type, "MULTZ-"); + } + } + + if (isDataPresent(scalarResultIndex)) { return scalarResultIndex; @@ -424,6 +444,13 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); m_cellResults->cellScalarResults(soilResultScalarIndex).resize(soilTimeStepCount); + + if (m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).size() > 0) + { + // Data is computed and allocated, nothing more to do + return; + } + m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index fa4fbd1d3c..5c8507d041 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -196,32 +196,7 @@ void RimResultDefinition::loadResult() RimReservoirCellResultsStorage* gridCellResults = this->currentGridCellResults(); if (gridCellResults) { - if (m_resultType() == RimDefines::STATIC_NATIVE) - { - if (m_resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANX"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANY"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "TRANZ"); - } - else if (m_resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) - { - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTX"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTX-"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTY"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTY-"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTZ"); - gridCellResults->findOrLoadScalarResult(m_resultType(), "MULTZ-"); - } - else - { - gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); - } - } - else - { - gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); - } + gridCellResults->findOrLoadScalarResult(m_resultType(), m_resultVariable); } updateFieldVisibility(); From b3fd96d72e8295136d4b16924eb66b6f3d3a8118 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 10:13:35 +0200 Subject: [PATCH 287/346] Cell edge: Update texture also if none is cell result --- .../ModelVisualization/RivScalarMapperUtils.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index 5a1622a90f..d525d34491 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -88,14 +88,11 @@ cvf::ref RivScalarMapperUtils::createCellEdgeEffect(cvf::DrawableGe } else { - if (cellResultSlot->hasResult()) - { - RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, - quadToCellFaceMapper, dg, gridIndex, opacityLevel); - - cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); - cellFaceEffectGen.setScalarMapper(cellScalarMapper); - } + RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo(timeStepIndex, cellResultSlot, cellEdgeResultSlot, + quadToCellFaceMapper, dg, gridIndex, opacityLevel); + + cvf::ScalarMapper* cellScalarMapper = cellResultSlot->legendConfig()->scalarMapper(); + cellFaceEffectGen.setScalarMapper(cellScalarMapper); } cellFaceEffectGen.setOpacityLevel(opacityLevel); From f69413087a82115eaefec89e46d302dd97d2b63d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 11:47:14 +0200 Subject: [PATCH 288/346] Custom fault result: Reorganized custom fault result selection Removed combo box used to specify fault color or custom result color. Fault colors is used if None is selected in result dialog. --- .../RivReservoirFaultsPartMgr.cpp | 12 ++--- .../Rim3dOverlayInfoConfig.cpp | 5 +- .../ProjectDataModel/RimFaultResultSlot.cpp | 50 +++++++------------ .../ProjectDataModel/RimFaultResultSlot.h | 12 ++--- .../ProjectDataModel/RimReservoirView.cpp | 20 +++----- 5 files changed, 34 insertions(+), 65 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 7a418eb3ba..7ea48d38fd 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -25,10 +25,11 @@ #include "cafPdmFieldCvfColor.h" -#include "RimFaultCollection.h" #include "RigMainGrid.h" -#include "RimReservoirView.h" +#include "RimFaultCollection.h" #include "RimFaultResultSlot.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" //-------------------------------------------------------------------------------------------------- @@ -182,14 +183,13 @@ void RivReservoirFaultsPartMgr::updateColors(size_t timeStepIndex, RimResultSlot { RimFault* rimFault = faultCollection->faults[i]; - if (m_reservoirView->faultResultSettings()->showCustomFaultResult() && - m_reservoirView->faultResultSettings()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) + if (cellResultSlot && (cellResultSlot->hasResult() || cellResultSlot->isTernarySaturationSelected()) ) { - m_faultParts[i]->applySingleColorEffect(); + m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); } else { - m_faultParts[i]->updateCellResultColor(timeStepIndex, cellResultSlot); + m_faultParts[i]->applySingleColorEffect(); } } } diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 33a7f6a880..40a464e9f8 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -160,7 +160,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() infoText += QString("" "
MinP10 Mean P90 Max
%1 %2 %3 %4 %5
").arg(min).arg(p10).arg(mean).arg(p90).arg(max); - if (m_reservoirView->faultResultSettings()->visualizationMode() != RimFaultResultSlot::FAULT_COLOR) + if (m_reservoirView->faultResultSettings()->hasValidCustomResult()) { QString faultMapping; bool isShowingGrid = m_reservoirView->faultCollection()->isGridVisualizationMode(); @@ -185,10 +185,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() } infoText += QString("Fault results: %1
").arg(faultMapping); - } - if (m_reservoirView->faultResultSettings()->customFaultResult()) - { infoText += QString("Fault Property: %1
").arg(m_reservoirView->faultResultSettings()->customFaultResult()->resultVariable()); } } diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index dfdbcadf48..7bb41bb852 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -24,16 +24,6 @@ #include "RimUiTreeModelPdm.h" -namespace caf -{ - template<> - void AppEnum< RimFaultResultSlot::FaultVisualizationMode >::setUp() - { - addItem(RimFaultResultSlot::FAULT_COLOR, "FAULT_COLOR", "Fault Colors"); - addItem(RimFaultResultSlot::CUSTOM_RESULT_MAPPING, "CUSTOM_RESULT_MAPPING", "Custom Cell Results"); - setDefault(RimFaultResultSlot::FAULT_COLOR); - } -} CAF_PDM_SOURCE_INIT(RimFaultResultSlot, "RimFaultResultSlot"); @@ -47,7 +37,6 @@ RimFaultResultSlot::RimFaultResultSlot() CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); - CAF_PDM_InitField(&visualizationMode, "VisualizationMode", caf::AppEnum(RimFaultResultSlot::FAULT_COLOR), "Fault Color Mapping", "", "", ""); CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); @@ -88,13 +77,6 @@ void RimFaultResultSlot::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel m_customFaultResult->fieldChangedByUi(changedField, oldValue, newValue); - if (changedField == &visualizationMode) - { - updateFieldVisibility(); - - RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); - } - if (changedField == &m_customFaultResult->m_resultVariableUiField) { RiuMainWindow::instance()->uiPdmModel()->updateUiSubTree(this); @@ -127,12 +109,7 @@ void RimFaultResultSlot::updateFieldVisibility() //-------------------------------------------------------------------------------------------------- RimResultSlot* RimFaultResultSlot::customFaultResult() { - if (showCustomFaultResult() && this->visualizationMode() == CUSTOM_RESULT_MAPPING) - { - return this->m_customFaultResult(); - } - - return NULL; + return this->m_customFaultResult(); } //-------------------------------------------------------------------------------------------------- @@ -148,16 +125,12 @@ caf::PdmFieldHandle* RimFaultResultSlot::objectToggleField() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { - uiOrdering.add(&visualizationMode); uiOrdering.add(&showNNCs); - if (visualizationMode == CUSTOM_RESULT_MAPPING) - { - caf::PdmUiGroup* group1 = uiOrdering.addNewGroup("Result"); - group1->add(&(m_customFaultResult->m_resultTypeUiField)); - group1->add(&(m_customFaultResult->m_porosityModelUiField)); - group1->add(&(m_customFaultResult->m_resultVariableUiField)); - } + caf::PdmUiGroup* group1 = uiOrdering.addNewGroup("Result"); + group1->add(&(m_customFaultResult->m_resultTypeUiField)); + group1->add(&(m_customFaultResult->m_porosityModelUiField)); + group1->add(&(m_customFaultResult->m_resultVariableUiField)); } //-------------------------------------------------------------------------------------------------- @@ -168,3 +141,16 @@ QList RimFaultResultSlot::calculateValueOptions(const ca return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultResultSlot::hasValidCustomResult() +{ + if (m_customFaultResult->hasResult() || m_customFaultResult->isTernarySaturationSelected()) + { + return true; + } + + return false; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 07d4be9a53..ccf3d410d8 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -32,12 +32,6 @@ class RimReservoirView; class RimFaultResultSlot : public caf::PdmObject { CAF_PDM_HEADER_INIT; -public: - enum FaultVisualizationMode - { - FAULT_COLOR, - CUSTOM_RESULT_MAPPING - }; public: RimFaultResultSlot(); @@ -45,13 +39,13 @@ class RimFaultResultSlot : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); - caf::PdmField< caf::AppEnum< FaultVisualizationMode > > visualizationMode; caf::PdmField showNNCs; caf::PdmField showCustomFaultResult; + bool hasValidCustomResult(); + RimResultSlot* customFaultResult(); - RimResultSlot* customFaultResult(); - void updateFieldVisibility(); + void updateFieldVisibility(); virtual QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly ); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index ad6dcd7d65..b56a783381 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -921,10 +921,7 @@ void RimReservoirView::loadDataAndUpdate() CVF_ASSERT(this->cellEdgeResult() != NULL); this->cellEdgeResult()->loadResult(); - if (this->faultResultSettings()->customFaultResult()) - { - this->faultResultSettings()->customFaultResult()->loadResult(); - } + this->faultResultSettings()->customFaultResult()->loadResult(); this->faultResultSettings()->updateFieldVisibility(); updateViewerWidget(); @@ -1100,7 +1097,7 @@ void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, if (fault) { resultInfoText->append(QString("\nFault Name: %1\n").arg(fault->name())); - if (this->faultResultSettings()->customFaultResult()) + if (this->faultResultSettings()->hasValidCustomResult()) { resultInfoText->push_back("Fault result data:\n"); appendTextFromResultSlot(eclipseCase, gridIndex, cellIndex, this->m_currentTimeStep, this->faultResultSettings()->customFaultResult(), resultInfoText); @@ -1321,7 +1318,7 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResultSettings()->customFaultResult()) + if (this->faultResultSettings()->hasValidCustomResult()) { updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } @@ -1986,19 +1983,14 @@ void RimReservoirView::updateFaultColors() std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); RimResultSlot* faultResultSlot = this->cellResult(); - if (this->faultResultSettings()->customFaultResult()) + if (this->faultResultSettings()->showCustomFaultResult()) { faultResultSlot = this->faultResultSettings()->customFaultResult(); } - for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { - if (this->faultResultSettings()->visualizationMode() == RimFaultResultSlot::FAULT_COLOR) - { - m_reservoirGridPartManager->updateFaultColors(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot); - } - else if (this->animationMode() && this->cellEdgeResult()->hasResult()) + if (this->animationMode() && this->cellEdgeResult()->hasResult()) { m_reservoirGridPartManager->updateFaultCellEdgeResultColor(faultGeometriesToRecolor[i], m_currentTimeStep, faultResultSlot, this->cellEdgeResult()); } @@ -2039,7 +2031,7 @@ bool RimReservoirView::isTimeStepDependentDataVisible() const if (this->cellResult()->isTernarySaturationSelected()) return true; - if (this->faultResultSettings->customFaultResult()) + if (this->faultResultSettings->showCustomFaultResult()) { if (this->faultResultSettings->customFaultResult()->hasDynamicResult()) return true; From 56b1f78f2fd4e5b57194fa67c03016af68513b5d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 11:55:26 +0200 Subject: [PATCH 289/346] Faults : Show NNCs moved from fault result to fault collection --- .../ModelVisualization/RivReservoirFaultsPartMgr.cpp | 4 ++-- ApplicationCode/ProjectDataModel/RimFaultCollection.cpp | 5 ++++- ApplicationCode/ProjectDataModel/RimFaultCollection.h | 1 + ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp | 4 ---- ApplicationCode/ProjectDataModel/RimFaultResultSlot.h | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 7ea48d38fd..88e955d882 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -132,7 +132,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) rivFaultPart->appendOppositeFaultFacesToModel(&parts); } - if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || m_reservoirView->faultResultSettings()->showNNCs() || forceDisplayOfFault) + if (faultCollection->showFaultFaces() || faultCollection->showOppositeFaultFaces() || faultCollection->showNNCs() || forceDisplayOfFault) { rivFaultPart->appendMeshLinePartsToModel(&parts); } @@ -142,7 +142,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) if (rimFault->showFault() && faultCollection->showFaultCollection()) { - if (m_reservoirView->faultResultSettings()->showNNCs()) + if (faultCollection->showNNCs()) { rivFaultPart->appendNNCFacesToModel(&parts); } diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 996a8c2038..8fb630c009 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -68,6 +68,8 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showFaultLabel, "ShowFaultLabel", false, "Show labels", "", "", ""); cvf::Color3f defWellLabelColor = RiaApplication::instance()->preferences()->defaultWellLabelColor(); CAF_PDM_InitField(&faultLabelColor, "FaultLabelColor", defWellLabelColor, "Label color", "", "", ""); + + CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", ""); @@ -106,7 +108,8 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel &showFaultLabel == changedField || &m_showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || - &faultResult == changedField + &faultResult == changedField || + &showNNCs == changedField ) { if (m_reservoirView) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index bef8d05656..18254497ae 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -74,6 +74,7 @@ class RimFaultCollection : public caf::PdmObject caf::PdmField faultLabelColor; caf::PdmField showFaultCollection; + caf::PdmField showNNCs; caf::PdmPointersField faults; RimFault* findFaultByName(QString name); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 7bb41bb852..898458fbe3 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -37,8 +37,6 @@ RimFaultResultSlot::RimFaultResultSlot() CAF_PDM_InitField(&showCustomFaultResult, "ShowCustomFaultResult", false, "Show Custom Fault Result", "", "", ""); showCustomFaultResult.setUiHidden(true); - CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitFieldNoDefault(&m_customFaultResult, "CustomResultSlot", "Custom Fault Result", ":/CellResult.png", "", ""); m_customFaultResult = new RimResultSlot(); m_customFaultResult.setOwnerObject(this); @@ -125,8 +123,6 @@ caf::PdmFieldHandle* RimFaultResultSlot::objectToggleField() //-------------------------------------------------------------------------------------------------- void RimFaultResultSlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { - uiOrdering.add(&showNNCs); - caf::PdmUiGroup* group1 = uiOrdering.addNewGroup("Result"); group1->add(&(m_customFaultResult->m_resultTypeUiField)); group1->add(&(m_customFaultResult->m_porosityModelUiField)); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index ccf3d410d8..0e30db8422 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -39,7 +39,6 @@ class RimFaultResultSlot : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); - caf::PdmField showNNCs; caf::PdmField showCustomFaultResult; bool hasValidCustomResult(); From 670ca4ced57af4e61bf18ac57cbee267fab83544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 12:07:08 +0200 Subject: [PATCH 290/346] riTRANSXYZ: nnc calculations in place Making this feaure complete. Had to add the concept of several results sets to the nnc data --- .../FileInterface/RifReaderEclipseOutput.cpp | 3 +- .../ModelVisualization/RivFaultPartMgr.cpp | 8 +- .../RivNNCGeometryGenerator.cpp | 11 +- .../RivNNCGeometryGenerator.h | 2 +- ApplicationCode/ProjectDataModel/RimCase.cpp | 13 +- .../RimReservoirCellResultsStorage.cpp | 197 ++++++++++++++++-- .../RimReservoirCellResultsStorage.h | 2 +- .../ProjectDataModel/RimReservoirView.cpp | 11 +- .../ReservoirDataModel/RigNNCData.h | 33 ++- .../RigReservoirBuilderMock.cpp | 8 +- 10 files changed, 255 insertions(+), 33 deletions(-) diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index a004f1aedb..3743ef4c4d 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -479,13 +479,14 @@ void RifReaderEclipseOutput::transferNNCData( const ecl_grid_type * mainEclGrid //cvf::Trace::show("Reading NNC. Count: " + cvf::String(numNNC)); mainGrid->nncData()->connections().resize(numNNC); + std::vector& transmissibilityValues = mainGrid->nncData()->makeConnectionScalarResult(cvf::UNDEFINED_SIZE_T); for (int nIdx = 0; nIdx < numNNC; ++nIdx) { RigGridBase* grid1 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr1); mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->reservoirCellIndex(eclNNCData[nIdx].global_index1); RigGridBase* grid2 = mainGrid->gridByIndex(eclNNCData[nIdx].grid_nr2); mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->reservoirCellIndex(eclNNCData[nIdx].global_index2); - mainGrid->nncData()->connections()[nIdx].m_transmissibility = eclNNCData[nIdx].trans; + transmissibilityValues[nIdx] = eclNNCData[nIdx].trans; } diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 51385f94b8..25902b9fa8 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -647,11 +647,15 @@ void RivFaultPartMgr::updateNNCColors(RimResultSlot* cellResultSlot) { if (m_NNCFaces.isNull()) return; - if (cellResultSlot && cellResultSlot->resultVariable() == RimDefines::combinedTransmissibilityResultName()) + if (cellResultSlot + && ( cellResultSlot->resultVariable() == RimDefines::combinedTransmissibilityResultName() + || cellResultSlot->resultVariable() == RimDefines::combinedRiTransResultName())) { + size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); + const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); - m_NNCGenerator->textureCoordinates(m_NNCTextureCoords.p(), mapper); + m_NNCGenerator->textureCoordinates(m_NNCTextureCoords.p(), mapper, scalarSetIndex); cvf::ref nncEffect; diff --git a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp index 2e70f368d2..60810ab438 100644 --- a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp @@ -144,12 +144,19 @@ void RivNNCGeometryGenerator::computeArrays() /// Calculates the texture coordinates in a "nearly" one dimensional texture. /// Undefined values are coded with a y-texture coordinate value of 1.0 instead of the normal 0.5 //-------------------------------------------------------------------------------------------------- -void RivNNCGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper) const +void RivNNCGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, const cvf::ScalarMapper* mapper, size_t scalarResultIndex) const { size_t numVertices = m_vertices->size(); textureCoords->resize(numVertices); cvf::Vec2f* rawPtr = textureCoords->ptr(); + + const std::vector* nncResultVals = m_nncData->connectionScalarResult(scalarResultIndex); + if (!nncResultVals) + { + textureCoords->setAll(cvf::Vec2f(0.0f, 1.0f)); + return; + } double cellScalarValue; cvf::Vec2f texCoord; @@ -157,7 +164,7 @@ void RivNNCGeometryGenerator::textureCoordinates(cvf::Vec2fArray* textureCoords, #pragma omp parallel for private(texCoord, cellScalarValue) for (int tIdx = 0; tIdx < static_cast(m_triangleIndexToNNCIndex->size()); tIdx++) { - cellScalarValue = m_nncData->connections()[(*m_triangleIndexToNNCIndex)[tIdx]].m_transmissibility; + cellScalarValue = (*nncResultVals)[(*m_triangleIndexToNNCIndex)[tIdx]]; texCoord = mapper->mapToTextureCoord(cellScalarValue); if (cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue) // a != a is true for NAN's { diff --git a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h index 54c5ddf38a..902b44d24a 100644 --- a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h @@ -44,7 +44,7 @@ class RivNNCGeometryGenerator : public cvf::Object void setCellVisibility( const cvf::UByteArray* cellVisibilities, const RigGridBase * grid); void textureCoordinates(cvf::Vec2fArray* textureCoords, - const cvf::ScalarMapper* mapper) const; + const cvf::ScalarMapper* mapper, size_t scalarResultIndex) const; // Mapping between cells and geometry cvf::ref > triangleToNNCIndex() const; diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index aa0aeec7b8..d2a5532ad0 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -545,6 +545,10 @@ QString RimCase::relocateFile(const QString& orgFileName, const QString& orgNew //-------------------------------------------------------------------------------------------------- bool RimCase::openReserviorCase() { + // If read already, return + + if (this->reservoirData() != NULL) return true; + if (!openEclipseGridFile()) { return false; @@ -552,7 +556,14 @@ bool RimCase::openReserviorCase() { RimReservoirCellResultsStorage* results = this->results(RifReaderInterface::MATRIX_RESULTS); - if (results->cellResults()) results->cellResults()->createPlaceholderResultEntries(); + if (results->cellResults()) + { + results->cellResults()->createPlaceholderResultEntries(); + // After the placeholder result for combined transmissibility is created, + // make sure the nnc transmissibilities can be addressed by this scalarResultIndex as well + size_t combinedTransResIdx = results->cellResults()->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); + reservoirData()->mainGrid()->nncData()->setCombTransmisibilityScalarResultIndex(combinedTransResIdx); + } } { diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 27454e2b69..b0b9b145d2 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -342,6 +342,7 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result computeRiTransComponent(RimDefines::riTransXResultName()); computeRiTransComponent(RimDefines::riTransYResultName()); computeRiTransComponent(RimDefines::riTransZResultName()); + computeNncCombRiTrans(); } if ( resultName == RimDefines::riTransXResultName() @@ -438,8 +439,7 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex soilTimeStepCount = qMax(soilTimeStepCount, sgasTimeStepCount); } } - - + // Make sure memory is allocated for the new SOIL results size_t soilResultScalarIndex = m_cellResults->findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); @@ -453,7 +453,6 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex m_cellResults->cellScalarResults(soilResultScalarIndex, timeStepIndex).resize(soilResultValueCount); - std::vector* swatForTimeStep = NULL; std::vector* sgasForTimeStep = NULL; @@ -735,8 +734,8 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Get the needed result indices we depend on size_t permResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, permCompName); - size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); - + size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); + // Get the result index of the output size_t riTransResultIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riTransComponentResultName); @@ -751,8 +750,8 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Get all the actual result values - std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; - std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; + std::vector & permResults = m_cellResults->cellScalarResults(permResultIdx)[0]; + std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; // Set up output container to correct number of results @@ -761,15 +760,15 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Prepare how to index the result values: - bool isPermUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permResultIdx); - bool isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); + bool isPermUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permResultIdx); + bool isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); bool isTransUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(riTransResultIdx); - + // Set up result index function pointers - ResultIndexFunction riTranIdxFunc = isTransUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; - ResultIndexFunction permIdxFunc = isPermUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; - ResultIndexFunction ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction riTranIdxFunc = isTransUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction permIdxFunc = isPermUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); @@ -800,20 +799,20 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Do nothing if neighbor cell has no results size_t neighborCellPermResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); if (neighborCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; - + // Connection geometry const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); bool isOnFault = fault; - + cvf::Vec3d faceAreaVec; cvf::Vec3d faceCenter; if (isOnFault) { - calculateConnectionGeometry( nativeCell, neighborCell, nodes,faceId, - &faceCenter, &faceAreaVec); + calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, + &faceCenter, &faceAreaVec); } else { @@ -863,7 +862,169 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr } } - +} + +#if 1 +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeNncCombRiTrans() +{ + if (!m_cellResults) return; + + size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName()); + if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex)) return; + + // Todo: Get the correct one from Unit set read by ERT + double cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) + + // Get the needed result indices we depend on + + size_t permXResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMX"); + size_t permYResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMY"); + size_t permZResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "PERMZ"); + + size_t ntgResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, "NTG"); + + // Get the result count, to handle that one of them might be globally defined + + size_t permxResultValueCount = m_cellResults->cellScalarResults(permXResultIdx)[0].size(); + size_t ntgResultValueCount = m_cellResults->cellScalarResults(ntgResultIdx)[0].size(); + + size_t resultValueCount = CVF_MIN(permxResultValueCount, ntgResultValueCount); + + // Get all the actual result values + + std::vector & permXResults = m_cellResults->cellScalarResults(permXResultIdx)[0]; + std::vector & permYResults = m_cellResults->cellScalarResults(permYResultIdx)[0]; + std::vector & permZResults = m_cellResults->cellScalarResults(permZResultIdx)[0]; + std::vector & ntgResults = m_cellResults->cellScalarResults(ntgResultIdx)[0]; + std::vector & riCombTransResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombTransScalarResultIndex); + + + // Prepare how to index the result values: + + bool isPermXUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permXResultIdx); + bool isPermYUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permYResultIdx); + bool isPermZUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(permZResultIdx); + bool isNtgUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(ntgResultIdx); + + + // Set up result index function pointers + + ResultIndexFunction permXIdxFunc = isPermXUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction permYIdxFunc = isPermYUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction permZIdxFunc = isPermZUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + ResultIndexFunction ntgIdxFunc = isNtgUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + + + const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); + const std::vector& nodes = m_ownerMainGrid->nodes(); + bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); + + // NNC calculation + std::vector& nncConnections = m_ownerMainGrid->nncData()->connections(); + for (size_t connIdx = 0; connIdx < nncConnections.size(); connIdx++) + { + size_t nativeResvCellIndex = nncConnections[connIdx].m_c1GlobIdx; + size_t neighborResvCellIdx = nncConnections[connIdx].m_c2GlobIdx; + cvf::StructGridInterface::FaceType faceId = nncConnections[connIdx].m_c1Face; + + ResultIndexFunction permIdxFunc = NULL; + std::vector * permResults; + + switch (faceId) + { + case cvf::StructGridInterface::POS_I: + case cvf::StructGridInterface::NEG_I: + permIdxFunc = permXIdxFunc; + permResults = &permXResults; + break; + case cvf::StructGridInterface::POS_J: + case cvf::StructGridInterface::NEG_J: + permIdxFunc = permYIdxFunc; + permResults = &permYResults; + break; + case cvf::StructGridInterface::POS_K: + case cvf::StructGridInterface::NEG_K: + permIdxFunc = permZIdxFunc; + permResults = &permZResults; + break; + } + + // Do nothing if we are only dealing with active cells, and this cell is not active: + size_t nativeCellPermResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); + if (nativeCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; + + // Do nothing if neighbor cell has no results + size_t neighborCellPermResIdx = (*permIdxFunc)(activeCellInfo, neighborResvCellIdx); + if (neighborCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; + + + const RigCell& nativeCell = m_ownerMainGrid->cells()[nativeResvCellIndex]; + const RigCell& neighborCell = m_ownerMainGrid->cells()[neighborResvCellIdx]; + + + // Connection geometry + + cvf::Vec3d faceAreaVec = cvf::Vec3d::ZERO;; + cvf::Vec3d faceCenter = cvf::Vec3d::ZERO;; + + // Polygon center + const std::vector& realPolygon = nncConnections[connIdx].m_polygon; + for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) + { + faceCenter += realPolygon[pIdx]; + } + + faceCenter *= 1.0 / realPolygon.size(); + + // Polygon area vector + + faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); + + if (!isFaceNormalsOutwards) faceAreaVec = -faceAreaVec; + + double halfCellTrans = 0; + double neighborHalfCellTrans = 0; + + // Native cell half cell transm + { + cvf::Vec3d centerToFace = faceCenter - nativeCell.center(); + + double perm = (*permResults)[nativeCellPermResIdx]; + + double ntg = 1.0; + if (faceId != cvf::StructGridInterface::POS_K) + { + size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, nativeResvCellIndex); + ntg = ntgResults[ntgResIdx]; + } + + halfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); + } + + // Neighbor cell half cell transm + { + cvf::Vec3d centerToFace = faceCenter - neighborCell.center(); + + double perm = (*permResults)[neighborCellPermResIdx]; + + double ntg = 1.0; + if (faceId != cvf::StructGridInterface::POS_K) + { + size_t ntgResIdx = (*ntgIdxFunc)(activeCellInfo, neighborResvCellIdx); + ntg = ntgResults[ntgResIdx]; + } + + neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); + } + + double newtranTemp = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); + riCombTransResults[connIdx] = newtranTemp; + } +#endif + } #endif diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 56136624c8..50f4603e4c 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -66,10 +66,10 @@ class RimReservoirCellResultsStorage : public caf::PdmObject private: void computeSOILForTimeStep(size_t timeStepIndex); void computeRiTransComponent(const QString& riTransComponentResultName); + void computeNncCombRiTrans(); QString getValidCacheFileName(); QString getCacheDirectoryPath(); - // Fields caf::PdmField m_resultCacheFileName; caf::PdmPointersField diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index b56a783381..6e434b06c6 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1817,9 +1817,16 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) const RigConnection& conn = nncData->connections()[nncIndex]; cvf::StructGridInterface::FaceEnum face(conn.m_c1Face); + // Print result value for the NNC + size_t scalarResultIdx = this->cellResult()->gridScalarIndex(); + const std::vector* nncValues = nncData->connectionScalarResult(scalarResultIdx); + if (nncValues) + { + resultInfo->append(QString("NNC Value : %1\n").arg((*nncValues)[nncIndex])); + } + QString faultName; - - resultInfo->append(QString("NNC Transmissibility : %1\n").arg(conn.m_transmissibility)); + { CVF_ASSERT(conn.m_c1GlobIdx < grid->cells().size()); const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index f574106d34..6d653a4220 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -36,8 +36,7 @@ class RigConnection RigConnection( ) : m_c1GlobIdx(cvf::UNDEFINED_SIZE_T), m_c1Face(cvf::StructGridInterface::NO_FACE), - m_c2GlobIdx(cvf::UNDEFINED_SIZE_T), - m_transmissibility(0.0) + m_c2GlobIdx(cvf::UNDEFINED_SIZE_T) {} bool hasCommonArea() const @@ -49,8 +48,6 @@ class RigConnection cvf::StructGridInterface::FaceType m_c1Face; size_t m_c2GlobIdx; - double m_transmissibility; - std::vector m_polygon; }; @@ -66,6 +63,33 @@ class RigNNCData : public cvf::Object std::vector& connections() { return m_connections; } const std::vector& connections() const { return m_connections; }; + std::vector& makeConnectionScalarResult(size_t scalarResultIndex) + { + std::vector& results = m_connectionResults[scalarResultIndex]; + results.resize(m_connections.size(), HUGE_VAL); + return results; + } + + const std::vector* connectionScalarResult(size_t scalarResultIndex) const + { + std::map >::const_iterator it = m_connectionResults.find(scalarResultIndex); + if (it != m_connectionResults.end()) + return &(it->second); + else + return NULL; + } + + void setCombTransmisibilityScalarResultIndex(size_t scalarResultIndex) + { + std::map >::iterator it = m_connectionResults.find(cvf::UNDEFINED_SIZE_T); + CVF_ASSERT(it != m_connectionResults.end()); + + std::vector& emptyData = m_connectionResults[scalarResultIndex]; + std::vector& realData = m_connectionResults[cvf::UNDEFINED_SIZE_T]; + emptyData.swap(realData); + m_connectionResults.erase(cvf::UNDEFINED_SIZE_T); + } + private: // This section is possibly not needed //const std::vector& findConnectionIndices(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; //typedef std::map, 7 > > ConnectionSearchMap; @@ -73,4 +97,5 @@ class RigNNCData : public cvf::Object private: std::vector m_connections; + std::map > m_connectionResults; ///< scalarResultIndex to value array map }; diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index 05b3f5c651..697edfc501 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -541,6 +541,13 @@ void RigReservoirBuilderMock::addFaults(RigCaseData* eclipseCase) addNnc(grid, i1, j1, k1, i2, j2, k2, nncConnections); } + + std::vector& tranVals = grid->nncData()->makeConnectionScalarResult(cvf::UNDEFINED_SIZE_T); + for (size_t cIdx = 0; cIdx < tranVals.size(); ++cIdx) + { + tranVals[cIdx] = 0.2; + } + } //-------------------------------------------------------------------------------------------------- @@ -562,7 +569,6 @@ void RigReservoirBuilderMock::addNnc(RigMainGrid* grid, size_t i1, size_t j1, si RigConnection conn; conn.m_c1GlobIdx = c1GlobalIndex; conn.m_c2GlobIdx = c2GlobalIndex; - conn.m_transmissibility = 0.2; nncConnections.push_back(conn); } From 27571a839a2b7990a0e2cefeae169f67a9137ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 13:35:49 +0200 Subject: [PATCH 291/346] Linux compile fix --- ApplicationCode/ReservoirDataModel/RigNNCData.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index 6d653a4220..626a47fa93 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -23,6 +23,7 @@ #include "cvfVector3.h" #include +#include #include "cvfStructGrid.h" #include "cafFixedArray.h" From 28f563960707464f865d031b4842fc25161f3235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 13:36:38 +0200 Subject: [PATCH 292/346] riTRANSXYZ: Removed unused code --- .../RimReservoirCellResultsStorage.cpp | 152 +++++------ .../ReservoirDataModel/CMakeLists_files.cmake | 2 - .../RigCombRiTransResultAccessor.cpp | 248 ------------------ .../RigCombRiTransResultAccessor.h | 70 ----- .../RigResultAccessorFactory.cpp | 15 -- 5 files changed, 76 insertions(+), 411 deletions(-) delete mode 100644 ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp delete mode 100644 ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index b0b9b145d2..bd249b8359 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -601,101 +601,104 @@ void RimReservoirCellResultsStorage::computeDepthRelatedResults() } } -#if 1 - -void calculateConnectionGeometry(const RigCell& c1, const RigCell& c2 , const std::vector& nodes, - cvf::StructGridInterface::FaceType faceId, - cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) +namespace RigTransmissibilityCalcTools { - CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); - - *faceCenter = cvf::Vec3d::ZERO; - *faceAreaVec = cvf::Vec3d::ZERO; + void calculateConnectionGeometry(const RigCell& c1, const RigCell& c2, const std::vector& nodes, + cvf::StructGridInterface::FaceType faceId, + cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) + { + CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); - std::vector polygon; - std::vector intersections; - caf::SizeTArray4 face1; - caf::SizeTArray4 face2; - c1.faceIndices(faceId, &face1); - c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); + *faceCenter = cvf::Vec3d::ZERO; + *faceAreaVec = cvf::Vec3d::ZERO; - bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( - &polygon, - &intersections, - (cvf::EdgeIntersectStorage*)NULL, - cvf::wrapArrayConst(&nodes), - face1.data(), - face2.data(), - 1e-6); + std::vector polygon; + std::vector intersections; + caf::SizeTArray4 face1; + caf::SizeTArray4 face2; + c1.faceIndices(faceId, &face1); + c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); + bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( + &polygon, + &intersections, + (cvf::EdgeIntersectStorage*)NULL, + cvf::wrapArrayConst(&nodes), + face1.data(), + face2.data(), + 1e-6); - if (foundOverlap) - { - std::vector realPolygon; - for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) + if (foundOverlap) { - if (polygon[pIdx] < nodes.size()) - realPolygon.push_back(nodes[polygon[pIdx]]); - else - realPolygon.push_back(intersections[polygon[pIdx] - nodes.size()]); - } + std::vector realPolygon; - // Polygon center - for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) - { - *faceCenter += realPolygon[pIdx]; - } + for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) + { + if (polygon[pIdx] < nodes.size()) + realPolygon.push_back(nodes[polygon[pIdx]]); + else + realPolygon.push_back(intersections[polygon[pIdx] - nodes.size()]); + } - *faceCenter *= 1.0 / realPolygon.size(); + // Polygon center + for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) + { + *faceCenter += realPolygon[pIdx]; + } - // Polygon area vector + *faceCenter *= 1.0 / realPolygon.size(); - *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); + // Polygon area vector - } + *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); -} + } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) -{ - return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); -} + } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) -{ - return cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); -} + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) + { + return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); + } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -typedef size_t (*ResultIndexFunction)(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex); + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) + { + return cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); + } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + typedef size_t(*ResultIndexFunction)(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex); -size_t directReservoirCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) -{ - return reservoirCellIndex; -} + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- + size_t directReservoirCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) + { + return reservoirCellIndex; + } -size_t reservoirActiveCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) -{ - return activeCellinfo->cellResultIndex(reservoirCellIndex); + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + + size_t reservoirActiveCellIndex(const RigActiveCellInfo* activeCellinfo, size_t reservoirCellIndex) + { + return activeCellinfo->cellResultIndex(reservoirCellIndex); + } } +using namespace RigTransmissibilityCalcTools; + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -864,7 +867,6 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr } } -#if 1 //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1023,11 +1025,9 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() double newtranTemp = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); riCombTransResults[connIdx] = newtranTemp; } -#endif } -#endif //-------------------------------------------------------------------------------------------------- /// diff --git a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake index b840aa81f7..06835f0e32 100644 --- a/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ReservoirDataModel/CMakeLists_files.cmake @@ -17,7 +17,6 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.h -${CEE_CURRENT_LIST_DIR}RigCombRiTransResultAccessor.h ${CEE_CURRENT_LIST_DIR}RigResultModifier.h ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.h ${CEE_CURRENT_LIST_DIR}RigLocalGrid.h @@ -51,7 +50,6 @@ ${CEE_CURRENT_LIST_DIR}RigActiveCellsResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCellEdgeResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigCombMultResultAccessor.cpp -${CEE_CURRENT_LIST_DIR}RigCombRiTransResultAccessor.cpp ${CEE_CURRENT_LIST_DIR}RigResultModifierFactory.cpp ${CEE_CURRENT_LIST_DIR}RigLocalGrid.cpp ${CEE_CURRENT_LIST_DIR}RigMainGrid.cpp diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp deleted file mode 100644 index 5f95b1eb1f..0000000000 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.cpp +++ /dev/null @@ -1,248 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) Statoil ASA, Ceetron Solutions AS -// -// 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 -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "RigCombRiTransResultAccessor.h" - -#include "RigMainGrid.h" -#include "RigGridBase.h" -#include "RigCell.h" - -#include -#include "cvfGeometryTools.h" - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RigCombRiTransResultAccessor::RigCombRiTransResultAccessor(const RigGridBase* grid) - : m_grid(grid) -{ - m_cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) -} - -//-------------------------------------------------------------------------------------------------- -/// Only sensible to provide the positive values, as the negative ones will never be used. -/// The negative faces gets their value from the neighbor cell in that direction -//-------------------------------------------------------------------------------------------------- -void RigCombRiTransResultAccessor::setPermResultAccessors( RigResultAccessor* xPermAccessor, - RigResultAccessor* yPermAccessor, - RigResultAccessor* zPermAccessor) - -{ - m_xPermAccessor = xPermAccessor; - m_yPermAccessor = yPermAccessor; - m_zPermAccessor = zPermAccessor; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RigCombRiTransResultAccessor::setNTGResultAccessor(RigResultAccessor* ntgAccessor) -{ - m_ntgAccessor = ntgAccessor; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const -{ - CVF_TIGHT_ASSERT(false); - - return HUGE_VAL; -} - -double RigCombRiTransResultAccessor::getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const -{ - switch (faceId) - { - case cvf::StructGridInterface::POS_I: - case cvf::StructGridInterface::NEG_I: - { - return m_xPermAccessor->cellScalar(gridLocalCellIndex); - } - break; - case cvf::StructGridInterface::POS_J: - case cvf::StructGridInterface::NEG_J: - { - return m_yPermAccessor->cellScalar(gridLocalCellIndex); - } - break; - case cvf::StructGridInterface::POS_K: - case cvf::StructGridInterface::NEG_K: - { - return m_zPermAccessor->cellScalar(gridLocalCellIndex); - } - break; - } - return HUGE_VAL; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::getNtgValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId ) const -{ - double ntg = 1.0; - - if (faceId != cvf::StructGridInterface::POS_K && faceId != cvf::StructGridInterface::NEG_K) - { - m_ntgAccessor->cellScalar(gridLocalCellIndex); - } - - return ntg; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec) -{ - return perm*ntg*(faceAreaVec*centerToFace) / (centerToFace*centerToFace); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) -{ - return cdarchy * mult / ( ( 1 / halfCellTrans) + (1 / neighborHalfCellTrans) ); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::calculateHalfCellTrans(size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, bool isFaultFace) const -{ - const RigCell& cell = m_grid->cell(gridLocalCellIndex); - - - cvf::Vec3d faceAreaVec; - cvf::Vec3d faceCenter; - - if (isFaultFace) - { - - calculateConnectionGeometry( m_grid, gridLocalCellIndex, neighborGridCellIdx, faceId, &faceCenter, &faceAreaVec); - } - else - { - const RigCell& cell = m_grid->cell(gridLocalCellIndex); - faceCenter = cell.faceCenter(faceId); - - faceAreaVec = cell.faceNormalWithAreaLenght(faceId); - } - - cvf::Vec3d centerToFace = faceCenter - cell.center(); - - double perm = getPermValue(gridLocalCellIndex, faceId); - double ntg = getNtgValue(gridLocalCellIndex, faceId ); - - return halfCellTransmissibility(perm, ntg, centerToFace, faceAreaVec); -} - -void RigCombRiTransResultAccessor::calculateConnectionGeometry( const RigGridBase* grid, size_t gridLocalCellIndex, size_t neighborGridCellIdx, - cvf::StructGridInterface::FaceType faceId, - cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) -{ - CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); - - *faceCenter = cvf::Vec3d::ZERO; - *faceAreaVec = cvf::Vec3d::ZERO; - const RigMainGrid* mainGrid = grid->mainGrid(); - - const RigCell& c1 = grid->cell(gridLocalCellIndex); - const RigCell& c2 = grid->cell(neighborGridCellIdx); - - std::vector polygon; - std::vector intersections; - caf::SizeTArray4 face1; - caf::SizeTArray4 face2; - c1.faceIndices(faceId, &face1); - c2.faceIndices(cvf::StructGridInterface::oppositeFace(faceId), &face2); - - bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( - &polygon, - &intersections, - (cvf::EdgeIntersectStorage*)NULL, - cvf::wrapArrayConst(&(mainGrid->nodes())), - face1.data(), - face2.data(), - 1e-6); - - - if (foundOverlap) - { - std::vector realPolygon; - - for (size_t pIdx = 0; pIdx < polygon.size(); ++pIdx) - { - if (polygon[pIdx] < grid->mainGrid()->nodes().size()) - realPolygon.push_back(grid->mainGrid()->nodes()[polygon[pIdx]]); - else - realPolygon.push_back(intersections[polygon[pIdx] - grid->mainGrid()->nodes().size()]); - } - - // Polygon center - for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) - { - *faceCenter += realPolygon[pIdx]; - } - - *faceCenter *= 1.0/realPolygon.size(); - - // Polygon area vector - - *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); - - } - -} -//-------------------------------------------------------------------------------------------------- -/// -/// Neighbor cell transmisibilities only is calculated here -/// Not NNC transmisibilities. That has to be done separately elsewhere -/// -/// Todo: What about Grid to Grid connections ? -/// Todo: needs optimization. Things are done several times. Caching of the results should be considered. etc. -/// -//-------------------------------------------------------------------------------------------------- -double RigCombRiTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const -{ - size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); - - if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) - { - size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex); - const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace(reservoirCellIndex, faceId); - bool isOnFault = fault; - - double halfCellTrans = 0; - double neighborHalfCellTrans = 0; - - halfCellTrans = calculateHalfCellTrans(gridLocalCellIndex, neighborGridCellIdx, faceId, isOnFault); - neighborHalfCellTrans = calculateHalfCellTrans(neighborGridCellIdx, gridLocalCellIndex, cvf::StructGridInterface::oppositeFace(faceId), isOnFault); - - return newtran(m_cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); - } - - return HUGE_VAL; -} diff --git a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h deleted file mode 100644 index 9ffe227112..0000000000 --- a/ApplicationCode/ReservoirDataModel/RigCombRiTransResultAccessor.h +++ /dev/null @@ -1,70 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// Copyright (C) Statoil ASA, Ceetron Solutions AS -// -// 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 -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "RigResultAccessor.h" - -#include "cvfCollection.h" - -class RigGridBase; - - -//================================================================================================== -/// -//================================================================================================== -class RigCombRiTransResultAccessor : public RigResultAccessor -{ -public: - RigCombRiTransResultAccessor(const RigGridBase* grid); - - void setPermResultAccessors(RigResultAccessor* xPermAccessor, - RigResultAccessor* yPermAccessor, - RigResultAccessor* zPermAccessor); - void setNTGResultAccessor( RigResultAccessor* ntgAccessor); - - /// CDARCY Darcy's constant - /// = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC) - /// = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD) - /// = 3.6 (LAB) - /// = 0.00864 (PVT-M) - void setCDARCHY(double cDarchy) { m_cdarchy = cDarchy;} - - virtual double cellScalar(size_t gridLocalCellIndex) const; - virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; - -private: - double getPermValue(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; - double calculateHalfCellTrans( size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, bool isFaultFace) const; - - double getNtgValue( size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId ) const; - static void calculateConnectionGeometry( const RigGridBase* grid, size_t gridLocalCellIndex, size_t neighborGridCellIdx, cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* centerToFace, cvf::Vec3d* faceAreaVec); - - static double halfCellTransmissibility(double perm, double ntg, const cvf::Vec3d& centerToFace, const cvf::Vec3d& faceAreaVec); - static double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans); - - cvf::ref m_xPermAccessor; - cvf::ref m_yPermAccessor; - cvf::ref m_zPermAccessor; - - cvf::ref m_ntgAccessor; - - double m_cdarchy; - - const RigGridBase* m_grid; -}; diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 15c6665f8b..6d5a729236 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -35,7 +35,6 @@ #include "cvfObject.h" #include -#include "RigCombRiTransResultAccessor.h" //-------------------------------------------------------------------------------------------------- /// @@ -91,20 +90,6 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); return cellFaceAccessObject; -#if 0 - cvf::ref cellFaceAccessObject = new RigCombRiTransResultAccessor(grid); - - cvf::ref permX = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMX"); - cvf::ref permY = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMY"); - cvf::ref permZ = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "PERMZ"); - cvf::ref ntg = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, "NTG"); - - cellFaceAccessObject->setPermResultAccessors(permX.p(), permY.p(), permZ.p()); - cellFaceAccessObject->setNTGResultAccessor(ntg.p()); - // todo : cellFaceAccessObject->setCDARCHY(); - - return cellFaceAccessObject; -#endif } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); From 76d6304f792eb86de869cff424fedda9e869832c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 12:16:25 +0200 Subject: [PATCH 293/346] Pick info : Use IJK instead of XYZ --- Fwk/AppFwk/CommonCode/cvfStructGrid.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp b/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp index 3c2c240986..9575d3afb4 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp @@ -44,12 +44,12 @@ namespace caf template<> void cvf::StructGridInterface::FaceEnum::setUp() { - addItem(cvf::StructGridInterface::POS_I, "X", ""); - addItem(cvf::StructGridInterface::NEG_I, "X-", ""); - addItem(cvf::StructGridInterface::POS_J, "Y", ""); - addItem(cvf::StructGridInterface::NEG_J, "Y-", ""); - addItem(cvf::StructGridInterface::POS_K, "Z", ""); - addItem(cvf::StructGridInterface::NEG_K, "Z-", ""); + addItem(cvf::StructGridInterface::POS_I, "POS I", ""); + addItem(cvf::StructGridInterface::NEG_I, "NEG I", ""); + addItem(cvf::StructGridInterface::POS_J, "POS J", ""); + addItem(cvf::StructGridInterface::NEG_J, "NEG J", ""); + addItem(cvf::StructGridInterface::POS_K, "POS K", ""); + addItem(cvf::StructGridInterface::NEG_K, "NEG K", ""); addItem(cvf::StructGridInterface::NO_FACE, "UnDef", ""); } } From 473a701bf503d53f58112849f303542e5ea0f427 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 13:34:20 +0200 Subject: [PATCH 294/346] Result info : Improved display of text --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 8 +++++--- ApplicationCode/ProjectDataModel/RimReservoirView.h | 2 +- ApplicationCode/UserInterface/RiuViewer.cpp | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 6e434b06c6..b36883f60d 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1035,7 +1035,7 @@ RiuViewer* RimReservoirView::viewer() //-------------------------------------------------------------------------------------------------- /// Get pick info text for given part ID, face index, and intersection point //-------------------------------------------------------------------------------------------------- -bool RimReservoirView::pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString* pickInfoText) const +bool RimReservoirView::pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString itemSeparator, QString* pickInfoText) const { CVF_ASSERT(pickInfoText); @@ -1060,10 +1060,12 @@ bool RimReservoirView::pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructG QString faceText = faceEnum.text(); - *pickInfoText = QString("Hit grid %1, cell [%2, %3, %4] face %5, ").arg(gridIndex).arg(i).arg(j).arg(k).arg(faceText); + *pickInfoText += QString("Hit grid %1").arg(gridIndex) + itemSeparator; + *pickInfoText += QString("Cell : [%1, %2, %3]").arg(i).arg(j).arg(k) + itemSeparator; + *pickInfoText += QString("Face : %1").arg(faceText) + itemSeparator; QString formattedText; - formattedText.sprintf("intersection point: [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); + formattedText.sprintf("Intersection point : [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); *pickInfoText += formattedText; return true; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 261df2cbad..e0f77fbf31 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -159,7 +159,7 @@ class RimReservoirView : public caf::PdmObject // Picking info - bool pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString* pickInfoText) const; + bool pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString itemSeparator, QString* pickInfoText) const; void appendCellResultInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) ; void appendNNCResultInfo(size_t nncIndex, QString* resultInfo); static void appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText); diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 29476f1678..e0654348a0 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -416,10 +416,10 @@ void RiuViewer::handlePickAction(int winPosX, int winPosY) cvf::StructGridInterface::FaceType face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); - m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, &pickInfo); + m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, ", ", &pickInfo); // Build up result from from both pick info and result values - m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, &resultInfo); + m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, "\n", &resultInfo); resultInfo += "\n"; m_reservoirView->appendCellResultInfo(gridIndex, cellIndex, face, &resultInfo); #if 0 From 10c76f2926666bfbbf3e00313c1a76359358c317 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 14:37:20 +0200 Subject: [PATCH 295/346] Fault import : Handle invalid fault specification gracefully --- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index dedd0e78f0..ffab327e42 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -912,7 +912,9 @@ void RifEclipseInputFileTools::readFaults(QFile &data, qint64 filePos, cvf::Coll cvf::StructGridInterface::FaceEnum cellFaceEnum = cvf::StructGridInterface::FaceEnum::fromText(faceString); - cvf::CellRange cellrange(i1 - 1, j1 - 1, k1 - 1, i2 - 1, j2 - 1, k2 - 1); // Adjust from 1-based to 0-based cell indices + // Adjust from 1-based to 0-based cell indices + // Guard against invalid cell ranges by limiting lowest possible range value to zero + cvf::CellRange cellrange(CVF_MAX(i1 - 1, 0), CVF_MAX(j1 - 1, 0), CVF_MAX(k1 - 1, 0), CVF_MAX(i2 - 1, 0), CVF_MAX(j2 - 1, 0), CVF_MAX(k2 - 1, 0)); if (!(fault && fault->name() == name)) { From 0bd0d6d7a7e2b82e05464fc97abc5f610cdc1952 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 26 Aug 2014 14:46:48 +0200 Subject: [PATCH 296/346] Linux fix: Added include of cmath and reorganized includes --- ApplicationCode/ReservoirDataModel/RigNNCData.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index 626a47fa93..2b2eec9332 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -21,16 +21,17 @@ #include "cvfBase.h" #include "cvfObject.h" #include "cvfVector3.h" +#include "cvfStructGrid.h" -#include +#include "cafFixedArray.h" + +#include // Needed for HUGE_VAL on Linux #include +#include -#include "cvfStructGrid.h" -#include "cafFixedArray.h" class RigMainGrid; - class RigConnection { public: From 1e59e050e69dc10a85815bfb364af5df5394185e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 14:06:55 +0200 Subject: [PATCH 297/346] Moved methods --- .../RimReservoirCellResultsStorage.cpp | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index bd249b8359..49c3aff8f3 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -218,74 +218,37 @@ RifReaderInterface* RimReservoirCellResultsStorage::readerInterface() return m_readerInterface.p(); } + //-------------------------------------------------------------------------------------------------- -/// This method is intended to be used for multicase cross statistical calculations, when -/// we need process one timestep at a time, freeing memory as we go. +/// //-------------------------------------------------------------------------------------------------- -size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex) +size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(const QString& resultName) { if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; - // Special handling for SOIL - if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") - { - size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); - { - computeSOILForTimeStep(timeStepIndex); - } - - return soilScalarResultIndex; - } + size_t scalarResultIndex = cvf::UNDEFINED_SIZE_T; - size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); - if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; + scalarResultIndex = this->findOrLoadScalarResult(RimDefines::STATIC_NATIVE, resultName); - if (type == RimDefines::GENERATED) + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { - return cvf::UNDEFINED_SIZE_T; + scalarResultIndex = this->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, resultName); } - if (m_readerInterface.notNull()) + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) { - size_t timeStepCount = m_cellResults->infoForEachResultIndex()[scalarResultIndex].m_timeStepDates.size(); - - bool resultLoadingSucess = true; - - if (type == RimDefines::DYNAMIC_NATIVE && timeStepCount > 0) - { - m_cellResults->cellScalarResults(scalarResultIndex).resize(timeStepCount); - - std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[timeStepIndex]; - if (values.size() == 0) - { - if (!m_readerInterface->dynamicResult(resultName, RifReaderInterface::MATRIX_RESULTS, timeStepIndex, &values)) - { - resultLoadingSucess = false; - } - } - } - else if (type == RimDefines::STATIC_NATIVE) - { - m_cellResults->cellScalarResults(scalarResultIndex).resize(1); - - std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[0]; - if (!m_readerInterface->staticResult(resultName, RifReaderInterface::MATRIX_RESULTS, &values)) - { - resultLoadingSucess = false; - } - } + scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::GENERATED, resultName); + } - if (!resultLoadingSucess) - { - // Error logging - CVF_ASSERT(false); - } + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) + { + scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::INPUT_PROPERTY, resultName); } return scalarResultIndex; - } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -399,6 +362,74 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result return scalarResultIndex; } +//-------------------------------------------------------------------------------------------------- +/// This method is intended to be used for multicase cross statistical calculations, when +/// we need process one timestep at a time, freeing memory as we go. +//-------------------------------------------------------------------------------------------------- +size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefines::ResultCatType type, const QString& resultName, size_t timeStepIndex) +{ + if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; + + // Special handling for SOIL + if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") + { + size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); + { + computeSOILForTimeStep(timeStepIndex); + } + + return soilScalarResultIndex; + } + + size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); + if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) return cvf::UNDEFINED_SIZE_T; + + if (type == RimDefines::GENERATED) + { + return cvf::UNDEFINED_SIZE_T; + } + + if (m_readerInterface.notNull()) + { + size_t timeStepCount = m_cellResults->infoForEachResultIndex()[scalarResultIndex].m_timeStepDates.size(); + + bool resultLoadingSucess = true; + + if (type == RimDefines::DYNAMIC_NATIVE && timeStepCount > 0) + { + m_cellResults->cellScalarResults(scalarResultIndex).resize(timeStepCount); + + std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[timeStepIndex]; + if (values.size() == 0) + { + if (!m_readerInterface->dynamicResult(resultName, RifReaderInterface::MATRIX_RESULTS, timeStepIndex, &values)) + { + resultLoadingSucess = false; + } + } + } + else if (type == RimDefines::STATIC_NATIVE) + { + m_cellResults->cellScalarResults(scalarResultIndex).resize(1); + + std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[0]; + if (!m_readerInterface->staticResult(resultName, RifReaderInterface::MATRIX_RESULTS, &values)) + { + resultLoadingSucess = false; + } + } + + if (!resultLoadingSucess) + { + // Error logging + CVF_ASSERT(false); + } + } + + return scalarResultIndex; + +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1029,37 +1060,6 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(const QString& resultName) -{ - if (!m_cellResults) return cvf::UNDEFINED_SIZE_T; - - size_t scalarResultIndex = cvf::UNDEFINED_SIZE_T; - - scalarResultIndex = this->findOrLoadScalarResult(RimDefines::STATIC_NATIVE, resultName); - - if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) - { - scalarResultIndex = this->findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, resultName); - } - - if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) - { - scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::GENERATED, resultName); - } - - if (scalarResultIndex == cvf::UNDEFINED_SIZE_T) - { - scalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::INPUT_PROPERTY, resultName); - } - - return scalarResultIndex; -} - - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- From 03a9bf459ddac84f6d8b25b64ad66f34d57a9ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 15:32:19 +0200 Subject: [PATCH 298/346] Added riMULTXYZ and X,Y,Z --- .../ModelVisualization/RivFaultPartMgr.cpp | 3 +- .../ProjectDataModel/RimDefines.cpp | 4 + ApplicationCode/ProjectDataModel/RimDefines.h | 5 +- .../RimReservoirCellResultsStorage.cpp | 146 ++++++++++++++++-- .../RimReservoirCellResultsStorage.h | 2 + .../ProjectDataModel/RimReservoirView.cpp | 14 ++ .../RigCaseCellResultsData.cpp | 23 +++ .../RigResultAccessorFactory.cpp | 12 ++ 8 files changed, 193 insertions(+), 16 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 25902b9fa8..3b788d3f72 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -649,7 +649,8 @@ void RivFaultPartMgr::updateNNCColors(RimResultSlot* cellResultSlot) if (cellResultSlot && ( cellResultSlot->resultVariable() == RimDefines::combinedTransmissibilityResultName() - || cellResultSlot->resultVariable() == RimDefines::combinedRiTransResultName())) + || cellResultSlot->resultVariable() == RimDefines::combinedRiTransResultName() + || cellResultSlot->resultVariable() == RimDefines::combinedRiMultResultName()) ) { size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index f312b6aca6..7d60d53620 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -68,6 +68,10 @@ bool RimDefines::isPerCellFaceResult(const QString& resultName) { return true; } + else if (resultName.compare(RimDefines::combinedRiMultResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } return false; } diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 5d97f36820..e485d9ce86 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -50,7 +50,10 @@ class RimDefines static QString riTransXResultName() { return "riTRANSX"; } static QString riTransYResultName() { return "riTRANSY"; } static QString riTransZResultName() { return "riTRANSZ"; } - + static QString riMultXResultName() { return "riMULTX"; } + static QString riMultYResultName() { return "riMULTY"; } + static QString riMultZResultName() { return "riMULTZ"; } + static QString combinedRiMultResultName() { return "riMULTXYZ"; } // Mock model text identifiers static QString mockModelBasic() { return "Result Mock Debug Model Simple"; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 49c3aff8f3..9e8837797a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -278,6 +278,32 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result this->findOrLoadScalarResult(type, "MULTZ"); this->findOrLoadScalarResult(type, "MULTZ-"); } + else if (resultName == RimDefines::combinedRiTransResultName()) + { + computeRiTransComponent(RimDefines::riTransXResultName()); + computeRiTransComponent(RimDefines::riTransYResultName()); + computeRiTransComponent(RimDefines::riTransZResultName()); + computeNncCombRiTrans(); + } + else if (resultName == RimDefines::riTransXResultName() + || resultName == RimDefines::riTransYResultName() + || resultName == RimDefines::riTransZResultName()) + { + computeRiTransComponent(resultName); + } + else if (resultName == RimDefines::combinedRiMultResultName()) + { + computeRiMULTComponent(RimDefines::riMultXResultName()); + computeRiMULTComponent(RimDefines::riMultYResultName()); + computeRiMULTComponent(RimDefines::riMultZResultName()); + computeNncCombRiMULT(); + } + else if (resultName == RimDefines::riMultXResultName() + || resultName == RimDefines::riMultYResultName() + || resultName == RimDefines::riMultZResultName()) + { + computeRiMULTComponent(resultName); + } } @@ -300,20 +326,7 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result return scalarResultIndex; } - if (resultName == RimDefines::combinedRiTransResultName()) - { - computeRiTransComponent(RimDefines::riTransXResultName()); - computeRiTransComponent(RimDefines::riTransYResultName()); - computeRiTransComponent(RimDefines::riTransZResultName()); - computeNncCombRiTrans(); - } - - if ( resultName == RimDefines::riTransXResultName() - || resultName == RimDefines::riTransYResultName() - || resultName == RimDefines::riTransZResultName()) - { - computeRiTransComponent(resultName); - } + if (type == RimDefines::GENERATED) { @@ -1060,6 +1073,111 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() } +double riMult(double transResults, double riTransResults) +{ + // To make 0.0 values give 1.0 in mult value + // We might want a tolerance here. + if (transResults == riTransResults) + { + return 1.0; + } + else + { + return transResults / riTransResults; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeRiMULTComponent(const QString& riMultCompName) +{ + if (!m_cellResults) return; + + // Set up which component to compute + + cvf::StructGridInterface::FaceType faceId; + QString riTransCompName; + QString transCompName; + + if (riMultCompName == RimDefines::riMultXResultName()) + { + riTransCompName = RimDefines::riTransXResultName(); + transCompName = "TRANX"; + } + else if (riMultCompName == RimDefines::riMultYResultName()) + { + riTransCompName = RimDefines::riTransYResultName(); + transCompName = "TRANY"; + } + else if (riMultCompName == RimDefines::riMultZResultName()) + { + riTransCompName = RimDefines::riTransZResultName(); + transCompName = "TRANZ"; + } + else + { + CVF_ASSERT(false); + } + + // Get the needed result indices we depend on + + size_t transResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, transCompName); + size_t riTransResultIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, riTransCompName); + + // Get the result index of the output + + size_t riMultResultIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riMultCompName); + CVF_ASSERT(riMultResultIdx != cvf::UNDEFINED_SIZE_T); + + // Get the result count, to handle that one of them might be globally defined + + CVF_ASSERT(m_cellResults->cellScalarResults(riTransResultIdx)[0].size() == m_cellResults->cellScalarResults(transResultIdx)[0].size()); + + size_t resultValueCount = m_cellResults->cellScalarResults(transResultIdx)[0].size(); + + // Get all the actual result values + + std::vector & riTransResults = m_cellResults->cellScalarResults(riTransResultIdx)[0]; + std::vector & transResults = m_cellResults->cellScalarResults(transResultIdx)[0]; + + std::vector & riMultResults = m_cellResults->cellScalarResults(riMultResultIdx)[0]; + + // Set up output container to correct number of results + + riMultResults.resize(resultValueCount); + + const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); + + for (size_t vIdx = 0; vIdx < transResults.size(); ++vIdx) + { + riMultResults[vIdx] = riMult(transResults[vIdx], riTransResults[vIdx]); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeNncCombRiMULT() +{ + if (!m_cellResults) return; + + size_t riCombMultScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiMultResultName()); + size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName()); + size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); + + if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombMultScalarResultIndex)) return; + + std::vector & riMultResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombMultScalarResultIndex); + const std::vector * riTransResults = m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex); + const std::vector * transResults = m_ownerMainGrid->nncData()->connectionScalarResult(combTransScalarResultIndex); + + for (size_t nncConIdx = 0; nncConIdx < riMultResults.size(); ++nncConIdx) + { + riMultResults[nncConIdx] = riMult((*transResults)[nncConIdx], (*riTransResults)[nncConIdx]); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 50f4603e4c..4da4b63d50 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -67,6 +67,8 @@ class RimReservoirCellResultsStorage : public caf::PdmObject void computeSOILForTimeStep(size_t timeStepIndex); void computeRiTransComponent(const QString& riTransComponentResultName); void computeNncCombRiTrans(); + void computeRiMULTComponent(const QString& riMultCompName); + void computeNncCombRiMULT(); QString getValidCacheFileName(); QString getCacheDirectoryPath(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index b36883f60d..c7977b8227 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -2146,6 +2146,20 @@ void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t resultInfoText->append(QString("riTran Z : %1\n").arg(scalarValue)); } } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiMultResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiMultResultName()); + { + double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riMult X : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riMult Y : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riMult Z : %1\n").arg(scalarValue)); + } + } else { resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->gridScalarIndex()); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index a7df18f536..55bd00a398 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -270,6 +270,14 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName())); statisticsCalculator = calc; } + else if (resultName == RimDefines::combinedRiMultResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riMultXResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riMultYResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riMultZResultName())); + statisticsCalculator = calc; + } else { statisticsCalculator = new RigNativeStatCalc(this, scalarResultIndex); @@ -542,6 +550,21 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName(), false, 0); } } + + // riMULTXYZ and X, Y, Z + { + size_t tranX, tranY, tranZ; + if (findTransmissibilityResults(tranX, tranY, tranZ) + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName()) != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName()) != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName()) != cvf::UNDEFINED_SIZE_T) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riMultXResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riMultYResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riMultZResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiMultResultName(), false, 0); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index 6d5a729236..b9d4e019c3 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -91,6 +91,18 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } + else if (uiResultName == RimDefines::combinedRiMultResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); + + cvf::ref xRiMultAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riMultXResultName()); + cvf::ref yRiMultAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riMultYResultName()); + cvf::ref zRiMultAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riMultZResultName()); + + cellFaceAccessObject->setTransResultAccessors(xRiMultAccessor.p(), yRiMultAccessor.p(), zRiMultAccessor.p()); + + return cellFaceAccessObject; + } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From 0c1588435a8c368e07e86d982b9ebdc4495ad6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 16:50:11 +0200 Subject: [PATCH 299/346] CellEdge: Fixed trouble with mixup of MULT and riMULT --- ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp | 4 ++-- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index 5ef2e8ba73..f3cf44dabc 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -222,7 +222,7 @@ QStringList RimCellEdgeResultSlot::findResultVariableNames() { if (RimDefines::isPerCellFaceResult(varList[i])) continue; - if (varList[i].contains(resultVariable)) + if (varList[i].startsWith(resultVariable)) { varNames.append(varList[i]); } @@ -292,7 +292,7 @@ bool RimCellEdgeResultSlot::hasResult() const //-------------------------------------------------------------------------------------------------- void RimCellEdgeResultSlot::updateIgnoredScalarValue() { - if (resultVariable == "MULT") + if (resultVariable == "MULT" || resultVariable == "riMULT") { m_ignoredResultScalar = 1.0; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 9e8837797a..17e2dabdfa 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -296,6 +296,7 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result computeRiMULTComponent(RimDefines::riMultXResultName()); computeRiMULTComponent(RimDefines::riMultYResultName()); computeRiMULTComponent(RimDefines::riMultZResultName()); + computeNncCombRiTrans(); computeNncCombRiMULT(); } else if (resultName == RimDefines::riMultXResultName() From 781d008f0764a2c14de5d2a81a6be9bd8c0ab9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 26 Aug 2014 17:23:22 +0200 Subject: [PATCH 300/346] Faults: Fixed bug introduced by 76d6304 --- .../FileInterface/RifEclipseInputFileTools.cpp | 14 +++++++++++++- .../FileInterface/RifEclipseInputFileTools.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index ffab327e42..ca44ff9784 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -844,6 +844,18 @@ bool RifEclipseInputFileTools::readFaultsAndParseIncludeStatementsRecursively(QF return true; } +cvf::StructGridInterface::FaceEnum RifEclipseInputFileTools::faceEnumFromText(const QString& faceString) +{ + if (faceString == "X" ) return cvf::StructGridInterface::POS_I; + if (faceString == "X-") return cvf::StructGridInterface::NEG_I; + if (faceString == "Y" ) return cvf::StructGridInterface::POS_J; + if (faceString == "Y-") return cvf::StructGridInterface::NEG_J; + if (faceString == "Z" ) return cvf::StructGridInterface::POS_K; + if (faceString == "Z-") return cvf::StructGridInterface::NEG_K; + + return cvf::StructGridInterface::NO_FACE; +} + //-------------------------------------------------------------------------------------------------- /// The file pointer is pointing at the line following the FAULTS keyword. /// Parse content of this keyword until end of file or @@ -910,7 +922,7 @@ void RifEclipseInputFileTools::readFaults(QFile &data, qint64 filePos, cvf::Coll QString faceString = entries[7]; faceString.remove("'"); - cvf::StructGridInterface::FaceEnum cellFaceEnum = cvf::StructGridInterface::FaceEnum::fromText(faceString); + cvf::StructGridInterface::FaceEnum cellFaceEnum = RifEclipseInputFileTools::faceEnumFromText(faceString); // Adjust from 1-based to 0-based cell indices // Guard against invalid cell ranges by limiting lowest possible range value to zero diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h index 2ee6f34de1..0ca8faea4c 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h @@ -82,4 +82,5 @@ class RifEclipseInputFileTools : public cvf::Object static qint64 findKeyword(const QString& keyword, QFile& file, qint64 startPos); + static cvf::StructGridInterface::FaceEnum faceEnumFromText(const QString& faceString); }; From b90c230d5c68da6eaab98d5ddeffc217058ef141 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 27 Aug 2014 09:21:52 +0200 Subject: [PATCH 301/346] Fault import : Skip reading if same line contains end keyword --- .../FileInterface/RifEclipseInputFileTools.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index ca44ff9784..9f2f373cc9 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -824,9 +824,11 @@ bool RifEclipseInputFileTools::readFaultsAndParseIncludeStatementsRecursively(QF } else if (line.startsWith(faultsKeyword, Qt::CaseInsensitive)) { - readFaults(file, file.pos(), faults, isEditKeywordDetected); - - filenamesWithFaults.push_back(file.fileName()); + if (!line.contains("/")) + { + readFaults(file, file.pos(), faults, isEditKeywordDetected); + filenamesWithFaults.push_back(file.fileName()); + } } if (isEditKeywordDetected && *isEditKeywordDetected) From 27b25443a1893a0970fbc13ea926f39aafe828a0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 27 Aug 2014 09:29:15 +0200 Subject: [PATCH 302/346] Use 1-based indices for text to be displayed to user --- ApplicationCode/ProjectDataModel/RimFaultCollection.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 8fb630c009..263d94cc6e 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -254,7 +254,8 @@ void RimFaultCollection::syncronizeFaults() size_t i2, j2, k2; mainGrid->ijkFromCellIndex(nncConnections[i].m_c2GlobIdx, &i2, &j2, &k2); - QString txt = QString("[%1 %2 %3] - [%4 %5 %6]").arg(i1).arg(j1).arg(k1).arg(i2).arg(j2).arg(k2); + // Convert to 1-based for IJK values to be displayed to the user + QString txt = QString("[%1 %2 %3] - [%4 %5 %6]").arg(i1 + 1).arg(j1 + 1).arg(k1 + 1).arg(i2 + 1).arg(j2 + 1).arg(k2 + 1); noCommonAreaNnc->name = txt; this->noCommonAreaNnncCollection()->noCommonAreaNncs().push_back(noCommonAreaNnc); From e40e3c40f1f1d6763d4a55b7912cfd03233a2a2f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 27 Aug 2014 09:54:12 +0200 Subject: [PATCH 303/346] Bugfix MULTXYZ : Clamp HUGE_VAL to 1.0 --- .../ReservoirDataModel/RigCombMultResultAccessor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp index fc6917ab96..b2598cb4c2 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp @@ -137,6 +137,12 @@ double RigCombMultResultAccessor::nativeMultScalar(size_t gridLocalCellIndex, cv } } + // FaceScalar with value HUGE_VAL means value outside valid IJK-range. Clamp to 1.0 as this means no change in MULT factor. + if (faceScalar == HUGE_VAL) + { + faceScalar = 1.0; + } + return faceScalar; } From d76dd6a588507dc682a72476482741fbe3a9ad2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Wed, 27 Aug 2014 11:41:08 +0200 Subject: [PATCH 304/346] Added riTRANSXYZbyArea (and X, Y, Z ) --- .../ModelVisualization/RivFaultPartMgr.cpp | 4 +- .../ProjectDataModel/RimDefines.cpp | 4 + ApplicationCode/ProjectDataModel/RimDefines.h | 9 +- .../RimReservoirCellResultsStorage.cpp | 155 ++++++++++++++++++ .../RimReservoirCellResultsStorage.h | 2 + .../ProjectDataModel/RimReservoirView.cpp | 14 ++ .../RigCaseCellResultsData.cpp | 32 ++++ .../RigResultAccessorFactory.cpp | 11 ++ 8 files changed, 229 insertions(+), 2 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 3b788d3f72..487953fdba 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -650,7 +650,9 @@ void RivFaultPartMgr::updateNNCColors(RimResultSlot* cellResultSlot) if (cellResultSlot && ( cellResultSlot->resultVariable() == RimDefines::combinedTransmissibilityResultName() || cellResultSlot->resultVariable() == RimDefines::combinedRiTransResultName() - || cellResultSlot->resultVariable() == RimDefines::combinedRiMultResultName()) ) + || cellResultSlot->resultVariable() == RimDefines::combinedRiMultResultName() + || cellResultSlot->resultVariable() == RimDefines::combinedRiAreaNormTransResultName() + )) { size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index 7d60d53620..ff6d54af22 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -72,6 +72,10 @@ bool RimDefines::isPerCellFaceResult(const QString& resultName) { return true; } + else if (resultName.compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) + { + return true; + } return false; } diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index e485d9ce86..32eb08fac7 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -46,15 +46,22 @@ class RimDefines static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } static QString ternarySaturationResultName() { return "TERNARY"; } static QString combinedMultResultName() { return "MULTXYZ"; } - static QString combinedRiTransResultName() { return "riTRANSXYZ"; } + static QString riTransXResultName() { return "riTRANSX"; } static QString riTransYResultName() { return "riTRANSY"; } static QString riTransZResultName() { return "riTRANSZ"; } + static QString combinedRiTransResultName() { return "riTRANSXYZ"; } + static QString riMultXResultName() { return "riMULTX"; } static QString riMultYResultName() { return "riMULTY"; } static QString riMultZResultName() { return "riMULTZ"; } static QString combinedRiMultResultName() { return "riMULTXYZ"; } + static QString riAreaNormTransXResultName() { return "riTRANSXbyArea"; } + static QString riAreaNormTransYResultName() { return "riTRANSYbyArea"; } + static QString riAreaNormTransZResultName() { return "riTRANSZbyArea"; } + static QString combinedRiAreaNormTransResultName() { return "riTRANSXYZbyArea"; } + // Mock model text identifiers static QString mockModelBasic() { return "Result Mock Debug Model Simple"; } static QString mockModelBasicWithResults() { return "Result Mock Debug Model With Results"; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 17e2dabdfa..e3ceead755 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -305,6 +305,19 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result { computeRiMULTComponent(resultName); } + else if (resultName == RimDefines::combinedRiAreaNormTransResultName()) + { + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransXResultName()); + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransYResultName()); + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransZResultName()); + computeNncCombRiTRANSbyArea(); + } + else if (resultName == RimDefines::riAreaNormTransXResultName() + || resultName == RimDefines::riAreaNormTransYResultName() + || resultName == RimDefines::riAreaNormTransZResultName()) + { + computeRiTRANSbyAreaComponent(resultName); + } } @@ -1179,6 +1192,148 @@ void RimReservoirCellResultsStorage::computeNncCombRiMULT() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeRiTRANSbyAreaComponent(const QString& riTransByAreaCompResultName) +{ + if (!m_cellResults) return; + + // Set up which component to compute + + cvf::StructGridInterface::FaceType faceId; + QString transCompName; + + if (riTransByAreaCompResultName == RimDefines::riAreaNormTransXResultName()) + { + transCompName = "TRANX"; + faceId = cvf::StructGridInterface::POS_I; + } + else if (riTransByAreaCompResultName == RimDefines::riAreaNormTransYResultName()) + { + transCompName = "TRANY"; + faceId = cvf::StructGridInterface::POS_J; + } + else if (riTransByAreaCompResultName == RimDefines::riAreaNormTransZResultName()) + { + transCompName = "TRANZ"; + faceId = cvf::StructGridInterface::POS_K; + } + else + { + CVF_ASSERT(false); + } + + // Get the needed result indices we depend on + + size_t tranCompScResIdx = findOrLoadScalarResult(RimDefines::STATIC_NATIVE, transCompName); + + // Get the result index of the output + + size_t riTranByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, riTransByAreaCompResultName); + CVF_ASSERT(riTranByAreaScResIdx != cvf::UNDEFINED_SIZE_T); + + // Get the result count, to handle that one of them might be globally defined + + size_t resultValueCount = m_cellResults->cellScalarResults(tranCompScResIdx)[0].size(); + + // Get all the actual result values + + std::vector & transResults = m_cellResults->cellScalarResults(tranCompScResIdx)[0]; + std::vector & riTransByAreaResults = m_cellResults->cellScalarResults(riTranByAreaScResIdx)[0]; + + // Set up output container to correct number of results + + riTransByAreaResults.resize(resultValueCount); + + // Prepare how to index the result values: + + bool isUsingResIdx = m_cellResults->isUsingGlobalActiveIndex(tranCompScResIdx); + + // Set up result index function pointers + + ResultIndexFunction resValIdxFunc = isUsingResIdx ? &reservoirActiveCellIndex : &directReservoirCellIndex; + + const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); + const std::vector& nodes = m_ownerMainGrid->nodes(); + bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); + + for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->cells().size(); nativeResvCellIndex++) + { + // Do nothing if we are only dealing with active cells, and this cell is not active: + size_t nativeCellResValIdx = (*resValIdxFunc)(activeCellInfo, nativeResvCellIndex); + + if (nativeCellResValIdx == cvf::UNDEFINED_SIZE_T) continue; + + const RigCell& nativeCell = m_ownerMainGrid->cells()[nativeResvCellIndex]; + RigGridBase* grid = nativeCell.hostGrid(); + + size_t gridLocalNativeCellIndex = nativeCell.gridLocalCellIndex(); + + size_t i, j, k, gridLocalNeighborCellIdx; + + grid->ijkFromCellIndex(gridLocalNativeCellIndex, &i, &j, &k); + + if (grid->cellIJKNeighbor(i, j, k, faceId, &gridLocalNeighborCellIdx)) + { + size_t neighborResvCellIdx = grid->reservoirCellIndex(gridLocalNeighborCellIdx); + const RigCell& neighborCell = m_ownerMainGrid->cells()[neighborResvCellIdx]; + + // Connection geometry + + const RigFault* fault = grid->mainGrid()->findFaultFromCellIndexAndCellFace(nativeResvCellIndex, faceId); + bool isOnFault = fault; + + cvf::Vec3d faceAreaVec; + cvf::Vec3d faceCenter; + + if (isOnFault) + { + calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, + &faceCenter, &faceAreaVec); + } + else + { + faceCenter = nativeCell.faceCenter(faceId); + faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); + } + + double areaOfOverlap = faceAreaVec.length(); + double transCompValue = transResults[nativeCellResValIdx]; + + riTransByAreaResults[nativeCellResValIdx] = transCompValue / areaOfOverlap; + } + + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimReservoirCellResultsStorage::computeNncCombRiTRANSbyArea() +{ + if (!m_cellResults) return; + + size_t riCombTransByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTransResultName()); + size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); + + if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransByAreaScResIdx)) return; + + std::vector & riAreaNormTransResults = m_ownerMainGrid->nncData()->makeConnectionScalarResult(riCombTransByAreaScResIdx); + const std::vector * transResults = m_ownerMainGrid->nncData()->connectionScalarResult(combTransScalarResultIndex); + + const std::vector& connections = m_ownerMainGrid->nncData()->connections(); + + for (size_t nncConIdx = 0; nncConIdx < riAreaNormTransResults.size(); ++nncConIdx) + { + const std::vector& realPolygon = connections[nncConIdx].m_polygon; + cvf::Vec3d faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); + double areaOfOverlap = faceAreaVec.length(); + + riAreaNormTransResults[nncConIdx] = (*transResults)[nncConIdx] / areaOfOverlap; + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 4da4b63d50..7570cd0bd6 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -69,6 +69,8 @@ class RimReservoirCellResultsStorage : public caf::PdmObject void computeNncCombRiTrans(); void computeRiMULTComponent(const QString& riMultCompName); void computeNncCombRiMULT(); + void computeRiTRANSbyAreaComponent(const QString& riTransByAreaCompResultName); + void computeNncCombRiTRANSbyArea(); QString getValidCacheFileName(); QString getCacheDirectoryPath(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index c7977b8227..cf8bf0c3f4 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -2160,6 +2160,20 @@ void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t resultInfoText->append(QString("riMult Z : %1\n").arg(scalarValue)); } } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiAreaNormTransResultName()); + { + double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riTransByArea X : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riTransByArea Y : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riTransByArea Z : %1\n").arg(scalarValue)); + } + } else { resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->gridScalarIndex()); diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 55bd00a398..da2a395c32 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -278,6 +278,14 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riMultZResultName())); statisticsCalculator = calc; } + else if (resultName == RimDefines::combinedRiAreaNormTransResultName()) + { + cvf::ref calc = new RigMultipleDatasetStatCalc(); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransXResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransYResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransZResultName())); + statisticsCalculator = calc; + } else { statisticsCalculator = new RigNativeStatCalc(this, scalarResultIndex); @@ -565,6 +573,30 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiMultResultName(), false, 0); } } + + // riTRANSXYZbyArea and X, Y, Z + { + if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANX") != cvf::UNDEFINED_SIZE_T) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransXResultName(), false, 0); + } + + if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANY") != cvf::UNDEFINED_SIZE_T) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransYResultName(), false, 0); + } + + if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANZ") != cvf::UNDEFINED_SIZE_T) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransZResultName(), false, 0); + } + + size_t tranX, tranY, tranZ; + if (findTransmissibilityResults(tranX, tranY, tranZ)) + { + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTransResultName(), false, 0); + } + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index b9d4e019c3..ff4ec35be8 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -103,7 +103,18 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } + else if (uiResultName == RimDefines::combinedRiAreaNormTransResultName()) + { + cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); + + cvf::ref xRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransXResultName()); + cvf::ref yRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransYResultName()); + cvf::ref zRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransZResultName()); + cellFaceAccessObject->setTransResultAccessors(xRiAreaNormTransAccessor.p(), yRiAreaNormTransAccessor.p(), zRiAreaNormTransAccessor.p()); + + return cellFaceAccessObject; + } return RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, uiResultName); } From ffbfb8bdf087902537a56967d3b22aeb2255cc89 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 27 Aug 2014 14:05:29 +0200 Subject: [PATCH 305/346] Read units type from file and set CDARCHY value based on units type --- .../RifEclipseOutputFileTools.cpp | 23 +++++++++ .../FileInterface/RifEclipseOutputFileTools.h | 2 + .../RifEclipseRestartDataAccess.h | 1 + .../RifEclipseRestartFilesetAccess.cpp | 16 ++++++ .../RifEclipseRestartFilesetAccess.h | 1 + .../RifEclipseUnifiedRestartFileAccess.cpp | 10 ++++ .../RifEclipseUnifiedRestartFileAccess.h | 1 + .../FileInterface/RifReaderEclipseOutput.cpp | 33 +++++++++--- .../RimReservoirCellResultsStorage.cpp | 51 ++++++++++++++++--- .../RimReservoirCellResultsStorage.h | 3 ++ .../ReservoirDataModel/RigCaseData.cpp | 2 + .../ReservoirDataModel/RigCaseData.h | 15 +++++- 12 files changed, 141 insertions(+), 17 deletions(-) diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index ee46809f05..347c2bb762 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -329,3 +329,26 @@ void RifEclipseOutputFileTools::readGridDimensions(const QString& gridFileName, stringlist_free( lgr_names ); } + +//-------------------------------------------------------------------------------------------------- +/// Returns the following integer values from the first INTEHEAD keyword found +/// 1 : METRIC +/// 2 : FIELD +/// 3 : LAB +/// -1 : No INTEHEAD keyword found +//-------------------------------------------------------------------------------------------------- +int RifEclipseOutputFileTools::readUnitsType(ecl_file_type* ecl_file) +{ + int unitsType = -1; + + if (ecl_file) + { + ecl_kw_type* kwINTEHEAD = ecl_file_iget_named_kw(ecl_file, INTEHEAD_KW, 0); + if (kwINTEHEAD) + { + unitsType = ecl_kw_iget_int(kwINTEHEAD, INTEHEAD_UNIT_INDEX); + } + } + + return unitsType; +} diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index a46c83e4b9..a91bc1e401 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -56,4 +56,6 @@ class RifEclipseOutputFileTools static QStringList filterFileNamesOfType(const QStringList& fileSet, ecl_file_enum fileType); static void readGridDimensions(const QString& gridFileName, std::vector< std::vector >& gridDimensions); + + static int readUnitsType(ecl_file_type* ecl_file); }; diff --git a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h index 757e324e02..26bac268b1 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h @@ -54,4 +54,5 @@ class RifEclipseRestartDataAccess : public cvf::Object virtual bool results(const QString& resultName, size_t timeStep, size_t gridCount, std::vector* values) = 0; virtual void readWellData(well_info_type * well_info) = 0; + virtual int readUnitsType() = 0; }; diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp index 0c105ad4f5..4898330928 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp @@ -240,3 +240,19 @@ void RifEclipseRestartFilesetAccess::openTimeStep(size_t timeStep) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseRestartFilesetAccess::readUnitsType() +{ + ecl_file_type* ecl_file = NULL; + + if (m_ecl_files.size() > 0) + { + openTimeStep(0); + ecl_file = m_ecl_files[0]; + } + + return RifEclipseOutputFileTools::readUnitsType(ecl_file); +} + diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h index 645f641fc4..70c4679bf0 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h @@ -47,6 +47,7 @@ class RifEclipseRestartFilesetAccess : public RifEclipseRestartDataAccess bool results(const QString& resultName, size_t timeStep, size_t gridCount, std::vector* values); virtual void readWellData(well_info_type* well_info); + virtual int readUnitsType(); private: void openTimeStep(size_t timeStep); diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp index 20c26e7caa..a3c6c165d4 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp @@ -163,3 +163,13 @@ void RifEclipseUnifiedRestartFileAccess::setRestartFiles(const QStringList& file } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RifEclipseUnifiedRestartFileAccess::readUnitsType() +{ + openFile(); + + return RifEclipseOutputFileTools::readUnitsType(m_ecl_file); +} + diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h index 066f685153..4c6265be81 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h @@ -48,6 +48,7 @@ class RifEclipseUnifiedRestartFileAccess : public RifEclipseRestartDataAccess bool results(const QString& resultName, size_t timeStep, size_t gridCount, std::vector* values); virtual void readWellData(well_info_type * well_info); + virtual int readUnitsType(); private: bool openFile(); diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index 3743ef4c4d..c163b71085 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -16,28 +16,29 @@ // ///////////////////////////////////////////////////////////////////////////////// -#include "cvfBase.h" +#include "RifReaderEclipseOutput.h" -#include "RigMainGrid.h" -#include "RigCaseData.h" #include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigMainGrid.h" -#include "RifReaderEclipseOutput.h" +#include "RifEclipseInputFileTools.h" #include "RifEclipseOutputFileTools.h" -#include "RifEclipseUnifiedRestartFileAccess.h" #include "RifEclipseRestartFilesetAccess.h" +#include "RifEclipseUnifiedRestartFileAccess.h" #include "RifReaderInterface.h" -#include +#include "cafProgressInfo.h" #include "ecl_grid.h" #include "well_state.h" #include "ecl_kw_magic.h" #include "ecl_nnc_export.h" -#include "cafProgressInfo.h" +#include #include -#include "RifEclipseInputFileTools.h" +#include // Needed for HUGE_VAL on Linux + //-------------------------------------------------------------------------------------------------- /// ECLIPSE cell numbering layout: @@ -676,6 +677,22 @@ void RifReaderEclipseOutput::buildMetaData() fractureModelResults->setTimeStepDates(resIndex, m_timeSteps); } } + + // Default units type is METRIC + RigCaseData::UnitsType unitsType = RigCaseData::UNITS_METRIC; + { + int unitsTypeValue = m_dynamicResultsAccess->readUnitsType(); + if (unitsTypeValue == 2) + { + unitsType = RigCaseData::UNITS_FIELD; + } + else if (unitsTypeValue == 3) + { + unitsType = RigCaseData::UNITS_LAB; + } + } + + m_eclipseCase->setUnitsType(unitsType); } progInfo.incrementProgress(); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index e3ceead755..d71ba04e49 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -18,20 +18,24 @@ #include "RimReservoirCellResultsStorage.h" -#include "RigCaseCellResultsData.h" #include "RigActiveCellInfo.h" -#include "RigMainGrid.h" +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" #include "RigCell.h" +#include "RigMainGrid.h" + +#include "RimCase.h" #include "RimTools.h" #include "cafProgressInfo.h" +#include "cvfGeometryTools.h" + #include #include #include #include #include -#include "cvfGeometryTools.h" CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorage, "ReservoirCellResultStorage"); @@ -789,8 +793,7 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr CVF_ASSERT(false); } - // Todo: Get the correct one from Unit set read by ERT - double cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) + double cdarchy = darchysValue(); // Get the needed result indices we depend on @@ -935,8 +938,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex)) return; - // Todo: Get the correct one from Unit set read by ERT - double cdarchy = 0.008527; // (ECLIPSE 100) (METRIC) + double cdarchy = darchysValue(); // Get the needed result indices we depend on @@ -1110,7 +1112,6 @@ void RimReservoirCellResultsStorage::computeRiMULTComponent(const QString& riMul // Set up which component to compute - cvf::StructGridInterface::FaceType faceId; QString riTransCompName; QString transCompName; @@ -1459,6 +1460,40 @@ bool RimReservoirCellResultsStorage::isDataPresent(size_t scalarResultIndex) con return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimReservoirCellResultsStorage::darchysValue() +{ + // See "Cartesian transmissibility calculations" in the "Eclipse Technical Description" + // CDARCY Darcys constant + // = 0.00852702 (E300); 0.008527 (ECLIPSE 100) (METRIC) + // = 0.00112712 (E300); 0.001127 (ECLIPSE 100) (FIELD) + // = 3.6 (LAB) + // = 0.00864 (PVT - M) + + double darchy = 0.008527; // (ECLIPSE 100) (METRIC) + + RimCase* rimCase = NULL; + this->firstAncestorOfType(rimCase); + + if (rimCase && rimCase->reservoirData()) + { + RigCaseData::UnitsType unitsType = rimCase->reservoirData()->unitsType(); + + if (unitsType == RigCaseData::UNITS_FIELD) + { + darchy = 0.001127; + } + else if (unitsType == RigCaseData::UNITS_LAB) + { + darchy = 3.6; + } + } + + return darchy; +} + CAF_PDM_SOURCE_INIT(RimReservoirCellResultsStorageEntryInfo, "ResultStorageEntryInfo"); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 7570cd0bd6..3a70ea8429 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -67,11 +67,14 @@ class RimReservoirCellResultsStorage : public caf::PdmObject void computeSOILForTimeStep(size_t timeStepIndex); void computeRiTransComponent(const QString& riTransComponentResultName); void computeNncCombRiTrans(); + void computeRiMULTComponent(const QString& riMultCompName); void computeNncCombRiMULT(); void computeRiTRANSbyAreaComponent(const QString& riTransByAreaCompResultName); void computeNncCombRiTRANSbyArea(); + double darchysValue(); + QString getValidCacheFileName(); QString getCacheDirectoryPath(); // Fields diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 3dd84a69b8..7b42593b43 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -36,6 +36,8 @@ RigCaseData::RigCaseData() m_matrixModelResults->setActiveCellInfo(m_activeCellInfo.p()); m_fractureModelResults->setActiveCellInfo(m_fractureActiveCellInfo.p()); + + m_unitsType = UNITS_METRIC; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index d69ab9f1cd..decf4ca66b 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -30,8 +30,16 @@ class RigCaseCellResultsData; -class RigCaseData: public cvf::Object +class RigCaseData : public cvf::Object { +public: + enum UnitsType + { + UNITS_METRIC, + UNITS_FIELD, + UNITS_LAB + }; + public: RigCaseData(); ~RigCaseData(); @@ -64,6 +72,9 @@ class RigCaseData: public cvf::Object void computeActiveCellBoundingBoxes(); + UnitsType unitsType() const { return m_unitsType; } + void setUnitsType(UnitsType unitsType) { m_unitsType = unitsType; } + private: void computeActiveCellIJKBBox(); void computeWellCellsPrGrid(); @@ -80,4 +91,6 @@ class RigCaseData: public cvf::Object cvf::Collection m_wellResults; //< A WellResults object for each well in the reservoir cvf::Collection m_wellCellsInGrid; //< A bool array pr grid with one bool pr cell telling wether the cell is a well cell or not cvf::Collection m_gridCellToWellIndex; //< Array pr grid with index to well pr cell telling which well a cell is in + + UnitsType m_unitsType; }; From 103a9f4018a1481df1942932e5a92d195648dbc0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 28 Aug 2014 09:54:34 +0200 Subject: [PATCH 306/346] Bugfix : Allocate max timestep count when receiving data from Octave --- .../RiaPropertyDataCommands.cpp | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index 7a7e83bf8e..a7ff9299ff 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -416,6 +416,9 @@ class RiaSetActiveCellProperty: public RiaSocketCommand if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) { scalarResultFrames = &(rimCase->results(m_porosityModelEnum)->cellResults()->cellScalarResults(scalarResultIndex)); + size_t timeStepCount = rimCase->results(m_porosityModelEnum)->cellResults()->maxTimeStepCount(); + scalarResultFrames->resize(timeStepCount); + m_currentScalarIndex = scalarResultIndex; m_currentPropertyName = propertyName; } @@ -484,17 +487,6 @@ class RiaSetActiveCellProperty: public RiaSocketCommand return true; } - // Resize the result container to be able to receive timesteps at the specified timestep idices - - std::vector::iterator maxTimeStepIt = std::max_element(m_requestedTimesteps.begin(), m_requestedTimesteps.end()); - CVF_ASSERT(maxTimeStepIt != m_requestedTimesteps.end()); - - size_t maxTimeStepIdx = (*maxTimeStepIt); - if (scalarResultFrames->size() <= maxTimeStepIdx) - { - scalarResultFrames->resize(maxTimeStepIdx+1); - } - m_currentReservoir = rimCase; m_scalarResultsToAdd = scalarResultFrames; @@ -778,6 +770,9 @@ class RiaSetGridProperty : public RiaSocketCommand if (scalarResultIndex != cvf::UNDEFINED_SIZE_T) { scalarResultFrames = &(rimCase->results(m_porosityModelEnum)->cellResults()->cellScalarResults(scalarResultIndex)); + size_t timeStepCount = rimCase->results(m_porosityModelEnum)->cellResults()->maxTimeStepCount(); + scalarResultFrames->resize(timeStepCount); + m_currentScalarIndex = scalarResultIndex; m_currentPropertyName = propertyName; } @@ -834,17 +829,6 @@ class RiaSetGridProperty : public RiaSocketCommand return true; } - // Resize the result container to be able to receive time steps at the specified time step indices - - std::vector::iterator maxTimeStepIt = std::max_element(m_requestedTimesteps.begin(), m_requestedTimesteps.end()); - CVF_ASSERT(maxTimeStepIt != m_requestedTimesteps.end()); - - size_t maxTimeStepIdx = (*maxTimeStepIt); - if (scalarResultFrames->size() <= maxTimeStepIdx) - { - scalarResultFrames->resize(maxTimeStepIdx+1); - } - m_currentReservoir = rimCase; m_scalarResultsToAdd = scalarResultFrames; From b7bc732b32fcc1bc58d47dbed4fa2074f4b651f0 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 28 Aug 2014 10:35:05 +0200 Subject: [PATCH 307/346] Bugfix : Do not compute SOIL if present on disk --- .../RimReservoirCellResultsStorage.cpp | 40 ++++++++++++------- .../RigCaseCellResultsData.cpp | 15 ++++--- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index d71ba04e49..ae96319e30 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -332,19 +332,25 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result if (resultName == "SOIL") { - // Trigger loading of SWAT, SGAS to establish time step count if no data has been loaded from file at this point - findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); - findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); - - for (size_t timeStepIdx = 0; timeStepIdx < m_cellResults->maxTimeStepCount(); timeStepIdx++) + if (m_cellResults->mustBeCalculated(scalarResultIndex)) { - computeSOILForTimeStep(timeStepIdx); - } + // Trigger loading of SWAT, SGAS to establish time step count if no data has been loaded from file at this point + findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SWAT"); + findOrLoadScalarResult(RimDefines::DYNAMIC_NATIVE, "SGAS"); - return scalarResultIndex; - } + m_cellResults->cellScalarResults(scalarResultIndex).resize(m_cellResults->maxTimeStepCount()); + for (size_t timeStepIdx = 0; timeStepIdx < m_cellResults->maxTimeStepCount(); timeStepIdx++) + { + std::vector& values = m_cellResults->cellScalarResults(scalarResultIndex)[timeStepIdx]; + if (values.size() == 0) + { + computeSOILForTimeStep(timeStepIdx); + } + } - + return scalarResultIndex; + } + } if (type == RimDefines::GENERATED) { @@ -405,11 +411,17 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResultForTimeStep(RimDefi if (type == RimDefines::DYNAMIC_NATIVE && resultName.toUpper() == "SOIL") { size_t soilScalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); + + if (m_cellResults->mustBeCalculated(soilScalarResultIndex)) { - computeSOILForTimeStep(timeStepIndex); - } + std::vector& values = m_cellResults->cellScalarResults(soilScalarResultIndex)[timeStepIndex]; + if (values.size() == 0) + { + computeSOILForTimeStep(timeStepIndex); + } - return soilScalarResultIndex; + return soilScalarResultIndex; + } } size_t scalarResultIndex = m_cellResults->findScalarResultIndex(type, resultName); @@ -552,7 +564,7 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex soilValue -= swatForTimeStep->at(idx); } - soilForTimeStep[idx] = soilValue; + soilForTimeStep[idx] = cvf::Math::clamp(soilValue, 0.0, 1.0); } } diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index da2a395c32..32defa4943 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -522,12 +522,17 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() { // SOIL { - size_t swatIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SWAT"); - size_t sgasIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SGAS"); - - if (swatIndex != cvf::UNDEFINED_SIZE_T || sgasIndex != cvf::UNDEFINED_SIZE_T) + size_t soilIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SOIL"); + if (soilIndex == cvf::UNDEFINED_SIZE_T) { - addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); + size_t swatIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SWAT"); + size_t sgasIndex = findScalarResultIndex(RimDefines::DYNAMIC_NATIVE, "SGAS"); + + if (swatIndex != cvf::UNDEFINED_SIZE_T || sgasIndex != cvf::UNDEFINED_SIZE_T) + { + soilIndex = addEmptyScalarResult(RimDefines::DYNAMIC_NATIVE, "SOIL", false); + this->setMustBeCalculated(soilIndex); + } } } From 5377742bbc75cb9d77cadf89348ce53c471d123d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 28 Aug 2014 09:17:45 +0200 Subject: [PATCH 308/346] riTRANSXYZ: Fixed negative values due to bug in polygon calculations --- ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl index f698490c3d..6ead7b8f9d 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl @@ -299,7 +299,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads(std::vector * p { int k; - for (k = 0; k < 4; ++k) + for (k = 3; k >= 0; --k) // Return opposite winding, to match winding of face 1 { polygon->push_back(cv2CubeFaceIndices[k]); } From edd7a671d9dea0ac2643010c2db4c5fa99b4c555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 28 Aug 2014 11:24:41 +0200 Subject: [PATCH 309/346] riMULTXYZ: Added tolerances for CellEdge and Calculations --- .../RivCellEdgeGeometryUtils.cpp | 8 ++++++-- .../ModelVisualization/RivCellEdgeGeometryUtils.h | 2 ++ .../RimReservoirCellResultsStorage.cpp | 15 ++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp index 14b3d9f3a7..a9c8e58444 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp @@ -150,7 +150,7 @@ void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + if (!hideScalarValue(scalarValue, ignoredScalarValue, 1e-2)) { edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; } @@ -178,6 +178,10 @@ void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( geo->setVertexAttribute(new cvf::FloatVertexAttribute("a_colorNegK", cellEdgeColorTextureCoordsArrays.at(5))); } +bool RivCellEdgeGeometryUtils::hideScalarValue(double scalarValue, double scalarValueToHide, double tolerance) +{ + return (scalarValue == HUGE_VAL || abs(scalarValue - scalarValueToHide) <= scalarValueToHide*tolerance); +} //-------------------------------------------------------------------------------------------------- /// @@ -247,7 +251,7 @@ void RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo(size_t tim double scalarValue = cellEdgeResultAccessor->cellFaceScalar(cellIndex, static_cast(cubeFaceIdx)); - if (scalarValue != HUGE_VAL && scalarValue != ignoredScalarValue) + if (!hideScalarValue(scalarValue, ignoredScalarValue, 1e-2)) { edgeColor = edgeResultScalarMapper->mapToTextureCoord(scalarValue)[0]; } diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h index fdc96745a6..80465bd6ab 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h @@ -67,4 +67,6 @@ class RivCellEdgeGeometryUtils size_t timeStepIndex, RigCaseData* eclipseCase, const RigGridBase* grid); + + static bool hideScalarValue(double scalarValue, double scalarValueToHide, double tolerance); }; diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index ae96319e30..2a349a63cb 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -1104,15 +1104,16 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() double riMult(double transResults, double riTransResults) { // To make 0.0 values give 1.0 in mult value - // We might want a tolerance here. - if (transResults == riTransResults) - { - return 1.0; - } - else + + if (riTransResults == 0.0) { - return transResults / riTransResults; + if (abs (transResults) < 1e-12) + { + return 1.0; + } } + + return transResults / riTransResults; } //-------------------------------------------------------------------------------------------------- From b61d58211210ccc49c103d643e7c5edce3211080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 28 Aug 2014 11:35:32 +0200 Subject: [PATCH 310/346] Completed the CDARCHY constant table --- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 2a349a63cb..aefe900f98 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -1498,10 +1498,19 @@ double RimReservoirCellResultsStorage::darchysValue() { darchy = 0.001127; } + else if (unitsType == RigCaseData::UNITS_METRIC) + { + darchy = 0.008527; + } else if (unitsType == RigCaseData::UNITS_LAB) { darchy = 3.6; } + else + { + darchy = 0.00864; // Assuming (PVT - M) + CVF_TIGHT_ASSERT(false); // The enum and doc does not state that the PVT-M actually exists, so to trap this in debug + } } return darchy; From 01cfed9ab750bf4caa87461bd8dda9596b7df579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Thu, 28 Aug 2014 13:37:56 +0200 Subject: [PATCH 311/346] Fixed crash after copy/paste of view and case --- .../ProjectDataModel/RimUiTreeModelPdm.cpp | 33 +++++++++++++++---- .../ProjectDataModel/RimUiTreeModelPdm.h | 2 +- .../cafProjectDataModel/cafPdmDocument.h | 3 +- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index 14f14e9ed1..b50569e979 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -610,7 +610,7 @@ RimIdenticalGridCaseGroup* RimUiTreeModelPdm::addCaseGroup(QModelIndex& inserted //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectGroup& pdmObjects) +void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, const caf::PdmObjectGroup& pdmObjects) { RimProject* proj = RiaApplication::instance()->project(); CVF_ASSERT(proj); @@ -638,6 +638,8 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG mainResultCase->readGridDimensions(mainCaseGridDimensions); } + std::vector insertedCases; + // Add cases to case group for (size_t i = 0; i < typedObjects.size(); i++) { @@ -650,6 +652,22 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG continue; } + insertedCases.push_back(rimResultReservoir); + } + + // Initialize the new objects + for (size_t i = 0; i < insertedCases.size(); i++) + { + RimResultCase* rimResultReservoir = insertedCases[i]; + caf::PdmDocument::initAfterReadTraversal(rimResultReservoir); + } + + // Load stuff + for (size_t i = 0; i < insertedCases.size(); i++) + { + RimResultCase* rimResultReservoir = insertedCases[i]; + + if (!mainResultCase) { rimResultReservoir->openEclipseGridFile(); @@ -690,9 +708,9 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG endInsertRows(); } - for (size_t i = 0; i < rimResultReservoir->reservoirViews.size(); i++) + for (size_t rvIdx = 0; rvIdx < rimResultReservoir->reservoirViews.size(); rvIdx++) { - RimReservoirView* riv = rimResultReservoir->reservoirViews()[i]; + RimReservoirView* riv = rimResultReservoir->reservoirViews()[rvIdx]; riv->loadDataAndUpdate(); } } @@ -717,16 +735,17 @@ void RimUiTreeModelPdm::addObjects(const QModelIndex& itemIndex, caf::PdmObjectG RimReservoirView* rimReservoirView = typedObjects[i]; QString nameOfCopy = QString("Copy of ") + rimReservoirView->name; rimReservoirView->name = nameOfCopy; - - rimReservoirView->setEclipseCase(rimCase); - + rimCase->reservoirViews().push_back(rimReservoirView); + // Delete all wells to be able to copy/paste between cases, as the wells differ between cases rimReservoirView->wellCollection()->wells().deleteAllChildObjects(); + caf::PdmDocument::initAfterReadTraversal(rimReservoirView); + rimReservoirView->setEclipseCase(rimCase); + caf::PdmDocument::updateUiIconStateRecursively(rimReservoirView); rimReservoirView->loadDataAndUpdate(); - rimCase->reservoirViews().push_back(rimReservoirView); int position = static_cast(rimCase->reservoirViews().size()); beginInsertRows(collectionIndex, position, position); diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h index d3337d18fc..79d81d2009 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h @@ -65,7 +65,7 @@ class RimUiTreeModelPdm : public caf::UiTreeModelPdm void addToParentAndBuildUiItems(caf::PdmUiTreeItem* parentTreeItem, int position, caf::PdmObject* pdmObject); void populateObjectGroupFromModelIndexList(const QModelIndexList& modelIndexList, caf::PdmObjectGroup* objectGroup); - void addObjects(const QModelIndex& itemIndex, caf::PdmObjectGroup& pdmObjects); + void addObjects(const QModelIndex& itemIndex, const caf::PdmObjectGroup& pdmObjects); void moveObjects(const QModelIndex& itemIndex, caf::PdmObjectGroup& pdmObjects); RimStatisticsCase* addStatisticalCalculation(const QModelIndex& itemIndex, QModelIndex& insertedModelIndex); diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h index c1a519ef90..1b9a200c0a 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmDocument.h @@ -127,10 +127,11 @@ class PdmDocument: public PdmObjectGroup void writeFile(QIODevice* device); static void updateUiIconStateRecursively(PdmObject * root); + static void initAfterReadTraversal(PdmObject * root); private: static void setupBeforeSaveTraversal(PdmObject * root); - static void initAfterReadTraversal(PdmObject * root); + }; From 68831f6e99902745fe61b582dedf6b3a6af451a2 Mon Sep 17 00:00:00 2001 From: magnesj Date: Sun, 31 Aug 2014 14:37:25 +0200 Subject: [PATCH 312/346] Fixed missing celledge visualization: abs/fabs usage error. Not detected on Windows --- .../ModelVisualization/RivCellEdgeGeometryUtils.cpp | 2 +- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp index a9c8e58444..57da9befa5 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp @@ -180,7 +180,7 @@ void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( bool RivCellEdgeGeometryUtils::hideScalarValue(double scalarValue, double scalarValueToHide, double tolerance) { - return (scalarValue == HUGE_VAL || abs(scalarValue - scalarValueToHide) <= scalarValueToHide*tolerance); + return (scalarValue == HUGE_VAL || cvf::Math::abs(scalarValue - scalarValueToHide) <= scalarValueToHide*tolerance); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index aefe900f98..54f722fa07 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -1107,7 +1107,7 @@ double riMult(double transResults, double riTransResults) if (riTransResults == 0.0) { - if (abs (transResults) < 1e-12) + if (cvf::Math::abs (transResults) < 1e-12) { return 1.0; } @@ -1540,4 +1540,4 @@ RimReservoirCellResultsStorageEntryInfo::RimReservoirCellResultsStorageEntryInfo RimReservoirCellResultsStorageEntryInfo::~RimReservoirCellResultsStorageEntryInfo() { -} \ No newline at end of file +} From 6857bd3122d3fb10791f724a0285b5bf4c1730d9 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 3 Sep 2014 07:08:44 +0200 Subject: [PATCH 313/346] Updated link to help web pages --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index e6cab5e794..6f530d33e7 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -1979,7 +1979,7 @@ void RiuMainWindow::slotAddWellCellsToRangeFilterAction(bool doAdd) //-------------------------------------------------------------------------------------------------- void RiuMainWindow::slotOpenUsersGuideInBrowserAction() { - QString usersGuideUrl = "https://github.com/OPM/ResInsight/wiki"; + QString usersGuideUrl = "http://resinsight.org/"; if (!QDesktopServices::openUrl(usersGuideUrl)) { From 7daf170f995036421c23b2fb509f0c4379b72010 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 3 Sep 2014 07:35:23 +0200 Subject: [PATCH 314/346] Fixed crash when activating riMULT --- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 54f722fa07..146cfabd91 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -1026,6 +1026,8 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() break; } + if (!permIdxFunc) continue; + // Do nothing if we are only dealing with active cells, and this cell is not active: size_t nativeCellPermResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); if (nativeCellPermResIdx == cvf::UNDEFINED_SIZE_T) continue; From ca2558bf208cc9036adb8f577956a6c555d7e83f Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 08:35:59 +0200 Subject: [PATCH 315/346] Bugfix: Update NNC colors when Cell Edge is active --- ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 487953fdba..7e80037e67 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -182,6 +182,8 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* //-------------------------------------------------------------------------------------------------- void RivFaultPartMgr::updateCellEdgeResultColor(size_t timeStepIndex, RimResultSlot* cellResultSlot, RimCellEdgeResultSlot* cellEdgeResultSlot) { + updateNNCColors(cellResultSlot); + if (m_nativeFaultFaces.notNull()) { cvf::DrawableGeo* dg = dynamic_cast(m_nativeFaultFaces->drawable()); From 9873f3cfc65722e7a8683d209081c99250ddcb53 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 08:39:44 +0200 Subject: [PATCH 316/346] Do not show fault result legend when fault result is disabled --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index cf8bf0c3f4..40723dfa28 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1320,7 +1320,7 @@ void RimReservoirView::updateLegends() CVF_ASSERT(results); updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); - if (this->faultResultSettings()->hasValidCustomResult()) + if (this->faultResultSettings()->showCustomFaultResult() && this->faultResultSettings()->hasValidCustomResult()) { updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); } From 323f8d77eb9454db5b9201b519001432424da335 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 09:14:01 +0200 Subject: [PATCH 317/346] Rename --- .../ModelVisualization/RivFaultPartMgr.cpp | 4 ++-- .../ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 4 ++-- .../ProjectDataModel/RimReservoirView.cpp | 14 +++++++------- .../ProjectDataModel/RimResultDefinition.cpp | 6 +++--- .../ProjectDataModel/RimResultDefinition.h | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 7e80037e67..0a3c973992 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -99,7 +99,7 @@ void RivFaultPartMgr::updateCellResultColor(size_t timeStepIndex, RimResultSlot* updateNNCColors(cellResultSlot); - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); + size_t scalarSetIndex = cellResultSlot->scalarResultIndex(); // If the result is static, only read that. size_t resTimeStepIdx = timeStepIndex; @@ -656,7 +656,7 @@ void RivFaultPartMgr::updateNNCColors(RimResultSlot* cellResultSlot) || cellResultSlot->resultVariable() == RimDefines::combinedRiAreaNormTransResultName() )) { - size_t scalarSetIndex = cellResultSlot->gridScalarIndex(); + size_t scalarSetIndex = cellResultSlot->scalarResultIndex(); const cvf::ScalarMapper* mapper = cellResultSlot->legendConfig()->scalarMapper(); diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 40a464e9f8..501fc2d9e2 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -150,7 +150,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() double min, max; double p10, p90; double mean; - size_t scalarIndex = m_reservoirView->cellResult()->gridScalarIndex(); + size_t scalarIndex = m_reservoirView->cellResult()->scalarResultIndex(); m_reservoirView->currentGridCellResults()->cellResults()->minMaxCellScalarValues(scalarIndex, min, max); m_reservoirView->currentGridCellResults()->cellResults()->p10p90CellScalarValues(scalarIndex, p10, p90); m_reservoirView->currentGridCellResults()->cellResults()->meanCellScalarValues(scalarIndex, mean); @@ -224,7 +224,7 @@ void Rim3dOverlayInfoConfig::update3DInfo() double p10, p90; double mean; - size_t scalarIndex = m_reservoirView->cellResult()->gridScalarIndex(); + size_t scalarIndex = m_reservoirView->cellResult()->scalarResultIndex(); m_reservoirView->currentGridCellResults()->cellResults()->minMaxCellScalarValues(scalarIndex, min, max); m_reservoirView->currentGridCellResults()->cellResults()->p10p90CellScalarValues(scalarIndex, p10, p90); m_reservoirView->currentGridCellResults()->cellResults()->meanCellScalarValues(scalarIndex, mean); diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 40723dfa28..7c1accee08 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1354,15 +1354,15 @@ void RimReservoirView::updateMinMaxValuesAndAddLegendToView(QString legendLabel, { double globalMin, globalMax; double globalPosClosestToZero, globalNegClosestToZero; - cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), globalMin, globalMax); - cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), globalPosClosestToZero, globalNegClosestToZero); + cellResultsData->minMaxCellScalarValues(resultSlot->scalarResultIndex(), globalMin, globalMax); + cellResultsData->posNegClosestToZero(resultSlot->scalarResultIndex(), globalPosClosestToZero, globalNegClosestToZero); double localMin, localMax; double localPosClosestToZero, localNegClosestToZero; if (resultSlot->hasDynamicResult()) { - cellResultsData->minMaxCellScalarValues(resultSlot->gridScalarIndex(), m_currentTimeStep, localMin, localMax); - cellResultsData->posNegClosestToZero(resultSlot->gridScalarIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); + cellResultsData->minMaxCellScalarValues(resultSlot->scalarResultIndex(), m_currentTimeStep, localMin, localMax); + cellResultsData->posNegClosestToZero(resultSlot->scalarResultIndex(), m_currentTimeStep, localPosClosestToZero, localNegClosestToZero); } else { @@ -1820,7 +1820,7 @@ void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) cvf::StructGridInterface::FaceEnum face(conn.m_c1Face); // Print result value for the NNC - size_t scalarResultIdx = this->cellResult()->gridScalarIndex(); + size_t scalarResultIdx = this->cellResult()->scalarResultIndex(); const std::vector* nncValues = nncData->connectionScalarResult(scalarResultIdx); if (nncValues) { @@ -2176,12 +2176,12 @@ void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t } else { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->gridScalarIndex()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->scalarResultIndex()); } } else { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultSlot->gridScalarIndex()); + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultSlot->scalarResultIndex()); } if (resultAccessor.notNull()) diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 5c8507d041..1a5a3bb12b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -178,7 +178,7 @@ QList RimResultDefinition::calculateValueOptions(const c //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -size_t RimResultDefinition::gridScalarIndex() const +size_t RimResultDefinition::scalarResultIndex() const { size_t gridScalarResultIndex = cvf::UNDEFINED_SIZE_T; @@ -210,7 +210,7 @@ void RimResultDefinition::loadResult() bool RimResultDefinition::hasStaticResult() const { const RimReservoirCellResultsStorage* gridCellResults = this->currentGridCellResults(); - size_t gridScalarResultIndex = this->gridScalarIndex(); + size_t gridScalarResultIndex = this->scalarResultIndex(); if (hasResult() && gridCellResults->cellResults()->timeStepCount(gridScalarResultIndex) == 1 ) { @@ -253,7 +253,7 @@ bool RimResultDefinition::hasDynamicResult() const if (this->currentGridCellResults() && this->currentGridCellResults()->cellResults()) { const RigCaseCellResultsData* gridCellResults = this->currentGridCellResults()->cellResults(); - size_t gridScalarResultIndex = this->gridScalarIndex(); + size_t gridScalarResultIndex = this->scalarResultIndex(); if (gridCellResults->timeStepCount(gridScalarResultIndex) > 1 ) { return true; diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index 462709a898..7af2322a17 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -51,7 +51,7 @@ class RimResultDefinition : public caf::PdmObject virtual void setResultVariable(const QString& val); void loadResult(); - size_t gridScalarIndex() const; + size_t scalarResultIndex() const; bool hasStaticResult() const; bool hasDynamicResult() const; bool hasResult() const; From 4fdb06e0e09cc822f5756e78afff7dc626bce951 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 09:28:39 +0200 Subject: [PATCH 318/346] Moved code from header to source --- .../ReservoirDataModel/RigNNCData.cpp | 46 +++++++++++++++++++ .../ReservoirDataModel/RigNNCData.h | 28 ++--------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index b45f81b289..6152d71b73 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -160,6 +160,52 @@ void RigNNCData::processConnections(const RigMainGrid& mainGrid) } } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector& RigNNCData::makeConnectionScalarResult(size_t scalarResultIndex) +{ + std::vector& results = m_connectionResults[scalarResultIndex]; + results.resize(m_connections.size(), HUGE_VAL); + return results; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector* RigNNCData::connectionScalarResult(size_t scalarResultIndex) const +{ + std::map >::const_iterator it = m_connectionResults.find(scalarResultIndex); + if (it != m_connectionResults.end()) + return &(it->second); + else + return NULL; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigNNCData::setCombTransmisibilityScalarResultIndex(size_t scalarResultIndex) +{ + std::map >::iterator it = m_connectionResults.find(cvf::UNDEFINED_SIZE_T); + CVF_ASSERT(it != m_connectionResults.end()); + + std::vector& emptyData = m_connectionResults[scalarResultIndex]; + std::vector& realData = m_connectionResults[cvf::UNDEFINED_SIZE_T]; + emptyData.swap(realData); + m_connectionResults.erase(cvf::UNDEFINED_SIZE_T); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigNNCData::hasScalarValues(size_t scalarResultIndex) +{ + std::map >::iterator it = m_connectionResults.find(scalarResultIndex); + return (it != m_connectionResults.end()); +} + /* //-------------------------------------------------------------------------------------------------- /// TODO: Possibly not needed ! diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index 2b2eec9332..9954c6dc5e 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -65,32 +65,12 @@ class RigNNCData : public cvf::Object std::vector& connections() { return m_connections; } const std::vector& connections() const { return m_connections; }; - std::vector& makeConnectionScalarResult(size_t scalarResultIndex) - { - std::vector& results = m_connectionResults[scalarResultIndex]; - results.resize(m_connections.size(), HUGE_VAL); - return results; - } - - const std::vector* connectionScalarResult(size_t scalarResultIndex) const - { - std::map >::const_iterator it = m_connectionResults.find(scalarResultIndex); - if (it != m_connectionResults.end()) - return &(it->second); - else - return NULL; - } + std::vector& makeConnectionScalarResult(size_t scalarResultIndex); + const std::vector* connectionScalarResult(size_t scalarResultIndex) const; - void setCombTransmisibilityScalarResultIndex(size_t scalarResultIndex) - { - std::map >::iterator it = m_connectionResults.find(cvf::UNDEFINED_SIZE_T); - CVF_ASSERT(it != m_connectionResults.end()); + void setCombTransmisibilityScalarResultIndex(size_t scalarResultIndex); - std::vector& emptyData = m_connectionResults[scalarResultIndex]; - std::vector& realData = m_connectionResults[cvf::UNDEFINED_SIZE_T]; - emptyData.swap(realData); - m_connectionResults.erase(cvf::UNDEFINED_SIZE_T); - } + bool hasScalarValues(size_t scalarResultIndex); private: // This section is possibly not needed //const std::vector& findConnectionIndices(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; From 5963d750851105f4042bed824926800eb75174c5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 09:30:00 +0200 Subject: [PATCH 319/346] Added checkbox for hiding NNC geometry when no NNC data is available --- .../ModelVisualization/RivFaultPartMgr.cpp | 19 ++++++++----- .../RivReservoirFaultsPartMgr.cpp | 13 ++++++++- .../RivReservoirViewPartMgr.cpp | 2 +- .../RimCellPropertyFilter.cpp | 2 +- .../ProjectDataModel/RimFaultResultSlot.cpp | 27 ++++++++++++++++++- .../ProjectDataModel/RimFaultResultSlot.h | 2 ++ 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index 0a3c973992..f9d820ae75 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -649,12 +649,19 @@ void RivFaultPartMgr::updateNNCColors(RimResultSlot* cellResultSlot) { if (m_NNCFaces.isNull()) return; - if (cellResultSlot - && ( cellResultSlot->resultVariable() == RimDefines::combinedTransmissibilityResultName() - || cellResultSlot->resultVariable() == RimDefines::combinedRiTransResultName() - || cellResultSlot->resultVariable() == RimDefines::combinedRiMultResultName() - || cellResultSlot->resultVariable() == RimDefines::combinedRiAreaNormTransResultName() - )) + bool showNncsWithScalarMappedColor = false; + + if (cellResultSlot) + { + size_t scalarSetIndex = cellResultSlot->scalarResultIndex(); + + if (m_grid->mainGrid()->nncData()->hasScalarValues(scalarSetIndex)) + { + showNncsWithScalarMappedColor = true; + } + } + + if (showNncsWithScalarMappedColor) { size_t scalarSetIndex = cellResultSlot->scalarResultIndex(); diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 88e955d882..046527b5e4 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -93,6 +93,8 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); if (!faultCollection) return; + RimFaultResultSlot* faultResultSlot = m_reservoirView->faultResultSettings(); + bool isShowingGrid = faultCollection->isGridVisualizationMode(); if (!faultCollection->showFaultCollection() && !isShowingGrid) return; @@ -144,7 +146,16 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) { if (faultCollection->showNNCs()) { - rivFaultPart->appendNNCFacesToModel(&parts); + bool showNncs = true; + if (faultResultSlot->hideNncsWhenNoResultIsAvailable()) + { + showNncs = faultResultSlot->isNncResultAvailable(); + } + + if (showNncs) + { + rivFaultPart->appendNNCFacesToModel(&parts); + } } } } diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 2f13d9f2e6..5c7e50575b 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -713,7 +713,7 @@ void RivReservoirViewPartMgr::computePropertyVisibility(cvf::UByteArray* cellVis const double lowerBound = (*pfIt)->lowerBound(); const double upperBound = (*pfIt)->upperBound(); - size_t scalarResultIndex = (*pfIt)->resultDefinition->gridScalarIndex(); + size_t scalarResultIndex = (*pfIt)->resultDefinition->scalarResultIndex(); size_t adjustedTimeStepIndex = timeStepIndex; diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index 5db902ff18..4ced6073c9 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -236,7 +236,7 @@ void RimCellPropertyFilter::computeResultValueRange() double min = 0.0; double max = 0.0; - size_t scalarIndex = resultDefinition->gridScalarIndex(); + size_t scalarIndex = resultDefinition->scalarResultIndex(); if (scalarIndex != cvf::UNDEFINED_SIZE_T) { RimReservoirCellResultsStorage* results = resultDefinition->currentGridCellResults(); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 898458fbe3..67171fb3c8 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -18,10 +18,14 @@ #include "RimFaultResultSlot.h" +#include "RigCaseData.h" +#include "RigMainGrid.h" + +#include "RimCase.h" #include "RimReservoirView.h" #include "RimResultSlot.h" -#include "RiuMainWindow.h" #include "RimUiTreeModelPdm.h" +#include "RiuMainWindow.h" @@ -47,6 +51,8 @@ RimFaultResultSlot::RimFaultResultSlot() m_customFaultResult->m_porosityModelUiField.setOwnerObject(this); m_customFaultResult->m_resultVariableUiField.setOwnerObject(this); + CAF_PDM_InitField(&hideNncsWhenNoResultIsAvailable, "HideNncsWhenNoResultIsAvailable", true, "Hide NNC geometry if no NNC result is available", "", "", ""); + updateFieldVisibility(); } @@ -150,3 +156,22 @@ bool RimFaultResultSlot::hasValidCustomResult() return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultResultSlot::isNncResultAvailable() +{ + if (this->hasValidCustomResult()) + { + size_t scalarSetIndex = this->customFaultResult()->scalarResultIndex(); + + RigMainGrid* mainGrid = m_reservoirView->eclipseCase()->reservoirData()->mainGrid(); + if (mainGrid && mainGrid->nncData()->hasScalarValues(scalarSetIndex)) + { + return true; + } + } + + return false; +} + diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 0e30db8422..e7362fd6e3 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -40,8 +40,10 @@ class RimFaultResultSlot : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField showCustomFaultResult; + caf::PdmField hideNncsWhenNoResultIsAvailable; bool hasValidCustomResult(); + bool isNncResultAvailable(); RimResultSlot* customFaultResult(); void updateFieldVisibility(); From 50f6420c1569953f025d8a83cc9f046dbcfbff21 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 09:55:55 +0200 Subject: [PATCH 320/346] NNC : Show item count in folder No Common Area Nncs --- .../ProjectDataModel/RimFaultCollection.cpp | 6 ++++-- .../RimNoCommonAreaNncCollection.cpp | 19 +++++++++++++++++++ .../RimNoCommonAreaNncCollection.h | 7 ++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 263d94cc6e..4ccb2265a4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -71,11 +71,11 @@ RimFaultCollection::RimFaultCollection() CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); - CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", ""); - CAF_PDM_InitFieldNoDefault(&noCommonAreaNnncCollection, "NoCommonAreaNnncCollection", "NNCs With No Common Area", "", "", ""); noCommonAreaNnncCollection = new RimNoCommonAreaNncCollection; + CAF_PDM_InitFieldNoDefault(&faults, "Faults", "Faults", "", "", ""); + m_reservoirView = NULL; } @@ -260,6 +260,8 @@ void RimFaultCollection::syncronizeFaults() noCommonAreaNnc->name = txt; this->noCommonAreaNnncCollection()->noCommonAreaNncs().push_back(noCommonAreaNnc); } + + this->noCommonAreaNnncCollection()->updateName(); } } diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp index 70799990f6..08a674e836 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp @@ -27,6 +27,9 @@ RimNoCommonAreaNncCollection::RimNoCommonAreaNncCollection() { CAF_PDM_InitObject("RimNoCommonAreaNncCollection", "", "", ""); + CAF_PDM_InitField(&name, "UserDescription", QString("No Common Area Nncs"), "Name", "", "", ""); + name.setUiHidden(true); + CAF_PDM_InitFieldNoDefault(&noCommonAreaNncs, "NoCommonAreaNncs", "NoCommonAreaNncs", "", "", ""); } @@ -38,3 +41,19 @@ RimNoCommonAreaNncCollection::~RimNoCommonAreaNncCollection() noCommonAreaNncs.deleteAllChildObjects(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmFieldHandle* RimNoCommonAreaNncCollection::userDescriptionField() +{ + return &name; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimNoCommonAreaNncCollection::updateName() +{ + name = QString("NNCs With No Common Area (%1)").arg(noCommonAreaNncs().size()); +} + diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h index f7bcd24737..dae7220a07 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h @@ -35,5 +35,10 @@ class RimNoCommonAreaNncCollection : public caf::PdmObject RimNoCommonAreaNncCollection(); virtual ~RimNoCommonAreaNncCollection(); - caf::PdmPointersField noCommonAreaNncs; + void updateName(); + + virtual caf::PdmFieldHandle* userDescriptionField(); + + caf::PdmField name; + caf::PdmPointersField noCommonAreaNncs; }; From 2906027429f58566a452c792457edfb90f80c426 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 4 Sep 2014 10:37:36 +0200 Subject: [PATCH 321/346] Append LGR name for NNCs connected to LGR --- .../ProjectDataModel/RimFaultCollection.cpp | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 4ccb2265a4..31537e452b 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -248,16 +248,56 @@ void RimFaultCollection::syncronizeFaults() { RimNoCommonAreaNNC* noCommonAreaNnc = new RimNoCommonAreaNNC(); - size_t i1, j1, k1; - mainGrid->ijkFromCellIndex(nncConnections[i].m_c1GlobIdx, &i1, &j1, &k1); - - size_t i2, j2, k2; - mainGrid->ijkFromCellIndex(nncConnections[i].m_c2GlobIdx, &i2, &j2, &k2); + QString firstConnectionText; + QString secondConnectionText; + + { + const RigCell& cell = mainGrid->cells()[nncConnections[i].m_c1GlobIdx]; + + RigGridBase* hostGrid = cell.hostGrid(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); + + size_t i, j, k; + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) + { + // Adjust to 1-based Eclipse indexing + i++; + j++; + k++; + + if (!hostGrid->isMainGrid()) + { + QString gridName = QString::fromStdString(hostGrid->gridName()); + firstConnectionText = gridName + " "; + } + firstConnectionText += QString("[%1 %2 %3] - ").arg(i).arg(j).arg(k); + } + } - // Convert to 1-based for IJK values to be displayed to the user - QString txt = QString("[%1 %2 %3] - [%4 %5 %6]").arg(i1 + 1).arg(j1 + 1).arg(k1 + 1).arg(i2 + 1).arg(j2 + 1).arg(k2 + 1); + { + const RigCell& cell = mainGrid->cells()[nncConnections[i].m_c2GlobIdx]; + + RigGridBase* hostGrid = cell.hostGrid(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); + + size_t i, j, k; + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) + { + // Adjust to 1-based Eclipse indexing + i++; + j++; + k++; + + if (!hostGrid->isMainGrid()) + { + QString gridName = QString::fromStdString(hostGrid->gridName()); + secondConnectionText = gridName + " "; + } + secondConnectionText += QString("[%1 %2 %3]").arg(i).arg(j).arg(k); + } + } - noCommonAreaNnc->name = txt; + noCommonAreaNnc->name = firstConnectionText + secondConnectionText; this->noCommonAreaNnncCollection()->noCommonAreaNncs().push_back(noCommonAreaNnc); } From 787d44e446610d17c8b081f8a9efad0e6e9feb27 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 5 Sep 2014 08:25:38 +0200 Subject: [PATCH 322/346] Added class used to build text strings from picked objects in 3D scene --- ApplicationCode/CMakeLists.txt | 2 + .../UserInterface/RiuResultTextBuilder.cpp | 316 ++++++++++++++++++ .../UserInterface/RiuResultTextBuilder.h | 73 ++++ 3 files changed, 391 insertions(+) create mode 100644 ApplicationCode/UserInterface/RiuResultTextBuilder.cpp create mode 100644 ApplicationCode/UserInterface/RiuResultTextBuilder.h diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index d4e7e4113f..b392fbbf8e 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -42,6 +42,7 @@ set( APPLICATION_FILES set( USER_INTERFACE_FILES UserInterface/RiuCursors.cpp + UserInterface/RiuResultTextBuilder.cpp UserInterface/RiuMainWindow.cpp UserInterface/RiuResultInfoPanel.cpp UserInterface/RiuViewer.cpp @@ -166,6 +167,7 @@ list( REMOVE_ITEM RAW_SOURCES UserInterface/RiuSimpleHistogramWidget.cpp UserInterface/RiuMultiCaseImportDialog.cpp + UserInterface/RiuResultTextBuilder.cpp ) include( CustomPCH.cmake ) diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp new file mode 100644 index 0000000000..7b3552be4e --- /dev/null +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -0,0 +1,316 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA, Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiuResultTextBuilder.h" + +#include "RigCaseCellResultsData.h" +#include "RigCaseData.h" +#include "RigMainGrid.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" + +#include "RimCase.h" +#include "RimCellEdgeResultSlot.h" +#include "RimFaultResultSlot.h" +#include "RimReservoirCellResultsStorage.h" +#include "RimReservoirView.h" +#include "RimResultSlot.h" + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiuResultTextBuilder::RiuResultTextBuilder(RimReservoirView* reservoirView, size_t gridIndex, size_t cellIndex, size_t timeStepIndex) +{ + CVF_ASSERT(reservoirView); + + m_reservoirView = reservoirView; + m_gridIndex = gridIndex; + m_cellIndex = cellIndex; + m_timeStepIndex = timeStepIndex; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::mainResultText() +{ + QString text; + + QString nncText = nncResultText(); + if (!nncText.isEmpty()) + { + text = nncText; + } + else + { + text = gridResultText(); + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::gridResultDetails() +{ + QString text; + + if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) + { + RigCaseData* eclipseCaseData = m_reservoirView->eclipseCase()->reservoirData(); + RigGridBase* grid = eclipseCaseData->grid(m_gridIndex); + + this->appendTextFromResultSlot(eclipseCaseData, m_gridIndex, m_cellIndex, m_timeStepIndex, m_reservoirView->cellResult(), &text); + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::faultResultDetails() +{ + QString text; + + if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) + { + RigCaseData* eclipseCaseData = m_reservoirView->eclipseCase()->reservoirData(); + RigGridBase* grid = eclipseCaseData->grid(m_gridIndex); + RigMainGrid* mainGrid = grid->mainGrid(); + + const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(m_cellIndex, m_face); + if (fault) + { + text.append(QString("Fault Name: %1\n").arg(fault->name())); + + cvf::StructGridInterface::FaceEnum faceHelper(m_face); + text.append("Fault Face : " + faceHelper.text() + "\n"); + + if (m_reservoirView->faultResultSettings()->hasValidCustomResult()) + { + text.append("Fault result data:\n"); + this->appendTextFromResultSlot(eclipseCaseData, m_gridIndex, m_cellIndex, m_timeStepIndex, m_reservoirView->currentFaultResultSlot(), &text); + } + } + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::gridResultText() +{ + QString text; + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::nncResultText() +{ + QString text; + + return text; + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuResultTextBuilder::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText) +{ + if (!resultSlot) + { + return; + } + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); + if (resultSlot->isTernarySaturationSelected()) + { + RimReservoirCellResultsStorage* gridCellResults = resultSlot->currentGridCellResults(); + if (gridCellResults) + { + 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"); + + cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, swatScalarSetIndex); + + double scalarValue = 0.0; + + if (dataAccessObjectX.notNull()) scalarValue = dataAccessObjectX->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SOIL : %1\n").arg(scalarValue)); + + if (dataAccessObjectY.notNull()) scalarValue = dataAccessObjectY->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SGAS : %1\n").arg(scalarValue)); + + if (dataAccessObjectZ.notNull()) scalarValue = dataAccessObjectZ->cellScalar(cellIndex); + else scalarValue = 0.0; + resultInfoText->append(QString("SWAT : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->hasResult()) + { + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); + cvf::ref resultAccessor; + + if (resultSlot->hasStaticResult()) + { + if (resultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedTransmissibilityResultName()); + { + double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("Tran Y : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("Tran Z : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref multResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedMultResultName()); + { + double scalarValue = 0.0; + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("MULTX : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_I); + resultInfoText->append(QString("MULTX- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("MULTY : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_J); + resultInfoText->append(QString("MULTY- : %1\n").arg(scalarValue)); + + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("MULTZ : %1\n").arg(scalarValue)); + scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_K); + resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiTransResultName()); + { + double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riTran X : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riTran Y : %1\n").arg(scalarValue)); + + scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riTran Z : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiMultResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiMultResultName()); + { + double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riMult X : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riMult Y : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riMult Z : %1\n").arg(scalarValue)); + } + } + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) + { + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiAreaNormTransResultName()); + { + double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); + resultInfoText->append(QString("riTransByArea X : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); + resultInfoText->append(QString("riTransByArea Y : %1\n").arg(scalarValue)); + + scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); + resultInfoText->append(QString("riTransByArea Z : %1\n").arg(scalarValue)); + } + } + else + { + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->scalarResultIndex()); + } + } + else + { + resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultSlot->scalarResultIndex()); + } + + if (resultAccessor.notNull()) + { + double scalarValue = resultAccessor->cellScalar(cellIndex); + resultInfoText->append(resultSlot->resultVariable()); + resultInfoText->append(QString(" : %1\n").arg(scalarValue)); + } + } + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::cellEdgeResultDetails() +{ + QString text; + + //if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) + if (m_reservoirView->cellEdgeResult()->hasResult()) + { + size_t resultIndices[6]; + QStringList resultNames; + m_reservoirView->cellEdgeResult()->gridScalarIndices(resultIndices); + m_reservoirView->cellEdgeResult()->gridScalarResultNames(&resultNames); + + text.push_back("\nCell edge result data:\n"); + for (int idx = 0; idx < 6; idx++) + { + if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; + + // Cell edge results are static, results are loaded for first time step only + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(m_reservoirView->cellResult()->porosityModel()); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(m_reservoirView->eclipseCase()->reservoirData(), m_gridIndex, porosityModel, 0, resultIndices[idx]); + if (resultAccessor.notNull()) + { + double scalarValue = resultAccessor->cellScalar(m_cellIndex); + text.append(QString("%1 : %2\n").arg(resultNames[idx]).arg(scalarValue)); + } + } + } + + return text; +} diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.h b/ApplicationCode/UserInterface/RiuResultTextBuilder.h new file mode 100644 index 0000000000..3568b8578c --- /dev/null +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.h @@ -0,0 +1,73 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cvfBase.h" +#include "cafPdmPointer.h" +#include "cvfStructGrid.h" + + +class RimReservoirView; +class RimResultSlot; +class QString; +class RigCaseData; + +namespace cvf { + class Part; +} + +//================================================================================================== +// +// +//================================================================================================== +class RiuResultTextBuilder +{ +public: + RiuResultTextBuilder(RimReservoirView* reservoirView, size_t gridIndex, size_t cellIndex, size_t timeStepIndex); + void setPickInfo(cvf::Part* part, cvf::uint partFaceHit, cvf::Part* nncPart, cvf::uint nncFaceHit, cvf::Vec3d intersectionPoint); + + QString mainResultText(); + + QString gridResultDetails(); + QString faultResultDetails(); + QString cellEdgeResultDetails(); + +private: + QString gridResultText(); + QString nncResultText(); + + void appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText); + +private: + caf::PdmPointer m_reservoirView; + + size_t m_gridIndex; + size_t m_cellIndex; + size_t m_timeStepIndex; + + cvf::StructGridInterface::FaceType m_face; + + cvf::Part* m_part; + uint m_partFaceIndex; + + cvf::Part* m_nncPart; + uint m_nncPartFaceIndex; + + cvf::Vec3d m_intersectionPoint; +}; From e2a5c449ce646863fe93944e1df38cf45e5aa053 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 Sep 2014 07:35:23 +0200 Subject: [PATCH 323/346] Impoved result info text presentation Display Cell result, Fault result, NNC result, and Cell edge result as a section with a linefeed above Always show value for intersection point at top with details below. --- .../ProjectDataModel/RimReservoirView.cpp | 375 +---------------- .../ProjectDataModel/RimReservoirView.h | 11 +- .../UserInterface/RiuResultTextBuilder.cpp | 391 +++++++++++++++++- .../UserInterface/RiuResultTextBuilder.h | 31 +- ApplicationCode/UserInterface/RiuViewer.cpp | 152 +++---- ApplicationCode/UserInterface/RiuViewer.h | 2 +- 6 files changed, 485 insertions(+), 477 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 7c1accee08..aaf6618c7b 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1031,126 +1031,6 @@ RiuViewer* RimReservoirView::viewer() return m_viewer; } - -//-------------------------------------------------------------------------------------------------- -/// Get pick info text for given part ID, face index, and intersection point -//-------------------------------------------------------------------------------------------------- -bool RimReservoirView::pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString itemSeparator, QString* pickInfoText) const -{ - CVF_ASSERT(pickInfoText); - - if (m_reservoir) - { - const RigCaseData* eclipseCase = m_reservoir->reservoirData(); - if (eclipseCase) - { - size_t i = 0; - size_t j = 0; - size_t k = 0; - if (eclipseCase->grid(gridIndex)->ijkFromCellIndex(cellIndex, &i, &j, &k)) - { - // Adjust to 1-based Eclipse indexing - i++; - j++; - k++; - - cvf::Vec3d domainCoord = point + eclipseCase->grid(gridIndex)->displayModelOffset(); - - cvf::StructGridInterface::FaceEnum faceEnum(face); - - QString faceText = faceEnum.text(); - - *pickInfoText += QString("Hit grid %1").arg(gridIndex) + itemSeparator; - *pickInfoText += QString("Cell : [%1, %2, %3]").arg(i).arg(j).arg(k) + itemSeparator; - *pickInfoText += QString("Face : %1").arg(faceText) + itemSeparator; - - QString formattedText; - formattedText.sprintf("Intersection point : [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); - - *pickInfoText += formattedText; - return true; - } - } - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// Append fault name and result value for the given cell to the string -//-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendCellResultInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) -{ - CVF_ASSERT(resultInfoText); - - if (m_reservoir && m_reservoir->reservoirData()) - { - RigCaseData* eclipseCase = m_reservoir->reservoirData(); - RigGridBase* grid = eclipseCase->grid(gridIndex); - - appendTextFromResultSlot(eclipseCase, gridIndex, cellIndex, this->m_currentTimeStep, this->cellResult(), resultInfoText); - - // Fault text data - if (grid->isMainGrid()) - { - RigMainGrid* mainGrid = grid->mainGrid(); - - const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(cellIndex, face); - if (fault) - { - resultInfoText->append(QString("\nFault Name: %1\n").arg(fault->name())); - if (this->faultResultSettings()->hasValidCustomResult()) - { - resultInfoText->push_back("Fault result data:\n"); - appendTextFromResultSlot(eclipseCase, gridIndex, cellIndex, this->m_currentTimeStep, this->faultResultSettings()->customFaultResult(), resultInfoText); - } - } - } - - if (this->cellEdgeResult()->hasResult()) - { - size_t resultIndices[6]; - QStringList resultNames; - this->cellEdgeResult()->gridScalarIndices(resultIndices); - this->cellEdgeResult()->gridScalarResultNames(&resultNames); - - resultInfoText->push_back("\nCell edge result data:\n"); - for (int idx = 0; idx < 6; idx++) - { - if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; - - // Cell edge results are static, results are loaded for first time step only - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(cellResult()->porosityModel()); - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultIndices[idx]); - if (resultAccessor.notNull()) - { - double scalarValue = resultAccessor->cellScalar(cellIndex); - resultInfoText->append(QString("%1 : %2\n").arg(resultNames[idx]).arg(scalarValue)); - } - } - } - - cvf::Collection wellResults = m_reservoir->reservoirData()->wellResults(); - for (size_t i = 0; i < wellResults.size(); i++) - { - RigSingleWellResultsData* singleWellResultData = wellResults.at(i); - - if (m_currentTimeStep < static_cast(singleWellResultData->firstResultTimeStep())) - { - continue; - } - - const RigWellResultFrame& wellResultFrame = singleWellResultData->wellResultFrame(m_currentTimeStep); - const RigWellResultPoint* wellResultCell = wellResultFrame.findResultCell(gridIndex, cellIndex); - if (wellResultCell) - { - resultInfoText->append(QString("Well-cell connection info: Well Name: %1 Branch Id: %2 Segment Id: %3\n").arg(singleWellResultData->m_wellName).arg(wellResultCell->m_ertBranchId).arg(wellResultCell->m_ertSegmentId)); - } - } - } -} - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1322,7 +1202,7 @@ void RimReservoirView::updateLegends() updateMinMaxValuesAndAddLegendToView(QString("Cell Results: \n"), this->cellResult(), results); if (this->faultResultSettings()->showCustomFaultResult() && this->faultResultSettings()->hasValidCustomResult()) { - updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->faultResultSettings()->customFaultResult(), results); + updateMinMaxValuesAndAddLegendToView(QString("Fault Results: \n"), this->currentFaultResultSlot(), results); } if (this->cellEdgeResult()->hasResult()) @@ -1797,98 +1677,6 @@ void RimReservoirView::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering cellGroup->add(&showInvalidCells); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendNNCResultInfo(size_t nncIndex, QString* resultInfo) -{ - CVF_ASSERT(resultInfo); - - if (m_reservoir && m_reservoir->reservoirData()) - { - RigCaseData* eclipseCase = m_reservoir->reservoirData(); - - RigMainGrid* grid = eclipseCase->mainGrid(); - CVF_ASSERT(grid); - - RigNNCData* nncData = grid->nncData(); - CVF_ASSERT(nncData); - - if (nncData) - { - const RigConnection& conn = nncData->connections()[nncIndex]; - cvf::StructGridInterface::FaceEnum face(conn.m_c1Face); - - // Print result value for the NNC - size_t scalarResultIdx = this->cellResult()->scalarResultIndex(); - const std::vector* nncValues = nncData->connectionScalarResult(scalarResultIdx); - if (nncValues) - { - resultInfo->append(QString("NNC Value : %1\n").arg((*nncValues)[nncIndex])); - } - - QString faultName; - - { - CVF_ASSERT(conn.m_c1GlobIdx < grid->cells().size()); - const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; - - RigGridBase* hostGrid = cell.hostGrid(); - size_t gridLocalCellIndex = cell.gridLocalCellIndex(); - - size_t i, j, k; - if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) - { - // Adjust to 1-based Eclipse indexing - i++; - j++; - k++; - - QString gridName = QString::fromStdString(hostGrid->gridName()); - resultInfo->append(QString("NNC 1 : cell [%1, %2, %3] face %4 (%5)\n").arg(i).arg(j).arg(k).arg(face.text()).arg(gridName)); - - appendTextFromFault(hostGrid, conn.m_c1GlobIdx, conn.m_c1Face, &faultName); - } - } - - { - CVF_ASSERT(conn.m_c2GlobIdx < grid->cells().size()); - const RigCell& cell = grid->cells()[conn.m_c2GlobIdx]; - - RigGridBase* hostGrid = cell.hostGrid(); - size_t gridLocalCellIndex = cell.gridLocalCellIndex(); - - size_t i, j, k; - if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) - { - // Adjust to 1-based Eclipse indexing - i++; - j++; - k++; - - QString gridName = QString::fromStdString(hostGrid->gridName()); - cvf::StructGridInterface::FaceEnum oppositeFaceEnum(cvf::StructGridInterface::oppositeFace(face)); - QString faceText = oppositeFaceEnum.text(); - - resultInfo->append(QString("NNC 2 : cell [%1, %2, %3] face %4 (%5)\n").arg(i).arg(j).arg(k).arg(faceText).arg(gridName)); - - if (faultName.isEmpty()) - { - appendTextFromFault(hostGrid, conn.m_c2GlobIdx, cvf::StructGridInterface::oppositeFace(conn.m_c1Face), &faultName); - } - } - } - - resultInfo->append(QString("Face: %2\n").arg(face.text())); - - if (!faultName.isEmpty()) - { - resultInfo->append(faultName); - } - } - } -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1991,11 +1779,7 @@ void RimReservoirView::updateFaultColors() // Update all fault geometry std::vector faultGeometriesToRecolor = visibleFaultGeometryTypes(); - RimResultSlot* faultResultSlot = this->cellResult(); - if (this->faultResultSettings()->showCustomFaultResult()) - { - faultResultSlot = this->faultResultSettings()->customFaultResult(); - } + RimResultSlot* faultResultSlot = currentFaultResultSlot(); for (size_t i = 0; i < faultGeometriesToRecolor.size(); ++i) { @@ -2010,22 +1794,6 @@ void RimReservoirView::updateFaultColors() } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendTextFromFault(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString) -{ - if (grid->isMainGrid()) - { - RigMainGrid* mainGrid = grid->mainGrid(); - - const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(cellIndex, face); - if (fault) - { - textString->append(QString("Fault Name: %1\n").arg(fault->name())); - } - } -} //-------------------------------------------------------------------------------------------------- /// @@ -2050,146 +1818,19 @@ bool RimReservoirView::isTimeStepDependentDataVisible() const return false; } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimReservoirView::appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText) +RimResultSlot* RimReservoirView::currentFaultResultSlot() { - if (!resultSlot) - { - return; - } + RimResultSlot* faultResultSlot = this->cellResult(); - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); - if (resultSlot->isTernarySaturationSelected()) + if (this->faultResultSettings()->showCustomFaultResult()) { - RimReservoirCellResultsStorage* gridCellResults = resultSlot->currentGridCellResults(); - if (gridCellResults) - { - 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"); - - cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, soilScalarSetIndex); - cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, sgasScalarSetIndex); - cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, swatScalarSetIndex); - - double scalarValue = 0.0; - - if (dataAccessObjectX.notNull()) scalarValue = dataAccessObjectX->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SOIL : %1\n").arg(scalarValue)); - - if (dataAccessObjectY.notNull()) scalarValue = dataAccessObjectY->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SGAS : %1\n").arg(scalarValue)); - - if (dataAccessObjectZ.notNull()) scalarValue = dataAccessObjectZ->cellScalar(cellIndex); - else scalarValue = 0.0; - resultInfoText->append(QString("SWAT : %1\n").arg(scalarValue)); - } + faultResultSlot = this->faultResultSettings()->customFaultResult(); } - else if (resultSlot->hasResult()) - { - RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); - cvf::ref resultAccessor; - - if (resultSlot->hasStaticResult()) - { - if (resultSlot->resultVariable().compare(RimDefines::combinedTransmissibilityResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedTransmissibilityResultName()); - { - double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("Tran X : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("Tran Y : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("Tran Z : %1\n").arg(scalarValue)); - } - } - else if (resultSlot->resultVariable().compare(RimDefines::combinedMultResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref multResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedMultResultName()); - { - double scalarValue = 0.0; - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("MULTX : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_I); - resultInfoText->append(QString("MULTX- : %1\n").arg(scalarValue)); - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("MULTY : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_J); - resultInfoText->append(QString("MULTY- : %1\n").arg(scalarValue)); - - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("MULTZ : %1\n").arg(scalarValue)); - scalarValue = multResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::NEG_K); - resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); - } - } - else if (resultSlot->resultVariable().compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiTransResultName()); - { - double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("riTran X : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("riTran Y : %1\n").arg(scalarValue)); - - scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("riTran Z : %1\n").arg(scalarValue)); - } - } - else if (resultSlot->resultVariable().compare(RimDefines::combinedRiMultResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiMultResultName()); - { - double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("riMult X : %1\n").arg(scalarValue)); - - scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("riMult Y : %1\n").arg(scalarValue)); - scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("riMult Z : %1\n").arg(scalarValue)); - } - } - else if (resultSlot->resultVariable().compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) - { - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiAreaNormTransResultName()); - { - double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); - resultInfoText->append(QString("riTransByArea X : %1\n").arg(scalarValue)); - - scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_J); - resultInfoText->append(QString("riTransByArea Y : %1\n").arg(scalarValue)); - - scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_K); - resultInfoText->append(QString("riTransByArea Z : %1\n").arg(scalarValue)); - } - } - else - { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, resultSlot->scalarResultIndex()); - } - } - else - { - resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, resultSlot->scalarResultIndex()); - } - - if (resultAccessor.notNull()) - { - double scalarValue = resultAccessor->cellScalar(cellIndex); - resultInfoText->append(resultSlot->resultVariable()); - resultInfoText->append(QString(" : %1\n").arg(scalarValue)); - } - } + return faultResultSlot; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index e0f77fbf31..9972e1da8a 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -133,6 +133,8 @@ class RimReservoirView : public caf::PdmObject // Access internal objects RimReservoirCellResultsStorage* currentGridCellResults(); RigActiveCellInfo* currentActiveCellInfo(); + RimResultSlot* currentFaultResultSlot(); + void setEclipseCase(RimCase* reservoir); RimCase* eclipseCase(); @@ -157,13 +159,6 @@ class RimReservoirView : public caf::PdmObject void setShowFaultsOnly(bool showFaults); bool isGridVisualizationMode() const; - - // Picking info - bool pickInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, const cvf::Vec3d& point, QString itemSeparator, QString* pickInfoText) const; - void appendCellResultInfo(size_t gridIndex, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* resultInfoText) ; - void appendNNCResultInfo(size_t nncIndex, QString* resultInfo); - static void appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText); - // Does this belong here, really ? void calculateVisibleWellCellsIncFence(cvf::UByteArray* visibleCells, RigGridBase * grid); @@ -185,8 +180,6 @@ class RimReservoirView : public caf::PdmObject // Display model generation private: - void appendTextFromFault(RigGridBase* grid, size_t cellIndex, cvf::StructGridInterface::FaceType face, QString* textString); - void createDisplayModel(); void updateDisplayModelVisibility(); void updateCurrentTimeStep(); diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp index 7b3552be4e..beab91960e 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -44,6 +44,34 @@ RiuResultTextBuilder::RiuResultTextBuilder(RimReservoirView* reservoirView, size m_gridIndex = gridIndex; m_cellIndex = cellIndex; m_timeStepIndex = timeStepIndex; + + m_nncIndex = cvf::UNDEFINED_SIZE_T; + m_intersectionPoint = cvf::Vec3d::UNDEFINED; + m_face = cvf::StructGridInterface::NO_FACE; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuResultTextBuilder::setNncIndex(size_t nncIndex) +{ + m_nncIndex = nncIndex; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuResultTextBuilder::setIntersectionPoint(cvf::Vec3d intersectionPoint) +{ + m_intersectionPoint = intersectionPoint; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuResultTextBuilder::setFace(cvf::StructGridInterface::FaceType face) +{ + m_face = face; } //-------------------------------------------------------------------------------------------------- @@ -51,21 +79,97 @@ RiuResultTextBuilder::RiuResultTextBuilder(RimReservoirView* reservoirView, size //-------------------------------------------------------------------------------------------------- QString RiuResultTextBuilder::mainResultText() { - QString text; + QString text; + + // Produce result text for all variants + // Priority defined as follows : NNC, Fault, Grid + { + QString nncText = nncResultText(); + QString faultText = faultResultText(); + + if (!nncText.isEmpty()) + { + text = "NNC : " + nncText; + } + else if (!faultResultText().isEmpty()) + { + text = "Fault : " + faultText; + } + else + { + text = "Grid cell : " + gridResultText(); + } + + text += "\n"; + } + + QString topoText = this->topologyText("\n"); + text += topoText; + text += "\n"; + + appendDetails(text, nncDetails()); + + if (nncDetails().isEmpty()) + { + appendDetails(text, faultResultDetails()); + } + + appendDetails(text, cellEdgeResultDetails()); - QString nncText = nncResultText(); - if (!nncText.isEmpty()) - { - text = nncText; - } - else - { - text = gridResultText(); - } + bool isCustomFaultResultVisible = m_reservoirView->faultResultSettings()->showCustomFaultResult() && m_reservoirView->faultResultSettings()->hasValidCustomResult(); + if (isCustomFaultResultVisible) + { + appendDetails(text, gridResultDetails()); + } + + appendDetails(text, wellResultText()); return text; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::topologyText(QString itemSeparator) +{ + QString text; + + if (m_reservoirView->eclipseCase()) + { + const RigCaseData* eclipseCase = m_reservoirView->eclipseCase()->reservoirData(); + if (eclipseCase) + { + size_t i = 0; + size_t j = 0; + size_t k = 0; + if (eclipseCase->grid(m_gridIndex)->ijkFromCellIndex(m_cellIndex, &i, &j, &k)) + { + // Adjust to 1-based Eclipse indexing + i++; + j++; + k++; + + cvf::Vec3d domainCoord = m_intersectionPoint + eclipseCase->grid(m_gridIndex)->displayModelOffset(); + + cvf::StructGridInterface::FaceEnum faceEnum(m_face); + + QString faceText = faceEnum.text(); + + text += QString("Face : %1").arg(faceText) + itemSeparator; + text += QString("Hit grid %1").arg(m_gridIndex) + itemSeparator; + text += QString("Cell : [%1, %2, %3]").arg(i).arg(j).arg(k) + itemSeparator; + + QString formattedText; + formattedText.sprintf("Intersection point : [E: %.2f, N: %.2f, Depth: %.2f]", domainCoord.x(), domainCoord.y(), -domainCoord.z()); + + text += formattedText; + } + } + } + + return text; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -79,6 +183,11 @@ QString RiuResultTextBuilder::gridResultDetails() RigGridBase* grid = eclipseCaseData->grid(m_gridIndex); this->appendTextFromResultSlot(eclipseCaseData, m_gridIndex, m_cellIndex, m_timeStepIndex, m_reservoirView->cellResult(), &text); + + if (!text.isEmpty()) + { + text.prepend("-- Grid cell result details --\n"); + } } return text; @@ -100,14 +209,16 @@ QString RiuResultTextBuilder::faultResultDetails() const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(m_cellIndex, m_face); if (fault) { - text.append(QString("Fault Name: %1\n").arg(fault->name())); + text += "-- Fault result details --\n"; + + text += QString("Fault Name: %1\n").arg(fault->name()); cvf::StructGridInterface::FaceEnum faceHelper(m_face); - text.append("Fault Face : " + faceHelper.text() + "\n"); + text += "Fault Face : " + faceHelper.text() + "\n"; if (m_reservoirView->faultResultSettings()->hasValidCustomResult()) { - text.append("Fault result data:\n"); + text += "Fault result data:\n"; this->appendTextFromResultSlot(eclipseCaseData, m_gridIndex, m_cellIndex, m_timeStepIndex, m_reservoirView->currentFaultResultSlot(), &text); } } @@ -116,16 +227,46 @@ QString RiuResultTextBuilder::faultResultDetails() return text; } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuResultTextBuilder::gridResultText() { - QString text; + QString text = cellResultText(m_reservoirView->cellResult()); return text; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::faultResultText() +{ + QString text; + + if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) + { + RigCaseData* eclipseCaseData = m_reservoirView->eclipseCase()->reservoirData(); + RigGridBase* grid = eclipseCaseData->grid(m_gridIndex); + RigMainGrid* mainGrid = grid->mainGrid(); + + const RigFault* fault = mainGrid->findFaultFromCellIndexAndCellFace(m_cellIndex, m_face); + if (fault) + { + cvf::StructGridInterface::FaceEnum faceHelper(m_face); + if (m_reservoirView->faultResultSettings()->hasValidCustomResult()) + { + text = cellResultText(m_reservoirView->currentFaultResultSlot()); + } + } + } + + return text; +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -133,8 +274,40 @@ QString RiuResultTextBuilder::nncResultText() { QString text; - return text; + if (m_nncIndex != cvf::UNDEFINED_SIZE_T) + { + if (m_reservoirView.notNull() && m_reservoirView->eclipseCase()) + { + RigCaseData* eclipseCase = m_reservoirView->eclipseCase()->reservoirData(); + + RigMainGrid* grid = eclipseCase->mainGrid(); + CVF_ASSERT(grid); + + RigNNCData* nncData = grid->nncData(); + CVF_ASSERT(nncData); + + if (nncData) + { + const RigConnection& conn = nncData->connections()[m_nncIndex]; + cvf::StructGridInterface::FaceEnum face(conn.m_c1Face); + + if (m_reservoirView->currentFaultResultSlot()) + { + size_t scalarResultIdx = m_reservoirView->currentFaultResultSlot()->scalarResultIndex(); + const std::vector* nncValues = nncData->connectionScalarResult(scalarResultIdx); + if (nncValues) + { + QString resultVar = m_reservoirView->currentFaultResultSlot()->resultVariable(); + double scalarValue = (*nncValues)[m_nncIndex]; + + text = QString("%1 : %2").arg(resultVar).arg(scalarValue); + } + } + } + } + } + return text; } //-------------------------------------------------------------------------------------------------- @@ -274,11 +447,11 @@ void RiuResultTextBuilder::appendTextFromResultSlot(RigCaseData* eclipseCase, si if (resultAccessor.notNull()) { double scalarValue = resultAccessor->cellScalar(cellIndex); - resultInfoText->append(resultSlot->resultVariable()); + resultInfoText->append("Cell result : "); + resultInfoText->append(resultSlot->resultVariable()); resultInfoText->append(QString(" : %1\n").arg(scalarValue)); } } - } //-------------------------------------------------------------------------------------------------- @@ -288,7 +461,6 @@ QString RiuResultTextBuilder::cellEdgeResultDetails() { QString text; - //if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) if (m_reservoirView->cellEdgeResult()->hasResult()) { size_t resultIndices[6]; @@ -296,7 +468,7 @@ QString RiuResultTextBuilder::cellEdgeResultDetails() m_reservoirView->cellEdgeResult()->gridScalarIndices(resultIndices); m_reservoirView->cellEdgeResult()->gridScalarResultNames(&resultNames); - text.push_back("\nCell edge result data:\n"); + text += "-- Cell edge result data --\n"; for (int idx = 0; idx < 6; idx++) { if (resultIndices[idx] == cvf::UNDEFINED_SIZE_T) continue; @@ -314,3 +486,184 @@ QString RiuResultTextBuilder::cellEdgeResultDetails() return text; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::nncDetails() +{ + QString text; + + if (m_nncIndex != cvf::UNDEFINED_SIZE_T) + { + if (m_reservoirView.notNull() && m_reservoirView->eclipseCase()) + { + RigCaseData* eclipseCase = m_reservoirView->eclipseCase()->reservoirData(); + + RigMainGrid* grid = eclipseCase->mainGrid(); + CVF_ASSERT(grid); + + RigNNCData* nncData = grid->nncData(); + CVF_ASSERT(nncData); + + if (nncData) + { + text += "-- NNC details --\n"; + { + const RigConnection& conn = nncData->connections()[m_nncIndex]; + cvf::StructGridInterface::FaceEnum face(conn.m_c1Face); + + // First cell of NNC + { + CVF_ASSERT(conn.m_c1GlobIdx < grid->cells().size()); + const RigCell& cell = grid->cells()[conn.m_c1GlobIdx]; + + RigGridBase* hostGrid = cell.hostGrid(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); + + size_t i, j, k; + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) + { + // Adjust to 1-based Eclipse indexing + i++; + j++; + k++; + + QString gridName = QString::fromStdString(hostGrid->gridName()); + text.append(QString("NNC 1 : cell [%1, %2, %3] face %4 (%5)\n").arg(i).arg(j).arg(k).arg(face.text()).arg(gridName)); + } + } + + // Second cell of NNC + { + CVF_ASSERT(conn.m_c2GlobIdx < grid->cells().size()); + const RigCell& cell = grid->cells()[conn.m_c2GlobIdx]; + + RigGridBase* hostGrid = cell.hostGrid(); + size_t gridLocalCellIndex = cell.gridLocalCellIndex(); + + size_t i, j, k; + if (hostGrid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k)) + { + // Adjust to 1-based Eclipse indexing + i++; + j++; + k++; + + QString gridName = QString::fromStdString(hostGrid->gridName()); + cvf::StructGridInterface::FaceEnum oppositeFaceEnum(cvf::StructGridInterface::oppositeFace(face)); + QString faceText = oppositeFaceEnum.text(); + + text.append(QString("NNC 2 : cell [%1, %2, %3] face %4 (%5)\n").arg(i).arg(j).arg(k).arg(faceText).arg(gridName)); + } + } + } + } + } + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuResultTextBuilder::appendDetails(QString& text, const QString& details) +{ + if (!details.isEmpty()) + { + text += "\n"; + text += details; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::cellResultText(RimResultSlot* resultSlot) +{ + QString text; + + if (m_reservoirView->eclipseCase() && m_reservoirView->eclipseCase()->reservoirData()) + { + RigCaseData* eclipseCaseData = m_reservoirView->eclipseCase()->reservoirData(); + RigGridBase* grid = eclipseCaseData->grid(m_gridIndex); + + RifReaderInterface::PorosityModelResultType porosityModel = RigCaseCellResultsData::convertFromProjectModelPorosityModel(resultSlot->porosityModel()); + + QString resultVar = resultSlot->resultVariable(); + + if (resultSlot->isTernarySaturationSelected()) + { + RimReservoirCellResultsStorage* gridCellResults = m_reservoirView->cellResult()->currentGridCellResults(); + if (gridCellResults) + { + 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"); + + cvf::ref dataAccessObjectX = RigResultAccessorFactory::createResultAccessor(eclipseCaseData, m_gridIndex, porosityModel, m_timeStepIndex, soilScalarSetIndex); + cvf::ref dataAccessObjectY = RigResultAccessorFactory::createResultAccessor(eclipseCaseData, m_gridIndex, porosityModel, m_timeStepIndex, sgasScalarSetIndex); + cvf::ref dataAccessObjectZ = RigResultAccessorFactory::createResultAccessor(eclipseCaseData, m_gridIndex, porosityModel, m_timeStepIndex, swatScalarSetIndex); + + double scalarValue = 0.0; + + if (dataAccessObjectX.notNull()) scalarValue = dataAccessObjectX->cellScalar(m_cellIndex); + else scalarValue = 0.0; + text += QString("SOIL : %1 ").arg(scalarValue); + + if (dataAccessObjectY.notNull()) scalarValue = dataAccessObjectY->cellScalar(m_cellIndex); + else scalarValue = 0.0; + text += QString("SGAS : %1 ").arg(scalarValue); + + if (dataAccessObjectZ.notNull()) scalarValue = dataAccessObjectZ->cellScalar(m_cellIndex); + else scalarValue = 0.0; + text += QString("SWAT : %1 ").arg(scalarValue); + } + } + else + { + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCaseData, m_gridIndex, porosityModel, m_timeStepIndex, resultVar); + if (resultAccessor.notNull()) + { + double scalarValue = resultAccessor->cellFaceScalar(m_cellIndex, m_face); + text = QString("%1 : %2").arg(resultVar).arg(scalarValue); + } + } + } + + return text; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RiuResultTextBuilder::wellResultText() +{ + QString text; + + if (m_reservoirView->eclipseCase() && + m_reservoirView->eclipseCase()->reservoirData() ) + { + cvf::Collection wellResults = m_reservoirView->eclipseCase()->reservoirData()->wellResults(); + for (size_t i = 0; i < wellResults.size(); i++) + { + RigSingleWellResultsData* singleWellResultData = wellResults.at(i); + + if (m_timeStepIndex < static_cast(singleWellResultData->firstResultTimeStep())) + { + continue; + } + + const RigWellResultFrame& wellResultFrame = singleWellResultData->wellResultFrame(m_timeStepIndex); + const RigWellResultPoint* wellResultCell = wellResultFrame.findResultCell(m_gridIndex, m_cellIndex); + if (wellResultCell) + { + text += QString("-- Well-cell connection info --\n Well Name: %1\n Branch Id: %2\n Segment Id: %3\n").arg(singleWellResultData->m_wellName).arg(wellResultCell->m_ertBranchId).arg(wellResultCell->m_ertSegmentId); + } + } + } + + return text; +} + diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.h b/ApplicationCode/UserInterface/RiuResultTextBuilder.h index 3568b8578c..4121c93745 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.h +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.h @@ -40,17 +40,28 @@ class RiuResultTextBuilder { public: RiuResultTextBuilder(RimReservoirView* reservoirView, size_t gridIndex, size_t cellIndex, size_t timeStepIndex); - void setPickInfo(cvf::Part* part, cvf::uint partFaceHit, cvf::Part* nncPart, cvf::uint nncFaceHit, cvf::Vec3d intersectionPoint); + void setFace(cvf::StructGridInterface::FaceType face); + void setNncIndex(size_t nncIndex); + void setIntersectionPoint(cvf::Vec3d intersectionPoint); QString mainResultText(); - QString gridResultDetails(); - QString faultResultDetails(); - QString cellEdgeResultDetails(); - + QString topologyText(QString itemSeparator); + private: - QString gridResultText(); - QString nncResultText(); + void appendDetails(QString& text, const QString& details); + + QString gridResultDetails(); + QString faultResultDetails(); + QString cellEdgeResultDetails(); + QString nncDetails(); + + QString gridResultText(); + QString faultResultText(); + QString nncResultText(); + QString wellResultText(); + + QString cellResultText(RimResultSlot* resultSlot); void appendTextFromResultSlot(RigCaseData* eclipseCase, size_t gridIndex, size_t cellIndex, size_t timeStepIndex, RimResultSlot* resultSlot, QString* resultInfoText); @@ -63,11 +74,7 @@ class RiuResultTextBuilder cvf::StructGridInterface::FaceType m_face; - cvf::Part* m_part; - uint m_partFaceIndex; - - cvf::Part* m_nncPart; - uint m_nncPartFaceIndex; + size_t m_nncIndex; cvf::Vec3d m_intersectionPoint; }; diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index e0654348a0..9ff86a3851 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -48,6 +48,7 @@ #include "cafPdmFieldCvfColor.h" #include "cafPdmFieldCvfMat4d.h" #include "RivSourceInfo.h" +#include "RiuResultTextBuilder.h" using cvf::ManipulatorTrackball; @@ -215,8 +216,9 @@ void RiuViewer::mouseReleaseEvent(QMouseEvent* event) uint faceIndex = cvf::UNDEFINED_UINT; cvf::Vec3d localIntersectionPoint(cvf::Vec3d::ZERO); - cvf::Part * firstHitPart = NULL; - firstHitPart = pickPointAndFace(winPosX, winPosY, &faceIndex, &localIntersectionPoint); + cvf::Part* firstHitPart = NULL; + cvf::Part* nncFirstHitPart = NULL; + pickPointAndFace(winPosX, winPosY, &localIntersectionPoint, &firstHitPart, &faceIndex, &nncFirstHitPart, NULL); if (firstHitPart) { if (faceIndex != cvf::UNDEFINED_UINT) @@ -375,7 +377,6 @@ void RiuViewer::keyPressEvent(QKeyEvent* event) } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -386,22 +387,24 @@ void RiuViewer::handlePickAction(int winPosX, int winPosY) RiuMainWindow* mainWnd = RiuMainWindow::instance(); if (!mainWnd) return; - QString pickInfo = "No hits"; - QString resultInfo = ""; - - uint faceIndex = cvf::UNDEFINED_UINT; + size_t gridIndex = cvf::UNDEFINED_SIZE_T; + size_t cellIndex = cvf::UNDEFINED_SIZE_T; + size_t nncIndex = cvf::UNDEFINED_SIZE_T; + cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::NO_FACE; cvf::Vec3d localIntersectionPoint(cvf::Vec3d::ZERO); - cvf::Part * firstHitPart = NULL; - firstHitPart = pickPointAndFace(winPosX, winPosY, &faceIndex, &localIntersectionPoint); - if (firstHitPart) { - // If a drawable geometry was hit, get info about the picked geometry - // and possibly the picked scalar value, if any - if (faceIndex != cvf::UNDEFINED_UINT) - { - size_t gridIndex = firstHitPart->id(); + cvf::Part* firstHitPart = NULL; + uint firstPartFaceIndex = cvf::UNDEFINED_UINT; + + cvf::Part* firstNncHitPart = NULL; + uint nncPartFaceIndex = cvf::UNDEFINED_UINT; + pickPointAndFace(winPosX, winPosY, &localIntersectionPoint, &firstHitPart, &firstPartFaceIndex, &firstNncHitPart, &nncPartFaceIndex); + + if (firstHitPart) + { + gridIndex = firstHitPart->id(); if (firstHitPart->sourceInfo()) { const RivSourceInfo* rivSourceInfo = dynamic_cast(firstHitPart->sourceInfo()); @@ -411,43 +414,42 @@ void RiuViewer::handlePickAction(int winPosX, int winPosY) { CVF_ASSERT(rivSourceInfo->m_cellFaceFromTriangleMapper.notNull()); - size_t cellIndex = cvf::UNDEFINED_SIZE_T; - cellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(faceIndex); - - cvf::StructGridInterface::FaceType face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(faceIndex); - - m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, ", ", &pickInfo); - - // Build up result from from both pick info and result values - m_reservoirView->pickInfo(gridIndex, cellIndex, face, localIntersectionPoint, "\n", &resultInfo); - resultInfo += "\n"; - m_reservoirView->appendCellResultInfo(gridIndex, cellIndex, face, &resultInfo); -#if 0 - const RigCaseData* reservoir = m_reservoirView->eclipseCase()->reservoirData(); - const RigGridBase* grid = reservoir->grid(gridIndex); - const RigCell& cell = grid->cell(cellIndex); - const caf::SizeTArray8& cellNodeIndices = cell.cornerIndices(); - const std::vector& nodes = reservoir->mainGrid()->nodes(); - for (int i = 0; i < 8; ++i) - { - resultInfo += QString::number(i) + " : "; - for (int j = 0; j < 3; ++j) - resultInfo += QString::number(nodes[cellNodeIndices[i]][j], 'g', 10) + " "; - resultInfo += "\n"; - } -#endif + cellIndex = rivSourceInfo->m_cellFaceFromTriangleMapper->cellIndex(firstPartFaceIndex); + face = rivSourceInfo->m_cellFaceFromTriangleMapper->cellFace(firstPartFaceIndex); } - else if (rivSourceInfo->m_NNCIndices.notNull()) - { - size_t nncIndex = rivSourceInfo->m_NNCIndices->get(faceIndex); + } + } + } - m_reservoirView->appendNNCResultInfo(nncIndex, &resultInfo); - } + + if (firstNncHitPart && firstNncHitPart->sourceInfo()) + { + const RivSourceInfo* rivSourceInfo = dynamic_cast(firstNncHitPart->sourceInfo()); + if (rivSourceInfo) + { + if (nncPartFaceIndex < rivSourceInfo->m_NNCIndices->size()) + { + nncIndex = rivSourceInfo->m_NNCIndices->get(nncPartFaceIndex); } } } } + QString pickInfo = "No hits"; + QString resultInfo = ""; + + if (cellIndex != cvf::UNDEFINED_SIZE_T) + { + RiuResultTextBuilder textBuilder(m_reservoirView, gridIndex, cellIndex, m_reservoirView->currentTimeStep()); + textBuilder.setFace(face); + textBuilder.setNncIndex(nncIndex); + textBuilder.setIntersectionPoint(localIntersectionPoint); + + resultInfo = textBuilder.mainResultText(); + + pickInfo = textBuilder.topologyText(", "); + } + mainWnd->statusBar()->showMessage(pickInfo); mainWnd->setResultInfo(resultInfo); } @@ -516,10 +518,8 @@ void RiuViewer::setEnableMask(unsigned int mask) //-------------------------------------------------------------------------------------------------- /// Perform picking and return the index of the face that was hit, if a drawable geo was hit //-------------------------------------------------------------------------------------------------- -cvf::Part* RiuViewer::pickPointAndFace(int winPosX, int winPosY, uint* faceHit, cvf::Vec3d* localIntersectionPoint) +void RiuViewer::pickPointAndFace(int winPosX, int winPosY, cvf::Vec3d* localIntersectionPoint, cvf::Part** firstPart, uint* firstPartFaceHit, cvf::Part** nncPart, uint* nncPartFaceHit) { - CVF_ASSERT(faceHit); - cvf::HitItemCollection hitItems; bool isSomethingHit = rayPick(winPosX, winPosY, &hitItems); @@ -531,8 +531,8 @@ cvf::Part* RiuViewer::pickPointAndFace(int winPosX, int winPosY, uint* faceHit, double pickDepthThresholdSquared = characteristicCellSize / 100.0; pickDepthThresholdSquared = pickDepthThresholdSquared * pickDepthThresholdSquared; - cvf::HitItem* hitItem = hitItems.firstItem(); - cvf::Vec3d firstItemIntersectionPoint = hitItem->intersectionPoint(); + cvf::HitItem* firstNonNncHitItem = NULL; + cvf::Vec3d firstItemIntersectionPoint = hitItems.item(0)->intersectionPoint(); // Check if we have a close hit item with NNC data for (size_t i = 0; i < hitItems.count(); i++) @@ -540,26 +540,47 @@ cvf::Part* RiuViewer::pickPointAndFace(int winPosX, int winPosY, uint* faceHit, cvf::HitItem* hitItemCandidate = hitItems.item(i); cvf::Vec3d diff = firstItemIntersectionPoint - hitItemCandidate->intersectionPoint(); - // Hit items are ordered by distance from eye - if (diff.lengthSquared() > pickDepthThresholdSquared) break; - const cvf::Part* pickedPartCandidate = hitItemCandidate->part(); + bool isNncpart = false; if (pickedPartCandidate && pickedPartCandidate->sourceInfo()) { - const RivSourceInfo* rivSourceInfo = dynamic_cast(pickedPartCandidate->sourceInfo()); - if (rivSourceInfo && rivSourceInfo->hasNNCIndices()) + // Hit items are ordered by distance from eye + if (diff.lengthSquared() < pickDepthThresholdSquared) { - hitItem = hitItemCandidate; - break; + const RivSourceInfo* rivSourceInfo = dynamic_cast(pickedPartCandidate->sourceInfo()); + if (rivSourceInfo && rivSourceInfo->hasNNCIndices()) + { + *nncPart = const_cast(pickedPartCandidate); + + const cvf::HitDetailDrawableGeo* detail = dynamic_cast(hitItemCandidate->detail()); + if (detail && nncPartFaceHit) + { + *nncPartFaceHit = detail->faceIndex(); + } + + isNncpart = true; + } } } + + if (!isNncpart && !firstNonNncHitItem) + { + firstNonNncHitItem = hitItemCandidate; + firstItemIntersectionPoint = firstNonNncHitItem->intersectionPoint(); + } + + if (firstNonNncHitItem && *nncPart) + { + break; + } } - const cvf::Part* pickedPart = hitItem->part(); + const cvf::Part* pickedPart = firstNonNncHitItem->part(); CVF_ASSERT(pickedPart); + *firstPart = const_cast(pickedPart); const cvf::Transform* xf = pickedPart->transform(); - cvf::Vec3d globalPickedPoint = hitItem->intersectionPoint(); + cvf::Vec3d globalPickedPoint = firstNonNncHitItem->intersectionPoint(); if(localIntersectionPoint) { @@ -573,21 +594,14 @@ cvf::Part* RiuViewer::pickPointAndFace(int winPosX, int winPosY, uint* faceHit, } } - if (faceHit) + if (firstPartFaceHit) { - - const cvf::HitDetailDrawableGeo* detail = dynamic_cast(hitItem->detail()); + const cvf::HitDetailDrawableGeo* detail = dynamic_cast(firstNonNncHitItem->detail()); if (detail) { - *faceHit = detail->faceIndex(); + *firstPartFaceHit = detail->faceIndex(); } } - - return const_cast(pickedPart); // Hack. The const'ness of HitItem will probably change to non-const - } - else - { - return NULL; } } diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index 5dd21d8a0b..07c322aa65 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -80,7 +80,7 @@ public slots: void mousePressEvent(QMouseEvent* event); void handlePickAction(int winPosX, int winPosY); - cvf::Part* pickPointAndFace(int winPosX, int winPosY, uint* faceHit, cvf::Vec3d* localIntersectionPoint); + void pickPointAndFace(int winPosX, int winPosY, cvf::Vec3d* localIntersectionPoint, cvf::Part** firstPart, uint* firstPartFaceHit, cvf::Part** nncPart, uint* nncPartFaceHit); private slots: void slotRangeFilterI(); From 6a25f7e8b9aeaced4fc92837c5a7d46a92dc9f49 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 Sep 2014 07:53:49 +0200 Subject: [PATCH 324/346] Move per cell face results at bottom of Cell Results --- .../ProjectDataModel/RimFaultResultSlot.cpp | 2 +- .../ProjectDataModel/RimResultDefinition.cpp | 30 ++++++++++++++++--- .../ProjectDataModel/RimResultDefinition.h | 9 +++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index 67171fb3c8..d174223284 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -140,7 +140,7 @@ void RimFaultResultSlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi //-------------------------------------------------------------------------------------------------- QList RimFaultResultSlot::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { - return m_customFaultResult->calculateValueOptions(fieldNeedingOptions, useOptionsOnly); + return m_customFaultResult->calculateValueOptionsForSpecifiedDerivedListPosition(true, fieldNeedingOptions, useOptionsOnly); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 1a5a3bb12b..4919432ad0 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -130,7 +130,15 @@ void RimResultDefinition::fieldChangedByUi(const caf::PdmFieldHandle* changedFie //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QList RimResultDefinition::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) +QList RimResultDefinition::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) +{ + return calculateValueOptionsForSpecifiedDerivedListPosition(false, fieldNeedingOptions, useOptionsOnly); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimResultDefinition::calculateValueOptionsForSpecifiedDerivedListPosition(bool showDerivedResultsFirstInList, const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { if (fieldNeedingOptions == &m_resultVariableUiField) { @@ -141,19 +149,20 @@ QList RimResultDefinition::calculateValueOptions(const c bool hasCombinedTransmissibility = false; QList optionList; + QList perCellFaceOptionList; for (int i = 0; i < varList.size(); ++i) { if (RimDefines::isPerCellFaceResult(varList[i])) { // Move combined per cell face results to top of list - optionList.push_front(caf::PdmOptionItemInfo(varList[i], varList[i])); + perCellFaceOptionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i])); } else { optionList.push_back(caf::PdmOptionItemInfo(varList[i], varList[i])); } } - + bool hasAtLeastOneTernaryComponent = false; if (varList.contains("SOIL")) hasAtLeastOneTernaryComponent = true; else if (varList.contains("SGAS")) hasAtLeastOneTernaryComponent = true; @@ -164,7 +173,19 @@ QList RimResultDefinition::calculateValueOptions(const c optionList.push_front(caf::PdmOptionItemInfo(RimDefines::ternarySaturationResultName(), RimDefines::ternarySaturationResultName())); } - optionList.push_front(caf::PdmOptionItemInfo( RimDefines::undefinedResultName(), RimDefines::undefinedResultName() )); + for (int i = 0; i < perCellFaceOptionList.size(); i++) + { + if (showDerivedResultsFirstInList) + { + optionList.push_front(perCellFaceOptionList[i]); + } + else + { + optionList.push_back(perCellFaceOptionList[i]); + } + } + + optionList.push_front(caf::PdmOptionItemInfo(RimDefines::undefinedResultName(), RimDefines::undefinedResultName())); if (useOptionsOnly) *useOptionsOnly = true; @@ -342,3 +363,4 @@ void RimResultDefinition::updateFieldVisibility() } } } + diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index 7af2322a17..4856671a0b 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -59,8 +59,7 @@ class RimResultDefinition : public caf::PdmObject RimReservoirCellResultsStorage* currentGridCellResults() const; - - virtual QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly ); + virtual QList calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly); virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue); virtual void initAfterRead(); @@ -71,19 +70,19 @@ class RimResultDefinition : public caf::PdmObject friend class RimCellPropertyFilter; friend class RimFaultResultSlot; + // User interface only fields, to support "filtering"-like behaviour etc. caf::PdmField< caf::AppEnum< RimDefines::ResultCatType > > m_resultTypeUiField; caf::PdmField< caf::AppEnum< RimDefines::PorosityModelType > > m_porosityModelUiField; caf::PdmField m_resultVariableUiField; - - //mutable size_t m_gridScalarResultIndex; - caf::PdmPointer m_reservoirView; protected: void updateFieldVisibility(); + QList calculateValueOptionsForSpecifiedDerivedListPosition(bool showDerivedResultsFirstInList, const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly); + private: QStringList getResultVariableListForCurrentUIFieldSettings(); }; From 7d58e22b0cc2532a448cbdc79c20a46ea538d154 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 Sep 2014 08:50:42 +0200 Subject: [PATCH 325/346] Reverted clamping of computed SOIL value introduced in b7bc732b32fcc1bc58d47dbed4fa2074f4b651f0 --- .../ProjectDataModel/RimReservoirCellResultsStorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 146cfabd91..9a787d2114 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -564,7 +564,7 @@ void RimReservoirCellResultsStorage::computeSOILForTimeStep(size_t timeStepIndex soilValue -= swatForTimeStep->at(idx); } - soilForTimeStep[idx] = cvf::Math::clamp(soilValue, 0.0, 1.0); + soilForTimeStep[idx] = soilValue; } } From 8c259dcd5ee1f1c5e6210d3f0842f2ce53d512d6 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 Sep 2014 15:36:44 +0200 Subject: [PATCH 326/346] Octave interface test fixes Do not test for number of properties, as this now is dynamic Do not read out SOIL, as the changes in property handling does not support statistics for derived results, and SOIL is now part of the general derived results. --- .../OctaveScripts/OctaveInterfaceTest.m | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/OctavePlugin/OctaveScripts/OctaveInterfaceTest.m b/OctavePlugin/OctaveScripts/OctaveInterfaceTest.m index 63ddcb9753..0dfa441bc8 100644 --- a/OctavePlugin/OctaveScripts/OctaveInterfaceTest.m +++ b/OctavePlugin/OctaveScripts/OctaveInterfaceTest.m @@ -1,6 +1,7 @@ ### The case with caseid 1 has to be selected/active in ResInsight when running this test-script ### Coarsening and Dual porosity is not exercised by this tes yet. We need models + ### CaseInfo riGetCurrentCase() %!test %! printf ("===== Testing ====> riGetCurrentCase\n"); @@ -113,7 +114,6 @@ %! PropertyInfos2 = riGetPropertyNames(1); %! PropertyInfos3 = riGetPropertyNames("Matrix"); %! PropertyInfos4 = riGetPropertyNames(1, "Matrix"); -%! assert(rows(PropertyInfos1) == 26) %! assert(PropertyInfos1(1).PropName == "PRESSURE"); %! assert(PropertyInfos1(1).PropType == "DynamicNative"); %! assert(PropertyInfos1(26).PropType == "StaticNative"); @@ -121,29 +121,29 @@ ### Matrix[numActiveCells][numTimestepsRequested] riGetActiveCellProperty([CaseId], PropertyName, [RequestedTimeSteps], [PorosityModel = "Matrix"|"Fracture"]) %!test %! printf ("===== Testing ====> riGetActiveCellProperty\n"); -%! ActivePropData1 = riGetActiveCellProperty("SOIL"); +%! ActivePropData1 = riGetActiveCellProperty("SWAT"); %! assert (rows(ActivePropData1) == rows(riGetActiveCellInfo())); %! assert (columns(ActivePropData1) == rows(riGetTimeStepDays())); -%! ActivePropData2 = riGetActiveCellProperty("SOIL", "Matrix"); +%! ActivePropData2 = riGetActiveCellProperty("SWAT", "Matrix"); %! assert (ActivePropData2 == ActivePropData1); -%! ActivePropData3 = riGetActiveCellProperty("SOIL", [1,3]); +%! ActivePropData3 = riGetActiveCellProperty("SWAT", [1,3]); %! assert (columns(ActivePropData3) == 2); %! assert (ActivePropData3(:,2) == ActivePropData1(:,3)); -%! ActivePropData4 = riGetActiveCellProperty("SOIL", [1,3], "Matrix"); +%! ActivePropData4 = riGetActiveCellProperty("SWAT", [1,3], "Matrix"); %! assert (ActivePropData3 == ActivePropData4); -%! ActivePropData5 = riGetActiveCellProperty(1, "SOIL"); +%! ActivePropData5 = riGetActiveCellProperty(1, "SWAT"); %! assert (ActivePropData5 == ActivePropData1); -%! ActivePropData6 = riGetActiveCellProperty(1, "SOIL", [1,3]); +%! ActivePropData6 = riGetActiveCellProperty(1, "SWAT", [1,3]); %! assert (ActivePropData6 == ActivePropData3); -%! ActivePropData7 = riGetActiveCellProperty(1, "SOIL", [1,3], "Matrix"); +%! ActivePropData7 = riGetActiveCellProperty(1, "SWAT", [1,3], "Matrix"); %! assert (ActivePropData7 == ActivePropData3); -%! ActivePropData8 = riGetActiveCellProperty(1, "SOIL", "Matrix"); +%! ActivePropData8 = riGetActiveCellProperty(1, "SWAT", "Matrix"); %! assert (ActivePropData8 == ActivePropData1); ### Matrix[numI][numJ][numK][numTimestepsRequested] riGetGridProperty([CaseId], GridIndex , PropertyName, [RequestedTimeSteps], [PorosityModel = "Matrix"|"Fracture"]) %!test %! printf ("===== Testing ====> riGetGridProperty\n"); -%! GridProps1 = riGetGridProperty( 0 , "SOIL" ); +%! GridProps1 = riGetGridProperty( 0 , "SWAT" ); %! assert( ndims (GridProps1) == 4); %! [ni, nj, nk, nts ] = size(GridProps1); %! disp(nts); @@ -151,23 +151,23 @@ %! assert(ni == 139); %! assert(nj == 48); %! assert(nk == 9); -%! assert(GridProps1(62,30,1,3), 0.59058, 0.00001); +%! assert(GridProps1(62,30,1,3), 0.40942, 0.00001); -%! GridProps2 = riGetGridProperty( 0 , "SOIL", [1,3]); +%! GridProps2 = riGetGridProperty( 0 , "SWAT", [1,3]); %! assert( ndims (GridProps2) == 4); %! [ni, nj, nk, nts ] = size(GridProps2); %! assert(nts == 2); %! assert(ni == 139); %! assert(nj == 48); %! assert(nk == 9); -%! assert(GridProps2(62,30,1,2), 0.59058, 0.00001); +%! assert(GridProps2(62,30,1,2), 0.40942, 0.00001); -%! GridProps3 = riGetGridProperty( 0 , "SOIL", [1,3], "Matrix"); -%! GridProps4 = riGetGridProperty( 0 , "SOIL", "Matrix"); -%! GridProps5 = riGetGridProperty(1, 0 , "SOIL" ); -%! GridProps6 = riGetGridProperty(1, 0 , "SOIL", [1,3]); -%! GridProps7 = riGetGridProperty(1, 0 , "SOIL", [1,3], "Matrix"); -%! GridProps8 = riGetGridProperty(1, 0 , "SOIL", "Matrix"); +%! GridProps3 = riGetGridProperty( 0 , "SWAT", [1,3], "Matrix"); +%! GridProps4 = riGetGridProperty( 0 , "SWAT", "Matrix"); +%! GridProps5 = riGetGridProperty(1, 0 , "SWAT" ); +%! GridProps6 = riGetGridProperty(1, 0 , "SWAT", [1,3]); +%! GridProps7 = riGetGridProperty(1, 0 , "SWAT", [1,3], "Matrix"); +%! GridProps8 = riGetGridProperty(1, 0 , "SWAT", "Matrix"); %! assert(GridProps3 == GridProps2); %! assert(GridProps4 == GridProps1); @@ -180,8 +180,8 @@ ### riSetActiveCellProperty( Matrix[numActiveCells][numTimeSteps], [CaseId], PropertyName, [TimeStepIndices], [PorosityModel = "Matrix"|"Fracture"]) %!test %! printf ("===== Testing ====> riSetActiveCellProperty\n"); -%! ActivePropData1 = riGetActiveCellProperty("SOIL"); -%! ActivePropData3 = riGetActiveCellProperty("SOIL", [1,3]); +%! ActivePropData1 = riGetActiveCellProperty("SWAT"); +%! ActivePropData3 = riGetActiveCellProperty("SWAT", [1,3]); %! riSetActiveCellProperty( ActivePropData1, "PropertyName1" ); %! riSetActiveCellProperty( ActivePropData3, "PropertyName2", [1,3]); @@ -204,8 +204,8 @@ ### riSetGridProperty( Matrix[numI][numJ][numK][numTimeSteps], [CaseId], GridIndex, PropertyName, [TimeStepIndices], [PorosityModel = "Matrix"|"Fracture"]) %!test %! printf ("===== Testing ====> riSetGridProperty\n"); -%! GridProps1 = riGetGridProperty( 0 , "SOIL" ); -%! GridProps2 = riGetGridProperty( 0 , "SOIL", [1,3]); +%! GridProps1 = riGetGridProperty( 0 , "SWAT" ); +%! GridProps2 = riGetGridProperty( 0 , "SWAT", [1,3]); %! riSetGridProperty( GridProps1, 0, "PropertyName11" ); %! riSetGridProperty( GridProps2, 0, "PropertyName12", [1,3]); @@ -309,7 +309,7 @@ %! assert (WellNames2{113}, "P20-03"); ### Vector[WellCellInfo] riGetWellCells([CaseId], WellName, TimeStep) -%!xtest +%!test %! printf ("===== Testing ====> riGetWellCells\n"); %! WellNames1 = riGetWellNames(); %! WellCellInfos1 = riGetWellCells(1, WellNames1{1}, 3); @@ -317,7 +317,7 @@ ### Vector[WellStatus] riGetWellStatus ([CaseId], WellName, [RequestedTimeSteps]) -%!xtest +%!test %! printf ("===== Testing ====> riGetWellStatus\n"); %! WellNames1 = riGetWellNames(); %! WellStatuses1 = riGetWellStatus(1, WellNames1{1}, [1,3]); From e605ceafa22843a7bba4c0d60c455db7f9c4e6bb Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 8 Sep 2014 15:39:23 +0200 Subject: [PATCH 327/346] Socket server : Improved server logic --- ApplicationCode/SocketInterface/RiaSocketServer.cpp | 6 +++--- ApplicationCode/SocketInterface/RiaSocketServer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.cpp b/ApplicationCode/SocketInterface/RiaSocketServer.cpp index f27c0679b0..9820cb4883 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketServer.cpp @@ -86,7 +86,7 @@ RiaSocketServer::RiaSocketServer(QObject* parent) return; } - connect(m_nextPendingConnectionTimer, SIGNAL(timeout()), this, SLOT(handleNextPendingConnection())); + connect(m_nextPendingConnectionTimer, SIGNAL(timeout()), this, SLOT(slotNewClientConnection())); connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(slotNewClientConnection())); } @@ -114,7 +114,7 @@ void RiaSocketServer::slotNewClientConnection() { // If we are currently handling a connection, just ignore the new one until the current one is disconnected. - if (m_currentClient && (m_currentClient->state() == QAbstractSocket::ConnectedState) ) + if (m_currentClient && (m_currentClient->state() != QAbstractSocket::UnconnectedState) ) { //PMonLog("Starting Timer"); m_nextPendingConnectionTimer->start(); // Reset and start again @@ -318,7 +318,7 @@ void RiaSocketServer::terminateCurrentConnection() //-------------------------------------------------------------------------------------------------- void RiaSocketServer::handleNextPendingConnection() { - if (m_currentClient && (m_currentClient->state() == QAbstractSocket::ConnectedState) ) + if (m_currentClient && (m_currentClient->state() != QAbstractSocket::UnconnectedState) ) { //PMonLog("Starting Timer"); m_nextPendingConnectionTimer->start(); // Reset and start again diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.h b/ApplicationCode/SocketInterface/RiaSocketServer.h index 2b55424629..1b25984f28 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.h +++ b/ApplicationCode/SocketInterface/RiaSocketServer.h @@ -60,9 +60,9 @@ private slots: void slotNewClientConnection(); void slotCurrentClientDisconnected(); void slotReadyRead(); - void handleNextPendingConnection(); private: + void handleNextPendingConnection(); void terminateCurrentConnection(); bool readCommandFromOctave(); From 980207f4a74d7fc2d0024306b96f9824ecd70176 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 9 Sep 2014 07:12:43 +0200 Subject: [PATCH 328/346] Rename : Removed s from TRANS to TRAN to be in line with Eclipse naming --- .../ProjectDataModel/RimDefines.cpp | 4 +- ApplicationCode/ProjectDataModel/RimDefines.h | 18 +++---- .../RimReservoirCellResultsStorage.cpp | 52 +++++++++---------- .../RigCaseCellResultsData.cpp | 38 +++++++------- .../RigResultAccessorFactory.cpp | 16 +++--- .../UserInterface/RiuResultTextBuilder.cpp | 8 +-- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index ff6d54af22..6ec7f8db80 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -64,7 +64,7 @@ bool RimDefines::isPerCellFaceResult(const QString& resultName) { return true; } - else if (resultName.compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) + else if (resultName.compare(RimDefines::combinedRiTranResultName(), Qt::CaseInsensitive) == 0) { return true; } @@ -72,7 +72,7 @@ bool RimDefines::isPerCellFaceResult(const QString& resultName) { return true; } - else if (resultName.compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) + else if (resultName.compare(RimDefines::combinedRiAreaNormTranResultName(), Qt::CaseInsensitive) == 0) { return true; } diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 32eb08fac7..2403e13230 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -43,24 +43,24 @@ class RimDefines static QString undefinedResultName() { return "None"; } static QString undefinedGridFaultName() { return "Undefined grid faults"; } - static QString combinedTransmissibilityResultName() { return "TRANSXYZ"; } + static QString combinedTransmissibilityResultName() { return "TRANXYZ"; } static QString ternarySaturationResultName() { return "TERNARY"; } static QString combinedMultResultName() { return "MULTXYZ"; } - static QString riTransXResultName() { return "riTRANSX"; } - static QString riTransYResultName() { return "riTRANSY"; } - static QString riTransZResultName() { return "riTRANSZ"; } - static QString combinedRiTransResultName() { return "riTRANSXYZ"; } + static QString riTranXResultName() { return "riTRANX"; } + static QString riTranYResultName() { return "riTRANY"; } + static QString riTranZResultName() { return "riTRANZ"; } + static QString combinedRiTranResultName() { return "riTRANXYZ"; } static QString riMultXResultName() { return "riMULTX"; } static QString riMultYResultName() { return "riMULTY"; } static QString riMultZResultName() { return "riMULTZ"; } static QString combinedRiMultResultName() { return "riMULTXYZ"; } - static QString riAreaNormTransXResultName() { return "riTRANSXbyArea"; } - static QString riAreaNormTransYResultName() { return "riTRANSYbyArea"; } - static QString riAreaNormTransZResultName() { return "riTRANSZbyArea"; } - static QString combinedRiAreaNormTransResultName() { return "riTRANSXYZbyArea"; } + static QString riAreaNormTranXResultName() { return "riTRANXbyArea"; } + static QString riAreaNormTranYResultName() { return "riTRANYbyArea"; } + static QString riAreaNormTranZResultName() { return "riTRANZbyArea"; } + static QString combinedRiAreaNormTranResultName() { return "riTRANXYZbyArea"; } // Mock model text identifiers static QString mockModelBasic() { return "Result Mock Debug Model Simple"; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 9a787d2114..8f841378b5 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -282,16 +282,16 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result this->findOrLoadScalarResult(type, "MULTZ"); this->findOrLoadScalarResult(type, "MULTZ-"); } - else if (resultName == RimDefines::combinedRiTransResultName()) + else if (resultName == RimDefines::combinedRiTranResultName()) { - computeRiTransComponent(RimDefines::riTransXResultName()); - computeRiTransComponent(RimDefines::riTransYResultName()); - computeRiTransComponent(RimDefines::riTransZResultName()); + computeRiTransComponent(RimDefines::riTranXResultName()); + computeRiTransComponent(RimDefines::riTranYResultName()); + computeRiTransComponent(RimDefines::riTranZResultName()); computeNncCombRiTrans(); } - else if (resultName == RimDefines::riTransXResultName() - || resultName == RimDefines::riTransYResultName() - || resultName == RimDefines::riTransZResultName()) + else if (resultName == RimDefines::riTranXResultName() + || resultName == RimDefines::riTranYResultName() + || resultName == RimDefines::riTranZResultName()) { computeRiTransComponent(resultName); } @@ -309,16 +309,16 @@ size_t RimReservoirCellResultsStorage::findOrLoadScalarResult(RimDefines::Result { computeRiMULTComponent(resultName); } - else if (resultName == RimDefines::combinedRiAreaNormTransResultName()) + else if (resultName == RimDefines::combinedRiAreaNormTranResultName()) { - computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransXResultName()); - computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransYResultName()); - computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTransZResultName()); + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranXResultName()); + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranYResultName()); + computeRiTRANSbyAreaComponent(RimDefines::riAreaNormTranZResultName()); computeNncCombRiTRANSbyArea(); } - else if (resultName == RimDefines::riAreaNormTransXResultName() - || resultName == RimDefines::riAreaNormTransYResultName() - || resultName == RimDefines::riAreaNormTransZResultName()) + else if (resultName == RimDefines::riAreaNormTranXResultName() + || resultName == RimDefines::riAreaNormTranYResultName() + || resultName == RimDefines::riAreaNormTranZResultName()) { computeRiTRANSbyAreaComponent(resultName); } @@ -785,17 +785,17 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr cvf::StructGridInterface::FaceType faceId; QString permCompName; - if (riTransComponentResultName == RimDefines::riTransXResultName()) + if (riTransComponentResultName == RimDefines::riTranXResultName()) { permCompName = "PERMX"; faceId = cvf::StructGridInterface::POS_I; } - else if (riTransComponentResultName == RimDefines::riTransYResultName()) + else if (riTransComponentResultName == RimDefines::riTranYResultName()) { permCompName = "PERMY"; faceId = cvf::StructGridInterface::POS_J; } - else if (riTransComponentResultName == RimDefines::riTransZResultName()) + else if (riTransComponentResultName == RimDefines::riTranZResultName()) { permCompName = "PERMZ"; faceId = cvf::StructGridInterface::POS_K; @@ -947,7 +947,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() { if (!m_cellResults) return; - size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName()); + size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTranResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransScalarResultIndex)) return; double cdarchy = darchysValue(); @@ -1132,17 +1132,17 @@ void RimReservoirCellResultsStorage::computeRiMULTComponent(const QString& riMul if (riMultCompName == RimDefines::riMultXResultName()) { - riTransCompName = RimDefines::riTransXResultName(); + riTransCompName = RimDefines::riTranXResultName(); transCompName = "TRANX"; } else if (riMultCompName == RimDefines::riMultYResultName()) { - riTransCompName = RimDefines::riTransYResultName(); + riTransCompName = RimDefines::riTranYResultName(); transCompName = "TRANY"; } else if (riMultCompName == RimDefines::riMultZResultName()) { - riTransCompName = RimDefines::riTransZResultName(); + riTransCompName = RimDefines::riTranZResultName(); transCompName = "TRANZ"; } else @@ -1193,7 +1193,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiMULT() if (!m_cellResults) return; size_t riCombMultScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiMultResultName()); - size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName()); + size_t riCombTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTranResultName()); size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombMultScalarResultIndex)) return; @@ -1220,17 +1220,17 @@ void RimReservoirCellResultsStorage::computeRiTRANSbyAreaComponent(const QString cvf::StructGridInterface::FaceType faceId; QString transCompName; - if (riTransByAreaCompResultName == RimDefines::riAreaNormTransXResultName()) + if (riTransByAreaCompResultName == RimDefines::riAreaNormTranXResultName()) { transCompName = "TRANX"; faceId = cvf::StructGridInterface::POS_I; } - else if (riTransByAreaCompResultName == RimDefines::riAreaNormTransYResultName()) + else if (riTransByAreaCompResultName == RimDefines::riAreaNormTranYResultName()) { transCompName = "TRANY"; faceId = cvf::StructGridInterface::POS_J; } - else if (riTransByAreaCompResultName == RimDefines::riAreaNormTransZResultName()) + else if (riTransByAreaCompResultName == RimDefines::riAreaNormTranZResultName()) { transCompName = "TRANZ"; faceId = cvf::StructGridInterface::POS_K; @@ -1330,7 +1330,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTRANSbyArea() { if (!m_cellResults) return; - size_t riCombTransByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTransResultName()); + size_t riCombTransByAreaScResIdx = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTranResultName()); size_t combTransScalarResultIndex = m_cellResults->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); if (m_ownerMainGrid->nncData()->connectionScalarResult(riCombTransByAreaScResIdx)) return; diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 32defa4943..9ff66181b9 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -262,12 +262,12 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty statisticsCalculator = calc; } - else if (resultName == RimDefines::combinedRiTransResultName()) + else if (resultName == RimDefines::combinedRiTranResultName()) { cvf::ref calc = new RigMultipleDatasetStatCalc(); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName())); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName())); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranXResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranYResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranZResultName())); statisticsCalculator = calc; } else if (resultName == RimDefines::combinedRiMultResultName()) @@ -278,12 +278,12 @@ size_t RigCaseCellResultsData::addEmptyScalarResult(RimDefines::ResultCatType ty calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riMultZResultName())); statisticsCalculator = calc; } - else if (resultName == RimDefines::combinedRiAreaNormTransResultName()) + else if (resultName == RimDefines::combinedRiAreaNormTranResultName()) { cvf::ref calc = new RigMultipleDatasetStatCalc(); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransXResultName())); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransYResultName())); - calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransZResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranXResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranYResultName())); + calc->addNativeStatisticsCalculator(this, findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranZResultName())); statisticsCalculator = calc; } else @@ -557,10 +557,10 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() && findScalarResultIndex(RimDefines::STATIC_NATIVE, "PERMY") != cvf::UNDEFINED_SIZE_T && findScalarResultIndex(RimDefines::STATIC_NATIVE, "PERMZ") != cvf::UNDEFINED_SIZE_T) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName(), false, 0); - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName(), false, 0); - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName(), false, 0); - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTransResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTranXResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTranYResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riTranZResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiTranResultName(), false, 0); } } @@ -568,9 +568,9 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() { size_t tranX, tranY, tranZ; if (findTransmissibilityResults(tranX, tranY, tranZ) - && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransXResultName()) != cvf::UNDEFINED_SIZE_T - && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransYResultName()) != cvf::UNDEFINED_SIZE_T - && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTransZResultName()) != cvf::UNDEFINED_SIZE_T) + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranXResultName()) != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranYResultName()) != cvf::UNDEFINED_SIZE_T + && findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::riTranZResultName()) != cvf::UNDEFINED_SIZE_T) { addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riMultXResultName(), false, 0); addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riMultYResultName(), false, 0); @@ -583,23 +583,23 @@ void RigCaseCellResultsData::createPlaceholderResultEntries() { if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANX") != cvf::UNDEFINED_SIZE_T) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransXResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranXResultName(), false, 0); } if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANY") != cvf::UNDEFINED_SIZE_T) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransYResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranYResultName(), false, 0); } if (findScalarResultIndex(RimDefines::STATIC_NATIVE, "TRANZ") != cvf::UNDEFINED_SIZE_T) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTransZResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::riAreaNormTranZResultName(), false, 0); } size_t tranX, tranY, tranZ; if (findTransmissibilityResults(tranX, tranY, tranZ)) { - addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTransResultName(), false, 0); + addStaticScalarResult(RimDefines::STATIC_NATIVE, RimDefines::combinedRiAreaNormTranResultName(), false, 0); } } } diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index ff4ec35be8..f57991e0c4 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -79,13 +79,13 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } - else if (uiResultName == RimDefines::combinedRiTransResultName()) + else if (uiResultName == RimDefines::combinedRiTranResultName()) { cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransXResultName()); - cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransYResultName()); - cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTransZResultName()); + cvf::ref xTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTranXResultName()); + cvf::ref yTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTranYResultName()); + cvf::ref zTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riTranZResultName()); cellFaceAccessObject->setTransResultAccessors(xTransAccessor.p(), yTransAccessor.p(), zTransAccessor.p()); @@ -103,13 +103,13 @@ cvf::ref RigResultAccessorFactory::createResultAccessor(RigCa return cellFaceAccessObject; } - else if (uiResultName == RimDefines::combinedRiAreaNormTransResultName()) + else if (uiResultName == RimDefines::combinedRiAreaNormTranResultName()) { cvf::ref cellFaceAccessObject = new RigCombTransResultAccessor(grid); - cvf::ref xRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransXResultName()); - cvf::ref yRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransYResultName()); - cvf::ref zRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTransZResultName()); + cvf::ref xRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTranXResultName()); + cvf::ref yRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTranYResultName()); + cvf::ref zRiAreaNormTransAccessor = RigResultAccessorFactory::createNativeResultAccessor(eclipseCase, gridIndex, porosityModel, timeStepIndex, RimDefines::riAreaNormTranZResultName()); cellFaceAccessObject->setTransResultAccessors(xRiAreaNormTransAccessor.p(), yRiAreaNormTransAccessor.p(), zRiAreaNormTransAccessor.p()); diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp index beab91960e..ed3b73f009 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -392,9 +392,9 @@ void RiuResultTextBuilder::appendTextFromResultSlot(RigCaseData* eclipseCase, si resultInfoText->append(QString("MULTZ- : %1\n").arg(scalarValue)); } } - else if (resultSlot->resultVariable().compare(RimDefines::combinedRiTransResultName(), Qt::CaseInsensitive) == 0) + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiTranResultName(), Qt::CaseInsensitive) == 0) { - cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiTransResultName()); + cvf::ref transResultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiTranResultName()); { double scalarValue = transResultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); resultInfoText->append(QString("riTran X : %1\n").arg(scalarValue)); @@ -420,9 +420,9 @@ void RiuResultTextBuilder::appendTextFromResultSlot(RigCaseData* eclipseCase, si resultInfoText->append(QString("riMult Z : %1\n").arg(scalarValue)); } } - else if (resultSlot->resultVariable().compare(RimDefines::combinedRiAreaNormTransResultName(), Qt::CaseInsensitive) == 0) + else if (resultSlot->resultVariable().compare(RimDefines::combinedRiAreaNormTranResultName(), Qt::CaseInsensitive) == 0) { - cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiAreaNormTransResultName()); + cvf::ref resultAccessor = RigResultAccessorFactory::createResultAccessor(eclipseCase, gridIndex, porosityModel, 0, RimDefines::combinedRiAreaNormTranResultName()); { double scalarValue = resultAccessor->cellFaceScalar(cellIndex, cvf::StructGridInterface::POS_I); resultInfoText->append(QString("riTransByArea X : %1\n").arg(scalarValue)); From 078ae992bff9b7431f3f32cde06d3a34330014a7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 9 Sep 2014 07:26:28 +0200 Subject: [PATCH 329/346] Result info : Always show fault result details --- ApplicationCode/UserInterface/RiuResultTextBuilder.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp index ed3b73f009..cfc5d171e8 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -109,10 +109,7 @@ QString RiuResultTextBuilder::mainResultText() appendDetails(text, nncDetails()); - if (nncDetails().isEmpty()) - { - appendDetails(text, faultResultDetails()); - } + appendDetails(text, faultResultDetails()); appendDetails(text, cellEdgeResultDetails()); From 5ff55b49349bb71f852aaba0f30cf606ac862a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 10:58:02 +0200 Subject: [PATCH 330/346] riTRAN: Use cell center to cell face center vectors --- .../RimReservoirCellResultsStorage.cpp | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 8f841378b5..30874e7b6f 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -678,12 +678,10 @@ void RimReservoirCellResultsStorage::computeDepthRelatedResults() namespace RigTransmissibilityCalcTools { void calculateConnectionGeometry(const RigCell& c1, const RigCell& c2, const std::vector& nodes, - cvf::StructGridInterface::FaceType faceId, - cvf::Vec3d* faceCenter, cvf::Vec3d* faceAreaVec) + cvf::StructGridInterface::FaceType faceId, cvf::Vec3d* faceAreaVec) { - CVF_TIGHT_ASSERT(faceCenter && faceAreaVec); + CVF_TIGHT_ASSERT(faceAreaVec); - *faceCenter = cvf::Vec3d::ZERO; *faceAreaVec = cvf::Vec3d::ZERO; std::vector polygon; @@ -715,14 +713,6 @@ namespace RigTransmissibilityCalcTools realPolygon.push_back(intersections[polygon[pIdx] - nodes.size()]); } - // Polygon center - for (size_t pIdx = 0; pIdx < realPolygon.size(); ++pIdx) - { - *faceCenter += realPolygon[pIdx]; - } - - *faceCenter *= 1.0 / realPolygon.size(); - // Polygon area vector *faceAreaVec = cvf::GeometryTools::polygonAreaNormal3D(realPolygon); @@ -887,12 +877,11 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr if (isOnFault) { - calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, - &faceCenter, &faceAreaVec); + calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, &faceAreaVec); } else { - faceCenter = nativeCell.faceCenter(faceId); + faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); } @@ -903,7 +892,7 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Native cell half cell transm { - cvf::Vec3d centerToFace = faceCenter - nativeCell.center(); + cvf::Vec3d centerToFace = nativeCell.faceCenter(faceId) - nativeCell.center(); size_t permResIdx = (*permIdxFunc)(activeCellInfo, nativeResvCellIndex); double perm = permResults[permResIdx]; @@ -920,7 +909,7 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr // Neighbor cell half cell transm { - cvf::Vec3d centerToFace = faceCenter - neighborCell.center(); + cvf::Vec3d centerToFace = neighborCell.faceCenter(cvf::StructGridInterface::oppositeFace(faceId)) - neighborCell.center(); double perm = permResults[neighborCellPermResIdx]; @@ -1066,7 +1055,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() // Native cell half cell transm { - cvf::Vec3d centerToFace = faceCenter - nativeCell.center(); + cvf::Vec3d centerToFace = nativeCell.faceCenter(faceId) - nativeCell.center(); double perm = (*permResults)[nativeCellPermResIdx]; @@ -1082,7 +1071,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() // Neighbor cell half cell transm { - cvf::Vec3d centerToFace = faceCenter - neighborCell.center(); + cvf::Vec3d centerToFace = neighborCell.faceCenter(cvf::StructGridInterface::oppositeFace(faceId)) - neighborCell.center(); double perm = (*permResults)[neighborCellPermResIdx]; @@ -1301,16 +1290,13 @@ void RimReservoirCellResultsStorage::computeRiTRANSbyAreaComponent(const QString bool isOnFault = fault; cvf::Vec3d faceAreaVec; - cvf::Vec3d faceCenter; if (isOnFault) { - calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, - &faceCenter, &faceAreaVec); + calculateConnectionGeometry(nativeCell, neighborCell, nodes, faceId, &faceAreaVec); } else { - faceCenter = nativeCell.faceCenter(faceId); faceAreaVec = nativeCell.faceNormalWithAreaLenght(faceId); } From 4befec7897a351f021d5797e3f80ec552ae2b358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 10:58:41 +0200 Subject: [PATCH 331/346] Result Info: Always show the grid cell results --- ApplicationCode/UserInterface/RiuResultTextBuilder.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp index cfc5d171e8..863f38f498 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -113,11 +113,7 @@ QString RiuResultTextBuilder::mainResultText() appendDetails(text, cellEdgeResultDetails()); - bool isCustomFaultResultVisible = m_reservoirView->faultResultSettings()->showCustomFaultResult() && m_reservoirView->faultResultSettings()->hasValidCustomResult(); - if (isCustomFaultResultVisible) - { - appendDetails(text, gridResultDetails()); - } + appendDetails(text, gridResultDetails()); appendDetails(text, wellResultText()); From 2f22624228014a14ed83d35756b2b8a7b9231fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 13:07:01 +0200 Subject: [PATCH 332/346] Fixed problems in auto nnc on/off Consolidated Gui into Fault --- .../RivReservoirFaultsPartMgr.cpp | 26 +++++++++++++++---- .../ProjectDataModel/RimFaultCollection.cpp | 11 ++++++-- .../ProjectDataModel/RimFaultCollection.h | 1 + .../ProjectDataModel/RimFaultResultSlot.cpp | 22 ++-------------- .../ProjectDataModel/RimFaultResultSlot.h | 2 -- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 046527b5e4..222038536e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -30,7 +30,8 @@ #include "RimFaultResultSlot.h" #include "RimReservoirView.h" #include "RimResultSlot.h" - +#include "RimCase.h" +#include "RigCaseData.h" //-------------------------------------------------------------------------------------------------- /// @@ -93,8 +94,7 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) RimFaultCollection* faultCollection = m_reservoirView->faultCollection(); if (!faultCollection) return; - RimFaultResultSlot* faultResultSlot = m_reservoirView->faultResultSettings(); - + bool isShowingGrid = faultCollection->isGridVisualizationMode(); if (!faultCollection->showFaultCollection() && !isShowingGrid) return; @@ -141,15 +141,31 @@ void RivReservoirFaultsPartMgr::appendPartsToModel(cvf::ModelBasicList* model) } // Parts that is not overridden by the grid settings + RimFaultResultSlot* faultResultSlot = m_reservoirView->faultResultSettings(); + RimResultSlot* cellResultSlot = m_reservoirView->cellResult(); if (rimFault->showFault() && faultCollection->showFaultCollection()) { if (faultCollection->showNNCs()) { bool showNncs = true; - if (faultResultSlot->hideNncsWhenNoResultIsAvailable()) + if (faultCollection->hideNncsWhenNoResultIsAvailable()) { - showNncs = faultResultSlot->isNncResultAvailable(); + size_t scalarResultIndex = cvf::UNDEFINED_SIZE_T; + if (faultResultSlot->showCustomFaultResult()) + { + scalarResultIndex = faultResultSlot->customFaultResult()->scalarResultIndex(); + } + else + { + scalarResultIndex = cellResultSlot->scalarResultIndex(); + } + + RigMainGrid* mainGrid = m_reservoirView->eclipseCase()->reservoirData()->mainGrid(); + if (!(mainGrid && mainGrid->nncData()->hasScalarValues(scalarResultIndex))) + { + showNncs = false; + } } if (showNncs) diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index 31537e452b..e5404d59d1 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -69,7 +69,8 @@ RimFaultCollection::RimFaultCollection() cvf::Color3f defWellLabelColor = RiaApplication::instance()->preferences()->defaultWellLabelColor(); CAF_PDM_InitField(&faultLabelColor, "FaultLabelColor", defWellLabelColor, "Label color", "", "", ""); - CAF_PDM_InitField(&showNNCs, "ShowNNCs", false, "Show NNCs", "", "", ""); + CAF_PDM_InitField(&showNNCs, "ShowNNCs", true, "Show NNCs", "", "", ""); + CAF_PDM_InitField(&hideNncsWhenNoResultIsAvailable, "HideNncsWhenNoResultIsAvailable", true, "Hide NNC geometry if no NNC result is available", "", "", ""); CAF_PDM_InitFieldNoDefault(&noCommonAreaNnncCollection, "NoCommonAreaNnncCollection", "NNCs With No Common Area", "", "", ""); noCommonAreaNnncCollection = new RimNoCommonAreaNncCollection; @@ -109,7 +110,8 @@ void RimFaultCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel &m_showFaultsOutsideFilters == changedField || &faultLabelColor == changedField || &faultResult == changedField || - &showNNCs == changedField + &showNNCs == changedField || + &hideNncsWhenNoResultIsAvailable == changedField ) { if (m_reservoirView) @@ -337,6 +339,11 @@ void RimFaultCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi ffviz->add(&showFaultFaces); ffviz->add(&showOppositeFaultFaces); ffviz->add(&faultResult); + + caf::PdmUiGroup* nncViz = uiOrdering.addNewGroup("NNC Visibility"); + nncViz->add(&showNNCs); + nncViz->add(&hideNncsWhenNoResultIsAvailable); + } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index 18254497ae..d8fa62defc 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -75,6 +75,7 @@ class RimFaultCollection : public caf::PdmObject caf::PdmField showFaultCollection; caf::PdmField showNNCs; + caf::PdmField hideNncsWhenNoResultIsAvailable; caf::PdmPointersField faults; RimFault* findFaultByName(QString name); diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index d174223284..a85dd814ed 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -51,7 +51,6 @@ RimFaultResultSlot::RimFaultResultSlot() m_customFaultResult->m_porosityModelUiField.setOwnerObject(this); m_customFaultResult->m_resultVariableUiField.setOwnerObject(this); - CAF_PDM_InitField(&hideNncsWhenNoResultIsAvailable, "HideNncsWhenNoResultIsAvailable", true, "Hide NNC geometry if no NNC result is available", "", "", ""); updateFieldVisibility(); } @@ -148,25 +147,9 @@ QList RimFaultResultSlot::calculateValueOptions(const ca //-------------------------------------------------------------------------------------------------- bool RimFaultResultSlot::hasValidCustomResult() { - if (m_customFaultResult->hasResult() || m_customFaultResult->isTernarySaturationSelected()) + if (this->showCustomFaultResult()) { - return true; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RimFaultResultSlot::isNncResultAvailable() -{ - if (this->hasValidCustomResult()) - { - size_t scalarSetIndex = this->customFaultResult()->scalarResultIndex(); - - RigMainGrid* mainGrid = m_reservoirView->eclipseCase()->reservoirData()->mainGrid(); - if (mainGrid && mainGrid->nncData()->hasScalarValues(scalarSetIndex)) + if (m_customFaultResult->hasResult() || m_customFaultResult->isTernarySaturationSelected()) { return true; } @@ -174,4 +157,3 @@ bool RimFaultResultSlot::isNncResultAvailable() return false; } - diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index e7362fd6e3..0e30db8422 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -40,10 +40,8 @@ class RimFaultResultSlot : public caf::PdmObject void setReservoirView(RimReservoirView* ownerReservoirView); caf::PdmField showCustomFaultResult; - caf::PdmField hideNncsWhenNoResultIsAvailable; bool hasValidCustomResult(); - bool isNncResultAvailable(); RimResultSlot* customFaultResult(); void updateFieldVisibility(); From fff8f0c89be8fef6a0d9c5496b3cccc96883024e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 13:07:40 +0200 Subject: [PATCH 333/346] Changed gui name of Fault Result to Separate Fault Result --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index aaf6618c7b..81dc097c97 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -105,7 +105,7 @@ RimReservoirView::RimReservoirView() CAF_PDM_InitFieldNoDefault(&cellEdgeResult, "GridCellEdgeResult", "Cell Edge Result", ":/EdgeResult_1.png", "", ""); cellEdgeResult = new RimCellEdgeResultSlot(); - CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Fault Result", "", "", ""); + CAF_PDM_InitFieldNoDefault(&faultResultSettings, "FaultResultSettings", "Separate Fault Result", "", "", ""); faultResultSettings = new RimFaultResultSlot(); CAF_PDM_InitFieldNoDefault(&overlayInfoConfig, "OverlayInfoConfig", "Info Box", "", "", ""); From ed202cc7cfd0774cc79969da393918fe0ee0f523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 14:02:03 +0200 Subject: [PATCH 334/346] Combined TRAN results: Now set to 0.0 on border to inactive cells / grid border --- .../RigCombTransResultAccessor.cpp | 62 ++++++++++--------- .../RigCombTransResultAccessor.h | 2 +- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 715a073137..5b39efc2d0 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -55,6 +55,35 @@ double RigCombTransResultAccessor::cellScalar(size_t gridLocalCellIndex) const return HUGE_VAL; } +//-------------------------------------------------------------------------------------------------- +/// Get tran value from neighbor cell. Return 0.0 on active/inactive cell borders and end of grid +//-------------------------------------------------------------------------------------------------- +double RigCombTransResultAccessor::neighborCellTran(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId, const RigResultAccessor* transAccessor) const +{ + if (transAccessor != NULL) + { + size_t i, j, k, neighborGridCellIdx; + m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); + + if (m_grid->cellIJKNeighbor(i, j, k, faceId, &neighborGridCellIdx)) + { + double neighborCellValue = transAccessor->cellScalar(neighborGridCellIdx); + if (neighborCellValue == HUGE_VAL && transAccessor->cellScalar(gridLocalCellIndex) != HUGE_VAL) + { + return 0.0; + } + else + { + return neighborCellValue; + } + } + else + { + return 0.0; + } + } + return HUGE_VAL; +} //-------------------------------------------------------------------------------------------------- /// @@ -73,16 +102,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf break; case cvf::StructGridInterface::NEG_I: { - if (m_xTransAccessor.notNull()) - { - size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); - - if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_I, &neighborGridCellIdx)) - { - return m_xTransAccessor->cellScalar(neighborGridCellIdx); - } - } + return this->neighborCellTran(gridLocalCellIndex, cvf::StructGridInterface::NEG_I, m_xTransAccessor.p()); } break; case cvf::StructGridInterface::POS_J: @@ -95,16 +115,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf break; case cvf::StructGridInterface::NEG_J: { - if (m_yTransAccessor.notNull()) - { - size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); - - if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_J, &neighborGridCellIdx)) - { - return m_yTransAccessor->cellScalar(neighborGridCellIdx); - } - } + return this->neighborCellTran(gridLocalCellIndex, cvf::StructGridInterface::NEG_J, m_yTransAccessor.p()); } break; case cvf::StructGridInterface::POS_K: @@ -117,16 +128,7 @@ double RigCombTransResultAccessor::cellFaceScalar(size_t gridLocalCellIndex, cvf break; case cvf::StructGridInterface::NEG_K: { - if (m_zTransAccessor.notNull()) - { - size_t i, j, k, neighborGridCellIdx; - m_grid->ijkFromCellIndex(gridLocalCellIndex, &i, &j, &k); - - if (m_grid->cellIJKNeighbor(i, j, k, cvf::StructGridInterface::NEG_K, &neighborGridCellIdx)) - { - return m_zTransAccessor->cellScalar(neighborGridCellIdx); - } - } + return this->neighborCellTran(gridLocalCellIndex, cvf::StructGridInterface::NEG_K, m_zTransAccessor.p()); } break; } diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index 2ecdc6202c..c16bee4118 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -39,8 +39,8 @@ class RigCombTransResultAccessor : public RigResultAccessor virtual double cellScalar(size_t gridLocalCellIndex) const; virtual double cellFaceScalar(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId) const; - private: + double neighborCellTran(size_t gridLocalCellIndex, cvf::StructGridInterface::FaceType faceId, const RigResultAccessor* transAccessor) const; cvf::ref m_xTransAccessor; cvf::ref m_yTransAccessor; From c9065eeed93df19f4be06aadd90edefb4540b894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 15:20:16 +0200 Subject: [PATCH 335/346] Made mean calculation handle inf and nan --- .../ReservoirDataModel/RigStatisticsCalculator.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp index a35bac926e..9788bf73ea 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp @@ -131,11 +131,21 @@ void RigNativeStatCalc::valueSumAndSampleCount(double& valueSum, size_t& sampleC for (size_t tIdx = 0; tIdx < m_resultsData->timeStepCount(m_scalarResultIndex); tIdx++) { std::vector& values = m_resultsData->cellScalarResults(m_scalarResultIndex, tIdx); + size_t undefValueCount = 0; for (size_t cIdx = 0; cIdx < values.size(); ++cIdx) { - valueSum += values[cIdx]; + double value = values[cIdx]; + if (value == HUGE_VAL || value != value) + { + ++undefValueCount; + continue; + } + + valueSum += value; } + sampleCount += values.size(); + sampleCount -= undefValueCount; } } From 74f927e13f91d74f2917e9f3ff81b44bb5f2a99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 9 Sep 2014 15:21:09 +0200 Subject: [PATCH 336/346] riTRAN/MULT :Improved handling of invalid operations 0/0 etc. --- .../RimReservoirCellResultsStorage.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 30874e7b6f..24820f5aee 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -734,7 +734,14 @@ namespace RigTransmissibilityCalcTools //-------------------------------------------------------------------------------------------------- double newtran(double cdarchy, double mult, double halfCellTrans, double neighborHalfCellTrans) { - return cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); + if (cvf::Math::abs(halfCellTrans) < 1e-15 || cvf::Math::abs(neighborHalfCellTrans) < 1e-15) + { + return 0.0; + } + + double result = cdarchy * mult / ((1 / halfCellTrans) + (1 / neighborHalfCellTrans)); + CVF_TIGHT_ASSERT(result == result); + return result; } //-------------------------------------------------------------------------------------------------- @@ -923,7 +930,7 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr neighborHalfCellTrans = halfCellTransmissibility(perm, ntg, centerToFace, -faceAreaVec); } - riTransResults[tranResIdx] = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans);; + riTransResults[tranResIdx] = newtran(cdarchy, 1.0, halfCellTrans, neighborHalfCellTrans); } } @@ -1094,17 +1101,23 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() double riMult(double transResults, double riTransResults) { - // To make 0.0 values give 1.0 in mult value + if (transResults == HUGE_VAL || riTransResults == HUGE_VAL) return HUGE_VAL; - if (riTransResults == 0.0) + // To make 0.0 values give 1.0 in mult value + if (cvf::Math::abs (riTransResults) < 1e-12) { if (cvf::Math::abs (transResults) < 1e-12) { return 1.0; } + + return HUGE_VAL; } - return transResults / riTransResults; + + double result = transResults / riTransResults; + + return result; } //-------------------------------------------------------------------------------------------------- From c7888bc2d37b1a81815e088f7894c32b2162c062 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 Sep 2014 10:43:38 +0200 Subject: [PATCH 337/346] Fixed missing cell result color for static cell results --- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 81dc097c97..02733bb359 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -686,7 +686,7 @@ void RimReservoirView::createDisplayModel() // If the animation was active before recreating everything, make viewer view current frame - if (isAnimationActive) + if (isAnimationActive || cellResult->hasResult()) { m_viewer->slotSetCurrentFrame(m_currentTimeStep); } From b58862ad9324ad096fcab1652dbbaa1dfb697f4d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 Sep 2014 11:41:27 +0200 Subject: [PATCH 338/346] Do not try to set combined transmissibility if no nnc data is present --- ApplicationCode/ProjectDataModel/RimCase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index d2a5532ad0..9aa0325ed5 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -562,7 +562,10 @@ bool RimCase::openReserviorCase() // After the placeholder result for combined transmissibility is created, // make sure the nnc transmissibilities can be addressed by this scalarResultIndex as well size_t combinedTransResIdx = results->cellResults()->findScalarResultIndex(RimDefines::STATIC_NATIVE, RimDefines::combinedTransmissibilityResultName()); - reservoirData()->mainGrid()->nncData()->setCombTransmisibilityScalarResultIndex(combinedTransResIdx); + if (combinedTransResIdx != cvf::UNDEFINED_SIZE_T) + { + reservoirData()->mainGrid()->nncData()->setCombTransmisibilityScalarResultIndex(combinedTransResIdx); + } } } From 6e55ca82e2beef3b49f30ebda5c00a4428da3819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20St=C3=B8ren?= Date: Tue, 23 Sep 2014 12:24:48 +0200 Subject: [PATCH 339/346] Fixed Problem regarding negative riTrans values The reason was a bit sloppy detection of whether the surface normals was pointing outwards or inwards in a cell. The cells can be turned inside out due to depth/Z or mapaxis conditions. --- .../ModelVisualization/RivFaultPartMgr.cpp | 4 +-- .../RimReservoirCellResultsStorage.cpp | 6 ++-- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../ReservoirDataModel/RigGridBase.h | 2 +- .../ReservoirDataModel/RigMainGrid.cpp | 34 +++++++++++++++++-- .../ReservoirDataModel/RigMainGrid.h | 2 +- Fwk/AppFwk/CommonCode/cvfStructGrid.cpp | 2 +- Fwk/AppFwk/CommonCode/cvfStructGrid.h | 8 ++--- 8 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index f9d820ae75..e6846e563a 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -610,7 +610,7 @@ caf::FaceCulling RivFaultPartMgr::faceCullingMode() const { if (m_rimFaultCollection->faultResult() == RimFaultCollection::FAULT_BACK_FACE_CULLING) { - if (m_grid->mainGrid()->faceNormalsIsOutwards()) + if (m_grid->mainGrid()->isFaceNormalsOutwards()) { return caf::FC_BACK; } @@ -621,7 +621,7 @@ caf::FaceCulling RivFaultPartMgr::faceCullingMode() const } else if (m_rimFaultCollection->faultResult() == RimFaultCollection::FAULT_FRONT_FACE_CULLING) { - if (m_grid->mainGrid()->faceNormalsIsOutwards()) + if (m_grid->mainGrid()->isFaceNormalsOutwards()) { return caf::FC_FRONT; } diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 24820f5aee..3c93cdfb29 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -846,7 +846,7 @@ void RimReservoirCellResultsStorage::computeRiTransComponent(const QString& riTr const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); - bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); + bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards(); for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->cells().size(); nativeResvCellIndex++) { @@ -990,7 +990,7 @@ void RimReservoirCellResultsStorage::computeNncCombRiTrans() const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); - bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); + bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards(); // NNC calculation std::vector& nncConnections = m_ownerMainGrid->nncData()->connections(); @@ -1274,7 +1274,7 @@ void RimReservoirCellResultsStorage::computeRiTRANSbyAreaComponent(const QString const RigActiveCellInfo* activeCellInfo = m_cellResults->activeCellInfo(); const std::vector& nodes = m_ownerMainGrid->nodes(); - bool isFaceNormalsOutwards = m_ownerMainGrid->faceNormalsIsOutwards(); + bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards(); for (size_t nativeResvCellIndex = 0; nativeResvCellIndex < m_ownerMainGrid->cells().size(); nativeResvCellIndex++) { diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index a7ab0b6391..c727ecfcca 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -351,7 +351,7 @@ cvf::Vec3d RigGridBase::displayModelOffset() const //-------------------------------------------------------------------------------------------------- /// Returns the min size of the I and J charactristic cell sizes //-------------------------------------------------------------------------------------------------- -double RigGridBase::characteristicIJCellSize() +double RigGridBase::characteristicIJCellSize() const { double characteristicCellSize = HUGE_VAL; diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index 2ce18bd867..733de4ec99 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -60,7 +60,7 @@ class RigGridBase : public cvf::StructGridInterface void setGridId(int id) { m_gridId = id; } int gridId() const { return m_gridId; } - double characteristicIJCellSize(); + double characteristicIJCellSize() const; std::string gridName() const; void setGridName(const std::string& gridName); diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index 118f22fb3b..eca3f8e973 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -363,9 +363,39 @@ void RigMainGrid::calculateFaults() /// The cell is normally inverted due to Depth becoming -Z at import, /// but if (only) one of the flipX/Y is done, the cell is back to normal //-------------------------------------------------------------------------------------------------- -bool RigMainGrid::faceNormalsIsOutwards() const +bool RigMainGrid::isFaceNormalsOutwards() const { - return m_flipXAxis ^ m_flipYAxis; + + for (int gcIdx = 0 ; gcIdx < static_cast(m_cells.size()); ++gcIdx) + { + if (!m_cells[gcIdx].isInvalid()) + { + cvf::Vec3d cellCenter = m_cells[gcIdx].center(); + cvf::Vec3d faceCenter = m_cells[gcIdx].faceCenter(StructGridInterface::POS_I); + cvf::Vec3d faceNormal = m_cells[gcIdx].faceNormalWithAreaLenght(StructGridInterface::POS_I); + + double typicalIJCellSize = characteristicIJCellSize(); + double dummy, dummy2, typicalKSize; + characteristicCellSizes(&dummy, &dummy2, &typicalKSize); + + if ( (faceCenter - cellCenter).length() > 0.2 * typicalIJCellSize + && (faceNormal.length() > (0.2 * typicalIJCellSize * 0.2* typicalKSize))) + { + // Cell is assumed ok to use, so calculate whether the normals are outwards or inwards + + if ((faceCenter - cellCenter) * faceNormal >= 0) + { + return true; + } + else + { + return false; + } + } + } + } + + return false; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index 525293239b..8b0210d2ea 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -52,7 +52,7 @@ class RigMainGrid : public RigGridBase const cvf::Collection& faults() { return m_faults; } void calculateFaults(); const RigFault* findFaultFromCellIndexAndCellFace(size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face) const; - bool faceNormalsIsOutwards() const; + bool isFaceNormalsOutwards() const; void computeCachedData(); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp b/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp index 9575d3afb4..708e3ad558 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGrid.cpp @@ -220,7 +220,7 @@ cvf::Vec3d StructGridInterface::displayModelOffset() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void StructGridInterface::characteristicCellSizes(double* iSize, double* jSize, double* kSize) +void StructGridInterface::characteristicCellSizes(double* iSize, double* jSize, double* kSize) const { CVF_ASSERT(iSize && jSize && kSize); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGrid.h b/Fwk/AppFwk/CommonCode/cvfStructGrid.h index 8f6019bdc9..0ed191f09a 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGrid.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGrid.h @@ -84,7 +84,7 @@ class StructGridInterface : public Object virtual cvf::Vec3d minCoordinate() const = 0; virtual cvf::Vec3d maxCoordinate() const = 0; - void characteristicCellSizes(double* iSize, double* jSize, double* kSize); + void characteristicCellSizes(double* iSize, double* jSize, double* kSize) const; virtual cvf::Vec3d displayModelOffset() const; @@ -109,9 +109,9 @@ class StructGridInterface : public Object static void neighborIJKAtCellFace(size_t i, size_t j, size_t k, StructGridInterface::FaceType face, size_t* ni, size_t* nj, size_t* nk); private: - double m_characteristicCellSizeI; - double m_characteristicCellSizeJ; - double m_characteristicCellSizeK; + mutable double m_characteristicCellSizeI; + mutable double m_characteristicCellSizeJ; + mutable double m_characteristicCellSizeK; }; } // namespace cvf From eb43a1e6ae9c23c3645e582f8ba4524d53fcf6f5 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 Sep 2014 13:46:20 +0200 Subject: [PATCH 340/346] Removed documentation folder. Doc is now available at resinsight.org --- Documentation/UsersGuide/BatchCommands.md | 48 ---- .../UsersGuide/CaseGroupsAndStatistics.md | 82 ------- .../UsersGuide/CommandLineParameters.md | 24 -- Documentation/UsersGuide/Faults.md | 88 ------- Documentation/UsersGuide/GettingStarted.md | 167 ------------- Documentation/UsersGuide/Installation.md | 28 --- Documentation/UsersGuide/OctaveInterface.md | 42 ---- .../UsersGuide/OctaveInterfaceReference.md | 222 ------------------ Documentation/UsersGuide/README.md | 73 ------ .../UsersGuide/RegressionTestSystem.md | 48 ---- Documentation/UsersGuide/ReservoirViews.md | 147 ------------ Documentation/UsersGuide/UsersGuide.md | 32 --- Documentation/UsersGuide/WellPaths.md | 74 ------ .../UsersGuide/images/3DViewOverview.png | Bin 114626 -> 0 bytes .../UsersGuide/images/AppLogo48x48.png | Bin 3337 -> 0 bytes Documentation/UsersGuide/images/Case24x24.png | Bin 1159 -> 0 bytes .../UsersGuide/images/CaseProperties.png | Bin 4984 -> 0 bytes .../UsersGuide/images/CellEdgeExample.png | Bin 40965 -> 0 bytes .../UsersGuide/images/CellFilter_Range.png | Bin 583 -> 0 bytes .../UsersGuide/images/CellFilter_Values.png | Bin 843 -> 0 bytes .../UsersGuide/images/CellResult.png | Bin 491 -> 0 bytes .../images/CreateGridCaseGroup16x16.png | Bin 669 -> 0 bytes .../images/CreateGridCaseGroup24x24.png | Bin 1260 -> 0 bytes .../CreateGridCaseGroupFromFileDialog.png | Bin 13792 -> 0 bytes .../UsersGuide/images/EclipseInput24x24.png | Bin 1120 -> 0 bytes .../UsersGuide/images/EdgeResult_1.png | Bin 295 -> 0 bytes .../ExecuteOctaveScriptOnSelectedCases.png | Bin 20051 -> 0 bytes .../UsersGuide/images/ExportProperty.png | Bin 8790 -> 0 bytes .../UsersGuide/images/FaultProperties.png | Bin 321741 -> 0 bytes .../UsersGuide/images/GridCaseGroup24x24.png | Bin 986 -> 0 bytes .../UsersGuide/images/GridCaseGroupTree.png | Bin 3581 -> 0 bytes .../UsersGuide/images/Histogram24x24.png | Bin 636 -> 0 bytes .../UsersGuide/images/HistogramExample.png | Bin 578 -> 0 bytes .../UsersGuide/images/InfoBox16x16.png | Bin 454 -> 0 bytes Documentation/UsersGuide/images/Legend.png | Bin 228 -> 0 bytes .../images/MSWDummyBranchExample.png | Bin 37123 -> 0 bytes .../UsersGuide/images/OctaveScriptTree.png | Bin 3476 -> 0 bytes .../images/PropertyFilterProperties.png | Bin 10119 -> 0 bytes .../images/RangeFilterProperties.png | Bin 10647 -> 0 bytes .../images/RegressionTestDialog.png | Bin 297802 -> 0 bytes .../images/ResInsightUIFullSize.png | Bin 220111 -> 0 bytes .../images/ResInsightUIFullSizeWindows.png | Bin 280111 -> 0 bytes .../images/ResInsightUIMediumSize.png | Bin 332035 -> 0 bytes .../images/ResInsightUISmallSizeWindows.png | Bin 74496 -> 0 bytes .../UsersGuide/images/ReservoirView.png | Bin 461 -> 0 bytes .../UsersGuide/images/RestoreDown.PNG | Bin 13237 -> 0 bytes .../images/SimulationWellsProperties.png | Bin 16246 -> 0 bytes Documentation/UsersGuide/images/SnapShot.png | Bin 1452 -> 0 bytes .../UsersGuide/images/SnapShotSave.png | Bin 1552 -> 0 bytes .../UsersGuide/images/SnapShotSaveViews.png | Bin 1745 -> 0 bytes .../images/StatisticsCaseProperties.png | Bin 10498 -> 0 bytes .../StatisticsCasePropertiesCalculated.png | Bin 5760 -> 0 bytes Documentation/UsersGuide/images/TopLink.png | Bin 554 -> 0 bytes .../UsersGuide/images/TreeViewToggle.png | Bin 1399 -> 0 bytes .../UsersGuide/images/WellCollection.png | Bin 554 -> 0 bytes .../images/WellPathCollectionProperties.png | Bin 8684 -> 0 bytes .../UsersGuide/images/WellProperties.png | Bin 6967 -> 0 bytes .../UsersGuide/images/WellsInTree.png | Bin 8076 -> 0 bytes .../images/draw_style_faults_24x24.png | Bin 1647 -> 0 bytes .../images/draw_style_faults_label_24x24.png | Bin 1448 -> 0 bytes .../images/draw_style_surface_24x24.png | Bin 551 -> 0 bytes .../draw_style_surface_w_fault_mesh_24x24.png | Bin 886 -> 0 bytes 62 files changed, 1075 deletions(-) delete mode 100644 Documentation/UsersGuide/BatchCommands.md delete mode 100644 Documentation/UsersGuide/CaseGroupsAndStatistics.md delete mode 100644 Documentation/UsersGuide/CommandLineParameters.md delete mode 100644 Documentation/UsersGuide/Faults.md delete mode 100644 Documentation/UsersGuide/GettingStarted.md delete mode 100644 Documentation/UsersGuide/Installation.md delete mode 100644 Documentation/UsersGuide/OctaveInterface.md delete mode 100644 Documentation/UsersGuide/OctaveInterfaceReference.md delete mode 100644 Documentation/UsersGuide/README.md delete mode 100644 Documentation/UsersGuide/RegressionTestSystem.md delete mode 100644 Documentation/UsersGuide/ReservoirViews.md delete mode 100644 Documentation/UsersGuide/UsersGuide.md delete mode 100644 Documentation/UsersGuide/WellPaths.md delete mode 100644 Documentation/UsersGuide/images/3DViewOverview.png delete mode 100644 Documentation/UsersGuide/images/AppLogo48x48.png delete mode 100644 Documentation/UsersGuide/images/Case24x24.png delete mode 100644 Documentation/UsersGuide/images/CaseProperties.png delete mode 100644 Documentation/UsersGuide/images/CellEdgeExample.png delete mode 100644 Documentation/UsersGuide/images/CellFilter_Range.png delete mode 100644 Documentation/UsersGuide/images/CellFilter_Values.png delete mode 100644 Documentation/UsersGuide/images/CellResult.png delete mode 100644 Documentation/UsersGuide/images/CreateGridCaseGroup16x16.png delete mode 100644 Documentation/UsersGuide/images/CreateGridCaseGroup24x24.png delete mode 100644 Documentation/UsersGuide/images/CreateGridCaseGroupFromFileDialog.png delete mode 100644 Documentation/UsersGuide/images/EclipseInput24x24.png delete mode 100644 Documentation/UsersGuide/images/EdgeResult_1.png delete mode 100644 Documentation/UsersGuide/images/ExecuteOctaveScriptOnSelectedCases.png delete mode 100644 Documentation/UsersGuide/images/ExportProperty.png delete mode 100644 Documentation/UsersGuide/images/FaultProperties.png delete mode 100644 Documentation/UsersGuide/images/GridCaseGroup24x24.png delete mode 100644 Documentation/UsersGuide/images/GridCaseGroupTree.png delete mode 100644 Documentation/UsersGuide/images/Histogram24x24.png delete mode 100644 Documentation/UsersGuide/images/HistogramExample.png delete mode 100644 Documentation/UsersGuide/images/InfoBox16x16.png delete mode 100644 Documentation/UsersGuide/images/Legend.png delete mode 100644 Documentation/UsersGuide/images/MSWDummyBranchExample.png delete mode 100644 Documentation/UsersGuide/images/OctaveScriptTree.png delete mode 100644 Documentation/UsersGuide/images/PropertyFilterProperties.png delete mode 100644 Documentation/UsersGuide/images/RangeFilterProperties.png delete mode 100644 Documentation/UsersGuide/images/RegressionTestDialog.png delete mode 100644 Documentation/UsersGuide/images/ResInsightUIFullSize.png delete mode 100644 Documentation/UsersGuide/images/ResInsightUIFullSizeWindows.png delete mode 100644 Documentation/UsersGuide/images/ResInsightUIMediumSize.png delete mode 100644 Documentation/UsersGuide/images/ResInsightUISmallSizeWindows.png delete mode 100644 Documentation/UsersGuide/images/ReservoirView.png delete mode 100644 Documentation/UsersGuide/images/RestoreDown.PNG delete mode 100644 Documentation/UsersGuide/images/SimulationWellsProperties.png delete mode 100644 Documentation/UsersGuide/images/SnapShot.png delete mode 100644 Documentation/UsersGuide/images/SnapShotSave.png delete mode 100644 Documentation/UsersGuide/images/SnapShotSaveViews.png delete mode 100644 Documentation/UsersGuide/images/StatisticsCaseProperties.png delete mode 100644 Documentation/UsersGuide/images/StatisticsCasePropertiesCalculated.png delete mode 100644 Documentation/UsersGuide/images/TopLink.png delete mode 100644 Documentation/UsersGuide/images/TreeViewToggle.png delete mode 100644 Documentation/UsersGuide/images/WellCollection.png delete mode 100644 Documentation/UsersGuide/images/WellPathCollectionProperties.png delete mode 100644 Documentation/UsersGuide/images/WellProperties.png delete mode 100644 Documentation/UsersGuide/images/WellsInTree.png delete mode 100644 Documentation/UsersGuide/images/draw_style_faults_24x24.png delete mode 100644 Documentation/UsersGuide/images/draw_style_faults_label_24x24.png delete mode 100644 Documentation/UsersGuide/images/draw_style_surface_24x24.png delete mode 100644 Documentation/UsersGuide/images/draw_style_surface_w_fault_mesh_24x24.png diff --git a/Documentation/UsersGuide/BatchCommands.md b/Documentation/UsersGuide/BatchCommands.md deleted file mode 100644 index 26cf3f0a57..0000000000 --- a/Documentation/UsersGuide/BatchCommands.md +++ /dev/null @@ -1,48 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------- -## Batch Commands - -ResInsight supports several commands useful in a batch setting. These examples are available from the [test section](https://github.com/OPM/ResInsight/tree/master/TestModels/Case_with_10_timesteps). - -See also [ Command Line Arguments](CommandLineParameters.md) for an overview of all command line arguments. - -### Example 1 : Create snapshots of all views for multiple cases -A list of cases is defined in **CaseList.txt**, containing the following - - Real0/BRUGGE_0000.EGRID - Real10/BRUGGE_0010.EGRID - Real30/BRUGGE_0030.EGRID - Real40/BRUGGE_0040.EGRID - -The command line used to run this example is shown here: - - ResInsight --project BatchTest.rsp --multiCaseSnapshots CaseList.txt --size 500 500 - -This will instruct ResInsight to read the project file **BatchTest.rsp**. All cases will be replaced one by one in ResInsight, and snapshots of all views will be written to file. - - -### Example 2 : Replace a single case and take snapshots of all views - -The command line used to run this example is shown here: - - ResInsight --project BatchTest.rsp --replaceCase "Real10\BRUGGE_0010.EGRID" --savesnapshots - -This will instruct ResInsight to read the project file **BatchTest.rsp**. The specified case **Real10\BRUGGE_0010.EGRID** will be imported into the project, and snapshots of all views will be written to file. - - -### Example 3 : Replace source cases in a case group and create snapshot -A list of cases is defined in **CaseList2.txt**, containing the following - - Real0/BRUGGE_0000.EGRID - Real10/BRUGGE_0010.EGRID - -The command line used to run this example is shown here: - - ResInsight --project BatchStatistics.rsp --replaceSourceCases CaseList2.txt --savesnapshots - -This will instruct ResInsight to read the project file **BatchTest.rsp**. All cases specified will be imported in the case group specified in the project file. Statistics will be computed, and snapshots for all views will be written to file. - - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/CaseGroupsAndStatistics.md b/Documentation/UsersGuide/CaseGroupsAndStatistics.md deleted file mode 100644 index e3671de86c..0000000000 --- a/Documentation/UsersGuide/CaseGroupsAndStatistics.md +++ /dev/null @@ -1,82 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ - -## Grid Case Groups and Statistics - -![](images/GridCaseGroupTree.png) - -**Grid Case Group**'s are designed to make it easy to calculate statistics per cell and per timestep of a large number of Eclipse simulation Cases with identical Grids (often labeled *realizations*). - -If you have several Eclipse simulations with different input parameters available, you can put all the realizations into a Grid Case Group and easily calculate each of the cells mean value, range and max/min values at each timestep between the realizations. - -### Creating Grid Case Groups -#### From files -The easiest way to create a **Grid Case Group** is to use the Import command: -**File->Import->Create Grid Case Group from Files** - -An import dialog is opened: -![](images/CreateGridCaseGroupFromFileDialog.png) - -1. Add one or more search folders to the list on the left. -2. The *.EGRID or *.GRID files found in these directories and sub directories are shown in the list to the right. -3. If you want to remove some *.EGRID files from the list, select them and press the **Remove** button. -4. When you are ready, press the **OK** button. - -ResInsight then creates a **Grid Case Group** for you, and populates its **Source Cases** with the Cases you selected. Then the first of those Cases are read completely, while the others are just scanned to verify that the Grids match and to detect changes in the Active Cells layout. - -This makes it quite fast to lo ad even a quite large number of realizations. - -#### Manually - -A Grid Case Group can be created from the context menu available when right clicking a Result Case, Input Case or a different Grid Case Group. **Source Cases** can then be added by using the mouse to *drag and drop* cases with equal grids into the **Grid Case Group**'s **Source Case** folder. -This is useful if you want to create statistics based only on a subset of the source cases in an already created **Grid Case Group**. - -**Drag and Drop** of cases will normally copy the cases to the new destination, but moving them is possible by pressing and holding the **Shift** key while dropping. - -### Viewing special Source Cases -To reduce the number of views, only a view for the first case is created automatically. If you want to inspect the results of a particular source case, right click the case and select **New view** from the context menu. A new 3D View will the be created on that particular case. - -*TIP:* To reduce memory usage, project loading time etc. it is vise to delete the 3D Views you do not need. 3D Views use a lot of system resources. - -### Statistics ## -After creating a grid case group, an empty **Statistics Case** is created for you in the **Derived Statistics** folder of the **Grid Case Group**. - -#### Setting up and Calculate -The properties of an uncalculated and a calculated **Statistics Case** is shown below: - -![](images/StatisticsCaseProperties.png) ![](images/StatisticsCasePropertiesCalculated.png) - -- **Compute**: Starts to calculate requested statistical Properties. -- **Edit** : Deletes the calculated results, and makes the controls to edit the setup available. -- **Summary of calculation setup** : Summarizes what to calculate -- **Properties to consider**: These options makes it possible to select what Eclipse properties to include in the Statistical calculations. Adding variables increase the memory usage and the computational time. -- **Percentile Setup**: Selects whether to calculate percentiles, what method and what percentile levels should be used. Turning this off speeds up the calculations. -- **Well Data Source Case**: This option selects which set of **Simulation Wells** to be shown along with the statistical results. You can select one of the **Source Cases**. - -##### Percentile Methods - -Three Percentile methods are implemented: - -- **Interpolated Observation** -The values are sorted, and the two observations representing the probabilities closest to the percentile are interpolated to find the value for the percentile. This is the default method. -- **Nearest Observation** -The values are sorted, and the first observation representing a probability higher or equal to the percentile probability is selected as the value for the percentile. This method is by some considered to be statistically more puristic. -- **Histogram based estimate** -A histogram is created and the percentile is calculated based on the histogram. This method will be faster when having a large number of realizations, because no value sorting is involved. You would however need several hundred realizations before this method should be considered. - - -#### Viewing the results -When the computation is complete, you have to create a 3D View on the **Statistics Case** to view the results. Use the Context menu available by right clicking the **Statistics Case** to create it. - -#### Adding Statistics Cases -A new statistical calculation can be created by activating the context menu for **Derived Statistic->New Statistics Case**. - ------- -[ Contents ](UsersGuide.md#contents) - - - - - - diff --git a/Documentation/UsersGuide/CommandLineParameters.md b/Documentation/UsersGuide/CommandLineParameters.md deleted file mode 100644 index 968a772869..0000000000 --- a/Documentation/UsersGuide/CommandLineParameters.md +++ /dev/null @@ -1,24 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------- -## Command Line Parameters # - -| Parameter | Description | -|-----------|-------------| -| `--last` | Open last used project. | -| `--project ` | Open project file . | -| `--case ` | Import Eclipse case (do not include .GRID/.EGRID) | -| `--startdir ` | Set startup directory. | -| `--savesnapshots` | Save snapshot of all views to 'snapshots' folder in project file folder. Application closes after snapshots have been written. | -| `--size ` | Set size of the main application window. | -| `--replaceCase [] ` | Replace grid in or first case with . | -| `--replaceSourceCases [] ` | Replace source cases in or first grid case group with the grid files listed in the file. | -| `--multiCaseSnapshots ` | For each grid file listed in the file, replace the first case in the project and save snapshot of all views. | -| `--help, -?` | Displays help text and version info | -| `--regressiontest ` | Run a regression test on all sub-folders starting with `TestCase*` of the given folder. **RegressionTest.rip** files in the sub-folders will be opened and snapshots of all the views is written to the sub-sub-folder **RegTestGeneratedImages**. Then difference images is generated in the sub-sub-folder **RegTestDiffImages** based on the images in sub-sub-folder **RegTestBaseImages**. The results are presented in **ResInsightRegressionTestReport.html** that is written in the given folder. | -| `--updateregressiontestbase ` | For all sub-folders starting with `TestCase*`, copy the images in the sub-sub-folder **RegTestGeneratedImages** to the sub-sub-folder **RegTestBaseImages** after deleting **RegTestBaseImages** completely. | - -See also the [Regression Test System ](RegressionTestSystem.md) for a more in-depth explanation. - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/Faults.md b/Documentation/UsersGuide/Faults.md deleted file mode 100644 index 5ce0bc92f7..0000000000 --- a/Documentation/UsersGuide/Faults.md +++ /dev/null @@ -1,88 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Faults - -ResInsight will detect all the cell faces with no geometrically matching neighbors, and display them as *Faults*. -This means that the are drawn in special ways, and that their visual appearance can be controlled separately from the rest of the grid. - -### Fault Names and NNC - -#### Import of Fault info from `*.DATA`-files -If enabled, ResInsight will also import fault information from the `*.DATA` files and use this information to group the detected faces into named items which is available in the ![](images/draw_style_faults_24x24.png) **Faults** item in the **Project Tree**. The imported faults are ordered in ascending order based on their name. - -> -***Note:*** As import of faults can be time consuming, reading of faults can be disabled from **Preferences -> Read fault data** - -#### Undefined grid faults -All the detected cell faces are compared to the faults imported from the `*.DATA` file in order to group them. If a particular face is *not* found among the fault faces defined in the `*.DATA` file or it's opposite face, the cell face is added to a fault called **Undefined grid faults**. This particular Fault will always be present, even if reading of the `*.DATA` file is disabled. - -#### Fault color - -Each named Fault is given a color on import. This color can be controlled by selecting the fault and edit its **Fault color** in the **Property Editor.** - -#### NNC visualization -ResInsight will read Non Neighbor Connections from the Eclipse output file (`*.INIT`), and create explicit visualizations of those witch have a common surface area. These NNC's are then sorted onto the Fault's and their visibility is controlled from the **Property Editor** of the **Faults** Item in the **Project Tree**. - -The color of the NNC faces are set to be a bit lighter than their corresponding named fault, and can not be controlled directly. - -Currently the only result property that is mapped onto the NNC is the static TRANSXYZ property which displays the transmissibility associated to each face. - -### Picking info - -When clicking on a cell face that is member of a fault, the fault name is displayed in the **Result Info** window, along with cell, and result property info. - -When clicking on a NNC, the relevant data for this NNC is displayed. - -### Fault visualization options - - -#### Toolbar control -Visualization mode and mesh lines can be controlled from the toolbar. - -- ![](images/draw_style_faults_24x24.png) **Faults-Only** visualization mode. -
When turned on, this option hides all the grid cells, and shows only the fault faces in the reservoir limited by the applied range and property filters. (Unless **Show faults outside filters** are turned on. See below.) -- ![](images/draw_style_surface_24x24.png) Turns faces on and mesh off -- ![](images/draw_style_surface_w_fault_mesh_24x24.png) Turns on all faces, and shows meshlines on faults only. -
This is a useful method to highlight the faults in your reservoir, because the faults stands out with black outlining. -- ![](images/draw_style_faults_label_24x24.png) Shows labels for faults - -#### Common Fault Options -By clicking the ![](images/draw_style_faults_24x24.png) **Faults** item in the **Project Tree**, the following options common to all the faults are displayed: - - ![](images/FaultProperties.png) - -##### Fault labels -- **Show labels**: Displays one label per fault with the name defined in the `*.DATA`-file -- **Label color**: Defines the label color - -##### Fault options -- **Show faults outside filters**: Turning this option on, will display faults outside the filter region, making the fault visualization completely ignore the Range and Property filters in action. -- **Show results on faults**: This toggle controls whether to show the selected result property on the faults or not. This should normally be left on. -- **Show NNCs**: Toggles whether to display the Non Neighbor Connections, or not. - -##### Fault Face Visibility -This group of options controls the visibility of the fault faces. Since they work together, and in some cases are overridden by the system, they can be a bit confusing. - -First of all. These options are only available in **Faults-only** visualization mode. ( See *Toolbar Control* above) When not in **Faults-Only** mode, ResInsight overrides the options, and the controls are inactive. - -Secondly: The option you would normally want to adjust is **Dynamic Face Selection** (See below). - -- **Show defined faces**: Displays the fault cell faces that are defined on the Eclipse input file (`*.DATA`) -- **Show opposite faces**: Displays the opposite fault cell faces from what is defined on the input file, based on IJK neighbors. -
*These two options should normally be left **On***.
They are useful when investigating the exact faults information provided on the `*.DATA` file. -
If you need to use them, it is normally wise to set the **Dynamic Face Selection** to "Show Both" - -######Dynamic Face Selection: - -At one particular position on a fault there are usually two cells competing for your attention: The cell closer to you as the viewer, or the one further from you. When showing results, this becomes important because these two cell faces have different result property values, and thus color. - -This option controls which of the two cell faces you actually can see: The one behind the fault, or the one in front of the fault. There is also an option of showing both, which will give you an undefined mixture, making it hard to be certain what you see. - -This means that ResInsight turns on or off the faces based on your view position and this option to make sure that you always see the faces (and thus the result property) you request. - - ------- -[ Contents ](UsersGuide.md#contents) - - diff --git a/Documentation/UsersGuide/GettingStarted.md b/Documentation/UsersGuide/GettingStarted.md deleted file mode 100644 index 7828975ed8..0000000000 --- a/Documentation/UsersGuide/GettingStarted.md +++ /dev/null @@ -1,167 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Getting started with ResInsight - -### Installation -Installation instructions for ResInsight can be found here: [Installation and Configuration](Installation.md) - - -### User interface overview - -The application has a main area and several docking windows. The different docking -windows can be managed from the **Windows** menu or directly using the local menu bar of the docking window. - -![ResInsight User Interface](images/ResInsightUIFullSizeWindows.png) - - -#### Docking Windows - -- **Project Tree** - contains all application objects in a tree structure. -- **Property Editor** - displays all properties for the selected object in the **Project Tree** -- **Process Monitor** - displays output from Octave when executing Octave scripts -- **Result Info** - displays info for the object being hit in the 3D scene when clicking with left mouse button - -*TIP:* A new project tree and property editor can be added from **Windows->New Project and Property View**. - - -### Toolbars - -A selected subset of actions are presented as controls in the toolbar. The different sections in the toolbar can be dragged and positioned anywhere as small floating toolbars. Management of the toolbar is done by right-clicking on the toolbar and then manipulating the displayed menu. - -#### 3D Views - -In the main area of the application, several 3D views can be open at the same time. One of them will be active and the active view can be either maximized to use the whole main area, or normalized so that you can see all the open 3D views. - -*TIP:* To see views next to each other select the **Restore down** icon in the application show here for Windows : - -![Restore Down](images/RestoreDown.PNG) - -#### Editing the views - -Most of the settings and features of ResInsight is accessible through the **Project Tree** and the **Property Editor**. Selecting an item in the **Project Tree** activates the corresponding 3D View, and shows the item properties in the **Property Editor** available for editing. - -Toggling a checkbox next to an item in the **Project Tree** will toggle visibility in the 3D view. Toggling a checkbox for a collection of items will affect the visibility for all items in the collection. ![](images/TreeViewToggle.png) - -Context menu commands are also available to do special operations on a selected set of items. - -### Cases and their types - -A *Case* in ResInsight means a Grid model with a particular set of results or property data. There are -three different Case types: - -##### Result case ![](images/Case24x24.png) -This is a Case based on the results of an Eclipse analysis, read from a grid file together with restart data. - -##### Input case ![](images/EclipseInput24x24.png) -This Case type is based on a `*.GRDECL` file, or a part of an Eclipse *Input* file. This Case type supports loading single ASCII files defining Eclipse Cell Properties, and also to export modified property sets to ASCII files. -Each of the Eclipse properties is listed as separate entities in the **Project Tree**, and can be renamed and exported. - -##### Statistics case ![](images/Histogram24x24.png) -This is a Case type that belongs to a *Grid Case Group* and makes statistical calculations based on the source cases in the Grid Case Group. - -#### Grid Case Groups ![](images/GridCaseGroup24x24.png) - -A **Grid Case Group** is a group of **Result Cases** with identical grids, but generally different active cells, initial values and results. These cases are called *Source Cases*. - -The purpose of a Grid Case group is to make it easy to calculate statistics across the source cases both for static and dynamic Eclipse Properties. - -See [ Multiple realizations and statistics ](CaseGroupsAndStatistics.md) for more on this. - -### Importing data - -#### Input data support ### - -ResInsight supports the following type of Eclipse input data: -- `*.GRID` and `*.EGRID` files along with their `*.INIT` and restart files `*.XNNN` and `*.UNRST`. -- Grid and Property data from `*.GRDECL` files. - -#### Importing Eclipse cases - -##### Eclipse Results -1. Select **File->Import->Import Eclipse Case** and select an `*.EGRID` or `*.GRID` Eclipse file for import. -2. The case is imported, and a view of the case is created - -*TIP:* You can select several grid files in one go by multiple selection of files( Ctrl + left mouse button, Shift + left mouse button). - -##### Eclipse ASCII input data -1. Select **File->Import->Import Input Eclipse Case** and select a `*.GRDECL` file. -2. The case is imported, and a view of the case is created -3. Right click the **Input Properties** in the generated **Input Case** and use the context menu to import additional Eclipse Property data files. - -##### Handling missing or wrong MAPAXES - -The X and Y grid data can be negated in order to make the Grid model appear correctly in ResInsight. This functionality is accessible in the **Property Editor** for all Case types as the toggle buttons **Flip X Axis** and **Flip Y Axis** as shown in the example below. - -![](images/CaseProperties.png) - - -### Model navigation - -ResInsight comes with two 3D navigation modes. The active mode can be selected in the **Preferences** dialog (**Edit -> Preferences**). - -|Abbreviation | Meaning | -|-------------|---------| -|LMB | Pressing left mouse button | -|MMB | Pressing Middle mouse button or scroll wheel button | -|RMB | Pressing Right mouse button | - - -#### Ceetron navigation mode - -|Mouse interaction | Action | -|------------------|---------| -|LMB | Pan model | -|MMB | Zoom to mouse pointer location | -|Scroll wheel | Zoom to mouse pointer location | -|RMB | Rotate model | -| | | -|RMB single click | Context menu | -|LMB single click | Update status bar and **Result Info** | - -#### CAD navigation mode - -|Mouse interaction | Action | -|------------------|--------| -|MMB | Rotate model | -|MMB + Shift | Pan model | -|Scroll wheel | Zoom to mouse pointer location | -| | | -|RMB single click | Context menu | -|LMB single click | Update status bar and **Result Info** | - - -### Project files and Cache directory - -ResInsight stores which cases you have imported and all the settings for each view etc. in a project file with the extension `.rsp`. -This file only contains references to the real data files, and even references to data files generated by ResInsight itself. - -Statistics calculations, property sets you generate by using Octave, and well paths are saved to a folder in the same directory as you save the project file, and is named \_cache. So if you need to move your project, make sure you move this folder as well. - -*TIP:* The `.rsp`-file is an XML file, and can be edited by any text editor. - -### Export options -#### Snapshot images -##### Single View ![](images/SnapShot.png) ![](images/SnapShotSave.png) -Image export of current 3D view can be launched from **File -> Export -> Snapshot To File**. A snapshot can also be copied to clipboard using **Edit->Copy Snapshot To Clipboard**. - -##### All Views ![](images/SnapShotSaveViews.png) -If a project contains multiple views, all views can be exported using **File -> Export -> Snapshot All Views To File**. - -It is also possible to snapshot all views from the command line. See [ Command Line Arguments] (CommandLineParameters.md) - - - - -#### Export of Eclipse Properties as ASCII data -Eclipse Properties can be exported to Eclipse ASCII files by activating the context menu for a **Cell Result**. ![](images/ExportProperty.png) - -The command will export the property set currently loaded and shown in the 3D View to a file with the following format: - - -- Exported from ResInsight - - - / - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/Installation.md b/Documentation/UsersGuide/Installation.md deleted file mode 100644 index 2d46fd2925..0000000000 --- a/Documentation/UsersGuide/Installation.md +++ /dev/null @@ -1,28 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Installation and configuration - -### Windows - -1. Download ZIP binary distribution from [https://github.com/OPM/ResInsight/releases](https://github.com/OPM/ResInsight/releases "release section on GitHub") -2. Extract content from ZIP file -3. (OPTIONAL) Launch ResInsight.exe, open **Edit ->Preferences** and define location of Octave, usually 'ResInsightRoot/octave/bin/octave.exe' - -#### Optional - Octave installation -Currently tested and verified version on Windows is Octave 3.6.1. NB! Version 3.6.2 has compile issues using VS2010, this version will not be able to compile the Octave plugins. - -- Download and install Octave 3.6.1 for VS2010 from [SourceForge](http://sourceforge.net/projects/octave/files/Octave%20Windows%20binaries/Octave%203.6.1%20for%20Windows%20Microsoft%20Visual%20Studio/octave-3.6.1-vs2010-setup-1.exe/download) -- Download a [missing library file](https://github.com/OPM/ResInsight/releases/download/1.0.0/dirent.lib) and copy it into Octave lib folder, typically **c:/Octave-3.6.1/lib/dirent.lib** See details on [SourceForge](http://sourceforge.net/mailarchive/message.php?msg_id=28933804) - - -## Linux - -1. Download TAR.GZ binary distribution from [https://github.com/OPM/ResInsight/releases](https://github.com/OPM/ResInsight/releases "release section on GitHub") -2. Extract content from TAR file -3. (OPTIONAL) Launch ResInsight, open **Edit -> Preferences** and define location of Octave in the field **Octave**, usually 'ResInsightRoot/octave/bin/octave-cli' - - - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/OctaveInterface.md b/Documentation/UsersGuide/OctaveInterface.md deleted file mode 100644 index 4c1a8ba1cd..0000000000 --- a/Documentation/UsersGuide/OctaveInterface.md +++ /dev/null @@ -1,42 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Octave Interface - -ResInsight provides a flexible interface to [Octave](http://www.gnu.org/software/octave/ "Octave"). -This includes a set of Octave functions that communicates with a running ResInsight session, features in ResInsight that makes it easy to manage and edit Octave scripts, and their execution using Octave. - -The Octave functions are documented in [ Octave Interface Reference](OctaveInterfaceReference.md). - - -### Script management -Octave scripts are available in the **Scripts** folder in the **Project Tree**. - -![](images/OctaveScriptTree.png) - -This folder contains an entry for each of the directories you have added as a **Script Folder**. Each of the folder lists available `*.m` files and sub directories. The tree is continuously updated to reflect the file structure on disk. - -#### Adding Script Folders -You can add directories by right clicking the **Scripts** item to access the context menu. - -Multiple standard script folder locations can also be defined in the field **Shared Script Folder(s)** in the **Preferences Dialog** (**Edit -> Preferences**). - -#### Editing scripts -To enable script editing from ResInsight you need to set up the path to a text editor in the **Script Editor** field in the **Preferences Dialog** (**Edit -> Preferences**) - -When done, scripts can be edited using the context menu command **Edit** on the script item in the tree. - -### Script execution -Octave scripts can be executed with or without a selection of cases as context. The [ Octave Interface Reference](OctaveInterfaceReference.md) highlights in more depth how to design your Octave scripts to utilize these features. - -#### Without a case selection -A script can be started by navigating to the script in the **Project Tree**, and selecting **Execute** from the context menu. The currently active case (The one with the active 3D View) will then be set as ResInsight's *Current Case*. - -#### With a case selection -One script can be executed on many cases by first selecting a set of cases, and then activating **Execute script** from the context menu for the case selection. The script is then executed once pr selected case. Each time ResInsight's *Current Case* is updated, making it accessible from the Octave script. - -![](images/ExecuteOctaveScriptOnSelectedCases.png) - - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/OctaveInterfaceReference.md b/Documentation/UsersGuide/OctaveInterfaceReference.md deleted file mode 100644 index ef76b50e7c..0000000000 --- a/Documentation/UsersGuide/OctaveInterfaceReference.md +++ /dev/null @@ -1,222 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -# Octave Interface Reference - -## Introduction -To identify a ResInsight case uniquely in the Octave script, an integer Id (CaseId) is used. This Id can be retrieved in several ways, but there are two main modes of operation regarding this for a particular octave script: Either the script is designed to work on a single case (the "Current Case"), or the script is designed to access the selection and traverse the cases by itself. - -### Single case scripts -Single case scripts do not need to address cases explicitly, but works on what ResInsight considers being the "Current Case". When the user selects several cases and executes a script on them, ResInsight loops over all cases in the selection, sets the current case and executes the script. All references to the "Current Case" from the script will then refer to the case currently being processed by ResInsight. -The Current Case can be accessed directly using **riGetCurrentCase()**, but the more direct way is to *omit the CaseId parameter* in the functions, the Current Case is then automatically used. - -### Multi case scripts -Scripts can access the selection state in ResInsight, and also retrieve lists of Case Groups and cases including some meta information. This can be used if the scripts need to get values from some cases, and store the results in others, etc. - -### Case Types -The case type (Labeled "CaseType" in the following specification) of a case is returned as a text string when retrieving lists of cases, and is one of the following: - -| Case Type | Description | -|----------------|-------------| -|ResultCase | A binary Eclipse case | -|InputCase | A case based on ASCII Eclipse input data | -|StatisticsCase | A statistics case based on many source cases in Grid Case Group | -|SourceCase | A binary Eclipse case in a Grid Case Group | - -### Unresolved issues -The issue around having multiple instances of ResInsight is still not addressed, but might affect the function signatures by adding a port number parameter to all of them. We will try to find ways to avoid this, but are still not certain that we will succeed. - -## Specification -### Project Information -The case information is presented in an octave Structure called CaseInfo, and contains the following fields: - - CaseInfo = { - CaseId = int # A project-unique integer used to address this - # particular case - CaseName = string # The name that has been assigned to the case - # in ResInsight. - CaseType = string # See the description above - CaseGroupId = int # A project-unique integer identifying the - # CaseGroup this case is a member of. - # -1 if not in a CaseGroup. Valid only for - # Statistics-, and SourceCases - } - -#### CaseInfo riGetCurrentCase() -This function returns a CaseInfo Structure for the Case considered being the "Current Case" by ResInsight. When ResInsight loops over a selection of cases and executes an Octave script for each of them, this function returns the CaseInfo for that particular Case. - -#### Vector[CaseInfo] riGetSelectedCases() -This function returns a CaseInfo Structure for each of the cases selected in ResInsight at the time when the script launched. - -#### Vector[CaseGroupInfo] riGetCaseGroups() -This function returns a CaseGroupInfo Structure for each of the case groups in the current ResInsight project. - - CaseGroupInfo = { - CaseGroupId = int # A project-unique integer used to address - # this particular CaseGroup - CaseGroupName = string # The name assigned to the CaseGroup - # in ResInsight - } - -#### Vector[CaseInfo] riGetCases([CaseGroupId]) -This function returns a CaseInfo Structure for all the cases in the current ResInsight project, including the Statistics cases and Source cases in a Grid Case Group. -If a CaseGroupId is provided, only the cases in that Case Group will be returned. - -### Retrieving Grid Metadata - -#### Matrix[numActiveCells][9] riGetActiveCellInfo([CaseId], [PorosityModel = "Matrix"|"Fracture"] ) -This function returns a two dimensional matrix containing grid and IJK information about each of the active cells in the requested case. The columns contain the following information: - - [GridIdx, I, J, K, ParentGridIdx, PI, PJ, PK, CoarseBoxIdx] - GridIdx # The index of the grid the cell resides in. - # Main grid has index 0 - I, J, K # 1-based index address of the cell in the grid. - ParentGridIdx # The index to the grid that this cell's grid - # is residing in. - PI, PJ, PK # 1-based address of the parent grid cell that - # this cell is a part of. - CoarseBoxIdx # 1-based coarsening box index, -1 if none. - # Coarsening box info can be retrieved using - # **riGetCoarseningInfo()** - -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Matrix[numCoarseGroups][6] riGetCoarseningInfo([CaseId]) -This function returns all coarse box definitions used in the grid. -The columns contain the following information: -[I1, I2, J1, J2, K1, K2]: 1-based index addresses of the min and max corners of the coarsening box. -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Matrix[numGrids][3] riGetGridDimensions([CaseId]) -This function returns a two dimensional matrix: One row for each grid, starting with the main grid. - -*NOTE*: This means that the "normal" GridIndices where 0 means Main Grid does not work directly with this matrix. You have to add 1. - -The columns contain the following information: -[NI, NJ, NK]: I, J, K dimensions of the grid. -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Vector[TimeStepDate] riGetTimeStepDates([CaseId]) -This function returns the date information for each of the time steps in the case as a Vector of Structures. -The Structure is defined as: - - TimeStepDate = { - Year = int # The year eg. 2013 - Month = int # The month. Eg. 12 - Day = int # The day in the month. Eg. 24 - Hour = int # The hour of the day. Eg. 17 - Minute = int # The minute in the hour. Eg. 55 - Second = int # The second within the minute. Eg. 30 - } - -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Vector[DecimalDay] riGetTimeStepDays([CaseId]) -This function returns the time from the simulation start as decimal days for all the time steps as a Vector of doubles. -If the CaseId is not defined, ResInsight's Current Case is used. - -### Retrieving Property Data - -#### Vector[PropertyInfo] riGetPropertyNames([CaseId] ], [PorosityModel = "Matrix"|"Fracture"]) -This function returns the name and type of all the properties in the case as a Vector of Structures. -The Structure is defined as: - - PropertyInfo { - PropName = string # Name of the property as received from - # the analysis tool - PropType = string # The type of the property: "StaticNative", - # "DynamicNative", "Input", "Generated" - } - -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Matrix[numActiveCells][numTimestepsRequested] riGetActiveCellProperty([CaseId], PropertyName, [RequestedTimeSteps], [PorosityModel = "Matrix"|"Fracture"]) - -This function returns a two dimensional matrix: [ActiveCells][Num TimestepsRequested] containing the requested property data from the case with CaseId. -If the case contains coarse-cells, the results are expanded onto the active cells. -If the CaseId is not defined, ResInsight's Current Case is used. -The RequestedTimeSteps must contain a list of indices to the requested timesteps. If not defined, all the timesteps are returned. - -#### Matrix[numI][numJ][numK][numTimestepsRequested] riGetGridProperty ([CaseId], GridIndex , PropertyName, [RequestedTimeSteps], [PorosityModel = "Matrix"|"Fracture"]) -This function returns a matrix of the requested property data for all the grid cells in the requested grid for each requested timestep. -Grids are indexed from 0 (main grid) to max number of LGR's -If the CaseId is not defined, ResInsight's Current Case is used. -The RequestedTimeSteps must contain a list of indices to the requested time steps. If not defined, all the timesteps are returned. -Writing Back to ResInsight - -#### riSetActiveCellProperty( Matrix[numActiveCells][numTimeSteps], [CaseId], PropertyName, [TimeStepIndices], [PorosityModel = "Matrix"|"Fracture"]) -Interprets the supplied matrix as a property set defined for the active cells in the case, and puts the data into ResInsight as a "Generated" property with the name "PropertyName". -The "TimeStepIndices" argument is used to "label" all the time steps present in the supplied data matrix, and must thus be complete. The time step data will then be put into ResInsight at the time steps requested. -If the CaseId is not defined, ResInsight's Current Case is used. - -#### riSetGridProperty( Matrix[numI][numJ][numK][numTimeSteps], [CaseId], GridIndex, PropertyName, [TimeStepIndices], [PorosityModel = "Matrix"|"Fracture"]) -Interprets the supplied matrix as a property set defined for all cells in one of the grids in a case, and puts the data into ResInsight as a "Generated" property with the name "PropertyName". -The "TimeStepIndices" argument is used to "label" all the time steps present in the supplied data matrix, and must thus be complete. The time step data will then be put into ResInsight at the time steps requested. -If the CaseId is not defined, ResInsight's Current Case is used. - -### Cell Geometry Functions - -#### Matrix[numI][numJ][numK][3] riGetCellCenters([CaseId], GridIndex) -This function returns the UTM coordinates (X, Y, Z) of the center point of all the cells in the grid. -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Matrix[ActiveCells][3] riGetActiveCellCenters([CaseId], [PorosityModel = "Matrix"|"Fracture"]) -This function returns the UTM coordinates (X, Y, Z) of the center point of each of the active cells. -If the CaseId is not defined, ResInsight's Current Case is used. -Cell Corner Index layout -The corner indices follow the ECLIPSE standard: - - 6-------------7 |k - /| /| | /j - / | / | |/ - / | / | *---i - 4-------------5 | - | | | | - | 2---------|---3 - | / | / - | / | / - |/ |/ - 0-------------1 - -#### Matrix[numI][numJ][numK][8][3] riGetCellCorners([CaseId], GridIndex) -This function returns the UTM coordinates(X, Y, Z) of the 8 corners of all the cells in the grid. -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Matrix[ActiveCells][8][3] riGetActiveCellCorners([CaseId], [PorosityModel = "Matrix"|"Fracture"]) -This function returns the UTM coordinates (X, Y, Z) of the 8 corners of each of the active cells. -If the CaseId is not defined, ResInsight's Current Case is used. - -### Well Data Functions - -#### Vector[WellNames] riGetWellNames([CaseId]) -This function returns the names of all the wells in the case as a Vector of strings. -If the CaseId is not defined, ResInsight's Current Case is used. -Vector[WellCellInfo] riGetWellCells([CaseId], WellName, TimeStep) -This function returns the cells defined in the specified well for the time step requested as a vector of Structures. The Structure is defined as: - - WellCellInfo { - I, J, K = int # Index to the cell in the grid - GridIndex = int # the index of the grid. Main grid has index 0. - CellStatus = int # is either 0 or 1, meaning the cell is closed - # or open respectively - BranchId = int # Branch id of the branch intersecting the cell - SegmentId = int # Branch segment id of the branch intersecting the cell - } - -If the CaseId is not defined, ResInsight's Current Case is used. - -#### Vector[WellStatus] riGetWellStatus ([CaseId], WellName, [RequestedTimeSteps]) -This function returns the status information for a specified well for each requested time step as a vector of Structures. The Structure is defined as: - - WellStatus { - WellType = string # "Producer", "OilInjector", - # "WaterInjector", "GasInjector", "NotDefined" - WellStatus = int # is either 0 or 1, meaning the well is shut - # or open respectively - } - -If the CaseId is not defined, ResInsight's Current Case is used. - - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/README.md b/Documentation/UsersGuide/README.md deleted file mode 100644 index 03c7f55a34..0000000000 --- a/Documentation/UsersGuide/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Documentation # -Documentation files uses the GitHub markdown syntax. A common file extension for markdown files is .md. - - -[GitHub Markdown syntax](https://help.github.com/articles/github-flavored-markdown) - -## How to produce PDF from markdown files ## - -Pandoc can be used to generated PDF from a markdown file like this - - pandoc -f markdown_github GettingStarted.md -o GettingStarted.pdf - -See here for information on Pandoc -[http://johnmacfarlane.net/pandoc/](http://johnmacfarlane.net/pandoc/) - - -## Internal documentation notes - -### Produce PDF from markup - 28. oct 2013 - -The documentation for Git is build using a set of markup files. Below is a set of command history on Ubuntu 13.04 to be able to produce PDF from markup. - -NOTE: On Ubuntu, use the following fonts in latex/config.yml -Ubuntu for normal text and DejaVu Sans Mono for monospace. - -https://github.com/progit/progit/issues/11 - - - 16 cd .. - 17 git clone https://github.com/progit/progit.git - 18 cd progit/ - 19 ls - 20 ./makepdfs en - 21 sudo apt-get install ruby - 22 ./makepdfs en - 23 sudo apt-get install pandoc - 24 ./makepdfs en - 25 sudo apt-get install xelatex - 26 sudo apt-get install texlive-xetex - 27 ./makepdfs en - 28 dir - 29 sudo apt-get install texlive - 30 ./makepdfs en - 31 sudo apt-get install texlive-latex-extra - 32 sudo apt-get install texlive-latex-base - 33 ./makepdfs en - 34 sudo apt-get install texlive-latex-extra - 35 ./makepdfs en - 36 ls - 37 cd latex/ - 38 ls - 39 kate config.yml - 40 sudo apt-get install kate - 41 kedit config.yml - 42 gedit config.yml - 43* - 44 cd .. - 45 ls - 46 ./makepdfs en - 47 fc-match helvetica - 48 ./makepdfs en - 49 fc-list - 50 fc-match helvetica - 51 fc-match helvetica neue - 52 ./makepdfs en - 53 fc-list - 54 ./makepdfs en - 55 ./makepdfs en --debug - 56 ./makepdfs en - 57 ls - 58 ./progit.en.pdf - 59 evince - 60 history diff --git a/Documentation/UsersGuide/RegressionTestSystem.md b/Documentation/UsersGuide/RegressionTestSystem.md deleted file mode 100644 index 342ffdb8c6..0000000000 --- a/Documentation/UsersGuide/RegressionTestSystem.md +++ /dev/null @@ -1,48 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Regression test system - -A regression tool for QA is build into ResInsight. This tool will do the following: - -1. Scan a directory for sub directories containing a **RegressionTest.rip** files. -2. Each found project file will be opened, and all views in this project will be exported as snapshot images to file. -3. When snapshot images from all projects are completed, difference images based on generated and QA-approved images are computed. -4. Based on these three sets of images, an HTML report is created and automatically displayed. - -### Starting regression tests - -To be able to run regression tests you need the **compare** tool from the [ImageMagic suite](http://www.imagemagick.org/script/compare.php). - - -You can start the tests either from the command line or from the ResInsight Gui. -From the ResInsight Gui select : **File->Testing->Regression Test Dialog** - -![](images/RegressionTestDialog.png) - -Specify location of compare tool in **Folder containing compare**. The current working directory of ResInsight is temporarily changed to this path during execution. - -### Creating regression tests - -An example of the folder structure is shown below: - - RegressionTestFolder/ - TestCase1/ - RegressionTest.rip - RegTestBaseImages/ - RegTestDiffImages/ - RegTestGeneratedImages/ - TestCase2/ - ... - -To create regression tests you need to do the following: - -1. Create a root directory containing one directory for each test case. -2. In each of the **Test Case** folders create a ResInsight project file called **RegressionTest.rip**. -3. Run the regression test for the first time, and thereby creating images that can be used as Base images. -4. Rename the generated RegTestGeneratedImages/ folder to RegTestBaseImages/ - -Now you are all set to test new releases of ResInsight towards your own Regression tests. - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/ReservoirViews.md b/Documentation/UsersGuide/ReservoirViews.md deleted file mode 100644 index 2a9df5430b..0000000000 --- a/Documentation/UsersGuide/ReservoirViews.md +++ /dev/null @@ -1,147 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Working with 3D Views - -3D Views are the windows displaying the Grid Models. The visualization is controlled by the **Project Tree** item representing the **View** and their subitems. Each item has a set of proerties that can be editied in the **Property View**. - -![](images/3DViewOverview.png) - -Below is a description of the most important View settings and their properties. - -### Cell Result ![](images/CellResult.png) - -The **Cell Result** item defines which Eclipse property the 3D View uses for the main cell color. The property can be chosen in the property panel of the **Cell Result** item. The mapping between cell values and color is defined by the **Legend Definition** ![](images/Legend.png) along with some appearance settings on the Legend itself. (Number format etc.) - -#### TRANSXYZ -Normally the Cell Result setting gives one cell color based on the legend and the selected Result Property. This is *not* the case for the special static TRANXYZ property. This property gives each face the correct color based on the TRANS value that is associated with that particular face. - -The Positive I-face of the cell gets the cell TRANX value, while the J-face gets the TRANY-value etc. The negative faces, however, get the value from the neighbor cell in that direction. The negative I-face gets the TRANX value of the IJK-neighbor in negative I direction, and so on for the -J and -K faces. - -### Cell Edge Results ![](images/EdgeResult_1.png) - -The **Cell Edge Result** visualization mode is one of ResInsight's special features. Its main use is to show the MULT(X, Y, Z) properties at the same time. -This will show the MULT property values *different from 1.0* along the correct edges of the cells. In effect this highlights the faults and makes it easy to verify all the MULT values in one go. - -![](images/CellEdgeExample.png) - -ResInsight supports all properties ending with X, Y, Z and X-, Y-, Z-. However, it is only the MULT property that ignores values of 1.0. - -When selecting a result variable for cell edge, a second legend shows up in the 3D view showing the variation in values for this second property. Color legend management is available when selecting the **Legend Definition** item belonging to the **Cell Edge Result** item. - -### Info Box - -The **Info Box** controls the visibility of the animation progress, the Case description box, and the results histogram. - -The **Results Histogram** shows a histogram of the complete time series of the currently loaded **Cell Result** together with: - -- The mean value ( a blue line ) -- P10 and P90 ( red lines ) - -![](images/HistogramExample.png) - - -### Cell Filters -Cell Filters are used to control visibility of the cells in the 3D view. Three types of filters exists: - -- **Range filter** : Define a IJK subset of the model. -- **Property filter** : Define a value range for a property to control cell visibility. -- **Well cell filter** : Display grid cells that has connections to a well. Controlled from the **Simulation Wells** item. - -All filters can be turned on or off using the toggle in the **Project Tree** and controlled from their corresponding **Property Editor**. - -#### Range filters - -Using range filters enables the user to define a set of IJK visible regions in the 3D view. -A new range filter can be added by activating the context menu for the **Range Filters** collection in the **Project Tree**. - -*TIP:* An I,J or K-slice range filter can be added directly from a Cell in the **3D View** by rightclicking the cell and using the context menu. - -Below is a snapshot of the **Property Editor** of the **Range Filter** : - -![](images/RangeFilterProperties.png) - - - **Filter Type** : The filter can either make the specified range visible ( *Include* ), or remove the range from the View ( *Exclude* ). - - **Grid** : This option selects which of the grids the range is addressing. - - **Apply to Subgrids** : This option tells ResInsight to use the visibility of the cells in the current grid to control the visibility of the cells in sub-LGR's. If this option is turned off, Sub LGR-cells is not included in this particular Range Filter. - -The **Start** and **Width** labels in front of the sliders features a number in parenthesis denoting maximum available value.
-The **Start** labels shows the index of the start of the active cells.
-The **Width** labels shows the number of active cells from the start of the active cells. - -#### Property filters - -**Property filters** apply to the results of the **Range filters**. Below is a snapshot of the **Property Editor** of the **Property Filter**. - -![](images/PropertyFilterProperties.png) - -This filter filters the cells based on a property value range (Min - Max). Cells in the range are either shown or hidden depending on the **Filter Type** ( *Include* / *Exclude* ). Exclude-filters removes the selected cells from the **View** even if some other filter includes them. - -A new property filter can be made by activating the context menu for **Property Filters**. The new property filter is based on the currently viewed cell result by default. - -### Simulation Wells - -This item controls the overall settings for how wells in the Eclipse simulation are visualized. -The wells are shown in two ways: - -1. A pipe through all cells with well connections -2. By adding the well cells to the set of visible cells - -The latter is handled internally as a special range filter, and adds cells to the set of range filtered cells. - -The Property Editor of the **Simulation Wells** item is shown below: - -![](images/SimulationWellsProperties.png) - - - -- **Add cells to range filter** This option controls how the well cells - (cells with connections to wells) are added to the set of range filtered cells. - - *All On* will add the cells from all wells disregarding the individual settings on the well. - - *All Off* will prevent any well cells to be added. - - *Individually* will respect the individual settings for each well, and add the cells from the wells with this option set on. -- **Use Well Fence** and -- **Well Fence direction** Controls whether to add extensions of the well cells in the I, J or K direction to the set of range filtered cells -- **Well head** These options control the appearance and position of the well labels and and symbols of the top of the well -- **Global Well Pipe Visibility** Controls if and when to show the pipe representation of the wells. The options are: - - *All On* will show the pipes from all wells disregarding the individual settings on the well. - - *All Off* will hide all simulation well pipes. - - *Individual* Will respect the individual settings for each well, and only show the well pipes from the wells with this option set on. See below. - - *Visible Cells Filtered* This option will only show the pipes of wells that are connected to visible cells. That means the combined result of **Range Filters**, **Property Filters** and any **Well Range Filters**. - *NOTE* : All Wells with **Well Range Filter** turned on will always be visible with this option selected. -- **Pipe Radius Scale** Scaling the pipe radius by the average max cell size. -- **Geometry based Branch detection** Applies only to ordinary wells (not MSW) - and will detect that parts of a well really is a branch. Those well parts will - be visualized as a branch starting at the well head instead of at the previous connected cell. - -##### Well pipes of Multi Segment Wells - -###### Geometry approximation -The pipe geometry generated for MSW's are based on the topology of the well (branch/segment structure) and the position of the cells being connected. The segment lengths are used as hints to place the branch points at sensible places. Thus the pipe geometry itself is not geometrically correct, but makes the topology of the well easier to see. - -###### Dummy branches -Often MSW's are modeled using a long stem without connections and a multitude of small branches; one for each connection. ResInsight offsets the the pipe within the cell to clearly show how the topology of the well is defined. - -![](images/MSWDummyBranchExample.png) - -###### Picking reveals Segment/Branch info - -Branch and segment info of a MSW-connected-Cell is shown in the **Result Info** window when picking a cell in the 3D View. This can be handy when relating the visualization to the input files. - -### Individual Simulation Well options - -Each of the wells can have some individual settings. These options works as specializations of the ones set on the global level (**Simulation Wells** See above) but will *only come into play when they are not ignored by the global settings*. - -This is particularly important to notice for the **Show Well Pipe** and **Range Filter** options. They will not have effect if the corresponding global settings in **Simulation Wells** allows them to. - -The properties of a single well are shown below. - -![](images/WellProperties.png) - -One option needs further explanation: - -- **Pipe Radius Scale** This option is a scale that is added to the "global" scale set in the **Simulation Wells** properties. - - ------- -[ Contents ](UsersGuide.md#contents) diff --git a/Documentation/UsersGuide/UsersGuide.md b/Documentation/UsersGuide/UsersGuide.md deleted file mode 100644 index 33c21440f4..0000000000 --- a/Documentation/UsersGuide/UsersGuide.md +++ /dev/null @@ -1,32 +0,0 @@ -# ![](images/AppLogo48x48.png) ResInsight 1.2 Users Guide - -## Introduction - -ResInsight is an open source, cross-platform 3D visualization and post processing tool for reservoir models and simulations. The system also constitutes a framework for further development and support for new data sources and visualization methods, e.g. additional solvers, seismic data, CSEM, geomechanics, and more. - -The user interface is tailored for efficient interpretation of reservoir simulation data with specialized visualizations of properties, faults and wells. It enables easy handling of a large number of realizations and calculation of statistics. To be highly responsive, ResInsight exploits multi-core CPUs and GPUs. Integration with GNU Octave enables powerful and flexible result manipulation and computations. Derived results can be returned to ResInsight for further handling and visualization. Eventually, derived and computed properties can be directly exported to Eclipse input formats for further simulation cycles and parameter studies. - -The main input data is -`*.GRID` and `*.EGRID` files along with their `*.INIT` and restart files `*.XNNN` and `*.UNRST`. -ResInsight also supports selected parts of Eclipse input files and can read grid -information and corresponding cell property data sets. - -ResInsight has been co-developed by Statoil ASA, Ceetron Solutions AS, and Ceetron AS with the aim to provide a versatile tool for professionals who need to visualize and process reservoir models. - -### Contents - -- [ Getting Started ](GettingStarted.md) -- [ Working with 3D Views ](ReservoirViews.md) -- [ Multiple realizations and statistics ](CaseGroupsAndStatistics.md) -- [ Octave Interface](OctaveInterface.md) -- [ Well Trajectories ](WellPaths.md) -- [ Faults ](Faults.md) -- [ Batch Commands ](BatchCommands.md) - -### Appendix - -- [ Octave Interface Reference](OctaveInterfaceReference.md) -- [ Regression Test System ](RegressionTestSystem.md) -- [ Command Line Arguments](CommandLineParameters.md) - - diff --git a/Documentation/UsersGuide/WellPaths.md b/Documentation/UsersGuide/WellPaths.md deleted file mode 100644 index 760de3388a..0000000000 --- a/Documentation/UsersGuide/WellPaths.md +++ /dev/null @@ -1,74 +0,0 @@ -[ Contents ](UsersGuide.md#contents) - ------ -## Well trajectories - -ResInsight can import Well trajectories from simple Ascii files. -In addition, a Statoil specific solution to retrieve Well Trajectories from their internal web service is implemented. - -### Ascii Well Trajectories - -The command **File -> Import -> Import Well Paths From File** will read the well paths in the selected file, and create one entry for each trajectory under the ![](images/WellCollection.png) **Wells** item in the **Project Tree**. - -The supported ASCII format is quite flexible but the main requirements are: - -1. Each data line must contain four numbers: X Y TVD MD separated with white-space. -2. A line starting with none-number-characters are ignored, unless : - 1. If the line contains a pair of : ', `, ´, ’ or ‘ the text between the quotation marks is used as a well name. - 2. If the line contains the case insensitive string "name " the rest of the line is used as a well name. -3. If a well name is found, a new well is created and the following data points ends up in it. - -###### Example 1: - - WELLNAME: ‘WELL1’ - 4507.0 5638.5 0.0 0.0 - 4507 5638.5 4628.6 1628.6 - 4297.4 5938.5 4632.4 1998.387 - -999 - WELLNAME: ‘WELL2’ - 5507.0 4638.5 0.0 0.0 - 5507 4638.5 3628.6 1628.6 - 5297.4 4938.5 3632.4 1998.387 - -999 - -###### Example 2: - X Y TVD MD - Name Well_1 - 5507.0 4638.5 0.0 0.0 - 5507 4638.5 3628.6 1628.6 - 5297.4 4938.5 3632.4 1998.387 - - Name Well_2 - 5507.0 4638.5 0.0 0.0 - 5507 4638.5 3628.6 1628.6 - 5297.4 4938.5 3632.4 1998.387 - - -The trajectory data is not copied into the ResInsight project as such. The project file only stores the file path, and the next time you open the project, ResInsight will try to read the well data from the file again. - -### Importing from SSI-Hub (Internal Statoil web-service) - -The command **File -> Import -> Import Well Paths From SSI-hub** launches a wizard to guide you through the process of selecting the well trajectories you need. - -After completing the wizard, the wells imported are accessible as Items under the ![](images/WellCollection.png) **Wells** item in the **Project Tree**. - -The trajectory data is not copied into the ResInsight project as such, but is stored in files in a directory called _wellpaths in the same directory as your project file. - -### Well Trajectory visualization - -All the imported well trajectories are available below the ![](images/WellCollection.png) **Wells** item in the **Project Tree**. - -![](images/WellsInTree.png) - -The visible wells are always shown in all the 3D Views in the complete project, so the toggles and settings control the overall project visibility of the Well Trajectories. The **Property Editor** of the **Wells** item is shown below - -![](images/WellPathCollectionProperties.png) - -- **Global well path visibility** This option forces the well paths on or off, ignoring the individual settings unless it is set to Individual. -- **Clip Well Paths** This option hides the top of the Well Trajectories to avoid displaying the very long lines from the reservoir to the sea surface. -- **Well Path clipping depth distance** This number is the distance from the top of the reservoir to the clipping depth. - ------- -[ Contents ](UsersGuide.md#contents) - - diff --git a/Documentation/UsersGuide/images/3DViewOverview.png b/Documentation/UsersGuide/images/3DViewOverview.png deleted file mode 100644 index e913685e88348696074fb89dffde1b62d57f58ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114626 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

)p#qd@$_Ul^j6*y;!+O$04M##$}BT%Hsl_Z5Xn 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

AlmY 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 T4kRXM00000NkvXXu0mjf%oT99 diff --git a/Documentation/UsersGuide/images/Case24x24.png b/Documentation/UsersGuide/images/Case24x24.png deleted file mode 100644 index 7e5d04ead780b6c9f422eef94bb0d92a05e3d872..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1159 zcmV;21bF+2P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m?d01m?e$8V@)00007bV*G`2i*!1 z4HY%J3X^~U00aj~L_t(Y$L*EfYnycx$3N%y;e)%3~&GoSOnfrWhne5gKU}r z5C`4>_I5;X^cp~cJa7qkHI?DSts0vS9gz!%4yv3;OT?hHR0hqa2?BQl`+>)S2aUms z*bwW9vb@rwTxp^TBA|)_4d6KNVk*Pz%?5x$*0%A}Z+t4jrM!E$+RXLw4YhkW>L$l$!yd#EJ_PxmkagPq` ztsmrhs`=82p3PON52g8hQ#xfD~mNfJGp=e(pdr*P;rkA zt139Ir}dW0bZLdDD>X`G2NekS3^H=>KGtsB2I{g<_=z7sdrQ=F70~^=`lYWsBmm_~ zLuclyvUsgV+qwQ&D-o;gn7mvWyfCw5<%(6w&o^bc?uq3K%KGs=Y@T>ps}1GLQ=hOf zKd-}yEgA?#SSsa>dM=ksD;n<$Vh4R$r>7W8)-RF1wp;?4~OQ z@rfPnW9;E)w10G`o;&j$*$~!8tUpguOoM(5ya#-nIl0;&*P;X1&JpQY9}3k~|==T@eMX3sitFfceZx^!LIrox}phftNdB=wA&_5o|lG zPP;AbcB>+P=RTy9gn);DZ5`|d*4~u3$Ukw2(nQ@n&)#l`DrFj4V002ovPDHLkV1g>x8-V}- diff --git a/Documentation/UsersGuide/images/CaseProperties.png b/Documentation/UsersGuide/images/CaseProperties.png deleted file mode 100644 index fe98659132b4796abd674dc7f442bbd020ac8acd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4984 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 diff --git a/Documentation/UsersGuide/images/CellEdgeExample.png b/Documentation/UsersGuide/images/CellEdgeExample.png deleted file mode 100644 index c25b47b53c646544b933751b17adf020269eff00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40965 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 jCrp*DtG8ohoRo&=Jnl~0|rzcvk$hdU%j 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 diff --git a/Documentation/UsersGuide/images/CellFilter_Values.png b/Documentation/UsersGuide/images/CellFilter_Values.png deleted file mode 100644 index 891753aad212610351adbe79c3d7eb5b28638db2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 843 zcmV-R1GM~!P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW3Ka!73GvcD^Z)J8=?{Kte?jrAQ!Ez=qU;3HSrp8356VjlGPpAP@^Xf(kYU z#Ds(dLPa7?Q9-0M3Q1b0wR8P_KhAj>c=m@vzqfj-W(`%g|J95BNU5II7thd}x~*EQ zYyK^&pRDK)tLRs&8>+{BtBc&#ei|ESDHbB`fj=b8&uJISw1&{62W5|<0^BBZ1EbVK zR4O)7OfxuT4fUvteuj9=<X#`ff~GkUx8{Bqyw%A)(HYKRTZP)=THee^svaFArJveKuk_R z8BY=#af2q1I0Pwh7I@>;H^apzo@aCSISwad;?+%TXN|dnC#Rc?SxpU(uU+Eka85nX z`QYuBO{%%LxQ4WfejgmqUhrAPgDB&%r46Q}Ol?ZkT4&0D-ENymmbpLpJ3r~)-(LW! zSd1tny(=HlSf2DxOUm5v@NCE|uBaO&)D<1u!_a2`kGsq#XE>1?5daAWAIR3yZ|asF zuo$y4uBrRyEQ%3?A>AV9(o&mYf52cd7(Y0=y;tR@UuFT6NJYz17E#1Z;re@D+%wbm z`d>n#S9a+1QeNME22Mxp{d2%CcYgix#^=|rc56W9cf$JZ>_2l;D=D^8< z!<&E7DH_!Il)>o%{X4(?^!2CLu9^yP1u(@DFc>4&3$89{w&9)kU)wtA?|ruv3bK&U zY;}1w8uHo4@4nI%$ReolU^56!F*OiOED#F;Vhh05N=F%u&Iti-?cYXXs0|d%fe5Mw zRL&SxODRw~zyq@}Kz}kjp}CZhT9^+f7z>^XixWpAfFXd1Fj6bj01-kG3lMgm+94l} za5eNyiY*}uUgZBL!2peb!($Uir~q#YtSA88l?{T=poF-rVS!j;#2Kk9V1t2?{0Fn9 VSw!QwCp7>7002ovPDHLkV1gRubDsbJ diff --git a/Documentation/UsersGuide/images/CellResult.png b/Documentation/UsersGuide/images/CellResult.png deleted file mode 100644 index 08b84b09ac60e2f07950eb9c8032ccf7e6fafd54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmVd%E&ONraUUGqCfpW2{@0wuPERH=6)nbwGDnuic)ymc zC=&}HPZwdcV|6hgf77Dd6~Wk2<#^((!TVAb_8j=Mt9Z6&6u5FCsfv_YS}luuU4>$S zVwdWtK)+A3HRN^+g^IK(^1{p+t>I6Q1p(g!bHwvq1C?o@YH|!ZmoQr6BhWnIYK`_z z%Q6m8E6Nh2_0Cv-mqt{ZrkQkZaV@>Vgg~|%3`qT@IUsE4L&N8C0=@*|_|4Jw zHLE-2o_hZsMgp589uV7u8P>U8aJ-b|9&*_kBU26jb@VZVT2TQ$=3yooxDz6oj@)$6 zdznUZqZ6zk8BC!tJAj!0ZV0<|6pljPcDv;V&T=JgkWR?vNnf5cj(z4WYrm!MjFlcn z(hIj|hZN}gsRDAbU$oa2ud5+M|EmCznR`6M1ai2>pyqntBj`AKZ^hW002ovPDHLkV1iz+*5?2K diff --git a/Documentation/UsersGuide/images/CreateGridCaseGroup16x16.png b/Documentation/UsersGuide/images/CreateGridCaseGroup16x16.png deleted file mode 100644 index 65bb871267f6dbe6b0a578e6f4c241b3b658a4af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 669 zcmV;O0%HA%P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*e) z4hS(Tnm_;m0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~0005> zNkln#Xz=3!MfoIEwTfSX%zjbe>K>pQs4q2ESBa-H71_p)} zDEH2l^}VV(fyK8c@%EZ31eoRVO9;IcR8*ME@c;L$=Qm!Tx^i3m!Qsc^T8uh@#s3)? z7;2C;GcYiyz{Iv^U7Rlobo87S+zC+W(`H~ap6m|M*7x{!h4O=;zmdk+pCJgt6>fq{X62}zSY5?cj13@np& z2YmTteEY|5S%wd9RoIyRxJ?hrYz{>U10>MIz`#(4EU+PoftQnsL788eHJpiw(dPHB zfA>Co__M@&F2inY2K+}i_q(yrdBKe>PkOpn!|#t{-D!W6J*dCo=)-_i%R00000NkvXXu0mjf D-;giT diff --git a/Documentation/UsersGuide/images/CreateGridCaseGroup24x24.png b/Documentation/UsersGuide/images/CreateGridCaseGroup24x24.png deleted file mode 100644 index 2146672c1c9c577db1804da2bf8909d7d04492a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1260 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 diff --git a/Documentation/UsersGuide/images/EclipseInput24x24.png b/Documentation/UsersGuide/images/EclipseInput24x24.png deleted file mode 100644 index ce0d05b3a047e50d823df36d7fbf2331bb26f1f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1120 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 diff --git a/Documentation/UsersGuide/images/ExportProperty.png b/Documentation/UsersGuide/images/ExportProperty.png deleted file mode 100644 index 4b459d0709065ba7df6b2c078bfc81d5b266acc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8790 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 diff --git a/Documentation/UsersGuide/images/GridCaseGroup24x24.png b/Documentation/UsersGuide/images/GridCaseGroup24x24.png deleted file mode 100644 index 030dc36aaf85e063230d3a3b8c798904cdf84f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmV<0110>4P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY3Kb3*9MgyMK>z>%9cffpbVF}# zZDnqB0000007G(RVRU6=Aa`kWXdp*PO;BVmWd{HN14BtfK~zY`y_CyOoK+ZypWk<# z8D?mK*6CD934%%`-l8ivH8I56#DqodUfmcsrcL+$1Kpaq=*Fd8*o6(U=vERFx-h7T zSfp_RBn)?CF5mZ^*TsMk3PQ2*U7h=L@}BoOVqd&GdgG?xbKonCucz+bn&m%)b{fN@ z*9)K_;4`ofK~n~kf**h}i~$pag0ZP@Z!I4e5Dbsrcm-GkD`0jRX$UBQy&*IRHe_g8 z;$6WzU_S!K2LRuLjbZ$Obj`3nP%5Z_MWBAcd%){pXSVlne1K6wx`Y@sEEGzB2uRGx zBtl@spdwTU(~|+(%lm;c=vRy!q60uu3&;U)sSW*k{{i1z1wTST0nq@hV1Rw_-EN8i zFbD))K*4rjzi8NLq209DW0&-{&&dfK&;pX3m4U$*?Q*gVv}q7!&8@D#YSjy2zO=c)JzC$W|CyNvGRK?sx<8PQJueQuW^j@pa(1S=jQB}` zYUbF;5}Wf|)V4M@`&Z*=p;#&o=L-2^97hUH_zSNBTfn1^0Ln$Iw}+s%Zu3iZH=e=$ z9am2Txcp+f%tBebSG2yeC28Vn^~Ul{n%ex8+pL@jQ0@r}2a4udOP;F&6KQ6XxgLuN}OY*)wJ2wCFahSH-}d8QL|JkrMW_`GmazgZ;6tt5{_WXg#Z8m07*qo IM6N<$g3WEfu>b%7 diff --git a/Documentation/UsersGuide/images/GridCaseGroupTree.png b/Documentation/UsersGuide/images/GridCaseGroupTree.png deleted file mode 100644 index b18056213b81a518b062c6ff04f3df32af333cff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3581 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 Dm!6_o diff --git a/Documentation/UsersGuide/images/Histogram24x24.png b/Documentation/UsersGuide/images/Histogram24x24.png deleted file mode 100644 index 6e3cd0aa45e0d2466ecef0d7ce84b6978752291b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 636 zcmV-?0)zdDP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY3Kb3)D0QnFI{*Lx9cffpbVF}# zZDnqB0000007G(RVRU6=Aa`kWXdp*PO;BVmWd{HN0p&?VK~zY`?UlW18&MF2zoV?# z#R*%)>{=K>3aOB^3&w_kvMH1*CQZl|PT>~_I9>Juk{7UE#eRy|4`6|cq*G-^bi#kTH-UX6;u;Jxt?|RX=$`Yj<8rB19%OJQn z&mm4TKWrskp%nBO_`2On##e*$(O*drHj{0{8z2E53Ovwt*h;>HttUUO2IoK5qR7N1 z*zPTA4uKx1wssGc`#b==(scl~2fU2atUZI;Zk%TCEA#jVssNp=#<)um&h7_h8?!Z;}RangLY7HUuFMF1oU!Ty>9tW*&Ew zpe8hd*#tWRwpQ4j9fK*=O%iy(4)6k_ZsMuX{Wk97x diff --git a/Documentation/UsersGuide/images/HistogramExample.png b/Documentation/UsersGuide/images/HistogramExample.png deleted file mode 100644 index 41ac8c05c3835932f5e32f61920aa243d69e05e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 578 zcmV-I0=@l-P){001%w0ssI2756%g00001b5ch_0Itp) z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY3Ks|>0XwYq*Z=?k9cffpbVF}# zZDnqB0000007G(RVRU6=Aa`kWXdp*PO;BVmWd{HN0jo(wK~#9!?cFa<13?&uah9wm z2owQP9ELM+2~NN%FbE8Sqi_k%fWc7#K~)eE+zJGtVpx{aZp+L!zen}|CbQ4H^L^7z z+uYqhZUNP>Z3w`4fbjt1f#PVB`==*I1_hBw_Ga4euXvuluJ7>slf#$kQzm0^JlT1e zzU6$jvKp=uIoR9%CF9HG^5VAl@vG~z`Lmz5p{glW?!Owm^c$gb%|-p6q8*5k@x6Wz zOK(b`JmW{V_Ui-B8KA1Eh^~9L0x%v>)%-^RV><=GjbEZGUB_{gnPwxO@uhaFKrY5- zC3kOGrPgA6d@M4Irxc3E?j&S97F(Cp^o&=}Kve@&nDO&azv-GV0dLEa@rrvBKvh%a z1kk9|oAJ&)WW1zDxQutQhf92yWX3U`>x&PLmRD5+l#}t&eUt%|^tl^P^i6tiR*Y}F zG0n&O;jgH*0h`Wv>7GdkjCC1rpbMG?B7Y_0xgKL3Fb!IwYl|6=TH?RLpCe~H_3J8` z7>~L-hgJoTJeQHx>78t@t3h2f$$$U(cS{5#F+4RMh>fZSj0YGGFdit64_pMV7PG6P QfB*mh07*qoM6N<$f|$Mdu>b%7 diff --git a/Documentation/UsersGuide/images/InfoBox16x16.png b/Documentation/UsersGuide/images/InfoBox16x16.png deleted file mode 100644 index 8a9342875cd4354d1580794cb0bbd010c73faccf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 454 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 bdGGIccO7#>E}+^tz{m2OE$Xp}N9_Lr_Ha*h diff --git a/Documentation/UsersGuide/images/OctaveScriptTree.png b/Documentation/UsersGuide/images/OctaveScriptTree.png deleted file mode 100644 index e36d58749e6cdd0f681dd02d36670c77c3e9dec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3476 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 diff --git a/Documentation/UsersGuide/images/RangeFilterProperties.png b/Documentation/UsersGuide/images/RangeFilterProperties.png deleted file mode 100644 index 96111973ba70a15db576e94d67d975d0543691f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10647 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 Bhyefq diff --git a/Documentation/UsersGuide/images/RegressionTestDialog.png b/Documentation/UsersGuide/images/RegressionTestDialog.png deleted file mode 100644 index d9c4ebc9ec31710c647982a2624f361404679fb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 297802 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 CXT?7N diff --git a/Documentation/UsersGuide/images/ResInsightUIFullSize.png b/Documentation/UsersGuide/images/ResInsightUIFullSize.png deleted file mode 100644 index 006086050f0a525081fafab2752ce7db0eabeb31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220111 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%0ATL{Hyv?l4#$H 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

lQAPV?XgyzS8BGk&lVh6CfQ(7TjZ zqzvB7-Kv(=!PMuNO9iZ9Po!sk)Bl@4QG+$to|1EdmLKc%is=A$%%yzJWC9W-=b>3< z!KC_~fB+@-XoxayjF8`Toa0U{#gMyjm||(0XfF-p<2@!3tf|<~vzU+C$p*U}FXQc( z#+QMiK5in!T*ppQQap?9|0Qdh;o<@x!u(b_O4OLwr|fW+1e5gpJL=AU1U!Tl`l-1) z&1?5O4Fx1WDpAx`F|K@|=%Y+`~(nH|Mhr>#@ zr4Gom+2L8eg0>W`feH7@#Or`!aFwLDVlYcCSm5LFxcrS4K~<~G@@1^g}e_?Bs25lR&x6GEWNCZ zcX|3(&JZVg3c${fuDNRl0%`GTgp$`o$yGc2DptCHvYXpRhttm?4*ucbBM|LYHS@*6 z=iejHWt~~Pd4p6B7gDh!Zr3)s#jGdIrXg6<)9&|Csh0$c;Ze=yu1JE~oQ@@rw;d&@ zxlS@B+r0GUQ+Bx8YbEK4EIQG;#40H}yUGqcZFNQ2B6>FYb|-_RgP9Y?@ykvtm5N12 zEiI<&HC@8pXRkTZTM_!{Jb(7!oktnFOVK=G1lVM{qZ@AG*9)|8?e8{f;@Y+ zJc(L0D93d~ku2T70PP0{jl6L7mopG39AH0E<$n3meuP>%sW=M^(@A@*1W&=AmqAQ) zJR+1JeO3m)#!);p%!`#Dk?rxfb&3by$sg>#N-!20;UYv9GDd!GY}M#OiYDsV{M*3K z)*1A7pFv|c_Fm}vdUbF&Iy$Qn4j@r6;UkG@b2HKls!}{I-no=EAD7j^FpuqKw;aUm zmr{zz;i40=Bzm|Caie0o?R!*G!-J>hg2Kj~&Y@g;0tG%H0boFh)>ol4GfkJoK+ z>ngrV8r@Up)4UQ8X&>5(wSPjw&H#E6?xgDb`!8CMuu8V~YAJsh^ zGhJjsHi?v0KFCI(kE~?0Oonc?HJqCR$LX$rry!7dm}-AoNBOJ0ic8csy=KuPd)ztDh30x0Bqiw%M#Ber&BZ=9s6JJjJaSAjtRCi^ zUFF^fiP?_ZgC0)HjWzO57M8<5YlR;oN5f?>vben{gHB&=2hI|1`OH(sEA)`OY^f2{ zsoHM18>>r_V=nk(b}q!#PqO^dH)i)W4>ojm4pRr)3?rzuAkniPRB2sui+Hv4Zw*hH zQ_15$VzhXWc;x=}?A{q(yrBYhoTcRm`;a}?ArLLdn@h>{AsjR6AznZjA;=+bV<_W& z4jEHTiB+V4@OX=|7u51{1OmkX?2mdXF5lVDNCKM)?L7wLE{@$%?fytIuM(jIW;Z4) z9G^ez!R6yAEd1~WAXK3_CyZQgKn@g^hE*r`#_c=qpOm-=g~U~rwwY$m690%k!aGV= zZ-se~8j^l}eYM(96#jv(Ylaxeyo!j+Y5V|9xB41$O1)fn8>II4@BS~VaCR@pWOGuL zXn|O(S|Xu+VN=Kg?njf;7+g0Q40@;!nZI7#n9E7K_^@avswYc=Ci9nZcU&aib{V!3 zX=B{*PJ-JQzl#|Byly9NL+_BUI;(fRPfQ}BY+l!m#dUbq@j4PzZL!V*Ds8U&jwUjc?sL72-6_< zB=|A>Z%?|z6Ou>3l15icmlSW8ZVTDr6~Piu-`K5jiDMm%sR5~D+g%<|zSKjaLKht3 zkO?2uuEMa_JGZ7H-1DVKkZI{t+W*vi3T$ctK>!;Nea~`ZD(XFd-qF~Al zs|qT1sqKePm6eQ@m8on_Y3~W29=`u96sJPUj~17wna@|(rivdwk5{LDc@utxh3x(D zevd4pX_p25m2TBd98(~J7gHNwv81b!jm1twg`H-8kGyDQw@H~2DZhWqVS$u&gTf)a zfzMM4`Z!JoS(c8}OXdCz?vsV{6scS->v%x1!LO;Ycf!$ASAAK=7E7z{#U>wmgj9^m zU`&@triM(65ygzwOqZ-CmEus0+|#66?r`1qw@P)&AC5|Hs4nJX3XGdz>SM4g20QGZ zo`8k>hu-&H-Ha;!4;p(Zz{2=zh)ee?S+hiOYKBLAFlr<;H~v_8-Jv&XW8_v_UkRY% zXib4VXPC94W)-x!m1bDGZIeo;1WQMa(SX6Z;$s5te9bRT;Mr_A_xJritT`0hH<(3r%*uomMQ^vz z%Cq@Q>1LaHn=ivE{avFaxvo;zX~b7df=5(^S6GTycz~ye*~-{5%cL}mq)S(!F7N${u@{ID zuJl3tQ9bft$14VLS{%{&7XEP9LkSMgYY#pxJ7jO)zlT5t!Fa`St-;}`AjsipqUE|Q z_Hu+{^jiya4NK??)w8bS$4g{4b6sV0Ks~UIf5cC>UrbGD29Q#7mjaKS+W;j~(e2R) zT}(7K?@*D53N*%CW(AQIbV?rX*u6FAuLN!H1j%^#?x)n$%!_t2r-tA9Z<=eEdWL(< zi?^P~f6e*!Y4s?t?rUUJCTxE!5w3w+sO3M|F|$-tSxUrmA|D)pXq2S-yYk|qia`Y` z>AmQ5t&;G=9i;#_IV6*m`#J;^wk1Q(8*i3g9*q1GriD5zjWj*`8Tx;gWrDi~@<)~G z|8fCTaF&E}+x<6lsTC93m5Lml9#h>K+f-JBR;-#9?WN^>j}?GeT+1@NL^Fat)XPq- zkG{t=|JLcyeZb&6J|_ZCQ8iz^xw+{9eT!r#;^Vuq@e>`0nP2s6Tr%uqf3CNbybFta zhJt)1pnPxIRoTo5$*uz}mV!p%eV<{}hk^Kh?#wS4GKW!O@)KAm5A+omVzhq{@@%h03|*9F*I zv=1)xjoYm-GItdizDT%6$igLK{`0dg*|0Zs_69yaaUzA5mrSo&uwtsqU9E#%kvNQ3 zk2$r-vGh`|H5n_*mNCo8pa;hn`f6xt{>@ZbDO;3vFnmjpy!JYrL*3nhX(oqiayj8W z6hC;emC}Z^9+hKbKDrH&tTDXfow}oYy@xxDHl*;`7>7;LWk}h0XyNCBvQ(^^nT80J zE?_L&O@v`{E<&aoSHP}y$wc&iR+Rdb7rjrtkf&-U;MWxS>eo*;=NT~}AswLPm?AlA z4zT4GvzGh0Q`@0HFQ|@L+KpYLy+3Z;0Wqj&M(R;?AkX56GH>A-7r-p|%R`-{Iv?eZ zRIq3sJ{+EcSzQY!)UCEswGuD9I$&6N2u#L{CFE%mi5w$RthG6*YA-%$jdt45;$Qbw z+NEz|+A?_A~l;}gVzK2mD^L3PyzDPHh-))VDU{$5v zPO6GZZT14Y%cn#9rozE)&%Yx&nX38 zo|a<|9|V3e?a~p0jGPb91lKHjuCFixLrH7P!La2Ym$I_3GOcadGimCw)*d!@wQj_N zm^P9459N+G$U{(Xg5IhmWmiolXi>FkF5G7=-e*+|3YCe$njRrFU58XWl-aKgH5QT3 zagm9fA4mda%40}p8{y=zy3@9adArw(2eZJvy&r1tfid~VNP&)7KA-}Dj*riPBm4dn zVvt@)InBJv?ALyG6 z8N1df(ysv068VoC8P%DtQZu3;Gcq@CMCupw?Lb8f_1=a|XGQ9qm zT2U(cFOh}yK|pd&;YpUwR*g%sUl~*8w>WYPLl#Ztkv`;(^GzYL{iTgzT7{@+BlKyr z#VObKkO6S|riYk+@JA4bp2_K+E~vVY1ZZoy1l)~~oK?KDVWl*OQ$5bLYv>-H%f%Ka z9i$7)Mi@oVf>?So?rGunzdP(l6pq3cO;Ub~saV4NXI%vsTBO%a4Tu|RVn&Utm5sOn zicN~5Fk74iM7US}+8$r>EH>x}5Xi7C?S_O&0eS#`btqH?wl{%VX4_hfDnXN&^9%jI zOE)1eq z-8ko9yV#57>)LDgQnJgsmloQ80sYk10*;mOL2zP4q|qNxfCrY(e~M*}t=GRU3<9d? zFvu$A;};u)gxsZ>JMrSwMlba8X{<)uNZ{+sf`!gB^JwF8Cag}LgrJH+iEITn4pYbB zuZ4l28rKL!gW1sgC;b-0mTC##I+OCi#4#&_g^ir!&E>~Jv^!e-xz)#l6~{6dG=plA z@3kYXCb^Fl3aa5P!BeZNt8^F2aP&O#Vc}Ou^|?GAbu*R@X-$-Ll4Gg^1Neam14Lo^q z?|3?Ch{Kd6&~^mb7j1|;lfNy8Hd5xD7sdT(!w)(3?4|ElIW4xUj_L?%p*s!-Sc^+dRW$<~i>Fgo+BcP2~D%W_ZFGkJ=8FFy@UC>FgCrUk=2Dx;&4+x z108j<&l$FhmDZ!61@WY1T}*zzdp}YEFMq#Z_$Fi7&$FWkaY7GRdkRO|%tnptgW%n% zl4;E!+#Ok(#E+^JRRamxXza#K(^@CNDIMEInliteRjf?xS`uN{wH&k*4!weEkn#Ux zVeYUfwz{X&7|g+ltvOJ`bYfp`uJwg~%-l7<*8AkDg}sJ21*2q8bC7I3L9FT2i%%-T zua#`spqpq*$fxUy4J13Gi_LpHm9}Qi^|z|Ii(M`>vs@ngAUzZ_MZPgT-^&i1_k32U znBX=30Zam}`1xDH6 zMSAUq22y4;z%>z%Q3fv7?-sp)WKs&Vzi4s7`zP_D{3{^l||dW4Kl!(cDnfNsL|{&d?o!!z6LeJiK#4V zkvA-b;>C|rYCTtp%h@m3fUdgvxjRFRO}$X$8-*D2;xFbgiG)Gl;AhZ@**LI@1~QR> zK_u)TL%t0j8V@AYvZ_%btgV&?N33E;0R0z0UCsGu#qZ;(y)0~QVJjDEYyqkwH z_;p3KF%Mb(fA=6>899$mQ{vJ6WFuuo;XPN9Hf5jcgj(V^Y#{k48~W^-r7sTRU}5h5H~ zIyyRf`k@Ag+V7;7&32)*?VbCHN3nfyLlp_(NUDRD=l}){I6w{<$Z>3kd`dxlZ9t~v z5-zSz0G!)o7E4elks9^e(DN%LzKP@28wDm`%>cx-Sw+~yv>bqKg!?D<45HsILb(Dg zmOv~P=g45~zpn-0c~zDJZm&Sog&Xg^>Ax2D*xTF-Eu<7 z-v5?}qb9cGlXZ2wIN6=WI`v=o#lNz9NpjS?DlWUA)s5KlvkYj~nk_S`U`yxrlUJgu zsmwe=VY?0~tEta-yUmSL^1h3Mdsy{8&)~mIOC3wlkq7xiiWi*2I^Fh9DaXQeytjtI zU8!+*EEapnS5p_L9%i}MBmw)!adzz`aaManOyA}&rpC9ow{Z`Z>cNAnud z4EsZk6>xJ!3oJW_3WwKPNBK_QJHoH0de}>_5p{<7uhje+t#DgJjTm}QeKs^ry)`HU zE0a1t_*KO(j(p7^z!MY`-Q(%(cHx?@d=U~e&DHYayMm4D2`kH4vl8jI5Hu8rrG|Gw zRxJ8zy9cgr|Hwo?OAbx0Jz-c{d0dc6_&>)W&~~P_`c74HN%5Old{4saV^qJ@p>KkpVLVVw98$x^t#>pd4c0#Uy0Qiv*4E8_Xr- zY_=OHA&VPHwz28OuVkHVIATgUWA-)OH z@-IJSeCOs7c)!H>E7&8}xK3h@^D@EQh5XOth*>%}F#DwMHmGuwt@HH2=sJl!YT^qI zV3PNLeV-sBLdbWPL=D7#;$)X)2mcbQcq~hkD9$xDe*aq~7Za5;3e5kAVLx&|8AYG? z-`6SXA)EfcFdDeYX6v=$yj|FZ79WYGeeIopiuZeGjX$kBcp5{3VJrKjh&Jbk;tIRa zFxWe57Cda9?K%+cM}EX79!2fI9kkFMx6s<}QT*Zm3LKM2`m3i`B!tL5q6EWFa%6ZY zTIq$5a>ya5I-4S2>keUJmGns{`3MRnx3gMg7mbK}+9Q(^tIKQTaJI1oe;IRBD1QH2 z@zEi!40_JxjIu?N4Mze;`r|jQ3q0JqE=T-{?r{IwVZgU`@|qKs)*6d!I7COceir=O zw*>3$2QfuDO;c5i(*gf@Cu|SRI%ITBY+yQrd=qC+)2{;EyLR#|ZqY5aC{rU8j= zd%GV+>eF`8`;k#sT>()mcg1Pf{sB^vuXrKDsgF1d7n?s&`1#2-TRui?w->#y4^;9R z5)FO$C4BcQN@a~#h_&;5Khr5+w+tT;?X%hD^?diUkbL(Z310aV6#Ad4afj|B9CCy! zwPnn9P=mZA&XJQ9ezFVk2*MCP-+TL+vv#FERtI%Gwbiz|%Yo%J1^%QQ4K}{=>cDm; z%eHWqgvZcBg4Sdfa>-WyD@7VlOdbUFNxIOQ2s%Iz+mNX3UGP2I2LKbjBvr2Vr!XET z5FY+Ih!t%lEZzN;S z3-~iajoFDT&X)!%zf%6FEgC7%%#%LE=2T7*-C6S&2ZCcxW<+m?vbmiogY=t2N00k7tU}uGG<~(@m6L*du1WFyc@y#_&aGjyfAg}qFbh*hYHOyE>20%} z2;RWBPplHwO@n4YIaq2qPlUy0IfCR9wiQ66cuUvBjY4z$x;N9C=%l_sC&KFPIVxlS z*GeFVAp4i>n|+JFus27}GcUb62RN3SW5q}xmY_X4C z8*!N099Z=w5NO4uWVpFs5y)&JAo|uN!|!Iy2}&>AG@gJbE71A4-i@asjY-sSTC@}X zI*E_$Z(q}Pf=X%Xq6|Vus%$OYhfGM_6p?L;6HJ7p>q-%9u<>x4_+LNUN>o5#FSGEk ze#*}`kc%mRRhkp=-e!H0AM0WY73#=ce%5SfjdmQMJvLYfWJ{_r+9a>K77UxXRYz=ek`Xc<{yz7I-7BBsoE0nmYbJG<{`MTV2=f2@b{G-QC??i@O#rTBNw8 zKyi21LUGsP4#gdc7x&^0H_v;=_dm(V*=H`Fb1%w_pi$6PlC+N%0W`Z?zHK5G{H)Rm zWEFPtZHWj}`adR3;<+*9hZL1F4NdM@O4?ZtWaA~2V4~1ZhrfE+++_<|2WG_084#nN z&4vx3El85|qU0?s-5h$uRjEMIyu;a#EFRLSx>uTyGfDqzaA1x$AskqztE-zqR0G&6 zD5e!d0@yMjHMKtIj%0@{li?-T>e~5Vu`(V-wbC#wJiy?u0{YZHqUGm@Gsnz<%{~8p zVp7D9A;BoGgD;)-Cp%zDJN-(Dp{h#F@l!U^{9fo+?M8PxNKgL{&`l=06JV`Y+k@dt zymPp9?3DO%AGzQl5g+^x39-IOEAN+PrZc?M*Xu5Kph1==4@h(of}JO;=$?8}BiG;>9I=FBDk8xYI)j5X@u0|k0;ML_g@fw*)pJ5X@Y1&KAk z)3>(KR#=C9XDD`Gd;uQUJNC@hbVPS-fhhrxOFz!6RPlGFb)~z_OKvMftmDt5Syaw~ z-iTSk=|BgmTn)cYo1aLm=${clx$Qfk{AZ-(CjZ`(Q)cj4NW~Y19Hu^W>v-%pit*Cf zFNiDvazu~k5CY%-XbkR(E9z0^*ya)uq=&`MKUsYk4v>@_^_n}NN@EX$3&juU>3NSI z?0~|;7trqV4LMoWh!c!gM#B++a5uwG9to-?0?-eO_EvAq$WX*dOed_v3VX)NC1CTN z+c1CZ%5IA(Wz12Fr0>Ve&IEt;fl_fDFR=Sl#4ZI(`MS*x#qP!*W7s48mxj+BJ0c>M zke1c@0+j-|pqaiNMeb>Y@tLEjdynNCQ`I*o+)plcm?eiI?@&kBjn-y`d?AiEb5HEg zKBO&>@u<|Ov)*BqsCs1>X{OSx~s(^`E3aU{P!K^}RleyS5P-M+gZT7iN1hN&Kl zdGmrCywpQ;sH`ANado6f?*!v}k7Sph4&Lp(pgl;w9h(O$?o>d!Td^YWbzy(76Q{>e zQ^50LmsTTkvTc8afumI$8ZfP}Zs;ElGA9v)2gE)golY}%$a@&2tceSYhVL_f0%(V^ zz@rQfuEHux*1(36#~?r#A)rMz2b*_hjn?!NF~{zAMJEVoO4pDtdQ$990 zlQrpC@@?TaA&4KWZ6cXglt6h*#*KST9k&MGYN*|}MG%+-lX@%Z8E_? zSr#P}c{s#uWm&(kN9&>Hv z$*9v8$p}`#UPiSSmRdIxJxbqi3QpYLw7_hTTW4(DrXbImq2TZv9qOMerY}{(hVcl{ zaRSk?ef);)*BIX^5Dh3BjFcc3-Q#f;B=nJj_+d5vJ!0O?nnC?r#Ju}!_T-RJfp$hc zJWKVlpO_CEU@#0Ie8GO%WV8OR`jrmYJog|tYH45DT=ms~GCMcnCI3Ym9k%RzbJZHWOD@Mxem zVECPTjdu#yam9+Pi4EAU`|`qYZus)OJmU2{-Vt1&WdG}XN#(i-kW&vsxppG7b;c&> zNR^pjs(UtIIY1hlEGYtCyTRUxf0-!n-J++T`5qOy4pmEEo1E*X{jrp)jiWV?9rW-C zV(t$nNWQGO)-)NR0!$GSy+jdv<9b~7pe*5RprbjyQ!u)O%@T>-p8}fQN>8BEvRfIl zDjT6^9-EgU*P889WYCHd0T@pPT=(_$T9>0B_HP-wd_rqgn&B%dlfhB^(8V1);Mr94 z7@NMkjLPlHMl_e&wXUrhDlIrH4Sy{IT5M%u`HRyZ1){l6zZVqSGrSe##Nbf3B>PA8ojUGX4|o{M8~AYfz9fbZ(S z*g+W{%IvU|B7r~ZBrC?P|3)67hmfb%1+AoMLmIFdf?cVu2Rc={bO_=fW80|R)zr|z zR6nO=Lzf_%Iu%-+)(6hY`Y^Vt_DhN{Wn+HDdXLnu4*pqki4!jPZ19?%{!gcBvY14d z8JEnIjO`0qDI;=!i-#l7DJRwgl3D^azC9<|=#1mQd3o(c`l!#iclh%ks6ZqrQ0ha~ z#@W{$lg3g(L4-G_3;8x|0LPT-n!wq5Gd<>gTA1}K-PT(eXTVFh0iNqCSwPoX-Vs&* ziQwEhlLqAP-Fg``kMo4{e>{-z5q=#*8!ti`Yd+4~oLq8`Y;{9GJr%*(2o zLE?A_AJhZ$cM)t=wI{ua)Dt?B1-1-8tbM^_@C& z=jVS|S?NU~I;I(vIbeH$g|7g2wvLQVp~Y@gxfAg*jE~x`{QM%}RNa~v-FepBp-K08 z!Z9(X)TDRw_wRIQYHj-)Yq?dzMC{KW(l=)xj9Z=_ALq;F{I+@|3wyxepaz=)`d{m$ z_?QsNUpsIp_Fh)iLsV;!5V#xni^b5&>3Oi;ZB9U}yQo4p89>nnO0N$a{_ZcWlS%(E z_7e7+?PsCU9{%rm%N-7mDOtaz3dwT4P1Kd{Bw}kGq?WJ)Xep@pvC8>BWRQ_a2^9fR z)A1qHf;?O<4(MZ5h0|tfC}&+t|Fm&nEk#@@Ez{rp!c93Wsd0^ac6X1NA{IctQ2n6G zNsqr6wiR={U?TYKDjPqhedHw}J=wf8)bWz*79eXh}@$~{?`AtK){xv43Eop?mDMp z)BI)X-N`=+1Wo91)_l=_pHxFYyLwhXF?4rPv(!{UI;H{`YG|w)en}bM?-TLOc3d^s z*#Qy1oO1cD|2p9Pa!0Rt-Q{nQn0P}Mi$=eN02LF&U-wD#B!S9MwN*&(Sg_mGg&72& z4u{GO=P~6+(sQ0s(}G8Ao(L#G_y8>7dF{{E?d#Z*pzU-B|=z5)L|FZc!ve{Q*G$=#HY_uJ%ijc-U^5+Me!)jx|Xi(cs1-7)X`A$AJ2m@ z_z!UKCLik^R6GKMwmZn;0!3wYVBV-tm+KH8Q;efNa} z-^Gck*Sifr^5~a@4Cr{S(MMRF7Lp*>|eE%j|}9kLr1tM&u6TU-nD|# zvXOz=<0#Mb{n;H5G`$PFK}2`8JR`IaCg3Jq@;G6cTd=iX-!xz!E+id_?wXb)js1RDL$ zG&mIrlVur~d#Eg-QQ)C%+;03I9XKyDTXU}diD=cJBI7ndcW6WDv`!30y!t&G(`+jS zx#!P!Y-)#UD6o6pTrVFdps&OL{zj#@C>cBudK~h|gLCr)Q-L=pvBU`k%hfK7F@PcF zbce}^Zpl_aj{hTz={w^?{U?Sqp&*c6cjz5K53j!zVsFV8dXNv=Cm^J}w!xR>%!3EI z)}N}AGKXYY(mfhx`Vlff>G?<~TLLX~q-{(9&Jijl*E#nbw*FHEf8y4*Lg9`m4N$1t zTWYDx+zwlfBo_9C3yknL7rcOEFA>8eu=s0A)Vdr>q@y+SSuA9sKEY1*_LuT)LHdH# z>0$8mU9-Mp-Uzo4H*63&SR0oGbH)ZeV%$J$U$;VE z%D$RstWY~>@{CkWm-}p%ql}Pz;j7(ilfaodO}Et4_GVXL0K<2E^PQhJ$Amlbt(DQs&_IvGVw4_`I>lKF!@Bga(%dUi7dW|sR#y9WpuHC;9@=jUB-(21Isr2 zt2aEb65aMIPhaT4qEgExR$Az_-U6`GHhM4|m_|I|XAhxJt*!{rwLDoRw-&yO>XNl| zSx~KorYYXc?j)pddVEuIr1qj_Va&pT`5TNkY%noEdwFM-|im4<*T_ zn57nJmI*+-OycL1bUByw5U;FK;{l}xgV&$AK8kE;uB_jdEtjn@z;l$T57-U#fP8Hv zV8n_?5wb@DSNo$k+BukHI2L;P=-0{R;f_R&T=O64iflnYYA|Y%?1}qFr;U*Onn!T& z`uVFEP)JSoGSz-NTfLjz(s@AYj4JsOy%5)=?HkS07C;OhvZ$GQ{~X%@A#$U~TefZY zNYpw0@nXyNJRqJnXrApnxM6vv(3v0B7Sw~Yhh}91L3RIyWxQjwR%px$ANv4!BpqtD z(Qs=ukD99mFVz@W%`iqi-K2b4FdE}IzjK*vqekGc*7)10Wmb_A8}Oy^PHeuIxSy;q zEd~9CaEdoj7B*-iPaXZHJp%OLB#L4)gw#K@uvB+i!vGE_T7H7n!v41og%tG7f&hFQ zg`B3<`IcJqd6NUV$8*f~;*-M|W>N1&+N>xQKA456lpO!IrX%!BPZngvv*ygb-t_yk zPO8Qc0z&1U`0xRctZj7_4qds zP7!SR?35Nkl6Yt>CxI?4F)yu68AJ}j#p47P3yF}svSM`9+l$<7RB8T*vB7@ComACd z`+x$|63{|HUFK(v^}mIEzix@Jaj>bU4XmG2R7yDbR36MHeV>Lu*h~?xwH%PKbz^kO zLR`<>*UIIK#_)MokaN0pnkvf`{XFZSp7g#treore%O8?b94e|4LwR)cINV2&d54i~mDHBvlwRtLL;f=4y%KZ;^W>9j2wm)O)dfMx+F*8S6L&1;k(LIkYMp zLXPDD9w>tDil?(UPy*fFV~@cCsN_KUt-G~SdjeI}M;jRz4wK*1#E58O7`AKn8hoVM zMKFQ;*;pW%rm@h=eBpfBKhyvs? zE;&>=E&70=%(`wmx^pak13eLHc(WgAQ zju}b{BV^i3&8oH+5O)+~I(u`151uf^hZ_puV+V-3eiWK*89m|Oz4{^LPw~T<^_%}W zF=%$jz=3gi&BV;Vrw=T8Z#mHt#u}PbkP=yfPfG~#xGW1H#(AsOAlyca`2gfiN4?wVVv`p=S$+9QFJ+?Dox)~66#%_hspof{b6>4r z_fWp^dfOMlXCicRJ$NvcTfLNz0ggGT7yNouU6c8K318&YdRy;vE`zhcR_(l1D6V#_ z3u^T*pQD6|m(jqOCLH(;g>X&3QEuHj^5o*O|GPy7paZrL|B<+D9DAHSwEEn3IxYPT zR8fBk_zX}y8g^0j>`&OF&SzZiB_jg|5RCxGm+HUQD_AG3ii(k{q??yVVUe4go>y2t z0i>grr{*U&eAU@6(!I?!{@=fIxSy<^EZnF4`dF#Qocf%#?wXaNG3i}fdHPbW4Nzmn zc0I~o`<}C83h7=yjz_px#t~kkusZ=9Mu(ND9L zKtDDI06(!jBn*k@Rk5F)PL=>KTcL<-gX0I}+_kQF%pj8`ZHghLYAatnb@U%G=0I~z zzAmzrZ<@M#&xTbp`VW+fN>y;I)N*f1GLTdK3An2&CaJcTTf`6X{>tL$?S30lG2vT( zZD@PV4Y&315h-6^*Td&$!Vz6@#kZVcPfZ0VFqZG<)k#^){XKGp3j_!vQRPF>DZ>lt zk-{1Ot0yctcSC$heJ(GO=%NX=xc;AOF-`k)YsJdG;>zZKU{ zbXcAbPbv>@BN)r`Dsd65Q?AA7qd!9Egx__CaU|82C`j1K&g;vTrdCev1i2ZEM%p-X zS1)I{Y4DdjzXoi!)18@ck}(3*Ke(5$_jaq#;NpCC%JllM^&C6`W!ehM+HqM9Jujr% zyEAKQOoeV2-jYb^LL36W$j)uN9(x`$LWiK6QfNYdvoM{y@VfYsbbWx8e?}E2iC#ee z*dTU;!>JHz2?eB+ube?hUAha`O1RwJ2NdCy;EtoYBsvvZ@waXppj61g%OQ)`r#k0H z_4@DFgW+Z;f4_61noal~^q~jyOC1NZzl7LqbBglNhyvZ+Wo0n(O3egHgYJqEBRj3@!H-box*$3+U zF;b+}zQ#k)Itv~x$dkVjx|PGDSboQVjpzLaTIOlN#1q;axeHK~aNe6xmK$IisyDta zr8mEaxV&M0IB{(BOfD$nq1snd4Jad*90{jqJfeq|Kt!4z9I6U*i}r%kf3Aw)kNwe4 zVY&p;K9)Q*;$afn;oQYyLhZRhLpEJh79J}!{Y&>fl*poyeD>LAcL7p$=hM}&ONR>Ek*`Tb(&EzYI%Lm?Yc z+_fXtYJ>?fveN?|;jF)1&HJ`wQ=bn_2tfbXAry@22W`aM0{%W^UJHM9tMGo~M zhOgEPX29x`50b*dz(|UJWA3*_iK!ES!tjmIQh`*JkSi3?Eifrj($!xja0q(69;p6U zK|$AglAiJBo-KJNZuJ}_1G;M?cg*aHz*pii*L`)sco@=j=qkyPt;?2y>mYf_Y_8hw z`{MyKW-KW&9S|ZBEvJir>!v%KY>y9K4Ayr_-R4_0Cl^YQk%;H)DGhWA=3v`5h=KQh`Ko+XN|JT@G&RMZ%zlg-K8v7Bm<}pJ|HPRSCncp>_zA zAqLSSs0;nCU{g|x^^kzHlo+38#!F+&t&-%wHkc*IE%?jzm+Om7QXV^%62e!g`6-_1 z^PS9>6|oUBRr{S(yABwHP{tA3a9$mLCiYn*PMA-uV>9Zu8XMp&W|oc2c-@5ty0Z9e z{u!gWsx(lmU1V^%TqsA^L^MEb3I?0m(_%t+PSDSEEaSn*%1HtD?z`%mf`VMM=3eNlY9RShC83k ztWHjg;D!IaR=8f^#kk8)2OhY&sn3Qk`9ZyIfcMds5j0?#2m`UYPxeW)6T>l6d15s; zH@1KeqwZwesPzY(WFl_{NegWediCuNX0_tgsziJb4T$LFJxv@uIhweo%N<26>)~?V zMG~QF5-}~WcQ3twRTm0Ph4_tb1ko&o0>eBtBp<3F+PtQmELt3pe35WU?4fwT(X$Hi z?C(Dc3Mw~FH8NSCM)JT?7g$oVGr7z}u7q}81`{mgeWQQ{KKp(Uy5hirA$|>kI`pde z7D)Z|qKRNCcDy*p$sD)~lv$1Y6o!kBJJ$b!0VEh>^~9yPS#sON{BDm#?v4%Z{8_+} zD|(NGi+9xYV^)}v-ffu5m6^vAk;TW@vL^53rW6pXC_n25Op|u z8F75D)ye7BByK6o)a@5_c>+qfOFyqMBHj|uy6B!EN}2i`(R3V7MK!U$% z&EfAskya~&(!$2&KHT8C*!A<#Rwc6l%roiI4h|wXkME9u!oD!Z^V$2PH;Q<-aa66+ z{ON+kQZRF{lYmMMT0W4Yr-RwA3|1 zQ&4MC7n^{Zz(aNcM{8a$suT^u3S)zu?;Euq&3ddQ?)Dv{M-n}z`3I39654`9FDiM? zUPgxOc0aq0y)a?bat?Mi+n)K0_|msSJKqn`@z1u!AMB$HmoMWO!1Jri+mFdW)ll6U zTPgk4GF~!zBiR?_J`7Yv<+j+IheW8)B(9%Cx|T=EeasPQ#Iwp-D^D0wQ)lhk%@6`MF+8a^%0P7)9BoHNw97KTl0*XEV!SLYDYG@aXnYkSnz_giF!1$YwY`k%3D8_HMPEWDL@3k0C@9$r8hV`VT zNND1C>K!yp^6im*6+{%G+qRwaWjGW!KL4K=L8#v3dpoQt0CXu>I=*xfofIk$!qo9cYLODux#+d?QbX!+BBv=&7&IK7+{F9>H{9@VbxwY7f#{` z6^05nBE=(FhiSbH-~F@5PgS8z-dmGav&a|$ZvS7@V@7k-QEk(K5=mw$BoPxDZA0!O z4I@9sf4Y+Amts=9M|g{@DGizo)_fMMjR*q7v0?mcy7CQ97nty!v&?XIlnYV4d}ik( z^JNjXOZRx4^`yUt{nbUR_@mWkNq4%onZ~rt+qs64 z8Y7Yq8QHSYfK_l|hp+b4 z)xqTA?|40B-i-@-i&uiQNb(TGy+j^o<(XLGBi`cP^wCnSd@sJ~)A-{+Z_k^|L-KpF zik(onJJCc>A?tg%`g?^~d`e|8&B^E2fJzfFT7=T2xD=-!KEcIA3}+awpJ-C(iPls| zNYaafT_|Hw$Md9ayO*1lu`yOdz2op>9%83kv2nBdSi?@3zIXQ+-5c`y1-=`GIK58q z96l``KbN2);q7&DwVrIY9EU$%O={n7=k(r_ejGeqF?1Pz$*D3udAhG^wdk@x&L1ha z{p7a)r7C%Q$K|RH9x&OXkOcR}OzSA%jpg&vU-$_dlEAY|$>Kl;1DOu> z`KqXFn1yloI1>np^Zc0u8PuSFlm;XkHFwm<%-eofg8|OKGsKVM)>OSmb>@Mt9r`vi zn&yj24KM4Sf4d8xR2Lf^UaCYgKB z?z3FMs<^YYx0iZ%rl&hTede)}E|A$?bj$6x$Q36AGLgysuO=g6B``161T4Rd7fOxc zRbUT}%UFn}_Q>E~d{e{va-q?`!4aFf=OlC?XO*0DlFDEL^u+XRt3oG^MOZ=T-~7L* zBw6;z_rYSIBQ{PGd7j_rnbwng&nCg65`XsbLVL4oZOeUf#)UUf4w%JP!RX^*(L1)@ ztn%bmbrNtf@7eP>TRo5#LPP)Og*usYg13g}LmlG~_}o-Qm;E7IOf6UQ;76NnnA5*U zb8Z~4rDy5ZGHPS>#x>FbFBZdXFKv>1Efoweq9`m7*?AmjZu)M2R21=F4}|z1Q>HfV zt0D?2vOroS3@TRwA_#OKyr}#&3JQ@fbdQ)^hLmQ8_EL>Z-?A_*4PL8(8iRa;@d%zq zZp&=>>Il(QA*8&QF$xrO9iG9+!uhBUZLJlEos$QNnb&Tgug;Kr%2aK6PBz=7K3`2B z_l$nW7Eh`>9rt5I&o&kZQJb0$(w0?h+5fSGglcO6NB(FW=Ax&aNS30n{LpHF^h^)5 z*fsp=Z8{MDNo0whBecp+_p5;cl=!5rFmQZ08f3@-$Pq$stw=bor`LyJLRq1~eygH_ zM(5WP_@wX;y{V$)#|%W5~-8-#Vbv_r}tDY4vV!-7;0Mu z#9CaJp)~}8O1sO_ne4oK11gRtiz=(DQ{$SXB{Irivi=M85FZOYCZ+o2aTd-W~?T!um zUVfNKz}bf9m364796n{jq9B_1pLB{*z~E(Qjfdh_0Uslkm=ku;~M)w%3Z6&|Ifb|SrO)}r2zA187B6xhcm=KP~$||AvLfZ z0cUwBD;-ZpX65|Izw-(M4U=1o2)sMKwhdfsXRO#lg+Zmpe8XKH^ zlapo}567v^R?*@M@Kf2@RYL>gWVUdNBbQdOf{&@8QHRN#Bry1|NB9RodH&`(st%%Q za?kIhzzhZjgNgg(SG3wpa|E@;q3(E;l;C`df4XT~*>^FBHJW;sp%|{UBBN`x9<}#X zWtkf^IkHltp12VF>vTDk3j4MEiL1hlQoWKP z4IIRfL%tuT+FI3y3_FgP`~Yi|Bz2(dt(?|!!MBZ}NHI?I>Rv}=@!kVjWs3(1^%sGv zKq_dpe>5t;VsQd(@$r?q3W4LePcllM@pmz0>+5N-#d8vn#V-{zol%$!ZI|)Kx(eJw zYe%5T!4|-ERZ-n50r={6ekKf-kMIZHn*7-jGWb`g;By2C0pLhhuCZH{vUZ$4QoBan9!Hq13Ku8h=QOFeCR z*Xqnn&tQeI7+gAyQ9aYe2H;IY6S&2l4p-`1>Xgn76s2?f{Ed=x{g!=KM5gM0*@W}i z+cNN3hhYX@7BXXnAa+buWi#gC@vk@xmMhdK@`9;V=b(ex57F6hjw0ql$qt-qxkM`U z$}Q)GZ><1?@qZ2Y@xJCwiQF4~mZ}@5_zgukoFV;<+dcDR>k9|11ZKFXHXK-EC5#LI z|F{6%`zUrMGE#d#2tT7!MM2r(Gv&F$n=4Dos9_--503Eak1*YtGKXKi4LCV}!k#pW zHda#2(-SQ`2uU&AB%Rs3s3H&HKj8t$%hxVk3F2UaU<30U=)B-8yPQ;1i3;7PFR*-?e%Rrbs+gz_z;`<;0*=rw*b)Lw~8|d9uQpQoBUY1)Yht`G# zwqS(OSV$c~8CY0RO`?FIVxQHDh+SZ>w;DSKt~Pv{2wB32mJs+4&Y^t~)O>E#`U|Mm ziA6~L)cE$#Uz~q+7b-UkK&Gkl1?Wb{63rjj~oIj*%{WCDEF*e{pQjUAs% zUSIL@vPIoWPI@RNggjX9=gIM&XXuO8v3a*j2}@ z!~}!OvG^$I!mtr%vaVpfD>Duo%lHlvU9*%U*~~9vkK^cl4Cw=phPho6qwC{rXCX+R z5k?|+5q9&JfCW{1Cj$yQ6{_Xi#1p@}3nMJ>!HLD(0WeIac0DG8oJi!K_?g~^(ldgA zyWa8c$RKiSbZE7@*gww=J%WtrF!hkMqT4`Tby+cC2>2{S4-^n#-G@xqVeLFK*iMB6 z%OVO$&xC@=+q7%vy!3djcBwm=@e_lCbq|K}q7z2%MNkh~t8CezKUGj&bv@cK4H@}m zCC^vwl!t1(p;257QZc1Y*o*mCSh`G=$?<)Rlpa{qVix>GX%l$7!_Yr`5$HIm-bg0G z@YDe*>FA|oZx3{4;YU+~4-I4hHyYXF$#`=ZS)Hs35)6C=O7{8zyt=tXGYowFl5I(J z{6yrQ1z%w>UpsGr*Fl+d1{q=c+HF#ksNC3fwK&($GX0Jfta%{Y8TMF^Isv^wTAC6& zSvPk6mYM%xEEtj}PyC$_l@T(<{oygn`T@ukM6p==?mDQ+LUo8wZeG9e1s}@u-9MN3^5*71G*(n%5fI{L6EYR?i@>HztqUau8B+J`wiPxziG;SCM z2HZPkElYZp$v^WW!lI|YbJnI4j|65NPezB-puBZ8czH(ccPbiEnqa$lAUYBhwhQ~L`?j%Cijr}g`Nf}<8SUs}`TtPZOZ786= zd-$C00<6?n(G&7JuZu+|rc7Bm=PM6};6*2TtJ)kcJ?yKEj@xiraskd67ppgpS?8Ui zk2awZ`2k7R2|trOUt_E)$pwmw-#Fg=)V+kgcI9Q_NKw|ETKGm-I3qj-Z?CSuv)W6; z*dC_h?)?3GW2JkT^6g_TxwPsq;X(A6kS_MeVZ!P>&*~9;(nZx5L>iw@yTivtlYe;2 z^d(G*s)^f1}bS{wlz>sf0n&KAGaof!nim z5#zl+KyT&BMX0?d;ERQ}b(g?|lMFKAs(hX=2=5uM9i6z-hJ{7YN)nWeF8ui8|xJivc4gw&ei@tY{)5%=eSP z3um?6l_87Rx%4z-2+CIHCSvT1OHRLMj5ld=Lgq{&xua_@ezI{koJ-21;Zz8yKH>+Z z=os4O)M#hlp%o?!v2%o|3@VKl{+`T_8YO_ttgJ(Go7GU$EeLrEJvYxh+hSQvDutR% z?j82iG&!F{{>k4(^T`S)Jwj%(Sl^tAxD8!ycQPtW#sG4c8((3!vkC%Tv4pm}1!QNK zj@JFQ@j*7r=s;Gt%MS#AAK{Q#mcSRq(6<^Vg|5rC@u|EqVEPRwI_nAz2wKA53wUuD zYKjv+y7n5!b?doME!W-LbH$M4Klu1lQ*0$DNE~86G3~mvldb$Mt5vS7VE!BzACgJ$ zAZm)KHi<7;B>1bh1z|*m~4O7@b`o`4{*PFqP~i)m88- z+D6d;Js$jay$?K|1`T^;Lk(o2wV7e+OrS;P#~CC%`^SSZ7rN_!&*QEb_jo#Y3^8rr zwfzhRX^)Uv`@r>F^Hinc3buy)k>k8@Md}fZhSgP*L^qO< zFl!G5sns)*SQUeiPfFMFKx#`66C$H^$OlGbBfomoh1JeRjQYkj8-{fyOmG$6mi=?yH?t~ig9mRuqSZ7QtD3|wjgxs1 z(Jdr0Y6N9dU&v)~>D467mVNuA2Twrc;pXZa+g=z4XnW!H$l{t!Hw$4hE4vKtfiDBl zVSE867dgam`L^xXZwoaO&Vk~MdW2s#JgGa2G2sDyD=+`ynHC?SJNmNY)_gLs02qg$ z3`GUk;+G6S&z9x8d4>SFY9HucZ908FH(FqKzdc?+V>5v^yKdLy^Jm8bvrt^7>gP>2 zla$;$!Q^|_Pz2|CE5)mbdb%v`5`i8Rk*MTot7-_~^H&Z}+zuuoJd`9{WQ4@E#&`0i z*Es%@c^5L#{IV)wWWfQJq8u9pRq4wJ4IoM;G1UMO2%otz7cpVlW|B7sZ+ZMU3HuqL z0N0VwOS~ate&A}A@$!^(V4T#X^6DMqQ-zZ z+KSaRfru7)AA66aQdjh#K1{ruHX5E-wa>+(5>{UQO56zx+)u{80(!uY{mm134Rd*Z zA)n%_n|bSh=wN-W3VZ6Od%)U#jz=mG>KDrzT2rTy#V8=={np04PaC}F_kkW!#NqWr znKyF-gcINw#Q+*#;iEh{Tuw{{7bH1z=13PFPejzf2188TzsD2 zPTj1%y6Cx9@ziln1)p_G=HNJ=KEer3-)BLp*8$?C=2YRV0C}{84Np}oe0ex=KKW4P zWN4}LO8cLd=w=hi(Y0(RPd~Z5(BVW?BxpI^tf#JWg*VPJ#$RsjcZ9x%7V_I_%w%vC zuA2x1`Osbm!BK!6I{|TCL%`_zJ|6ANZE8V5#c{qp&9Y8X`*kBSX|*0yicy37BYvA( z7*VNaRFzR8FuxFL%KC{1_*do{mD@?wco810ECvtG4~Gnsnu++ar>u@CYH5Q`)f#p; z=pbp&%i(s)Rthm|^CPl#!Q=2|*wj0Vc5P?obz#PVWoD?O# zV{{)UVtR;VM=TzpN&^|1=}3{h6tbrAs2_JrE-HOFNV9u1AGwc`+M3czF)Hz7-=k6l zPGI1A_|goV%)d>c5Lx_lW8548^r~&XeTU1+fRNa9;rjH4*nwjWMajximZCmqIPqVh zWt(bH2vYd^DiY#4njy5;==D@)oLP3S>8X8n96^?w1JlkFQPHPydz=6r=`A&Sn}K4I#t?uy_Yl zkfi)F&LD`(7V$5KP=(*U9#srKJK!y5;wYK;o?kF^Z=!8IeM`~&hmD6@xt>GRsgYI? z$xDle9fZy=WxJ;E8Ci>5+klGgZcbipFdt^#DH2&Kh>u}Fz)Jf#{jVB^I_45=aXUCX z6>EYX2>=cr{?^nWzn(DRyYFA0$Mm^#(=2yrpY#iP&f6xHGa!MoDS_6pu{4qA2k0@r zp>VH<)peh}z!FbZ7Jk!i3ili#3wxuMXdFEN0HLM>P`x2Xa+6>;ZFSu4yQwelB5r*Z zb3$lDyb`=l4UX3^sWDW+482(BzQHm#p>y;sY49 z7F1aB-&X_1k3egAgmu*0tih#^GOyg5&;>W4K8@nM(TkdV>e$V#5>hmnyxBAj*=7+?;N~ zius%`F*S3i#|aa2VfnJ;3HZNS`bxSgkLC!QPr&g!^$Xx$8`N|A9G83=G6 zFRnW@z(EH9Cna4-Jp_?_Sb`+>2aNT-I)THT!-I{((vF~0(!8}Ih4=$p4pH>u==q3jagVb8LQX7MN&^O zt!z&iLc*^KLhbhU#1iijXx>JHL7`=xLMKE9u*3!}zvjYcPByb#_QGf6mTKxSyadKS zk+DDlXibi;*JCwtelK72FD97<1K(2AsaQ|P6uKSz+^4#^Z5Dra;`w>mZJw{(E4TXI z;qfWIZ@m(QhM6arVX-?6g~2|1vTgWp6@-xzKHb5$Z@hc{MDz^gcsicNdSsB2L-Dc_ z1c-WH8dLdB$G>oXUM{Oi8yetK`aFjS9yMG!NSvtl`Q28YYtqr9t><-0(tmKhyjs)T zdVvAZiKTzqDnv9G>9L;`5tcH!NkmixI!(u4&dZQx0_D(M?NGX*r-d@GN-2cw_+z=P zeL-#Iwhyxoz7$1!{&4{R!v&w#*7E@ucm9z(AEr7K7~yyLmrP~pf`8K#>g4W%Ut!dY zTy|HJarx(qJAGzI zE!BW}ZlX>+sjlbwaSM_6Gcs3g<~Sxa{8xJjI+>=!U5qW~6#)S~w_V4{eT1?W4^LZ7 zQezV`u+)qPDK(foe01cob8tQveWuf>w^S``uwkx--7IskO_G7Nz3bw1vCN-=aIVc4 zEaB+A8>HnMwTj%jo2pyo*pvw_`tB_`eWl>4kb+ZZP4T4Bd_V-@`X8U4I!5FV+Pr%` zvcQg~UWZ?u?L&{aP;Ye;9^zh?C!XN144^!%lm`R^iq$T5;cY{K%#p1Unkq^_g42M5 z7V24UppUDr(v#K{P$FhE>|vz&1qA=Vd7xEtWwIL?%s*KZ3qH%|995Gp=^%4HD%ix|A8ZIO2<{&hZ5Coy{DzPLxRA)j6363jot>V}i^~{hk)6kt zlcUZlMQe-I&wnGi0c@<`FJQMe4p$1Sz&J1pMUy`Ivxa?F)Eg8A?2AHX#ZhKAxr78oMmOnBGs;8{dh-0?Jz;%TjVvIJ8|LE@m_ zz~DY?KoZ)ptCteTJg8Z9^P52C!co?hbg4x?h9(U;HNEEKx5b%ZZ=Hq9Qk}A(g5bcU zCl_B@A@j1U@9oJ75C@BTa{s5Z@KyNmW9(^Yn4ERu7o z8@Ckg1Res@WLxTe&hl+aY6*#pJ$$27Rg;Py6QmL>7rdfo)$wVrB-nnC%L;#qj{Aut zy{&MNGX?$+Afu!MQ(y(Jd<_FR(zRyrSm(tjJ&umb!NOkCB0613edcu3(VDL-^eJL$ zJ^6u6r1KETxIm`}4<6-EdlVj=8Jj8Qu^W7J8S}1!B)&9mwvWyVUmY#rtRFN0u@H2Z z))i@SkM7&GOZ`8%IJxgK(E9rOXHVzz^>5Kvju?mNV58`>{b^ZayV+N`P?9T%t6{@} zsk@W$Z+9`}cu56#g(JoAYa$~6poNWMWvXSnfB&}m8n&sHT|e$S5AA1owD7bT((j?|uG#DH&_uorKy`lMK9}%(U9o zM?#4I=j_L)=U^-Xr4OmGlM$HuTsTPzq5#+eB_WZJf}o-j-K1c4rY*GuE=3>)3+zI{ zX+~m`T3bAor0RwHIF<73btq%B%2hz%(aJe!TVj+~h%^04+CuOigiMN5Tqu{|dR0J5 zUtEatCdoaOeNf|&&&y-%*x*T4;;u$l&2=c~E;$Z$?EtLq{28Wi&wt?3ReYNCElQyD zBT2x;qoer?ib;;|V@;3NRvlusUb>Bc`$I-s5IU~w5hu*=92LfF|w|%IkKSemg7Yv;B&rz}c zNRaPHt|Z7XP@l#VICGo%XY_TNB?XR`RntmJQYElE_s4F1#|yrX>UiPlp7%pXWL7_m z+rkOV?sr5-LgMf8ZQ*-7lem@a_}1S%A)Cb%@ayaF>-K+(;j%`RQ(AS$koCwW;jz1J z3OOs>vmcnr+V#quPse-(s2>j^d?_QeADt1^W3HVCx)h}TUJ@Y>iow#s+aJ}=dhX>W z%&xrYa3+i;8q()ke(&98E_67Z|09|cvaG8*dPkIg8Q0TuC*T6;k6f}QY4P@{nu~lb zew?q)I1birWxynSj%IwI(-TaZG+CCr34;HWv~YQXG=?7XxIy2GRCTgucMi!a%A(+4 zL;-$HjCt}<7b}~oJ5+PRGH!nPS*%PGkygQ3uo;8-oC=U3gCXy>!X0gYmprIrfd4d2 z%%U6%w9ur?0w@XL1=g7UDEvM%4PMp%yy+k zKsT{Tdt+GmVjPe1s$Y>0mT;!N%Qs8SqQj~_uhY=C!*pKa`ZGCxAAa4j`PzbpIzzHI zvGK=uGTn$DmMh!Xb82F(?<5yI!$KZ#T%V^I>UNFEJN?V!FwNaQSh$+E{P_5-p1!by z!bd)Vga|1J0T+Jp8=a4o2!)Rnh+$5AyJXTyJ5s;Egewb4tRgQ~E=64#co7*(mn#*_ zu^}lcB!JUj`P|#uXqOK#O?|7Uo-2>7|D__!$|7SBWu%Ihz(H@JfrHrP8?LJ+T!0ON zgfbu_%e|4ZC*sJbg#;6buur%D0QN|N#^~VlgoyWM zgxFEn)Wm&hQmL`9ZQnYG;@zMn>!Ye{GE8z*WGnzg&*DH zkjFQ6_Al?IGNiHM@zuxO%%E#|cp^#R80PlWh?Aec(0)!uSyYBXvf8-r z3zlr^PE50opQAA~(CN`>gWOka)tm`YQ71AI%6Nc3T$o^0pXVi$l1N$Wg`XrS8d%8Y zbc)EnQL)5fY^?jIxZn89Y!hkxx&6-=zkIGlaAax! z@$x;~ykD)xBfd=+$X8KGpRcRF8|vso&j49_n}ideT`Ii%nkJcR)~TT8)OB%|muV?^ z2leM%w^KF^`}*zKJ9yvz?h{@jAmqg_cHWEAV(;PMp|0zZ-#x{H($y@QBuAH?J70Y`4wreuITEB}}f znjDA=OPGtB|L>45PD^*2I>7{Pa&m6AH&Sn~Yot%$op3$S=ZPX5{4J3D3``<%fbYZuBY? zK~*$mpja{x-e(*Y-*CQw*3E!`@Ep#rKU+LmBKpPxZZh|VN2D}EmNJCHt zChC+-;)%1{tj}vvdut$HU`M#muTKg(F8}_PYt7EyDz70iytg((Q~{XMK@O3vVA*AQtQcyE3OjQw5ZIBhn?ZsSctcTYo*5}06Ga> zr3;Jy(*mR|4>1uIOF&fT%zel~P*_s??cuBp?F3KYi9oAUYhdZSFaU`B?3>Pm0C^#E zTOi?LSZaM+PX(3ZG*!qFH&7fpZ7kqZTGX4W+@Vd`y(-#Glg427Ze4orU1nKQNz7bq zv}TMYyMlmfXUX3p%+?mUT~Po%>`HHP>$9h3-*b{%>o(hAcxv0y4KbO!?S|M~FS>oY zyCErm=i&YOkFz^#dzPr@I=aE!0QGq7$Ewe_Sb+;I3epOG6-Uom=`U$K`f@;@Jqz@T z&cmNNA0WOyq7JfpkDx!X>*hsD_*jrciA*ZwZu%7ym@Db>YYL*Q`mQLmo)s!VRfs-2 zZ{45}v^WM2VGu2)RvIGx`C>y}+SXPYMz~3=j2c=snu8dCMfrO`n$iPVpK7S8Ho<@x zt8aVyDB9$6BW`n2V@EE$NP7tH@2woSv&8#FjJh3a)=$aN%VTK-!`npULreHhfHh3D z3!OJ6zv#8(S6A*^QXA^uc>KhrT1V6sgWpQ$mv25eSF5-vuZ6=wI3v z|8=d`pTY+Ni9(@EX1{17ADvpY)OxHi$-zJP6SS`8M-&ZXJ{OP87qWZGpByf6iFJ88 z=8wO|&L_IN+^NaiZ zPD-GGPP`;U22?DO@0;9BsY(7L#T8v-RUu(Z8oK!#b!nZADHbUn3_m1>idi=EO}$3t z3pj3!oidjQ;FDi3`w&S@P4-qJedg_vu#MlWS7j$_hC%CN@UgGgP5n<(F4neR94RQ2 zBzoj*@tI?GfAjX+CkTHYjJx5Fx9ryZ!VvZ?FcxN@s~^pW{yu2&xM@}7c`&%wvJ>zm zTdEu17?*Y7tH`*veU8#uJ=XYBw)XbvBxCd)DRahkq6JQaY+BaDN9Drt}J5cF#_yKAykkmnM8 zZ>qyYs_^f%0_e;4(T?tH#eVwoYCGQkvCp?VO_E`TBzILfD+Zb}X8QRKCd5joEztaq zQIT^LLr@^XW`H1nI4Za!U`(hFa5h^01s8AF$IWTDBgVGT1wO22a!W}gwtOR zz5q+D+WWS;uRZ9HWBt{J7&y$9?@0O@eFyLQZ)mm8B!tKnP((&hD>S8cV=w9pqzb%$ zOA!*iXZIZhAv^C~Thai6Qiqwqfmag*^v-Q#cS+W;DPGdYv0h>Zo-$xd7`p zUwuQGZa-reDCBN`mS182%zB=P0NMW2iRHP78cUgo$foS5oGk`FeY zanncj)waA7tcW&m_9w(Kq(LShLe9`2qcVl;P1}5hgX-sR5Tt{P(epS$e^7o;CB^(s z*$z^mpeF<5k%2$;R_Z`n3s1+^#fM>q_a*erthyzlIdV1FVX3b7=`iG6h4t7CMu23c0m&TC1Aac(#Ru zP9@Rz7+c;9ZJA^;XW^pRukT2){DQH9b+9FuZ58rDPjBMfCl459S5!163Ldc^Vv1o5joHt{7G;QAwI>L}>UyC= zqPPPvx^8UCxXfOmZ&t_Qs(kxq(RYvEB=kkR;Rm|4(6ZG6c`q1c_+dWT9>5J-^SX=o z2&xBxg$S)wd%n-8s`N|gzvdF%HuxB9Da4jbCV_$EPN>^S?2dvT==4(;=&W&lT80ns z_g?jg|H+OGm5nn&jQjNSd~fL3plMqQ;e&;g%wnZcX9{{sT&jSl6gHa%0J%@SWSW4Rds%A(rJc5|8B1P8zI zOCtdB;VH+3=}!(8W9}N!u}mTR95tG;#-!I+C81>1Ap5**2`n0A7u^gsk{$;_3%fT! z_sYcy9*E1CI$Hd5U#vMU@Y%u2AY}Z#E5ML)35L!-J6gYW^cr7j$`jinX?(YGKK8Tw zqGq=DWdEbrYR~(nIi@`v?AX+$qhp*Oqn4ydww-ili>+^7PNjjhC!=lNuhFD6_g%}j zEHgY>5nE9V*xp=>`LrT)WzOT==0SlGTD&i>zew+bdYix!~0IgT1zxKYX##g`TPEc1(%%oyoa_wRPg5qZuQ!Ue`6IL$6 zk95_+Rc3pklSOA|MsJ}U^+ogC)a~ZxzrT9*B>2jBTGkb$vQt2drf(#XRSp=`n$1*_ zaar_x^r^Gdik#?v;~L}h9Uu9 z8de-hmuWzdo!>U1D%=BC)j0}6Uj6-1XdRGz{ku#)>f5b#7ylJjqrB%gwCOJ>+4NHF zsstAndQJ)I=YUe@E}){*U+6O`MJNUB+NnNxH_hwhZ|j`}cgkg$XN7^(rQY@NmeBB~ z3EjQ}AB9~Nn+9&d+jBu&h)9WdBbG*gD36xKLh3Q0Oke>)>e1!E!RUx-6;YnDP@Zwo z`wI&7o(~XH;I>*2#Z(dx>UxH^OBf#gavN1KcQ*brL_*JVr{gEmno!$ge%sB&oZW|_ z?U22$fT{grvCF3Pmu^f_p1|NZ-OkS2{iQ;T4wcT?%kkjAkz1i8rE?vVVOgf&be30J z*acAI0M!7EKYS5EJ)*PBe}HV9MdFm`4?tfW4PZtLAUmw_{&)*vmU1kF%6=Ay`=Lo# zRmO~CvUVRsSmtns?0Au_CCpJ=Ts;(z*&niP-)&0K(}So0qF@gJ+Z#6>m9dRK)_tI9 zvat^Cg_my6o-gkXjWIPTcU8+PLZcN_XTzp;Ae2Hb3I4Cs#iOkDd=%O>y!omzri!ty z>O6BA*AP*9G+0={uCKK?M+$_|OwT!;e@%q&3h6i)ymj8v`N#)!pnn4P(8t&O-58hm z7klqf-GPcgO~H!5bT(VMyiSf&<}Kh3FX9R3zJ?A~b~1~0`rXC^G{4*w%_bLlwlGO_%g=)r=bu)p6plB^b<&`akm;Ss4X(-hp92ReE157VG~-K**vlWY z^m14*Y@wHCgPM@)Trm%r{s#pD-gnTcN-$aIhk~3Ca$%S!T(*#;cA%_4T!g=I94e5f zX(TS#Chkm~T;u?uHZZOo9DpiG7rSj~uHF0wzNO_(Mh2E?KR>g51^>yq+&MW}>1M|i ze`!6Hx4XlK(D^5Up`*K&3m*_5j~mg?u$5qJ$>9L++p?r2j3KHFF2Cr)ecf-)H{Ve3 z;2lwczZ1y@Uw=;YdF@lo<@^piPHVzPSk0wHEk3;L)L&Yv#L2R-GYO#W4Q|I=vhl_(Ufs-oS-Qf!?m`u9*-+i44De_dJQ-XM#MD&RF z=oPni7RI~%{=!P$asA~n(3#s7Ey7g(P&AWN2~eC0AIZ8UD>-V@@mWxc7H83xe@nuQRT zmmHc_3JZc?iIMjAgttC}h9u+v)@@u0X~2!J*|cO>yT{7R+#*iQ~6%pCzFw7b0?SQ6}+ z&Yr|WZ+**UO4+}Y`HM4E!-QzctXRoj{Bm$>LklXZIoF}FVv}Wvim%ifdiQkUQHr+Q z0*aT~Gld^9^nfdfnU+x-4!Mv^Gf73H*#+Lv2cl}O%oU;HBL`~&7=}60WgaC>X^G?M z=`PnUC*@(?dVi!>1p7CV0|J& zr0-md(Q_AjR1@n>=!i>@36iM<^r;w@9&}vyPBe3=;9c2QL}1;=z7M($ zcQ|2f;nXyO^cF%J7GrVA2PC+i0ZKw#?B5Q-^8J!Fl_2j$C3J|1A35}M9MfnXjF1%% zPWcIdecbmNNrBg$8VaKQ{*QR~lg%lYZZfi-HD~5DQmS6@9v2Ms1~fnljSFiT0f)qZ zmQskU<`h>Nw^u{2t>48keZB>I=g@dMKd0ZzlSZu>#ycM7g`ZNvvWs@2(VjmBCAUgX zE1_0lh%v_*6cKT<{%2Ndjy@G(iWKk6Lq`i%huCEcOSkzLP2V6XnN*uuz&UnjMd`Rc zqZdECQ*#4~7DiN6)lCY_cN)#8=N2+$wnF*2=Oq`)V`U?lHk446IX@e*$L+H#aix?0 z0|VWeS-IL3eL_GU?Y{4^cbI(S686jb^ER*bG&5e;K` zJZC12Bb_NT@EsFm@D|Q_03M8tCX4l%D4CIpjso?)e;1XoiHwvBTh>eZfgT(T_oxns z%w{f3t?hz)xeKI~KZupkq%=T(cxV=~ZGz!E7*LHDl{|!uA7CYy<(ESgrsw24?B^1x zNT?z?RnIT4zubKEXw7$~7M3{A*`C zPdA9eCGS3_gxEsKw;CDEiS}n=op7#dy5M71ks@nSX~8bRrM!g1z%k5Z*W+T_n3s;| zgGJ{D!4qg~d3>~zVW=iV_9*264*^-CaFnquLj112v`I+as-r^bCAvVay|Dv4mcE8t z-VdxDHdNNoEvLJBl`GU&;mQ zE}d-3wMYfnnmE z|HhLJeOY%9Vb8m3y4a4mq)_zbk#;`4P9gWZ8Aj1(+gKVY2ty zulH-rWY0Y)3@rUhy7F}UWp=dd*I&;SOGHOXraePb%*kqwVnn$~_PBDj$0d7z?k|6x z5vbub=UP~gr4!-_AH2R-Z_GboIG(n(uHvaf^75Vb07-fX{_e^~hwsn{W}3 zOq5cQ4;6tgQtiMy*CV_iFx!#Jn<5iEZt0-rP!)At_6Sf36Mp8-iOZ$DxIdDZI1>B;KFZus>ey4h2?6DMy z6XvveWm^tVUXyJ$Z$fX`}v|uS!Lqm6L z05*gHcVuWNwC}B2T!E&eknz-undfqTk%Ef}Nu`oM6+Q*13ydj?Y7n6l)+c@S=4r9A zSx6mgy>1$;&(c_PpZo;nBkj5?prtcxp5lLsi+|0U&r5ye>3W7h8VZb+Ion=$m73XFD!( zWgKwH+pKQ{0ZYio;FF^0ZpS2I-Ub?QeG+?H;pfb7Hn1`3xb1zL5}Mxsg3r%%h8WgX z^{+;zpG!sg7;=EdBo2hCsoQ!zt;S55OF7kUgS!YC>#7bvxL5IG$`3uJ5dk%%(ty%i z@YUTH2iaQQw*6Q&Tkpx-xI7-g4`d(7?mZwcxw*v@XL@Whe@GzDzH<`ot2OyDtR6=w zK08jA13JDwoWP)-_X{$YB39Q)DfToRpan0$Lt5FjCiluVl7wK_p)}aY>n3`*fFg~ z%kxjdT=1)bviJ}1bZlIr=}|Nwz@n}4c@a}znf;>1YzOX`a8D6q{(NE6X5@=U4mI42 zD9!$h?D;?#`2iO)2oHo9p}}9z0I*ZRA4Ghz+PG#Wh~X;w;kjr{-h<|RJ)m{0xp ztd<07sgmZ#FRyj^&T5L2WmCeN8`5TY&DyL*gp4O$iYUU|j()%K> z*Zv^@O1{@lykkKQe{oj6S=is;F4S$~^&2K%qq67>HE-gmwB;+PbL_oZS$W@EctqFO zcypFx#O7-8&DtOx7?Uj-Rr^EnIz3Y-^f@UM8{XWM&tVdA61AW{-JEjwZDlc~?A!Wi z9z-5QS44P7i)Ts82#7Btuw11{DRvU2DDhR2J0>7jxC3jtc~^Gdsz$low*Z@QATgf< z&@T?oCmttG*7yc{@i`MjQr5r~M#M&<&B45Xak{{0XDdI*6YzLD_80DQLI4uoD{J>j zxZ@mAWB@YiHBi@PHm3J-K>*})(kG1jHV^2fa^9`Befd%vGD`9?2m7MYT$Z{OLIb^e z^iKPAe&;QeIl)`Cx204az8oC!mWTC+(&Bzehs~D=S-XXB*CSHhvyO7#MEICuRS7!! z3mJ5anOOn6xhTd}{@GfGt+0dXwKmK6F~>ybD(1iK`x>0OLTsIDosQ{)@a_|5LY0k| zxqfn^qrz9iJw?7~Na-4#l=T+5iEbD!#(U|DRp@A%sYabBmWNo3@TVpd_;#dw3qs?y zF6o7V;GblfEJB04w$ttyD1rOE3!%hPI5?qr5vp$5un*p7R>ZD(*p_QzSxMWwcJMN6 z@UnUE(!;^QuWQ3uK=2puv+wJqqn)m+sa(**)5}y%t#4;%-4Qdiq^fJcB-se17)2T2 z#hpyfn6rck^64|%DJOX5+#qEQ?7 z+WkQ&t{d7}EMvydSWnY*S9CLIL|ID2n4@*o<*3N4T8LtjyphX$=O z90wI)caWw#E_V%&Dn1QL_m_VTR&2!zFgsW1qpB;J-^kZ9k<@7 zg-1_NlfWZC@VdCtV=5v!DW=Ky*irwwtC@Y#JJo78>USF$*9vO$GdJ$=*v<-o%RKp4 z){t9UF^N0B4J_tpg?;#j!~kL#LkKrzS*N(Ze9$)EjcDUg|jF`X2M}SR;_~bEp&~S&8pGd_$v*cU@ube0eL}_BhjB> zB!!=rJB~qr81ciciXsj3y8@#$jp zh@%(T>Y!M_Gb(npEOQ(5=bzmo>%Rg|SyNfyzUjW*!{P&VJTvD-}dbaQ}LPZ{Xr8 zmt#0EQf-*0ecyoMg_t3R5LtQX{g+1WHc|Y^j-^=ag;|WwWhgI0SnwAP1?@*IBp7bR z8j`|>i#h*4Ex_7r0-^(YKjln84$rJ)GWYReqrbFa+*+miYg=zIPgtQLwZdydvj^=)GHsjFNz4f*dM@hB*wn&JR(7Krp!#^V^N231`StzU(4$}qSet(1rrhZ!DUmGx|} zQB&7m#nMXFBp5rwmeA0y1jwsfQQiB_+n+t)#^%Y>z7JY=7U;a&{Bi803;*Z*T|e+& zBYs{=0OJ>?0o}PFGnBFKscZi=ZJuoXP)^%XJz08Res%9HWcQur$7qqBUP<@fC8$XF zj>pOsj)*Mtmf3F=E^Gg^pUIL_`T_lbm-6+IVpLO80Dvk2ad~}DHx#s!TF>=gz5WUv zgZ^B8-(Np=YvHBhwbwxL)D=J#FP&J#%sWdg1+8v$vEas2-u>K82ol7@WWebg32Z zkD!q)zU>OdA_GMbIuHSAiDL*vu0LD!Ir>)z4%F}=sR`W6@}`NPVpQdl-D=sz(+O=m zr;5hrF3eToAh!+zf~j5VapBP0L2&~YmQC#+e6MnCR*Z#y#*Yt|6?o}Z2zzXs`Dxwi zeXSk4kaf-8=D$NUQlT3d&_}Q>>F_Oqs@K?E z#=OJ{eVg|i%F3sO=x)puJ1#t_tsGV`C~_F>yiXh_oAP4>waCbAzRQGD> zECgf@V>-#jV07`GNc6`EBf}2jCgspaN@~bA-Wy~vW0>Rz1PXWl&`y3_+!>>7iRHzu zt!T6M3u&4T7Wgp1eQW%gU=SpT!b@H0ZGmZiCHM??Xzi$(_#i+2bC@#iKn}H1fkDj@Mc| zuVWK)M`jdM)8W@oCYO8`@UpIkylNZqy#&0tJj!)#w^&}iC0;NiU#?OUpGEb0qo=p^ zCKH)&{uP{-C+{2dKrrp0lpn-+*6^e)cxtJzz2G<)v!t^q!t%>U?!V!ZeWj@48=sve zb5WupbkDq{z(caEUy`Ud*Vdb~gotar-?S}-=Tr(KDwb#fz~^$c{`ygQhLTmUSVf0QF-_@LY(+KGCyHsnTWb)j zMA6?93~vcnof5_dTP_Sgfjiyeu2u#gPd778hXe9XSy!*I{-d(i^mRoClgWHw%hrl~ zhqLB@OT2SH+sbfSzGcp7RkuxR80Fx&zqOHJRLA2Me|$;x=evA_cI4vrIffmk3vR}# zw29VeD^5xnqpMRfqdX2e<5~CH-P?$^9dTx9$Mx{<@JbtWb&OQKvnv@B?!}Y#Ht9br zzORv>r&K#A%ehrqvGt%-i*Sx)`L?d5%fOkfve%&~w59^QmvD`1OdMxAAH9L4maC;TOIt+W4>y} zM5=JRc0?3emz-Y7>%9oV`Y+disiAqi0)`mp zl@t>B<}TRnc^dEEHc*GweW-UIYCTs&2)d%1GA|+P51x@)$c0QqFHiTh zZTIogTjt13jk(pE(0Zyw=?n6D(hf+1YY$21Q6`VW+{_#yUjaz)=)9XPoP-hrq9MnJ zH}AObj1^G2pu1VVEWqao{#BL*#0clABCI+iez>zjt3f%Z+>uh7dL&F~B%qckku!AH zoR(;~Sha;m!X&H-Ad@Je#c6v{#$Ws-kQy#Jrn7nbD6^V|oHbd0D-O4MfhR+(?I)wQ z_Ck;Udr9*ML=pVQMZ5a5p}=@7eJ=PcgTK~u5tdk2Myd`I>teCEL^Z^7T-B~#mWp^$Wt3#*nGfi*?ztal$ z+_qx)-*PAKLZ)=NLn%eo(w=}NTgPN`m{!ruDhK#*WX-^oDu*^2K*_F1rJ#w2e`K17 zse*{`BP^0`#m{$bw>8?WeNbv2xhp|3=IZUP51hwbq4aiI8Vv3ENYi25qS}19MIF}~ zf>~Lfa69;x{NuM{)74}zTkG*?{Y%N-umS3e$qR~A@YbmJjB@hi{%~Ww(l$D(Q%6`_ zwf)^xQq_t%LzT-~t#haM5{+2DbZRQ_2fKl5HrB_F#Xk`-P7X|$QL~nU22Ivy8g~C{ zlCbQ7=tk*z#O5}da@w-Xx%!^sC3Jj7_P1ynS=9^Su^ISpmm8k;^p8LN$cXM&cM-CR zL!@yT();aO+f)YXten4`8QvOnOyhbS4D$QvY%P5HdqI!+A=E(Q=dkl>)u0!FZllBT z;aq`y#OEH<+MSJ9BhRaov^J$z;r(-@KD1RFz?ca8OOK+|2Vw#ykyrYm;dj{90UzEe zm0sTr`#l0$&=WpsKk4TKshhCYsFfwA>t~;hzQR8SiE-IfNo9N*PRc*yQ@oyecM8e` zu){Cwo-ynzeb=go67q)N2|X}PLuB!Y)tw{yB|R#P5Mw}|%&`%ry^_yrC20myQ2I`k z&%Fac6&;+!;e8qtArWp}{Wt(VSX89po-&RTMm4o@n?^zA7ce&v!PzlqSM5hvy&^1r z;DZIHhadadDCvYoF@57~&OPnKFTco4epUNPNsavHs$*~)dn+82Oj=`QT30~quo`#3 z%m9%MJ5k0L&kYBak)Mi0;&+FFeRobMq%CDosEN`lQUyFAc88>;lFQukIsqjlletD5 zz*^_0N2>|$DAj1OQj@4-fdco@&n%Yju}tFfj+zfC<*T3y2+D+tZ-5wCNJi*CGk-}~ zwLba!iHpC5{;RaR-U#_P5XExw_{`0XC6eW_kTRNh?6xEaUxcS%Bsn7ju`rReU-~AB z40rez1t2vAcOA3)gR@K%!;pvdj@Mcbq^7!b0zGaENr6+jPq20EZ0k~cJls0>ZqOC} z$kqOFFPwelMw<`Uy`tuyA2Gy4FI}pHW}>DH``@z1g2otjR3hLNvT-Qu3lA*Dwe)^c z?ciKFAV#ze{o$A#d2-)!sKPlep$*KSt>H(>zN$=vT=C4F>m zKgv(BYrkB)a??!{Ix6lgP19_&5?=q?s-&bG{Z8;{D1-Nwwas?Q$*5q=qf_HDk@oTS zQpnM^&O{tSb@Pu6nMe1|(p!0_67HG;0zQ^4SD6J`$?v~7zLpQ7wE44SlgJLwS z*7&p{bZNQ`+o<1nJix4}(L>%_SysNkd5LJ9;<#DEUyC?dUbmW#Qv335#hDn3L?9%B z-lR`5pqj=FELeb%Ups@Uz-;qlQ_PXbuul>Q5RE%QBQx9)1x;mg7$ODOlX9YA$>R6v z8%Go?y-5afrfe2%3n8c9@-+b#HD?scD6p{oC^|_gB_z(T##mvyv;Lv_2&*gV_fk3SzUfaO(ZWT7W4v$KQ(C?Ix5QW-m| zWn(iQSO~mXB%B!@33Weh+(F53)FKs#p=e?P^qGet$wPDNxk$WwLrMh9b%j&THYD#En%E+nH5?daW?>1INqP?vwwi;b0yem9?ini9GZ z!iCLP4%$n4Y_{~{R%7S(I3wiGBb6ErJ~>EG27sAieW{tU^!DxV6EaW7^{g7UBxDtG z6yFcy)3>pO4ZoAAxJBC46NQgs!M~(Wg*!<1430xZFUd@-zwu7Pt^CdheFF5itTD3q zzuTtl#(KLoK277)4-+<@@JC+p$X|Yomv(JGnq2Krf$24m$pK>yP0i{`wbeS40wmzv zg3Y3#V?P^pEF6ps$Ef)=!iRSO&Rl7Gzyo&u9|~R@k79xGZqcQxOI?G#)HRh*OI(GT^7h{Ea%JkPW(ECibo5&3hKkL z8$H~Lh3H;Pe(`#K(M&2GEN={V(yjf(N0sjF_|h$T!K&LYxu(gGK#7TP*FcCruLwTPt2vyhP{yLL<$Rh!^-)0JC7yV4vR*NiF z=5y&*QZJ;k*6M&PfX>hDPz!C9Z(+bt9T~SIf$^FiT2cHaQQGCN&aNNKp2w*1r`1sm zLPv2-FQP?9`zXH6!0zvsg`Cllq@$%}7E^S?97B)lgs(bPGx?|Rz@F-?_0v=8PVY|) zfnyTvNT%NWA_yhw)Lu*CR)>yM>8LNKp4#aGCsE2ZU~Fn~zEfz}fKD_&aavxq#%|Vg z#SaX;dfoIkVo1u#m}%T3G++KqI^fM7WQjvn4Y4cXY7(@Zp}9tYr-%t9pWU(SQfl0@ zq>ZU~pH4-vgsNR(ocx3j;gEb6D#Tv#ZA0-f55pt3HkXbIA8n^mW3u_Lea$x6AFpk^ z*L&F#Gv+^5=3llbAz8hWLjif5>Ke9a4mtsJF#}zSaJVh0;NKL4otW_K*AmX<+T}r{ zak#~H-xq?+>(JfkexOCp3OcI?5LRdt)62xhEkqDn2!xrV18>Q$H`B?fiNJyqsbfV^ zU@VFN@pgxm1|(U!H29cBqZAM|IE5jFt@8HtX|?n6F}YTMtj4cQK})N_J3I9y2=Xg% zzs7Jhov{y*E-#ia%XlobH9D6k`3SQ(E+L5HSAy7yhCk?ixf|Fw(5iGGT{_>oL|ZBu z(lf;V=EtO+#D)2@1+d5*Y#z)=5^-^s&q_qSMJF6!%A~#+RDpqOm$KK*0fC>S*Z)NO zFEY+&avXKN<(*YAf;C={%FN}4EV=7Z>!#zL0PvfblD9J2`4Ir93cn(G-Z-;;J9B}R zxJQR3f8MlhOspV&J4~ci^O4A!#CvnBno!+mn@)avuxL zL`fMGgPjbA{M}Lk#)c}c7D{;&{jHWwoYw1x?PZ7GlAQPFJuY`o-7^a?^FA_f4Me{V zu6;Rh8i`e8{*S9g_j;?w2R<;0w7*Maj1zxRj1^7}=fhl4`DD|xLZ`;9aw;UZ+B z;G`Wqv(2gv^|r>pM_k%9R;`VX)+;=<{YqLS#P;HQl|1yApA&sQ`0WtLya?_+6X6Wb z&8V!r&MQxcXHHm69(H_@p!2))Gx4116&GEbQR1%kp@K5cl{*tMDiTlP=zz>trm3B< zK_$c*7v`rY{8n=h-P@z)v>1E&dI6P+osG8ka-b|Z?ae4UQD*HTLXYM+hAolF&^OTV z*p^-;02c=xF6Mw^U_t$fN5l?iNWQ$HAoyDJ$P4fDU*c2>BtsMu&4Lb2PR1}&%jiDx zik1+>7=X!d#)U&<$3o04B;8Re4FSl>$u80QDOLFYc>2cZI@_S@J4T}hO&Z%a8ZbiUq3TF#0j1gaoOp}X$1eB%DiCyc|LddfR3R#{_-orrdK^lRGorwhRLis$ZHRu z;Dhg8H@^b2?`C<_?>daNarNxZ)7i->mVobG=3#Pj^3Jo{tdZyGRQX|?ZakzsEZEo= zWE4GKq3?Jv`*s#;u8=qN2ffs?=+Wu=*I(NsCFAyP{5!cXq&pGmsd9GL zjNtM+_M!OOSK1g1!otWvlHN?_3lym;MaemQI7RY=!wT)yR&f>LX5G0xcj6X1Yp!Y- z?ipob1u(EZ!6_6^bjN|tmE_>0;Yg)DtaDeK5h3!wv$whAXflq*ltS>-XZ-`W{Wo}X zT&KpcXe~ZER!Abe6TqST(tvElGPj}KCs`mvZDiw57G8HXZekrclduwW@!QA=!uW4tj4UwleM zM83j}W>QIHKyffFU1?-Pt*}U`T(zeEGXwy45^o5+V2!z>meo7HZ0i8K_&|)L*7FUAkc1dA`8)2Kv0J~#=MG)RKZEJ zH2lP+Ml%%(=#9hmJDh*H0V3T5@sOpxbOk)#=JFi&c=B=KAuuIjCP1ekL5RV%jO0T8W#Q+o$ixy3bzeG8?eBPvGXsj z<-SPk=HqjiOe_K8q-`dg!JWE{HkJ+~=-BCIzjSUcr}*W;Y+*MM`&hVe7ndeg8egcw z*d2n~NOTw{`kVCzwm70`vI$`-^sE{LG0^58&HK%Gcb19({`P#JR&R22*E%_{qwffP z>+&cF#ai)0+Pi%Gfy~D*9PIYuc9g7~AepSLLW$1p;CQy^{(&vRXj5v`}Jz zP*frDN`-ZoWzGba$GU7_tS~i-AMS0m$VOC7q5rwbwd_^t^mc->EY?EXmU2P7IdX!& zfY&Y>q2AaU&an5d<0vk3gB25ORk_`xv^k;!v@2U6DLxXs5MCfYG~lG% zFDWFyna-`O^48Wlj3f%=4?#;{VuA_X*f#)e62c2IpIIWoZMozlBsYTmx~V!!68DZ^=ErJ$R0v8cjh)XVW z;`OYt(bCejx3@#T_iBHChie<@;hYaKzd*87{>|?Bw%Q+=8Nv*N`UtQoR(H)O=#eXh zkjKy{g1{ut(__y{>6>68&QloiD9(4~^@Z&};}s1=;1YuB*#bNp-{iVV5@|O-2fOWh zNZe=g{R$V-qF=N*pRC1lYY3&h7AzB4rOXCDSLNOCdgKN5TCga;H5cHDpbL-WIn%0# z4SgN8|2g*qkJDzQvbKlUcCAU0{95LLBWu#G^(8@qP|DSK^Po-W?loHFjUQF;{r5`3 z0}}Pb)TobH!F5RpBq$j>m&dsy+jRALm8Wo64x0HnkE#3iwoH=T#;qvYXGecD%4O&1 z%9>zmQQDF9FT6u5NW?8m<-_OY)}3;{AvGz7axW0-)*y=m^{TepZmnbNx~x|? zpD`RD3l&~!q+R9PWI|_eJ@r1pvyzGPO$)4?6Yn38EN>dD`RQ5lRrPZk%=RTd1F?G3e=#DVRg{F5f047A@0FVyP}268A1_|Nury#(vl2nWn0s#WhhGoG6s>6@)8WHG3BHw^Hd|++kURGMon3j}+u6FSwX07|ZJz9KII6wtOeOIyWbup{6hJmK{ zFbMhPMX#q}{8naZ^Imj)2eq2uX}><@ZFw@C|D|GM!~DY6^R-i^=t;42%l9RefG>8_ zd3x{ZMxy&}sqpPZVXgb+23!A|q89JL5Z+)0o0oiEkDP~FKOjJi%#F~bl)U*P1nZ6| zu}IqlnprNxjFyG!xyg-!<@!M((e@{)$yv$!PsGH-zjL`=MM5W0=Zuv$>lA$fu4$?* zwv$ldBvS1aT^glo9^ItEL*J_?#XNH=DjEC|22G2Tt>%d%@S!G?yRwo}*}Ex7{>6df z1&wLS%ayzEySoMa5d8h7Jp}K?l$Xbgh>Tg#I} z_O9_B2vrbK*is{puqM*_(-NO&gVSWp<5qwHxe*HaB>7p3)NEo3=a(#^{_osR#2nF> zNN}0PaQ>z7%;BfS7Z7|gR(n};7|ev#P-GB_xKRnIjde{T1KbI#b0|AR$T2O~KRufg z+mafyq5WmKDufR^42|xSm=ggtJU}$-h`5@f;H9~{C{g((F7$JZzpEOp3A(Y#k3Pvn zNC<;MX^CclhnQ&`#}XpNNeK~%Hw@%LEP*)_(m0f6G9(9gmp#*pH&ALu7HPsNSRlqH z35h5|C}GGdDH5B6GLRYfmiDeqvi6VlH|z@>17 zz8k^+U{aTZLkYO-`Nxj--3!k(G?NQkJVpybqg3w2W~-|gGJ!@V6>{m;B{NR}CIGkh zH;go{2I0t@kMrVX!fkQV-taL91Jnxvlmjr7P(=za%zva3_b&0trn}2+{oe6S(fiF6 z-d|D4iHbS$>eDJM2qbbne#V<~qKXB})@@B6t1nI0=~bmEgp7jOp8sT2lM}gTfl)bx z*mQ&zEYVaM!3l7Gh2(X^0q+fI9I;ef3Iy_qpwTK`9r5Xa1mzGEv6UYT6~Qr!agMv} zea=*o-@-nugw3^tuR?W)^MuwTR`@A*`qn#5qN9Her>+0B@0>=iV!f2=2cl-R7j>q? z6QEON&{j>!MPSJ8oQdyZ5(85IuNPq0>0DHfzrVa>RSE0I7+R60BGyub7iBQCNC>B{ zyYkIv(G!s5(a&+n^Z>~fG^#Yp4gqp8>vRLi%8Ah;27f3gg)D+_(dKpeXJ=l;YHNzq zz&}ucQGzuFM2--(Ta*SWhd%*$XQvq~30h_lKRn{CZMf<%5Ezb7Ql{33i==jr)`BF= z31}#zl@I+3tATPL>xu5&X~M=6?U|vh+#Ps+0xL@u#zo32?PY7f{2PE8c5pE56u11u zcJ9{OBSHIauyhKqcsAsyJ=TrE#N%?*oGPKxtCxfFXM)6|#x~2<7&zl20P4)+rftlC z4X5$tJiqsaGFJs<&b7{E(rOMq1R&M){(KkWY}I+fhEwXX)$^`wV#0wO{qd+!IbZ9E zmoFtFhQQw*K&%t$xGo68)t>~=0{rOA=?618pp-y}vPbj2Ht1wb(j#4UosxljOk~qG zTRx#TOKcN|$x9#DwvQrNQV&tWNcJ?~-smEVbI2^RRTyk0e%}f_8}-w`;WE0r--Qe) zd-4NHd8!WyLrTT$OUc(lOL6^ERs@WR9W2UUE2!LaGSLW%Uy%@sN1XG`qA@kYMsIP{ zr+JvK>vt8rx2Stc{EnHGIa>IGbJiqI4MI}#Vnno^7~f^Nk>{4cgreaRq&(SvGz8hM zwPbTXZ+wkW2l1UGv0oh)+T=tF(L zJ4Exi(=Z1A;scKw9a0yYy+koZg9Pn>FSHg_WciF_d+Gh9MC`>oE+?IY{si3K-Z#iU zVMOs++U6KeP9@{}J|m+E2#xmJ)4p%!b9(~kNvH?<<5L7n7X@LeQtq$YmCwdsRRbF; zdVfd}{3nRjN+e0T*Du_q{9{5oy@(6*Pm*+}UM(zv3LRz*VsDkaMUKD{UA8aoler81Kr%H5M=Et{=MKei66H*RQ{2 zOl-W;*DV&8i}SQtKeI$8f&F94l-xc?qLN4bz121B7gj7=S$XOAa&oZ~?R2Z}sv28; zxv+d_NMEOfWM$U5e1q?2P0!{Vi91|Els55Qm4KK_ImDp?ACujr3ds*Os|ft!=mgAs z`hrMvn-z*Y<0fI0cj15lrkIbt%V`{|2EhLhGz2^pV3vf>zBpD;0GpwiFXW3!5ve6E z3Y1xVVnkHLbRmQyJ`>db`H#w4O$2Y57>#3E*RjpgM`9VJ#YdH@gBuSm9ttaK1B=z9 z(R`-u5M#gw1Nu9rSmP>vWU}E%oS+(qjm6{$vq&1nH}qot3)+uk698nqy!ZLD8r|uG z7%MBi{WJr=F5&0|yWl^et%q%Om-Eber~NVOn)ZWa*ZWvGYzAJZ zc{w??DsCl>6^G|rB8liWlewbmLJ66j{E@ZhVs*V$o8_7YMd}|~o+mBqo@ZM=F3UB> zts8SU3pCq*2l>KK&e?vRXzfQCs8RCB^uSUDd;vj#iXZDVqOs` z_Q(X`oRte8ldjEQcn}wI)YsGY2KmfSfJE7sUW~P`r><}6ohzQ5ZsHG9p<2Zsa=TNf zO~!AD5fd>78;>nZ9>V4K&}n12C=!`nXLVm&JPY?yR1?(IM$14)-!L+y(@*8G2I?Ho z%b_cX)s6}pm>pxtiH8zM$Wjb3^vOw0b0k@^8=Atv%M@uLg~$`4&saj2KkZCXBdz^~y=Mw#-k%j*C z1$4DLOh*S{FrEq&vkPutP4Nx4*gvR5Du&l+AI2z((rmglNS~85W?;c|)$b{i3%}fr z!#W%nGfG>MH((3h9Pk5GIvyt<^$!P*YM6)bAEg~H^o@NJpozLqWKf3jVn5j1{KbhQ z)6)kw2KH#%5h8G~Yt)TL-kx53FJm4ual|l@C~-N=l%R&f9U(BkhY(XE{)IJeQaVEd+-| zJz`>^s;Xe_v&;Wb)p?lvb2zTF#m17`yREs2y|<#m=y$N8L@d7F)u0=A1OX>fgZov- zyuzi=KLdV6P>5FZDiaLEJ4_i&4+J~JIj~X*`pFkpA73pG9J0qlDEkjODH|~4L*V{9 zD7-1$j+G?kLBKh#35&*IO_U^!06!Uj?G`49f51M5uLmV?K`lZ21flo?=dw?`->--r z{8Q4*h!Tb$Rpx}i<3~ShtYLMAVmjT9oIX{v3M9hLHZI5>v7{qJbY>i!c;h2p@w}%u zP!w9dJH|#?5)VAS7_Hysa9#9EI%TV-$SkjP zhz3y%5hU9N$dhk|5BwU001*TETpnlL8JO_#=79ewV$~vZ6AqD2tZvSq@Yz)palP+) zgP_4nWGl;hBbMq4dnGZct(Dh`V8WN7{2MO{{;3Hyd(aVt!E%i*1qBOWJbYhPZL2`p zY+Xz6*glQb+@b}C5`VQT!=6=BYwf~!5vYE;Hg{m3yNzIQ+OmtaKbpZ7mhI~~TOub1 zE{Fm0d<;aO-q&&Bb#Y5e;dx0-&Fg8uEjC9Z82^(KBRR4(Jzj(3Iet5JChG9kCX@Hq zLsYLjT51LcYP!>>L%~{@ks>K`G-0#pTwagsk*)4eVMsjK>B*a0&|mOa0X3)($XA3% z*qM_-$#;^$uL>Raen~J_q!UjY2>mx;Yu}J1Mw2IEln#fJkVTLuf}h9e{O`Cc^lUtw zP@Vp|LOEzBLljbQ1gMCZMNqs34RLW$FA#6(i!77EjnBmM-N6`B!%vu=l{+fn$V{!_p6gV#Ojv8EVKy(f0?vK@PnY*re#<`P#Abaai0#@hQdCOg`Kp` zV(1KXAdI!lr`!bvkK1vM4@L$5_GWak?xi^X(A@KpAP=-Ma<^?2_dyd6^zXRUxEPi! z6=aVUXA4{!D|r$^KnAEt<#w}1rZ*j}1!F@lMILPIkn2noUG(v0W2 zg3vEkOURWL<`Q#usikopp+?*4JMWkwz6$=!>b`~rR`B}^diA=GYW1C6y6#Tl_)sYb zha<6u;lE2oB*WIch~YBTzO zPE#yj{|&Tn5{OkfGGDVpP;N5O*h>-~%0$qYR;C|}Dl3ZySpw z-K9RsOu6v8Ko2C~cAW2~L@=43jdaJxQu;6Zfr-u~kCtL^ix~=QlEvk}v|6f+8{3J- z+u5=(&6B>7vsrHofFr^A&{{iaiQEeZiTEefm#EpXS_2Ayc?0Dd{TEDnSN1Ku5}3J9 z+)JA8ipb5JLRWV7{skOCkWl&D<|`AgqL$j)Sza={iW)d%qW0EoUboBuI-6ql$<4sd z{)d3~^HF3u-jbOOo$I_D1srM#G8nV7K<1azB<0y>d)cx0cYCQ!3wZr;&ZFzPo!i3W zBJ{gkEKJux05V*GmCSq65~`D(M@BPep(0ctO&NP)aGoRBK!y&apFAZgd} z514XYADlIJsxl{<{hexZOU==92losG1<3p(qu7f721o~>=X0YGZ)!!PS*L8?IuZ{G zSh|w1VPBTlF-J>onqmm$5)n7zNb$Q3X}t%~-A`vN{PA|OBO|S`VSkSzlY$hUd1gCG z^8$;=yo-9XMFsup!BHHWz6XAEK7Q~1keV7f(9IXz@n}Rm+dpo`GA(9|pMV~yA#rGv zV&{;OkUi)xX9aW;` zG>wcEA;iB4wrOs^8hyWH<>!=Iq_P^u5fdAK@1{d{i6LLZ^Y?kgG1O+RLCe}^xE6r? z%X}!36eoK+Kq*iEE18fl^%v$9H$W0Q}MD3hrfwJPJn8LSi5=7@H3<;|-mHCQp-D-=AO~DqfCL)T=WJ;9m zVCaWaYierp4#gvG5b@=m`RxAL-z`f5k{$8N-rdWfvx+%qeDw)$V1b)U!Ef*~ZqT>Uo& zei7Qdc?>KPK?#hB#`FmSy9aOhQe$J`u#1U}q7YNiPw0i;V}0G(UZv0x?8+=nnbb4i zTabq`(m8E2RVFey!YV7hQq!okwI=@lecbA{9sh807IKrq7U!LZxM?{N|4C*8$xdlmc8YO(yzeKoPM(A`ax^*PTq9RF4REYenMQoY*xlKBJf5lVlV zVQAMYYD*Aq`C!&O@!t4+jUA7}c1?Hm(5>Jjt*PY-mD{*GsXU(R5}< z2QBnTh|ztOUG z)2#OUGt2L1`KS|-`XZ)YRRq}hN>-F!aLV(ZgtyY6^eO-ATp0_Xp9(|Sd4m*W=OeKV!B$jMTk-0tpJ zy<7^?e2Q*&*8g)BZ!lm1+0xoXN<1mvG1yZD!3d~1f7V34jG{(a5hD51CQ226Sr_QF zsIevAbTaz{P(p?qfN?}}Z$j{+(TR&K|DL%XR4jR-q`W98*Mb5)Zx4vZ&`wfBeb`B4 za{!CCOGZ(zROF)v`^Nz>{9O&s{)IRaqE1trKFfBd)N<0K+-1Dx(^~iDT=9%(_z;F% zLQTeO`&E?x@?s_F69d^C{p@m4i-|b`aH;eZEo*!K@hj+T{ZbCn{f}F{U@T!2_rdUm z6H4`>{<7Tegm>3+Xy4gVYjN1rti9iF@yu`W5+Cryau-lD?gK+}bkBHB;CZAFvxu&4gc?LPvF6OHu(-#<8Wg2Y%n_G`y%VTG8xRDm z^~t&5LqJd;lh@LVm+-28d!{0hhl_O;kbJ|b+FC{OqZ3ce4`M60sP{xB9Y(iw!QlpL z&C_(3pbhR$x;`<2-X8qo<q5h4K@m;hPdY&#Fa9E?n;mqz{kH2iYZA&1*7*ij^ z5a;}d75hU2vg`@3PxUXM%GeO?x_{1)#ho2e>OYDvLws6El{UQk`-XJR3|T2+V8-YsfTtrI`qI%9RvcU|=bqqY zk6>@U^Xzz{;M>l$0>9-XV_?P7`gt)mm4T9)i;*bM+dpaE+IbuLCjyY#Z^+E1D9hPNzj$K&3v-W5GcN|5X zy;Vd?D)AE*4ISzq+e$>@W_hQM)4Mxz31$UJ%he(?bO6ZiC_8e79X3z#3k#AB5JPSp2)jM5+){L6ZJh~Yo%%HzLXN$Sn~*sDFz_dAW-6d5e;zI?g6 z^h`;y_r2Wg{J3e^{`fh_|8W@G9`|lIGGoZsV%vWH^6|Vec9#d?@`}+~8(OBrTlOKw zw04DSf>62=QIi!rc5V^>)~VdbN@QKelBh79vj?EXIN7;JK%enR3uUUhf5`-V}mS^m35&SQw_;lWEZ#Mi!p=M?~Nk+jW zo{jAq1#Hfj=??^&Z~XpZl+&Z{?XLu=M3jue&vFX#%b2TA;zuDZo(k@huZ0$;lYJ6M zuHut){J$V5TQRx5NQeg{TydJDV?|o{BTEB_csa=S^&GCN7hCW^3rbAJWCM;SP>6P5 z=>Mt53O|ga$XRk`i&%osdQLBN5ffN58aa$ML=nGO<%N713#czyb-id;=MF<5vdd%s zWi(sRfq*dlpwiZw09roYNyJt17GM@hB}NEgAvY6P1m-%!LW0!zHo9~ zL3Co*>rOF06-tt-KTIft6yI@bXV)sdgez-`(otFG?$HuD3u+vvu@IfJ-W1_eZbX_= z`Ai(m?lh8@S2{@a53+w9)2o5z-O=kvIY*+T)2_)t{C^Hxo~*Jr-f>@@f-3Ni3Y2^pxE3LR878E8fRLLXo!|m%yWW`oL)75k-^!x!|&l!M!Fh>iI~dxlQrwa$!mZ z3oDF^gJ7mz2jhkT>oS9g+3OF(qIu#cR_~h)E!K>xa?Ra=tjTm7fdStKk?Locb@l)) zW53!VzDrqs=NONx!OHwoDsoy)R@DxMX*`09q7D z((!<#mAP98ajHou$R>ElPODa=6@cu7qE`DhN4UzyVK~tg4fub8-};-Uj!*D)g^m#> zwD8r(VBz-oU@Awu=U<33Fp`5HFU#u9e(`+ zDQ&Fiew4}!m8fPio2RJ0-e)v1sNwUk#GJEnGy^*GF}{IriZU)?CwDisWoOkJ@wtZ8 zyb?Fjw$)5c4W`3ZvOyhXh-|1XI=oN8>jVS$vEN%Yf*i?K(xSK%Z6W}0a2A&SUn|oj zfvvpeaAsjyy9Icrq!IDBC}tiqO~3k%VW~qr9>1Y}{K?X%r9b&~`W&S2?M9(5#@;MV za!1O)?oV(5O_g~~V%sDd2yWjFa;z=F4>=uFZVeXHIuHW+vz3lFCpK7hggCVLquLPVfR= zE~Y@6ybUq17x(=|{L)w;v_&s~!3lRloWtcA{s8Gn`-h|Ps`0_m5F|S!U#_VqR6cZY zAmBPSUmoLR7HQ(Mq4}^9@!tK5U~qQFKjvEv%sSGZHegWuNK%Kj650Re-=DhZJQ6>P z`mHX2f8+7>2~U$d14jrKZyuGuDFlYBnI}sS!a%dEyu7x&T;hxGX0GLQ&MB099!;VX zb2$W=Kd!kkszKw7)elZar^soZZ1>7OCK=Z+EG?dIYLDsKd2mYrMi)-GGpB+!r{3fD zYOlt2@(6fhaLLUG9Ks{^lBo8slftA@Ui0X<7CmmsV&;#_MQ1&B7uC0Xt@nL;-wFK9 zbKUp4K2g1`$FvIk>-})Mx+MCTLT(gn-Z(0gP;hKZxilq_knRYKt+~Cj(p|vAG3H2{ zkNBlE%s60dg5~DPz>K*vMe%F_QcK7G^>}f!dXvHElX%6;&|z~t@Aj0U4sYmtoaiHt z+dj;aqzpl@xtK06x^-vo_mU_0cC3(7)b%a<=B}&vt$ufN@ci!1WE6dOlnP@!tyM7+ z?A#xFRF=TQ7M|a~J{*7TNxmg3YhU!2*~)UREty63gdwSjakZik_0mHK^6d%;`p8}C zJoZ0prB8g-1iocf+9BDt37ZE>&!B7A{-$pvsyD+0=WjxC6hvltKzxtQu`x@(Wa6ZO zPudY9ts^pdEL19 zc*S#UKg7cplh6|8su{7z#8=AI2qw(9xjPr$&4cE=^$Fl8GS1VHf8mmB=8bO<@-Kk93hGh z8lPtJeNN$u^t^qY?mYDMxqiy~61tcD1LE7*S1hrxojEi_{r3Fna?I~pz7a8gZfG&sgzt)<;KI6 zs?v9Z(&7n_SzDW1TcOgqS?s5Cm+ZaCK0uvA9Lw>7@AbB~M^$M~AMgCIC`}*tt*PIG zzKthRUG!XJr5xh_4zRqE@k@Hz+NT4^Ykct@7Y~V+ z8zi_ENTFfh{D-;Xkg7PIoe*T=$qtHbDmlBMV0fDhgwjnZKAzt21kZM*?2=z6MjRph zGmGDJ;g;zFC~Sygq4C}=FGDL|S$>#T{9i8sR9w9r*(OAD?u}hD%m&4lDD479EF3p8 z2dl97|F^87d;-&Hu#~?0`98(+>-t@7cNf?*8~NzGKk(GwpN}bOyI+5g`)S@bh7pdB zPpg%fJB}uZz(sl9R;{-bH@U4+5n>Z)?x|KsLj6*zs7Zq{icsLAzcUl~OQA3#6rP3- zc0QW{>loPzw@bA7pBdjp)E6W$PRu;ibt_y$lQT(GNnFv=B`^s&VszRpXnh-Og}iR$ zhS6+~cw6i^fQ1DdmP_g1UKhuY|3p4QlT1x-sd*s(F!L;gu}oV)Wzjb^@1s`o7PPz- zxZ<#hCF<14G~6C}6Zzg$*`hMK^q9va8PC>midh*$0DRr#O3|`OhmnlpRu~N~i99C^ z;AOw7jm;q_0?&H^2=>{*-PT6j;b!#0ub-a$D=BWr}pcQ;tHnO7m;d{ zOyS7=w+84oboW_pk7c=hENYW}=ArY~osCR9hdcXdNgroDG}n;*;m((CppE!HDEu_Q zX0rL4W_fqVw2`*(Anrdt;{(O%9M!JJdg{!&m%ZKoBf#z5n{XQCgY9rBmxAKMbH7-A zjo{<0k?3uC+V}orGk3J;=K9mY#?MQtXso=uzsRaHS{V-1pcNct=|x&&z)~GDET;`~ zYb;qv{%h?1Oucw+0v&$kQC9^VBX%&TQgK}?$3_1KUIF}M=4aW28na8YgEV)Zr8e=;;U9k05d>rVIm>Rk!bb(3Pn=$oTG(@BO`qUz(D_DS)8wi7keJ$?5sGimXSQPXq~^A{~822+$-G`r4u+iPAN? zdbm!r<+IOfZ(p^yp?Q3N{uTgxKylGgcOrz#41HRF0in?(G}O^n3>Ul@0ayV55m2~T z7!jHk0D1UO^QluM(6H!}7iSh>B%7BF9-4WSaE>(Zt0fdRP#JLZRb)-iZo*^yn-n7q zW4Lb-SwvA3l9YT?az}{D(4^*}H<8~1EGl6r#nAt}2)Nt>Uy0z0kx}Nm;m+m_(H+J6 za|Q*V)}>E(;D+)>knT|ZOk8XHCMMam=&8^i?N?^wCrs5X9FuIc10LxicXfm|#d@4x z9qDiOr4(InQ@*+263Ol@Wg#TxgN;x_3im=iW~7Cmcq39&Kn!}Ek-^91^d{4fY_KMR z=FhFK|CWPD-Y3S#JUshsXyT;4e>(@Am$-|Isg`EWU~|22ESrF9JNfmW0gsQjs&3P> zmDeD+<_1j0jRGz3 zr6fX!`WX#Yff&xl7b+5OVP!f7V?s6_$QoY78V(jQO?i7o3%NVPj@q^IYmk0#LaL%w zG4|W*e|q_*)%P`om7e81L;+x!;9$`xv^|ZanKKdU%%dxPs&4g#V~5-;jJx&wcvxud zwcYS`wp!;T0O`8@^nM!8h+?GWb{eqsvpv&jWjVgye@^SQ;a{lSY0ze^y_*sntnOIG zqyZ283u#nZcgqvZs_Rfew=+jt;|c`KCprPLZODI0T@IqW$y&Wn-`Zsuh^STZmMtSi z6$XGL52kCJa;$z%h%X5o))tgAG!`(dn7l&p)OX*;@2&iQQ_i%hb)jjh?1ieAP^DZ$`a*8}>`n^@*9JT2 zU_Q7#y>)+SYd~Hr$;a&k{PXaa$K{8sQ?u(B9xulIhXsJ>gh`USE#)$_c8^4SOd@0P zs$d%6BQJglu(Bg-knZmeWea0&tSmbFXxVUHAf(OLr$*m*On+wVh^DZ?MX>)7&Aca@ z@mZu;WIcM@We|nPyI>Pb$4w;_LS?~0#+jq=qF4fW^LrZaxI4`Ps>P!GM3@qWBAqmr#R z4sXi>pw(=J8rLspZr^{rtYIQ34yK2v_BpA^pr^C1V-u*5SEsoY%d6})uoZb__+CZ5 z4M&5ENA90!ki%2cMQrL&;onK6P^VhT6W~KW%>f_nBAfoAil` z9X#6h_BPpY3kApsVa4F<=xQs1o z>|vhlVKDx(h?FE9rFoM<6qtXoe}f8gCopNFIN>V6Mv8=y{I|PbH2W|n8%@YDDRlj?E54`@N?G}f;Zru$52K*|Jhgfs zB9xXHZ z4I#ZmP>JvF|EjMqY~x0liNJt^yg!(P^S=Ux2^|zf!Jchz!^Zo*U7Jtf+z()AudgXL zHxGxQUS{Okd*5V<=(+EJmZ~SSY1V%Zxzhe|Hg8_FXoeoyn7B)Q=qj906U7o&zwe#x zav8%j+awlZ;l%M6yJM;TRGj%-jYAv)dipE`2FP4rS!LNneUPicRMHcA7Vn!&I)cON zCLST|5O}12?@^(h*W_a-ks1TkC@Hxj55uPfU`U^1v9Eb_-s}(dx**|&f+j~7tim^? zS7I17BZf7%^@y? z{ix-a>t>V;iRwV>2=!!rUg)GF^DFpa==8HHSJ#H(@BYw5wdWib&ex=0 z#I<~19AXL)3!pT))r1-_ekn8}^_ZSCLrd?fMn;gk>~v+LR>7u*X=6#@z~Vqa-#6x^ zygm+>?kg`1wls*yY6NG{0RC&f5>V5of73~M8jTkxxorIYrA-kb5%Z_v+af{KReDdr zV`y~=0(5VV6<1GPY(s;Ihs3GS#bmP`Ow9$O8z*XPp+$=?GU_;Q5cq6@zNJr3zh6%X z#jw%Idm$>jtD241$L@`_`B)NH^<%o^quKGJZ=XZgF>yy-2e2`M8cEztY#U$qnVbkA z*bSEYnVS+5A9MMu$I~v~mi-7g4TV+o^bq{PBB$EwNt3vtpEi^!Df|x?wyTY$A^Wu& z?M{BYa@)Qy%p^m1%cxnr%|>9Zq6W#kN5+Tt*)JfVaYTDA3O#jvq+ceYX-L;&2??G%F}ObIU85IVG>ZW z5Dsh(p}44lswe*ML>4QSiyf@4;oJ6DIG*FkIPR5H(<9q|`%nL9dRd_}2+nt9T6E;% zpfjZ#l(?O9=-J8nR9Qdu-_+oxr>|Mq*){+M3_TnawJQsMwb#`#j(m(nLigoXtj?$L z^?L-H8%t+jUUTQYyzQ)BPO9aRbH7GcayQyhiQk)geSw@2vQb#?w)g?E3QL9lC;ah! z>W%!Km;=7H$K~ttlxVt`Q)bhAm9C-z628XcK^B~rcD06VZN*7~yt(JY)XRn2G>`Y= zT^RpWS)Cznw1SdA;04xf<_syhFbv65!`N|5<8l85(k{mdkKG zL2P2UIxtRC9BnRKxGO6^@x{243}iWJcJHZYD=xh@`?B=U{w+kM{S&|zVEHfKI^MDu zO!4_WwwHA|lzoc51anw{uho44hJn#IFu~dNWh``2W_8gQHd|2&(Y;nDLL{btXHI@P z6Y5-u^i)+Vw@HT=0<@)iFf|j>s}x|&pLh}BktneFd5l@P`1$e24rxBzOEOR_#B_f= z380_gJZENp#fPVX8uQ;0vcD&Y94Qu^NphzFBHPxa>B!!=H#A1%sZJ;qlzr#hQFp4e zMeC6g6_^f$nV!`quk;5*f(zw_dHd9ZD(p!PH(?$-pW{`dsf`Z;Mf9Jc56xwBw!6Xq zg^9Y1`a ztwf@xMcl-qqTf!+>PccAZmaA!ThP^n0pLD$sJ?(bm5MK}%&K}FsP|93P#n7nfH{YwhKMspEc4!?N5QB~W?qa9B%AHg!8< zFFBXPde7r91rOHaxVT&3Qom+WDqonIaC4wrkjup_P>Ofk1YUKnEnnd4rTa2~JQILp zP$wtAp5e@A7{-3dP1>MdFjUd>Jo|)4l%pU1UvAcf(-1LQ^W6k|o#QbV&qumHgi6z6 zDLHQyU`GvOO+yS#r?YH@#dp0N?OC$bybsRB)&B0_shR*INpsaDhTBr$hI518RL8O2 z3!JLk)w(j0>c9w@{!!wZ@6R!v(paF@BaN)U0OOHl6^pQJ_Gf}x*B9G+pTg(2k}$?x zE75xXlCbL(**UTGX~v~lcNxJVSq}#r@-8OduGhkiR$owIX0D+kr95Vq7vZ;+RB|!c5*{)}cE$DVTQ*TYChO=&@d%*e4 zVG#o0p2GvAHGW2u%PtvySYg&_+m8y+R6=Q?6DR+v&0>6rg|vKGXETqbXOL@YZM9!* zpzw+~Ta)qJjWHiEf(FI;vR?$D#&*44PXz|fHkwh?wi(&P5mJ&!l1G=6Gy>8z5Q-XQ z&CRBsx8aky{LlMoZd@G2gkEQb(>^tiV{~u=cRvU!MIujQ7Vv^1ov2N{^4e%7vbY(m zi~}B4AjMKtD&2SgTE{$8!@DDx`$MmzCDJYlpaE#iM|XrwM}R0x;IV5k8GmC7@cb#$ zM)u2imjMTV@;vWQXb>qPEK@YX*UXTEwU(>{Ek8+U&mzPWnO&pPu(+i13Pay~gxCrn zMG+_Cf0IL|Lhu=m3e7;G`?B&iQelqJcDyhqRso+hwp1uWO%ghDLrlLUVm2ImqrmPu zN|9n&I!-ydkf6bK<>f78Y$cIVx@3yshR51_OpKSrQuFizn!+LEJ z+Z@BMu>=alfuWue=RcrTzBrmrF3sTbJOA>V#p{w1gtp}8C4z1S+@yTFTcmr~wHTU<82)1gZxaW<#e zx;%uC>2;fbn!R);PjCq$=^vPl1Sfo?PYWz2II0>Z6$Y#{ikM|I(x1v3I;V80_HDD7 zHpo=h0?Cnu<%I}b$V;eIqQgbFk#@0#hMZL!WatT^r3RuBdbUNi?}Y~ayZ`zj$wCBk+__Lv#P}yWzjaSYgzw4@9RJ#I5da#^v@DLKrR8V@ z|Bt9|jE=1NzV4)BPi#zV+qP}n_5>4SVsm2Knx150+nCt4=I!UV)_=XX*Xj?q?}x6s zRR{a*eM;no-Pq0@6fbgxcV9CNZal3j2hddaA`&%7~1n`K6DNvg5euvoW*Ha{N%WSnA<2J~XsO9h6MjUDxC0 zqM9TM$Lq)8`R?QQdjC5-{6=F;;G2M^c80U=a0vVQ+MKeW=KR8fs*%uT*O|*jD>(|W zLv>}PGQ~YOnX9iDDd2Ud01V7zXY=853|V}zi<~o|a4(+xuEPr`@Yuq#z4Az#d@1HD zlNs-3$s93Kr+{L8g`0<2f)oUsYTVjLFc#y)LIFS%>uTlQ-&TAdlGT-?02e7(Ezsn9 zU~?-~j4HLEWx<{Kuy{@kH5z0{W$_I|CQL>VYXW@Ss5Zl;d>rF6{^lU)s%Z83mPW|Q zV{1oL2x>=%?rY{dsHg;jxRNzyq!oWAzk3lWwP`t_^vgP!mC1a%F>awrEBW#Jj~Udi zO_OLm_U8}PdkNa8JXz^LqH(-ec=*TSxzt8u%)b|$Et^i@f?=7Vq4<_sU^hWcyLa|S zOzU`+d3}%Dd@$n7hEjpiCXC5griA*hwg5$vEmamzx2-xut8r0AT_;{LOKfNPQb#^M zU6+~joqDAN5Z$li10<&LAoAEG5phEL`8eXY`oX@t0AyWT4Lh#301bI0$ik|sqp>vD z;e>jbQikzR(_^8y%9`^^TZ_r;+G44AHl*)p0oT79Rg3-dzWJewHC>t<iobBQ5`eLY9(~!@d_5OJ@-A&Kc?8Haq&g`&g|u zCG;X+t~Amn!k8KK(DYC8M12UCGq=2LYAM8`O=ZG|=d?`rU4Jn!6t6Ik@d!Q3Bt);a z`V;U+rWZups{8{M4FXK@^(Y|w>x8npxmy084^CD_7w1dfewe9j!>?fQOjN+P=|GIa z#~2$O`eJDGCjbc6&oLn*`<88QlM)Q+15>u6VQC3_navWQJ|qzNIt_%n^F|( zj__K;7c@rp9?Y%wQbt4ZWtNaHv$b#&v|&-FfN)uN{MGYhRM&m`bE$6Y~#X|KI>3YVa1&^LjeW+}q-QIH3wyTbmdr*L_1l%BTTR`S1jHbURN-=4EI1NsI)8}Cz)zkt8^!jkN zdDP;|u1GOqf!@A>p2N=#+!6kUxh$%X@_FffLN4t9z)g324CT?|QXilDZ0YzoB*C5v zB<)t*6(r%<@RJ(dm_*LwtOtCK_yWCIr<)v$H#$7XEd0x(Ew4hS%!Ki)HhV^!4X2 zpHI~g8$NqH)JLJvHcpo`3~}IK1QBtsww4aY{q-mIGqzVm=BNRgL--x_Ntbb;(y*=V zJIiNchsb7NijD~Qj6o>n7~6htTOFeEYtJ8?V8+DP6FPB7C<-xfS`xiq5Kb1v{!ge7 z{}^=vvL0xBPizbs2V7!r^?`SRXTf|XxW;D@T&`vTU~=NwRs^$)ASy(3$m8>=p+GIN zP?*AO=*c{L{8RAx$FV5tp^;zRC&MM-2wB?cVKB!Sr;&vxTNnIw#M2L#F&C}{o7h|2 z3eM!V&WYC6_5K(b!7|rox40)#YDcl zSoAvrA^ARP5Kl7N{tjYA9xV>H%ucxP5{9c4mLjZzK0B>sZPG_-#bu&`xpzrQ_ zc-SR?daD?2nfs5sdGMs;kvOI^drGsc7}shfh&$6J%mIpqh4+6&QExo9<4EEE?FRLs zMEh+$_z4Ijh*#iQ@OaPb*m95E4Vek1NN{YhKaYCC<^%n@-4epgw3*?yIk^Sb9AiJy z&K%Qk>)f|AGBzp>u?=!~(JKf-f}TQpi$nr$sL}-B;2{EwWEbs^_$20k9p28$LIgoL z61{0M1{G}!n0QOsmtF%`WeJWWP6GHP#&rj_kK4x zqAVPm=e@zh@9Ph)i}U$@6+J?aZ(L?m*Oslr5}exSAEOj(-NzcKRhEZbd~I&z$`I0GbB7Ru;Y-po$gOW9{vF- z2!TKm;8Y&anZ>G(a+>UHobO`SmppAk{W;EtW2w{w;ziJDnw+pp#t@9bo{NxPh*gQ#o+674RL`0g z!G_}~Vs~*V1Z!!--%xHn-4z%cX{2se6c+=rumCKkpsJr>8W9%Go8QYM7u< z=)AI#i}lGb06IW2W?%#}7&mJ40tr%OCyNKrGMH2V<8ptj zYAs40Tr9079)YQVYy9_JSACwvPNQ-rzooBl?|3#~M~9DyJx*Z0g$>VfyYG-v-fJRX zaH`GLDF5a=2^ft9OM9j!a}p4EGB#^j)9_mZmI?U(j|<>)BW1#%0z|`RcOVBh-!x>7 zgNx0p@Hd@<3%C@bR{p9$`P{G4IaRTnii~Uk9F?AF!~&+fs8jPv=kO6w`E_X5o#r(_ z09cq_Ey0{=6>{loUCtsYu;Z3dN>UK8ZB|c_^7o1{?5vzBUbOSmMtH-&<}d*O`+1Wh zU~$RsbxY_6zY@B@KuMQw;FHmk_6&B$!)L??!wC9Y5W&~ ze5T^|2$tjq_jI~%dpr7NA%P`uc{AaJcqk4JS|>nkr?uKS|En|T!=mX<^R(GkOTJ?)>vbiwn|#WonkRh$yMQi6 zsrIzu|HVdiqx96az@N%TYfB+kW)6#n;*(N|=-Bg0!;8#f z0~^3i_S~lhaiVUH!K{G-ucN#|4Iw02XfoH9tMPGqtaN*|)hKrv+gR?k+EGr@1O;%u zZke$4pfc$*yAWTQa_fhjS>s~7!m_9lI!aR~k6;c`N@Km6Us(AiG+r{e)y{P!yS^Bn z=R`yW`~nVdM&Vg3B;x+ZFipIt?V1AfT#j|k-u;M!1CKXI-idd-TFdfb(jjqt*fH4* z3+OZwop`zt{`i7Hn+sKY()_F!#L6+ z%MtM1n+mQFont)Iva{%0{mp>w{ftK+b2Gdbzm8Pg9c-xU!mr#(%*^-xZg$%Tvq9TM zTs@jS6^ijH$s^#>cA{ko_2PhcJ#!0~dX2r^&a7#aUziH%=juxM9}a@>-`8utKi8Je zp3G4TG$I!_cR3zF{ZTUJ!t?(m&zUr^JKpgGvg5F(JGbYA-Ju z^376n;-lKjyKsxNklW!t0g#Om*DH(3ErY4u zg4N9l4hCBdrs^P0z9M;$CrT;Bh2b**S=8h_%9b-z*lVIrmA#Kpg#_bh=dAQcBMlnS zxAHWBOHEhS&CK<{l>WR+0u_`+Bxo-H6cC<_Aay=Q91Kj>^n z7wZ|9oBW-&^EUJ%OGpMtcG=# zQF*BJq-VTab|&Qb;r6SQ#g!FIPDu)Cn!!QA$b6xWk`CzwOmtS|SC#TWW9ulZbqOIgD|R-E zCZ|UD)%3}%oO@CUNBD?Y%wb$8`Q+jFwx+s;%wF>qUHYravlF(?4OiR-9l|EIVk zSSFg5PNhccKb^nVSyd7$qAG{Sx72*4A^0B1u7Vwz6t*g?+%PFV)KPS5R8E^qo&d;W(zNMRvOw86_1I5_`U_4eZwM21=s|4<)nq zkV9P)6~}!@?tbnE3#C5kaGh4n0yJU~2!H%HgBh7L5=WhZXu&RODa9OWN(#@e@O$TW zUiQ@qb?BD#Az) zt`1q|*JwVGYN{Y3uk|`Z5=iyjlC6v3#`iVl(e;b6gYm`y-{q+jyH6RVuJ?K2&`5xQ z%jPJSGXAt8VjbjZ(T&(2?;1(tq2h%SG;TY>hujj3`qWNeX*5`#S{q?euIsvBM>s}JDDYvGi{ z*L`dbgZ}%-g{UfcyPo7_&tgqpKEvZmN9)W%zEr`>MsEYn(?5=Iw;bQSE^9crsrzA- z-FjnRm`zYn>ik33Z;&3#e}9}Evi2hHA|+k{em%Ta-kM8W(~&@9fp3JsH5ZO zbbUQXyrQW02Y$J!{}M${q3x87{=op&^|edJW|M*gb6!s*Uo|1#eOjerO2bv}SsWq` z;^%1izdEwoQB0XEjD-nL1LNHY4}u^DsUEp-BgCsLa~Cc%>%x5Mo2Xi zrB;7>y87CI9H;etdQ?EAZIftU2sg81qPpm!$nI#_tDj^5mBi(_xs|!O=ksRceYPWa zoUyw;jsRv1LmSxm@3J?dDiJyX$m})zs|LsTpMR$S#ISXDC^}CS$Q+RIAkG?`8@SEO z$qg7Z(n+SO+Z1X8!9eB%X-uMoZK>ojv#sl`D_QJDUF%-Sqb>L@ZkOu8Or29wQ9xb`?D#fRwl-kxWomYwgNdS#+tfm7I~tQRwjU!F$g)~^O-Xusb?&~AAp zVUSh4R#1|*B(OyH@8g0>``Q+>h{Vt2ZeJIpODTB>?p{b>;Ra+Hyk%e-LO7}!uN=}Ijaq=DH94ia%JQRSWM)knWdG=%iQlxb zFm$wgRAqOZWYNys`+QlA&q<1&FUPKBi^q$%!DPIbBeM}OHLr}JCN^IIoK7IEDn>wo z1AlGKEGwz5J|k8g=cWF`p_ge~%>D<)Q|o>S5< z{Vi2;&6p=J!|`1+5^7EwSzj*_hCaQ)@bxc$|3oIq z8i&kJIm5aPAj1OS>PF_WqQYwWolqo0Pad0y|qJk;e%Z!kdr_@`f^wnSTn&Rc{ zf87@T;3enod?Q9I$8_J71a(b)|3dITu5fu6*>8=aIEAZnyDhkH7!kT6m+TfdL-f`3 z85o^YA3Q(8uUO2^5$};Xc&qN+Di0*=95iN&TawM}(GJrOzZL2j%XOJ)Bay4=7a>4v zPF1Ujo6C?a?_jz*cMZ9CFJp>{qV65pjuvr1}(r*{+)rjB22aW`;DyMk}jKB$%KJy z$kPHoU5D%|?pw!-K5$`ER~j_O-imI18GKL3`BYS8W4717>ugPc3v z=C=G<@$}K#Wab3znwW=!sic~V5ZljwAr~Us!1hf87WWTlA+78WR+n=Iu>CLVzsDM%X#g4-#x2}lD{q#kB1<2{FpT#EUz3;es!m6wEg&g_!U#$RO zqDUkpI5&1tIf7;D5l?_$jTXwMh*?Fb(8gKM)r=oAI1X%+$RSXq@=p`IG+c+TZ?Do9 zgFQOWwz}#yD=b$L94CMs>D0>A|6+%jRq0nOgG1zb+3k!$PE1~jv*ufJ?>HeI{1X%; z2>`Rz3V0$?zwCoc%=sN_A%jXBJ@~OrR^z@YsweoYIGWSGF22^Ldu>~nCC(kEooC9l zk|@2FoV9t}WGs|mw+Lp7@0*1a(=Ps7>r~cz-Vbn0#t4>;jqRXmHPti9$uYksggw_b zwqzI>>D!1*xawk(aQr^da(iQ&mw+{5JLf@Uy$nZQeB9BVjkU^1jxMExB4__gnoKqQ!iWk@~#m_P^m5b^wI-Tyn>bNPYa?oO^=wD&g3wx&at=q*$zn9jIumHCg7H_{vNt7}Kt7qskYt=RSPuqCy>;woC7?Psv zB#hs*Wh-;QPP3Inr`m5VJWd|iC0LN*{k@nFk{}5PVGTY1=i#b;v01y4(OVg6NH^>s z27gvGW!cefKKN;n>ZDt~m<8*EmUH}r(}KhSe~uu|EI%ahTNlxYSv9X~nFXnkx;l`= zB;r!N^2O?0Z!NK+*w>=rGuYi8_`W_n!XWXvYD)=0#?!iQarJudXI82kd}4b49EJcS zz;Peb?~`59aUVj8`IxGilQnGyVN7H!8Zy#~kz1HX2EZsEjknoQg5k4(B3w1mMB-Ef zj=gA{jJLTnY$aD51*Z;wfgl?&xeebii<{R^3p}Z|ICm6*ZgBOst&Pgn+L4zL-L|;X zI$zP6PYh8oCww&GH8sk3Pynyh%DfmI;NshG2kNgHr#yTi#w)AL8?;%ipGHdXWF=@8 zr7tBjZ>}Y>Wa`q6q88I`lx;vM!ASq?LtbSUu{T;Fc-zN zL%1mtbeh<@Nev=#!#ExylU=mXUe;VeLUrVaxBRVla&z7xsq(fD^KPFofz~|wq-=V- zRlJlDZ@#6ch|DYTF$52K6}>;&`aa*pK#Njzi7|KAuW`w-9#8oFeymbE#9bG916ROP zzTiy5nl4hS{>~~EjDHDTxK#z}(q0#d)jxz}RXo6`6paAig^+C{en1rB);Pi*9|Jop z{o>cJ#pCdI15khuMm8So1?1hd+f<2dYh5tN_lV8T(jrhqjhfrXV-mq~itSLh zIKS36s>FoCr_JGy$~tYs6?m-dkzgIBFl7mzu3VvYU?vPa(y+|8789z(CP223)VPb1 zTYua`9_*^gp}bXG^9LuJAvVfo_-uv=5jtfcD12RwD%;1VD-bQ|1b9Ehz z*vVIscC`3zOS*MgHNH`3r+>0v70gxZo2&IdoiRD@k#l_+K17*>H4`nKvk)g^Gw|QE zF&;zi!_5znlarY3!ToxmSaU;`E~09F^gKf?nHt;>9@XQ;8Z?_8EL7VKVc}St-drM& z(}n1wZVQH&PUe^^a)*TuZhya`s;3H5O@g9$VbLr@1F84g(wkog!=rD3Yi-CnRoktl=(gIVC>PkwC4dkU!Gkyhm?uDA@-0lCkX;{?L6!l+ zBwC#{;<#-+1Sn|4B12iv)=`e{_|u(>7-#EU!7qd& z;y%8)ZeYJ>Xvp`LJgqsMa|%Hz=Umu#mF=LiT&hjj<=f&pC!lKN{OXrPkY^Uf|D1>g z8wFqouMmfYxB~hR*zO*g4;umG1~Nl3LmESWgEfHH0Mhos1=#J)24kv^~p%msPxc4>G_-*oApO z{v=1@jwynIkjV~G;kKDQ8?9U#Lu5^Qb{&8}XcXjqa* zB$;wFv%Tam{6c0xp|H!$8GI)m56}iE1#t!82r@E3n?cBhcHpbzX7H3L-XPxXoA{mI zBJrC}0=xN(2(-KGVrOR7Z=q5%zJ(-#0E$9iZvZOBzwcp>Hj`P$TvHN-@HQ4C<()BD z?bz=Pq2A|-Wi~O0Ng_Q@M5ky7w%AHHwJ`!1J`Wbtffc(4QEc&VQ_Q+kc)HZ(9o_tW zFacoT9%Y5*3??E2y9B#R6hygYt;%Gdl9`D6WF_O5aOfIz=sWvmOP#~{U6aP^lf^Oo!Vzv z>*PLOCc4i<5$+P<=TErni~n-ceG0k9_7F5N+W2hp|Kb$>F=u5xitn<;f_)cYd9Z8b z7Ay+TJtR;B#s|^n??UXJ$QM8%wZ6j=#tP~^tXG85H*6`<_8xp?K&}jgETX_^v%w&= z;M{MdA|X{IpW>q~U0a8_U_W$DjMGiKxkL;sLCcdPNN4vlFv+S^E>Bf*K5@wRrjo~) zgL*CZ18Ty~dL%BL_d|(Hz15e|z%C~B^W+Y1X_2?I)ekagxvB9r|yb zCUJk8_5dr^9m?gwSa7jJ`ftu9ybX)A`{<4`$ys*xgh5{_Bl^;z_$3ZRk8^hmPc@Do zlMFwPRze4;ow1g&4u#T+Ti4CO9G=Bxta@1D!`*JXi4RSD^|hzVS5yF~cWXvY;_nY) zf%g{{0S%Wktcw-1mY>_efdNMf0`Rg5vy#bm(aHN?6@bv~LH6~=NW#a);`ljN+ka&; ziz+nh!fuBa1b~4YMf0nw*w!J#46IaCQ!fw$wyOoNL9l_|QlWMuYmIPa!%qIOh&=yW z@qgmsk74`wPd#vIf+B330^-Y;WumAW)nbXsrt0b!x|Bki#Kj7RBHjAvOFNH@D<`d` z^%zl|AOe*vnjNb_M2A1YW0df9&D$TJOO!T$DpZ-^>FDf&bHfa*4s-u&1zI_!{vn`g z7-&U>RtfF}%6{ab{ohrfe&y$+8>o(>?dVARv&ZW`K))-xGd6EK1`CCo5p~%$&cpG> z+(K5$fiWHOv7v{GQU8}8zUtCTWlcpcj!lR3tq-x$U}_58`ImVR={&FSw!|*&W_^Uk zY_@p`m8BXykA8Af_Ew=$I(2$_t{M6_JNT_z?8nATDNORWiJUMH#jwn)MOr|4j*$d& z{J=z;%|&B#FlNHVL~t77DUyOX_mRF3{5x`CuzUz&$as`K6(L2|>SeY-cYW1sDEQQ6 zWgLjB_+LY+MRCSOjAsxpn*-fu)DqD^TQ^HLN8JLYEfVuNigU;xZRMmNR?AL1HX;zs z!H6MG5Ys><3-%JVZ(g5v@^^F@(0Y||UK8;#of@>1<_Va5=*g1R_RfbwF`*IzC1&=S zF9wGwJ+wU)m$XS{NUlsxa7>!nZvyO#V{2C-S!2%vM!tLD>23 z`>kbZtk(D`EkIyH5^VVMn;N5iHjK8^{{ga}Y*{|4OYwH%whuQQz_9G;$Y9rw4aux5 z)xO}pt@xu2goM>T-#2h47UDdr%QDyg{RTcnag}N_sG^MsS15{F$K{fs_$72qhq!T`fr*YZkVMQR!0ak=9=K;8PTe@*HKcDl;F?edj3KDfYI$?Eci| zNX}m9^6OaW;Q%nxUuCBgXQ97XAicj6R0{gaK2?+|31R!J7&#YV*OD#ulpbBena%3i zkjm?dSA5VR*9{b(tMuAieckTZ-JX$uY*Am2)paaxW*oHn5J-e@hE0bQFN4Tp4MOfr z%gFS1=^#zU=^%L~y{3F>CkgyF@#3D3`9W4Jk;MW=dA0cSW{Y2o zXq{8x36vT!EVAx9YQh<}vp}sNN)XbH;^X_FB`70=KNt^W3~=0$2DOKvTvLN`P2@!L zlI31^8NDctR1|tRaBa-SQcfr@6RG2~7Z7MWDw>!@|9qcN+?2(Nf8+MMTp$Xg5X4>e zQ25>2B4}>u1C}4E0g7vmq~n_8VdL6+CW0C|im%snmeLkNd|$++2c}JamxN*J%M;1`$Zukq|o2Vbq`PKG?3 z7DMJ$$^5m|X3@!gwVhut2mRlKLeYFt+b`-3A69sZv!EJMN?KaHl>*cNJixV7Xwq7D z;p5kLYYQ1gt2)IUX4+*SARXvvLU*n8 z2C@cDUt;6ShwKTOqIUx&r)0?qyWG( zPeZ@MXo-r^ZbpPxSnVgei_kUJ4s-AwvJ}-;eN!!HIHV#b4&Aax%_v$!Zg7WBwMZh1 zAtLvFgLq)izDT$mh8eiak+~$EJ@S8CfW#-oJ!Q>XRSnZE@5CZ$8tHfV%z4iEffDKz zSe>uPl%0t`s~>INp!s2nR~pw8r;0k>dDFxtX}KO&VMsYykTYQjA#yK8R1%ym;MTQI zWj^v#9EbJb1>5!$ANhBgv$K8~Jo1XD%1%2L;=PJV%WBi5&gD&>_mv`WyYiB!wNzHN z7`b=z|ApP;0j@YE5UywenV@l$-^eaK8L@+(d7pS-+!Hvg<$H}472Tpx2r3+JxrO)f z#Wt%$EFC-*d|B%|%IQ};JcFAHb#2XPkze*N5gjJKfPW>r6c_O9;$wHcE1@1Yri}feW$Q#ga19khZ;>k9 z2YiowbMhl*TE3Q{#8^V-k6u67up+-^t8^Jivb<5f0s!3&FD;`+_AY0F`AGlz`mH8I zar0j#h5ksND@_$M;w<@DaRE)V;AAoeB1= z8`g}Jj}ti`_}1hl3-q@M7!(kjnn(OY2M?6{S}amN=LoypDfpacDw9`B@Q)uCK8bC< zlFEdjdtBHh(bEAAnZ7tjO5og_2($P+u`KkM@U6{|39DYt9NtT4EESQ`KWypV$ptQ` z9>f((8GbSqI=#(|wxE^1TB0{aDW(#zA!+0k(hRaZ;=Pduj}1Q6>O7Q2wTO@}A|OsO zveNRD$_lPvDGJ6xGUN}U9=70?+IkG+F*0Pl6kSDQ)Mh~y>M>b?n0oBRG!vdiH{5YO7&Iq)yM?@g~#kPcbDic zd*Uqz6a-xBNXB*zG&;O+=?K9?2c>#AnHEXjjb*@CNx8trrIK(c}Vu?C|Z1&zkpqeT%y?vlB){e(KDQ3z2_HLix2&vdUoA za;SXIS<*&UNU{R|&UsC{%Qkjpdo!5!+ZL2Wy^0^ zJ8{qI0X7yxsmFLYc(>7H_DeOs*S}$ca~mv1lUJ}3zKHit_N-z{ zsni*MGnt2gaFgryqmV%qXhT$y5D{3U2=-_9*2u4+@0S4ha`i4;{JT-x3I{^%6AR=) zZQU0a3Zq6+Ut8sHCIm68t;$oa5|7S*o4FH$RA?U;m{1!!YWh`m@GiCn^?1124HL2s zJiS@r>Rw1-DwtSMEdQ>yu!N%DF-l=s3Hb@kWZt|P+uaivQHjC1zywPcwVmUr+E7&>BN{$zUFey^%XLp{R$C4!V{l%gGOE=Qe);jeZS_ZJ`|Nl#>ges zbvBaCH){C!c2Wa^QJb5AQYsW20&`6m*G$HZ^ z$^`X+`=dPMr3q7@7payj$D9ILX-EB7n9RX27g1X)3z?ccZWhF_OqC3dl$)l7>kc%i zHS9(Rx(Bu+l;x+DU<#h3>kT)A5L^J%GwyYQ1lFqgr&=6CAPF`}tN1+4H_Kk)XFy>{ z+AQ9!%9y?J+u91eGF${Ej#vTD?Z^P?uZMobx3{;ai*=k~iPSpFp*XywJnt>b3`6Yh zBC|eknv!(r)L3-+VVEimRbh9jLXx}!VNFed_;U2SFO{KomA#wWz~Nk7isKJhv%h`m zVoE76-wSZ*Z5zcX%8_tZk`L@go6@j7 zKRxwf!`oK#TD@#kzV{o_~uncg9t*h!f8B=JW{NIX->cP=c=2*E-BF22K84DdHcvIdQEg<#X5BT_Orq6$7D0+6Kq`Y>9$ z4=VlB@fFh{@xJ79qz!x+o*wD&i%h?R$a^}hXz<#e%)Oc-*Wl4E==OaI%zyTQrl>?fx~NM zZQ=UPW0zL4Z_A`#f;;Gv^{Um*mUer;UikwfY~~vb>cRcp{??&YcAmD*SRX!WNjI>{ zGU_2}QncG>mXNq4JIwQzfKJI~kvIdF$mF$#YJez! zBmnP|l2__T;=*{1<|1%yWrEOv^UU33S*5L7+>I=wt^jNQg~}3DIaqyqVSB(cZDkdX zd;)|fny)l&XQc70>9e~L)ug<(POpiJ{zH>ruZZZvK_*cbAEqdz+AVBj;=mh}ve6)? zPEJhuAWPeour2Umxi#^PRLO7cFhuT3`U|Q2a&jXJOM~YoJlW7hNK|yrihPJN;%Kd! z{88yrE%C6PvP)h>9%02Fx0nYq5*7p>#A{y+x5o?65oEt;8iO7NOsOEK98ao@>xUn4 z`vxT#je~ZH-Ya`T^HZ2qGnvhtcvRO+E`KrvQGOu>r!zXTw}XWYip>n;a~z8E4C7se zmEb9Qjc34JGuqPL+OPOp0_NV7Ym%TqI`=&FV)-imV*{o3ivki zHK}+U|IW$;`x;`0Vuyh%mKOFX`{gp}kQ12) z@;RD7E6t*{q6%$|bFZ9{VXJ*I2c;3Elryf8vAbFe)(iLqOjrZJKPF9|8{!egKXpFe;NSIx5PAkQOre$sVp8?ygmV{xTljJxGcF8g6kAv+{Y9Edz-=<$ ztx!qfU0J7pbN0omr|uWuu=BYgQu z#^;pEQ@r?W%Zpp5nrfItrVQI{-03qWV=s-If9`;qkjeOlKxQd0iMmSD%mH`o%Z$Bl z`d&MGAw;T0P_lnU#77dHIcay^jRN#TI)fpN;NEAL-px&z08MAZpu5R*MvK1Pujzl} zqbsgVadkxepR6<^GejDF3VgG)I+JS9b=e)a_ivy-V#&hfQ*C400cQp$(%47vK2aWyo~KSWH|>g z1^;CXA_)2hUX4%@3;25Fw%Mh&YbPFj7Yy=eZ2MUB4Q`$xLBMe>MuHWg7L(sIGq<0g zp9chp(B?mDa=Xn^WQq_Y+DHT%e*O9t^di+fzU113jPX5*Zyr?R{cn<8*kw@aPSslP z%u(EWYT_V};4Z-$1-UoDsmOAQFs5sKTRn?bc0pW73h6|exk`x_AK-#C(kb3DK9OJphQ zHBD!_D!*>Hj7LS2lVdlQWnR^V%MO&IvXyvv$Kfsl<2d7J8jt~aH{+v`WQM2wjJGVl zMgazObn;5<3_eObbEhG$Qg7?8s|#^;ap8mV?-l;y>XLfQH#(`g@zI!g768flA6aOU zH%jK7ETsCvV~%!x?~eYoID$PXq_~*4eTi+l6?o$FT2d@q9}@MC81+W5qH?r00=23a z^*DWY?uHKBwI_^ns_C?+?lio2Kw9<}$($L;j>F&|uKH$T}NsBUSI*qUKe-Z z-<0b1ll5)ktNdT9|2;>NdP7ot# z5_C%!o}X@IqDV>>m8l$fj7=2B@r^)<({@ef;M+-^$QL6O4F-ycHfv`+yJqU(+B)~q zRC!OVJg=l33EyQ%6)X$3oAgL=#yw_KE7i)9QrK^*mF;2~Ri~!X=2F3GGj6PRe=BfE zB@NAH*A`r_)P|+B4VLD*;8$oADI9f*Phq07G~~x*Gn{6AEzQuYY9-mWjq0$HDd;=M zf?L$|B^bKkpH+IUD{4UEZw_yrG4d^$aF!r-)J^;Q_H4iJC ze0bg+5#j`e{AZqR?P?)v-GfFL zkEJks7nGu$mq8N6Y5%&Mxhda+A(5 zU}x@^zUMM^V%bXIGHMXV6R^PNTlHdpoUjqgQxSo4*UrAjB`ni__aLqEIk-1}z15L? z!WlpJyAEpK5qw**n~d5!ds4mZecIA(w!*s7uf^Wv2cH|eB3XpwoMmEt^y1D1EXbf@ z612c}gJ&UHK_!G}2{u0meE$GBnZPt)@C(}B<5~PTFHZa4)dkm;RSg^AP3<1v}F|r5CT|WJ1_t))YpUnkb8(?FytlRu*15- zz#6@R8mZtjJy;H!K%tAvk0(rj)J`_!j*+>cvI-H0JBEzg;Gp|1>;BK1s3r&%Agz)0 z6PpCXI}%il9#-=6Ka+R?TpEeto zfZLzX1pi^(>?J?T8BmFfn-z`@Yd!Y`=^M>#(~NgPv@o2FfgfFpe_K&=!LJ~Oo`%+m zL{F%N2-je7t;cO^>5WRP*OjI02Yk_83u5~2ZY;NbZNVdKGna9|q)WQx>c>F4!?%xd zV+Hez{VUll8fB=L6XhU$^HYJP+i|+O@dJh(p&fD%*Ny|5w<@SQ(P&Ukvx$L2CE00p$hp1AkS$=;=%-TrstGC2iPj)}7 z@E4TKauKSN9@;y|>|)F^Ikl<#FS3b~zrjbRZ-9GEM3Y?2S zBLkBXGWk;B zLH8!JQsU&bHcLjlj!(d|s1W*B5vgc4**Sph;gp$7NdIpn^9-%SVx7De< zjpl?jm-yak>})<(;VFo`(1MItBNd>x&R!!L%AGd44^3?^X%3eU-KB%rWVMZ?2l0o1 zm(=-JJyjk_OsfEf)V731--c~q!_r51_Yzuwd=A__Lb&p`RyA_UzmOk@t?Vn(yGovTP&9L4Oa=z{YfYGnjy!}l82>xtEv1sL| z!yne*n6|lHxU28wDwhR-VuhZIaUgWl1s~q+gFHS(mr4d>o?4J(C{^=S6fhnVBjqC6 za|MH@VCt8ROI=V#sf~u^F;s#Mz{0xFv`KY{B;HtAx{NwOy1(H}TUDYaC3pxzf%M>$;Plz;sz0VUs|s?N)zCXXqKh^b^o92d3@i~hs%$3|Y0 z_Wz^mE!d*`qV?e!hED139=bcE8;PMyy1PL_x;sTsy1R1_>5^`wyFo$$-|=^@bFTM4 z-(c@&_S)-?b#JhadlT99<|NlcuIw85F)!Me;j6Cdk+l4V+Akwn%2;vm8&{E-vzuJf zr_IoTuG`>mMNJdKAj|~M?VoZS z6KY9t9*Ru^!WMn+{Xd?zE0`ru{P|PdL#jxOO?%2VJ`Z$1x2A(2iQ|qk@ixpEclye8 z6&=7rBcwPRJsp{ia0eB1UE;Cn-}ip5r14lmQ9-(2A@u>iTu|(W8vY@Y{FeA44V)ch zL{8i+u5xC=vRD7J41X+dF=-LX^JGBCil<@{XSxJC=! zjEfdz{()5twF&hB>aJ$x32CR8RmzGdodCsApk|g+QOS>)xkrcPeht7~%>EJePjobZ zO;jUkIdNpU*R^LMmqa4iw$O1G!vQkr6kqXEfJ$#G_F@*Xxu{^EiA13R7c&Rl#qZa% z&}pbos#9OJIpXi@{z`O=SjawBcf%%;U#CLF_8^Z$_tUvC3l%<$1)8hNAyvpv9cbi-z}O$(Yw0 zt2wF`oszfu0VCei`>ul8j@p)*qp2SoIHgs|r4mWh73`I{ zxh9XpDO`2Y>rf<$XbT#pCHGlH#`E=#rm`|d??JlJXQ8$Rr@GXSr@mBsOBX7nK^f$5 zH-Fdw{D3-70m*=cnDR#3UwNGlkm9~mQKZiDOLQ~ZCff~%&1WoExk=Ptf}&ut$8GhR zuj?1yWYBjd91A8@-;DC%o=JQgmsoWg?0KY+WgpWb!_qufTx_;}KxrdEFTd9^Yhu^s zoiBKgDH8mU^w!?1n6Lyy^-VTQeluSNXV&gQ<3rwC_Lf-wT4l(Xlc9CoshX;&TWXa*Zzs+czsa?{ zJmPfPD^p;flzPeUd!qgl5}c?s!lc2FMU9V_u0(=yM5oxuIv1mqx))Otl_%tJfFZCB zdpd1LOHGJAF^0)_yw;?s_3dAwk*`?Ak^f6 zdyDNX|88EiySSXSdlwNn8BhIQ(h9C6%S`cHYIOojyI(w+y-kk7h!JgTI(7RrjofAi z;+xk_iq3zjdrvSZ$XQn$T_hcMp2{tGL#k`bSEhh)|0()&vMn7MRZGA`^wvi5NbDa; z#6+OefF24SZrhsW9JWl`@YmSznzE9qyga&$y*L&r+N8R_DX#k=JyL_Z(=`p?T0eV%T`W;5EtE}zUSlU8mN0sql9fsxuuZ~1a3WgKd}3VAX_ zw~5@3XJM}a`|a;%nQl6_?Pf>Mw%py_sT7F67+?D9p2aGrNlIxMQ)?l|#1O9?ZR+ZD zSS8BiSJ=x5LySYs*}fG=lqr4J1AEK0VWv?Jjb?!RljD9BaJkv~%4G2*$8d|K@nRGP)>hi(Ww|K|VP00+0A8w(8(4;1i!GB~D;8Z_T<&?MXdbgxb_!3-2;L zu#Zxrr73G)f$l`Aj+(mKW_Z_jW@SH`ipcF1&*fH+-^Ja!Q6d#wr6C*pxnfx$!}=oS zE{5r<&gs_Uwe5?uhOCN(n5d24eQ#y&7ft5BkR}2?}`niQ5!#N z^6-jZIno<(Hk8nh9_MP*{z`*koBE*SFRVGtx9BCJn;4)wHodJY|7QaaAEg$wRtO1X zZx%SI;67-iS7PN%{UglK+U00Rlx3D`Xnv@)%176JdKfRu((}fCX0=`aMlsW5djw^N zyA?-kHA{cZG7I0wXqttSZ32a1h;E|$CN-eAchxGGtf9$2eM-b!SMMY_kv3hK!EV4F zSlljIq(?g_Pt=+_&v);yH^A+qjN=nZ@uw#<^<%hc;|*qzZi9I{Lt?tr7==Mc^Q5Zw zy;MjQg={Yt+NZ?G9=Ug&GsI7yNccoXu8ssZyE$GpVdZp1iwmGYl0c_Ok{~y0%apcF ztCY^9L6LQX!SQXMl#+o1i%lCYN$*QGG6e$JU^XYvM7Dhf%aO*@YSa1=m(Bjt%j&&Z zHCbtxm&Im#=^vZrxAL79QuuG2Mh0hdddA+teN!nE*WQ-bMBuDdln`)bYjI_$Z$eGx zo~wsL8%F;c!y&jFybSyao*R9LnIK72qafLwgwd+R+J}KFEE9{1ezhb*#?Y? z03o@1e?oG>Gy1)YbR+mdR&jbUlcf1dMA96^1v9P0)G@BSP4g)*g>KvbdI3_aXfiyt z2#X@{WpTL72yRi;KWlHXQh80}$C}gcr;VYwnC9wcnwFHI(RK zg;It-1!h`_xq&4v4f&2?+i9%?*^b2#XH<^BFFPDeb`uLb=Au0~iodfNVL_k&68XlO zD*Nji=+vGA)Ws5x{B-Z}eo-h_wgUb0*hVZfb%Xd_qKaN~CCX&@*U`%|>!9asKD0jGejBC>o%%2UHAOkbLnTsouI( zMyX6zh}`4L2LHPh3aBSR`C%4nus6Lz=V5Eav1;5uHDP(D&824yDYpIa`xhAREDX9YP315!U`L5SSI0&sY63}mPR!%BiUtCaV7e@4(M~~eZMieL`YoHOg@d0JZqUp> zF_&UE9Rx2(B1i(bO4>`bvGg5?&*Q&x-YSFk$*9AYiAgR^@#qCXf?*k%7GXE~`PMnMB=v-z!2%Jw@&JWd#!3 zze3ULif<$Z3p+|735T?dw6Q@f|^_l=1mKmFtzLg%ACw@bawOF@Wk zHGV(5*!$7Q7;F1V3O^^guii;V0zD8JaHSzh9M1|feZ{{EnuS37U~M1WE4y5bJ905` z7gZLY!=mWpR#;I{Q3Fe%C)iG+Hjn3V@BT|VWC_@x%_nQ@rw zRQ9j76lw9}0$Ie7{X`eS%hm1T7d6KSNSgI=Ipz{aAC?{Li%_J}g*YYlq@nU5NpO@1 z;>bqu-B@}E)pRHlcomil&qCw0axiBM@y(mjA14d)DxZJ%KJ;8JTO=j)V3#=f9es_e z?R)(V)6TQlj7b74++{>K<-8(3>QC}gc)i8!w-?im2pYL->l17>UifBIifEdC63dwZ zuZ%o`QUO~10wQ7cFSpjjDEz2gP3N|!{NsZ3BxmuKgm?5gMS0w;*nQ&HQ$!LDekOms zPyDB`*rMNLsH9z11XjU!2waovcZL-C3o8P!W@=ns%3pap0#w9%9@)fu#4Xxy#_Ar9nIM zaqN@+Y9!7lM_rnZv-@P}X7Yhn-@os-2B5HPD{)LRq(HJqq%EA(tW*Yazq%Qdf3_j+ zJ-TsPEQ#kuG>)^&%b#s7re_JTE-;>$XG-L4FS;WG^Q1-D3ylMLy}IHMFkXnDo0`<;FI5Pokb-_Ah-{39O>l)C9yIYUbXJD z2{a0TVNr@ydtS6K^<{e%ip7XBx*GUPuC*5q&^iX52w$W zzrUk@xQ}Osr)hTXV5`UbQ#t?+`ayo4)w~(^!kR=7bWiFK~F5 zd8C8fCBNbrG>G^y7QrBQr&8Wh5?R1nNCp&AnorT%osni4wp>Bb;O%a>7!3D{{U``9 zqpyc+|BeT`^4LP%y4hy?*B}bv;oM5XN&cTIeiqBLn*#e0^H?{poiF33F^HTcnKm6B zQ6RM@19)EZ2x|9$huTkDPjkM$)>j#dHI(p0jRs^ql##m3_N$J)alz-u$!;V8Upg%!?AfPA!;5&VliMBHh>zbnE3Mpovi*0LK5?|g}J;TKD zZ+oLxnf*^5c&=#yQ{>!~m3elMS#8BduIUMb)o-p4*hsNn6@`g(ZEPSuz$_{Jv;30d z-gi-x4HJtXGm2Hu$X$XfyBv9a>|I*$I@((6=n3&rt%h?(e3Ww6YnqBC}q zmZEt3(pXlry5c#tQ2Ee`vx`gG%8}M)W3K1yF?O)J_bg+BIfGxox2|OBO>!%O;wgk6 zl;kp~>;FnLy2wCw!!>BJ7QN~hk)wZbyBs{N}*XR=TD*%CboJMI@ zNBjonh|lbe@2hC|t}wSes)@x82z(~!1@@x(@a=HE9Dps<(RCOWXG)_< zN}+K7^W!6e^xCl2z|j87f4^}7HBLFy#`CfMewMcVV6Sv0@tB{?QAW;GxLL{3)njTi zUn`%lpK~R%{mO1mq`WfnVdB`b%Pg^Pb+-8Ty3+tW-*l$CM4CE7va(wTW@&Ffsrt&0 zaQ6H^kZL;47IG%2fQGq&bhHq9eAf;+hX?9Y=DkiN;L_AJf4yc3 zxYXaAd(zi{Fk3t9AC?cMv4^*(sc0J4ANCulPmW=uE~nY6D~>W|_)O^5MnY4Td0^g> zewTJH2Wrv3^26OmjQf#wwBd@Hq*jAv73a(OO5?mamXrCHU=Q%wq?y5?_bUYZMJ#wvJXOyZDgsEDn@!4{t5RiXrvQ zdT<9qZ>jz~Jc!>Q4OY$b%OsyQ-NujLj4wVzLQUZVej_qE`Gz7{!xK`sW zs+(0*ev&|q7ybB^yv4S}W`!-M4{jMvC8ae<@wa5Q@|FC$hRo@wWmwyu^7W9cYv9xO z@4Ti)*;3Ik-$@c)0zvAB3Yvp2JA@xI2?#a+m^g^Es|^hSkVRSK;kT6LY~8wlCBG4g z)q9sEr)_W8Y+|wcjIt)yC_NkG8QoFMFR+vmLnmP0gZB=~7}7RO`LDA}P>H9wiN)9J z=nNSOwW`X*aHKS-H?y_%3l9E!lMq4C_)cfaxFJU4=q)|Ng5klXozrrA;6<#eUQ;_v z=_`NR25zic1T!bMa4W{MLI8qYq_0s)c|R^E!FQ zkUTY$e7?ctyr=~hAqaDj{|?KCRq+w;5+8e^hN$$IPC~wF7mhA-;Vj+>Nq>M7?5W6c&j1&GeKBztKBuzZqxYP^=8$-extvX=8m)lvE?k zz!xwPslHDIB_mvO?hbc)7_s}|#iB*(hTp(FnayUkeVgO=g2*F~3i*8phD(Uuz!a3q zC$Qq?5Y9Zy<5T3;hf^lpU_MqvNn+8N55#tbtB(&UXupwSGf+16X%Vtyt|<0Qz_=G^ z*u`OP+SlBgyB_9JN|$EFCC&1JRmBb#ejseiOfV)4pD0eM+h2NXZgpx2HVBc_auV?4 z{xr0<*t;%(9Vu~cPBZK+4&g)m%A9`&{S;1aa_nYjfa*O`8Nv5Vd4N`Xn$U*4rN)~*L!_B2^ff;Y3|zBk*=nG>qQ z@xEs9GVWqi8Fz^)TYG&7eI9fMm}o&JOs9QS1X|kMjeqL?Xlctvqu4cxzI!}i11y5j zdXQp=yjC|1AbjJxj;pF|eQ(-vA1ST^<%c^f!NiG~&4vg(+TdWN!RDftT8kIz_dIQ~ z4jR=16Ed>na=A4rLl`$$#f8vvMGh1s8ckwg>1ydGS^5t+$1|-Zn^q|_iMFE)oK}YA z{WjJL3@vSk1T`ftsV1Zy0cT07xIYz$4JWyz!YVu|aT|MlIS392=9S!&v@a}E1G5^N zZtS;AS1cPXl4=t*7zuoe-+$6{*aDmTS1KHgev@gnWy6@u75wJ&!Tgo%Kc`!i3WFS$ z(ErKFP|x_c-0hVM_AOJL9nQs&-Du_`ew09GXZ#(s{Uf( zw>1L~@?w_hsq3)(H^4>5VLp-8;k(i1--zWD?r5X<%$ax{Oexwa>`tVWycRhRFh{xp zymsx$ZGId*gAV!cWWRHOH+-4*nLizqz(?@#{;3)6N-`!^(o4}$S!^*uJjJ*@y*@=O z^DFl#onCyUu>GNEv87%mr^gYSR;q5K?!`=U*+o*tpTx3FuM$?Xh{3;tcS_a`$#-cO zHx2Ixs44B}GmI;^v`?RHE(9nlJ);j@jVRkmlS{aJ=uo-QyrT+4u^ic@vKbZ zrJ`NTd~YwhRtf<>L|E8Njgn}s$+ri^m(~?{CAZb`o?6oZ!4_f?*Ch!rE4i4E%kH(o05mZE{h#+XU`7(N&vlIy9-@H z>&`TjR%+`8X{|P;)2OpYUy&Fsj>&}$s1dKUCH%AbdhREBgGjgd2{H@uG+rqE+1H0$ ze{c})V`ezdl-l4$ap>hm6bH(?Kme{Tt zVvnToF)im5`lv1p2P98ISADye{}@*}hM`Qa|5b7aLko5?J|WfTXOI}R+#kGlys(7$ zDQ8YJUE{D|l8L$OA7F5h>$SW0ufGOerJj8!oSLd)Rl;O7bizc;tahqd4ZNcLPvXsC z$#=-KdK|o}(QCLFWcYm&XL{f1Q%&)@pTl&Q%*F1I&Xkl;jsoV%PYtYijXRhW-rCOn zDP#~BtMNjulct*)Ebg?K(sQh#%nF_!Nz~DxW@o~DZd6Udu!7d8e!!D*U=`-mmXEO z77`898pUT?iR+m#zJLM;WHL$8z`!3iP0k!mwrn39(;mn_st^ltxVR4RJ1txc7HQ(? zh#NFN9B)lL@u$^>)oRi47chFeXvOJdSs`J-DGPe&*6a_9)k5y*Ryxh{_<+rCt%O8C{f35lG#Kao_VrS6N_<#k^txnNOj?)R=s=7}7o>OdaOrMIcB9$yqb(34EiP2AsgoLbbRr_#%} zL*rBKxZ_;;RwH383RlH>YC7PL0x2r-d!n4CeeDVsxsdmb>t903KoUHZeZcP7bjo_J zMp`ikKlu`fy3FRP#~G1m&(K&KyyJ(|l^S`CfUC;n?*%;8K9ID8f9YDLeA^k?&A@~V2}>vzBxyP z)&9D48lJ51s)C%S88c>M)eW86%7F@3B)nP>-2S($k*}ceL=(3q_*=ezLxg8u*qub1 z?ZT|b+m42ICMWImn2jlQIF}fSwEqBB@$CPrm;NKggpP~Tyf4;aN-A!b`D}4!Qvu`T zmM>LW<_c0E_M@xrNv~4a!XDR&C0EdpujCA6+b+zFeNtp*wW)^n)~}VtVy2T=P}RN$ z+3^LPH3@iupk~eJ-XQ{Ri>WT4>)Mj8^_|dL>`&wsV{)3HZM^69avq&nkQkCFTEs>X z#MjU$<&Vy^R~Y4n7kj2Nn`e0MG{#tMa6Vawoa$P*JUbvYulWZeu}7JglnszwZ73{G z5MVe{p-A@4s66A2Vk|~ZC@JQX-Os^GEwfBDraK(b3(jor4GN13UuoRL2t;kqtGAlj zg8y-Q7#QTM{2kWY(nwQC<@~=Y=)D|lDrBkFSYX|CU?PXdLRYj@LFjcvI78{%5^xFV z0_cU$1Cm_=@@so&K%teH2+Ye9F6JwcrMAAwq|Ug#*!kVAjf|*Mw^RNMkpoqFI;N;! zUyi`X{TnFgwM8W}&n&3Y@vCe%lstUtG_^_H-q37SjFPdujja~> z;rcySKZhaJB&$;%Y*;c{V}siTEelZxj)y`tU)Esq23as3jOR!9Q?UAfv`z~bnPUTg zfB#bTg4bG~9v1Jx;?b-S0Yq1+jS=C{;{IO}Z2+wh(uvHvcu)xBLmsI*vW~IVrLfw! ziFF%&K(zpokXqQX=4yxmKxH2R01H6$*dSgObIcL2AaLbyjir@Tvx?VAN^r0%M=~IB zK*I8U$75wVNP7X5v1B7(YZb^eVtVmI-iD6Ef1hD)dH?-wq*yqGaj2YDMbz=1c`g8+ zD{V|Qs8H5X`*ZWOjv4_$4S1`xOHhYZKSXB-Qw$QjzZ?9W+r@uD2DMgt_-i9`GcSYe z=fH+*9;hj4eD`{9=L0DE6;|J5A_LLsrvAXn8(AEtG%bF-O~&D@Wspwgo(S|BIttYd zAq}%@MQa;+!>Qc4fmY}IE~3BeFrNB|FSO{}bXvw5BpdFBDUZYz-j+BiEniM_+)`l= zVR>h#JvJ<^jTJ$}?Q_F!312VQ4=zn!6Y`9BU9?u#S|+~dA(5KNMrTdsjd_Mq#M^{$ z^0d-0ucnCaZwg-tme|)I5*hEY9ByRaZ;c(S>`P;q;)7| zCe6uml4~!gJC5(6&X(aPe)YlU{c?VxxnLnY5z77Y9xxy+gnz(k$8hPc?Hw2MCn7&F z@`~41?MAkQ0Hwjc{=`CVr%>a8a^_uYUi6*#~$ zQVaz%yfY>hV>ZTfK~=l|%f+S1^p9CqvZ_`Ae@s8jD+`o!oVvGEpLwe)QF>5m<*+$2 zzB`t1({OngZ=#i1ap4>j4b-C(xfz*_Rnz15E09RGu*nW9ZUAc=!5)*{P$6rJFk^+e z4;-S(fD)d2of>4OKl2#e&AzbU3T@!ef?Od1e~Q{tvG~EWiW208)drG`Wh}L0a6WM` z?Z0zLOb;UxtzZlTqe)1`JP^s^!{jBI2t=WtQyQNx$hTuhml!T@bV1xW!MU z;bE-53L`Qx@F-Tjlcg!Hl@hl-E#eB1F5E@Bw+O5?g?a`vtr6~G!5ZBE z7GSy7F~5!-vcc6tAK(Er4X*~U2FQcvLTE!^Ns}sExZmrv`DlNbEy((}oEbAFBQ6M< zu*a`+zAcIcPzrSrIEF=~-GYovlmq7dO+*Gu~)tR0PlS#cT9i{k+4p*)_hhbkptl6Ad68gT_ z-&Og7FtFG-JUi)GWI%TR;zmVC36d}0`Jmt^Sy-#xgUZf_bS0z8u%&n=IklvJwB=HM%T=ro?O#07l)C zF}ll=A;e|CF&m*e9;z$ph^ja+_o|sl{8Uhm3s{?%k zT&|yszV&b_c0l%F!-&Nu@3LY5F=N0GBAZIsX*=9`$dx6@bKtdSO5XWX$k#Z`7?Eh* zu$=Cb`Z~;g=ipBkhNwuQgs)Mdv>o2{|wesSeWM|0OI z?!+lGR7=Gv7%p&lMhepM=1pPRoqtWLx8u&x4nSE<9C zY2GgZXs^_7wuQ+cu{o(=JKFd~jV2N%^A|unT6sv>sOXbZWQ|66WCJ(m2xUI35JwbTiR;T=lgQ5xRwl`DTI)BGsIBk%AN zgnwe0YeD`|UKF?}3)1=iv)6{f_oujJ>T$*d^h!&Ozij%%e--aOoUPz?6=qHpcrXIC zCO4lN95neT(!mVt4?u^I(@?x+q3&?0-1IJHXftf_j9Cwb?Z)@_gnUj=s{_D3zx z#mcm)@xMrdpIeCg!AimWn6-_ccHU{&%lmODQ*>95mx0)}Y=@a2H?GSHuyt)TcTRNh zidMvJ>GDhA1E~GS19x>KK^`NugI%H)?Zw;&nFU$f-AOQl&eZ$@>_|9=2 zAmt+&Aq65l#*Ln}x|QZ?Z{&MEBW2o;+yBt&q4=ABDx7*sZm zoZxc5pDV!WVpaN|ey{BZQza|+7T!SEf6sqA!J!Dv21c|+yacgETvXc zCG{qP1whSGqr2>_910q29cwmAY0zKb?&fl1#>Z|0orIpO~p#=zIatZvP3aFkfBPQ;#QoE+(kY&vy#U2Jl%siLwdM`-#DVhl9z|NZOOY@7am)?BI?cR)A zJ`DKhO&pxY3^efH(ww?MG0hkpmLEI~t!_f&6MvgxSCeg|4b62r zHa^2D`G>OQ8$3{Qy+aW2N=$&2*=I9CDO{X*nE_v+Tc6nIOAy&r{cdsB!0JGNURwIa zV1{*dmge!5_6cP^Ubyo-|DfCUu|T3(YaHsb7)5;NGX}el-y?~@v$Bie!O75|LYq7 zuM2OfR`YkQok_5-Y2UO_slEh+$cGSy4>In#n-JYVaOMS>o7pG2ZkWKAeqOFGwJcuy zvGa+91?^RwmN$;tkeI2LD2EC?O)t55N>HFhUze1DFGsyDNq7$75Y>K^wu(=sqf@c3 zU|)G+vjMODCSDhl+$L}xD2n^YRj<`~^?{%A=0~0EzEj2A>Z}C>bw76{)bdeRb)ca~ z;B4^_;rEC<332)Gb$)?Zg#|_m=ax(cq!slQY&(xq0IGXIfLY%OgSr22LCG|K`uh#2 z?;wf}L3h6yuIQ-vxV)ZmIV329I%0{u@E1?Oh_z?SS3y@*T+&~}if@h2$FZRw^c z-bPK(*?mb>df_-B8ccN(X|=&FZSm~8p=yRbXbcKQR{_1EXHRj$%#-Dw_go@gNFy;y zXuyi*kMDk$&O)kCRCjL`FXshRl%}QH!LzsN9h)p3a=mTohtfvh-fa>WjWf<=91bk- zfPK%0GD75Yj$q*}|J(B+?fqO|e-t*$J`yw08su-e8S&V9(&Aa@ol|zs$mZ2>(}zet ze{!|1QuaXxRk}87Iit^AaD8!T)nAy|#lK1R6H_tqQS|N@ODL**Rn_*w%cmmJ2R|`g zmD`BGao!zGYw5(w!>?+Kq$<~eJlbc&{ z;+`&cNo=7!R%I|os&C(cX_B#J)w?bJ!{f99oVsJHB_$75y^M|dxrc8O>|#>JSXAm> zTz9ucPsV?x9NHD)BlpjBMe|=OjgsBa)~vHC=#`^hBK{4yLJ|0<=e=?PCU0m|$lv`M zezdM;4nM=4B>Bp3?qg3JLY(K@@E5-*f5izubC^VHSui(@sAYIClaE;Rpwva}KU2=`ep?(F*}!XbU9vk2!(?5hjhX8^2**b38%9M}v@Y z0tC@%PfIY1R(CG~8IotnIdD!;`+EDyWciAclzsOuR(qrO9b=w4&_x}=8LcaZdd{eJ z%=Jkf42zG^<$BatYm#Q^DE;<2E|gmOyxE&&&Wd`ILT$bKd2^H&{-BBM2lvrmZ#Vu`}BhLcoswvDsR z<5f4Ge&+s`We1M3l)*gw_zj)xZnx*>z4Ivf6VmB*9N{s&t zw03eL(htZ;jsVk$K}e#u2TZksd0rJU<7lCFPztkU?Nc8e^tZhniKK8|lgafhn04Cx z{%~uSiQGY&5u~&rq~PLhDj#}Gxb1x@qZA&XeiSbf72%q;;tacuR4Y-s+GS0&{Z zF{O8*6G%}g;b3QT3u4DOR`OYSpRBa)K~+JMq58Gsu3eW#$#Ba09J^(mKAsg*W7eCZ zP^X#DRTe7s!SMI=5GCv)%m<)%e6a2R`1Snh=k@%XUNP8r?Zdk96A`Y;ahM7wH+lW} z7}hs5y99*Fn}j_*olb)u-}yB~rte{eAYK`ox#{w1rV_Y{&&effof1uLG7hB^c4K`<#h`b;!@j2Pb2PN1jBOK* z?)HMCN&v$nuzat~H@p&o6TO{zpy3fdxJL=-U!aM(+_*DJ6H80nQv>3tuigMs^wnp)dSyfY7YK^e&FQPSU zG{c0{3|uiSt3L+{84J#Ity2g_V;s2DSQ#BV{diq-F=v%1T3}X2ilq|i$eJjI@%UD+ zz!ec$RJnvd#zkFEM{zYIwdb@b(Y*F+VRS{MZ|rb(mBZn&|A-F0&X@DH3SgzMOKXgfS@^Yr z0oBh^<7f1uZsk#B)!N|-!GLvqixU`V)#KT_|8-jLep^YCwgeky4nrE@CQLF&mfUOY zYOvi7nV~U|r_^TK{4fZoS@tCgwrie)rK&6k_YWLIzo)+TNdK_p!#<&`jbpdSvPN2a6WqILsA0X&rYC@w^gc#%!{sH%!s3p*50QwiXP-}DuZCqekVjDa$V)PqJ zef=a*OG5U2=+hEwM?K$GcP#AiCFBWyFgOc;L%hlD^GY^-c2$M+8hlXIe%F$X1w&Rm zuw0N1D8TiCW*zVxEU>tjle&(Q2g8~Yi1`^Vok(>PKSiaZfkh{rdK-R*OX;vk=HQz8 z^1?>hrSHo4lE^#k=eE<+pf|c59Q}PIjW$XVX=XM;x(EL10$}Fan6kL^uN6h763nu? zbO$aP(n@y*cyuJ10XWAObcq1A5-pp(E6nTPb9B>|SY6K=Ad7%dJATqb8(0GH9Ke#Y z9!W5@LnN``SW9VV&UUeTtoIza>Ue!*ZT3U#>bG8y@|b(BvG3gWbdK_Xtro6@@P+=6 zzc64c0ZKSRT^W1AQ|QFbrf%DYW73o=F#_ZU!%X)=jzl-QA`eqRzqQ6rtwlop%JPj? zJ7MMsy{6LOgs1L3Dx^%yt7`f~pIr>&-{k*!#=!weNq^TI79bzi`PmyhXJzK)24cjM&LKf(5c>quYGd5R> zD;Tp5wS$qu1qE>}(0zf$vX;QuTO%{nE0L`xXc=JL1De4UHOf=qCTVw1(sb^SCKSG&UAT#uDF&AiP~+!Y?HjlW z1U~#F-ZK8r66;9BjWlB1wJa^-I(DX-Rr9mA`Yc}1W#9Vbi=OKjs9)Abo7+q0ij5N$ zscwrwRlS>E@LzLQ{jR5Z=Q{SNktQ>0y6~!Koc-hxnBGrsZb{C3Kn%;V%7`<1f=mRn z0nmSjY{LV@`;f~(jBp+>T5TyW?lg3I-FEr}%zS|XivtHxFah^a&Gv!uMvw8Rp7Rj+ z@>6(OvcJp>N=8nLd@c^Y7~pomAtl@P4-^KPG+0apd+Iar%4iFybMPJTeEN|t!&767 zG_rDekk3MXjhG|WzGZKRCD+o1bqw}eg|oD1r0KX4xbo*n5rKeU9JYxps7)z9? zfFgwinMquI=-lOoMIGpZ6Ct>G4D%jOX`c~_yLxIRIa&g1r+7PPy!7%%uX^_<+r?O` zqHId5Lgqq_p&SZm>Tqgs`KXRH9=qTVa3D}E6Z4e)&g4DyZ=}qfQ@YlE`wGj0p~$g2 zp*z=H4!X45v4JZvsn1|^-PjnqCjbvf20XLaHhDb1;89X;2Qt?c53sXYVJV;Vl(F3e zF@Bjem#5ZR$I>oPElw7tvs-iakoXo_1vZ7>v=nDY!MqyJLOc;)D)=OEc=X5u8<*Xl zN+!~4eSbSv6Q^pQG$`osCamg+Az1KJe^Vxu;ajLyy*X?`9_A5T_lncu5UB_m2s2cC zQ{e8vZq#V)<~9`?5qCh0yZo;gu)ayWxIR-A*iLf(CJ<^0l!xPhhegl*A?to2V-}XE zds>m?xI(@vdm0h|NkbJSQP;KVAiGKV!uhP^oIGcyz&^O3Q4>=!y0%6F0~QYFgs1{# z`Og|QC)Fj2uCM;N+e6Qg(eUjGyf=BPc#sZBu-%h}cP8DLOg9MkQdnw#JAYh}?1^Xl ze3q-?n}$|UIyv{y8|+kUyWzKkd7PjRwgD$1oDT@MChV%C-S-QCkbn?bYvr&>oTrMP z$V^+x&=;t;_k-AjtWQJ=J^lUR4i?P5om9iiSezMZMQSh(=670ly>daJ(QQG*qG$mE zbXp9)Ki)xyZiG~}H7CRFwi0x!p@oy!|H|>%KFO97Fs*VTm-=%sF2E=l^8ijA@c@

CmwtbEYeIfYk&OUnkO?plM-U&$T!qPdG-jaim-4|Ra|mKDfED&@^C51kDtF5f7nH zF|iXMNV1H!4$OPP%=3f$0q_P0fZB4U7- zN;kq{TpDR1p<_Mt5C|OwTMb|I_oL3`csfq_>&#-JiUdT>Pi8fqgdrLt6zU)%VCfrf z?K6%ZEB$4#95a))nsW*8zW%|k&?F^)AzX^2Sil`(kL|TX3hjUVPR}ft|wlCcyK9CJCcZQPAxo zH^h>j^oaBOg7M&%{)l!8HPb~!rcL~am89^q=N6^_t_}|Ohrg^_!|&gn4=cdik`J1v zwG{Lje$#UE@H8$2 zt`=caMLQ*b5G|-D`D2Uy+JVG_+S0#E)K63ar|aLqK$68*+?1-&7ueIeefC=2Sw_0% zu}8_UuGw`vhdnoRdH-*P)85?sTmcGO?f6A$b)TrPThLykum_7}|365hu;>42!`}6h2B$Jm9iPh5$Ld?Ey`s*x6Rfg$cR< z7>`a}LCysuzvMn2=WwqR^}+)bgRj8147#$BbtLJ%K=*jO0e$A-n>2-~)orfYP?p_G z^Z(TY2N?$p^GQSG_`O`JuhpYMfrIfml}|;xi>B>S1Oa9Zr2~)k!iLuTIm2`75MW8&E8``VJM& z3GgsGU&wcdRTCV}SzOGG3~G{rNIBZ68T}w?iKI$LS)7vgl40YwPL&vN!K60| zVS7!K$%z;FEiZz^kV4!So&A*$-e(oz|8W8dZxF_h5B5YQ4KiVVKRL8tDbF~yTX}v> zzrwXb*;xR3g130xam&~!62;VjUPB!Zuk%^Bh7G_Aw8pH`^YC6&s}A>Gy33q|;<6bBYR`VuyX4Qj~k4}-p#O@(h2jiSqa_PQax*5Hva+ncST^{Ft;3*=_cVdr%0_4q1b>i z%GRqcX@8tebe-F!Xy27MRo|sL#-f=FIweWOVWL40m%8Ya;MEd8U-Vx4^YgHkdi){9 z0FI0VNou_bdTwz8e4qp-9qix$S(nw1fQyCi-$*ns)U7ADeJ`tKYp)+ zMb>S<(c$cCpV7?#Za-r&>$m4Z%$%Ip5*i`V^gKI#LSkCeh614pq^|;k-+(~w!mITd zcji`PChsWmYQ!n-?>80Cd83!o?>?V(YbRaqOH-f!t!AGTS#`KOs!RB?M5VPh%bkM;&#J~554Kmo$TB-bF5(uT+;K{FCeJ#SqD;d7y9)b- zvK#KS79PY#0Rj#DAwi=+@h&4sxi?lB=~*t?ZQ&Oav0J~Lw5WT4G%hmJ zMHx(nBmFI5SST9eQAff)e3-{o+8>i%Wfm@KjJ@8SPS(~cHS{BCljaxZZv6;`x{~MD z^*HZ*>IPfaPmCxk5Pf(Q#J8Z&BCkOK4&@(9@(K&;r~h0JLxi{L-F1ur*Tjg0Dq&yD z@Y{;Bd+Pbi*~tqBDItpf@1t)uwr#yt#63$8*>g8+DuhzF$Cy~ZSSLg zrQ_x_95NfztmogT@tZ#FvEuA~6UdvwIFtqV9%R$*y^Y7O)5_1YxF=wtlOM{iBs#?> z>nkK8%>UWbz+;m~2ks!bGe0PS`KPxe&=GND7v5}_j!+Xe2n_CKm9FQIJ#y9$bM05p zTkbf|JlafR20?rZxXZ`~_nfYt1GP0N)a%0A#R#NH=cCll9>j1dEw5um@^_{s>_j50 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�dbw!X4uM(VS;$L6nTgUwra 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 diff --git a/Documentation/UsersGuide/images/ResInsightUIMediumSize.png b/Documentation/UsersGuide/images/ResInsightUIMediumSize.png deleted file mode 100644 index 6ad520ccbed5116046aecaa5a74ee2c139aa932c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 332035 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%0DAO zQA%FbFVb`X_5M=E>c^8lbHg)>0#maHL71r^DzM`rOBJbLNw!W%s;F1G^#w`JInK=4y1Sop?|Apv+@_V<&@h>bq7}dTW3Z_J z5~pHIOUq)YAk8X=m16w9mEAgAMngyyEF6FuKwY5if)LgR?p)AAdrzk?T=^9B)PPwc zJ0OO8S%JU zLU59i|3ahs*;MY-KTnDd$%OdJ)Ot*k!OJ@sga(Xid~|Pz3dt}eD0?Fd>5UlC(3m0t zw6Kt*LzHfR5-AoKdcZwj%;|AY`YJAD^rftRvnt5E6PtQsXi;M`N5 zms&aNLJl2Xo(Rn$9CrL^cGn5rZkny6I%J#3IoCH2Qm5Uc8P_P0$Fq9$nBpJ#`5m?ZNSOaz1YH z0m)}G-_9BR(@K?I_^%ixRf2or4%M-SdasIS;K?I4g`7v_yLxf=kKi2D@P0+2eI<^^ zVb&AgDiF7{#8H@66;M^{LzScMuPFQ>T}T&9CpV5WEP$0Ez+}zRkEEp9Opw-)FFdvn z8{3C2p;=$<^_35;tlXGM;|Y_hogK<`2_fb;e@G35h`l)7WzhHm1DuzlEi$>p{C9L> z7u{kEIg0{m80&Bt5emrYLTk+;2o>mxH%2kH-Dx=ZAWLlm31}{Ze_b(XvrKwec~KJ4 zCN>twco<*NH6Sr2A(gQtBqg8ygmQ7cwk|z=RlkrO^Hb*NauGnU(*IPMv6%K6m(>E-yFUU3@KCqH%SYbCF z-^OX00va4bc)kUGzn#URrcgnH&Xvac3fQd98Xre*GFmckxuh1-83OP6h=6tQ_4+Vz zH6!RlFo1;a<;v=Edi#b}QbmvzaH3K%sFb6Crx0V1)(~`HZ-x0heY}+_s&FlfcNNO+ zHhs3r>e)7KJ+f=&$0A843znr~FeGJ{hCysXgJUQ#l@8GNb}SxGqZ;kp2PnFmdKDh+ zlRM}?xh1iEvFi$WApRyR)toj}j**5|{8WIPmw%F>+h)M-r>U*`t_rR1UXm<2RHaUf z+Oh$mV{DXPGCC-6S?*SgR2Z5q-1WBfg)45nOufGz(#zaBp;|=e*5yVPW$m?Fc z;Au{6Eg(br$S^u?E%0AuUcYQ z*{6YN&!ZEUN#7cviLfLT+aK-k1JGr3-q6oX>`LvUr_uIVwit{&c3Am-?eaor2gK-z z@ie?3t{+_nD3=5MudnPD>Eb6$gwCZuXw<&)g)QBp3?P=^rRS3%h2c9NyO~uhQ?Eu1 zrqWNS*#3=yR7Sm4ZxGw1m8XAT=isa)3RLx?y3bGMlQa)w&=vR(&70a#gX5mw!Tkpk zM1@X4bmb_y1YT~{a4$6}phCyMroIXuFyX~R&X(GHe0>)(s>5Zya#DBW0(osXwyrCv zq>Pz2te?Y^Cyx~`o+2XNc;~_$XagDA%)X6_1j$)hA!rS{W<*~)w=dHA;fd6$}y*e4-(z9h*?bRt5X8mdy0{d~Ktl?qk} zJ&CfbPWX@9O`(8cA77T!y1QFLUSXTXK(l+r>yr_NfIz>k8iZQESE~TkJwwd!lW=Z- zt$7L0JKZqx5h335j767~B?96-*ERxGXM6=UL+KXGUTwQ4*VNO0E|Yak{;n6hlRw-E z7Wbz~_+F>>&nffxUWa;gYnz_-20XvKy0v;9H9y~6(P|jlJv(*_A(YiPdEd_GT;>}s zHL_0n9IhoB2w&UQN^!sbTjz5(lsot8R2ygl{_js8$3Z>>>aZHg&bTv3KHZL!$8*ej zEyZ->ruAHQOWE_syPtpVm8xE^0y7pq899!OT0X(ffYI`~9*?B79;w6T;ldc^iRXp2 zdj~*{*I`mApsk@s5*{0${I^l<+x>z9WK{#b7^%bJurRwui4{i%6>}wW zS$L^U*?ha>)G5i#!=ICTBbLwK-V>S!<7H2NJ-ycgPv0^8m=c1>xD*74<5{(srY6Sx zFTy@h&X%|8OeXr?eT}^Rzo(8LfZzUB0eYx-e>)7xs1g%-6)a)Bru?&HrJ=#$n%9>q z;Lw(TYXI_BXv!uDv`1MVY;Xo_C^QHH0Wy+qeJ$-i+I?} z9GEC{|_IG@q^hC zCuNDaU;uraHHs4BvIQQ=5-)+g67eQ(7jAKNu;@$rkAPH5wbXyVJXIibG^oi)czJ(I zM)&&qeB@)7=hEaGR5wI@N*?5Q_7@$4gbA z5G`GOyICic6nYV^EF1G`W5KM+5q`w;J2o#)gtC?0!{{HwaidW5!lG- z2K&SASOhaEJ_E(>KDNVVblL>c#$oM0mm4_HqGiiKUU=t;r*-C%ZL?y;p5qH~oD`<+ zwX}vcbVsN2$G_6crB>VZhdop)z6pcyD1BACeXC&Cv>_G^E z*&=NTa`Z${A-q^`y7YxWvitsS4pOBd)S@50#=L%%N0TwDaVOOGAi2M3mwDz%8K^=} zWX344ASyC(H~WJ5nF4Rio3eTSA*kNL+_PIG5EtzHm!t=ZqPw(pSsCd7BHZ= z+#+wy5X75vP|ZI`bXi8&D2l2C4#=;M-M+Ki4oTC~L(PT_`$&wSt5@(?*Aaw>43=cy z(Xv*;Jm~A+J1*29k*0xeL0VRB3Nkq$=kwVR_QNvpFcI^FjT3ok;y8! z3M0C3;-*HUe0udCzCifv-!u>lXI6jb7$5QPFdDv2M?`H+U zPHhK^x|PJD7$!@it+k6}$=&6wvl)gba?~El-b#}D@L1_ovJ9aPZk_#?B2^U(Wf?6h zome!L6Euyq-dVK$KSp9D)E`Q{I8n+5`f^AL8bYIr8UM2WhD=$+^e4_jG{Pd?9)i}I ze7p3YZ<5QpkFLE8NuFPpjr?^AOiNHpyEhvY*2guf;_|*qHpF{%Z>2e`32i=K1MJSc z_q~PDIe^`?3JqGWF|5$8ko(-4@#C;+A%mCuE1x%s=AUTd^{tngh z=y2cfW^TjP>Vu6y!AT+D=pSjIU!#vk34?}ii=#lf(JFnQH@pTnanW+PhFng+n` z{e-siLz!CIa0dznqXtRrN;qtiK+}+=&~^83R$V@ypbZiG$-)0t*$OTaNJX~8Y1q@h z*ri(w%zt|`9wohHtpzqbKhnz0x>kI}C9RzE97aXpU&5L<8N{^V9@nZ`GJDJO$eA03 z1Xb_e_{m~!TQ8M)RBv5=CMKb=HrvHUJ)ey{5;j@0TUUE5wtRq4m5A*8sOo(VMqr8B z5D|DNL4b8kc!^GR8jytSA_WDNvV{y=u0wC@vS*X!rovOEwr;nzB0n#%RJ-`=dajtv)}$hN*VmP{Cuu>TGFfa(xh-L!3f_Uj3BctTBy`|Q5LsR*nM z)Hx;<1MEzF0sMWl$6~&d^Jt^PJ9+PG>jbyYTVRXhn%B+B8~{*Mj0bTKw**X`N}=+~ z%E;KS9<5P}b0QLGg6I?{g@sB4Jc16vWH59cLu6oO{!MW40TM#UV#xx@Mg z+IZrq==g_Me?!1fo=|i(9pj>Zz16XY!`97FQE?z53l!9y-@99Px!P^_x%Ew;#o^># zec6W7Qmagc`%{G2l`E(i2MQ-Rs(ZZiK(p5ey9me~#*OBkZhZWaZ}QJPmYd1bNjznj(Dh zzB|_|ih1*(D5M()G_lez{zkd*4u*Ok%XVRbEgNeDUIjy0uDT$Rh;|1E3G_o^9cYTl zwN`iut^lhKFHle!DI_SU7L}OAj~GJe#hpG9Qjj}fNi9g?XDNNCbA;C7bALKkA)Oo+ zOq|r-?e#MZj8N_N-gRVQxo&cJod>5$Qp%}PgJdE*oQvQ(-RAeFvda1BL>guOEBvG& z*d(#VU*kjj*d6lOMgyiH&azmVXtdsQu94*!-w-Inn)@&bO;h zi^b)z^>^Yx{*g%V;ix1=uV?#eU}>thM`+kEF)t?-2E;W09dsL9`Y*uAOL1aig81f7 zWLVy0ch*tM`ng@t$LVBA6{C<|N?y7a0L?Iqh>HGKNu;R(dJ725i8yV&oR!6bjxLQr zIeuM_+N)X)419lCbk%aCrlHRH>Ty?LSEF{?gE#~lnnM<6M;=nn zSG}d@>XvEw-eUUA#e%XC16--;mxk@#_xQ_A1K$Ds)TX|5snf!BG)bycrCE)bj}9eC z`SbA=23n+%Xhb<6&qyMF(RSLO)20`0`_Np&Fu+BCj4B#(1}Uzfc5UWAirgo6tu%s^%akz$};W(R#pSw;kFV7B)aCfp1f-0S@N z`0)m7LWK-+hy&~L771QE-VE=A2S-8_jXtde>fro8vfG&AhDIjHpJZ2(U`T~|YI`p) z>0H&mUS-@QTXYX)IwX>`GibF={L29b3-=#>skoCpC8ySOU1jifQevIyo{FNomzCI6 z*SXx!p(DK@tnb%y2n8aETQMe7UGj=s^8kJT5F{&$)IMD3yYcsPavNMjABlEd1ueAd zF&a~Q`1#6BDo3YFD+8i*mK$oelturO)l$b`5((M}svQhR!;p-Oi<=l5BjxkS-lQHJ zT$#j)nbXF@CNXP-A=&?`=)`vDB@wYnf}76fx%7JgF5umEa~P=CJ^c1Ea<->U_>Dkk zmcK${iE-()gBagsI{zP9+1xQoc;zC4X1TV@eY%l)xq7>0H9taB)H%szoAF7s?;{5w zEBKk0C%iY{ois&5Gb|;Ga7z8{J_rsoS;(fDKYovcSSWqoBqoONtJiUkUh9&>)`dsA z6f!>BLAA@R(EH?xbCUhGTo%Cq+ni<<_u7?xt&s2In>kk|K(tk^|8Wrf_Lf09mB;Qd zK3ttOlHd;zf@*dL6#NWp?eo#c-b@v_)zN#AxKHDFg>rc>H8o3zOjjRoXJ{3(bA&7e zEnUW=ow^XiT=tXUrbeOYLC~iKacW`RMVLljCA= zXyj<0k6&nO_~`!4gPCyboE`67JPPZ{bfdD3i%O2K9Wg90tWKRS)BPMSw!H`{>v2g!pNg^i7?g8w0_ls6v%!yJ@Gaq zOkreYk?Fp2WjyrIUG2A3Ru=N>MO@#RY(7pFa+Mb;v{1Y(W>#LUHS5B{A{axopE7Fd z0RcVCJS}9x!aKek1Pb2X?Z^X>h1OgIQ#k&P@dIb~05IiBuyo=qr=nIVtvtC!J`qh+ zHfPK2(Mb%t^XZ2EZNq`@Zx|>l+B0YV$HpBQ%A+&cWc95}FpF6;_+en;8+8G}vEo`h za~fS{>Fw<;U37zlWIdA^Yn}XaP$*8Kay%kha;XhqM&?YAH)GeLjYsg$gLcFQ=$aKQ z8)wc^Aq)C73gnOvw>IyhFlkxz+gZ+ltVK^poy119kuQn~+vR)1vBb1|H$f#jX{LCY zefG$BP|dc~7}U`dX<~iq{0OtApH30K7ClK6toP3d;SSt(q=8f8R+o2?bi$YWtZ-H7 zmU6o>R_or&J}M~9chv_iu?}>Ph>Bd*7Vn8rCj~_~o$;M+WNLf1(7Qh4D*7+71-Z~; zuSr&ti4m5`Y#Qtg*k#(O;Br=RlLdc95`nhoCvT{5jRPw0c+Hy#; zN<_xf4;upYFiyI34@&e{YPwQ}k$w!~eF`o2I9xL^CV0pJwxka#2d;R5R)0#EV5ZU{{axK#8_^; zzQ!}sjlywvDaPusw+UpH5`XaxqUnR~W6NT|$)$^iFue&7zI=odaa4?VOISWDu~|EC z3#X15<$X*-l-jM1EJc@;r7prUj7=mKm;WQ#MQt{%jr-BzbyBA0ockw8QQVav4i=qu9a z>7M%jUmC$A)i$j!rU=;GJPpmnEJNn+Pm*=85@wY99nS7O@LTCrcC{%~6oSd4N%fP5 zbVL{?hc(cQ<4CTRu{dF;qx3^Y2)Mq`KC0TU>0*QORBuFmHwboD==Lc8EnWSo_&#b# zV~>fi$Dl%US8}D{C);5Rg-YJc4_PUa;8hlsltg7G4xlSQZ1@sOPHHN*-_zChO!m?i zcF*(%v;LppTv%wP3BwLIn-!pQPh(DYECYGvn(BPL-OI$(>5y{ZUuLb9hKGQ`l5BT% z+-xSqn7ruxB7UIG2>N%&H?ZF_i50(=e9g>ZSe!#_v?s!hCq4gwPw4#VBQ#5)`?m%RhR>R}bcX zkl>^;k)^E=c00_Da46c#x>;m(|DU@!+=<|V;~n|0lqT%3mIiyvOvAaPzw({=Fh?-oKRm0GsD(=O)Mo2GyN@VSKNGZk@^nl!wuObk`;s{F0{;#ajRs~8qa*297N#+i- z5ZmAmlh6y6JR{N9>k8ky0bE*E_WAL8x!LKNZfgu{Qz?^O0}(+h91 zMMS0gpU3$cfZ+Td^^kyoVLH>}X}P3VxINVznR!J{%{?s-EzG42wL zS?yO;AB^gMizJ(1om`BT+2>5O*#GZ4798E88ABheMfOjvJ51u)^5Rd5hcyZN!W4(W zy=(Q~+Ag<;QyAIG$I$!cM~5$nz23MN9gs#o-CH}n#h~fhZ0Fg9vw76v9-)sM_IG|= z?a{BDuLJlbJvwp^uoXRp2J)mxrJ9Gk+Xn!hUvBk?*yQ_W7as5{;6=3B3~54qE&bS9Ul z&$q&#Jo0F)#Qf)_Hb*(~%N#i!$4_+rOPM;2+gZGy>fs3`6_FY^stMvJlLe?36tUkJ z;u0uL#jl|#uqvtv%NuN?v#sc&5%1*x>+mGgSBzQdBhVSu8ni3k|0c>s{)m`b@&;Xr ztW)(J$HvBob*h26N|InH3wRFCIx1ExlSO@P!%l( zNcKK)`wtzM=d@@8Pvh@4#2O0H#66BLJ-Lx>Y5NK=o|#5UXjV;45se}W%gc|gfq|rG z-SA3uE_O9LJLC*7a0Z@OOrMR@kY`K<`cqFQ(tcyhcD7T}TEWCCk&e`tR|T zSw#gn=4wS;Whlr&E&>Hp^i^~*qLC7+)nXDD(a09vlB_99SJNcs#B=Mos9kTvs(Ijp znN(EZ3-+n>RFkUplN2~sLx*G}8L(!tl;P<#*d=P%cKz2YABOk$_v48LgfY3;K> z>rgOk9H;Yg5-f+!@bFULkg)VsAYxRqKJ{MS=+ z^)4>DIV`tZ-KeEtOkC2k#gpN#mn3QiIV{PonS{W-=7p3{%7`yK<$ATgBh$pXt?YVC zf|soS998NsK)vT4+<|Sf2`mPG|L!^IgEhg5n+2>mXDsCGLiBt+Ml-pMTUi9Sq`0`G zpAuC(cAEY=?A$I7uk%&vm2S@4hK;LC)ksy%iNB2e+xu~FSqlz_hK5LleTogM*Hn$& zOjX|qYmt|2n`OsbfHbkY@9B>0JcI*m@C68FhP5e4&c@qYChj<&^bU=FepFNGBxD zP+pQ(I4?8BS*GpTgr2StLAdlFy03xu+s{p$%O6d*DN;;28>1Q0kN%$Tb9;3kZG?t$M!wx#x_SzvYsYVoeutd`JKzqd6IH zsyd&nB$U~jIFwcxY+O-TffOO@*$I8Z_&ETo(w)pQ~f0_A)Rl6%$ zT#11$m5zzX@#avn;m$TN9GgdlPYXFAahxlGx6dLVs56~D<%g`*ITSIU)KrT#M)F3> zhcaelE*0%ybbmhv)hbJ(UP9j9 zuB%ZeVcDnJ4HU44@9AIGJuZm>q^*zjPFAjAOehkKKk(sS`29AZ&Uha!2my4oX4*W> zes8Wyo>}kL{T5YAu|77(XO!U%8$EXaLS;iv?4(>lK zA_0>?GLWoY=WKcM$>_Ot)#*` zLh$C-lj?ewba_==pj}Yv^mqfTtFo4BYqdL$hnwvR>C)um&*w@8hR-{P6@J|fSFy&C zzOP+#9`U=K0zL|DpRt7g)aO4^Z5M?Liyb0+dAp&L4xBC|PjG_&s)y ztg>SV0EdVFw!7lw#FGlS4+wD!XmvcFB3w=&7V+j41}s|o z`jacmhU;~X)!f5(bCaup_<7@bpe6Xt54mh# zd)v8rp63F^bGBm^$_0qj?|G&4;gFdfc|Rl2JLPV~qFgj)SPGCtisk@MBCyNeutt?; z>XcrKgbq_SdWSkx0zONFb4G}KzKfdk!3Pqk*Q^#9PJ}`~vWJyk^>H!SgQ@dbFn*xp0v#Taucs-yMkv_y_~h4S&LwFKKl~z21>)O)FUf zCn<)sMiSH0u;|8Qlg?2g@D!vf7V5V0aeo$mQJ8O1EQ148D~_-slTkt9A;VHps9@c} zb{je+uFah`;e0XlaaRv8BmtH1;?-oS9m@54b&d0h6;`SWMMK&H8B z8R_O0xIwtLRjFNZvz6!h=r=q(0-5vcWFb9})af)lk#q#U19|O=E zSY&+7dewt&-vA$%t2%GeX+QUs{1YdoYcD}Nty;fQyNHq)oF>QDmAZ7JN}Z~Q`I!er z85v~tu-UUqOic2~D0XIpCg;a#;^wmj1(tLmO1Y8Ut=Wu>nq|?lnTv z3d@g3Grx&Hy!G|y5#Uq1bVKkava8VSU&?^<4lO$-_hD+v?dj)nF}mGhfTC(j$6TxOQj#L5X3Oc=?wHM_ zN{LCZNW29@H`H(`3+_W{QlOKU?XGhF)yU60FJQpjhYJdlkV0>$5?m+ib<(RezkcSQK}A7TFioC&1Z+N;Kr^@5;q%r_f-|>}wTrfV@yQHXxLEsVcRr$6 zI7|lDfAT-Fdh`NW_bz(A32(LqFf%YP2r!<7L4-&l2VD2|82!b>zz=`^H~%cq>J%3j zGc(@RdRWC8xYCeep(BbG1gReCK@047ujb}734$JRJ<>CN)>{s=78&__-;cAt32l$h zq#JblluVhOgI_JD#8C*Rd;-_z02^*YSy##(Z(#)}@%d+O4;2XzFr^X=_!!%he!chU zsB6Q5DWp>!>VyL2MgS4v-M3qla;a7Ohn)Zl&Fi^~k-XaFHWv)6@}_{_n}7`^zo-Ar z?0@f$t-e#0ths0FpZnKla1WQS=Yt5X>z>#B&p>USoSaMvu0j(tCI9)~k+*zG7>qHV z<;i$$>wDAX*cT6eWTt45!tN-3<6Nph%gCjL1OachR)tbcS^cG_U$)E@+WF=7F zZ0fax!KjYWdu<*{f-Zc_aaCoPD^=+uXK7mt7#7ce2g7NH1%1H+(S?b}R%c8rZS=ht zD831wHIH5=GbGKR{OLw_h$whaNz-won^~S1Zy`v2$%&PqV_Bv9HGJj;*?zm@LXQ*T z*KVUQ;TI4nm`*j)md~y3uKl)`7Xpn6)v(nL=&oDRW}t$Ok1%zS*V^5c=j7FyP|3tL zZZ!Unrn7*FqYKyYV#VD{ad&s8K=I>8x0#C4BOv87EBhe_ir z{>XOF#+Y)H{5=B${|lo>s%6Vl9?>?H2JY5GHlIKO`3GDoDV%AUp=ONwwR~oV=vl>_ zfI6(lFq1~5hX z;U4YXMl7EES+}N>z&udkl>Q2;EG$@Wa;b31Y!Ux`-5ZU~kn(7-i4Bd#59x~|=` zOCb?V2`26R>HXabq85Vq@3~BJnvqlCY=+mJ-^aGmUwM7HZuxzAeV;GZ@8;kz)qFb6 zMl#3LLJ)1VTUYj1Q-Rf24NGku&-(h^U6~rgA+{UMUkaDgCHHRA?4tEy8iYP^iL&|S z^M{@b8s(G4(_?l#4p;L+mKBO_f}irhgMwvm?u@N=Q>f-X`Z2EQobUtmmDXRw%U^Q<2Gp)zV z0@;OLQl&uPEc=iqCr3D6d;te<@)fM>^0CosmV=kpQoi$$;-@F$NV)gfH4-lF@oC4V zfY%iK|2`*UyWK}sb-u1f^8;_v{(<+)@=`1*!R3(5aR z>;Fi-MYflSr=8{xW@V(%$b8es*AMtSNk1iHyY8vNXqGd@UYB<9+X!qADO)d>8v6Gg z9=s}Tqje`Mo=>EUdZ&G-ri^J9+t{vx26r|?ru1rfo}jYx|9_o#z)Q;eD2scU9--FU{ zDq*3k2wiTLR`OupnMo7UwviiF6=eaTMev2SFlJyBE0+&hhdLK&qBDX=@QG+VawaS& z)5`~H(4hdYFEuZypnC|uvCia}`6dC9Q6KoZB!EHsvjq*^&<*Uu*a%8-=ldWj9MI@& z5I?>-?`Uh&PN!cuc6xgM==-Y<8fr?HRZtfB6+t94ur3p|i?);B?$eZP|FdYezhCp> zuPJHZoyYHSi+{Y&85w7Q;E}K3$;qz-zCL@3$o8EV9|^>iI@Z?Z8IJNOs_;)#Oe;cL zE^F0>@lSYoa$R6xAC7`wt1ByalypS2+~g1@q;UTH!19<4^2o%*FB~9)7r&g5nTUyr ziEll9fawNUO24c)YW>G2oVmX}Gy#$EwY422jp<*Z4Jj9{$?@^l08_V42n++mt&RtO z5KLBBH*59qk-Sf=nV*XGG;7+dDF=Q9?ghF!Nw*c4siPjW&#e*S zCTBmw*2L#QF-$_fPuKSoG{$$A3X6>kd`ZW5e*&SBTk;iex6s<_n16FG9mmQRz(^(i zIgMB{_Quj`f^wC8Mw>7b8$yU_U@hd%5a;P_<)%bja_z$C@K{V|LelZZoJ$&=p`e2A zjuQ#?Q&)ut5<4MmD7FaZP3A(G9so0`I1Qn}?GE)ab6q(Y}m%a7`0@f1{ z0FV1d4ctp+NFP}ozzti|v*@=Q;R5U^`L$N&-h4hY^B(vK9y41B%y%6DFhI!nfV_OF zk<)v~0bsOmK#1^cM0<`9_>Q3l2P31}%ZH5z2MEK(mGg(k+U4y!^@}bIR!nyCpnb;Z zzEg7s3~`b%usMRi3D+DQrzdWw4s+o;LxPszJUlp%$4HEi$0v#!-G`$vpH8nKh<djn%ZOtk@_(6T^S;!T+v*1ID(8D&G7Oga)8h9;C-HwC{ zzBX!@e1QP)G`a&nEkKSET`Y~_({TKQcCY-IuxwAAYE4)7V_t(I)!yNUZW946T9=DE zDlzoz*Apov2XLBd*Ex-^sa7u>YW=Dzwmwq6z z#G{SQo((SiBW&BoLS3?d1s08xOyC!}d43y(1fm(5LXuuy)pb7!`xh}18>DZ!8 zpT=3GQ)MuJ;!LAj@+>iXAg*;j$m`@=tgEAjy5m&MMTYD~2XX{60na81Rs>gI8{BJS zt@#<^VomAmnPh0DTcU^#kXBhAY>OCM#%9?HoFM8SL76-xEF7~@~@TWNu)b%PRxh_szAYANC%ei@jJ*!R~h8C9dj3V?t zh)h`Ttyw~iiD+sJ|Jn%| z3Q{p4v11%M))3LjpCw&`=GeB_Gl8&Ve=-cDjaTK(D8?31g#ba+p~oL3Y|T!R*|4rZ zkKue&UvyCdyExGl;fPzmd@oEe`xkgEj!-H}zp88pKVw<~@@LBe^6wHilRf>92(FK0 zPK3ZZqM!K&1r1CzP}G5(@mDOy#RctZtZFYg<%)$WZRhsj?Y#vVXLh_^$9NY(Wm>&3_CbYlp_naONVNi zL|JT}1nDf|b0S-%@|pE{ZeD~{rr{KX?2d-Go~)gp>u^?GU7JiC21v?X1S)FG_*DHhId#A-21%0m$=Y27m} zpd7}Cp@s9UevA%EHo z7{wM?Zp!r4*~2>&3?|^uHgsAcz=a(=Uoc}+Y^E+@uTULiiU20K;UUaC0lRuKVQ1vK z7`=v4czmY6IYgDJ^rk-;ev6PxUlovHG1qVT<*5fZi1u48*$2aMQEg;Qfe1*A(~lc$jw5 z`}RGm_%ivDLy+aKR&sT`0FBx|@4h2aybmt+m{;eWLrSn>{euXhqNws>Y9Alz-b}Ln z@}Wh^zK|z0KCFce$%e1}zc8P}wv{Nw`sBKv&18UvU!k~Xr@*@ln|CFokR0w4j z$r_k@9I66GP_~<)So;k!sbIJ>M6(ByZ&d(9^E(MkL1Z7eKOxTWwPJ&-FbdED06dN= z73OB$dbrCs)3;_;-v~l}fPxQvv=rRKCiMd;V+RRj>8fS>?gBI`Y1)DR;6dW?=G%jW z?3Fs!V?(HSI=4d^gvu;;iReZ!(Wv63Q$o*|67#14xv$ z{bZEOWM*xBqFRc-A_Bi@GYk*dXZ)R#Nq@@*n|#c;-(ZU$ZnK_!{3$T43SJgVGJ+}s zNI16j0|`HC`UjTXHnL;Pq~&TP^?PRu`OMdjfM{>$>jPQU;_F1;HAL1Wx9>&B^0Ef- zUI?DNCXK_f9KI!|=zG^Gv;+HPyRV2ogWaR#1^YSLiwQ@NI2yU;E&s$(#ilW2vAgSb zyWP=);7eJyR*{P7UOYFUQ1`Z?u`zE3Jul*l}^Tu zv;JG=^Rz`MAvRMcPuouRt{npQsGcpfKO_<7NDuzeZPU$XV zL5A(zzUG(MfJg4igZwW1R76*D{f}OXlS-DshdP!|_g9Ayk_<$x$Tic~(s2BLFk(0! zzpzBqXTHqkgeX6Q{UZ{SB8jpKEREis_7_6DFF?@9)HaHxQ=IQdQkNhRdG-^&Q_9l~ zr8ZF?ICr_+c>ew#90@d04pwbD7=|Vr2h@S&_iT>pc~Uf+r{!32B5jh2l;ry7XjT|C ztZk&v`LJAOEB|%i@~>_84XXv&bUuTTyGK`Gj*01GG=?mg(0R+fjdth5=wvIQC|!N zXGC=Ma`~5CJzw3KQ$!$CeE;gznaP#q@?6#V(PqSk3jmI3NE9N*A71_#e96DwXpdN+ z*X+0+`7@W$hg7l3W_fq@_u7zrXb*Tz8}BdKTrO;ag0|NI(UIb_wv@w}%_) z_tV3>gA3&^J!UMjsayrW_Gx(92|`J}EQE@l?OrM;a%`8f^)I-^9w-|HwFn~Rn0@`& zphZ�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 z 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%0Ap@X}d<(*N`n6xbevC1Lb3zE`+*d#eAcQ#j=%WLH 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%0DuAzuqngpht}kY>B+~)`1f2q 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 diff --git a/Documentation/UsersGuide/images/SimulationWellsProperties.png b/Documentation/UsersGuide/images/SimulationWellsProperties.png deleted file mode 100644 index 9d47cc49632f520b34b978c4330842e78413b8f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16246 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 diff --git a/Documentation/UsersGuide/images/StatisticsCaseProperties.png b/Documentation/UsersGuide/images/StatisticsCaseProperties.png deleted file mode 100644 index e31f00dd801894a386ca5a749c5117f46c9883d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10498 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 Y{bW%V5@5IRJ0DR;(?Fw4?Q!`30obXessI20 diff --git a/Documentation/UsersGuide/images/StatisticsCasePropertiesCalculated.png b/Documentation/UsersGuide/images/StatisticsCasePropertiesCalculated.png deleted file mode 100644 index db72e512cf05ced80b4568100d94b52c6a5d901a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5760 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 diff --git a/Documentation/UsersGuide/images/TopLink.png b/Documentation/UsersGuide/images/TopLink.png deleted file mode 100644 index be404c4ffdd8f622085623923ca1a5420c0e6289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 554 zcmeAS@N?(olHy`uVBq!ia0y~yU@8N$1vuD%L?`uu!b%WvhGAA9DicwV~5x~E?7h18rIo|9BmA3S)#essF(v}xBloF(?z9jH+B z*P3d@)7US6HzDnt@ZP<#KEC%J`J`8`nKy6aWED@Z1AlgliixeZkvSbGaeC8+h^J?7 zPxbH>$T2XqJ90f?^3Ej9GXG|vH9<^3GZ{{#{yvfZo1x-=qG{0Q2X%d`o5dM_1pO7; zy*zp&(3zY!ZmnXR;J5wKkHrf&UiM1LRncCt>-%GT^CaGvL zF8Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RY3Kt158^8D#MgRZ+9cffpbVF}# zZDnqB0000007G(RVRU6=Aa`kWXdp*PO;BVmWd{HN1mHY>4K|1=~9knzj6QVWnjd-sWi zEH`ZR7_NVWh#_Y4wnS|-9R6aQB)A}9LJTbgi{bi5En-9>zPnr<1Qaj>CQK&hU9oIW zoiSWEor=#ni`S0P+1XE%v1JRHr5~}to)IO;J;F(^O!m?OE>S6K8d-mMq)J=?#V_sx zDNym_p43S_QY8-p_hAx4L{^K)`-#V@*&VkvJp>C|F{iJ^G%Fu67RN;lnR$E6GuLv- zYMjs9Q_z1TLQj1U$!BJgoxCuSWjV6&(bH)kL6&x$WI22kskcEJM2qlFQgY4l7Klo_ z)9IW}sYFE90K0)1z^;j*gd+@^uaTa&3YZ6+=StxBgh;zAEt{5io9jX?MI+ANfDQi^ z9mKvfn_n-q#f6nii+%e6q{`t?2!J>a_?(~|nEdV6R(Av9MjS4m{qVF%CBsPZ#{?nQ{%$u4bMO?37@SxKAaSmb7U^ONG3qtKmJ!Z(P>#djT@*-P@lcG9g zZL2wJZL^%aMUIt6cc#<)`EM-xd2T#U@#^ISxzed{p3l3MYy*#*I%T!hL6Q7T= zrX7wfe6$CgL!=@YR8IA+gN+OK%uR6x<-uU(VF5pAU~>K zCxkE%o=e}=azIH+@gS0ka)p`ae*{cO-#}bAuYWhEI%I7duCYtqYg(QJ_`b_3rt8cD z_}Ipa@um|uUf9ffFK#H}(47Z5LG>k76;&0ja>$UafAji1jc%yskekzN^4|+roRr@KkdzaZI zR)D$!I?UD{vyJ|Cj>U?;t_p{Jv9wg+Re_v`O$_-zzsC@>dE2PYr$)P-676=5Y*?90 z&hc8}@*!^$Ixp}Oeg>V002ovPDHLk FV1j46g6seQ diff --git a/Documentation/UsersGuide/images/WellCollection.png b/Documentation/UsersGuide/images/WellCollection.png deleted file mode 100644 index 38dcffa4e3c8191a07fa3f943c3214b15dca6a87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 554 zcmV+_0@eMAP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyV* z3jiI{21dvL00F8=L_t(I%XN{zOB-Pv#y{^%BqcdhyrIcW4xw|0{0Bl}79&oDWN^_j zxR*BAn4wb_N4q!}2ndC^$OVMbxqpCzOA+rJJRu&^5V-5$`yOvz%rm{b@B4h8A762> zT}(Y!vfnHSmY_5KlLDNzYT~$30!Z&~W|XUWBtQ@)^oQ}*5^|m8Xh_eM0C=t(tIHMZ zlW()MdN-U-WDq4S?LuL`OikHea3p(e=R&)%V;J@uXRX@Aa?}8_4q8?WP4-oJlh^D6 zDWrBTsSiPv3=9{(ZM{E?x3s!BG#k)sJ6}9k5=05_W?zSz z+#kkACzsDDFkb)t$o%i@^zr-M8_g5V&aE!WU!DKFsue$N7#q|H#J%Jyfv;dEjWRe24)I&(R diff --git a/Documentation/UsersGuide/images/WellPathCollectionProperties.png b/Documentation/UsersGuide/images/WellPathCollectionProperties.png deleted file mode 100644 index a8626cbf75b754e5d77a8fe70232618fa9c964a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8684 zcmai)2UJtdw#Nffq=_^^5D@7_npCMG9RcZ8dhgOfLR6#+NbjA1^xm6@0i*?__Y!&! zEkJ<0@O}5)yY5~0tv72UO7zA5X&|&9i1Iviot7tca0V zEXISctE>Jo{~?aXN74tYhH9236?g^Q+E)+24Qu!98ls|}>>fpED|~5P^Ce@}gw?mz z9{0y`J@*3*5{fd}UN|>eH-`_b7au|P|?=;5;1mUFp{-Hpdu`Sq`>Gvx8Ha^e$=88&vvZ!YX5f2!o#Z){C> z-0##dFPSEkke|1Ot{MkDkfG&u+;VntQ6nu#Fzq)Gn?5I@;21j>ua`~?DMZxJ_P%UJ3C+`V)<_wBl=E)W$+>Ypdi9)m2W;PLT&2H{Eyfc;ISsH4^v*g*@ zkg!fL~vfQ&-n-e zm8d*Mzd3N+Imp(9c&M`|jqLz6oblm{Vq$1tz!y-tjQv3nvNwxfj8S1GmbG_i?9@u< zhb~m=cfc1ZXU>$i(j^M(ynQ#dGWH+t z!dx-oGM~>U>5oIqsnkPi6~mQ8Ay2#tWpo!X4Hy&o)%>fEsJGq`;-cme`+6~gFFUXS zWseby9}YQs(X-|O-4Z4sM;!n-#k;F$A9v^GMp*AE;0g;Moeel8yxIDEw%O|1F{9XE z+j*&aN^y!O^pVok_Z7_Q6hT86l9-qnAPKsP5*|@8n}E%Eowtpj?m1bePmSKbfUCQf zqHa2~tvl&&;HEccsE+GhVj`S-+^QpSlJ#HPTY`pbp|pWVueO(LLqntXDt>jY1-iqP zU2gAfk=1=y&lcTz6Q0Kwu}aQLfg(1FZ!%(!gFHe7UzDF*n@kTVC z?q)zDRY;Y?+3nKzcc&KK$!)wi$!;d0KG&xNHkJ-a?THQL5^o-zSp08GjI@Qib5=;` z)xEF#2v?)ql)%#iFmzt(0yYk%tT3SuG+T!ARAtX!V@)yJX=I}(TSVSgSfWe}vzuZ> zem)CvYVG=+xj8e68av<+JN|rLCu^lmR4R( z?3onW8iN$M4wTgqLR0s1APW=c*}vbYRXUf&=7&YX;X4>1kHi{Wk+()tmvfyU1Z8qE zR25ZM2|enCfxbaE8=V#+c1i2RJD&G@_S1$7ZcPb0UICi0aj^zeh3xzRe^IqdrqP5qI_uBf1KJb!$_2xC= zdgY)xK(f>CMc^rB`A)5X^SF_>+;8?&U%F3K?93iX9-k>>Q_;_57!~m1MU63&@@CA&uS)NBl zpo>p40=e(+|EHXn-n^XI8#zMLjwZEM_ z+OpAA+V=C3l<-Glsq3oZ>!6^Zt-1#cq~XTR?&}*v=|cxi)&ohjV%|*)E?ZzTqW2f%no2w;nDpFTa3_ zlM&+Zp|H$Uo4j@>(JfIl!iLj`o+ujh|24WS>@WcxX7|hU6-;pbKi5x33AX9CAX8fQ zPRVr@Y9|Cyw?*YvYv!C@+=shh$D(_&i`c{lf*G;YO2yBSQEU-sEQbC*fw13=$^>45 zzM9`)m9)t+67IO9}Jb>I80%5_HfTxH68pV1JCQWNT&dnbYOl zn(#=I&%%!QvG!2}2|Wx}T6Ry6gVO*%1o%$GiYt|xeNri^z*9pbEW31c^Lu#S`%j8} zarWao%jmPP7&#F}m8iLWl2Hfo<9@5nyy86Uw~1b68r>7yHNmFcS@N{PpCT2M-pe_P zgCiq$6kV1&faN;q&jlwhRaD2%*-TG<1sNe_d7h{=wj@S|bZ;>kSs5YK*!yG}$1NUK zC1lb=finxe7A2>BC${dG6YOup6xewUv{SyR8m*~L9@Je}UNgkI_>caqMpxwCa?>eh`R%h8JyqPC08m$tBnF?7g3BNUQ5DEJBv}{(T z)P-t?{RXyiaY~T#5mH4}&6|WT!pTa82_BQ8a$eTgT&j$&mE>%l&zyIG+)Ir!JN`dA zE9dO4E`8y94n+8V^kg1&wt*u(c`ZYJ@abyH%8sj&r*#)&4+m-#V(28i_fkwk98i+t zOH<5DHyb+FR7_T5`_$u&rECmNmMN?IT?b|-8$*$ikzzgvPAk2MnPNWN+}tjUZGJ<& zjb`oU?RcZD{g^WQjw;_7qwVieQB%M4Imj4T=ckSuI%ut{^E{Yu&dp`msvYY>X1t5& zg^7CYjE9r4rU3`vMYP|$cMq4C?hD!+IMXPmIl8XNJ`Q7}77S;et(`^pM68C&k?pr*7J{hniak2*@#b5@Q%~79hVu=LREXqz9 z-QKH$!;Bnh9-+v83Z+ABIZdmz=x~yYv^+|~F-JaZNrI52kX;IPG28<>K@DDR-}VIN z_yvcx&+of-hak@~7`2VB$2hk8$r^T_cf`F(*Ual9g-iCVdlbBx-Ogjw)yN^WDV@WS zCeAUL$xV_3GwXAZCMPA$)?O6VI6XF?b-}mcNv#{ReWQaNcPg=1jv=80S>>F)Dyx@_ ztGg%)5(!NX+f$1mXeLbEtNDRRu{(mTH?tUlsRLqn<9>D66(wHPe-=C2c=1oCuCz23 z@Ck7GNELM}>X668es5HRj5$7|y6(bu7Bb$M%lI4u;r$v}IKEQN-@by0v86Eyyisqb zpl@|zRs_rvPol7L()AH%1NyGdM&G;yq=5cA{oIWsx|TggqmLTPKYis^1fAJH(sMEI zJ-60{5nG;zSs87+TG=lHE{+9L^d8oOcAe!$jl3QEBxr}9`&L@&^bejh2S{wS zD67kpv1jagx>h43qvPG=bm{h|9;R8gW-Z;_;(5b0*9NN`xmw%K%KFmSZHKAYNvr&3 zJ;r{nK$l_@B^o))W!W3foVR_MH8XW}1&NCnrXOukx*sQYYdeEW$I-y}3yahFa`p4g zFjbme$184T{1wCPQs1+-w`^-Ce$=A8H!kLt$v;tBGl|g6-S4URj9J_Ec{>@5xEy2P z>-qsFA=c?1@O>pIY?eswS7pN5Hs1|aP-+RH_M8NDCDWx8%Hz56+_LxQ0>tYb)G9Ud zAD&;tD|M!tJ4rPu%f2_Y&Mz**VB+D;uPZNO0DsdDETD#K>A3pJ>%2TH6~&K59c>WE z1_$K6?F&X65QP#GD?Ql&|DamrbVe01qLhOJxZ8YOMUn{)bvk&+FS=ic`mw*`0li{( za1|-)=NG6G&d?GBY`rLev_!j($x&`A`)1ETRncTwh-shfdB!|esKg$8omD0M%bzUo z7kQC+Rxua+*{}SJbPI8kb$%;qoxyE64RWpF??oY^ImY=S>(NaCZSqlNKKy3YSekh$ z7grCNZytxnNqy%?I#X+6j9)$_RO zW-NkgcNM>3Zhn|~y-ufm9=@e)tMCdMom7ngQMM{sbk7wu9>Z}TlvEc3Ux z$@ggRQ!)FaEci$4k*+*IvUQS+3K?a}LxBpiLtlT*6*KMPFlhssGZAO*SDB_4(TpWF&#ACPapr z_@JLraAI2u>=_|9AN|dwVy@9OGEY&~b6=Q~(^Hik;@D}xM}JuhMK=lvIGJ1y)q{|T z$PLCyC3ejQM<(mrYceFF^Q<#EFc3OuL>VLQquq9X$jPbA*!jJ}PO=8-FV0-wEq?8~ zBQBlY+}vDUUA?*)@t_rX&^jd)=>FTz_^But7&9q}rBX9zblzuNHuVX;O1iv3>kC?# z$7418cS+L9T%oBYxjMN?&b#nfp#OC&X7V|=E~;=xrs zTn`OiTX2{u+4AVz;FY{QKVI=EHrdUUo?TbwgtzwG2yoz z01@G2(^E-Eti=Uc{}G2jJxKUkb}fsvoXLuPJK4h!v-nG5-^;)Gb~4(gEH-W}BO&Q) zj^cQN1t-29QHdZ{&bZ-^WqaD9`&RJ-rd(l@DivCkc|u2Mo^qY?gK zMv9s=AnO$8bI$JB%p|s%T@m-q6Td46>UymG6H3JjB!aw>iY8@8Xb@mO<5;6dxmKDk z?-7I2w?-?0`x@(Xxe2xx;qA3c!+w9dF9S@3QAgR>*Ps@}N~lue>f`tty9B(+C@(~e z=`OucYu}eF1m7zy<<9!vXj%cOL%e=xB9y z6%Ee0P!lsdyDjuB?&JYGfjnXVk6y!C`V01JgZ+3`eYnEzygXA$X zW?ssZrzOwU7q#=JJ|@kLruU*D|C7k!5g9%ZbEFv!9`n^#dry)P-UbjKndgA3@%+Kb zdaL<CK5U|?fAUHYYX?ZK~fa5qWl*`%L_U4MG2WGkA8KHFy3XSnoQq%gosxz zB&K3|@Mfy-WICLSdq>P5`+?6(&WC7UIR6VvZ~p1;wF;7CA3@zvBmM%Hne~N750GnC zL>^ZbaaNyx+IxeR=O8dS&~tl zR}ZHC58`fZOXh}|{j#8To>|XSyyUQ&U@Ne)H|@RFg;I3zzq>zYETF@`GEv>_+Csn6 ze^Nfi6X=x@*0*&rdk|SW@#@dTpSj@X5f|gpcDa+=G;h|-!Psw6aic2vED`I9eT56r z4>e%iht@6$CZb0TYsV&6B`ps>MI@b{MVHJ|nDD&2k6YX(ttu7}6`0dNR1!rDJjiU^ z2s11Gcv0-Zt`O01@E2|yJ_83>7|gA=r<5}d>%LnYDEQ;f;9qehxUlLtKAkov0Vthd zH9+fSyeUcKzp2@G@cJL@K5s%l+g8%M#WMo)sD1}>9q+S}R^vZyb%PWpZ0uEBnR{v+ zQqn^ahdH+=``Jm1i;CZ&n!v?CuV5+X0lC~V!{Vw+UuP-B5D@#hFxu_Ld?Y< ztF0f?y=O;+8gl%iPK%3IhQtXpCZ@9&sZ<;hcJrb$hq?d@ofZf65cqmsT6>bUw=3O}wbrCg&;LA%R@I{J9H@lkELd zshACZz9gop%Z$4vTXUj!K+~jh!gvxpETLRucAylVkp)>M9?CL<~x97S9|{Gw8;LXESh5nzTU z+<(bZXe!IWJ+r4?%*yKgT7hAfsRT7ebF^NO-SusATbmR5M)RrTDJ5Vx+};;?eC$pO zR3=@Qr;`R@RAp&*j?XOl>H>cBK&AfCrT-xIs-&x55orL=Z;~pzyT!Up_Qv3m7XYHM z4Ai%W4N3&(2G+$_zV^ZVlj({Ay0S1)4C!kp@%^u$k>DVmND?w0q!r?KMe5|_^mo_(#M}F1eT3uUIl&~*i=jv&|J&79sGh; z4bd4JA$<+CdfLr=LP`}Wo_Ttat_omFX`Hii{7+Gxtft)RpJ%ah2Af*M*6k8CFXzbz zP5A8#`a}nk=P7FZ9k*9isog@~R*S?nNP122SVkH1Q&F~=coU^14KR5J2;R+=}kxA8bHfj=DuV-r3JuZg=em zit)$(^=P&(sNXHs^29PUR!QbV#*4fF)cFBT7@ST<3JkwYut)tsrlht8v!!l&Xtu!7Q?`yg#RB?!On$mr7u5Cp(F}Lu zqp;7xbl`in44~^uu`9NLWo5TjkK&`ma(3TC_~X zW9Kc*&`<}i-(R`&u*~RjW=`|?4^>iD3DlEY$4d3+OI0sa_4myB!w09+fvAS{m~Dka zldHj-AStz*fR&xI6 z?=N*CBL@aH3qi9}wihtC6dHAm8eHTyJ@X`+Cz|%E<+(}GbT@3CIG#q~{#X;sG($fk zPrn=ZJ*AvY&10OM8I6QEArJ-)ayf;vb6OT@S=q?Qyu%p@oS+q+Ak@(S>fs@M%O;nf6Eoig(;}?fc#1H?<0R= z#tJeOVkYg_5%f3toou)+wXdthNLf7%>N2~C*hdg*Z=q%6d17D%t}23mSGAze#)iso zPJ&reNMH2!lygaEag1^VV%di;8)@yl#B2CgdlF+Uks^6C9qt6LeYN_d&IMoJ z2iVXRq&@(vG$59wU=}u6is8VSSg*G$>gzsqle=`tUx;|k9%y~e%BfjUMvXgtw4zO3 z@$2_7wKh07xW8gd{D~J2yj-8kMqS*7R~*<;Le3wod06$zxOhR$j{4^1lB76oV-8Dv~Rw7+ll(UQ;c)05E|t9rJo=OTF1am$cKYGHIR5;@$=x;Bm8%|9&HWS&}Ts_NfMti1|&!QaXK7_Vr zgSv#q5Y10@k;S0hSMU@YV}Zn@8uUU`yw)9qbWy%%7uNPXbX7}oNH`?kp2$nhqpU1U zz@c!()M5M~*oEF`pmetv009FNiLXb=$$Ep zW7JM$(NY@Av;LmjgG{J|)wm*tbI!soFse$D4m43;r^|C_X%W5A^HIXw!goJkJ%qkZ z9f^7g-}f^S1n Z#9?B%EpK4@zwUNkD9NeGR>+ur{vRdVCq)1N diff --git a/Documentation/UsersGuide/images/WellProperties.png b/Documentation/UsersGuide/images/WellProperties.png deleted file mode 100644 index 2af593ad16dea06feef9cdc4c25f6b1c5cc127f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6967 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 NnrdLx@+UT-{{=YYqs9OL diff --git a/Documentation/UsersGuide/images/WellsInTree.png b/Documentation/UsersGuide/images/WellsInTree.png deleted file mode 100644 index 68bf5cdfedec2c435f35e28b49a4844fee7ba29e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8076 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 From 57ade584b2c4f0b239bff29c919a85a6082cf287 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 Sep 2014 14:34:03 +0200 Subject: [PATCH 341/346] Updated about dialog --- ApplicationCode/UserInterface/RiuMainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 6f530d33e7..066bf96f15 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -761,7 +761,7 @@ void RiuMainWindow::slotAbout() dlg.setApplicationName(RI_APPLICATION_NAME); dlg.setApplicationVersion(RiaApplication::getVersionStringApp(true)); - dlg.setCopyright("Copyright 2011-2013 Statoil ASA, Ceetron AS"); + dlg.setCopyright("Copyright Statoil ASA, Ceetron Solutions AS, Ceetron AS"); dlg.showQtVersion(false); #ifdef _DEBUG dlg.setIsDebugBuild(true); From b4df5419b10f34a251fb1a1f3ac884b6c8a35b82 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Tue, 23 Sep 2014 15:04:57 +0200 Subject: [PATCH 342/346] Updated file header for modified files --- ApplicationCode/Application/RiaApplication.cpp | 4 +++- ApplicationCode/Application/RiaApplication.h | 4 +++- ApplicationCode/Application/RiaPreferences.cpp | 4 +++- ApplicationCode/Application/RiaPreferences.h | 4 +++- .../FileInterface/FileInterface_UnitTests/Ert-Test.cpp | 4 +++- .../FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp | 6 +++--- ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp | 4 +++- ApplicationCode/FileInterface/RifEclipseInputFileTools.h | 4 +++- ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp | 4 +++- ApplicationCode/FileInterface/RifEclipseOutputFileTools.h | 4 +++- ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h | 4 +++- .../FileInterface/RifEclipseRestartFilesetAccess.cpp | 4 +++- .../FileInterface/RifEclipseRestartFilesetAccess.h | 4 +++- .../FileInterface/RifEclipseUnifiedRestartFileAccess.cpp | 4 +++- .../FileInterface/RifEclipseUnifiedRestartFileAccess.h | 4 +++- ApplicationCode/FileInterface/RifReaderEclipseInput.cpp | 4 +++- ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp | 4 +++- ApplicationCode/FileInterface/RifReaderEclipseOutput.h | 4 +++- ApplicationCode/FileInterface/RifReaderInterface.h | 4 +++- ApplicationCode/FileInterface/RifReaderMockModel.cpp | 4 +++- ApplicationCode/FileInterface/RifReaderMockModel.h | 4 +++- ApplicationCode/ModelVisualization/RivGridPartMgr.cpp | 4 +++- ApplicationCode/ModelVisualization/RivGridPartMgr.h | 4 +++- ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp | 4 +++- ApplicationCode/ModelVisualization/RivReservoirPartMgr.h | 4 +++- .../ModelVisualization/RivReservoirPipesPartMgr.cpp | 4 +++- .../ModelVisualization/RivReservoirViewPartMgr.cpp | 4 +++- .../ModelVisualization/RivReservoirViewPartMgr.h | 4 +++- ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp | 4 +++- .../ModelVisualization/RivWellPathCollectionPartMgr.cpp | 4 +++- .../ModelVisualization/RivWellPathCollectionPartMgr.h | 4 +++- ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp | 4 +++- ApplicationCode/ModelVisualization/RivWellPathPartMgr.h | 4 +++- ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp | 4 +++- ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimAnalysisModels.h | 4 +++- ApplicationCode/ProjectDataModel/RimCase.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCase.h | 4 +++- ApplicationCode/ProjectDataModel/RimCaseCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h | 4 +++- ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h | 4 +++- .../ProjectDataModel/RimCellPropertyFilterCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCellRangeFilter.h | 4 +++- .../ProjectDataModel/RimCellRangeFilterCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCommandObject.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimCommandObject.h | 4 +++- ApplicationCode/ProjectDataModel/RimDefines.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimDefines.h | 4 +++- .../ProjectDataModel/RimIdenticalGridCaseGroup.cpp | 5 +++-- .../ProjectDataModel/RimIdenticalGridCaseGroup.h | 4 +++- ApplicationCode/ProjectDataModel/RimInputCase.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimInputProperty.cpp | 4 +++- .../ProjectDataModel/RimInputPropertyCollection.cpp | 4 +++- .../ProjectDataModel/RimInputPropertyCollection.h | 4 +++- ApplicationCode/ProjectDataModel/RimLegendConfig.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimLegendConfig.h | 4 +++- ApplicationCode/ProjectDataModel/RimOilField.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimOilField.h | 4 +++- ApplicationCode/ProjectDataModel/RimProject.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimProject.h | 4 +++- ApplicationCode/ProjectDataModel/RimReservoirView.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimReservoirView.h | 4 +++- ApplicationCode/ProjectDataModel/RimResultCase.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimResultCase.h | 4 +++- ApplicationCode/ProjectDataModel/RimResultDefinition.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimResultDefinition.h | 4 +++- ApplicationCode/ProjectDataModel/RimResultSlot.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimResultSlot.h | 4 +++- ApplicationCode/ProjectDataModel/RimScriptCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimScriptCollection.h | 4 +++- ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimStatisticsCase.h | 4 +++- .../ProjectDataModel/RimStatisticsCaseCollection.cpp | 4 +++- .../ProjectDataModel/RimStatisticsCaseCollection.h | 4 +++- .../ProjectDataModel/RimStatisticsCaseEvaluator.cpp | 4 +++- .../ProjectDataModel/RimStatisticsCaseEvaluator.h | 4 +++- ApplicationCode/ProjectDataModel/RimTools.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimTools.h | 4 +++- ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h | 4 +++- ApplicationCode/ProjectDataModel/RimUiTreeView.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimWell.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimWell.h | 4 +++- ApplicationCode/ProjectDataModel/RimWellCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimWellCollection.h | 4 +++- ApplicationCode/ProjectDataModel/RimWellPath.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimWellPath.h | 4 +++- ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp | 4 +++- ApplicationCode/ProjectDataModel/RimWellPathCollection.h | 4 +++- .../ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h | 4 +++- .../ReservoirDataModel/RigCaseCellResultsData.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h | 4 +++- ApplicationCode/ReservoirDataModel/RigCaseData.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigCaseData.h | 4 +++- ApplicationCode/ReservoirDataModel/RigCell.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigCell.h | 4 +++- ApplicationCode/ReservoirDataModel/RigGridBase.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigGridBase.h | 4 +++- ApplicationCode/ReservoirDataModel/RigMainGrid.cpp | 4 +++- ApplicationCode/ReservoirDataModel/RigMainGrid.h | 4 +++- .../ReservoirDataModel/RigReservoirBuilderMock.cpp | 4 +++- .../ReservoirDataModel/RigReservoirBuilderMock.h | 4 +++- ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaGeometryCommands.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaSocketServer.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaSocketServer.h | 4 +++- ApplicationCode/SocketInterface/RiaSocketTools.cpp | 5 ++++- ApplicationCode/SocketInterface/RiaSocketTools.h | 5 ++++- ApplicationCode/SocketInterface/RiaWellDataCommands.cpp | 5 ++++- ApplicationCode/UserInterface/RiuMainWindow.cpp | 4 +++- ApplicationCode/UserInterface/RiuMainWindow.h | 4 +++- ApplicationCode/UserInterface/RiuViewer.cpp | 4 +++- ApplicationCode/UserInterface/RiuViewer.h | 4 +++- ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp | 4 +++- 122 files changed, 374 insertions(+), 125 deletions(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index 9c9e323a52..e6f05ebbf3 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Application/RiaApplication.h b/ApplicationCode/Application/RiaApplication.h index d724644b94..1d04f1ace7 100644 --- a/ApplicationCode/Application/RiaApplication.h +++ b/ApplicationCode/Application/RiaApplication.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Application/RiaPreferences.cpp b/ApplicationCode/Application/RiaPreferences.cpp index f26603352f..4271085fe0 100644 --- a/ApplicationCode/Application/RiaPreferences.cpp +++ b/ApplicationCode/Application/RiaPreferences.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Application/RiaPreferences.h b/ApplicationCode/Application/RiaPreferences.h index 4f3eed0b87..7d3f89b9ff 100644 --- a/ApplicationCode/Application/RiaPreferences.h +++ b/ApplicationCode/Application/RiaPreferences.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/Ert-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/Ert-Test.cpp index daf5299eae..bdb0ce65ce 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/Ert-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/Ert-Test.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp index 98bd5fbba8..5c7b451bbb 100644 --- a/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp +++ b/ApplicationCode/FileInterface/FileInterface_UnitTests/RifReaderEclipseOutput-Test.cpp @@ -1,8 +1,8 @@ - - ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp index 9f2f373cc9..cb9264ea6a 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h index 0ca8faea4c..461c5aeee9 100644 --- a/ApplicationCode/FileInterface/RifEclipseInputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseInputFileTools.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp index 347c2bb762..0bf35563c4 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h index a91bc1e401..8b6abcde5a 100644 --- a/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h +++ b/ApplicationCode/FileInterface/RifEclipseOutputFileTools.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h index 26bac268b1..81bfc31819 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartDataAccess.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp index 4898330928..ff838c57ff 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h index 70c4679bf0..3bcbee647d 100644 --- a/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseRestartFilesetAccess.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp index a3c6c165d4..43159f8f56 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h index 4c6265be81..fd2e85bee8 100644 --- a/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h +++ b/ApplicationCode/FileInterface/RifEclipseUnifiedRestartFileAccess.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderEclipseInput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseInput.cpp index 8e74e59068..2f6ff3f235 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseInput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseInput.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp index c163b71085..40b0ea6e12 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h index 4f2668f162..5ee457471f 100644 --- a/ApplicationCode/FileInterface/RifReaderEclipseOutput.h +++ b/ApplicationCode/FileInterface/RifReaderEclipseOutput.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderInterface.h b/ApplicationCode/FileInterface/RifReaderInterface.h index 6f66a4aeda..8ec215f5de 100644 --- a/ApplicationCode/FileInterface/RifReaderInterface.h +++ b/ApplicationCode/FileInterface/RifReaderInterface.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderMockModel.cpp b/ApplicationCode/FileInterface/RifReaderMockModel.cpp index 64507ebc8d..0db76f7f25 100644 --- a/ApplicationCode/FileInterface/RifReaderMockModel.cpp +++ b/ApplicationCode/FileInterface/RifReaderMockModel.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderMockModel.h b/ApplicationCode/FileInterface/RifReaderMockModel.h index 3acd5a7c7b..dbe4a083ee 100644 --- a/ApplicationCode/FileInterface/RifReaderMockModel.h +++ b/ApplicationCode/FileInterface/RifReaderMockModel.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp index 5d85e3c457..1c2a3d0c47 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivGridPartMgr.h b/ApplicationCode/ModelVisualization/RivGridPartMgr.h index ddd3b87a62..a1b29cdb37 100644 --- a/ApplicationCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivGridPartMgr.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp index 90d573c7f7..c11bdfaac3 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h index 817fcb46fc..1e9e2b894b 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirPartMgr.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp index 64e58e3b3e..0ac416a076 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirPipesPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp index 5c7e50575b..f094460efd 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h index a499b6b683..f5fce9e94e 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp index cbd0d78d8d..7b64b4f8be 100644 --- a/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellHeadPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp index 4e34fcbf45..f2f7714f77 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h index 88b6dd86ca..5f0171bc8c 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathCollectionPartMgr.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp index f8b5542ab3..6bc354e569 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h index 873c15296e..0f01a673cd 100644 --- a/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellPathPartMgr.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp index 8c2eae1287..546a57fd57 100644 --- a/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellPipesPartMgr.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 501fc2d9e2..9165ad92dc 100644 --- a/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp index 5d2bd3c368..5a3f8f9408 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h index 6a205d4778..44673a9b8c 100644 --- a/ApplicationCode/ProjectDataModel/RimAnalysisModels.h +++ b/ApplicationCode/ProjectDataModel/RimAnalysisModels.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCase.cpp b/ApplicationCode/ProjectDataModel/RimCase.cpp index 9aa0325ed5..9343c17afe 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimCase.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCase.h b/ApplicationCode/ProjectDataModel/RimCase.h index 3de3d04c49..ccaee649f8 100644 --- a/ApplicationCode/ProjectDataModel/RimCase.h +++ b/ApplicationCode/ProjectDataModel/RimCase.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp index 630684c92c..2ab8bb64ad 100644 --- a/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCaseCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp index f3cf44dabc..19926c6dee 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h index 51ebce253a..8be396dad6 100644 --- a/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimCellEdgeResultSlot.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp index 4ced6073c9..e09bc9df37 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h index 71a942b3ee..7e92b29787 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilter.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp index c1024f6c3a..c4bac8aaac 100644 --- a/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellPropertyFilterCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp index 4bc3f601d2..15fff47817 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h index fe4bbbc10e..78ee97f190 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilter.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp index 6c1a7bde75..ff430c838e 100644 --- a/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimCellRangeFilterCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp index 554d8d926b..56b934001d 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.cpp +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimCommandObject.h b/ApplicationCode/ProjectDataModel/RimCommandObject.h index 81417ac7d5..33c596565d 100644 --- a/ApplicationCode/ProjectDataModel/RimCommandObject.h +++ b/ApplicationCode/ProjectDataModel/RimCommandObject.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimDefines.cpp b/ApplicationCode/ProjectDataModel/RimDefines.cpp index 6ec7f8db80..ccc6eb4dab 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.cpp +++ b/ApplicationCode/ProjectDataModel/RimDefines.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimDefines.h b/ApplicationCode/ProjectDataModel/RimDefines.h index 2403e13230..21c0addb60 100644 --- a/ApplicationCode/ProjectDataModel/RimDefines.h +++ b/ApplicationCode/ProjectDataModel/RimDefines.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp index 1dec69908d..68aae7017e 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.cpp @@ -1,7 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h index 31c66c8211..6a033e1ede 100644 --- a/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h +++ b/ApplicationCode/ProjectDataModel/RimIdenticalGridCaseGroup.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimInputCase.cpp b/ApplicationCode/ProjectDataModel/RimInputCase.cpp index f003e5db0f..3c4b6847f2 100644 --- a/ApplicationCode/ProjectDataModel/RimInputCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputCase.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp index 3aed9d899f..acbd17a801 100644 --- a/ApplicationCode/ProjectDataModel/RimInputProperty.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputProperty.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp index 8250191135..0758a0576c 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h index 302e97a50b..81828209cb 100644 --- a/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h +++ b/ApplicationCode/ProjectDataModel/RimInputPropertyCollection.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimLegendConfig.cpp index 3cfd96ca48..72c1312e3f 100644 --- a/ApplicationCode/ProjectDataModel/RimLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimLegendConfig.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimLegendConfig.h b/ApplicationCode/ProjectDataModel/RimLegendConfig.h index a8a697601d..6d8704d29a 100644 --- a/ApplicationCode/ProjectDataModel/RimLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimLegendConfig.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimOilField.cpp b/ApplicationCode/ProjectDataModel/RimOilField.cpp index 13855a3962..f56e5bc456 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.cpp +++ b/ApplicationCode/ProjectDataModel/RimOilField.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimOilField.h b/ApplicationCode/ProjectDataModel/RimOilField.h index 925c20b378..0a26e32d40 100644 --- a/ApplicationCode/ProjectDataModel/RimOilField.h +++ b/ApplicationCode/ProjectDataModel/RimOilField.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimProject.cpp b/ApplicationCode/ProjectDataModel/RimProject.cpp index 03bd43fcfe..3fea5fd02a 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationCode/ProjectDataModel/RimProject.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimProject.h b/ApplicationCode/ProjectDataModel/RimProject.h index 3226a0ee1e..214706e7a7 100644 --- a/ApplicationCode/ProjectDataModel/RimProject.h +++ b/ApplicationCode/ProjectDataModel/RimProject.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp index 02733bb359..b592adfb51 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimReservoirView.h b/ApplicationCode/ProjectDataModel/RimReservoirView.h index 9972e1da8a..5a85363b71 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirView.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirView.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.cpp b/ApplicationCode/ProjectDataModel/RimResultCase.cpp index da71221787..c83df1600a 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultCase.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultCase.h b/ApplicationCode/ProjectDataModel/RimResultCase.h index 9d768fc36b..b373bb3ddb 100644 --- a/ApplicationCode/ProjectDataModel/RimResultCase.h +++ b/ApplicationCode/ProjectDataModel/RimResultCase.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp index 4919432ad0..245489343e 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultDefinition.h b/ApplicationCode/ProjectDataModel/RimResultDefinition.h index 4856671a0b..e3a6d3754a 100644 --- a/ApplicationCode/ProjectDataModel/RimResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimResultDefinition.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp index 7ceb23ad01..01ea519c71 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimResultSlot.h b/ApplicationCode/ProjectDataModel/RimResultSlot.h index f39250f7ad..c08ebc69d4 100644 --- a/ApplicationCode/ProjectDataModel/RimResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimResultSlot.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp index 17e3053bd6..eb26bf7a83 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimScriptCollection.h b/ApplicationCode/ProjectDataModel/RimScriptCollection.h index 88c4bcffa3..2562a3c83c 100644 --- a/ApplicationCode/ProjectDataModel/RimScriptCollection.h +++ b/ApplicationCode/ProjectDataModel/RimScriptCollection.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp index 51e8d45859..b2a0c39f85 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCase.h b/ApplicationCode/ProjectDataModel/RimStatisticsCase.h index f3124cf511..a225d50674 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCase.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCase.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp index a5fb4e94a6..c4563c6fdd 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h index 699c28a5c6..71f5bf5228 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseCollection.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp index 66b6f25a30..883d5c6d4e 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h index 62f4ca36cc..7dfad6eb7b 100644 --- a/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h +++ b/ApplicationCode/ProjectDataModel/RimStatisticsCaseEvaluator.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimTools.cpp b/ApplicationCode/ProjectDataModel/RimTools.cpp index 453bc259ba..f1fadca848 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.cpp +++ b/ApplicationCode/ProjectDataModel/RimTools.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimTools.h b/ApplicationCode/ProjectDataModel/RimTools.h index e39f961043..8dbcb7e535 100644 --- a/ApplicationCode/ProjectDataModel/RimTools.h +++ b/ApplicationCode/ProjectDataModel/RimTools.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp index b50569e979..81a9750ead 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h index 79d81d2009..a5a1a07730 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h +++ b/ApplicationCode/ProjectDataModel/RimUiTreeModelPdm.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp index 0b7331ce8a..a8a4e1dd3f 100644 --- a/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp +++ b/ApplicationCode/ProjectDataModel/RimUiTreeView.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWell.cpp b/ApplicationCode/ProjectDataModel/RimWell.cpp index 9a3a221ecc..cd85659e14 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.cpp +++ b/ApplicationCode/ProjectDataModel/RimWell.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWell.h b/ApplicationCode/ProjectDataModel/RimWell.h index 1e591f85c7..fae8c997c7 100644 --- a/ApplicationCode/ProjectDataModel/RimWell.h +++ b/ApplicationCode/ProjectDataModel/RimWell.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp index a4efac4ea8..2888f6d3ea 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellCollection.h b/ApplicationCode/ProjectDataModel/RimWellCollection.h index 8ca7232006..0bf9e7ad6e 100644 --- a/ApplicationCode/ProjectDataModel/RimWellCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellCollection.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.cpp b/ApplicationCode/ProjectDataModel/RimWellPath.cpp index 29ed5040b9..598da51516 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPath.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellPath.h b/ApplicationCode/ProjectDataModel/RimWellPath.h index 068f84d4f8..928cd2fb17 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPath.h +++ b/ApplicationCode/ProjectDataModel/RimWellPath.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp index edc4c74fcf..45fd93376c 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h index 7d30e10fca..4b60c7e535 100644 --- a/ApplicationCode/ProjectDataModel/RimWellPathCollection.h +++ b/ApplicationCode/ProjectDataModel/RimWellPathCollection.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp index 5252bbac88..526bb1f997 100644 --- a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp +++ b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/RigActiveCellInfo-Test.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp index 2c631b2d16..1a27ad8c62 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h index 8002f5bbb7..93c23ba12a 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellInfo.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp index 9ff66181b9..cbe1826d8b 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h index 30cf5c3ac6..dc5ddf4182 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseCellResultsData.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp index 7b42593b43..3b40771fc9 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCaseData.h b/ApplicationCode/ReservoirDataModel/RigCaseData.h index decf4ca66b..8b49fb29ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigCaseData.h +++ b/ApplicationCode/ReservoirDataModel/RigCaseData.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCell.cpp b/ApplicationCode/ReservoirDataModel/RigCell.cpp index 730328b7db..a4af1b32a8 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCell.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCell.h b/ApplicationCode/ReservoirDataModel/RigCell.h index 7108a12452..1cda50a286 100644 --- a/ApplicationCode/ReservoirDataModel/RigCell.h +++ b/ApplicationCode/ReservoirDataModel/RigCell.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp index c727ecfcca..08b9ce84d6 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigGridBase.h b/ApplicationCode/ReservoirDataModel/RigGridBase.h index 733de4ec99..7ea661d93f 100644 --- a/ApplicationCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationCode/ReservoirDataModel/RigGridBase.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp index eca3f8e973..0e5412221f 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigMainGrid.h b/ApplicationCode/ReservoirDataModel/RigMainGrid.h index 8b0210d2ea..f208d3f5cb 100644 --- a/ApplicationCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationCode/ReservoirDataModel/RigMainGrid.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp index 697edfc501..c245f4eeff 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h index 9200788ed5..37b1c786ab 100644 --- a/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h +++ b/ApplicationCode/ReservoirDataModel/RigReservoirBuilderMock.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp index 5d25d52fb9..2c495d83a5 100644 --- a/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaCaseInfoCommands.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp index d7784f1997..018cc97d19 100644 --- a/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaGeometryCommands.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp index 35c221d4fd..96c2b69c9a 100644 --- a/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaProjectInfoCommands.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp index a7ff9299ff..048da8f0ca 100644 --- a/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaPropertyDataCommands.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.cpp b/ApplicationCode/SocketInterface/RiaSocketServer.cpp index 9820cb4883..28b9bb3826 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketServer.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaSocketServer.h b/ApplicationCode/SocketInterface/RiaSocketServer.h index 1b25984f28..1dd24af67b 100644 --- a/ApplicationCode/SocketInterface/RiaSocketServer.h +++ b/ApplicationCode/SocketInterface/RiaSocketServer.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.cpp b/ApplicationCode/SocketInterface/RiaSocketTools.cpp index c275994254..71e6d5cd47 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketTools.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaSocketTools.h b/ApplicationCode/SocketInterface/RiaSocketTools.h index b331799e2e..b324a25292 100644 --- a/ApplicationCode/SocketInterface/RiaSocketTools.h +++ b/ApplicationCode/SocketInterface/RiaSocketTools.h @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp index 83fc17b77e..b8b3857ee7 100644 --- a/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp +++ b/ApplicationCode/SocketInterface/RiaWellDataCommands.cpp @@ -1,5 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuMainWindow.cpp b/ApplicationCode/UserInterface/RiuMainWindow.cpp index 066bf96f15..5ebb970e73 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.cpp +++ b/ApplicationCode/UserInterface/RiuMainWindow.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuMainWindow.h b/ApplicationCode/UserInterface/RiuMainWindow.h index 42e1a7c8f2..8ce06d71b1 100644 --- a/ApplicationCode/UserInterface/RiuMainWindow.h +++ b/ApplicationCode/UserInterface/RiuMainWindow.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 9ff86a3851..730db7629c 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index 07c322aa65..a8131d63da 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp index 17d8fe61da..53646b15aa 100644 --- a/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp +++ b/ApplicationCode/WellPathImportSsihub/RimOilFieldEntry.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 2d36af4f0626746d3e49c80d7af842a3740984b7 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 24 Sep 2014 07:14:52 +0200 Subject: [PATCH 343/346] Updated file header for new files --- .../Application/RiaProjectModifier.cpp | 3 ++- .../Application/RiaProjectModifier.h | 3 ++- .../FileInterface/RifReaderInterface.cpp | 3 ++- .../FileInterface/RifReaderSettings.cpp | 3 ++- .../FileInterface/RifReaderSettings.h | 3 ++- .../RivTernaryScalarMapper-Test.cpp | 3 ++- .../RivCellEdgeEffectGenerator.cpp | 4 +++- .../RivCellEdgeEffectGenerator.h | 4 +++- .../RivCellEdgeGeometryUtils.cpp | 3 ++- .../RivCellEdgeGeometryUtils.h | 3 ++- .../ModelVisualization/RivColorTableArray.cpp | 3 ++- .../ModelVisualization/RivColorTableArray.h | 3 ++- .../RivFaultGeometryGenerator.cpp | 3 ++- .../RivFaultGeometryGenerator.h | 3 ++- .../ModelVisualization/RivFaultPartMgr.cpp | 3 ++- .../ModelVisualization/RivFaultPartMgr.h | 3 ++- .../RivNNCGeometryGenerator.cpp | 3 ++- .../RivNNCGeometryGenerator.h | 3 ++- .../RivReservoirFaultsPartMgr.cpp | 3 ++- .../RivReservoirFaultsPartMgr.h | 3 ++- .../RivResultToTextureMapper.h | 3 ++- .../RivScalarMapperUtils.cpp | 3 ++- .../ModelVisualization/RivScalarMapperUtils.h | 3 ++- .../ModelVisualization/RivSourceInfo.cpp | 3 ++- .../ModelVisualization/RivSourceInfo.h | 3 ++- .../RivTernaryResultToTextureMapper.h | 3 ++- .../RivTernarySaturationOverlayItem.cpp | 3 ++- .../RivTernarySaturationOverlayItem.h | 3 ++- .../RivTernaryScalarMapper.cpp | 3 ++- .../RivTernaryScalarMapper.h | 3 ++- .../RivTernaryScalarMapperEffectGenerator.cpp | 3 ++- .../RivTernaryScalarMapperEffectGenerator.h | 3 ++- .../RivTernaryTextureCoordsCreator.cpp | 3 ++- .../RivTernaryTextureCoordsCreator.h | 3 ++- .../RivTextureCoordsCreator.cpp | 3 ++- .../RivTextureCoordsCreator.h | 3 ++- ApplicationCode/ProjectDataModel/RimFault.cpp | 3 ++- ApplicationCode/ProjectDataModel/RimFault.h | 3 ++- .../ProjectDataModel/RimFaultCollection.cpp | 3 ++- .../ProjectDataModel/RimFaultCollection.h | 3 ++- .../ProjectDataModel/RimFaultResultSlot.cpp | 3 ++- .../ProjectDataModel/RimFaultResultSlot.h | 3 ++- .../ProjectDataModel/RimMockModelSettings.cpp | 3 ++- .../ProjectDataModel/RimMockModelSettings.h | 3 ++- .../ProjectDataModel/RimNoCommonAreaNNC.cpp | 3 ++- .../ProjectDataModel/RimNoCommonAreaNNC.h | 3 ++- .../RimNoCommonAreaNncCollection.cpp | 3 ++- .../RimNoCommonAreaNncCollection.h | 3 ++- .../RimReservoirCellResultsStorage.cpp | 3 ++- .../RimReservoirCellResultsStorage.h | 3 ++- .../RimTernaryLegendConfig.cpp | 3 ++- .../ProjectDataModel/RimTernaryLegendConfig.h | 3 ++- .../cvfGeometryTools-Test.cpp | 3 ++- .../RigActiveCellsResultAccessor.cpp | 3 ++- .../RigActiveCellsResultAccessor.h | 3 ++- .../RigAllGridCellsResultAccessor.cpp | 3 ++- .../RigAllGridCellsResultAccessor.h | 3 ++- .../RigCellEdgeResultAccessor.cpp | 3 ++- .../RigCellEdgeResultAccessor.h | 3 ++- .../RigCombMultResultAccessor.cpp | 3 ++- .../RigCombMultResultAccessor.h | 3 ++- .../RigCombTransResultAccessor.cpp | 3 ++- .../RigCombTransResultAccessor.h | 3 ++- .../ReservoirDataModel/RigFault.cpp | 3 ++- ApplicationCode/ReservoirDataModel/RigFault.h | 3 ++- .../ReservoirDataModel/RigNNCData.cpp | 3 ++- .../ReservoirDataModel/RigNNCData.h | 3 ++- .../RigPipeInCellEvaluator.h | 3 ++- .../ReservoirDataModel/RigResultAccessor.cpp | 3 ++- .../ReservoirDataModel/RigResultAccessor.h | 3 ++- .../ReservoirDataModel/RigResultAccessor2d.h | 3 ++- .../RigResultAccessorFactory.cpp | 3 ++- .../RigResultAccessorFactory.h | 3 ++- .../ReservoirDataModel/RigResultModifier.h | 3 ++- .../RigResultModifierFactory.cpp | 3 ++- .../RigResultModifierFactory.h | 3 ++- .../RigStatisticsCalculator.cpp | 3 ++- .../RigStatisticsCalculator.h | 3 ++- .../RigStatisticsDataCache.cpp | 3 ++- .../RigStatisticsDataCache.h | 3 ++- .../RigTernaryResultAccessor2d.cpp | 3 ++- .../RigTernaryResultAccessor2d.h | 3 ++- .../ReservoirDataModel/cvfGeometryTools.cpp | 19 +++++++++++++++++++ .../ReservoirDataModel/cvfGeometryTools.h | 19 +++++++++++++++++++ .../ReservoirDataModel/cvfGeometryTools.inl | 19 +++++++++++++++++++ .../SocketInterface/RiaSocketDataTransfer.cpp | 3 ++- .../SocketInterface/RiaSocketDataTransfer.h | 3 ++- .../UserInterface/RiuResultTextBuilder.cpp | 3 ++- .../UserInterface/RiuResultTextBuilder.h | 3 ++- 89 files changed, 231 insertions(+), 86 deletions(-) diff --git a/ApplicationCode/Application/RiaProjectModifier.cpp b/ApplicationCode/Application/RiaProjectModifier.cpp index 0840d24be2..6de42bef55 100644 --- a/ApplicationCode/Application/RiaProjectModifier.cpp +++ b/ApplicationCode/Application/RiaProjectModifier.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/Application/RiaProjectModifier.h b/ApplicationCode/Application/RiaProjectModifier.h index 209a75e0c1..3518630b91 100644 --- a/ApplicationCode/Application/RiaProjectModifier.h +++ b/ApplicationCode/Application/RiaProjectModifier.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderInterface.cpp b/ApplicationCode/FileInterface/RifReaderInterface.cpp index c08eb619e5..0c2c852827 100644 --- a/ApplicationCode/FileInterface/RifReaderInterface.cpp +++ b/ApplicationCode/FileInterface/RifReaderInterface.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderSettings.cpp b/ApplicationCode/FileInterface/RifReaderSettings.cpp index c2b05aaa4e..b6d74adaa4 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.cpp +++ b/ApplicationCode/FileInterface/RifReaderSettings.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/FileInterface/RifReaderSettings.h b/ApplicationCode/FileInterface/RifReaderSettings.h index 7bf3ed050e..793495ed3f 100644 --- a/ApplicationCode/FileInterface/RifReaderSettings.h +++ b/ApplicationCode/FileInterface/RifReaderSettings.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp index f9ac412145..579412857c 100644 --- a/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp +++ b/ApplicationCode/ModelVisualization/ModelVisualization_UnitTests/RivTernaryScalarMapper-Test.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp index 0110826514..3171aad530 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.cpp @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h index 8167250dcc..967cc0de12 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeEffectGenerator.h @@ -1,6 +1,8 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) 2011- Statoil ASA +// Copyright (C) 2013- Ceetron Solutions AS +// Copyright (C) 2011-2012 Ceetron AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp index 57da9befa5..c23b50c919 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h index 80465bd6ab..ce11b19a18 100644 --- a/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h +++ b/ApplicationCode/ModelVisualization/RivCellEdgeGeometryUtils.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivColorTableArray.cpp b/ApplicationCode/ModelVisualization/RivColorTableArray.cpp index 451ad62a49..a3a6f60d28 100644 --- a/ApplicationCode/ModelVisualization/RivColorTableArray.cpp +++ b/ApplicationCode/ModelVisualization/RivColorTableArray.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivColorTableArray.h b/ApplicationCode/ModelVisualization/RivColorTableArray.h index 8702cd0ca5..df59373f25 100644 --- a/ApplicationCode/ModelVisualization/RivColorTableArray.h +++ b/ApplicationCode/ModelVisualization/RivColorTableArray.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp index eccc672ccf..4a7c73a8c0 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h index 987b26a0dd..a41e75a67f 100644 --- a/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivFaultGeometryGenerator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp index e6846e563a..773a1314e6 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h index 44f2a66538..5f21cc6cb7 100644 --- a/ApplicationCode/ModelVisualization/RivFaultPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivFaultPartMgr.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp index 60810ab438..8f438f4763 100644 --- a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h index 902b44d24a..60affaf6b5 100644 --- a/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h +++ b/ApplicationCode/ModelVisualization/RivNNCGeometryGenerator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp index 222038536e..b6ec6a08d9 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h index 3bc9c23587..7723319ce0 100644 --- a/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h +++ b/ApplicationCode/ModelVisualization/RivReservoirFaultsPartMgr.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h index 06dff66b72..e70ac7d6f3 100644 --- a/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h +++ b/ApplicationCode/ModelVisualization/RivResultToTextureMapper.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp index d525d34491..cac3315d34 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h index 09d84e663b..64bd98dcee 100644 --- a/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h +++ b/ApplicationCode/ModelVisualization/RivScalarMapperUtils.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp index 1e67105cde..4025bd1f9a 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.cpp +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivSourceInfo.h b/ApplicationCode/ModelVisualization/RivSourceInfo.h index b4e5f1306c..5c53214770 100644 --- a/ApplicationCode/ModelVisualization/RivSourceInfo.h +++ b/ApplicationCode/ModelVisualization/RivSourceInfo.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h index a93e8e95c2..45c8604585 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryResultToTextureMapper.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp index 85404d9cd2..b01401826f 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h index a016060560..f2cdf4eb7a 100644 --- a/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h +++ b/ApplicationCode/ModelVisualization/RivTernarySaturationOverlayItem.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp index a81a16d2f2..b16a8d3c7c 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h index 566f499e01..68c17b058e 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapper.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp index 76041518bb..60b7630413 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h index 3d953ef8df..d45121421b 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h +++ b/ApplicationCode/ModelVisualization/RivTernaryScalarMapperEffectGenerator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp index 10b8bc3aad..edef41aca8 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h index 751cd51b73..d209c018f0 100644 --- a/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTernaryTextureCoordsCreator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp index 2f2ec89591..4b3b8e6301 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h index f73cbf8315..7c1a4f174d 100644 --- a/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h +++ b/ApplicationCode/ModelVisualization/RivTextureCoordsCreator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFault.cpp b/ApplicationCode/ProjectDataModel/RimFault.cpp index b0d1c99d4d..ab499fea80 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.cpp +++ b/ApplicationCode/ProjectDataModel/RimFault.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFault.h b/ApplicationCode/ProjectDataModel/RimFault.h index 22bac08bf6..b8aeaf91b4 100644 --- a/ApplicationCode/ProjectDataModel/RimFault.h +++ b/ApplicationCode/ProjectDataModel/RimFault.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp index e5404d59d1..e16532c68e 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFaultCollection.h b/ApplicationCode/ProjectDataModel/RimFaultCollection.h index d8fa62defc..54c93b908b 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultCollection.h +++ b/ApplicationCode/ProjectDataModel/RimFaultCollection.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp index a85dd814ed..f29f1408b4 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h index 0e30db8422..b123503faa 100644 --- a/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h +++ b/ApplicationCode/ProjectDataModel/RimFaultResultSlot.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimMockModelSettings.cpp b/ApplicationCode/ProjectDataModel/RimMockModelSettings.cpp index 1266629d4e..e7e6fce382 100644 --- a/ApplicationCode/ProjectDataModel/RimMockModelSettings.cpp +++ b/ApplicationCode/ProjectDataModel/RimMockModelSettings.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimMockModelSettings.h b/ApplicationCode/ProjectDataModel/RimMockModelSettings.h index 64d1beac66..b6bc055bea 100644 --- a/ApplicationCode/ProjectDataModel/RimMockModelSettings.h +++ b/ApplicationCode/ProjectDataModel/RimMockModelSettings.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp index 7a20063789..7c05ca685b 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h index 100789c2a2..0707dd66e9 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNNC.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp index 08a674e836..2da7c58588 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h index dae7220a07..deb48e53a4 100644 --- a/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h +++ b/ApplicationCode/ProjectDataModel/RimNoCommonAreaNncCollection.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp index 3c93cdfb29..d533ccb702 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h index 3a70ea8429..4e9fbffe3e 100644 --- a/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h +++ b/ApplicationCode/ProjectDataModel/RimReservoirCellResultsStorage.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp index 5ee3e364a3..12565042a8 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h index 7567867752..12fe8f1e89 100644 --- a/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h +++ b/ApplicationCode/ProjectDataModel/RimTernaryLegendConfig.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/cvfGeometryTools-Test.cpp b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/cvfGeometryTools-Test.cpp index eefc79effb..3d3eefd9be 100644 --- a/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/cvfGeometryTools-Test.cpp +++ b/ApplicationCode/ReservoirDataModel/ReservoirDataModel_UnitTests/cvfGeometryTools-Test.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp index 29c563a25e..a2267e84aa 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h index 4cd7ae73f0..e9fa9b1c0c 100644 --- a/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigActiveCellsResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp index 247ef7f953..71e360ceb4 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h index 194b591d4d..4c347a555b 100644 --- a/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigAllGridCellsResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp index f21876d427..6ed6218bb4 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h index 4ca4d0a09a..3ba5e22898 100644 --- a/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCellEdgeResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp index b2598cb4c2..a06104fbf0 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h index b24604f7a3..74aa312a9c 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombMultResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp index 5b39efc2d0..8d011f3757 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h index c16bee4118..c250f0791a 100644 --- a/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigCombTransResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigFault.cpp b/ApplicationCode/ReservoirDataModel/RigFault.cpp index 82e5c35eb3..2b86d45bd8 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.cpp +++ b/ApplicationCode/ReservoirDataModel/RigFault.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigFault.h b/ApplicationCode/ReservoirDataModel/RigFault.h index 8a935365e4..e259850d57 100644 --- a/ApplicationCode/ReservoirDataModel/RigFault.h +++ b/ApplicationCode/ReservoirDataModel/RigFault.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index 6152d71b73..fc76ca211e 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.h b/ApplicationCode/ReservoirDataModel/RigNNCData.h index 9954c6dc5e..d9d55439a8 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.h +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h index 5a65f69475..5a435ca99e 100644 --- a/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h +++ b/ApplicationCode/ReservoirDataModel/RigPipeInCellEvaluator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp index aed929abea..7d208c2774 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h index 92f860037d..19c0037b49 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h index c3b568be20..2e86aa1f78 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessor2d.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp index f57991e0c4..1986fcc3e0 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h index a0b27e8412..53815e4189 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultAccessorFactory.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifier.h b/ApplicationCode/ReservoirDataModel/RigResultModifier.h index 651d12c4fe..79bb36495d 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifier.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifier.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp index 8d04aa6bcf..30cb443232 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h index 18f7dbd3f3..7c320fa4ad 100644 --- a/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h +++ b/ApplicationCode/ReservoirDataModel/RigResultModifierFactory.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp index 9788bf73ea..af56724a2d 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h index 5edeb22196..7ecc4f48ee 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsCalculator.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp index 01534e3455..87b8c6d403 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h index b588a8f511..0688ea00d0 100644 --- a/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h +++ b/ApplicationCode/ReservoirDataModel/RigStatisticsDataCache.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp index bfb431b1b0..d3ab6568b8 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h index 14f71a72ae..c081ae3896 100644 --- a/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h +++ b/ApplicationCode/ReservoirDataModel/RigTernaryResultAccessor2d.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp index 5363af7c00..b354a71787 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.cpp @@ -1,3 +1,22 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + #include "cvfGeometryTools.h" #pragma warning (disable : 4503) diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h index 97d26c549b..fb11aefddf 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.h @@ -1,3 +1,22 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + #pragma once #include "cvfBase.h" #include "cvfArray.h" diff --git a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl index 6ead7b8f9d..7b9aeed23d 100644 --- a/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl +++ b/ApplicationCode/ReservoirDataModel/cvfGeometryTools.inl @@ -1,3 +1,22 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + #include diff --git a/ApplicationCode/SocketInterface/RiaSocketDataTransfer.cpp b/ApplicationCode/SocketInterface/RiaSocketDataTransfer.cpp index 0d2ec8879f..e68e48899d 100644 --- a/ApplicationCode/SocketInterface/RiaSocketDataTransfer.cpp +++ b/ApplicationCode/SocketInterface/RiaSocketDataTransfer.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/SocketInterface/RiaSocketDataTransfer.h b/ApplicationCode/SocketInterface/RiaSocketDataTransfer.h index 7c16beb8aa..4298ad6363 100644 --- a/ApplicationCode/SocketInterface/RiaSocketDataTransfer.h +++ b/ApplicationCode/SocketInterface/RiaSocketDataTransfer.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp index 863f38f498..a21b951e17 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.cpp @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) Statoil ASA, Ceetron Solutions AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/ApplicationCode/UserInterface/RiuResultTextBuilder.h b/ApplicationCode/UserInterface/RiuResultTextBuilder.h index 4121c93745..0b7aaede2c 100644 --- a/ApplicationCode/UserInterface/RiuResultTextBuilder.h +++ b/ApplicationCode/UserInterface/RiuResultTextBuilder.h @@ -1,6 +1,7 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 212b41f854fd8cb182859258a4fb9d33b4673653 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 24 Sep 2014 07:21:26 +0200 Subject: [PATCH 344/346] Updated help text --- ApplicationCode/Application/RiaApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationCode/Application/RiaApplication.cpp b/ApplicationCode/Application/RiaApplication.cpp index e6f05ebbf3..4e45051b09 100644 --- a/ApplicationCode/Application/RiaApplication.cpp +++ b/ApplicationCode/Application/RiaApplication.cpp @@ -839,7 +839,7 @@ bool RiaApplication::parseArguments() progOpt.setOptionPrefix(cvf::ProgramOptions::DOUBLE_DASH); m_helpText = QString("\n%1 v. %2\n").arg(RI_APPLICATION_NAME).arg(getVersionStringApp(false)); - m_helpText += "Copyright Statoil ASA, Ceetron AS 2011, 2012\n\n"; + m_helpText += "Copyright Statoil ASA, Ceetron Solution AS, Ceetron AS\n\n"; const cvf::String usageText = progOpt.usageText(110, 30); m_helpText += cvfqt::Utils::toQString(usageText); From b046a0354db1528933387cb2d2b15ba429517603 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 24 Sep 2014 13:28:08 +0200 Subject: [PATCH 345/346] Converted assert to if statement when no NNC data is present --- ApplicationCode/ReservoirDataModel/RigNNCData.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp index fc76ca211e..2b5abde1f0 100644 --- a/ApplicationCode/ReservoirDataModel/RigNNCData.cpp +++ b/ApplicationCode/ReservoirDataModel/RigNNCData.cpp @@ -190,12 +190,13 @@ const std::vector* RigNNCData::connectionScalarResult(size_t scalarResul void RigNNCData::setCombTransmisibilityScalarResultIndex(size_t scalarResultIndex) { std::map >::iterator it = m_connectionResults.find(cvf::UNDEFINED_SIZE_T); - CVF_ASSERT(it != m_connectionResults.end()); - - std::vector& emptyData = m_connectionResults[scalarResultIndex]; - std::vector& realData = m_connectionResults[cvf::UNDEFINED_SIZE_T]; - emptyData.swap(realData); - m_connectionResults.erase(cvf::UNDEFINED_SIZE_T); + if (it != m_connectionResults.end()) + { + std::vector& emptyData = m_connectionResults[scalarResultIndex]; + std::vector& realData = m_connectionResults[cvf::UNDEFINED_SIZE_T]; + emptyData.swap(realData); + m_connectionResults.erase(cvf::UNDEFINED_SIZE_T); + } } //-------------------------------------------------------------------------------------------------- From 85934c46ec65263a9b34c523587ba3db330d2685 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 24 Sep 2014 13:29:02 +0200 Subject: [PATCH 346/346] Set ResInsight 1.3 by removing -dev from version string --- ResInsightVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResInsightVersion.cmake b/ResInsightVersion.cmake index f0906e5df6..59bddbc2c0 100644 --- a/ResInsightVersion.cmake +++ b/ResInsightVersion.cmake @@ -2,7 +2,7 @@ set(CMAKE_MAJOR_VERSION 1) set(CMAKE_MINOR_VERSION 3) set(CMAKE_PATCH_VERSION 0) -set(DEV_VERSION "-dev") +# set(DEV_VERSION "-dev") set(PRODUCTVER ${CMAKE_MAJOR_VERSION},${CMAKE_MINOR_VERSION},0,${CMAKE_PATCH_VERSION}) set(STRPRODUCTVER ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}${DEV_VERSION})

}9cPT9W!pS*$NuEL{$c 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%0D|P z3Sb}hZ5pCjjDhM*7zuE9I#DbNemhVfFf5f*`&@-L@#=kxxJ3$pD++!-FbHE}!H>jt z;mWZGAu>z!T*7E&zvnaU_!&|`BswYPJp>#hfER9E z#9y_liQ^sy=fl=;5CN~4j^Cw=J~wW^uxu4lP{)%Sj_ls|x^OV+SVc?s?H8%<6-z^j zbAnj%hD?ADOhAnf$Yw_K?@!d8_z%iNTy4fq8TV$sZyUw3LqU4M{TM7Die=rUu8J4> z`Wf?wT2Sc1JMI*Choi z{tmvxgdZT^>(KeaXVgT1N3K=12?B)MiKYCPv2+1$_06|g`A;PP7jne`0CA3MQ0un& zvhs#Iq?uGU@w>>&5DwSfqCX4q)82r_rI6a}*XI;_9yg<(|Km>ehLasfopH`4%@Q#Z zz7!N&!%i$lK3n1_QreG+QT3qN?s_e2!ntx%CA|IHrpl9dVC*97b;YhaBa4Cd7OwR6Nxj*%i)(TwEh202CUW9wSt-E^7vF&jqLP)5{#WmN0x=8{;h+AqME7mWt4-Fem8w_fF^ zW(IBTV_hwLZpVT%^vV)rFpd(We88_oOEpv-m_+tNZ=rir83$~keYUR^4t6;-cku`Qpc8OZucj&G_+|>z zX{KsZL2I@25$sAGQK7Yot_|D9X6(p2Ob&WhJz}((Uv}qp8O4^|5p}UK z<79e#O7?DHW|dB`^^GyqBn<~Zja#}gCwTatqqv#^N?qsY_Ur?xk6WUG-KUq8FRpKY zd|JMscQ;Tq9=D%(d=W6e?Ai5ju%Xf&c5$ymN1xhtH&>H9S|?gvZI6kVsd#1a;ze;$ z5hFA6pNkN3a`MpM9gBZ1f2=-w^{d?59Jqdx{ms7{6=TAvJLi`xmWfKgh7wYNLaS=m zC;|gKHLf_8SDE+-`s_bKKIoouv#RHX|WrSl7NhAX%yK zy|q4yvKOU^b+Vm^7x=a|dk=b1*g1u5ZQpg2f60SO3^s!Mz4;H?)SS+7{a#u)amD)q zHA3+S{lYWxK>UBCrdn=B~Ft%KC>~8 zo7EQDMJr#>`S1D1AOm(dO0KT5+^Mh$P-6o@@j6Xh7RQbQjwKlx88bLYpOcZ10pI)j zvW(XVxW2P5c+@QQIXodi748&2hC;)-)y+Oz;??on8m|Wt)JwX#jOpbJ0{SwV)-tC{ z_2Y`5o2O{VYL&D88l6||ekVIg8Ey6P$CfB!!?QO9XG&@B%2WgVv7pj@IEdp=ztA#| z2##SfCZC66PwznWc<@Nf8Cx6gM_AhFsOi@{`-hnqQgT_g9wEXFD?YWyzurX2NSs~w zugR}nS?pjjem1;dEJtua$)d@k6)|2RqSaF~hIU0QULBkoKSQ!00VH6OtZ_@aw@uyM zUiHit;Anaw2Cr*bHHy%g)_TybLe;z%ZJ!^Q{)#^3@S_?g$q_gH%Z$D9x0dx%)@anx zNLEHpY3kgG@4p$KPWRdPJ}v4KNX1A0hhKuC=%Fae`EhZ6Jta%zB&#tDeSY-qN3WIk z*!waY{pSL~*0SEuH)_RIHK2?#=EYe>=qxglpMFDA9P$FQyQS}^p8**enUNxwAD$UZ zJnrZ;)-HAb(L^5<^8aT2#BXNCb8QS|`SQ&MK|)4N{psbr0QW0ADa)2Ji278gj7|Z? zFTD^Z`qX$~oA;egc^tnOz8Ag{0ryAKi>m;LW!o7FNX7w=tF(?hn9j}lfE*DhZ$F<2 z$|!bZ*XdJu4#pvh979LKFrfc%MPqET-U@+Wk?dePrtwsiPdH9|sxm#L+Q~p<3~^$5 zY1x;%GBL6czaVxpPNRGU%ioivDC+OKuWR%Xx0i8iKFfp8%V2S;LpUk?3|&@4Ja8L0 zt0omAIv(fEJ%QK_>DA*=QE(we-}R%ytZ1|Ev2dsl|40*mJO)blR0GqWI!*bTGI^Qs zcbZrR^<=KigeM%%%E^ktbd6Uj8U5u~>Dx#=0I93cL9G<9K&uJc8X^OMH9=&2d3r*&8(NbSSZYT7L zzo;;J;cPwqI+NarN_a1m_@N`>qNb9nlW6_oQXU{VI0`%4`Bj|j|EotbC(Irs(r@P? z4ab=5j(p5~qJt9iE*RSl=*XH6N(gESI4rq*A$NoUKmdLe(q;VHsBs(ek$Eaol>0sG zjpO!PA6O9*5J|_B4Z#4dSCPM~!VkXyct&tz7L%l@UOV$*DEwf0f{8K<6)vR!TqR$A zbTrW29oGduq`yP1dU5E`tB(TuZ9h3eI1U(VZ$6M6yK53!6}`!H#nXPTs;>F&%WA@5 zMBevsYR^pP7^Lu&SU-oFt8viJSC6378i9(z% zZO&(g$^ontCON1&P_^1YjuIjcRatdkl3#BbE$63~@;mM@0xy0Dq$Vsnjkf%9^bv$w zkaHj4zXjWJYOrLV?VXM!==9&~81cH^F_ID9R*#7HE?0XL)SB4)Ln&hP(oY^DI)y*1Zit!5wKsgC2 zlH6PzR?^4mFFRxVgZ4)$nv1$OMLy#i-e&GtC5I{(JaX) z0&_TOps)03+ZVEQiC$ZtCMoM0uD;&kWoD;*w$L}@K@qNf(U+COKpX79@$pojXIPs* z#Tf0h(AY|TXO3^x>R%6B?x$zbDH_Xl>+i)>m8933Z$e&D{?7F|v=9A?XePe_FtJKJ}qenVgG)uFWbEif9_9q_n8GkJx4L8^`|~Ptk)!-!Y@#(fZ&xR{i@YVn=8aR|qH`NV47VhvdLe51#EAA+44&`7<|v)I5uT5v zaP`o==)G-vK)+Ar)ng42%Rb>(2`x1g7syo^5)E4y3TQJcigzv7*?0c&YO|#388aPW z+L9}^)tNzNLF{Jfdk`1-=Vt2`>BE*OOF`MlRw32Rr`$o`DO#^CWlHkoa%P=@^<&$WqHxQ{bX(rQI8ykPd%y_lz7J+K@g zYs%se$h1vGN8?w@ZSf23kkg!Uo*(wlfojGCYbuQLy|v?5>W4W6x)i)<5*!RXe0(ES z(aEyCo*MDEb%a6Y%F?+zKp&_P6gdv&c_$!4{paC>g1L@{D8t#CG2rC)py@>lkVl0o zQbpWSFRn#QB?4?YUo8MG%&(ZHwt1bnqBjus%Cj#JKpx15A{M-g^XL z*O&jmtr8b@0^m$8xeY}zQtdP#x|GpBsh+WCmd{-hVPXoru{|a4;4|j1U*qTEAhEom{_}oCuAVb%R9-I47<)K}kv$ynx;bto}8N61dj&SQ5_aS<8ysV%TIPQ0($4ywWjdGgb>h`?&a7h_Ez`lIhQEBgg1IjSJUs6x7@La%749qST#ChIm-O0UDO1~r!(p=1f6V0;V zCb1)E@f=2JRaATXMk^ErM%!CfWPa@~|8+d7Mb<_sg~#W$-Yh@Q{Nje1f}|@T@>V%l zGm2vi4GEdF++BBl&ryj!$k#$;P7Z%ljt;HGkv@1cNH6xu(m8GJAJoQD=WX9d&!Uvb zJG1D_KNHYs*2pu=rO_+h_{h3Y-WI^6t;|7&TB~hwo2YbGaz3^Mo_qg&L!|S9YH^G@ z203?GO(|W|Hw8`Hg@NEYQTCSUH={aq^`Msd=yG+t?284>+-8q>0>mUbQk(Q? znDyh!2a=7=O*B!?>G9j=*y)10dH;rgn>MRzPs;Gu3ac4&$)MOCak5rG+dY@}2^B%A z30AW9e7^GD6d8-X$jmmJX%1yrVt^8*!Rh&(UyO3fK`Jw#BK771@>Bs7M=vSWu-{(+)wcRP*Xb%dSZY*I@H8{t0GxZJA)7Y3ftHUmAlT-z^Qh)E!&l@-PGuLy@onyQ{i9Mt6yOZLc^zpTtYXrpXCYf{kBh^VQcSpBCQe))PfuBng}}`~;)3-F z!Ef=G;ew7#4v5j`8+yfV1vlk?L?`i?GEz`OWAy)0x#FiN zMB=|b%kANV+^%=EWQQD-LJ$5+zss2lyCB1ZOZsIa%b6o0_&eL${3O!XtunE9W8eUC zKrEowzuR2Aoj&r7m$!Em$-g|ioMD`jwV6xJixe%D>#$DthL#m=E6_qS{7RXYUUI>`I##IHHc;B+a;ymOZbey z7KoOm&-?BK@L~jJ?$Cu)C)@PSpc2#eY`pZmPo0>l8Oia72ry5tuf!*DKd$F-eE?0z2g&aZ)w~$0S#X@^T9NKRoq9 zu1@?RZt$yy*m_7YY!d{l0vuWZL0eA?_ri^z4HJKC-W!F(>)jYpbEqSu8&@ zGczk|$4~k=pkvIjdC@I~B%Qafc;8u!E=9F>!%K?c_m4^)7SsWbCho6tadGjV@4&8W z0T?5SB+Vqh`f4IcPzPUt$2f?c zuv}UIE~B{1?w$4V8+}QK+K)BBD8$%Z6`Nr-2Sz{jt&B7{KOjw-oG zOshfdM~>U|8|6Hxz=TU*$leoSQm%t1Ah+JtCeSf>HqkpaHkK)E02QZ|-^s}Y9V-HC zZ&F}(zK}7FwLTIEWX8)&5`E! z7RHiJ++U%lbxRP=2~d_5oTFLh#$IVV8Ful`L-b>4NHDgFQpvmT%tr$!WdtuhjdEGI z0b0yVNmU~Uq*FiSTWznpy80LE#(^#GHcNq=5djUeRV6XK5Lu@5C+z7^Zi<7o z?#OpMC%un9XI59OEi5d8A1@7dRXHVjP8zzjD~ZwB7s}T1SchWn!--XXs3lALdrZSp z^h^yv(CbY~fysZvfL1o_Ta)EPY4`^~A+YSddx zhI1;-u9sssj3~ApElkk(}#@|2fo8G&fmE1`W;f!058weo4ZnAUFK3ZF;pc6eV4N>b(ba zSPA4fmr__+Q<8I*&+Pa#=>?+#H~ui6v&lak7Z;bGpI=kyp@E<`;uph&>Y;;xIB{(* ztsoi}=K2U0VffwfOq-goNC;fE8y~=>cshBW#l%9ZGm~!4jKK(=Mgr4lA8!})q@;1n z%Jg%iul1I<@i-aeArqz4)_=E@3Df5GsswfFb`L=SnVNayro(nkChwr#}@e#Jge?bWsz?QQ-_!Nik2$ z&6FeV4`23sW&4J9#L4JSPY6;(vA3+sr-PF-zhRCmJ14Y7Nq)EcHo{Cxx8CjQ$6;B> zzaySgwl8pW{7sr+BK{NG=Y*))-xLQVCo~J?PVF zzL_g@Q#g%mSf~s)VGQO5EOkksHXUV%uvK_dzd4Oe08!|zx^>;C7K8l-k$b^^LAu(* z8KF&+epN!I{zM)o;*!px=v`*ep_0%?w|2r!Pj80WeOA}1@@YlGvcE%Vddoief9>;e z`e5s0mdn6?{Ih+Pj5;N5xa?5#H#27{5k6v^MOu_(>QSIBe=`1mkxQl-qD6U-jn48k zD@jOR7k|DSUt*8fxH<3e9RI=8XtH>|s_^h{{IQcNMYVHv^u@#PD9<7}Uez5@92Wa) zl;@MNyTt8a9LAI$8Z@4hv!C0<(ljB8?ltReEweio(u?1hn&{x?r^db0gTFzA+LbhG zM&7|jrKg`)Jmz* zO72YNb~OOaX9FkFHTFSc%af>bg~fn(Yd({9tq*PJB#R}Ek_@fL=g*a!eaZH!xap`F zzezd13_kr@&NZ0xPEVNgtSoVIsI&}|T=jUUq%7S^B^Rc4n$vB8{9vaa2N7NwOVNs0 z5EW;rnl7_+R!`G^v8efZYOoMvkgjsh!s)4_-Htnaj^JCg*rwJ2g?9gVvf%2oBzO*z=*>kpHb95S8AUt|2 zVS_h`*OD6C@?YhRUyLO?+b0azZaTh#qcpiUJ&7nb)I}EXirUzYeYrd z`9R<{jzKJNMQP%dDu<}O2b3HKB4Ut;i$GqDnfHNZPM2_bR@=U1fe33Bpd*fXf&5H1yaRj8H59L-RW$rT7!Ap!2dbP-A{KUc!td_HaC z%_6Iggv9m^H83d1D;-fc-ZI|d*{S#UxEj}3UJfw3R?_f`Ntoc($XJ9(_Cp}YT(~Uu zKgvo9i_l$M;$!+xs(PoGMS<#j$`{Sy9*Y6M#u@0m=-TqnYUkPMDFu1?|4KYOou%Ud zV7P}B1+2NgzILxy`N#S6t>Pgu0Zr*2yq&Cm@9RlC!XkFn<;C6rs_VV=6+ozq9GHWB z@9p6zR{WOY&FhEB@(qmx^z?^YO@pqC^Ep^KpsK6rkPxW0>!UuQ;xPRPn2XarrB7PMUB zwNN2^lISCRP_$LrkPd0@gc+ldWw532VUE7cR~pvt(2*M7YfaP!Adoag()>Q7b415S zprJ91O8)W7!12RHW2BX?F5;+*kdV-`^J1>&S8=g$cnCEy`x-11S0khy2cX%?KZ=uf{jS@!WuPu?C9!f2F8HHZ;z ztfip|WaNM4fTKs!d9#RVhaX>@6!i7=ZSt$z8#1A$CVtYQA|lHkf!f;I@0x64Jhg;q zWP?w?H`)Gj20j!p4)g$+Ai7Z~8C`~D@X4oqtt}=b|Na;3*sTjg=x}ECR;m=na}l0nmCy>x<97* zs~w=3FG$SpcfJc<6A7bn+$Kvk3NquOE^wS|zek4q$`6$7w{-q={rq*-`ss-~{^-a^ z$HUFxud#xh)JxfC`_GuCk*`$mzjjppOz4mEkPDHRoBu^gMF%=P?(RIj{bd~>ZRO4P zUuZ9t#%wb4bppl49GQRSvPi1~`_sCmSwCyic?BH;WT^ii|%=kdRgPL%+%&Le{ zrYm*cNMaTjS-7PW8e$R+xpZqtjHo01(EeQMdW!KN{Cz_|8H?b!kdmNM>4530U=pvp zDUu9qVA98f!7rwo`X$=(U`P|2^%aBf89OEvZ^~d%?4{n!cRLkcE{N5}&9x3_YG$AG zYc}xu>m<8oc386QGlo-lbi#ZG`_Ik!59e;-7@O1@!q5NZ=-lNlni$c7cvT0h6?S?7 zRL-7}aMQ4^z}wl`DMx9{py<&kb1ZHO^?|6MX}{-MO_FH^K|}E)tG63t zKNKwgt>)r$CB*)p1{6VdhVu15aA#{~%`C!v>5bJV9`6tgp~Wmz(mF%7c77wnjr}<# zFN&jQlDpW{(DoQcsBXI>M~Q*GwjHpxwuEK8;?oE*q*YjH+5fd)wg=3XR8HH0X$ntB-xU>r5D}T)t9%+4Ad042+ zleDs0E&IG3wKm}dF;AOl7kwgm2{BP)<&3->v^*QG#Ai|Hkbm%l4hEc{Cs=j{AYz`BT&L`tAoR#mlxTJuo`ym>5 z+7xhk<8cePzcKXYB#tGk=SN`dS=g%^vV3*iZSzVH)iV~;l6osv0&YnCNTv`d?7J#d~tAFgW&7SIj*7PoF{XTR&yXreNbI`02 zUN>-1I;^(~xfeY<|G`3D3DFHBO++n+MmSd{t2yO^{L)ZK}Ud8Z^9UuO_-pjtx#LiC|oP3Tq4dJoJSh3IS z+4CJ*b5ouy7~W;*t=^OT6 zvy|Z?I=COFYZOQO?JGF&@5xxFsr@8-fqWiz)VJpjc@RD%Y~eJc_twU3_0%TUxpUJ3 zv!?HvYMVbV`AvuLCr7p>)AX26HNvc?Hantc`jrs%rl&oc;hKd^CGE`-FB8qU8EKBP zU)#H3G(9+wb`$xOrh=fgQN;@QCXcY$>-*~;#i*k0uVNhHZH4N@;?d>peZ=GLGnrpc z>mK_3Y%hB7iog5Y{WjArTYD19e;++=O8un0&o6L;S-6*h1UJ1Z=j zAGfp(*6gn!d6$|jSSS~{DTmX?)pP{NT%e+}-3 zwr{>m^Mz*DADN-d`S4IJ$Ug#mk1EE0QH4`Me*V(WpV8mOQT?hERb1A9j;HMGy<4`c z9x#yEv{U`vru8+$0wvK`<;t1+R~2ZipW&NmbmT16AeL$@7LZi$boXbVx)rS5$G0@r z53a*P!5(H3CtPR97cEOF`FGlRKP5FNx0TOefLOg`U5+@i*l?N_U{w`i2ml8TW+6F? zd7cr?1jSM0&v)o2$8hFt5uzEUs91j6C4F^(u!vul?lnn6qaanxoUQDet8z6EyRV!} zC_T+n0QCHs)fJz9*i1~fnbsFa!(oYD=81l|6RVQ=*EKfl`63w zSJS|*1YoNoR4?Y6f4ox!yl6rCT{LA?v|ucZe?!l6SFpIU1D`h8I8 zP&S)c98i8m*M2wblGSku;w~1nAh;!_b6-LHxBPtBU2Njk(!mFNMWMAQ#z;DufGUqD z?1m^x6t*eYGm4jnJxKz#CrME(#9>o!PJ6jOh4+=lYS#gnfTk(SguEFUS@}DaZdy{d zJg9YF!7-0(yj(T->j!1yk=e%&o>3L#J0x|G8-lg0`Ac7&H1a1pVxRsmw%#(Ts_zRI z-sccf(j`bAkPr~*Za8!!jdVz-bci5*=uo=5r9m20Qo6fKQu^-S|Bm~9de1ioFc_@0 z_S|zl^ND&lH@6Upj5T;jFc^RCR(2=x$Awti-`NxXd!Hit47h0n6GH`KZ zyK)?oZyf~t3kK;7tN;1>i~G01F^`}w5=;77zL`vNfZ zo2}xDfD2c!p(@}S4lDo0{qvQ;+vv}&3Wj)+;6uDdYfeqg&HN31?M9Bbr12~! z!L-D7C5d-};Y;1k6WtrN!GSUmXizUkS{}I-3!Yp2neJ5dWI!UC*u*TUJpjiHC-wRp zw6RY{`Mbx&F%|+~c-Rk)j(YNEsL7*kynfw*$aw$=he~WPm#Q zOP9=!=umlcAj3uDmRbNE$ai^trxRF?(z=@iGEdmg4CIvkLUcbGe~71>UXn8ptas6o zZj(^^j?TaA89sMO!%;4MJg$GMVnT| zcWt)RvX&x--R7U#vvOF@Ztq{HOmWr5poNgVnj)nv1uc_WD&!r`{Q~VmqK;zZw{ROZ z|9)7)#M0;X00QE{zBhv*RCD`Oi@iLx!|CkoMZxbVL690`*zSqGEo5BTH=_14zpGtP z_Cq6-RCvb&oo}k5AfYHGv%#(J=#yfscqx1OwBo|Ot(Hi@`7*|f!XTSSEgpRi*U9*j zuPFnc8j#EAY0Wgk6P+Mdy}s}f#NUSf+iT{>D$SP+9;U_oaz8&Sk)}&F4iqUZRT7SW z;lIR%ewA!R%Wo|spxyvr4ZrhI5m<7>5lTk)Th5n5)BzGbx;tBw$KkU_!PK}ChaQ5c zS3sb!>^uLfKyG{nA*zX5fvz8yvxV--$F?GTi9D>ym@5xYT^A!BbqjkQ6T^2$_J63f`z@(@oHcEk5ue|G zYxnR=p~5~eZ|8Mp%jSF<%l-MU8b?ohR6mLq4USIm!APxa!!_Xe!|SMek0?UdCiwet z>}ZHP367q^=aL-W{6_->GB9!IQJPd!X1_Xm*%?6yL_D4=8+9QL%k981 z1USgPS4pf$eDL7V>lD{3*uHliNXs^({opfZ9RYU99{gBMgXZnR7S*uykPcilOQgUu zZc5&CGICZnQJPsd9MIIQRpZNvC{e-*V*yEG7}x16kj_R;|&SdIz(c6l@E;Dl~sdof_AfG90-A=N= z@4P*qhxNc$s}$TZ;$G}xBb^-ChW*b(`!Kb_*F57%#{5S~1@f=3m{^qBN~GkQNJ|J_ z;32{(dVE+TefPt;(1m5`~YPbNA|`%JbV>{mLM8^-4aTI{ ztZ7M9nX3}=GZIr%Qc~hT^Y|W*)(l(|)t=85mjt)dG0ueYM31h!oDUhyPo4ff>6hdM z0SufpdD}rAJg+~}Hhaa|eKy4Y*wVFN_&9^KOnG`GWvOC*71F4K?M?@;@km6*o7@!? zX44vFT-ACdm;T$1FqJ*#{godLaaUQdYzmVYRLWTkXV-BF-SvjxzxI!Nj=($i<-2{~ zL7T`2PWhnLuz$Vr<9`aHQ9;ho=x7Nk{d3zw)>OKn@%ugnzdYt@uNzaZXF%T0?y1eA zrNs*PTU%ny6RC?G=x)QtZJKs}T9ju@)Xrupw!U)P*I0J1$oxMpK!8a86tCvW@^y-4 zZf$%TYm0Ax$5K+ByDRQ+Y0^G9$W$tcJwgW1xi5v*Q(k9vbz))=jXCkXw&=!-u$KC* zU(j$@xW~A7F9FMa$}~1qGc2W=B=aAWVzB_6IFw7npN>o1S+U~RtBp0D z9$W5k$Vtzz!Qfk->*BY)h2F?+y4lByET*sjb>^U9;V1-G9Cvx~={u^K;uq%c@Ndzw z!>b?eD-OJnz?&{aH?uHb^)u*9yKt!I=1rVbS6rc9$ z71Jq0s~?O4RC=*L+tw>I5L>tDnEeh4k-Lre(*oc%m~kA8fLMAiL2i}##j)Y8M{A$; z6j*rh!$aOBe(qUQWt^GiM)>dFzenC%QIpy^*a~p1@|c^PkJyZLo^iC=FfsGW<=n`C2H6|Xco*-Uy4Zsv z@&0OI%2OLdElAa`-^GlnMEi$`v%6r*l-*d-RaC$e;ZKc1FC;YSjN?T(+!C z!{8{tzWyTU8D*-l&v&iQV3=*jGuuelc8=p8;XMlCCklVA@BV5T`wqWzNaMSfcIHYN z_fa-bcHUc0LhwcXkuvCyo}qouE$IUP@Qo?%!TW2^=JWO{WhCBU2%M}@9pBz)QRdcB z@5rMWMLgBG`OWikc=^Fg!=k5uW>T(ji=BSRAXRx1b0ldRni#XUMLo!W^@}gyugt5> zcw+1`uL`0}*pyp1(I}Dy>_5vr8!;&oj{vzT4g>{~5iji@T${?vUkeH@Sk^H)4)lgt zC&oz8Hn;Oi+tfDIhHi!eA%@DVTQijbgyoP zl!RVa18s-QXixpOoBTh`PdtF^7xLm_g|vA$b0p<`4W<6@?Rq2juexu-I6vS^uxA3p31E*{(9IjL!}{9mG*~ga>lS8 z=d;bB_4W0hFq~Jdj&h*Ib;2tOY*_*9kkK$j&9dX0x!z{>;N0`E*WZQmu3yq+A{U3m zO{_8>U%)wgHcXooV>k840@-9@`HU=N{O)i{zTRCY<1<0?r>Yu8Q*wp>wA{+G8+xt% zGp<}|%63tk*BRH834DoJjbtb+hOZDv$n8Y_H5v(#HEGMhdsW84Pf>~j{}TB_M^;BE z{lAdbZ{ebyie2$tC?jnT0cqg8g+b$5g+RunJL~UncGGoJ z+E|=O0a?*MDN$3DMa`HjQvl4z0jaT%@5>`W_A@x}u-x~^l#Lpw*`|Z8`U}`RHBu~2 zA{gSU{TZug;_z;-rhRNNlITkcsu)|zJe}}4ompZJIiJ&e50CFl4zW_Spspn5KK6*G zwZ{a6u7ckaAkz@iO5q|)(8hhCM&tQvh-(K@DE8beEiH+BUFtzC^GYo*d(LXpvTVIEafF<8y$evqV z5SCqGJG( zC~w11VV>IQs$4U3z1;c+&0pICj|vf(s;Y5njW1K=N7)YXw{Kh~MxuW|u!cpoZ14j* zr;(K-J|V;fwln)U4&~qV7WomhVn3g2)*l*Y`th_rkliPt40`>`+@jHizykHEyuVqc zSO>3Xi#-pcdyJ-x<)l(iO?WGue9z$hFBU2g!PVvRx=@h0x0t2VZIqH};lY#%uhN}; zy1e{9Km=R%LtM`|+0Vhj>V+eoE{4atg~JyySg{KU z?N=Xte0&r>e9$)P=!p~mf*UR)C@9G~%sNnng;cO#-y6k@^lSoo49_y*6%)`_-(Nk8 zx)4778DGp>-P1^GVu?NKc?((inqD3J9<9xEF0>V>z*GMML97BpAQ182T)Rvwow_>m zEHgdU#^FrV`6Q!37CYr)&vWHlk+9M54ywSsvH$U2!O6YZ-h2h%@AvEZv$AW9;O9SB zJ6q0c%Q`(n4QjQn7X|*7NCUX>9O?tMhpNA2@Jt5&T32?An)epM4$``7&ezFdTPhlj z)dW@Zm#9Os=`$j!!ph7`-UjnFA3+l}TykoS%tGqpRFfZD3r|?keugxFt^d?190fs` zsDlIpp8?R@Rs|^rtT%7s-re=1z~RKU;_m@`y-dOs+@s3OrZ2>60uAPl+^B^TvDBna zj{U{XdEEgxyu7^cw6rKb<}wls_sb&z-py0&eIF`=}Is+)ExC+M7RFO zN^x=aGjxye)iw6MD#6={PP<$DRn>la_<>zW@L|Mfw&I*B!1_#U=Kk)eGg9{{ygy~d zX#1D&C#7p_R*q1!TuScO^Ml%)?j{e14(FFt1CNm2+85o)gI99Vb!Glw;sRNIH?qkD zA$99ubi}vm=OBgI%0G>fB^~?ohnZd8m?=udU}E^z;OI#tPATMvr6gZ26xIL?s=Nr4 z;#CL~D)p=5EUo%&CWRF7ngf5gZY0z8>d;E8&Dv4H?MRkeAryz|`1}SuyW-;FVBqYC zUr~E=vlp1sewWDz_a)mbX!TSWmg$cOoB3NrS5Qy@W=r6PfY}n;+uO+>$jZ0tnH&3p zT)jW#4$QZA7-aq0bK!dl5^ku$S%$@|oyS)?QY>|O$sARE{e`YG^<+wjZ^tEvt6P+~ zLCvS*wtHRXkuqBzPLA`ulJio7qJ@ynUA4YJG{AhJA}8*BPllKxUB1BcvoG6!LWwI{ zOz{FbT>j%7Z?50A>=WM9R_eFgb{Vfgo%V>{Jsp$q9*~}84s1id$P_rsDY&|N#GGIq zy|K0YXdY%lL+Yy{eHY3khtI7m#a#&RV@+bcJ8b-E?Z^Y*qzU_e4;PPTqRE_nMSF4~ z{pmuy2Lm5E=;oXk@5xYoLJ1t&ta?Ei5hP?Y@KL z)`^LAW<4cUTW@+-zp!2(cdDeqbINwxK{a{E#nWo`z=6A^`Roz)SCE~)>e2jFUr%6O z@JeYvuTol`35E$%!V!q@_M$MOl*;|z>bvh~J(pupi9Iab#s$o+Qr(0(cq9stQkdOH zfe9SGH{}bZzl>LL-hmUe5wOC4qiHQoh<@&Mg94mIM#NB+MH{k=cDTj3vfYJ2+8 z<+*t0B$wrHr5sSvaxfjP!ZsmWVWKwHMV*ec`##i^i&7>X`?7ePx+K&!fP;g?GfIPo*EV z@FNyX0hl7-qPWsXEX>3Z&=PR|NuT#A4*eU!C=|UPO-`(iiz1g4%pX@4#Z=|u6xy#{ zH(qcwvBXMXwzAmg2m^-gP5T@>1?scEZhioBIQBhSQN#xa2UXvz*DJ>S^8qPy`dV6A zQwb>jHVEn_w;6{Q)C1vJf?%ZF;h~+p4anC-{RDOpF~7+>VLLVTuiIc-SAlzu~`Gzy#f^%Ve9gHZx?F-AhVec+bLqf zR%GgBC^ofhRNt-SDPh@j3gaq%7Y)q(`|!SD9nUDp;9qA*ZR;ZWGx4yuvMSt0S`H!Ja2nJYE2p&?|aJ*pOx3ufGA4sgWD&F${y)?~oOQ5sE+2F~BsaII)8 z!LZN8#YHv8Q0dPSIjW2>uj23ZVo`k*FWCK6w^xw(o0~xeFRkSC%#5HvncONZl#tQM zdQpQ3@c!uXBCtE)cyM^wy>&4>XNwJp#R!gA4A#%Drug4@y`%tn=v5Ik=v{mIFXJO46$D*olNpF93O~tYU_`cL zSljJR=UJKg`5Bp*&?*W1f0DtEg_m>DqUHV@!|HLcB$~BI*^_a7!r^!4UqDZOz&d-I zlg5O{wKk($GV1%-obhk%S{$4JxQS$)Oh+P>xEGg-fT`KV z6PvB@0sPqPFOdVU$bi#}326TK=Y|!1_7M#iaMj-kJv|HkRv*5iTPOqeABgho-CjBZboJ;BEYhfmbT~7N|cKAS;D9) z&~Idk~GeI$kC`o(KZu)(n?)Y$wb z;IK{)ss&HNcvYU9=6uZ9Qeni)x1Y+0A0C9wwp!-tmO#m2^>!XkXtdBtl)2+DA_dxb zky^$V+^!?2P_a?C`^GeXZ!~*92P2hrOdR)*RCe8GdFp>-BseVGlp=RIVRWx3Yq$2S z+|>g?GA3#oDNMS8AL~a5EMZGVSS-Hj8>z9tSJ;B;@T>INn)w^h*kJAEQ@Y9&(q=j- zFsFct5DNz6xCa=wW4yV5w2+7Zi@BpKuz*ibYinrK zZG{g3+ROBQFJ3*Gw2$r(n7sW@!zG4B6M`0;-AT?^khs0Mi7T=HXq+L)JG142ClTD0 zy>jw&Jw-?{$6TkzN=vB+$dA5wBqZv@zVXoTo>Zlp>R`#Sk(Oly((Ddj8a5+Z&P(Ij zghVqgip#bfIaee>eGHIK1@vEU;%NSN&Qt&6)^?a+dHu0(6y^D_t@JMCnvu~7z3A6eyH(YS(7%5#=3OUY-uX@U8>8MMCcli!GcBMpiT&ZV1g=E#=a{n& zSl6W`Ph-HI-@RobnQ1O1R;mI@9^CX&A^Xb^JAe$5wG%W5lnw{zX zE`uf3M8%kGO+6n}-bFohJSC%+Ry zk)&5F9&T=vGc#5HE{jP?))IU)M^|Y)A6UQ-C#Qy+D-p>u2poX5Tvu1u*#D-08ZGza z!-o$CK}gR$7MI^e#ULd^``(v6>Ps6W+NjD%Vg&kkxP;a?_4Z2J(XIRIdy1rsxFIv1 z?)Pt+?Nq-xIf(!7wDZlRrD!S2s5JKI0! z%uDxgUR>hB7KI^!rBpTsp;F-;oCc2cD5rCHf$!~{@i%5kfi$*-O$rq=rROoeVG#Hc zO>}zTRF<_!RhH16vp%|*Q#gEW|0>HOkjRk^*5l0Qf%sn9<0;t-`f`#3 zeiE#YTaraHAL{00rxOkjzs2@^tv6Q^Z>P4$5L>=$jMbx!>lqHy*V6+va^4raaR~_< zF3r73tl;Y&FX%pK&1$s39EK^!3E z!id|2Cg3GFB=##<-^Tv$GGfe95%&DY&6i!cqS;B_tjrsk)H>`H3mSOUF7qFouWCJ$evo0HBDJUD?*WppiGwI8#TYg~(zFbl>GLHVI`Dz;b{A=sy@Gz_4LiLB4N<-cq=os4u z9s%`0R#MAa+>Ot2ZGc79-myzFxb}bcqGa+aDk?x37&+z17fA9uktsn@QDdwWX6Po! z;pUDhkt=a{rVtuIp?+au=#`=HENwp#j`6Ln&sy2MvM`Cg%z;2!LAji6aiO^IZij64 z=kLFlm#iGau^j*L+Q+zewD>bb-=cdfPMcO_m@%hE)c;hc%FTQi3Dp{oCdwh^7=nyB%|6t02&wwh&txN|AG*a9MdyXon zS`X*~Vjn2uQ0s-MCQb5F>8%qJZYEcIZ>6SW0~O=#?kO?K%i`eiP~Gm5rkABC>X?YP zD*j~=vl+@kXoOt&;i30;^PHTZfC+|wGu`6!26yo;5{syF;Nor|*Xy)on5r@!pCrp5 zBH>@XwLHk&)YeXh$AcDaAQS1xV`qCC+hD2Me&PH6i`SC-K&`Hl3Lgto&qlS+$=QuB zTZ)2-^mxrQhy?Y=5cT9n1c2w?SH!r{Vd>}N{5W_8oS3NHe?(ofMaTp$Haf0MzhYB( zU{xrdE$R#gt8?lg!1-<1;7D~gsse zuM0?Hp;siZtYJ!nIshYQL35IN+r!N8JJjm2zB8CPK|zxrmY)?xbANS2p0j~01Zu*Y zizTzI(-x#LTbuE-#ulqz)uMI+ugn<+L87sZx*4j{VCB_Acok zBp|6sy7DVg$qIO#KEP82WO<-#QPcHS$K^?H|G=Z4lx~zwLT=H$}%j%+b0A`k{H2;toP-Oq61vz$S6p>uqt; zy8Pj?iuYumVF2=+WYBcT9tSvth(h#xY5=vpPUQ{EVn)-RQ)4^-G(bx0!6XML<_6W= zRY_5djAo>fiDrZ;?|Ql5@<`UXRpqV-B2IqAoC=I1q*M%4Gi&xKHKH(g5A~9_6@F5s z6X)U^y)5c3D-U5*NHno1$A178lrPCJ-6-VKHAvuUyvUG=$@&BULpiglBK4GR20x@!5=U%5FTFzTCd8TjHmxCArdJhMc`t?PZR zk7?PM6B!?gGNhRb5+@k*#HimlE})33u7dkuZe7m#dUKqEqtp#hjY7~0+m?F&btWI_CVJ3*enaqdv;+QO zkgW|u+$=;DEj7051oWJ#vcVQEFq}BKf}Mo5!Rk zsDmD`09@Hw~DYW+y^~dLvc2@j6s{@(F zg(Ff?BVE&R%Q^}{k8-dp1ux|?+EIfToEXR;8~w+|Ur;qRzMx%W6!9i4DTxR>j3{ss zw1?W3{Y6lS{Q=*E3Gd5J8%8_H2X%+CmhKoZS1`9g5VB7wn)&~@0OBgK&UUf$pQ)6h z5W!$3*Y}d=#R=RY{F-qv{TB0&lfOfJ#ZcjOKiAU{ni=Rr5D@5y{GV9?ypm1c?b!p9 zq$j(0q-8C3&=pV5;HXkmTK5h$U4fgM)5}jVlx~aa6Rp^R_IIVzB4U_XdYC312Fuys zzJ&7I4Ck#o=%pqu>Yum@v&HA*f77z@QJ#_oET4bt&1OPD6X8P(*5MgyG8NoUpc6Rt zzcpr=Yw5X~ljPBR=lPmllzj}(+RpCY!Mv;x1&_MV##uyIjItzxmyC)&=yyZPJ805L zMO!wwVBif8lnJjnnVXw`Q3wQ&DT&>U3s@))3S&sF$#475l%z?lEG@l-GQSGzXDAn$ z^`ecxFaB3j`$rg*LNYW@a@$VxCh`z$@P=%)1Zl=%zeMMfx+RWw{)r- z-%HaCYnz^Fb2Lq6@Ak?^cu%r4ut@1^-nxQy^u!cd(S z%<2N=Sn5F*c`Q6LT!sq|_^?SNL-#gJ1&iaA3Y5Sj*YeB7XKpf@J>90##HU?wlKda0 z4W9HQwkS>1V^Is9c5^gMGb|S**6kNCUz;DVf_L9PWKKr03S*(VV~ypqB1NyGwTU|- zG|7le;xAgVD7_RZwg{ls@ObN3ixJ8+n6!$tGnAhG-)S}~ot&L|{a8_$I|U;&|1C3R z%M7XnviRW8kd3`fd;K{s?K7^{L1Osd9_Fh-AdLl*?;mJbYHaJU=~s zb+cGhaA$S-D)p53cTX!k$o0Dr#ayr?5c(LAoS68r-6(c|jxwI_*%?^7$f-J-6dD7D zv0Y6=8qQ0D6JHhCwCO1M=_)O0>uzHa7LrqUa{bj-`bMd=WV|s(x4>`_>1&StT_ng3 zNsgiUYD2jX&4vNYa;@_Ac7M`BB0e?t{SV*}l>CpL7PFHwy2?Hb-U8YG|J0wBFWSXq z?|zL6w_jugyf$p*cG%)nDs%Y8{WqGwwjqS{bf-w2A970aTrS-d=GLWB!K_O3TFYMt zT_DXSX#Xhrm>HFUsTw5nN7Y%e^$q@2#d2r{23%8h&1IRwP!&cu<={WRn2&2E(9ObP_ECkzs+F*&{F=Wkqio zNW@0~!erz@bLog0xmu=2ul+@1Pm$sw<=K*DeqBpZ&;MP(A7x+EdYkkW>n53cgQ^cQ zA;m<}|JlExERFm(Rp^vxzc|#O8zJYsZch16PC8@s(c?Dbx>|on^l@yntn%i1AwVVn z>_th1%eq|!UhIo+YETzU;N|bBR08QsF9puQga}dIugvKE+=TOtRU}9!EQZ^AyDA+ai#QLt)|D?{{9`r2^Lm{&7DG2>-1D2q8I8KP4QE zd4SUQar>jxW=u`A;93Y8q8b&R+$_KE1m~S)8^i8wD7&Zu&;d8(zygvCocH@ySzzxO z5h)kpibrHk7_Ju54P(x6Ozj zK#WQJQy04Wi-fbImt$4u$;SSU*thY+1=`EGN_E=uB9U}rJ=Rsc1^cNl88-Q{z|$Ni zZN74>H(maimiOV!NYzsRk>)zfXcuY}pEL z=$jprw2Y>0F@g6sK^;mcdcq-D5{8`Z@6rpA83NNX6}QD-%3=A)t|@+4;V_F|tZ{O+ zLLBk;QqK^ofcoo>Y?6^*6>VFC3TQu9Cu>(QsL|it{6qbDp?D%tKCQ&@N0(aGmMs{S zy6>RU@@sMw6UD_@XBajGGusG6jEl2&Y<6)G6kDi(zAplvVY3TH!HNL#yXVc4uf1aZ zzZeQm#-b+`^M=RIUZi>x#ZYuN8jp?V#V}vD?>BH6(0A*p0&jy#V*9)Mzizq<#yjgz zC53qBCs0COFARLF+0Rz1W{|NL=wy^5(GCTvF&X7j@fQQKve9_z)1fqssI?bKu9-i+ zMo-IYl=kb?&-|k-i(tCKW7Gu5%p}4j8M(Oe<$R~fUS6!D!&+N7 z3c73iMhvNkAv7F2UEu%GJn7$5r1ERbck#M@)0`GHkHwN}6bZ!*KO39xbwA-W~8yMl z{NL<9+u%EA_s5jq_FL`z5un7Z&X1)cLpZ|tP0iA{R4oGtMN+#QYkfw15Q@a17^ zi%luizNMk>^$n~Zc!4kS3!O7GNtT~0>EH5_^M zuvx7B^Bm2>(PaPjDtN9~SCaTHB}HMmf&uNu*T!qE{=?2t^5D;mPds-I1wSIvIzCt# zHG3gCdIPp5o<^6`2Ht5co;;;}4XKu6Gcm@0LtRFTEN;$;hCWEE+Gkrv+|Z!fsU=oZ zVBMD-fnhso>r?{H+aJ`V=Lp0;1!BGzySl_M!9)*1*2Smx^bh#0Yq|ZK-&0OC*~{qq z^Um)y&Yi{Pfv;XGJDgc^OB^-%u#B3G)bb#HGmZZ3#3*jL)2RY8s7Vikml*GH*U$T$dYW+Q{(NCJ zeyv`4VeR8h{@ZMZu9@^EJf=?bg*#)PO*X@hp*mZ6O)M8wf zfa6W=;w$p_s}Q;1c`*pG7187c3`H_t3D<)3=JlgglW7m)rElH0xGyI86A9*kTsv?U zDn(PXFW9hfAIeKp#hQE@MsI5IPMPh8{7{OkGj+7_dsv_lwK_(_LOR^Icj(Ol-dp@+rFUs5lVzFg+ zrU!p`#PswQAgXDI(KS)&+eUj<){4kX8XQW|sT>Q9lIqDvGOkzB9$Cq}1iKZc- zKaMMwiiQH?(TU?Ns>>zapBK%1jkdmyGFZbvI6>gZ+MyrqBB%9~zBB$HDUhh5q6%+eX~xH+9*qEAc#7SY z^9A-sPJhQjplB2{N7|h%@|&@U7*P+YoQZHZ(wh?U0^C-$0>k=2ntiddcuIbojj>BT zT_&?8W%nM^=gg?^AK#JbvSkOu_PH@?2=h(Hu`?-Yen*t+5}n(_4HIBXK0#@S56$$9 zAF@zh6TE%*6#h{9%4q%LFOt!_J|web_RN{Q z*tlnBIjs&p2cNu5v^xmRA(S|xKCJQTqlWe0<2yZQVF2MZa$q*!%fc8T7M|_2=f_^N zp>q2_;0JnEzSPLv!Ha4m3g&O*0$sA~;o3!fl461V02+prWW0R_^h=ss*wX1O_ZK;}3L^yH34rxR@lO<~sQOPc##BK_-nzY#p|^t0-cKngb<|0eGhJs5*oxvE z_hfc5m6ybZ-3`5d_YE!4xn|7N_N9Dt*f$JOdmZ;m*kFxcsPe^dT>Wi(m=O0SW^*MOM!~h8naud0fYN$)&O+EiQTwoT^o^QG6X*_*(dG zuSuR%7Lt$kGF-EDIB}X{nvX4~z&+>EY-_Ulq%l@8gX_3sZBHqkUii|t@cLBQ@J780 z&hHaFl;Fnxo(=KkZFY;bS~mk%I6Z!+l(UMD41Ykegatez#I^@U1HWnQK_J_rTd zyf}w)H}&13$+k@e_p@QTZgtI`!J^mLpVdR<(koDWl;sUE-|HFiicn6&hPc-JHhpoR znvrW%q(ows1ObC}z=UE-9u%JHO8xFj=Va2OvcdB%yzZZ}Is+8Atz1-297BcIKI)`X z1XEVb+Z{C?zkXF)9|*lb>*1p86JRe;i5nZAh*tc)nmz)F|*-ht%oUd?|6MmqL?=X zE*UlwnNhqrqzthCyA!dDR{h^}4#XzCbis#VlcvW5uV|})dLcYL&6W68;~^pNI8W9y z>j1EcJyORMJRO49je`|zdLRpEqXY>VH2Tw zmO%aE8sk`_HL+BZII^D))iWfQ$0?rieWE%t<#z?W2SZYG4cjPVuhc|hkbR%Zsk=?E z!XRyyppMb&Q&?Rj4@JAGcd%36Z*h!t9Gqjhn0AeHK|c-avgsB`V*|of0rb@hh8H+f zcVg%WMIkZu>VHncYfg{G8(pLq0O1kuq&RA_kim|3@zC`BX0{ zj{uo0kDna5Y!fYNU!-W;kF38RA6?((e$JLf$IdH|RjpTiyRKJ}u%FqOH5%VE2r4A6 zXvnFTcJZ7<&5v7TYFftV5}9-gnx-+YHBx#)%!T_E;dBTh;GXmJ(ZpWD*2d-`UvsWm zVW#0=Iyv+EvkLC@!9*qvh9_rQ<5BM9OXyH@sd>|ZqOFZ#n>-wjFxBPV{DtXL;4a_Q zS!OM=DNM61X+$G`XPEpP5Wa%2{k0AOh_FEnj`0)K!s`z7k?*j)2zJM@Nz&jGCRHt5 za6Kt3Iz5Hu(MsPjV$=|XWan4BiH;2rL}3I#fxBpbrb1woYy-$V4p*3_`Q z!Dhfb;v^L+Cg)2Ecr{_{#erY2}NRP?(85a)9wID zOHxp``JiNW@n?gl$d6BmM~9h-iCd2PRne!9mOm5!Sb_4j$8_hV7WYW4=sdTOkmPBV zQr8wturs#!=Z@*a81Toa1{>usM4bPCiA+K~L~Nasura1 z`#JmVn<~AYUOG)fx9Tyu*&qKDdYN2x;9qG$ja64ZXNXq2z!!e@aX2Ym=pf}m;ovk< z_URikE{@%}BpeYNd^!6ZU895HXtoJ842*#gx$_pRyZZ&{c&=BU_2fJcui+3=gtse8V&mS6S0Lc=Xm5r-#v{|L<=JMyU2Ai> z`FQYhGn*1oScIl2fcax*F}R~!ng!$AqufuAbI*fP+$YIYVLsutPUi~Ds*(*yf&PiXN;Q<)y zXvQoAW-9vJx3!2TWh5gc{+1pLx3jG`E#5*!mx#HofF9&-&`cx&wl>j-4=@HplBXLy z%oRw7;4Xg7Gl%UFK~CVm4%=n|;&;M2OiwgfwsXu*urF72`PW5^^=Gd=s3U#ID*gqM zPlO~1p;Be+-|K`6szY^}EaFVL;UOP{<}W+-nZ6?Ma_CS#61-LS=2C>y3p4lVQV4mu zy9Uu1j>j<{%W}BJuYWZ|9K8>=qz|OiVp{?IU|D|D`fsQzh_u{A|LmhFdp8v^7NZi9 zh8P}xdX}amFzsLgsE$}7D50D*oY61Uz)n(+1XB_$*fybUZQSPi806hk-XB}IzX@LU zOFd)ZE9Ap}FNr~ji(X$(t4Bi~KXPS_zB<4Y^HBiC@6;#cwaa97PSvofSqV&krJoLw zTWfi}^y^L98-nkj0Q#ffS}emQUuW3G+jUKu_${I@vCc^F zQYgIcP2m?Rm7