mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 22:50:25 -05:00
Migrate all assert macros in ApplicationLibCode to CAF_ASSERT and remove every use of cvfAssert.h. CVF_ASSERT is replaced one to one. CVF_TIGHT_ASSERT is also replaced by CAF_ASSERT, which is semantically exact: CVF_ENABLE_TIGHT_ASSERTS is 1 only under _DEBUG, and that is what CAF_ASSERT now does. The two CVF_FAIL_MSG sites become CAF_ASSERT( false && "message" ), preserving the message with the idiom already used elsewhere in the code base. Counts before and after: CVF_ASSERT 1044 to 0, CVF_TIGHT_ASSERT 66 to 0, CVF_FAIL_MSG 2 to 0, cvfAssert.h references 154 to 0. Include handling: files that included cvfAssert.h directly now include cafAssert.h instead, includes left dead by the migration are removed, and files that were relying on cvfAssert.h transitively get an explicit cafAssert.h. Files that reach cafAssert.h through another caf header are left unchanged; a missing include here is a compile error, not a silently disabled assert. ResultStatisticsCache links only LibCore and therefore had no path to cafAssert.h. Add the cafPdmCore directory as a private include path rather than linking the library, since cafAssert.h is header only. Note that this stops these asserts from firing in Release and RelWithDebInfo, where CVF_ASSERT was previously active.
905 lines
34 KiB
C++
905 lines
34 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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
|
|
// 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 <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RigEclipseCaseData.h"
|
|
|
|
#include "RifReaderEclipseOutput.h"
|
|
|
|
#include "RigActiveCellInfo.h"
|
|
#include "RigCaseCellResultsData.h"
|
|
#include "RigEclipseResultAddress.h"
|
|
#include "RigEquil.h"
|
|
#include "RigFormationNames.h"
|
|
#include "RigMainGrid.h"
|
|
#include "RigResultAccessorFactory.h"
|
|
#include "RigVirtualPerforationTransmissibilities.h"
|
|
#include "Well/RigSimWellData.h"
|
|
#include "Well/RigSimulationWellCenterLineCalculator.h"
|
|
#include "Well/RigSimulationWellCoordsAndMD.h"
|
|
#include "Well/RigWellPath.h"
|
|
#include "Well/RigWellResultFrame.h"
|
|
#include "Well/RigWellResultPoint.h"
|
|
|
|
#include "cafAssert.h"
|
|
|
|
#include <QDebug>
|
|
|
|
#include <array>
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigEclipseCaseData::RigEclipseCaseData( RimEclipseCase* ownerCase )
|
|
: m_hasParsedDeckForEquilData( false )
|
|
{
|
|
m_mainGrid = new RigMainGrid();
|
|
m_ownerCase = ownerCase;
|
|
|
|
m_matrixModelResults = new RigCaseCellResultsData( this, RiaDefines::PorosityModelType::MATRIX_MODEL );
|
|
m_fractureModelResults = new RigCaseCellResultsData( this, RiaDefines::PorosityModelType::FRACTURE_MODEL );
|
|
|
|
m_activeCellInfo = new RigActiveCellInfo;
|
|
m_fractureActiveCellInfo = new RigActiveCellInfo;
|
|
|
|
m_matrixModelResults->setActiveCellInfo( m_activeCellInfo.p() );
|
|
m_fractureModelResults->setActiveCellInfo( m_fractureActiveCellInfo.p() );
|
|
|
|
m_unitsType = RiaDefines::EclipseUnitSystem::UNITS_METRIC;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigEclipseCaseData::~RigEclipseCaseData()
|
|
{
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigMainGrid* RigEclipseCaseData::mainGrid()
|
|
{
|
|
return m_mainGrid.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigMainGrid* RigEclipseCaseData::mainGrid() const
|
|
{
|
|
return m_mainGrid.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setMainGrid( RigMainGrid* mainGrid )
|
|
{
|
|
m_mainGrid = mainGrid;
|
|
|
|
m_matrixModelResults->setMainGrid( m_mainGrid.p() );
|
|
m_fractureModelResults->setMainGrid( m_mainGrid.p() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::allGrids( std::vector<RigGridBase*>* grids )
|
|
{
|
|
CAF_ASSERT( grids );
|
|
|
|
if ( m_mainGrid.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
size_t i;
|
|
for ( i = 0; i < m_mainGrid->gridCount(); i++ )
|
|
{
|
|
grids->push_back( m_mainGrid->gridByIndex( i ) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::allGrids( std::vector<const RigGridBase*>* grids ) const
|
|
{
|
|
CAF_ASSERT( grids );
|
|
|
|
if ( m_mainGrid.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
size_t i;
|
|
for ( i = 0; i < m_mainGrid->gridCount(); i++ )
|
|
{
|
|
grids->push_back( m_mainGrid->gridByIndex( i ) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Get grid by index. The main grid has index 0, so the first lgr has index 1
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigGridBase* RigEclipseCaseData::grid( size_t index ) const
|
|
{
|
|
CAF_ASSERT( m_mainGrid.notNull() );
|
|
return m_mainGrid->gridByIndex( index );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Get grid by index. The main grid has index 0, so the first lgr has index 1
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigGridBase* RigEclipseCaseData::grid( size_t index )
|
|
{
|
|
CAF_ASSERT( m_mainGrid.notNull() );
|
|
return m_mainGrid->gridByIndex( index );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigGridBase* RigEclipseCaseData::grid( const QString& gridName ) const
|
|
{
|
|
if ( m_mainGrid.isNull() )
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if ( gridName.isEmpty() )
|
|
{
|
|
return m_mainGrid.p();
|
|
}
|
|
|
|
size_t i;
|
|
for ( i = 0; i < m_mainGrid->gridCount(); i++ )
|
|
{
|
|
const RigGridBase* grid = m_mainGrid->gridByIndex( i );
|
|
if ( QString::fromStdString( grid->gridName() ) == gridName ) return grid;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
size_t RigEclipseCaseData::gridCount() const
|
|
{
|
|
CAF_ASSERT( m_mainGrid.notNull() );
|
|
return m_mainGrid->gridCount();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// The cached well cell arrays are indexed by grid cell index, and are only valid as long as they
|
|
/// have one array per grid sized to match the cell count of that grid.
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RigEclipseCaseData::isWellCellsPrGridUpToDate( const std::vector<RigGridBase*>& grids ) const
|
|
{
|
|
if ( m_wellCellsInGrid.size() != grids.size() ) return false;
|
|
|
|
for ( size_t gIdx = 0; gIdx < grids.size(); ++gIdx )
|
|
{
|
|
if ( m_wellCellsInGrid[gIdx].isNull() || m_wellCellsInGrid[gIdx]->size() != grids[gIdx]->cellCount() ) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeWellCellsPrGrid()
|
|
{
|
|
std::vector<RigGridBase*> grids;
|
|
allGrids( &grids );
|
|
|
|
// If we have computed this already for the current set of grids, return. The cached arrays are indexed by grid
|
|
// cell index, and must be recomputed if the grids have changed after the previous computation.
|
|
if ( isWellCellsPrGridUpToDate( grids ) ) return;
|
|
|
|
// Debug code used to display grid names and grid sizes
|
|
/*
|
|
size_t totCellCount = 0;
|
|
for (auto g : grids)
|
|
{
|
|
qDebug() << g->gridName().data();
|
|
qDebug() << g->cellCountI() << " " << g->cellCountJ() << " " << g->cellCountK() << " ";
|
|
|
|
size_t cellCount = g->cellCount();
|
|
totCellCount += cellCount;
|
|
qDebug() << cellCount;
|
|
|
|
qDebug() << "\n";
|
|
}
|
|
|
|
qDebug() << "\nTotal cell count " << totCellCount;
|
|
*/
|
|
|
|
size_t gIdx;
|
|
|
|
// Allocate and initialize the arrays
|
|
|
|
m_wellCellsInGrid.resize( grids.size() );
|
|
m_gridCellToResultWellIndex.resize( grids.size() );
|
|
|
|
for ( gIdx = 0; gIdx < grids.size(); ++gIdx )
|
|
{
|
|
if ( m_wellCellsInGrid[gIdx].isNull() || m_wellCellsInGrid[gIdx]->size() != grids[gIdx]->cellCount() )
|
|
{
|
|
m_wellCellsInGrid[gIdx] = new cvf::UByteArray;
|
|
m_wellCellsInGrid[gIdx]->resize( grids[gIdx]->cellCount() );
|
|
|
|
m_gridCellToResultWellIndex[gIdx] = new cvf::UIntArray;
|
|
m_gridCellToResultWellIndex[gIdx]->resize( grids[gIdx]->cellCount() );
|
|
}
|
|
m_wellCellsInGrid[gIdx]->setAll( false );
|
|
m_gridCellToResultWellIndex[gIdx]->setAll( cvf::UNDEFINED_UINT );
|
|
}
|
|
|
|
// Fill arrays with data
|
|
size_t wIdx;
|
|
for ( wIdx = 0; wIdx < m_simWellData.size(); ++wIdx )
|
|
{
|
|
size_t tIdx;
|
|
for ( tIdx = 0; tIdx < m_simWellData[wIdx]->m_wellCellsTimeSteps.size(); ++tIdx )
|
|
{
|
|
RigWellResultFrame& wellCells = m_simWellData[wIdx]->m_wellCellsTimeSteps[tIdx];
|
|
|
|
// Well result branches
|
|
for ( const auto& wellSegment : wellCells.wellResultBranches() )
|
|
{
|
|
for ( const auto& resultPoint : wellSegment.branchResultPoints() )
|
|
{
|
|
size_t gridIndex = resultPoint.gridIndex();
|
|
size_t gridCellIndex = resultPoint.cellIndex();
|
|
if ( gridIndex < m_wellCellsInGrid.size() && gridCellIndex < m_wellCellsInGrid[gridIndex]->size() )
|
|
{
|
|
// NOTE : We do not check if the grid cell is active as we do for well head.
|
|
// If we add test for active cell, thorough testing and verification of the new behavior must
|
|
// be addressed
|
|
m_wellCellsInGrid[gridIndex]->set( gridCellIndex, true );
|
|
m_gridCellToResultWellIndex[gridIndex]->set( gridCellIndex, static_cast<cvf::uint>( wIdx ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setSimWellData( const cvf::Collection<RigSimWellData>& data )
|
|
{
|
|
m_simWellData = data;
|
|
m_wellCellsInGrid.clear();
|
|
m_gridCellToResultWellIndex.clear();
|
|
|
|
computeWellCellsPrGrid();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<QString> RigEclipseCaseData::findSortedWellNames() const
|
|
{
|
|
std::set<QString> sortedWellNames;
|
|
|
|
const cvf::Collection<RigSimWellData>& simWellData = wellResults();
|
|
|
|
for ( size_t wIdx = 0; wIdx < simWellData.size(); ++wIdx )
|
|
{
|
|
sortedWellNames.insert( simWellData[wIdx]->m_wellName );
|
|
}
|
|
|
|
return sortedWellNames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigSimWellData* RigEclipseCaseData::findSimWellData( QString wellName ) const
|
|
{
|
|
for ( size_t wIdx = 0; wIdx < m_simWellData.size(); ++wIdx )
|
|
{
|
|
if ( m_simWellData[wIdx]->m_wellName == wellName )
|
|
{
|
|
return m_simWellData[wIdx].p();
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const cvf::UByteArray* RigEclipseCaseData::wellCellsInGrid( size_t gridIndex )
|
|
{
|
|
computeWellCellsPrGrid();
|
|
CAF_ASSERT( gridIndex < m_wellCellsInGrid.size() );
|
|
|
|
return m_wellCellsInGrid[gridIndex].p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const cvf::UIntArray* RigEclipseCaseData::gridCellToResultWellIndex( size_t gridIndex )
|
|
{
|
|
computeWellCellsPrGrid();
|
|
CAF_ASSERT( gridIndex < m_gridCellToResultWellIndex.size() );
|
|
|
|
return m_gridCellToResultWellIndex[gridIndex].p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigCell& RigEclipseCaseData::cellFromWellResultCell( const RigWellResultPoint& wellResultPoint ) const
|
|
{
|
|
CAF_ASSERT( wellResultPoint.isCell() );
|
|
|
|
size_t gridIndex = wellResultPoint.gridIndex();
|
|
size_t gridCellIndex = wellResultPoint.cellIndex();
|
|
|
|
std::vector<const RigGridBase*> grids;
|
|
allGrids( &grids );
|
|
|
|
return grids[gridIndex]->cell( gridCellIndex );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RigEclipseCaseData::findSharedSourceFace( cvf::StructGridInterface::FaceType& sharedSourceFace,
|
|
const RigWellResultPoint& sourceWellCellResult,
|
|
const RigWellResultPoint& otherWellCellResult ) const
|
|
{
|
|
size_t gridIndex = sourceWellCellResult.gridIndex();
|
|
size_t gridCellIndex = sourceWellCellResult.cellIndex();
|
|
|
|
size_t otherGridIndex = otherWellCellResult.gridIndex();
|
|
size_t otherGridCellIndex = otherWellCellResult.cellIndex();
|
|
|
|
if ( gridIndex != otherGridIndex ) return false;
|
|
|
|
std::vector<const RigGridBase*> grids;
|
|
allGrids( &grids );
|
|
|
|
const RigGridBase* grid = grids[gridIndex];
|
|
size_t i, j, k;
|
|
grid->ijkFromCellIndex( gridCellIndex, &i, &j, &k );
|
|
|
|
size_t faceIdx;
|
|
for ( faceIdx = 0; faceIdx < 6; faceIdx++ )
|
|
{
|
|
cvf::StructGridInterface::FaceType sourceFace = static_cast<cvf::StructGridInterface::FaceType>( faceIdx );
|
|
|
|
size_t ni, nj, nk;
|
|
RigGridBase::neighborIJKAtCellFace( i, j, k, sourceFace, &ni, &nj, &nk );
|
|
|
|
if ( grid->isCellValid( ni, nj, nk ) )
|
|
{
|
|
size_t neighborCellIndex = grid->cellIndexFromIJK( ni, nj, nk );
|
|
|
|
if ( neighborCellIndex == otherGridCellIndex )
|
|
{
|
|
sharedSourceFace = sourceFace;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Helper class used to find min/max range for valid and active cells
|
|
//--------------------------------------------------------------------------------------------------
|
|
class CellRangeBB
|
|
{
|
|
public:
|
|
CellRangeBB()
|
|
: m_min( cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T )
|
|
, m_max( 0, 0, 0 )
|
|
{
|
|
}
|
|
|
|
void add( size_t i, size_t j, size_t k )
|
|
{
|
|
if ( i < m_min.x() ) m_min.x() = i;
|
|
if ( j < m_min.y() ) m_min.y() = j;
|
|
if ( k < m_min.z() ) m_min.z() = k;
|
|
|
|
if ( i > m_max.x() ) m_max.x() = i;
|
|
if ( j > m_max.y() ) m_max.y() = j;
|
|
if ( k > m_max.z() ) m_max.z() = k;
|
|
}
|
|
|
|
public:
|
|
caf::VecIjk0 m_min;
|
|
caf::VecIjk0 m_max;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeActiveCellIJKBBox()
|
|
{
|
|
if ( m_mainGrid.notNull() && m_activeCellInfo.notNull() && m_fractureActiveCellInfo.notNull() )
|
|
{
|
|
CellRangeBB matrixModelActiveBB;
|
|
CellRangeBB fractureModelActiveBB;
|
|
|
|
for ( size_t idx = 0; idx < m_mainGrid->cellCount(); idx++ )
|
|
{
|
|
size_t i, j, k;
|
|
m_mainGrid->ijkFromCellIndex( idx, &i, &j, &k );
|
|
|
|
if ( !m_mainGrid->isCellValid( i, j, k ) ) continue;
|
|
|
|
if ( m_activeCellInfo->isActive( ReservoirCellIndex( idx ) ) )
|
|
{
|
|
matrixModelActiveBB.add( i, j, k );
|
|
}
|
|
|
|
if ( m_fractureActiveCellInfo->isActive( ReservoirCellIndex( idx ) ) )
|
|
{
|
|
fractureModelActiveBB.add( i, j, k );
|
|
}
|
|
}
|
|
m_activeCellInfo->setIjkBoundingBox( RigBoundingBoxIjk<caf::VecIjk0>( matrixModelActiveBB.m_min, matrixModelActiveBB.m_max ) );
|
|
m_fractureActiveCellInfo->setIjkBoundingBox(
|
|
RigBoundingBoxIjk<caf::VecIjk0>( fractureModelActiveBB.m_min, fractureModelActiveBB.m_max ) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeActiveCellBoundingBoxes( bool useOptimizedVersion )
|
|
{
|
|
computeActiveCellIJKBBox();
|
|
|
|
if ( useOptimizedVersion )
|
|
computeActiveCellsGeometryBoundingBoxOptimized();
|
|
else
|
|
computeActiveCellsGeometryBoundingBoxSlow();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeDepthRelatedResults()
|
|
{
|
|
RigCaseCellResultsData::computeDepthRelatedResults( m_matrixModelResults.p(), m_fractureModelResults.p() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<QString> RigEclipseCaseData::simulationWellNames() const
|
|
{
|
|
std::vector<QString> wellNames;
|
|
for ( const auto& wellResult : wellResults() )
|
|
{
|
|
wellNames.push_back( wellResult->m_wellName );
|
|
}
|
|
return wellNames;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RigEclipseCaseData::hasSimulationWell( const QString& simWellName ) const
|
|
{
|
|
const auto wellNames = simulationWellNames();
|
|
return std::find( wellNames.begin(), wellNames.end(), simWellName ) != wellNames.end();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<const RigWellPath*>
|
|
RigEclipseCaseData::simulationWellBranches( const QString& simWellName, bool includeAllCellCenters, bool useAutoDetectionOfBranches ) const
|
|
{
|
|
std::vector<const RigWellPath*> branches;
|
|
|
|
if ( simWellName.isEmpty() || simWellName.toUpper() == "NONE" )
|
|
{
|
|
return branches;
|
|
}
|
|
|
|
const RigSimWellData* simWellData = findSimWellData( simWellName );
|
|
if ( !simWellData ) return branches;
|
|
|
|
std::tuple<QString, bool, bool> simWellSeachItem = std::make_tuple( simWellName, includeAllCellCenters, useAutoDetectionOfBranches );
|
|
|
|
if ( m_simWellBranchCache.find( simWellSeachItem ) == m_simWellBranchCache.end() )
|
|
{
|
|
const auto simWellBranches = RigSimulationWellCenterLineCalculator::calculateWellPipeCenterlineForTimeStep( this,
|
|
simWellData,
|
|
-1,
|
|
useAutoDetectionOfBranches,
|
|
includeAllCellCenters );
|
|
|
|
m_simWellBranchCache.insert( std::make_pair( simWellSeachItem, cvf::Collection<RigWellPath>() ) );
|
|
|
|
for ( const auto& [coords, wellCells] : simWellBranches )
|
|
{
|
|
auto wellMdCalculator = RigSimulationWellCoordsAndMD( coords );
|
|
|
|
cvf::ref<RigWellPath> newWellPath = new RigWellPath( wellMdCalculator.wellPathPoints(), wellMdCalculator.measuredDepths() );
|
|
|
|
m_simWellBranchCache[simWellSeachItem].push_back( newWellPath.p() );
|
|
}
|
|
}
|
|
|
|
for ( const auto& branch : m_simWellBranchCache[simWellSeachItem] )
|
|
{
|
|
branches.push_back( branch.p() );
|
|
}
|
|
|
|
return branches;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setVirtualPerforationTransmissibilities( RigVirtualPerforationTransmissibilities* virtualPerforationTransmissibilities )
|
|
{
|
|
m_virtualPerforationTransmissibilities = virtualPerforationTransmissibilities;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigVirtualPerforationTransmissibilities* RigEclipseCaseData::virtualPerforationTransmissibilities() const
|
|
{
|
|
return m_virtualPerforationTransmissibilities.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::ensureDeckIsParsedForEquilData( const QString& dataDeckFile, const QString& includeFileAbsolutePathPrefix )
|
|
{
|
|
if ( !m_hasParsedDeckForEquilData )
|
|
{
|
|
RifReaderEclipseOutput::importEquilData( dataDeckFile, includeFileAbsolutePathPrefix, this );
|
|
|
|
m_hasParsedDeckForEquilData = true;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RigEquil> RigEclipseCaseData::equilData() const
|
|
{
|
|
return m_equil;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setEquilData( const std::vector<RigEquil>& equilObjects )
|
|
{
|
|
m_equil = equilObjects;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigActiveCellInfo* RigEclipseCaseData::activeCellInfo( RiaDefines::PorosityModelType porosityModel )
|
|
{
|
|
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL )
|
|
{
|
|
return m_activeCellInfo.p();
|
|
}
|
|
|
|
return m_fractureActiveCellInfo.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigActiveCellInfo* RigEclipseCaseData::activeCellInfo( RiaDefines::PorosityModelType porosityModel ) const
|
|
{
|
|
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL )
|
|
{
|
|
return m_activeCellInfo.p();
|
|
}
|
|
|
|
return m_fractureActiveCellInfo.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setActiveCellInfo( RiaDefines::PorosityModelType porosityModel, RigActiveCellInfo* activeCellInfo )
|
|
{
|
|
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL )
|
|
{
|
|
m_activeCellInfo = activeCellInfo;
|
|
m_matrixModelResults->setActiveCellInfo( m_activeCellInfo.p() );
|
|
}
|
|
else
|
|
{
|
|
m_fractureActiveCellInfo = activeCellInfo;
|
|
m_fractureModelResults->setActiveCellInfo( m_fractureActiveCellInfo.p() );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RigEclipseCaseData::hasFractureResults() const
|
|
{
|
|
return activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL ) &&
|
|
activeCellInfo( RiaDefines::PorosityModelType::FRACTURE_MODEL )->reservoirActiveCellCount() > 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeActiveCellsGeometryBoundingBoxSlow()
|
|
{
|
|
if ( m_activeCellInfo.isNull() || m_fractureActiveCellInfo.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( m_mainGrid.isNull() )
|
|
{
|
|
cvf::BoundingBox bb;
|
|
m_activeCellInfo->setGeometryBoundingBox( bb );
|
|
m_fractureActiveCellInfo->setGeometryBoundingBox( bb );
|
|
return;
|
|
}
|
|
|
|
RigActiveCellInfo* activeInfos[2];
|
|
activeInfos[0] = m_fractureActiveCellInfo.p();
|
|
activeInfos[1] = m_activeCellInfo.p(); // Last, to make this bb.min become display offset
|
|
|
|
cvf::BoundingBox bb;
|
|
for ( int acIdx = 0; acIdx < 2; ++acIdx )
|
|
{
|
|
bb.reset();
|
|
if ( m_mainGrid->nodes().empty() )
|
|
{
|
|
bb.add( cvf::Vec3d::ZERO );
|
|
}
|
|
else
|
|
{
|
|
for ( size_t i = 0; i < m_mainGrid->cellCount(); i++ )
|
|
{
|
|
if ( activeInfos[acIdx]->isActive( ReservoirCellIndex( i ) ) )
|
|
{
|
|
std::array<cvf::Vec3d, 8> hexCorners = m_mainGrid->cellCornerVertices( i );
|
|
for ( const auto& corner : hexCorners )
|
|
{
|
|
bb.add( corner );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
activeInfos[acIdx]->setGeometryBoundingBox( bb );
|
|
}
|
|
|
|
// This design choice is unfortunate, as the bounding box of active cells can be computed in different ways.
|
|
// Must keep the code to make sure existing projects display 3D model at the same location in the scene.
|
|
m_mainGrid->setDisplayModelOffset( bb.min() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::computeActiveCellsGeometryBoundingBoxOptimized()
|
|
{
|
|
if ( m_activeCellInfo.isNull() || m_fractureActiveCellInfo.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( m_mainGrid.isNull() )
|
|
{
|
|
cvf::BoundingBox bb;
|
|
m_activeCellInfo->setGeometryBoundingBox( bb );
|
|
m_fractureActiveCellInfo->setGeometryBoundingBox( bb );
|
|
return;
|
|
}
|
|
|
|
RigActiveCellInfo* activeInfos[2];
|
|
activeInfos[0] = m_fractureActiveCellInfo.p();
|
|
activeInfos[1] = m_activeCellInfo.p();
|
|
|
|
cvf::BoundingBox bb;
|
|
for ( int acIdx = 0; acIdx < 2; ++acIdx )
|
|
{
|
|
bb.reset();
|
|
if ( m_mainGrid->nodes().empty() )
|
|
{
|
|
bb.add( cvf::Vec3d::ZERO );
|
|
}
|
|
else
|
|
{
|
|
// Use the top and bottom layer of active cells to compute the bounding box
|
|
|
|
const auto& bbox = activeInfos[acIdx]->ijkBoundingBox();
|
|
const auto& minBB = bbox.min();
|
|
const auto& maxBB = bbox.max();
|
|
|
|
for ( auto k : { minBB.z(), maxBB.z() } )
|
|
{
|
|
for ( size_t i = minBB.x(); i <= maxBB.x(); i++ )
|
|
{
|
|
for ( size_t j = minBB.y(); j <= maxBB.y(); j++ )
|
|
{
|
|
if ( m_mainGrid->isCellValid( i, j, k ) )
|
|
{
|
|
size_t cellIndex = m_mainGrid->cellIndexFromIJK( i, j, k );
|
|
|
|
std::array<cvf::Vec3d, 8> hexCorners = m_mainGrid->cellCornerVertices( cellIndex );
|
|
for ( const auto& corner : hexCorners )
|
|
{
|
|
bb.add( corner );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_mainGrid->totalTemporaryGridCellCount() > 0 )
|
|
{
|
|
// When we have LGRs for radial grids, we must loop over all local grids. The local grids can contain coordinates not present
|
|
// in the main grid
|
|
|
|
for ( size_t i = 0; i < m_mainGrid->gridCount(); i++ )
|
|
{
|
|
auto localGrid = m_mainGrid->gridByIndex( i );
|
|
for ( size_t localCellIndex = 0; localCellIndex < localGrid->cellCount(); localCellIndex++ )
|
|
{
|
|
size_t globalCellIndex = localGrid->reservoirCellIndex( localCellIndex );
|
|
|
|
if ( globalCellIndex < activeInfos[acIdx]->reservoirCellCount() &&
|
|
activeInfos[acIdx]->isActive( ReservoirCellIndex( globalCellIndex ) ) )
|
|
{
|
|
std::array<cvf::Vec3d, 8> hexCorners = localGrid->cellCornerVertices( localCellIndex );
|
|
for ( const auto& corner : hexCorners )
|
|
{
|
|
bb.add( corner );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
activeInfos[acIdx]->setGeometryBoundingBox( bb );
|
|
}
|
|
|
|
auto bbMainGrid = m_mainGrid->boundingBox();
|
|
|
|
// Use center of bounding box as display offset. This point will be stable and independent of the active cell bounding box.
|
|
m_mainGrid->setDisplayModelOffset( bbMainGrid.center() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setActiveFormationNames( const RigFormationNames* activeFormationNames )
|
|
{
|
|
m_matrixModelResults->setActiveFormationNames( activeFormationNames );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigFormationNames* RigEclipseCaseData::activeFormationNames() const
|
|
{
|
|
return m_matrixModelResults->activeFormationNames();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<QString> RigEclipseCaseData::formationNames() const
|
|
{
|
|
if ( activeFormationNames() )
|
|
{
|
|
return activeFormationNames()->formationNames();
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigAllanDiagramData* RigEclipseCaseData::allanDiagramData()
|
|
{
|
|
return m_matrixModelResults->allanDiagramData();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RigCaseCellResultsData* RigEclipseCaseData::results( RiaDefines::PorosityModelType porosityModel )
|
|
{
|
|
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL )
|
|
{
|
|
return m_matrixModelResults.p();
|
|
}
|
|
|
|
return m_fractureModelResults.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigCaseCellResultsData* RigEclipseCaseData::results( RiaDefines::PorosityModelType porosityModel ) const
|
|
{
|
|
if ( porosityModel == RiaDefines::PorosityModelType::MATRIX_MODEL )
|
|
{
|
|
return m_matrixModelResults.p();
|
|
}
|
|
|
|
return m_fractureModelResults.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const std::vector<double>* RigEclipseCaseData::resultValues( RiaDefines::PorosityModelType porosityModel,
|
|
RiaDefines::ResultCatType type,
|
|
const QString& resultName,
|
|
size_t timeStepIndex )
|
|
{
|
|
RigCaseCellResultsData* gridCellResults = results( porosityModel );
|
|
|
|
const std::vector<double>* swatResults = nullptr;
|
|
if ( gridCellResults->ensureKnownResultLoaded( RigEclipseResultAddress( type, resultName ) ) )
|
|
{
|
|
swatResults = &( gridCellResults->cellScalarResults( RigEclipseResultAddress( type, resultName ), timeStepIndex ) );
|
|
}
|
|
|
|
return swatResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<RiaDefines::PhaseType> RigEclipseCaseData::availablePhases() const
|
|
{
|
|
return m_availablePhases;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RigEclipseCaseData::setAvailablePhases( const std::set<RiaDefines::PhaseType>& phases )
|
|
{
|
|
m_availablePhases = phases;
|
|
}
|