mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
commit
63381756f4
@ -18,6 +18,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaFontCache.h
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.h
|
${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.h
|
${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RiaStringListSerializer.h
|
${CMAKE_CURRENT_LIST_DIR}/RiaStringListSerializer.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RiaNncDefines.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set (SOURCE_GROUP_SOURCE_FILES
|
set (SOURCE_GROUP_SOURCE_FILES
|
||||||
@ -40,6 +41,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaFontCache.cpp
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RiaEclipseFileNameTools.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RiaFeatureCommandContext.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RiaStringListSerializer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RiaStringListSerializer.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RiaNncDefines.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND CODE_HEADER_FILES
|
list(APPEND CODE_HEADER_FILES
|
||||||
|
75
ApplicationCode/Application/RiaNncDefines.cpp
Normal file
75
ApplicationCode/Application/RiaNncDefines.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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 "RiaNncDefines.h"
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameFluxWat()
|
||||||
|
{
|
||||||
|
return "FLRWAT";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameFluxOil()
|
||||||
|
{
|
||||||
|
return "FLROIL";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameFluxGas()
|
||||||
|
{
|
||||||
|
return "FLRGAS";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameCombTrans()
|
||||||
|
{
|
||||||
|
return "TRAN";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameRiCombTrans()
|
||||||
|
{
|
||||||
|
return "riTRAN";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameRiCombTransByArea()
|
||||||
|
{
|
||||||
|
return "riTRANbyArea";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
QString RiaDefines::propertyNameRiCombMult()
|
||||||
|
{
|
||||||
|
return "riMULT";
|
||||||
|
}
|
32
ApplicationCode/Application/RiaNncDefines.h
Normal file
32
ApplicationCode/Application/RiaNncDefines.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace RiaDefines
|
||||||
|
{
|
||||||
|
QString propertyNameFluxWat();
|
||||||
|
QString propertyNameFluxOil();
|
||||||
|
QString propertyNameFluxGas();
|
||||||
|
QString propertyNameCombTrans();
|
||||||
|
QString propertyNameRiCombTrans();
|
||||||
|
QString propertyNameRiCombTransByArea();
|
||||||
|
QString propertyNameRiCombMult();
|
||||||
|
}; // namespace RiaDefines
|
@ -464,7 +464,7 @@ bool RifReaderEclipseOutput::open( const QString& fileName, RigEclipseCaseData*
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto subNncTask = nncProgress.task( "Processing connections", 8 );
|
auto subNncTask = nncProgress.task( "Processing connections", 8 );
|
||||||
eclipseCase->mainGrid()->nncData()->processConnections( *( eclipseCase->mainGrid() ) );
|
eclipseCase->mainGrid()->nncData()->processNativeConnections( *( eclipseCase->mainGrid() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,24 +728,31 @@ void RifReaderEclipseOutput::transferStaticNNCData( const ecl_grid_type* mainEcl
|
|||||||
if ( numNNC > 0 )
|
if ( numNNC > 0 )
|
||||||
{
|
{
|
||||||
// Transform to our own data structures
|
// Transform to our own data structures
|
||||||
|
std::vector<RigConnection> nncConnections;
|
||||||
|
std::vector<double> transmissibilityValuesTemp;
|
||||||
|
|
||||||
mainGrid->nncData()->connections().resize( numNNC );
|
|
||||||
std::vector<double>& transmissibilityValues = mainGrid->nncData()->makeStaticConnectionScalarResult(
|
|
||||||
RigNNCData::propertyNameCombTrans() );
|
|
||||||
const double* transValues = ecl_nnc_data_get_values( tran_data );
|
const double* transValues = ecl_nnc_data_get_values( tran_data );
|
||||||
|
|
||||||
for ( int nIdx = 0; nIdx < numNNC; ++nIdx )
|
for ( int nIdx = 0; nIdx < numNNC; ++nIdx )
|
||||||
{
|
{
|
||||||
const ecl_nnc_pair_type* geometry_pair = ecl_nnc_geometry_iget( nnc_geo, nIdx );
|
const ecl_nnc_pair_type* geometry_pair = ecl_nnc_geometry_iget( nnc_geo, nIdx );
|
||||||
RigGridBase* grid1 = mainGrid->gridByIndex( geometry_pair->grid_nr1 );
|
RigGridBase* grid1 = mainGrid->gridByIndex( geometry_pair->grid_nr1 );
|
||||||
mainGrid->nncData()->connections()[nIdx].m_c1GlobIdx = grid1->reservoirCellIndex(
|
RigGridBase* grid2 = mainGrid->gridByIndex( geometry_pair->grid_nr2 );
|
||||||
geometry_pair->global_index1 );
|
|
||||||
RigGridBase* grid2 = mainGrid->gridByIndex( geometry_pair->grid_nr2 );
|
|
||||||
mainGrid->nncData()->connections()[nIdx].m_c2GlobIdx = grid2->reservoirCellIndex(
|
|
||||||
geometry_pair->global_index2 );
|
|
||||||
|
|
||||||
transmissibilityValues[nIdx] = transValues[nIdx];
|
RigConnection nncConnection;
|
||||||
|
nncConnection.m_c1GlobIdx = grid1->reservoirCellIndex( geometry_pair->global_index1 );
|
||||||
|
nncConnection.m_c2GlobIdx = grid2->reservoirCellIndex( geometry_pair->global_index2 );
|
||||||
|
|
||||||
|
nncConnections.push_back( nncConnection );
|
||||||
|
|
||||||
|
transmissibilityValuesTemp.push_back( transValues[nIdx] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainGrid->nncData()->setConnections( nncConnections );
|
||||||
|
|
||||||
|
std::vector<double>& transmissibilityValues = mainGrid->nncData()->makeStaticConnectionScalarResult(
|
||||||
|
RiaDefines::propertyNameCombTrans() );
|
||||||
|
transmissibilityValues = transmissibilityValuesTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecl_nnc_data_free( tran_data );
|
ecl_nnc_data_free( tran_data );
|
||||||
@ -767,11 +774,11 @@ void RifReaderEclipseOutput::transferDynamicNNCData( const ecl_grid_type* mainEc
|
|||||||
size_t timeStepCount = m_dynamicResultsAccess->timeStepCount();
|
size_t timeStepCount = m_dynamicResultsAccess->timeStepCount();
|
||||||
|
|
||||||
std::vector<std::vector<double>>& waterFluxData =
|
std::vector<std::vector<double>>& waterFluxData =
|
||||||
mainGrid->nncData()->makeDynamicConnectionScalarResult( RigNNCData::propertyNameFluxWat(), timeStepCount );
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxWat(), timeStepCount );
|
||||||
std::vector<std::vector<double>>& oilFluxData =
|
std::vector<std::vector<double>>& oilFluxData =
|
||||||
mainGrid->nncData()->makeDynamicConnectionScalarResult( RigNNCData::propertyNameFluxOil(), timeStepCount );
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxOil(), timeStepCount );
|
||||||
std::vector<std::vector<double>>& gasFluxData =
|
std::vector<std::vector<double>>& gasFluxData =
|
||||||
mainGrid->nncData()->makeDynamicConnectionScalarResult( RigNNCData::propertyNameFluxGas(), timeStepCount );
|
mainGrid->nncData()->makeDynamicConnectionScalarResult( RiaDefines::propertyNameFluxGas(), timeStepCount );
|
||||||
|
|
||||||
for ( size_t timeStep = 0; timeStep < timeStepCount; ++timeStep )
|
for ( size_t timeStep = 0; timeStep < timeStepCount; ++timeStep )
|
||||||
{
|
{
|
||||||
|
@ -72,13 +72,22 @@ RivFaultPartMgr::RivFaultPartMgr( const RigGridBase* grid,
|
|||||||
m_nativeFaultGenerator = new RivFaultGeometryGenerator( grid, rimFault->faultGeometry(), true );
|
m_nativeFaultGenerator = new RivFaultGeometryGenerator( grid, rimFault->faultGeometry(), true );
|
||||||
m_oppositeFaultGenerator = new RivFaultGeometryGenerator( grid, rimFault->faultGeometry(), false );
|
m_oppositeFaultGenerator = new RivFaultGeometryGenerator( grid, rimFault->faultGeometry(), false );
|
||||||
|
|
||||||
m_NNCGenerator = new RivNNCGeometryGenerator( grid->mainGrid()->nncData(),
|
m_nativeFaultFacesTextureCoords = new cvf::Vec2fArray;
|
||||||
|
m_oppositeFaultFacesTextureCoords = new cvf::Vec2fArray;
|
||||||
|
|
||||||
|
m_NNCGenerator = new RivNNCGeometryGenerator( false,
|
||||||
|
grid->mainGrid()->nncData(),
|
||||||
grid->mainGrid()->displayModelOffset(),
|
grid->mainGrid()->displayModelOffset(),
|
||||||
connIdxes.p() );
|
connIdxes.p() );
|
||||||
|
|
||||||
m_nativeFaultFacesTextureCoords = new cvf::Vec2fArray;
|
m_NNCTextureCoords = new cvf::Vec2fArray;
|
||||||
m_oppositeFaultFacesTextureCoords = new cvf::Vec2fArray;
|
|
||||||
m_NNCTextureCoords = new cvf::Vec2fArray;
|
m_allenNNCGenerator = new RivNNCGeometryGenerator( true,
|
||||||
|
grid->mainGrid()->nncData(),
|
||||||
|
grid->mainGrid()->displayModelOffset(),
|
||||||
|
connIdxes.p() );
|
||||||
|
|
||||||
|
m_allenNNCTextureCoords = new cvf::Vec2fArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -89,6 +98,7 @@ void RivFaultPartMgr::setCellVisibility( cvf::UByteArray* cellVisibilities )
|
|||||||
m_nativeFaultGenerator->setCellVisibility( cellVisibilities );
|
m_nativeFaultGenerator->setCellVisibility( cellVisibilities );
|
||||||
m_oppositeFaultGenerator->setCellVisibility( cellVisibilities );
|
m_oppositeFaultGenerator->setCellVisibility( cellVisibilities );
|
||||||
m_NNCGenerator->setCellVisibility( cellVisibilities, m_grid.p() );
|
m_NNCGenerator->setCellVisibility( cellVisibilities, m_grid.p() );
|
||||||
|
m_allenNNCGenerator->setCellVisibility( cellVisibilities, m_grid.p() );
|
||||||
|
|
||||||
generatePartGeometry();
|
generatePartGeometry();
|
||||||
}
|
}
|
||||||
@ -393,10 +403,44 @@ void RivFaultPartMgr::generatePartGeometry()
|
|||||||
part->setEnableMask( faultBit );
|
part->setEnableMask( faultBit );
|
||||||
part->setPriority( RivPartPriority::PartType::Nnc );
|
part->setPriority( RivPartPriority::PartType::Nnc );
|
||||||
|
|
||||||
|
cvf::ref<cvf::Effect> eff = new cvf::Effect;
|
||||||
|
part->setEffect( eff.p() );
|
||||||
|
|
||||||
m_NNCFaces = part;
|
m_NNCFaces = part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cvf::ref<cvf::DrawableGeo> geo = m_allenNNCGenerator->generateSurface();
|
||||||
|
if ( geo.notNull() )
|
||||||
|
{
|
||||||
|
geo->computeNormals();
|
||||||
|
|
||||||
|
if ( useBufferObjects )
|
||||||
|
{
|
||||||
|
geo->setRenderMode( cvf::DrawableGeo::BUFFER_OBJECT );
|
||||||
|
}
|
||||||
|
|
||||||
|
cvf::ref<cvf::Part> part = new cvf::Part;
|
||||||
|
part->setName( "Allen NNC in Fault. Grid " + cvf::String( static_cast<int>( m_grid->gridIndex() ) ) );
|
||||||
|
part->setDrawable( geo.p() );
|
||||||
|
|
||||||
|
// Set mapping from triangle face index to cell index
|
||||||
|
cvf::ref<RivSourceInfo> si = new RivSourceInfo( m_rimFault, m_grid->gridIndex() );
|
||||||
|
si->m_NNCIndices = m_allenNNCGenerator->triangleToNNCIndex().p();
|
||||||
|
part->setSourceInfo( si.p() );
|
||||||
|
|
||||||
|
part->updateBoundingBox();
|
||||||
|
part->setEnableMask( faultBit );
|
||||||
|
part->setPriority( RivPartPriority::PartType::Nnc );
|
||||||
|
|
||||||
|
cvf::ref<cvf::Effect> eff = new cvf::Effect;
|
||||||
|
part->setEffect( eff.p() );
|
||||||
|
|
||||||
|
m_allenNNCFaces = part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
createLabelWithAnchorLine( m_nativeFaultFaces.p() );
|
createLabelWithAnchorLine( m_nativeFaultFaces.p() );
|
||||||
|
|
||||||
updatePartEffect();
|
updatePartEffect();
|
||||||
@ -449,7 +493,9 @@ void RivFaultPartMgr::updatePartEffect()
|
|||||||
m_nativeFaultFaces->setPriority( RivPartPriority::PartType::TransparentFault );
|
m_nativeFaultFaces->setPriority( RivPartPriority::PartType::TransparentFault );
|
||||||
if ( m_oppositeFaultFaces.notNull() )
|
if ( m_oppositeFaultFaces.notNull() )
|
||||||
m_oppositeFaultFaces->setPriority( RivPartPriority::PartType::TransparentFault );
|
m_oppositeFaultFaces->setPriority( RivPartPriority::PartType::TransparentFault );
|
||||||
|
|
||||||
if ( m_NNCFaces.notNull() ) m_NNCFaces->setPriority( RivPartPriority::PartType::TransparentNnc );
|
if ( m_NNCFaces.notNull() ) m_NNCFaces->setPriority( RivPartPriority::PartType::TransparentNnc );
|
||||||
|
if ( m_allenNNCFaces.notNull() ) m_allenNNCFaces->setPriority( RivPartPriority::PartType::TransparentNnc );
|
||||||
|
|
||||||
if ( m_nativeFaultGridLines.notNull() )
|
if ( m_nativeFaultGridLines.notNull() )
|
||||||
{
|
{
|
||||||
@ -643,7 +689,15 @@ void RivFaultPartMgr::appendMeshLinePartsToModel( cvf::ModelBasicList* model )
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RivFaultPartMgr::appendNNCFacesToModel( cvf::ModelBasicList* model )
|
void RivFaultPartMgr::appendCompleteNNCFacesToModel( cvf::ModelBasicList* model )
|
||||||
|
{
|
||||||
|
if ( m_allenNNCFaces.notNull() ) model->addPart( m_allenNNCFaces.p() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void RivFaultPartMgr::appendNativeNNCFacesToModel( cvf::ModelBasicList* model )
|
||||||
{
|
{
|
||||||
if ( m_NNCFaces.notNull() ) model->addPart( m_NNCFaces.p() );
|
if ( m_NNCFaces.notNull() ) model->addPart( m_NNCFaces.p() );
|
||||||
}
|
}
|
||||||
@ -730,6 +784,12 @@ void RivFaultPartMgr::updateNNCColors( size_t timeStepIndex, RimEclipseCellColor
|
|||||||
resultType,
|
resultType,
|
||||||
eclResAddr,
|
eclResAddr,
|
||||||
nativeTimeStepIndex );
|
nativeTimeStepIndex );
|
||||||
|
|
||||||
|
m_allenNNCGenerator->textureCoordinates( m_allenNNCTextureCoords.p(),
|
||||||
|
mapper,
|
||||||
|
resultType,
|
||||||
|
eclResAddr,
|
||||||
|
nativeTimeStepIndex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,10 +810,18 @@ void RivFaultPartMgr::updateNNCColors( size_t timeStepIndex, RimEclipseCellColor
|
|||||||
nncEffect = nncEffgen.generateCachedEffect();
|
nncEffect = nncEffgen.generateCachedEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>( m_NNCFaces->drawable() );
|
{
|
||||||
if ( dg ) dg->setTextureCoordArray( m_NNCTextureCoords.p() );
|
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>( m_NNCFaces->drawable() );
|
||||||
|
if ( dg ) dg->setTextureCoordArray( m_NNCTextureCoords.p() );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cvf::DrawableGeo* dg = dynamic_cast<cvf::DrawableGeo*>( m_allenNNCFaces->drawable() );
|
||||||
|
if ( dg ) dg->setTextureCoordArray( m_allenNNCTextureCoords.p() );
|
||||||
|
}
|
||||||
|
|
||||||
m_NNCFaces->setEffect( nncEffect.p() );
|
m_NNCFaces->setEffect( nncEffect.p() );
|
||||||
|
m_allenNNCFaces->setEffect( nncEffect.p() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -780,5 +848,6 @@ void RivFaultPartMgr::updateNNCColors( size_t timeStepIndex, RimEclipseCellColor
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_NNCFaces->setEffect( nncEffect.p() );
|
m_NNCFaces->setEffect( nncEffect.p() );
|
||||||
|
m_allenNNCFaces->setEffect( nncEffect.p() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,10 +68,12 @@ public:
|
|||||||
|
|
||||||
void appendNativeFaultFacesToModel( cvf::ModelBasicList* model );
|
void appendNativeFaultFacesToModel( cvf::ModelBasicList* model );
|
||||||
void appendOppositeFaultFacesToModel( cvf::ModelBasicList* model );
|
void appendOppositeFaultFacesToModel( cvf::ModelBasicList* model );
|
||||||
void appendNNCFacesToModel( cvf::ModelBasicList* model );
|
|
||||||
void appendLabelPartsToModel( cvf::ModelBasicList* model );
|
void appendLabelPartsToModel( cvf::ModelBasicList* model );
|
||||||
void appendMeshLinePartsToModel( cvf::ModelBasicList* model );
|
void appendMeshLinePartsToModel( cvf::ModelBasicList* model );
|
||||||
|
|
||||||
|
void appendNativeNNCFacesToModel( cvf::ModelBasicList* model );
|
||||||
|
void appendCompleteNNCFacesToModel( cvf::ModelBasicList* model );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generatePartGeometry();
|
void generatePartGeometry();
|
||||||
void updatePartEffect();
|
void updatePartEffect();
|
||||||
@ -108,6 +110,10 @@ private:
|
|||||||
cvf::ref<cvf::Part> m_NNCFaces;
|
cvf::ref<cvf::Part> m_NNCFaces;
|
||||||
cvf::ref<cvf::Vec2fArray> m_NNCTextureCoords;
|
cvf::ref<cvf::Vec2fArray> m_NNCTextureCoords;
|
||||||
|
|
||||||
|
cvf::ref<RivNNCGeometryGenerator> m_allenNNCGenerator;
|
||||||
|
cvf::ref<cvf::Part> m_allenNNCFaces;
|
||||||
|
cvf::ref<cvf::Vec2fArray> m_allenNNCTextureCoords;
|
||||||
|
|
||||||
cvf::ref<cvf::Part> m_faultLabelPart;
|
cvf::ref<cvf::Part> m_faultLabelPart;
|
||||||
cvf::ref<cvf::Part> m_faultLabelLinePart;
|
cvf::ref<cvf::Part> m_faultLabelLinePart;
|
||||||
};
|
};
|
||||||
|
@ -31,10 +31,12 @@
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
RivNNCGeometryGenerator::RivNNCGeometryGenerator( const RigNNCData* nncData,
|
RivNNCGeometryGenerator::RivNNCGeometryGenerator( bool includeAllen,
|
||||||
|
const RigNNCData* nncData,
|
||||||
const cvf::Vec3d& offset,
|
const cvf::Vec3d& offset,
|
||||||
const cvf::Array<size_t>* nncIndexes )
|
const cvf::Array<size_t>* nncIndexes )
|
||||||
: m_nncData( nncData )
|
: m_includeAllenDiagramGeometry( includeAllen )
|
||||||
|
, m_nncData( nncData )
|
||||||
, m_nncIndexes( nncIndexes )
|
, m_nncIndexes( nncIndexes )
|
||||||
, m_offset( offset )
|
, m_offset( offset )
|
||||||
{
|
{
|
||||||
@ -86,6 +88,11 @@ void RivNNCGeometryGenerator::computeArrays()
|
|||||||
{
|
{
|
||||||
size_t conIdx = m_nncIndexes.isNull() ? nIdx : ( *m_nncIndexes )[nIdx];
|
size_t conIdx = m_nncIndexes.isNull() ? nIdx : ( *m_nncIndexes )[nIdx];
|
||||||
|
|
||||||
|
if ( !m_includeAllenDiagramGeometry && conIdx >= m_nncData->nativeConnectionCount() )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const RigConnection& conn = m_nncData->connections()[conIdx];
|
const RigConnection& conn = m_nncData->connections()[conIdx];
|
||||||
|
|
||||||
if ( conn.m_polygon.size() )
|
if ( conn.m_polygon.size() )
|
||||||
@ -177,8 +184,17 @@ void RivNNCGeometryGenerator::textureCoordinates( cvf::Vec2fArray*
|
|||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for ( int tIdx = 0; tIdx < static_cast<int>( m_triangleIndexToNNCIndex->size() ); tIdx++ )
|
for ( int tIdx = 0; tIdx < static_cast<int>( m_triangleIndexToNNCIndex->size() ); tIdx++ )
|
||||||
{
|
{
|
||||||
double cellScalarValue = ( *nncResultVals )[( *m_triangleIndexToNNCIndex )[tIdx]];
|
double cellScalarValue = HUGE_VAL;
|
||||||
cvf::Vec2f texCoord = mapper->mapToTextureCoord( cellScalarValue );
|
size_t resultIndex = ( *m_triangleIndexToNNCIndex )[tIdx];
|
||||||
|
|
||||||
|
// The nnc connections can have more connections than reported from Eclipse, clamp the result index to Eclipse Results
|
||||||
|
|
||||||
|
if ( resultIndex < nncResultVals->size() )
|
||||||
|
{
|
||||||
|
cellScalarValue = ( *nncResultVals )[resultIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
cvf::Vec2f texCoord = mapper->mapToTextureCoord( cellScalarValue );
|
||||||
if ( cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue ) // a != a is true for NAN's
|
if ( cellScalarValue == HUGE_VAL || cellScalarValue != cellScalarValue ) // a != a is true for NAN's
|
||||||
{
|
{
|
||||||
texCoord[1] = 1.0f;
|
texCoord[1] = 1.0f;
|
||||||
|
@ -42,7 +42,11 @@ class RigEclipseResultAddress;
|
|||||||
class RivNNCGeometryGenerator : public cvf::Object
|
class RivNNCGeometryGenerator : public cvf::Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RivNNCGeometryGenerator( const RigNNCData* nncData, const cvf::Vec3d& offset, const cvf::Array<size_t>* nncIndexes );
|
RivNNCGeometryGenerator( bool includeAllen,
|
||||||
|
const RigNNCData* nncData,
|
||||||
|
const cvf::Vec3d& offset,
|
||||||
|
const cvf::Array<size_t>* nncIndexes );
|
||||||
|
|
||||||
~RivNNCGeometryGenerator() override;
|
~RivNNCGeometryGenerator() override;
|
||||||
|
|
||||||
void setCellVisibility( const cvf::UByteArray* cellVisibilities, const RigGridBase* grid );
|
void setCellVisibility( const cvf::UByteArray* cellVisibilities, const RigGridBase* grid );
|
||||||
@ -63,6 +67,8 @@ private:
|
|||||||
void computeArrays();
|
void computeArrays();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_includeAllenDiagramGeometry;
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
cvf::cref<RigNNCData> m_nncData;
|
cvf::cref<RigNNCData> m_nncData;
|
||||||
cvf::cref<cvf::Array<size_t>> m_nncIndexes;
|
cvf::cref<cvf::Array<size_t>> m_nncIndexes;
|
||||||
|
@ -154,7 +154,9 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
|
|||||||
{
|
{
|
||||||
if ( faultCollection->showNNCs() )
|
if ( faultCollection->showNNCs() )
|
||||||
{
|
{
|
||||||
bool showNncs = true;
|
bool showNncs = true;
|
||||||
|
bool showAllenNncGeometry = false;
|
||||||
|
|
||||||
if ( faultCollection->hideNncsWhenNoResultIsAvailable() )
|
if ( faultCollection->hideNncsWhenNoResultIsAvailable() )
|
||||||
{
|
{
|
||||||
RigEclipseResultAddress eclipseResultAddress;
|
RigEclipseResultAddress eclipseResultAddress;
|
||||||
@ -167,6 +169,11 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
|
|||||||
eclipseResultAddress = cellResultColors->eclipseResultAddress();
|
eclipseResultAddress = cellResultColors->eclipseResultAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( eclipseResultAddress.m_resultCatType == RiaDefines::ALLEN_DIAGRAMS )
|
||||||
|
{
|
||||||
|
showAllenNncGeometry = true;
|
||||||
|
}
|
||||||
|
|
||||||
RigMainGrid* mainGrid = m_reservoirView->mainGrid();
|
RigMainGrid* mainGrid = m_reservoirView->mainGrid();
|
||||||
if ( !( mainGrid && mainGrid->nncData()->hasScalarValues( eclipseResultAddress ) ) )
|
if ( !( mainGrid && mainGrid->nncData()->hasScalarValues( eclipseResultAddress ) ) )
|
||||||
{
|
{
|
||||||
@ -176,7 +183,14 @@ void RivReservoirFaultsPartMgr::appendPartsToModel( cvf::ModelBasicList* model )
|
|||||||
|
|
||||||
if ( showNncs )
|
if ( showNncs )
|
||||||
{
|
{
|
||||||
rivFaultPart->appendNNCFacesToModel( &parts );
|
if ( showAllenNncGeometry )
|
||||||
|
{
|
||||||
|
rivFaultPart->appendCompleteNNCFacesToModel( &parts );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rivFaultPart->appendNativeNNCFacesToModel( &parts );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -828,7 +828,7 @@ bool RimEclipseCase::openReserviorCase()
|
|||||||
RiaDefines::combinedTransmissibilityResultName() );
|
RiaDefines::combinedTransmissibilityResultName() );
|
||||||
if ( results->hasResultEntry( combinedTransmissibilityResAddr ) )
|
if ( results->hasResultEntry( combinedTransmissibilityResAddr ) )
|
||||||
{
|
{
|
||||||
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RigNNCData::propertyNameCombTrans(),
|
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameCombTrans(),
|
||||||
combinedTransmissibilityResAddr );
|
combinedTransmissibilityResAddr );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,7 +836,7 @@ bool RimEclipseCase::openReserviorCase()
|
|||||||
RiaDefines::combinedWaterFluxResultName() );
|
RiaDefines::combinedWaterFluxResultName() );
|
||||||
if ( results->hasResultEntry( combinedWaterFluxResAddr ) )
|
if ( results->hasResultEntry( combinedWaterFluxResAddr ) )
|
||||||
{
|
{
|
||||||
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RigNNCData::propertyNameFluxWat(),
|
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxWat(),
|
||||||
combinedWaterFluxResAddr );
|
combinedWaterFluxResAddr );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,7 +844,7 @@ bool RimEclipseCase::openReserviorCase()
|
|||||||
RiaDefines::combinedOilFluxResultName() );
|
RiaDefines::combinedOilFluxResultName() );
|
||||||
if ( results->hasResultEntry( combinedOilFluxResAddr ) )
|
if ( results->hasResultEntry( combinedOilFluxResAddr ) )
|
||||||
{
|
{
|
||||||
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RigNNCData::propertyNameFluxOil(),
|
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxOil(),
|
||||||
combinedOilFluxResAddr );
|
combinedOilFluxResAddr );
|
||||||
}
|
}
|
||||||
RigEclipseResultAddress combinedGasFluxResAddr( RiaDefines::DYNAMIC_NATIVE,
|
RigEclipseResultAddress combinedGasFluxResAddr( RiaDefines::DYNAMIC_NATIVE,
|
||||||
@ -852,7 +852,7 @@ bool RimEclipseCase::openReserviorCase()
|
|||||||
|
|
||||||
if ( results->hasResultEntry( combinedGasFluxResAddr ) )
|
if ( results->hasResultEntry( combinedGasFluxResAddr ) )
|
||||||
{
|
{
|
||||||
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RigNNCData::propertyNameFluxGas(),
|
eclipseCaseData()->mainGrid()->nncData()->setEclResultAddress( RiaDefines::propertyNameFluxGas(),
|
||||||
combinedGasFluxResAddr );
|
combinedGasFluxResAddr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,8 +272,8 @@ void RimFaultInViewCollection::syncronizeFaults()
|
|||||||
// NNCs
|
// NNCs
|
||||||
this->noCommonAreaNnncCollection()->noCommonAreaNncs().deleteAllChildObjects();
|
this->noCommonAreaNnncCollection()->noCommonAreaNncs().deleteAllChildObjects();
|
||||||
|
|
||||||
RigMainGrid* mainGrid = parentView()->mainGrid();
|
RigMainGrid* mainGrid = parentView()->mainGrid();
|
||||||
std::vector<RigConnection>& nncConnections = mainGrid->nncData()->connections();
|
const std::vector<RigConnection>& nncConnections = mainGrid->nncData()->connections();
|
||||||
for ( size_t connIndex = 0; connIndex < nncConnections.size(); connIndex++ )
|
for ( size_t connIndex = 0; connIndex < nncConnections.size(); connIndex++ )
|
||||||
{
|
{
|
||||||
if ( !nncConnections[connIndex].hasCommonArea() )
|
if ( !nncConnections[connIndex].hasCommonArea() )
|
||||||
|
@ -75,6 +75,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RigEclipseCrossPlotDataExtractor.h
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RigEquil.h
|
${CMAKE_CURRENT_LIST_DIR}/RigEquil.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.h
|
${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.h
|
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RigCellFaceGeometryTools.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -147,6 +149,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RigEclipseCrossPlotDataExtractor.cpp
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RigEquil.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RigEquil.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RigWbsParameter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RigEclipseAllenFaultsStatCalc.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RigCellFaceGeometryTools.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND CODE_HEADER_FILES
|
list(APPEND CODE_HEADER_FILES
|
||||||
|
@ -2196,8 +2196,8 @@ void RigCaseCellResultsData::computeNncCombRiTrans()
|
|||||||
std::vector<double>& permYResults = m_cellScalarResults[permYResultIdx][0];
|
std::vector<double>& permYResults = m_cellScalarResults[permYResultIdx][0];
|
||||||
std::vector<double>& permZResults = m_cellScalarResults[permZResultIdx][0];
|
std::vector<double>& permZResults = m_cellScalarResults[permZResultIdx][0];
|
||||||
std::vector<double>& riCombTransResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
std::vector<double>& riCombTransResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
||||||
RigNNCData::propertyNameRiCombTrans() );
|
RiaDefines::propertyNameRiCombTrans() );
|
||||||
m_ownerMainGrid->nncData()->setEclResultAddress( RigNNCData::propertyNameRiCombTrans(), riCombTransEclResAddr );
|
m_ownerMainGrid->nncData()->setEclResultAddress( RiaDefines::propertyNameRiCombTrans(), riCombTransEclResAddr );
|
||||||
|
|
||||||
std::vector<double>* ntgResults = nullptr;
|
std::vector<double>* ntgResults = nullptr;
|
||||||
if ( hasNTGResults )
|
if ( hasNTGResults )
|
||||||
@ -2239,7 +2239,7 @@ void RigCaseCellResultsData::computeNncCombRiTrans()
|
|||||||
bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards();
|
bool isFaceNormalsOutwards = m_ownerMainGrid->isFaceNormalsOutwards();
|
||||||
|
|
||||||
// NNC calculation
|
// NNC calculation
|
||||||
std::vector<RigConnection>& nncConnections = m_ownerMainGrid->nncData()->connections();
|
const std::vector<RigConnection>& nncConnections = m_ownerMainGrid->nncData()->connections();
|
||||||
for ( size_t connIdx = 0; connIdx < nncConnections.size(); connIdx++ )
|
for ( size_t connIdx = 0; connIdx < nncConnections.size(); connIdx++ )
|
||||||
{
|
{
|
||||||
size_t nativeResvCellIndex = nncConnections[connIdx].m_c1GlobIdx;
|
size_t nativeResvCellIndex = nncConnections[connIdx].m_c1GlobIdx;
|
||||||
@ -2444,7 +2444,7 @@ void RigCaseCellResultsData::computeNncCombRiMULT()
|
|||||||
if ( m_ownerMainGrid->nncData()->staticConnectionScalarResult( riCombMultEclResAddr ) ) return;
|
if ( m_ownerMainGrid->nncData()->staticConnectionScalarResult( riCombMultEclResAddr ) ) return;
|
||||||
|
|
||||||
std::vector<double>& riMultResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
std::vector<double>& riMultResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
||||||
RigNNCData::propertyNameRiCombMult() );
|
RiaDefines::propertyNameRiCombMult() );
|
||||||
|
|
||||||
const std::vector<double>* riTransResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
const std::vector<double>* riTransResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
||||||
riCombTransEclResAddr );
|
riCombTransEclResAddr );
|
||||||
@ -2452,7 +2452,7 @@ void RigCaseCellResultsData::computeNncCombRiMULT()
|
|||||||
const std::vector<double>* transResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
const std::vector<double>* transResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
||||||
combTransEclResAddr );
|
combTransEclResAddr );
|
||||||
|
|
||||||
m_ownerMainGrid->nncData()->setEclResultAddress( RigNNCData::propertyNameRiCombMult(), riCombMultEclResAddr );
|
m_ownerMainGrid->nncData()->setEclResultAddress( RiaDefines::propertyNameRiCombMult(), riCombMultEclResAddr );
|
||||||
|
|
||||||
for ( size_t nncConIdx = 0; nncConIdx < riMultResults.size(); ++nncConIdx )
|
for ( size_t nncConIdx = 0; nncConIdx < riMultResults.size(); ++nncConIdx )
|
||||||
{
|
{
|
||||||
@ -2585,9 +2585,9 @@ void RigCaseCellResultsData::computeNncCombRiTRANSbyArea()
|
|||||||
if ( m_ownerMainGrid->nncData()->staticConnectionScalarResult( riCombTransByAreaEclResAddr ) ) return;
|
if ( m_ownerMainGrid->nncData()->staticConnectionScalarResult( riCombTransByAreaEclResAddr ) ) return;
|
||||||
|
|
||||||
std::vector<double>& riAreaNormTransResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
std::vector<double>& riAreaNormTransResults = m_ownerMainGrid->nncData()->makeStaticConnectionScalarResult(
|
||||||
RigNNCData::propertyNameRiCombTransByArea() );
|
RiaDefines::propertyNameRiCombTransByArea() );
|
||||||
|
|
||||||
m_ownerMainGrid->nncData()->setEclResultAddress( RigNNCData::propertyNameRiCombTransByArea(),
|
m_ownerMainGrid->nncData()->setEclResultAddress( RiaDefines::propertyNameRiCombTransByArea(),
|
||||||
riCombTransByAreaEclResAddr );
|
riCombTransByAreaEclResAddr );
|
||||||
|
|
||||||
const std::vector<double>* transResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
const std::vector<double>* transResults = m_ownerMainGrid->nncData()->staticConnectionScalarResult(
|
||||||
|
341
ApplicationCode/ReservoirDataModel/RigCellFaceGeometryTools.cpp
Normal file
341
ApplicationCode/ReservoirDataModel/RigCellFaceGeometryTools.cpp
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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 "RigCellFaceGeometryTools.h"
|
||||||
|
|
||||||
|
#include "RigCell.h"
|
||||||
|
#include "RigMainGrid.h"
|
||||||
|
#include "RigNncConnection.h"
|
||||||
|
|
||||||
|
#include "cvfGeometryTools.h"
|
||||||
|
|
||||||
|
#include "cafAssert.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
cvf::StructGridInterface::FaceType
|
||||||
|
RigCellFaceGeometryTools::calculateCellFaceOverlap( const RigCell& c1,
|
||||||
|
const RigCell& c2,
|
||||||
|
const RigMainGrid& mainGrid,
|
||||||
|
std::vector<size_t>* connectionPolygon,
|
||||||
|
std::vector<cvf::Vec3d>* connectionIntersections )
|
||||||
|
{
|
||||||
|
// Try to find the shared face
|
||||||
|
|
||||||
|
bool isPossibleNeighborInDirection[6] = {true, true, true, true, true, true};
|
||||||
|
|
||||||
|
if ( c1.hostGrid() == c2.hostGrid() )
|
||||||
|
{
|
||||||
|
char hasNeighbourInAnyDirection = 0;
|
||||||
|
|
||||||
|
size_t i1, j1, k1;
|
||||||
|
c1.hostGrid()->ijkFromCellIndex( c1.gridLocalCellIndex(), &i1, &j1, &k1 );
|
||||||
|
size_t i2, j2, k2;
|
||||||
|
c2.hostGrid()->ijkFromCellIndex( c2.gridLocalCellIndex(), &i2, &j2, &k2 );
|
||||||
|
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_I] = ( ( i1 + 1 ) == i2 );
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_I] = ( ( i2 + 1 ) == i1 );
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_J] = ( ( j1 + 1 ) == j2 );
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_J] = ( ( j2 + 1 ) == j1 );
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_K] = ( ( k1 + 1 ) == k2 );
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_K] = ( ( k2 + 1 ) == k1 );
|
||||||
|
|
||||||
|
hasNeighbourInAnyDirection = isPossibleNeighborInDirection[cvf::StructGridInterface::POS_I] +
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_I] +
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_J] +
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_J] +
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_K] +
|
||||||
|
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_K];
|
||||||
|
|
||||||
|
// If cell 2 is not adjancent with respect to any of the six ijk directions,
|
||||||
|
// assume that we have no overlapping area.
|
||||||
|
|
||||||
|
if ( !hasNeighbourInAnyDirection )
|
||||||
|
{
|
||||||
|
// Add to search map
|
||||||
|
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c1GlobIdx][cvf::StructGridInterface::NO_FACE].push_back(cnIdx);
|
||||||
|
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c2GlobIdx][cvf::StructGridInterface::NO_FACE].push_back(cnIdx);
|
||||||
|
|
||||||
|
// cvf::Trace::show("NNC: No direct neighbors : C1: " + cvf::String((int)m_connections[cnIdx].m_c1GlobIdx) +
|
||||||
|
// " C2: " + cvf::String((int)m_connections[cnIdx].m_c2GlobIdx));
|
||||||
|
return cvf::StructGridInterface::NO_FACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( unsigned char fIdx = 0; fIdx < 6; ++fIdx )
|
||||||
|
{
|
||||||
|
if ( !isPossibleNeighborInDirection[fIdx] )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate connection polygon
|
||||||
|
|
||||||
|
std::vector<size_t> polygon;
|
||||||
|
std::vector<cvf::Vec3d> intersections;
|
||||||
|
std::array<size_t, 4> face1;
|
||||||
|
std::array<size_t, 4> face2;
|
||||||
|
c1.faceIndices( ( cvf::StructGridInterface::FaceType )( fIdx ), &face1 );
|
||||||
|
c2.faceIndices( cvf::StructGridInterface::oppositeFace( ( cvf::StructGridInterface::FaceType )( fIdx ) ), &face2 );
|
||||||
|
|
||||||
|
bool foundOverlap =
|
||||||
|
cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
||||||
|
&intersections,
|
||||||
|
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
||||||
|
cvf::wrapArrayConst( &mainGrid.nodes() ),
|
||||||
|
face1.data(),
|
||||||
|
face2.data(),
|
||||||
|
1e-6 );
|
||||||
|
|
||||||
|
if ( foundOverlap )
|
||||||
|
{
|
||||||
|
if ( connectionPolygon ) ( *connectionPolygon ) = polygon;
|
||||||
|
if ( connectionIntersections ) ( *connectionIntersections ) = intersections;
|
||||||
|
return ( cvf::StructGridInterface::FaceType )( fIdx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cvf::StructGridInterface::NO_FACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<RigConnection> RigCellFaceGeometryTools::computeOtherNncs( const RigMainGrid* mainGrid,
|
||||||
|
const std::vector<RigConnection>& nativeConnections )
|
||||||
|
{
|
||||||
|
// Compute Non-Neighbor Connections (NNC) not reported by Eclipse. NNCs with zero transmissibility are not reported
|
||||||
|
// by Eclipse. Use faults as basis for subset of cells to find NNC connection for. The imported connections from
|
||||||
|
// Eclipse are located at the beginning of the connections vector.
|
||||||
|
|
||||||
|
std::vector<RigConnection> otherConnections;
|
||||||
|
|
||||||
|
class CellPair
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CellPair( size_t globalIdx1, size_t globalIdx2 )
|
||||||
|
{
|
||||||
|
if ( globalIdx1 < globalIdx2 )
|
||||||
|
{
|
||||||
|
m_globalCellIdx1 = globalIdx1;
|
||||||
|
m_globalCellIdx2 = globalIdx2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_globalCellIdx1 = globalIdx2;
|
||||||
|
m_globalCellIdx2 = globalIdx1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<( const CellPair& other ) const
|
||||||
|
{
|
||||||
|
if ( m_globalCellIdx1 != other.m_globalCellIdx1 )
|
||||||
|
{
|
||||||
|
return m_globalCellIdx1 < other.m_globalCellIdx1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( m_globalCellIdx2 < other.m_globalCellIdx2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_globalCellIdx1;
|
||||||
|
size_t m_globalCellIdx2;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<CellPair> nativeCellPairs;
|
||||||
|
|
||||||
|
for ( const auto& c : nativeConnections )
|
||||||
|
{
|
||||||
|
nativeCellPairs.emplace( CellPair( c.m_c1GlobIdx, c.m_c2GlobIdx ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nativeConnections.size() != nativeCellPairs.size() )
|
||||||
|
{
|
||||||
|
QString message = QString( "Nnc connection imported from Eclipse are not unique\nNNC count : %1\nUnique : %2" )
|
||||||
|
.arg( nativeConnections.size() )
|
||||||
|
.arg( nativeCellPairs.size() );
|
||||||
|
qDebug() << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<CellPair> otherCellPairs;
|
||||||
|
|
||||||
|
const cvf::Collection<RigFault>& faults = mainGrid->faults();
|
||||||
|
for ( size_t faultIdx = 0; faultIdx < faults.size(); faultIdx++ )
|
||||||
|
{
|
||||||
|
const RigFault* fault = faults.at( faultIdx );
|
||||||
|
|
||||||
|
const std::vector<RigFault::FaultFace>& faultFaces = fault->faultFaces();
|
||||||
|
for ( const auto& f : faultFaces )
|
||||||
|
{
|
||||||
|
size_t sourceReservoirCellIndex = f.m_nativeReservoirCellIndex;
|
||||||
|
cvf::StructGridInterface::FaceType sourceCellFace = f.m_nativeFace;
|
||||||
|
|
||||||
|
const std::vector<cvf::Vec3d>& mainGridNodes = mainGrid->nodes();
|
||||||
|
|
||||||
|
cvf::BoundingBox bb;
|
||||||
|
std::array<size_t, 4> sourceFaceIndices;
|
||||||
|
mainGrid->globalCellArray()[sourceReservoirCellIndex].faceIndices( sourceCellFace, &sourceFaceIndices );
|
||||||
|
|
||||||
|
bb.add( mainGridNodes[sourceFaceIndices[0]] );
|
||||||
|
bb.add( mainGridNodes[sourceFaceIndices[1]] );
|
||||||
|
bb.add( mainGridNodes[sourceFaceIndices[2]] );
|
||||||
|
bb.add( mainGridNodes[sourceFaceIndices[3]] );
|
||||||
|
|
||||||
|
std::vector<size_t> closeCells;
|
||||||
|
mainGrid->findIntersectingCells( bb, &closeCells );
|
||||||
|
|
||||||
|
cvf::StructGridInterface::FaceType candidateFace = cvf::StructGridInterface::oppositeFace( sourceCellFace );
|
||||||
|
|
||||||
|
size_t neighborCellIndex = std::numeric_limits<size_t>::max();
|
||||||
|
size_t ni = std::numeric_limits<size_t>::max();
|
||||||
|
size_t nj = std::numeric_limits<size_t>::max();
|
||||||
|
size_t nk = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t j;
|
||||||
|
size_t k;
|
||||||
|
mainGrid->ijkFromCellIndex( sourceReservoirCellIndex, &i, &j, &k );
|
||||||
|
|
||||||
|
mainGrid->neighborIJKAtCellFace( i, j, k, sourceCellFace, &ni, &nj, &nk );
|
||||||
|
|
||||||
|
if ( mainGrid->isCellValid( ni, nj, nk ) )
|
||||||
|
{
|
||||||
|
neighborCellIndex = mainGrid->cellIndexFromIJK( ni, nj, nk );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t candidateCellIndex : closeCells )
|
||||||
|
{
|
||||||
|
if ( candidateCellIndex == sourceReservoirCellIndex )
|
||||||
|
{
|
||||||
|
// Exclude cellIndex for source cell
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( candidateCellIndex == neighborCellIndex )
|
||||||
|
{
|
||||||
|
// Exclude direct neighbor
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( neighborCellIndex != std::numeric_limits<size_t>::max() )
|
||||||
|
{
|
||||||
|
// Find target IJK index based on source cell and cell face
|
||||||
|
// Exclude cells not matching destination target index
|
||||||
|
|
||||||
|
size_t ci = std::numeric_limits<size_t>::max();
|
||||||
|
size_t cj = std::numeric_limits<size_t>::max();
|
||||||
|
size_t ck = std::numeric_limits<size_t>::max();
|
||||||
|
mainGrid->ijkFromCellIndex( candidateCellIndex, &ci, &cj, &ck );
|
||||||
|
|
||||||
|
if ( sourceCellFace == cvf::StructGridInterface::POS_I ||
|
||||||
|
sourceCellFace == cvf::StructGridInterface::NEG_I )
|
||||||
|
{
|
||||||
|
if ( ni != ci )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( sourceCellFace == cvf::StructGridInterface::POS_J ||
|
||||||
|
sourceCellFace == cvf::StructGridInterface::NEG_J )
|
||||||
|
{
|
||||||
|
if ( nj != cj )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( sourceCellFace == cvf::StructGridInterface::POS_K ||
|
||||||
|
sourceCellFace == cvf::StructGridInterface::NEG_K )
|
||||||
|
{
|
||||||
|
if ( nk != ck )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CellPair candidate( sourceReservoirCellIndex, candidateCellIndex );
|
||||||
|
|
||||||
|
if ( nativeCellPairs.count( candidate ) > 0 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( otherCellPairs.count( candidate ) > 0 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> polygon;
|
||||||
|
std::vector<cvf::Vec3d> intersections;
|
||||||
|
|
||||||
|
std::array<size_t, 4> candidateFaceIndices;
|
||||||
|
mainGrid->globalCellArray()[candidateCellIndex].faceIndices( candidateFace, &candidateFaceIndices );
|
||||||
|
|
||||||
|
bool foundOverlap =
|
||||||
|
cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
||||||
|
&intersections,
|
||||||
|
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
||||||
|
cvf::wrapArrayConst( &mainGridNodes ),
|
||||||
|
sourceFaceIndices.data(),
|
||||||
|
candidateFaceIndices.data(),
|
||||||
|
1e-6 );
|
||||||
|
|
||||||
|
if ( foundOverlap )
|
||||||
|
{
|
||||||
|
otherCellPairs.emplace( candidate );
|
||||||
|
|
||||||
|
RigConnection conn;
|
||||||
|
conn.m_c1GlobIdx = sourceReservoirCellIndex;
|
||||||
|
conn.m_c1Face = sourceCellFace;
|
||||||
|
conn.m_c2GlobIdx = candidateCellIndex;
|
||||||
|
|
||||||
|
conn.m_polygon = RigCellFaceGeometryTools::extractPolygon( mainGridNodes, polygon, intersections );
|
||||||
|
|
||||||
|
otherConnections.emplace_back( conn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return otherConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<cvf::Vec3d> RigCellFaceGeometryTools::extractPolygon( const std::vector<cvf::Vec3d>& nativeNodes,
|
||||||
|
const std::vector<size_t>& connectionPolygon,
|
||||||
|
const std::vector<cvf::Vec3d>& connectionIntersections )
|
||||||
|
{
|
||||||
|
std::vector<cvf::Vec3d> allPolygonNodes;
|
||||||
|
|
||||||
|
for ( size_t polygonIndex : connectionPolygon )
|
||||||
|
{
|
||||||
|
if ( polygonIndex < nativeNodes.size() )
|
||||||
|
allPolygonNodes.push_back( nativeNodes[polygonIndex] );
|
||||||
|
else
|
||||||
|
allPolygonNodes.push_back( connectionIntersections[polygonIndex - nativeNodes.size()] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return allPolygonNodes;
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cvfCollection.h"
|
||||||
|
#include "cvfStructGrid.h"
|
||||||
|
#include "cvfVector3.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class RigCell;
|
||||||
|
class RigMainGrid;
|
||||||
|
class RigConnection;
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
///
|
||||||
|
//==================================================================================================
|
||||||
|
class RigCellFaceGeometryTools
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static cvf::StructGridInterface::FaceType calculateCellFaceOverlap( const RigCell& c1,
|
||||||
|
const RigCell& c2,
|
||||||
|
const RigMainGrid& mainGrid,
|
||||||
|
std::vector<size_t>* connectionPolygon,
|
||||||
|
std::vector<cvf::Vec3d>* connectionIntersections );
|
||||||
|
|
||||||
|
static std::vector<RigConnection> computeOtherNncs( const RigMainGrid* mainGrid,
|
||||||
|
const std::vector<RigConnection>& nativeConnections );
|
||||||
|
|
||||||
|
static std::vector<cvf::Vec3d> extractPolygon( const std::vector<cvf::Vec3d>& nativeNodes,
|
||||||
|
const std::vector<size_t>& connectionPolygon,
|
||||||
|
const std::vector<cvf::Vec3d>& connectionIntersections );
|
||||||
|
};
|
@ -556,6 +556,8 @@ void RigMainGrid::calculateFaults( const RigActiveCellInfo* activeCellInfo )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->nncData()->computeCompleteSetOfNncs( this );
|
||||||
|
|
||||||
distributeNNCsToFaults();
|
distributeNNCsToFaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "RigNNCData.h"
|
#include "RigNNCData.h"
|
||||||
|
|
||||||
|
#include "RigCellFaceGeometryTools.h"
|
||||||
#include "RigEclipseResultAddress.h"
|
#include "RigEclipseResultAddress.h"
|
||||||
#include "RigMainGrid.h"
|
#include "RigMainGrid.h"
|
||||||
|
|
||||||
#include "cvfGeometryTools.h"
|
#include "cvfGeometryTools.h"
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -30,7 +33,7 @@ RigNNCData::RigNNCData() {}
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RigNNCData::processConnections( const RigMainGrid& mainGrid )
|
void RigNNCData::processNativeConnections( const RigMainGrid& mainGrid )
|
||||||
{
|
{
|
||||||
// cvf::Trace::show("NNC: Total number: " + cvf::String((int)m_connections.size()));
|
// cvf::Trace::show("NNC: Total number: " + cvf::String((int)m_connections.size()));
|
||||||
|
|
||||||
@ -43,21 +46,21 @@ void RigNNCData::processConnections( const RigMainGrid& mainGrid )
|
|||||||
std::vector<cvf::Vec3d> connectionIntersections;
|
std::vector<cvf::Vec3d> connectionIntersections;
|
||||||
cvf::StructGridInterface::FaceType connectionFace = cvf::StructGridInterface::NO_FACE;
|
cvf::StructGridInterface::FaceType connectionFace = cvf::StructGridInterface::NO_FACE;
|
||||||
|
|
||||||
connectionFace = calculateCellFaceOverlap( c1, c2, mainGrid, &connectionPolygon, &connectionIntersections );
|
connectionFace = RigCellFaceGeometryTools::calculateCellFaceOverlap( c1,
|
||||||
|
c2,
|
||||||
|
mainGrid,
|
||||||
|
&connectionPolygon,
|
||||||
|
&connectionIntersections );
|
||||||
|
|
||||||
if ( connectionFace != cvf::StructGridInterface::NO_FACE )
|
if ( connectionFace != cvf::StructGridInterface::NO_FACE )
|
||||||
{
|
{
|
||||||
// Found an overlap polygon. Store data about connection
|
// Found an overlap polygon. Store data about connection
|
||||||
|
|
||||||
m_connections[cnIdx].m_c1Face = connectionFace;
|
m_connections[cnIdx].m_c1Face = connectionFace;
|
||||||
for ( size_t pIdx = 0; pIdx < connectionPolygon.size(); ++pIdx )
|
|
||||||
{
|
m_connections[cnIdx].m_polygon = RigCellFaceGeometryTools::extractPolygon( mainGrid.nodes(),
|
||||||
if ( connectionPolygon[pIdx] < mainGrid.nodes().size() )
|
connectionPolygon,
|
||||||
m_connections[cnIdx].m_polygon.push_back( mainGrid.nodes()[connectionPolygon[pIdx]] );
|
connectionIntersections );
|
||||||
else
|
|
||||||
m_connections[cnIdx].m_polygon.push_back(
|
|
||||||
connectionIntersections[connectionPolygon[pIdx] - mainGrid.nodes().size()] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to search map, possibly not needed
|
// Add to search map, possibly not needed
|
||||||
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c1GlobIdx][connectionFace].push_back(cnIdx);
|
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c1GlobIdx][connectionFace].push_back(cnIdx);
|
||||||
@ -74,109 +77,37 @@ void RigNNCData::processConnections( const RigMainGrid& mainGrid )
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
cvf::StructGridInterface::FaceType RigNNCData::calculateCellFaceOverlap( const RigCell& c1,
|
void RigNNCData::computeCompleteSetOfNncs( const RigMainGrid* mainGrid )
|
||||||
const RigCell& c2,
|
|
||||||
const RigMainGrid& mainGrid,
|
|
||||||
std::vector<size_t>* connectionPolygon,
|
|
||||||
std::vector<cvf::Vec3d>* connectionIntersections )
|
|
||||||
{
|
{
|
||||||
// Try to find the shared face
|
m_nativeConnectionCount = m_connections.size();
|
||||||
|
|
||||||
bool isPossibleNeighborInDirection[6] = {true, true, true, true, true, true};
|
std::vector<RigConnection> otherConnections = RigCellFaceGeometryTools::computeOtherNncs( mainGrid, m_connections );
|
||||||
|
|
||||||
if ( c1.hostGrid() == c2.hostGrid() )
|
m_connections.insert( m_connections.end(), otherConnections.begin(), otherConnections.end() );
|
||||||
{
|
}
|
||||||
char hasNeighbourInAnyDirection = 0;
|
|
||||||
|
|
||||||
size_t i1, j1, k1;
|
//--------------------------------------------------------------------------------------------------
|
||||||
c1.hostGrid()->ijkFromCellIndex( c1.gridLocalCellIndex(), &i1, &j1, &k1 );
|
///
|
||||||
size_t i2, j2, k2;
|
//--------------------------------------------------------------------------------------------------
|
||||||
c2.hostGrid()->ijkFromCellIndex( c2.gridLocalCellIndex(), &i2, &j2, &k2 );
|
void RigNNCData::setConnections( std::vector<RigConnection>& connections )
|
||||||
|
{
|
||||||
|
m_connections = connections;
|
||||||
|
}
|
||||||
|
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_I] = ( ( i1 + 1 ) == i2 );
|
//--------------------------------------------------------------------------------------------------
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_I] = ( ( i2 + 1 ) == i1 );
|
///
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_J] = ( ( j1 + 1 ) == j2 );
|
//--------------------------------------------------------------------------------------------------
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_J] = ( ( j2 + 1 ) == j1 );
|
size_t RigNNCData::nativeConnectionCount() const
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_K] = ( ( k1 + 1 ) == k2 );
|
{
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_K] = ( ( k2 + 1 ) == k1 );
|
return m_nativeConnectionCount;
|
||||||
|
}
|
||||||
|
|
||||||
hasNeighbourInAnyDirection = isPossibleNeighborInDirection[cvf::StructGridInterface::POS_I] +
|
//--------------------------------------------------------------------------------------------------
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_I] +
|
///
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_J] +
|
//--------------------------------------------------------------------------------------------------
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_J] +
|
const std::vector<RigConnection>& RigNNCData::connections() const
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::POS_K] +
|
{
|
||||||
isPossibleNeighborInDirection[cvf::StructGridInterface::NEG_K];
|
return m_connections;
|
||||||
|
|
||||||
// If cell 2 is not adjancent with respect to any of the six ijk directions,
|
|
||||||
// assume that we have no overlapping area.
|
|
||||||
|
|
||||||
if ( !hasNeighbourInAnyDirection )
|
|
||||||
{
|
|
||||||
// Add to search map
|
|
||||||
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c1GlobIdx][cvf::StructGridInterface::NO_FACE].push_back(cnIdx);
|
|
||||||
// m_cellIdxToFaceToConnectionIdxMap[m_connections[cnIdx].m_c2GlobIdx][cvf::StructGridInterface::NO_FACE].push_back(cnIdx);
|
|
||||||
|
|
||||||
// cvf::Trace::show("NNC: No direct neighbors : C1: " + cvf::String((int)m_connections[cnIdx].m_c1GlobIdx) +
|
|
||||||
// " C2: " + cvf::String((int)m_connections[cnIdx].m_c2GlobIdx));
|
|
||||||
return cvf::StructGridInterface::NO_FACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Possibly do some testing to avoid unneccesary overlap calculations
|
|
||||||
cvf::Vec3d normal;
|
|
||||||
for ( char fIdx = 0; fIdx < 6; ++fIdx )
|
|
||||||
{
|
|
||||||
if ( isPossibleNeighborInDirection[fIdx] )
|
|
||||||
{
|
|
||||||
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.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() )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for ( unsigned char fIdx = 0; fIdx < 6; ++fIdx )
|
|
||||||
{
|
|
||||||
if ( !isPossibleNeighborInDirection[fIdx] )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate connection polygon
|
|
||||||
|
|
||||||
std::vector<size_t> polygon;
|
|
||||||
std::vector<cvf::Vec3d> intersections;
|
|
||||||
std::array<size_t, 4> face1;
|
|
||||||
std::array<size_t, 4> face2;
|
|
||||||
c1.faceIndices( ( cvf::StructGridInterface::FaceType )( fIdx ), &face1 );
|
|
||||||
c2.faceIndices( cvf::StructGridInterface::oppositeFace( ( cvf::StructGridInterface::FaceType )( fIdx ) ), &face2 );
|
|
||||||
|
|
||||||
bool foundOverlap =
|
|
||||||
cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
|
||||||
&intersections,
|
|
||||||
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
|
||||||
cvf::wrapArrayConst( &mainGrid.nodes() ),
|
|
||||||
face1.data(),
|
|
||||||
face2.data(),
|
|
||||||
1e-6 );
|
|
||||||
|
|
||||||
if ( foundOverlap )
|
|
||||||
{
|
|
||||||
if ( connectionPolygon ) ( *connectionPolygon ) = polygon;
|
|
||||||
if ( connectionIntersections ) ( *connectionIntersections ) = intersections;
|
|
||||||
return ( cvf::StructGridInterface::FaceType )( fIdx );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cvf::StructGridInterface::NO_FACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -529,10 +460,10 @@ const QString RigNNCData::getNNCDataTypeFromScalarResultIndex( const RigEclipseR
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RigNNCData::isNative( QString nncDataType ) const
|
bool RigNNCData::isNative( QString nncDataType ) const
|
||||||
{
|
{
|
||||||
if ( nncDataType == RigNNCData::propertyNameCombTrans() || nncDataType == RigNNCData::propertyNameFluxGas() ||
|
if ( nncDataType == RiaDefines::propertyNameCombTrans() || nncDataType == RiaDefines::propertyNameFluxGas() ||
|
||||||
nncDataType == RigNNCData::propertyNameFluxOil() || nncDataType == RigNNCData::propertyNameFluxWat() ||
|
nncDataType == RiaDefines::propertyNameFluxOil() || nncDataType == RiaDefines::propertyNameFluxWat() ||
|
||||||
nncDataType == RigNNCData::propertyNameRiCombMult() || nncDataType == RigNNCData::propertyNameRiCombTrans() ||
|
nncDataType == RiaDefines::propertyNameRiCombMult() || nncDataType == RiaDefines::propertyNameRiCombTrans() ||
|
||||||
nncDataType == RigNNCData::propertyNameRiCombTransByArea() )
|
nncDataType == RiaDefines::propertyNameRiCombTransByArea() )
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "RiaNncDefines.h"
|
||||||
|
|
||||||
|
#include "RigNncConnection.h"
|
||||||
|
|
||||||
#include "cvfObject.h"
|
#include "cvfObject.h"
|
||||||
#include "cvfStructGrid.h"
|
#include "cvfStructGrid.h"
|
||||||
#include "cvfVector3.h"
|
#include "cvfVector3.h"
|
||||||
@ -31,28 +35,6 @@ class RigMainGrid;
|
|||||||
class RigCell;
|
class RigCell;
|
||||||
class RigEclipseResultAddress;
|
class RigEclipseResultAddress;
|
||||||
|
|
||||||
class RigConnection
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RigConnection()
|
|
||||||
: m_c1GlobIdx( cvf::UNDEFINED_SIZE_T )
|
|
||||||
, m_c1Face( cvf::StructGridInterface::NO_FACE )
|
|
||||||
, m_c2GlobIdx( cvf::UNDEFINED_SIZE_T )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasCommonArea() const
|
|
||||||
{
|
|
||||||
return m_polygon.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t m_c1GlobIdx;
|
|
||||||
cvf::StructGridInterface::FaceType m_c1Face;
|
|
||||||
size_t m_c2GlobIdx;
|
|
||||||
|
|
||||||
std::vector<cvf::Vec3d> m_polygon;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RigNNCData : public cvf::Object
|
class RigNNCData : public cvf::Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -63,53 +45,15 @@ public:
|
|||||||
NNC_GENERATED
|
NNC_GENERATED
|
||||||
};
|
};
|
||||||
|
|
||||||
static QString propertyNameFluxWat()
|
|
||||||
{
|
|
||||||
return "FLRWAT";
|
|
||||||
}
|
|
||||||
static QString propertyNameFluxOil()
|
|
||||||
{
|
|
||||||
return "FLROIL";
|
|
||||||
}
|
|
||||||
static QString propertyNameFluxGas()
|
|
||||||
{
|
|
||||||
return "FLRGAS";
|
|
||||||
}
|
|
||||||
static QString propertyNameCombTrans()
|
|
||||||
{
|
|
||||||
return "TRAN";
|
|
||||||
}
|
|
||||||
static QString propertyNameRiCombTrans()
|
|
||||||
{
|
|
||||||
return "riTRAN";
|
|
||||||
}
|
|
||||||
static QString propertyNameRiCombTransByArea()
|
|
||||||
{
|
|
||||||
return "riTRANbyArea";
|
|
||||||
}
|
|
||||||
static QString propertyNameRiCombMult()
|
|
||||||
{
|
|
||||||
return "riMULT";
|
|
||||||
}
|
|
||||||
|
|
||||||
RigNNCData();
|
RigNNCData();
|
||||||
|
|
||||||
void processConnections( const RigMainGrid& mainGrid );
|
void processNativeConnections( const RigMainGrid& mainGrid );
|
||||||
|
void computeCompleteSetOfNncs( const RigMainGrid* mainGrid );
|
||||||
|
|
||||||
static cvf::StructGridInterface::FaceType calculateCellFaceOverlap( const RigCell& c1,
|
void setConnections( std::vector<RigConnection>& connections );
|
||||||
const RigCell& c2,
|
size_t nativeConnectionCount() const;
|
||||||
const RigMainGrid& mainGrid,
|
|
||||||
std::vector<size_t>* connectionPolygon,
|
|
||||||
std::vector<cvf::Vec3d>* connectionIntersections );
|
|
||||||
|
|
||||||
std::vector<RigConnection>& connections()
|
const std::vector<RigConnection>& connections() const;
|
||||||
{
|
|
||||||
return m_connections;
|
|
||||||
}
|
|
||||||
const std::vector<RigConnection>& connections() const
|
|
||||||
{
|
|
||||||
return m_connections;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<double>& makeStaticConnectionScalarResult( QString nncDataType );
|
std::vector<double>& makeStaticConnectionScalarResult( QString nncDataType );
|
||||||
const std::vector<double>* staticConnectionScalarResult( const RigEclipseResultAddress& resVarAddr ) const;
|
const std::vector<double>* staticConnectionScalarResult( const RigEclipseResultAddress& resVarAddr ) const;
|
||||||
@ -146,6 +90,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RigConnection> m_connections;
|
std::vector<RigConnection> m_connections;
|
||||||
|
size_t m_nativeConnectionCount;
|
||||||
std::map<QString, std::vector<std::vector<double>>> m_connectionResults;
|
std::map<QString, std::vector<std::vector<double>>> m_connectionResults;
|
||||||
std::map<RigEclipseResultAddress, QString> m_resultAddrToNNCDataType;
|
std::map<RigEclipseResultAddress, QString> m_resultAddrToNNCDataType;
|
||||||
};
|
};
|
||||||
|
39
ApplicationCode/ReservoirDataModel/RigNncConnection.cpp
Normal file
39
ApplicationCode/ReservoirDataModel/RigNncConnection.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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 "RigNncConnection.h"
|
||||||
|
|
||||||
|
#include "cvfMath.h"
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RigConnection::RigConnection()
|
||||||
|
: m_c1GlobIdx( cvf::UNDEFINED_SIZE_T )
|
||||||
|
, m_c1Face( cvf::StructGridInterface::NO_FACE )
|
||||||
|
, m_c2GlobIdx( cvf::UNDEFINED_SIZE_T )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RigConnection::hasCommonArea() const
|
||||||
|
{
|
||||||
|
return m_polygon.size() > 0;
|
||||||
|
}
|
41
ApplicationCode/ReservoirDataModel/RigNncConnection.h
Normal file
41
ApplicationCode/ReservoirDataModel/RigNncConnection.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 Equinor ASA
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cvfStructGrid.h"
|
||||||
|
#include "cvfVector3.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
class RigConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RigConnection();
|
||||||
|
|
||||||
|
bool hasCommonArea() const;
|
||||||
|
|
||||||
|
size_t m_c1GlobIdx;
|
||||||
|
cvf::StructGridInterface::FaceType m_c1Face;
|
||||||
|
size_t m_c2GlobIdx;
|
||||||
|
|
||||||
|
std::vector<cvf::Vec3d> m_polygon;
|
||||||
|
};
|
@ -103,9 +103,9 @@ RigNumberOfFloodedPoreVolumesCalculator::RigNumberOfFloodedPoreVolumesCalculator
|
|||||||
|
|
||||||
progress.incrementProgress();
|
progress.incrementProgress();
|
||||||
|
|
||||||
// TODO: oil or gas flowrate
|
// TODO: oil or gas flow rate
|
||||||
std::vector<const std::vector<double>*> flowrateNNCatAllTimeSteps;
|
std::vector<const std::vector<double>*> flowrateNNCatAllTimeSteps;
|
||||||
QString nncConnectionProperty = mainGrid->nncData()->propertyNameFluxWat();
|
QString nncConnectionProperty = RiaDefines::propertyNameFluxWat();
|
||||||
|
|
||||||
progress.incrementProgress();
|
progress.incrementProgress();
|
||||||
|
|
||||||
|
@ -536,7 +536,7 @@ void RigReservoirBuilderMock::addFaults( RigEclipseCaseData* eclipseCase )
|
|||||||
grid->setFaults( faults );
|
grid->setFaults( faults );
|
||||||
|
|
||||||
// NNCs
|
// NNCs
|
||||||
std::vector<RigConnection>& nncConnections = grid->nncData()->connections();
|
std::vector<RigConnection> nncConnections;
|
||||||
{
|
{
|
||||||
size_t i1 = 2;
|
size_t i1 = 2;
|
||||||
size_t j1 = 2;
|
size_t j1 = 2;
|
||||||
@ -561,8 +561,10 @@ void RigReservoirBuilderMock::addFaults( RigEclipseCaseData* eclipseCase )
|
|||||||
addNnc( grid, i1, j1, k1, i2, j2, k2, nncConnections );
|
addNnc( grid, i1, j1, k1, i2, j2, k2, nncConnections );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grid->nncData()->setConnections( nncConnections );
|
||||||
|
|
||||||
std::vector<double>& tranVals = grid->nncData()->makeStaticConnectionScalarResult(
|
std::vector<double>& tranVals = grid->nncData()->makeStaticConnectionScalarResult(
|
||||||
RigNNCData::propertyNameCombTrans() );
|
RiaDefines::propertyNameCombTrans() );
|
||||||
for ( size_t cIdx = 0; cIdx < tranVals.size(); ++cIdx )
|
for ( size_t cIdx = 0; cIdx < tranVals.size(); ++cIdx )
|
||||||
{
|
{
|
||||||
tranVals[cIdx] = 0.2;
|
tranVals[cIdx] = 0.2;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "RigSimulationWellCenterLineCalculator.h"
|
#include "RigSimulationWellCenterLineCalculator.h"
|
||||||
|
|
||||||
#include "RigCell.h"
|
#include "RigCell.h"
|
||||||
|
#include "RigCellFaceGeometryTools.h"
|
||||||
#include "RigEclipseCaseData.h"
|
#include "RigEclipseCaseData.h"
|
||||||
#include "RigMainGrid.h"
|
#include "RigMainGrid.h"
|
||||||
|
|
||||||
@ -800,11 +801,12 @@ private:
|
|||||||
std::vector<size_t> poygonIndices;
|
std::vector<size_t> poygonIndices;
|
||||||
std::vector<cvf::Vec3d> intersections;
|
std::vector<cvf::Vec3d> intersections;
|
||||||
|
|
||||||
auto contactFace = RigNNCData::calculateCellFaceOverlap( c1,
|
auto contactFace =
|
||||||
c2,
|
RigCellFaceGeometryTools::calculateCellFaceOverlap( c1,
|
||||||
*( m_eclipseCaseData->mainGrid() ),
|
c2,
|
||||||
&poygonIndices,
|
*( m_eclipseCaseData->mainGrid() ),
|
||||||
&intersections );
|
&poygonIndices,
|
||||||
|
&intersections );
|
||||||
|
|
||||||
if ( contactFace != cvf::StructGridInterface::NO_FACE )
|
if ( contactFace != cvf::StructGridInterface::NO_FACE )
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
// for more details.
|
// for more details.
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RigSimWellData.h"
|
#include "RigSimWellData.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user