///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015- Statoil ASA // Copyright (C) 2015- 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 "RigCaseToCaseCellMapper.h" #include "RigCaseToCaseCellMapperTools.h" #include "RigFemPart.h" #include "RigFemPartGrid.h" #include "RigMainGrid.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigCaseToCaseCellMapper::RigCaseToCaseCellMapper( RigMainGrid* masterEclGrid, RigMainGrid* dependentEclGrid ) : m_masterGrid( masterEclGrid ) , m_dependentGrid( dependentEclGrid ) , m_masterFemPart( nullptr ) , m_dependentFemPart( nullptr ) { m_masterCellOrIntervalIndex.resize( dependentEclGrid->globalCellArray().size(), cvf::UNDEFINED_INT ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigCaseToCaseCellMapper::RigCaseToCaseCellMapper( RigFemPart* masterFemPart, RigMainGrid* dependentEclGrid ) : m_masterGrid( nullptr ) , m_dependentGrid( dependentEclGrid ) , m_masterFemPart( masterFemPart ) , m_dependentFemPart( nullptr ) { m_masterCellOrIntervalIndex.resize( dependentEclGrid->globalCellArray().size(), cvf::UNDEFINED_INT ); this->calculateEclToGeomCellMapping( dependentEclGrid, masterFemPart, false ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigCaseToCaseCellMapper::RigCaseToCaseCellMapper( RigFemPart* masterFemPart, RigFemPart* dependentFemPart ) : m_masterGrid( nullptr ) , m_dependentGrid( nullptr ) , m_masterFemPart( masterFemPart ) , m_dependentFemPart( dependentFemPart ) { m_masterCellOrIntervalIndex.resize( dependentFemPart->elementCount(), cvf::UNDEFINED_INT ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigCaseToCaseCellMapper::RigCaseToCaseCellMapper( RigMainGrid* masterEclGrid, RigFemPart* dependentFemPart ) : m_masterGrid( masterEclGrid ) , m_dependentGrid( nullptr ) , m_masterFemPart( dependentFemPart ) , m_dependentFemPart( nullptr ) { m_masterCellOrIntervalIndex.resize( dependentFemPart->elementCount(), cvf::UNDEFINED_INT ); this->calculateEclToGeomCellMapping( masterEclGrid, dependentFemPart, true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const int* RigCaseToCaseCellMapper::masterCaseCellIndices( int dependentCaseReservoirCellIndex, int* masterCaseCellIndexCount ) const { int seriesIndex = m_masterCellOrIntervalIndex[dependentCaseReservoirCellIndex]; if ( seriesIndex == cvf::UNDEFINED_INT ) { ( *masterCaseCellIndexCount ) = 0; return nullptr; } if ( seriesIndex < 0 ) { ( *masterCaseCellIndexCount ) = static_cast( m_masterCellIndexSeries[-seriesIndex].size() ); return &( m_masterCellIndexSeries[-seriesIndex][0] ); } else { ( *masterCaseCellIndexCount ) = 1; return &( m_masterCellOrIntervalIndex[dependentCaseReservoirCellIndex] ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigCaseToCaseCellMapper::addMapping( int depCaseCellIdx, int masterCaseMatchingCell ) { int mcOrSeriesIdx = m_masterCellOrIntervalIndex[depCaseCellIdx]; if ( mcOrSeriesIdx == cvf::UNDEFINED_INT ) { m_masterCellOrIntervalIndex[depCaseCellIdx] = masterCaseMatchingCell; } else if ( mcOrSeriesIdx >= 0 ) { int newSeriesIdx = static_cast( m_masterCellIndexSeries.size() ); m_masterCellIndexSeries.push_back( std::vector() ); m_masterCellIndexSeries.back().push_back( mcOrSeriesIdx ); m_masterCellIndexSeries.back().push_back( masterCaseMatchingCell ); m_masterCellOrIntervalIndex[depCaseCellIdx] = -newSeriesIdx; } else { m_masterCellIndexSeries[-mcOrSeriesIdx].push_back( masterCaseMatchingCell ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RigCaseToCaseCellMapper::calculateEclToGeomCellMapping( RigMainGrid* masterEclGrid, RigFemPart* dependentFemPart, bool eclipseIsMaster ) { // Find tolerance double cellSizeI, cellSizeJ, cellSizeK; masterEclGrid->characteristicCellSizes( &cellSizeI, &cellSizeJ, &cellSizeK ); double xyTolerance = cellSizeI * 0.4; double zTolerance = cellSizeK * 0.4; bool isEclFaceNormalsOutwards = masterEclGrid->isFaceNormalsOutwards(); cvf::Vec3d elmCorners[8]; size_t cellCount = masterEclGrid->cellCount(); for ( size_t cellIdx = 0; cellIdx < cellCount; ++cellIdx ) { #ifdef _DEBUG { // For debugging size_t i, j, k; masterEclGrid->ijkFromCellIndex( cellIdx, &i, &j, &k ); // Will not work when LGR present } #endif cvf::Vec3d geoMechConvertedEclCell[8]; RigCaseToCaseCellMapperTools::estimatedFemCellFromEclCell( masterEclGrid, cellIdx, geoMechConvertedEclCell ); cvf::BoundingBox elmBBox; for ( int i = 0; i < 8; ++i ) elmBBox.add( geoMechConvertedEclCell[i] ); std::vector closeElements; dependentFemPart->findIntersectingCells( elmBBox, &closeElements ); for ( size_t ccIdx = 0; ccIdx < closeElements.size(); ++ccIdx ) { int elmIdx = static_cast( closeElements[ccIdx] ); RigCaseToCaseCellMapperTools::elementCorners( dependentFemPart, elmIdx, elmCorners ); RigCaseToCaseCellMapperTools::rotateCellTopologicallyToMatchBaseCell( geoMechConvertedEclCell, isEclFaceNormalsOutwards, elmCorners ); bool isMatching = RigCaseToCaseCellMapperTools::isEclFemCellsMatching( geoMechConvertedEclCell, elmCorners, xyTolerance, zTolerance ); if ( isMatching ) { if ( eclipseIsMaster ) addMapping( elmIdx, static_cast( cellIdx ) ); else addMapping( static_cast( cellIdx ), elmIdx ); break; } } } }