ResInsight/ApplicationLibCode/ReservoirDataModel/RigFault.cpp
Magne Sjaastad 0d213e659c #8371 Make sure all NNC faces are created and assigned
Make sure that the first cell in RigConnection is assigned the lowest cell index. Assign the opposite face if the cell indexes are swapped.
In RigCellFaceGeometryTools, test both combinations of (cellA, cellB) and (cellB, cellA)
2021-12-16 14:25:21 +01:00

236 lines
8.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigFault.h"
#include "RigMainGrid.h"
cvf::ref<RigFaultsPrCellAccumulator> RigFault::m_faultsPrCellAcc;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFault::RigFault()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::addCellRangeForFace( cvf::StructGridInterface::FaceType face, const cvf::CellRange& cellRange )
{
size_t faceIndex = static_cast<size_t>( face );
CVF_ASSERT( faceIndex < 6 );
m_cellRangesForFaces[faceIndex].push_back( cellRange );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::setName( const QString& name )
{
m_name = name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigFault::name() const
{
return m_name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigFault::FaultFace>& RigFault::faultFaces()
{
return m_faultFaces;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RigFault::FaultFace>& RigFault::faultFaces() const
{
return m_faultFaces;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t>& RigFault::connectionIndices()
{
return m_connectionIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<size_t>& RigFault::connectionIndices() const
{
return m_connectionIndices;
}
//--------------------------------------------------------------------------------------------------
/// Order FaultCellAndFace by i, j, face then k.
//--------------------------------------------------------------------------------------------------
bool RigFault::ordering( CellAndFace first, CellAndFace second )
{
size_t i1, i2, j1, j2, k1, k2;
cvf::StructGridInterface::FaceType f1, f2;
std::tie( i1, j1, k1, f1 ) = first;
std::tie( i2, j2, k2, f2 ) = second;
if ( i1 == i2 )
{
if ( j1 == j2 )
{
if ( f1 == f2 )
{
return k1 < k2;
}
else
{
return f1 < f2;
}
}
else
{
return j1 < j2;
}
}
else
{
return i1 < i2;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::computeFaultFacesFromCellRanges( const RigMainGrid* mainGrid )
{
if ( !mainGrid ) return;
m_faultFaces.clear();
for ( size_t faceType = 0; faceType < 6; faceType++ )
{
cvf::StructGridInterface::FaceType faceEnum = cvf::StructGridInterface::FaceType( faceType );
const std::vector<cvf::CellRange>& cellRanges = m_cellRangesForFaces[faceType];
for ( const cvf::CellRange& cellRange : cellRanges )
{
cvf::Vec3st min, max;
cellRange.range( min, max );
for ( size_t i = min.x(); i <= max.x(); i++ )
{
if ( i >= mainGrid->cellCountI() )
{
continue;
}
for ( size_t j = min.y(); j <= max.y(); j++ )
{
if ( j >= mainGrid->cellCountJ() )
{
continue;
}
for ( size_t k = min.z(); k <= max.z(); k++ )
{
if ( k >= mainGrid->cellCountK() )
{
continue;
}
// Do not need to compute global grid cell index as for a maingrid localIndex == globalIndex
// size_t reservoirCellIndex = grid->reservoirCellIndex(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 gridLocalCellIndex = mainGrid->cellIndexFromIJK( i, j, k );
size_t oppositeCellIndex = mainGrid->cellIndexFromIJK( ni, nj, nk );
m_faultFaces.push_back( FaultFace( gridLocalCellIndex, faceEnum, oppositeCellIndex ) );
}
else
{
// cvf::Trace::show("Warning: Undefined Fault neighbor detected.");
}
}
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFault::accumulateFaultsPrCell( RigFaultsPrCellAccumulator* faultsPrCellAcc, int faultIdx )
{
for ( const FaultFace& ff : m_faultFaces )
{
// Could detect overlapping faults here .... if (faultsPrCellAcc->faultIdx(ff.m_nativeReservoirCellIndex,
// ff.m_nativeFace)
// >= 0)
faultsPrCellAcc->setFaultIdx( ff.m_nativeReservoirCellIndex, ff.m_nativeFace, faultIdx );
faultsPrCellAcc->setFaultIdx( ff.m_oppositeReservoirCellIndex,
cvf::StructGridInterface::oppositeFace( ff.m_nativeFace ),
faultIdx );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFaultsPrCellAccumulator::RigFaultsPrCellAccumulator( size_t reservoirCellCount )
{
std::array<int, 6> initVals = { NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT, NO_FAULT };
m_faultIdxForCellFace.resize( reservoirCellCount, initVals );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigFaultsPrCellAccumulator::faultIdx( size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face ) const
{
// Ensure no crash after creating temporary LGRs
if ( reservoirCellIndex < m_faultIdxForCellFace.size() )
{
return m_faultIdxForCellFace[reservoirCellIndex][face];
}
return NO_FAULT;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultsPrCellAccumulator::setFaultIdx( size_t reservoirCellIndex, cvf::StructGridInterface::FaceType face, int faultIdx )
{
m_faultIdxForCellFace[reservoirCellIndex][face] = faultIdx;
}