Fault reactivation gridding update (#10855)

Rewrite grid generator - grid based on eclipse model layers in reservoir.
This commit is contained in:
jonjenssen
2023-11-20 15:39:17 +01:00
committed by GitHub
parent 0852f857a0
commit 2b795bf499
20 changed files with 1242 additions and 659 deletions

View File

@@ -51,6 +51,7 @@
#include "RimEclipseCaseCollection.h"
#include "RimEclipseView.h"
#include "RimEnsembleWellLogsCollection.h"
#include "RimFaultReactivationModelCollection.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechCase.h"
@@ -685,6 +686,19 @@ bool RiaApplication::loadProject( const QString& projectFileName, ProjectLoadAct
cas->intersectionViewCollection()->syncFromExistingIntersections( false );
}
{
std::vector<Rim3dView*> views;
m_project->allViews( views );
for ( auto view : views )
{
if ( auto eclipseView = dynamic_cast<RimEclipseView*>( view ) )
{
eclipseView->faultReactivationModelCollection()->loadDataAndUpdate();
}
}
}
for ( RimOilField* oilField : m_project->oilFields )
{
for ( auto seisView : oilField->seismicViewCollection()->views() )

View File

@@ -93,16 +93,10 @@ void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked )
normal *= eclView->ownerCase()->characteristicCellSize();
normal *= 3;
auto antiNormal = -1.0 * normal;
if ( !eclView->mainGrid()->isFaceNormalsOutwards() ) normal = normal * -1.0;
auto camPos = eclView->viewer()->mainCamera()->position();
auto target1 = cell.faceCenter( face );
auto candidate1 = target1 + normal;
auto candidate2 = target1 + antiNormal;
auto target2 = candidate1;
if ( camPos.pointDistance( candidate2 ) < camPos.pointDistance( candidate1 ) ) target2 = candidate2;
cvf::Vec3d target1 = cell.faceCenter( face );
cvf::Vec3d target2 = target1 + normal;
// get base directory for our work, should be a new, empty folder somewhere
QString defaultDir =
@@ -112,7 +106,8 @@ void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked )
if ( baseDir.isNull() || baseDir.isEmpty() ) return;
QString errMsg;
auto model = eclView->faultReactivationModelCollection()->addNewModel( rimFault, target1, target2, baseDir, errMsg );
auto model =
eclView->faultReactivationModelCollection()->addNewModel( rimFault, currentCellIndex, face, target1, target2, baseDir, errMsg );
if ( model != nullptr )
{
model->updateTimeSteps();

View File

@@ -89,7 +89,7 @@ std::pair<bool, std::string> RifFaultReactivationModelExporter::exportToStream(
std::vector<std::function<std::pair<bool, std::string>()>> methods = {
[&]() { return printHeading( stream, applicationNameAndVersion ); },
[&]() { return printParts( stream, *model, partNames, borders, faces, boundaries, materialNames ); },
[&]() { return printAssembly( stream, *model, partNames, rimModel.localCoordSysNormalsXY() ); },
[&]() { return printAssembly( stream, *model, partNames, model->modelLocalNormalsXY() ); },
[&]()
{
return printMaterials( stream, rimModel, materialNames, *dataAccess, exportDirectory, partNames, useGridDensity, useGridElasticProperties );

View File

@@ -110,26 +110,10 @@ void RivFaultReactivationModelPartMgr::appendGeometryPartsToModel( cvf::ModelBas
{
if ( !m_canUseShaders ) return;
auto plane = m_frm->faultPlane();
if ( plane->isValid() && m_frm->showFaultPlane() )
{
cvf::Vec3dArray displayPoints;
displayPoints.reserve( plane->rect().size() );
for ( auto& vOrg : plane->rect() )
{
displayPoints.add( displayCoordTransform->transformToDisplayCoord( vOrg ) );
}
cvf::ref<cvf::Part> quadPart = createSingleTexturedQuadPart( displayPoints, plane->texture(), false );
vizModel->addPart( quadPart.p() );
}
auto theModel = m_frm->model();
if ( theModel->isValid() && m_frm->showModel() )
{
for ( auto part : theModel->allModelParts() )
for ( auto part = 0; part < RigFaultReactivationModel::numModelParts(); part++ )
{
cvf::Vec3dArray displayPoints;
displayPoints.reserve( theModel->rect( part ).size() );

View File

@@ -282,10 +282,11 @@ RimUserDefinedFilter* RimCellFilterCollection::addNewUserDefinedFilter( RimCase*
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimUserDefinedIndexFilter* RimCellFilterCollection::addNewUserDefinedIndexFilter( RimCase* srcCase )
RimUserDefinedIndexFilter* RimCellFilterCollection::addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector<size_t>& defCellIndexes )
{
RimUserDefinedIndexFilter* pFilter = new RimUserDefinedIndexFilter();
pFilter->setCase( srcCase );
pFilter->setCellIndexes( defCellIndexes );
addFilter( pFilter );
onFilterUpdated( pFilter );
return pFilter;

View File

@@ -56,7 +56,7 @@ public:
RimCellRangeFilter* addNewCellRangeFilter( RimCase* srcCase, int gridIndex, int sliceDirection = -1, int defaultSlice = -1 );
RimCellIndexFilter* addNewCellIndexFilter( RimCase* srcCase );
RimUserDefinedFilter* addNewUserDefinedFilter( RimCase* srcCase );
RimUserDefinedIndexFilter* addNewUserDefinedIndexFilter( RimCase* srcCase );
RimUserDefinedIndexFilter* addNewUserDefinedIndexFilter( RimCase* srcCase, const std::vector<size_t>& defCellIndexes = {} );
void removeFilter( RimCellFilter* filter );

View File

@@ -47,6 +47,20 @@ RimUserDefinedIndexFilter::~RimUserDefinedIndexFilter()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimUserDefinedIndexFilter::setCellIndexes( std::vector<size_t> cellIndexes )
{
std::vector<int> cIdxs;
for ( auto cIdx : cellIndexes )
{
cIdxs.push_back( (int)cIdx );
}
m_individualCellIndexes.setValue( cIdxs );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -36,6 +36,8 @@ public:
RimUserDefinedIndexFilter();
~RimUserDefinedIndexFilter() override;
void setCellIndexes( std::vector<size_t> cellIndexes );
void updateCellIndexFilter( cvf::UByteArray* includeVisibility, cvf::UByteArray* excludeVisibility, int gridIndex ) override;
protected:

View File

@@ -21,16 +21,6 @@
namespace RimFaultReactivation
{
enum class ModelParts
{
HiPart1,
MidPart1,
LowPart1,
HiPart2,
MidPart2,
LowPart2
};
enum class GridPart
{
PART1,

View File

@@ -26,8 +26,11 @@
#include "RifJsonEncodeDecode.h"
#include "RifParameterXmlReader.h"
#include "RigActiveCellInfo.h"
#include "RigBasicPlane.h"
#include "RigEclipseCaseData.h"
#include "RigFaultReactivationModel.h"
#include "RigFaultReactivationModelGenerator.h"
#include "RigPolyLinesData.h"
#include "WellPathCommands/PointTangentManipulator/RicPolyline3dEditor.h"
@@ -78,34 +81,34 @@ RimFaultReactivationModel::RimFaultReactivationModel()
CAF_PDM_InitFieldNoDefault( &m_geomechCase, "GeoMechCase", "Global GeoMech Model" );
CAF_PDM_InitFieldNoDefault( &m_baseDir, "BaseDirectory", "Working folder" );
CAF_PDM_InitField( &m_modelThickness, "ModelThickness", 100.0, "Model Cell Thickness" );
CAF_PDM_InitField( &m_extentHorizontal, "HorizontalExtent", 1000.0, "Horizontal Extent" );
CAF_PDM_InitField( &m_extentVerticalAbove, "VerticalExtentAbove", 200.0, "Vertical Extent Above Anchor" );
m_extentVerticalAbove.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
m_extentVerticalAbove.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP );
CAF_PDM_InitField( &m_extentVerticalBelow, "VerticalExtentBelow", 200.0, "Vertical Extent Below Anchor" );
m_extentVerticalBelow.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
m_extentVerticalBelow.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP );
CAF_PDM_InitField( &m_modelExtentFromAnchor, "ModelExtentFromAnchor", 1000.0, "Horz. Extent from Anchor" );
CAF_PDM_InitField( &m_modelMinZ, "ModelMinZ", 0.0, "Start Depth" );
CAF_PDM_InitField( &m_modelBelowSize, "ModelBelowSize", 500.0, "Depth Below Fault" );
CAF_PDM_InitField( &m_showFaultPlane, "ShowFaultPlane", true, "Show Fault Plane" );
CAF_PDM_InitField( &m_showModelPlane, "ShowModelPlane", false, "Show 2D Model" );
CAF_PDM_InitFieldNoDefault( &m_startCellIndex, "StartCellIndex", "Start Cell Index" );
CAF_PDM_InitFieldNoDefault( &m_startCellFace, "StartCellFace", "Start Cell Face" );
m_startCellIndex = 0;
m_startCellFace = cvf::StructGridInterface::FaceType::NO_FACE;
CAF_PDM_InitField( &m_faultExtendUpwards, "FaultExtendUpwards", 100.0, "Fault Extension Above Reservoir" );
m_faultExtendUpwards.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_faultExtendDownwards, "FaultExtendDownwards", 100.0, "Fault Extension Below Reservoir" );
m_faultExtendDownwards.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_showModelPlane, "ShowModelPlane", true, "Show 2D Model" );
CAF_PDM_InitFieldNoDefault( &m_fault, "Fault", "Fault" );
m_fault.uiCapability()->setUiReadOnly( true );
CAF_PDM_InitField( &m_faultPlaneColor, "FaultPlaneColor", cvf::Color3f( cvf::Color3f::GRAY ), "Plane Color" );
CAF_PDM_InitField( &m_modelPart1Color, "ModelPart1Color", cvf::Color3f( cvf::Color3f::GREEN ), "Part 1 Color" );
CAF_PDM_InitField( &m_modelPart2Color, "ModelPart2Color", cvf::Color3f( cvf::Color3f::BLUE ), "Part 2 Color" );
CAF_PDM_InitField( &m_numberOfCellsHorzPart1, "NumberOfCellsHorzPart1", 20, "Horizontal Number of Cells, Part 1" );
CAF_PDM_InitField( &m_numberOfCellsHorzPart2, "NumberOfCellsHorzPart2", 20, "Horizontal Number of Cells, Part 2" );
CAF_PDM_InitField( &m_numberOfCellsVertUp, "NumberOfCellsVertUp", 20, "Vertical Number of Cells, Upper Part" );
CAF_PDM_InitField( &m_numberOfCellsVertMid, "NumberOfCellsVertMid", 20, "Vertical Number of Cells, Middle Part" );
CAF_PDM_InitField( &m_numberOfCellsVertLow, "NumberOfCellsVertLow", 20, "Vertical Number of Cells, Lower Part" );
CAF_PDM_InitField( &m_maxReservoirCellHeight, "MaxReservoirCellHeight", 20.0, "Max. Reservoir Cell Height" );
CAF_PDM_InitField( &m_cellHeightGrowFactor, "CellHeightGrowFactor", 1.05, "Cell Height Grow Factor Outside Reservoir" );
CAF_PDM_InitField( &m_useLocalCoordinates, "UseLocalCoordinates", false, "Export Using Local Coordinates" );
@@ -115,11 +118,11 @@ RimFaultReactivationModel::RimFaultReactivationModel()
m_selectedTimeSteps.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_selectedTimeSteps.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
CAF_PDM_InitField( &m_useGridPorePressure, "UseGridPorePressure", true, "Use Grid Pore Pressure" );
CAF_PDM_InitField( &m_useGridVoidRatio, "UseGridVoidRatio", true, "Use Grid Void Ratio" );
CAF_PDM_InitField( &m_useGridTemperature, "UseGridTemperature", true, "Use Grid Temperature" );
CAF_PDM_InitField( &m_useGridDensity, "UseGridDensity", true, "Use Grid Density" );
CAF_PDM_InitField( &m_useGridElasticProperties, "UseGridElasticProperties", true, "Use Grid Elastic Properties" );
CAF_PDM_InitField( &m_useGridPorePressure, "UseGridPorePressure", true, "Output Grid Pore Pressure" );
CAF_PDM_InitField( &m_useGridVoidRatio, "UseGridVoidRatio", true, "Output Grid Void Ratio" );
CAF_PDM_InitField( &m_useGridTemperature, "UseGridTemperature", true, "Output Grid Temperature" );
CAF_PDM_InitField( &m_useGridDensity, "UseGridDensity", false, "Output Grid Density" );
CAF_PDM_InitField( &m_useGridElasticProperties, "UseGridElasticProperties", false, "Output Grid Elastic Properties" );
CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" );
m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
@@ -134,8 +137,7 @@ RimFaultReactivationModel::RimFaultReactivationModel()
setDeletable( true );
m_faultPlane = new RigBasicPlane();
m_modelPlane = new RigFaultReactivationModel();
m_2Dmodel = new RigFaultReactivationModel();
}
//--------------------------------------------------------------------------------------------------
@@ -145,14 +147,6 @@ RimFaultReactivationModel::~RimFaultReactivationModel()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultReactivationModel::initAfterRead()
{
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -220,9 +214,11 @@ std::pair<bool, std::string> RimFaultReactivationModel::validateBeforeRun() cons
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultReactivationModel::setFault( RimFaultInView* fault )
void RimFaultReactivationModel::setFaultInformation( RimFaultInView* fault, size_t cellIndex, cvf::StructGridInterface::FaceType face )
{
m_fault = fault;
m_startCellIndex = cellIndex;
m_startCellFace = face;
}
//--------------------------------------------------------------------------------------------------
@@ -300,46 +296,31 @@ void RimFaultReactivationModel::updateVisualization()
auto view = firstAncestorOrThisOfType<Rim3dView>();
if ( !view ) return;
if ( m_startCellIndex() == 0 ) return;
if ( m_startCellFace() == cvf::StructGridInterface::FaceType::NO_FACE ) return;
if ( m_targets.size() < 2 ) return;
auto normal = m_targets[1]->targetPointXYZ() - m_targets[0]->targetPointXYZ();
normal.z() = normal.z() * view->scaleZ() * view->scaleZ();
normal.normalize();
normal.z() = 0.0;
if ( !normal.normalize() ) return;
m_faultPlane->setPlane( m_targets[0]->targetPointXYZ(), normal );
m_faultPlane->setMaxExtentFromAnchor( m_extentHorizontal, m_extentVerticalAbove, m_extentVerticalBelow );
m_faultPlane->setColor( m_faultPlaneColor );
m_faultPlane->updateRect();
double maxZ = m_faultPlane->maxDepth();
auto [topInt, bottomInt] = m_faultPlane->intersectTopBottomLine();
cvf::Vec3d zdir( 0, 0, 1 );
auto modelNormal = normal ^ zdir;
auto modelNormal = normal ^ cvf::Vec3d::Z_AXIS;
modelNormal.normalize();
m_modelPlane->setPlane( m_targets[0]->targetPointXYZ(), modelNormal );
m_modelPlane->setFaultPlaneIntersect( topInt, bottomInt );
m_modelPlane->setMaxExtentFromAnchor( m_modelExtentFromAnchor, m_modelMinZ, maxZ + m_modelBelowSize );
m_modelPlane->setPartColors( m_modelPart1Color, m_modelPart2Color );
m_modelPlane->setCellCounts( m_numberOfCellsHorzPart1,
m_numberOfCellsHorzPart2,
m_numberOfCellsVertUp,
m_numberOfCellsVertMid,
m_numberOfCellsVertLow );
m_modelPlane->setThickness( m_modelThickness );
auto generator = std::make_shared<RigFaultReactivationModelGenerator>( m_targets[0]->targetPointXYZ(), modelNormal );
generator->setFault( m_fault()->faultGeometry() );
generator->setGrid( eclipseCase()->mainGrid() );
generator->setActiveCellInfo( eclipseCase()->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ) );
generator->setModelSize( m_modelMinZ, m_modelBelowSize, m_modelExtentFromAnchor );
generator->setFaultBufferDepth( m_faultExtendUpwards, m_faultExtendDownwards );
generator->setModelThickness( m_modelThickness );
generator->setModelGriddingOptions( m_maxReservoirCellHeight, m_cellHeightGrowFactor, m_numberOfCellsHorzPart1, m_numberOfCellsHorzPart2 );
generator->setupLocalCoordinateTransform();
generator->setUseLocalCoordinates( m_useLocalCoordinates );
// set up transform to local coordinate system
{
auto [xVec, yVec] = localCoordSysNormalsXY();
cvf::Mat4d transform = cvf::Mat4d::fromCoordSystemAxes( &xVec, &yVec, &cvf::Vec3d::Z_AXIS );
cvf::Vec3d center = m_targets[0]->targetPointXYZ() * -1.0;
center.z() = 0.0;
center.transformPoint( transform );
transform.setTranslation( center );
m_modelPlane->setLocalCoordTransformation( transform );
m_modelPlane->setUseLocalCoordinates( m_useLocalCoordinates );
}
m_modelPlane->updateGeometry();
m_2Dmodel->setPartColors( m_modelPart1Color, m_modelPart2Color );
m_2Dmodel->setGenerator( generator );
m_2Dmodel->updateGeometry( m_startCellIndex, (cvf::StructGridInterface::FaceType)m_startCellFace() );
view->scheduleCreateDisplayModelAndRedraw();
}
@@ -407,28 +388,12 @@ RivFaultReactivationModelPartMgr* RimFaultReactivationModel::partMgr()
return m_partMgr.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigBasicPlane> RimFaultReactivationModel::faultPlane() const
{
return m_faultPlane;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigFaultReactivationModel> RimFaultReactivationModel::model() const
{
return m_modelPlane;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFaultReactivationModel::showFaultPlane() const
{
return m_showFaultPlane;
return m_2Dmodel;
}
//--------------------------------------------------------------------------------------------------
@@ -439,24 +404,6 @@ bool RimFaultReactivationModel::showModel() const
return m_showModelPlane;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<cvf::Vec3d, cvf::Vec3d> RimFaultReactivationModel::localCoordSysNormalsXY() const
{
cvf::Vec3d yNormal = m_modelPlane->normal();
cvf::Vec3d xNormal = yNormal ^ cvf::Vec3d::Z_AXIS;
xNormal.z() = 0.0;
yNormal.z() = 0.0;
xNormal.normalize();
yNormal.normalize();
yNormal = xNormal ^ cvf::Vec3d::Z_AXIS;
return std::make_pair( xNormal, yNormal );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -468,14 +415,6 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm
genGrp->add( &m_baseDir );
genGrp->add( &m_geomechCase );
auto faultGrp = uiOrdering.addNewGroup( "Fault Plane" );
faultGrp->add( &m_showFaultPlane );
faultGrp->add( &m_faultPlaneColor );
faultGrp->add( &m_extentHorizontal );
faultGrp->add( &m_extentVerticalAbove );
faultGrp->add( &m_extentVerticalBelow );
auto modelGrp = uiOrdering.addNewGroup( "2D Model" );
modelGrp->add( &m_showModelPlane );
@@ -484,21 +423,23 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm
sizeModelGrp->add( &m_modelMinZ );
sizeModelGrp->add( &m_modelBelowSize );
auto gridModelGrp = modelGrp->addNewGroup( "Grid" );
auto faultGrp = modelGrp->addNewGroup( "Fault" );
faultGrp->add( &m_faultExtendUpwards );
faultGrp->add( &m_faultExtendDownwards );
auto gridModelGrp = modelGrp->addNewGroup( "Grid" );
gridModelGrp->add( &m_modelThickness );
gridModelGrp->add( &m_maxReservoirCellHeight );
gridModelGrp->add( &m_cellHeightGrowFactor );
gridModelGrp->add( &m_numberOfCellsHorzPart1 );
gridModelGrp->add( &m_numberOfCellsHorzPart2 );
gridModelGrp->add( &m_numberOfCellsVertUp );
gridModelGrp->add( &m_numberOfCellsVertMid );
gridModelGrp->add( &m_numberOfCellsVertLow );
gridModelGrp->add( &m_useLocalCoordinates );
auto timeStepGrp = uiOrdering.addNewGroup( "Time Steps" );
timeStepGrp->add( &m_timeStepFilter );
timeStepGrp->add( &m_selectedTimeSteps );
auto propertiesGrp = uiOrdering.addNewGroup( "Properties" );
auto propertiesGrp = uiOrdering.addNewGroup( "Export" );
propertiesGrp->add( &m_useLocalCoordinates );
propertiesGrp->add( &m_useGridPorePressure );
propertiesGrp->add( &m_useGridVoidRatio );
propertiesGrp->add( &m_useGridTemperature );
@@ -521,7 +462,12 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm
//--------------------------------------------------------------------------------------------------
void RimFaultReactivationModel::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
if ( changedField == &m_userDescription )
if ( ( changedField == &m_useGridPorePressure ) || ( changedField == &m_useGridVoidRatio ) || ( changedField == &m_useGridTemperature ) ||
( changedField == &m_useGridDensity ) || ( changedField == &m_useGridElasticProperties ) )
{
return; // do nothing
}
else if ( changedField == &m_userDescription )
{
updateConnectedEditors();
}
@@ -544,7 +490,7 @@ void RimFaultReactivationModel::defineEditorAttribute( const caf::PdmFieldHandle
tvAttribute->resizePolicy = caf::PdmUiTableViewEditorAttribute::RESIZE_TO_FIT_CONTENT;
}
}
else if ( ( field == &m_extentVerticalAbove ) || ( field == &m_extentVerticalBelow ) )
else if ( ( field == &m_faultExtendUpwards ) || ( field == &m_faultExtendDownwards ) )
{
auto* attr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute );
@@ -693,12 +639,13 @@ QString RimFaultReactivationModel::baseFilename() const
//--------------------------------------------------------------------------------------------------
bool RimFaultReactivationModel::exportModelSettings()
{
if ( m_faultPlane.isNull() ) return false;
if ( m_2Dmodel.isNull() ) return false;
if ( !m_2Dmodel->isValid() ) return false;
QMap<QString, QVariant> settings;
auto [topPosition, bottomPosition] = m_faultPlane->intersectTopBottomLine();
auto faultNormal = m_faultPlane->normal();
auto [topPosition, bottomPosition] = m_2Dmodel->faultTopBottom();
auto faultNormal = m_2Dmodel->faultNormal();
// make sure we move horizontally
faultNormal.z() = 0.0;
@@ -732,11 +679,8 @@ bool RimFaultReactivationModel::extractAndExportModelData()
selectedTimeStepIndexes.push_back( idx - m_availableTimeSteps.begin() );
}
auto grid = eCase->mainGrid();
// extract data for each timestep
m_dataAccess = std::make_shared<RimFaultReactivationDataAccess>( eCase, geoMechCase(), selectedTimeStepIndexes );
model()->generateElementSets( m_dataAccess.get(), grid );
m_dataAccess->extractModelData( *model() );
return true;

View File

@@ -28,12 +28,12 @@
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
// Include to make Pdm work for cvf::Color
#include "cafPdmFieldCvfColor.h"
#include "cvfColor3.h"
#include "cvfStructGrid.h"
#include "cvfVector3.h"
#include <QDateTime>
@@ -79,7 +79,7 @@ public:
std::pair<bool, std::string> validateBeforeRun() const;
void setFault( RimFaultInView* fault );
void setFaultInformation( RimFaultInView* fault, size_t cellIndex, cvf::StructGridInterface::FaceType face );
RimFaultInView* fault() const;
void setTargets( cvf::Vec3d target1, cvf::Vec3d target2 );
@@ -91,6 +91,7 @@ public:
void deleteTarget( RimPolylineTarget* targetToDelete ) override;
void updateEditorsAndVisualization() override;
void updateVisualization() override;
std::vector<RimPolylineTarget*> activeTargets() const override;
bool pickingEnabled() const override;
caf::PickEventHandler* pickEventHandler() const override;
@@ -98,14 +99,9 @@ public:
// polyline data interface
cvf::ref<RigPolyLinesData> polyLinesData() const override;
cvf::ref<RigBasicPlane> faultPlane() const;
bool showFaultPlane() const;
cvf::ref<RigFaultReactivationModel> model() const;
bool showModel() const;
std::pair<cvf::Vec3d, cvf::Vec3d> localCoordSysNormalsXY() const;
bool extractAndExportModelData();
QString baseDir() const;
@@ -142,8 +138,6 @@ protected:
RimEclipseCase* eclipseCase();
RimGeoMechCase* geoMechCase();
void initAfterRead() override;
QString baseFilename() const;
bool exportModelSettings();
@@ -160,24 +154,24 @@ private:
caf::PdmPtrField<RimFaultInView*> m_fault;
caf::PdmPtrField<RimGeoMechCase*> m_geomechCase;
caf::PdmChildArrayField<RimPolylineTarget*> m_targets;
caf::PdmField<cvf::Color3f> m_faultPlaneColor;
caf::PdmField<cvf::Color3f> m_modelPart1Color;
caf::PdmField<cvf::Color3f> m_modelPart2Color;
caf::PdmField<bool> m_showFaultPlane;
caf::PdmField<bool> m_showModelPlane;
caf::PdmField<double> m_extentVerticalAbove;
caf::PdmField<double> m_extentVerticalBelow;
caf::PdmField<double> m_extentHorizontal;
caf::PdmField<double> m_modelExtentFromAnchor;
caf::PdmField<double> m_modelMinZ;
caf::PdmField<double> m_modelBelowSize;
caf::PdmField<double> m_faultExtendUpwards;
caf::PdmField<double> m_faultExtendDownwards;
caf::PdmField<double> m_maxReservoirCellHeight;
caf::PdmField<double> m_cellHeightGrowFactor;
caf::PdmField<int> m_numberOfCellsHorzPart1;
caf::PdmField<int> m_numberOfCellsHorzPart2;
caf::PdmField<int> m_numberOfCellsVertUp;
caf::PdmField<int> m_numberOfCellsVertMid;
caf::PdmField<int> m_numberOfCellsVertLow;
caf::PdmField<bool> m_useLocalCoordinates;
caf::PdmField<bool> m_useGridPorePressure;
@@ -186,8 +180,10 @@ private:
caf::PdmField<bool> m_useGridDensity;
caf::PdmField<bool> m_useGridElasticProperties;
cvf::ref<RigBasicPlane> m_faultPlane;
cvf::ref<RigFaultReactivationModel> m_modelPlane;
caf::PdmField<size_t> m_startCellIndex;
caf::PdmField<int> m_startCellFace;
cvf::ref<RigFaultReactivationModel> m_2Dmodel;
caf::PdmField<TimeStepFilterEnum> m_timeStepFilter;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;

View File

@@ -62,13 +62,15 @@ RimFaultReactivationModelCollection::~RimFaultReactivationModelCollection()
///
//--------------------------------------------------------------------------------------------------
RimFaultReactivationModel* RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault,
size_t cellIndex,
cvf::StructGridInterface::FaceType face,
cvf::Vec3d target1,
cvf::Vec3d target2,
QString baseDir,
QString& outErrMsg )
{
auto newModel = new RimFaultReactivationModel();
newModel->setFault( fault );
newModel->setFaultInformation( fault, cellIndex, face );
newModel->setBaseDir( baseDir );
newModel->setUserDescription( fault->name() );
newModel->setTargets( target1, target2 );
@@ -210,3 +212,14 @@ void RimFaultReactivationModelCollection::syncTimeSteps()
frm->updateTimeSteps();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFaultReactivationModelCollection::loadDataAndUpdate()
{
for ( auto& frm : m_models )
{
frm->updateVisualization();
}
}

View File

@@ -22,6 +22,7 @@
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cvfStructGrid.h"
#include "cvfVector3.h"
#include <vector>
@@ -50,7 +51,13 @@ public:
RimFaultReactivationModelCollection();
~RimFaultReactivationModelCollection() override;
RimFaultReactivationModel* addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2, QString baseDir, QString& errMsg );
RimFaultReactivationModel* addNewModel( RimFaultInView* fault,
size_t cellIndex,
cvf::StructGridInterface::FaceType face,
cvf::Vec3d target1,
cvf::Vec3d target2,
QString baseDir,
QString& errMsg );
bool empty();
int size();
@@ -67,6 +74,8 @@ public:
void syncTimeSteps();
void loadDataAndUpdate();
protected:
caf::PdmFieldHandle* userDescriptionField() override;

View File

@@ -92,6 +92,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.h
${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.h
${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.h
${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModelGenerator.h
${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.h
${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.h
${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.h
@@ -184,6 +185,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGriddedPart3d.cpp
${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModel.cpp
${CMAKE_CURRENT_LIST_DIR}/RigFaultReactivationModelGenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellAllocationOverTime.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellResultBranch.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellResultFrame.cpp

View File

@@ -18,6 +18,7 @@
#include "RigFaultReactivationModel.h"
#include "RigFaultReactivationModelGenerator.h"
#include "RigGriddedPart3d.h"
#include "RigPolyLinesData.h"
@@ -29,19 +30,9 @@
///
//--------------------------------------------------------------------------------------------------
RigFaultReactivationModel::RigFaultReactivationModel()
: m_maxZ( 0 )
, m_minZ( 0 )
, m_maxHorzExtent( 0 )
, m_isValid( false )
, m_cellCountHorzPart1( 1 )
, m_cellCountHorzPart2( 1 )
, m_cellCountVertUpper( 1 )
, m_cellCountVertMiddle( 1 )
, m_cellCountVertLower( 1 )
, m_thickness( 1.0 )
: m_isValid( false )
{
for ( auto part : allModelParts() )
for ( int part = 0; part < numModelParts(); part++ )
{
m_parts[part] = RigFRModelPart();
m_parts[part].texture = new cvf::TextureImage();
@@ -50,17 +41,15 @@ RigFaultReactivationModel::RigFaultReactivationModel()
m_parts[part].rect.reserve( 4 );
}
m_cornerIndexes[ModelParts::HiPart1] = { 2, 3, 7, 6 };
m_cornerIndexes[ModelParts::MidPart1] = { 1, 2, 6, 5 };
m_cornerIndexes[ModelParts::LowPart1] = { 0, 1, 5, 4 };
m_cornerIndexes[ModelParts::HiPart2] = { 6, 7, 11, 10 };
m_cornerIndexes[ModelParts::MidPart2] = { 5, 6, 10, 9 };
m_cornerIndexes[ModelParts::LowPart2] = { 4, 5, 9, 8 };
m_cornerIndexes[0] = { 0, 1, 7, 6 };
m_cornerIndexes[1] = { 1, 2, 8, 7 };
m_cornerIndexes[2] = { 2, 3, 9, 8 };
m_cornerIndexes[3] = { 3, 4, 10, 9 };
m_cornerIndexes[4] = { 4, 5, 11, 10 };
for ( auto part : allGridParts() )
{
m_3dparts[part] = std::make_shared<RigGriddedPart3d>( part == GridPart::PART2 );
m_3dparts[part] = std::make_shared<RigGriddedPart3d>();
}
}
@@ -71,14 +60,6 @@ RigFaultReactivationModel::~RigFaultReactivationModel()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimFaultReactivation::ModelParts> RigFaultReactivationModel::allModelParts() const
{
return { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1, ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -93,7 +74,8 @@ std::vector<RimFaultReactivation::GridPart> RigFaultReactivationModel::allGridPa
void RigFaultReactivationModel::reset()
{
m_isValid = false;
for ( auto part : allModelParts() )
for ( int part = 0; part < numModelParts(); part++ )
{
m_parts[part].rect.clear();
m_parts[part].rect.reserve( 4 );
@@ -113,27 +95,19 @@ bool RigFaultReactivationModel::isValid() const
return m_isValid;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal )
{
m_planeAnchor = anchorPoint;
m_planeNormal = normal;
reset();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color )
{
for ( auto part : { ModelParts::HiPart1, ModelParts::MidPart1, ModelParts::LowPart1 } )
const int oneSidedParts = numModelParts() / 2;
for ( int part = 0; part < oneSidedParts; part++ )
{
m_parts[part].texture->fill( cvf::Color4ub( part1Color.rByte(), part1Color.gByte(), part1Color.bByte(), 255 ) );
}
for ( auto part : { ModelParts::HiPart2, ModelParts::MidPart2, ModelParts::LowPart2 } )
for ( int part = oneSidedParts; part < numModelParts(); part++ )
{
m_parts[part].texture->fill( cvf::Color4ub( part2Color.rByte(), part2Color.gByte(), part2Color.bByte(), 255 ) );
}
@@ -142,167 +116,58 @@ void RigFaultReactivationModel::setPartColors( cvf::Color3f part1Color, cvf::Col
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ )
void RigFaultReactivationModel::setGenerator( std::shared_ptr<RigFaultReactivationModelGenerator> generator )
{
m_maxHorzExtent = maxExtentHorz;
m_minZ = minZ;
m_maxZ = maxZ;
reset();
m_generator = generator;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom )
std::pair<cvf::Vec3d, cvf::Vec3d> RigFaultReactivationModel::modelLocalNormalsXY() const
{
m_faultPlaneIntersectBottom = faultPlaneBottom;
m_faultPlaneIntersectTop = faultPlaneTop;
reset();
if ( m_generator.get() == nullptr )
{
return std::make_pair( cvf::Vec3d( 1.0, 0.0, 0.0 ), cvf::Vec3d( 0.0, 1.0, 0.0 ) );
}
return m_generator->modelLocalNormalsXY();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower )
{
m_cellCountHorzPart1 = horzPart1;
m_cellCountHorzPart2 = horzPart2;
m_cellCountVertUpper = vertUpper;
m_cellCountVertMiddle = vertMiddle;
m_cellCountVertLower = vertLower;
reset();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setThickness( double thickness )
{
m_thickness = thickness;
reset();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setLocalCoordTransformation( cvf::Mat4d transform )
{
m_localCoordTransform = transform;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::setUseLocalCoordinates( bool useLocalCoordinates )
{
m_3dparts[GridPart::PART1]->setUseLocalCoordinates( useLocalCoordinates );
m_3dparts[GridPart::PART2]->setUseLocalCoordinates( useLocalCoordinates );
}
//--------------------------------------------------------------------------------------------------
/// 7
/// 3----------|----------- 11
/// | | |
/// | | |
/// | | |
/// 2|---------|----------| 10
/// | \6 |
/// | X Anchor |
/// | \ |
/// 1-------------|------- 9
/// | 5| |
/// | | |
/// | | |
/// | | |
/// 0-------------|-------- 8
/// 4
///
///
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::updateGeometry()
void RigFaultReactivationModel::updateGeometry( size_t startCell, cvf::StructGridInterface::FaceType startFace )
{
reset();
m_generator->generateGeometry( startCell, startFace, m_3dparts[GridPart::PART1].get(), m_3dparts[GridPart::PART2].get() );
if ( ( m_maxHorzExtent <= 0.0 ) || ( m_minZ == m_maxZ ) )
{
return;
}
auto& frontPoints = m_generator->frontPoints();
auto& backPoints = m_generator->backPoints();
cvf::Vec3d zDir( 0, 0, 1 );
const int oneSideParts = numModelParts() / 2;
auto alongPlane = m_planeNormal ^ zDir;
alongPlane.normalize();
// how far from anchor point we should stop
const double extHorz = m_maxHorzExtent / 2.0;
auto mr = m_planeAnchor + alongPlane * extHorz;
auto ml = m_planeAnchor - alongPlane * extHorz;
cvf::Vec3dArray points;
points.resize( 12 );
points[0] = ml;
points[0].z() = -m_maxZ;
points[1] = ml;
points[1].z() = m_faultPlaneIntersectBottom.z();
points[2] = ml;
points[2].z() = m_faultPlaneIntersectTop.z();
points[3] = ml;
points[3].z() = -m_minZ;
points[4] = m_faultPlaneIntersectBottom;
points[4].z() = -m_maxZ;
points[5] = m_faultPlaneIntersectBottom;
points[6] = m_faultPlaneIntersectTop;
points[7] = m_faultPlaneIntersectTop;
points[7].z() = -m_minZ;
points[8] = mr;
points[8].z() = -m_maxZ;
points[9] = mr;
points[9].z() = m_faultPlaneIntersectBottom.z();
points[10] = mr;
points[10].z() = m_faultPlaneIntersectTop.z();
points[11] = mr;
points[11].z() = -m_minZ;
for ( auto part : allModelParts() )
for ( int part = 0; part < oneSideParts; part++ )
{
for ( auto i : m_cornerIndexes[part] )
{
m_parts[part].rect.push_back( points[i] );
m_parts[part].rect.push_back( frontPoints[i] );
}
}
for ( int part = 0; part < oneSideParts; part++ )
{
for ( auto i : m_cornerIndexes[part] )
{
m_parts[part + oneSideParts].rect.push_back( backPoints[i] );
}
}
m_isValid = true;
generateGrids( points );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RigFaultReactivationModel::normal() const
{
return m_planeNormal;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RigFaultReactivationModel::rect( RimFaultReactivation::ModelParts part ) const
std::vector<cvf::Vec3d> RigFaultReactivationModel::rect( int part ) const
{
return m_parts.at( part ).rect;
}
@@ -310,7 +175,7 @@ std::vector<cvf::Vec3d> RigFaultReactivationModel::rect( RimFaultReactivation::M
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::TextureImage> RigFaultReactivationModel::texture( RimFaultReactivation::ModelParts part ) const
cvf::ref<cvf::TextureImage> RigFaultReactivationModel::texture( int part ) const
{
return m_parts.at( part ).texture;
}
@@ -323,28 +188,6 @@ const std::vector<std::vector<cvf::Vec3d>>& RigFaultReactivationModel::meshLines
return m_3dparts.at( part )->meshLines();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::generateGrids( cvf::Vec3dArray points )
{
m_3dparts[GridPart::PART1]->generateGeometry( { points[0], points[1], points[2], points[3], points[4], points[5], points[6], points[7] },
m_cellCountHorzPart1,
m_cellCountVertLower,
m_cellCountVertMiddle,
m_cellCountVertUpper,
m_thickness );
m_3dparts[GridPart::PART2]->generateGeometry( { points[8], points[9], points[10], points[11], points[4], points[5], points[6], points[7] },
m_cellCountHorzPart2,
m_cellCountVertLower,
m_cellCountVertMiddle,
m_cellCountVertUpper,
m_thickness );
m_3dparts[GridPart::PART1]->generateLocalNodes( m_localCoordTransform );
m_3dparts[GridPart::PART2]->generateLocalNodes( m_localCoordTransform );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -356,10 +199,17 @@ std::shared_ptr<RigGriddedPart3d> RigFaultReactivationModel::grid( RimFaultReact
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModel::generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid )
const cvf::Vec3d RigFaultReactivationModel::faultNormal() const
{
for ( auto part : allGridParts() )
if ( m_generator.get() == nullptr ) return { 0.0, 0.0, 0.0 };
return m_generator->normal();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::pair<cvf::Vec3d, cvf::Vec3d> RigFaultReactivationModel::faultTopBottom() const
{
m_3dparts[part]->generateElementSets( dataAccess, grid );
}
if ( m_generator.get() == nullptr ) return std::make_pair( cvf::Vec3d(), cvf::Vec3d() );
return m_generator->faultTopBottomPoints();
}

View File

@@ -25,6 +25,7 @@
#include "cvfMatrix4.h"
#include "cvfObject.h"
#include "cvfPlane.h"
#include "cvfStructGrid.h"
#include "cvfTextureImage.h"
#include "cvfVector3.h"
@@ -35,6 +36,7 @@
class RigGriddedPart3d;
class RigMainGrid;
class RimFaultReactivationDataAccess;
class RigFaultReactivationModelGenerator;
class RigFRModelPart
{
@@ -52,70 +54,42 @@ public:
//==================================================================================================
class RigFaultReactivationModel : public cvf::Object
{
using ModelParts = RimFaultReactivation::ModelParts;
using GridPart = RimFaultReactivation::GridPart;
public:
RigFaultReactivationModel();
~RigFaultReactivationModel() override;
std::vector<ModelParts> allModelParts() const;
static int numModelParts() { return 10; };
std::vector<GridPart> allGridParts() const;
bool isValid() const;
void reset();
void setPlane( cvf::Vec3d anchorPoint, cvf::Vec3d normal );
void setFaultPlaneIntersect( cvf::Vec3d faultPlaneTop, cvf::Vec3d faultPlaneBottom );
void setMaxExtentFromAnchor( double maxExtentHorz, double minZ, double maxZ );
void setGenerator( std::shared_ptr<RigFaultReactivationModelGenerator> generator );
void setCellCounts( int horzPart1, int horzPart2, int vertUpper, int vertMiddle, int vertLower );
void setThickness( double thickness );
void setLocalCoordTransformation( cvf::Mat4d transform );
void setUseLocalCoordinates( bool useLocalCoordinates );
std::pair<cvf::Vec3d, cvf::Vec3d> modelLocalNormalsXY() const;
void updateGeometry();
cvf::Vec3d normal() const;
void updateGeometry( size_t startCell, cvf::StructGridInterface::FaceType startFace );
void setPartColors( cvf::Color3f part1Color, cvf::Color3f part2Color );
std::vector<cvf::Vec3d> rect( ModelParts part ) const;
cvf::ref<cvf::TextureImage> texture( ModelParts part ) const;
std::vector<cvf::Vec3d> rect( int nPart ) const;
cvf::ref<cvf::TextureImage> texture( int nPart ) const;
const std::vector<std::vector<cvf::Vec3d>>& meshLines( GridPart part ) const;
std::shared_ptr<RigGriddedPart3d> grid( GridPart part ) const;
void generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid );
protected:
void generateGrids( cvf::Vec3dArray points );
const cvf::Vec3d faultNormal() const;
const std::pair<cvf::Vec3d, cvf::Vec3d> faultTopBottom() const;
private:
cvf::Vec3d m_planeNormal;
cvf::Vec3d m_planeAnchor;
std::shared_ptr<RigFaultReactivationModelGenerator> m_generator;
cvf::Vec3d m_faultPlaneIntersectTop;
cvf::Vec3d m_faultPlaneIntersectBottom;
std::array<std::vector<int>, 5> m_cornerIndexes;
std::array<RigFRModelPart, 10> m_parts;
double m_maxHorzExtent;
double m_minZ;
double m_maxZ;
double m_thickness;
int m_cellCountHorzPart1;
int m_cellCountHorzPart2;
int m_cellCountVertUpper;
int m_cellCountVertMiddle;
int m_cellCountVertLower;
std::map<ModelParts, std::vector<int>> m_cornerIndexes;
std::map<ModelParts, RigFRModelPart> m_parts;
bool m_isValid;
std::map<GridPart, std::shared_ptr<RigGriddedPart3d>> m_3dparts;
cvf::Mat4d m_localCoordTransform;
};

View File

@@ -0,0 +1,588 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "RigFaultReactivationModelGenerator.h"
#include "RiaApplication.h"
#include "RigActiveCellInfo.h"
#include "RigFault.h"
#include "RigGriddedPart3d.h"
#include "RigMainGrid.h"
#include "RimCellFilterCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimGridView.h"
#include "RimUserDefinedIndexFilter.h"
#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFaultReactivationModelGenerator::RigFaultReactivationModelGenerator( cvf::Vec3d position, cvf::Vec3d normal )
: m_startPosition( position )
, m_normal( normal )
, m_bufferAboveFault( 0.0 )
, m_bufferBelowFault( 0.0 )
, m_startDepth( 0.0 )
, m_depthBelowFault( 100.0 )
, m_horzExtentFromFault( 1000.0 )
, m_modelThickness( 100.0 )
, m_useLocalCoordinates( false )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFaultReactivationModelGenerator::~RigFaultReactivationModelGenerator()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setFault( const RigFault* fault )
{
m_fault = fault;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setGrid( const RigMainGrid* grid )
{
m_grid = grid;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setActiveCellInfo( const RigActiveCellInfo* activeCellInfo )
{
m_activeCellInfo = activeCellInfo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setFaultBufferDepth( double aboveFault, double belowFault )
{
m_bufferAboveFault = aboveFault;
m_bufferBelowFault = belowFault;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setModelSize( double startDepth, double depthBelowFault, double horzExtentFromFault )
{
m_startDepth = startDepth;
m_depthBelowFault = depthBelowFault;
m_horzExtentFromFault = horzExtentFromFault;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setModelThickness( double thickness )
{
m_modelThickness = thickness;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setUseLocalCoordinates( bool useLocalCoordinates )
{
m_useLocalCoordinates = useLocalCoordinates;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setModelGriddingOptions( double maxCellHeight,
double cellSizeFactor,
int noOfCellsHorzFront,
int noOfCellsHorzBack )
{
m_maxCellHeight = maxCellHeight;
m_cellSizeFactor = cellSizeFactor;
m_noOfCellsHorzFront = noOfCellsHorzFront;
m_noOfCellsHorzBack = noOfCellsHorzBack;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<cvf::Vec3d, cvf::Vec3d> RigFaultReactivationModelGenerator::modelLocalNormalsXY()
{
cvf::Vec3d xNormal = m_normal ^ cvf::Vec3d::Z_AXIS;
xNormal.z() = 0.0;
xNormal.normalize();
cvf::Vec3d yNormal = xNormal ^ cvf::Vec3d::Z_AXIS;
return std::make_pair( xNormal, yNormal );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::setupLocalCoordinateTransform()
{
auto [xNormal, yNormal] = modelLocalNormalsXY();
m_localCoordTransform = cvf::Mat4d::fromCoordSystemAxes( &xNormal, &yNormal, &cvf::Vec3d::Z_AXIS );
cvf::Vec3d center = m_startPosition * -1.0;
center.z() = 0.0;
center.transformPoint( m_localCoordTransform );
m_localCoordTransform.setTranslation( center );
}
//--------------------------------------------------------------------------------------------------
/// change corner order to be consistent so that index (0,1) and (2,3) gives the lower and upper horz. lines no matter what I or J face we
/// have
//--------------------------------------------------------------------------------------------------
const std::array<int, 4> RigFaultReactivationModelGenerator::faceIJCornerIndexes( cvf::StructGridInterface::FaceType face )
{
switch ( face )
{
case cvf::StructGridInterface::POS_I:
case cvf::StructGridInterface::NEG_J:
return { 0, 1, 3, 2 };
case cvf::StructGridInterface::NEG_I:
case cvf::StructGridInterface::POS_J:
return { 0, 3, 1, 2 };
case cvf::StructGridInterface::POS_K:
case cvf::StructGridInterface::NEG_K:
case cvf::StructGridInterface::NO_FACE:
default:
break;
}
CVF_ASSERT( false ); // not supported for K faces
return { 0, 0, 0, 0 };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RigFaultReactivationModelGenerator::lineIntersect( const cvf::Plane& plane, cvf::Vec3d lineA, cvf::Vec3d lineB )
{
double dist = 0.0;
return caf::HexGridIntersectionTools::planeLineIntersectionForMC( plane, lineA, lineB, &dist );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigFaultReactivationModelGenerator::oppositeStartCellIndex( const std::vector<size_t> cellIndexColumn,
cvf::StructGridInterface::FaceType face )
{
auto oppositeStartFace = cvf::StructGridInterface::oppositeFace( face );
bool bFoundOppositeCell = false;
size_t oppositeCellIdx = 0;
for ( auto backCellIdx : cellIndexColumn )
{
for ( auto& faultFace : m_fault->faultFaces() )
{
if ( ( faultFace.m_nativeFace == face ) && ( faultFace.m_nativeReservoirCellIndex == backCellIdx ) )
{
bFoundOppositeCell = true;
oppositeCellIdx = faultFace.m_oppositeReservoirCellIndex;
break;
}
else if ( ( faultFace.m_nativeFace == oppositeStartFace ) && ( faultFace.m_oppositeReservoirCellIndex == backCellIdx ) )
{
bFoundOppositeCell = true;
oppositeCellIdx = faultFace.m_nativeReservoirCellIndex;
break;
}
}
if ( bFoundOppositeCell ) break;
}
return oppositeCellIdx;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::addFilter( QString name, std::vector<size_t> cells )
{
RimEclipseView* view = dynamic_cast<RimEclipseView*>( RiaApplication::instance()->activeGridView() );
if ( view == nullptr ) return;
auto cellFilters = view->cellFilterCollection();
if ( cellFilters == nullptr ) return;
auto eCase = cellFilters->firstAncestorOfType<RimEclipseCase>();
auto filter = cellFilters->addNewUserDefinedIndexFilter( eCase, cells );
filter->setName( name );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::array<cvf::Vec3d, 12>& RigFaultReactivationModelGenerator::frontPoints() const
{
return m_frontPoints;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::array<cvf::Vec3d, 12>& RigFaultReactivationModelGenerator::backPoints() const
{
return m_backPoints;
}
//--------------------------------------------------------------------------------------------------
/// <---- fault normal *
/// *
/// 15 *
/// 7---------|------------ 23 top model *
/// | | | *
/// | | | *
/// 6|_____14_|___________| 22 top fault w/buffer *
/// 5|-----13-\-----------| 21 top fault front *
/// 4|---------\-12-------| 20 top fault back *
/// | X | start position in fault (user selected) *
/// 3|--------11-\--------| 19 bottom fault front *
/// 2|------------\-10----| 18 bottom fault back *
/// 1|_____________\______| 17 bottom fault w/buffer *
/// | 9| | *
/// | | | *
/// | | | *
/// 0--------------|------- 16 bottom model *
/// 8 *
/// front back *
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::generatePointsFrontBack()
{
std::array<cvf::Vec3d, 24> points;
auto alongModel = m_normal ^ cvf::Vec3d::Z_AXIS;
alongModel.normalize();
double top_depth = -m_startDepth;
double bottom_depth = m_bottomFault.z() - m_depthBelowFault;
cvf::Vec3d edge_front = m_startPosition - m_horzExtentFromFault * alongModel;
cvf::Vec3d edge_back = m_startPosition + m_horzExtentFromFault * alongModel;
points[8] = m_bottomFault;
points[8].z() = bottom_depth;
points[9] = m_bottomFault;
points[10] = m_bottomReservoirBack;
points[11] = m_bottomReservoirFront;
points[12] = m_topReservoirBack;
points[13] = m_topReservoirFront;
points[14] = m_topFault;
points[15] = m_topFault;
points[15].z() = top_depth;
for ( int i = 0; i < 8; i++ )
{
points[i] = edge_front;
points[i].z() = points[i + 8].z();
}
for ( int i = 16; i < 24; i++ )
{
points[i] = edge_back;
points[i].z() = points[i - 8].z();
}
std::array<cvf::Vec3d, 12> frontPoints;
std::array<cvf::Vec3d, 12> backPoints;
// only return the corner points used for each part
std::vector<size_t> frontMap = { 0, 1, 3, 5, 6, 7, 8, 9, 11, 13, 14, 15 };
std::vector<size_t> backMap = { 16, 17, 18, 20, 22, 23, 8, 9, 10, 12, 14, 15 };
for ( int i = 0; i < 12; i++ )
{
m_frontPoints[i] = points[frontMap[i]];
m_backPoints[i] = points[backMap[i]];
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::generateGeometry( size_t startCellIndex,
cvf::StructGridInterface::FaceType startFace,
RigGriddedPart3d* frontPart,
RigGriddedPart3d* backPart )
{
std::vector<size_t> cellColumnBackSearch;
std::vector<size_t> cellColumnBack;
std::vector<size_t> cellColumnFront;
size_t i, j, k;
std::vector<int> kLayersFront;
std::vector<int> kLayersBack;
// build column of cells behind fault
m_grid->ijkFromCellIndexUnguarded( startCellIndex, &i, &j, &k );
cellColumnBackSearch.push_back( startCellIndex ); // want the user clicked cell to be the first in the search list
for ( size_t kLayer = 0; kLayer < m_grid->cellCountK(); kLayer++ )
{
auto cellIdx = m_grid->cellIndexFromIJKUnguarded( i, j, kLayer );
if ( cellIdx != startCellIndex ) cellColumnBackSearch.push_back( cellIdx );
cellColumnBack.push_back( cellIdx );
if ( m_activeCellInfo->isActive( cellIdx ) )
kLayersBack.push_back( (int)kLayer );
else
kLayersBack.push_back( -1 );
}
// build cell column of cells in front of fault, opposite to the cell column behind the fault
auto oppositeStartFace = cvf::StructGridInterface::oppositeFace( startFace );
size_t oppositeCellIdx = oppositeStartCellIndex( cellColumnBackSearch, startFace );
m_grid->ijkFromCellIndexUnguarded( oppositeCellIdx, &i, &j, &k );
for ( size_t kLayer = 0; kLayer < m_grid->cellCountK(); kLayer++ )
{
auto cellIdx = m_grid->cellIndexFromIJKUnguarded( i, j, kLayer );
cellColumnFront.push_back( cellIdx );
if ( m_activeCellInfo->isActive( cellIdx ) )
kLayersFront.push_back( (int)kLayer );
else
kLayersFront.push_back( -1 );
}
auto zPositionsBack = elementLayers( startFace, cellColumnBack );
auto zPositionsFront = elementLayers( oppositeStartFace, cellColumnFront );
std::reverse( kLayersBack.begin(), kLayersBack.end() );
std::reverse( kLayersFront.begin(), kLayersFront.end() );
// add extra fault buffer below the fault, starting at the deepest bottom-most cell on either side of the fault
double front_bottom = zPositionsFront.begin()->first;
double back_bottom = zPositionsBack.begin()->first;
m_bottomReservoirFront = zPositionsFront.begin()->second;
m_bottomReservoirBack = zPositionsBack.begin()->second;
cvf::Vec3d bottom_point = m_bottomReservoirFront;
if ( front_bottom < back_bottom )
{
bottom_point = extrapolatePoint( zPositionsBack.begin()->second, ( ++zPositionsBack.begin() )->second, m_bufferBelowFault );
}
else if ( back_bottom < front_bottom )
{
bottom_point = extrapolatePoint( zPositionsFront.begin()->second, ( ++zPositionsFront.begin() )->second, m_bufferBelowFault );
}
m_bottomFault = bottom_point;
// add extra fault buffer above the fault, starting at the shallowest top-most cell on either side of the fault
double front_top = zPositionsFront.rbegin()->first;
double back_top = zPositionsBack.rbegin()->first;
m_topReservoirFront = zPositionsFront.rbegin()->second;
m_topReservoirBack = zPositionsBack.rbegin()->second;
cvf::Vec3d top_point = m_topReservoirFront;
if ( front_top < back_top )
{
top_point = extrapolatePoint( zPositionsFront.rbegin()->second, ( ++zPositionsFront.rbegin() )->second, m_bufferAboveFault );
}
else if ( back_top < front_top )
{
top_point = extrapolatePoint( zPositionsBack.rbegin()->second, ( ++zPositionsBack.rbegin() )->second, m_bufferAboveFault );
}
m_topFault = top_point;
splitLargeLayers( zPositionsFront, kLayersFront, m_maxCellHeight );
splitLargeLayers( zPositionsBack, kLayersBack, m_maxCellHeight );
std::vector<cvf::Vec3d> frontReservoirLayers;
for ( auto& kvp : zPositionsFront )
frontReservoirLayers.push_back( kvp.second );
std::vector<cvf::Vec3d> backReservoirLayers;
for ( auto& kvp : zPositionsBack )
backReservoirLayers.push_back( kvp.second );
generatePointsFrontBack();
frontPart->generateGeometry( m_frontPoints,
frontReservoirLayers,
kLayersFront,
m_maxCellHeight,
m_cellSizeFactor,
m_noOfCellsHorzFront,
m_modelThickness );
backPart->generateGeometry( m_backPoints, backReservoirLayers, kLayersBack, m_maxCellHeight, m_cellSizeFactor, m_noOfCellsHorzBack, m_modelThickness );
frontPart->generateLocalNodes( m_localCoordTransform );
backPart->generateLocalNodes( m_localCoordTransform );
frontPart->setUseLocalCoordinates( m_useLocalCoordinates );
backPart->setUseLocalCoordinates( m_useLocalCoordinates );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<double, cvf::Vec3d> RigFaultReactivationModelGenerator::elementLayers( cvf::StructGridInterface::FaceType face,
const std::vector<size_t>& cellIndexColumn )
{
cvf::Plane modelPlane;
modelPlane.setFromPointAndNormal( m_startPosition, m_normal );
auto cornerIndexes = faceIJCornerIndexes( face );
std::vector<int> klayers;
std::map<double, cvf::Vec3d> zPositions;
for ( auto cellIdx : cellIndexColumn )
{
RigCell cell = m_grid->cell( cellIdx );
auto corners = cell.faceCorners( face );
cvf::Vec3d intersect1 = lineIntersect( modelPlane, corners[cornerIndexes[0]], corners[cornerIndexes[1]] );
cvf::Vec3d intersect2 = lineIntersect( modelPlane, corners[cornerIndexes[2]], corners[cornerIndexes[3]] );
zPositions[intersect1.z()] = intersect1;
zPositions[intersect2.z()] = intersect2;
}
return zPositions;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RigFaultReactivationModelGenerator::extrapolatePoint( cvf::Vec3d startPoint, cvf::Vec3d endPoint, double buffer )
{
cvf::Vec3d direction = startPoint - endPoint;
direction.normalize();
return endPoint + ( buffer * direction );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFaultReactivationModelGenerator::splitLargeLayers( std::map<double, cvf::Vec3d>& layers, std::vector<int>& kLayers, double maxHeight )
{
std::vector<cvf::Vec3d> additionalPoints;
std::pair<double, cvf::Vec3d> prevLayer;
std::vector<int> newKLayers;
bool first = true;
int k = 0;
kLayers.push_back( kLayers.back() );
for ( auto& layer : layers )
{
if ( first )
{
prevLayer = layer;
first = false;
newKLayers.push_back( kLayers[k++] );
continue;
}
if ( std::abs( prevLayer.first - layer.first ) > maxHeight )
{
const auto& points = interpolateExtraPoints( prevLayer.second, layer.second, maxHeight );
for ( auto& p : points )
{
additionalPoints.push_back( p );
newKLayers.push_back( kLayers[k] );
}
}
prevLayer = layer;
newKLayers.push_back( kLayers[k++] );
}
for ( auto& p : additionalPoints )
{
layers[p.z()] = p;
}
kLayers.clear();
for ( auto k : newKLayers )
{
kLayers.push_back( k );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<cvf::Vec3d> RigFaultReactivationModelGenerator::interpolateExtraPoints( cvf::Vec3d from, cvf::Vec3d to, double maxStep )
{
std::vector<cvf::Vec3d> points;
const double distance = from.pointDistance( to );
const int nSteps = (int)std::ceil( distance / maxStep );
const double stepSize = distance / nSteps;
auto stepVec = to - from;
stepVec.normalize();
stepVec *= stepSize;
cvf::Vec3d p = from;
for ( int i = 1; i < nSteps; i++ )
{
p += stepVec;
points.push_back( p );
}
return points;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const cvf::Vec3d RigFaultReactivationModelGenerator::normal() const
{
return m_normal;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::pair<cvf::Vec3d, cvf::Vec3d> RigFaultReactivationModelGenerator::faultTopBottomPoints() const
{
return std::make_pair( m_topFault, m_bottomFault );
}

View File

@@ -0,0 +1,116 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 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 "cvfMatrix4.h"
#include "cvfObject.h"
#include "cvfPlane.h"
#include "cvfStructGrid.h"
#include "cvfVector3.h"
#include <array>
#include <vector>
#include <QString>
class RigFault;
class RigMainGrid;
class RigGriddedPart3d;
class RigActiveCellInfo;
class RigFaultReactivationModelGenerator : cvf::Object
{
public:
RigFaultReactivationModelGenerator( cvf::Vec3d position, cvf::Vec3d normal );
~RigFaultReactivationModelGenerator();
void setFault( const RigFault* fault );
void setGrid( const RigMainGrid* grid );
void setActiveCellInfo( const RigActiveCellInfo* activeCellInfo );
void setFaultBufferDepth( double aboveFault, double belowFault );
void setModelSize( double startDepth, double depthBelowFault, double horzExtentFromFault );
void setModelThickness( double thickness );
void setModelGriddingOptions( double maxCellHeight, double cellSizeFactor, int noOfCellsHorzFront, int noOfCellsHorzBack );
void setUseLocalCoordinates( bool useLocalCoordinates );
void setupLocalCoordinateTransform();
std::pair<cvf::Vec3d, cvf::Vec3d> modelLocalNormalsXY();
void generateGeometry( size_t startCellIndex,
cvf::StructGridInterface::FaceType startFace,
RigGriddedPart3d* frontPart,
RigGriddedPart3d* backPart );
const std::array<cvf::Vec3d, 12>& frontPoints() const;
const std::array<cvf::Vec3d, 12>& backPoints() const;
const cvf::Vec3d normal() const;
const std::pair<cvf::Vec3d, cvf::Vec3d> faultTopBottomPoints() const;
protected:
static const std::array<int, 4> faceIJCornerIndexes( cvf::StructGridInterface::FaceType face );
static const std::vector<cvf::Vec3d> interpolateExtraPoints( cvf::Vec3d from, cvf::Vec3d to, double maxStep );
static cvf::Vec3d lineIntersect( const cvf::Plane& plane, cvf::Vec3d lineA, cvf::Vec3d lineB );
static cvf::Vec3d extrapolatePoint( cvf::Vec3d startPoint, cvf::Vec3d endPoint, double stopDepth );
static void splitLargeLayers( std::map<double, cvf::Vec3d>& layers, std::vector<int>& kLayers, double maxHeight );
std::map<double, cvf::Vec3d> elementLayers( cvf::StructGridInterface::FaceType face, const std::vector<size_t>& cellIndexColumn );
void addFilter( QString name, std::vector<size_t> cells );
size_t oppositeStartCellIndex( const std::vector<size_t> cellIndexColumn, cvf::StructGridInterface::FaceType face );
void generatePointsFrontBack();
private:
cvf::Vec3d m_startPosition;
cvf::Vec3d m_normal;
std::array<cvf::Vec3d, 12> m_frontPoints;
std::array<cvf::Vec3d, 12> m_backPoints;
cvf::cref<RigFault> m_fault;
cvf::cref<RigMainGrid> m_grid;
cvf::cref<RigActiveCellInfo> m_activeCellInfo;
double m_bufferAboveFault;
double m_bufferBelowFault;
double m_startDepth;
double m_depthBelowFault;
double m_horzExtentFromFault;
double m_modelThickness;
double m_maxCellHeight;
double m_cellSizeFactor;
int m_noOfCellsHorzFront;
int m_noOfCellsHorzBack;
cvf::Vec3d m_topReservoirFront;
cvf::Vec3d m_topReservoirBack;
cvf::Vec3d m_bottomReservoirFront;
cvf::Vec3d m_bottomReservoirBack;
cvf::Vec3d m_topFault;
cvf::Vec3d m_bottomFault;
cvf::Mat4d m_localCoordTransform;
bool m_useLocalCoordinates;
};

View File

@@ -26,10 +26,13 @@
#include "cvfBoundingBox.h"
#include "cvfTextureImage.h"
#include <cmath>
#include <map>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGriddedPart3d::RigGriddedPart3d( bool flipFrontBack )
RigGriddedPart3d::RigGriddedPart3d()
: m_useLocalCoordinates( false )
{
}
@@ -54,6 +57,15 @@ void RigGriddedPart3d::reset()
m_elementIndices.clear();
m_meshLines.clear();
m_elementSets.clear();
m_elementKLayer.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RigGriddedPart3d::Regions> RigGriddedPart3d::allRegions()
{
return { Regions::LowerUnderburden, Regions::UpperUnderburden, Regions::Reservoir, Regions::LowerOverburden, Regions::UpperOverburden };
}
//--------------------------------------------------------------------------------------------------
@@ -65,79 +77,208 @@ cvf::Vec3d RigGriddedPart3d::stepVector( cvf::Vec3d start, cvf::Vec3d stop, int
return vec.getNormalized() * ( vec.length() / nSteps );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RigGriddedPart3d::generateConstantLayers( double zFrom, double zTo, double maxSize )
{
std::vector<double> layers;
double diff = zTo - zFrom;
if ( std::abs( diff ) <= maxSize )
{
layers.push_back( std::min( zFrom, zTo ) );
return layers;
}
double steps = std::abs( diff / maxSize );
int nSteps = (int)std::ceil( steps );
double stepSize = diff / nSteps;
for ( int i = 0; i < nSteps; i++ )
{
layers.push_back( zFrom + stepSize * i );
}
std::sort( layers.begin(), layers.end() );
return layers;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RigGriddedPart3d::generateGrowingLayers( double zFrom, double zTo, double maxSize, double growfactor )
{
std::vector<double> layers;
double diff = zTo - zFrom;
if ( std::abs( diff ) <= maxSize )
{
layers.push_back( std::min( zFrom, zTo ) );
return layers;
}
double startHeight = maxSize;
double curDepth = zFrom;
if ( zTo < zFrom )
{
while ( curDepth > zTo )
{
layers.push_back( curDepth );
curDepth -= startHeight;
startHeight *= growfactor;
}
}
else if ( zTo > zFrom )
{
while ( curDepth < zTo )
{
layers.push_back( curDepth );
curDepth += startHeight;
startHeight *= growfactor;
}
}
std::sort( layers.begin(), layers.end() );
return layers;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RigGriddedPart3d::extractZValues( std::vector<cvf::Vec3d> points )
{
std::vector<double> layers;
for ( auto& p : points )
{
layers.push_back( p.z() );
}
return layers;
}
//--------------------------------------------------------------------------------------------------
/// Point index in input
///
///
/// 3 ----------- 7 *
/// | | *
/// | | *
/// | | *
/// 2 |---------| 6 *
/// 5 ------| 11 *
/// | OU | Overburden Upper *
/// 4 |------\10 *
/// | OL \ Overburden Lower *
/// 3 |--------\ 9 *
/// | \ *
/// | \ *
/// | \ *
/// 1 -------------| 5 *
/// | R \ Reservoir *
/// 2 |___________\ 8 *
/// | UU \ Underburden Upper *
/// 1 |-------------\7 *
/// | | *
/// | UL | Underburden Lower *
/// | | *
/// | | *
/// | | *
/// 0 -------------- 4 *
/// 0 -------------- 6 *
///
/// Assumes 0->4, 1->5, 2->6 and 3->7 is parallel
/// Assumes horizontal lines are parallel
///
///
//--------------------------------------------------------------------------------------------------
void RigGriddedPart3d::generateGeometry( std::vector<cvf::Vec3d> inputPoints,
void RigGriddedPart3d::generateGeometry( const std::array<cvf::Vec3d, 12>& inputPoints,
const std::vector<cvf::Vec3d>& reservoirLayers,
const std::vector<int>& kLayers,
const double maxCellHeight,
double cellSizeFactor,
int nHorzCells,
int nVertCellsLower,
int nVertCellsMiddle,
int nVertCellsUpper,
double thickness )
double modelThickness )
{
reset();
const cvf::Vec3d step0to1 = stepVector( inputPoints[0], inputPoints[1], nVertCellsLower );
const cvf::Vec3d step1to2 = stepVector( inputPoints[1], inputPoints[2], nVertCellsMiddle );
const cvf::Vec3d step2to3 = stepVector( inputPoints[2], inputPoints[3], nVertCellsUpper );
std::map<Regions, std::vector<double>> layersPerRegion;
const cvf::Vec3d step4to5 = stepVector( inputPoints[4], inputPoints[5], nVertCellsLower );
const cvf::Vec3d step5to6 = stepVector( inputPoints[5], inputPoints[6], nVertCellsMiddle );
const cvf::Vec3d step6to7 = stepVector( inputPoints[6], inputPoints[7], nVertCellsUpper );
layersPerRegion[Regions::LowerUnderburden] = generateGrowingLayers( inputPoints[1].z(), inputPoints[0].z(), maxCellHeight, cellSizeFactor );
layersPerRegion[Regions::UpperUnderburden] = generateConstantLayers( inputPoints[1].z(), inputPoints[2].z(), maxCellHeight );
layersPerRegion[Regions::Reservoir] = extractZValues( reservoirLayers );
layersPerRegion[Regions::LowerOverburden] = generateConstantLayers( inputPoints[3].z(), inputPoints[4].z(), maxCellHeight );
layersPerRegion[Regions::UpperOverburden] = generateGrowingLayers( inputPoints[4].z(), inputPoints[5].z(), maxCellHeight, cellSizeFactor );
const cvf::Vec3d step0to4 = stepVector( inputPoints[0], inputPoints[4], nHorzCells );
size_t nVertCells = 0;
cvf::Vec3d tVec = step0to4 ^ step0to1;
tVec.normalize();
tVec *= thickness;
for ( auto region : allRegions() )
{
nVertCells += layersPerRegion[region].size();
}
const std::vector<double> m_thicknessFactors = { -1.0, 0.0, 1.0 };
const int nThicknessCells = 2;
const int nVertCells = nVertCellsLower + nVertCellsMiddle + nVertCellsUpper;
cvf::Vec3d tVec = stepVector( inputPoints[0], inputPoints[6], nHorzCells ) ^ cvf::Vec3d::Z_AXIS;
tVec.normalize();
tVec *= modelThickness;
const std::vector<int> vertLines = { nVertCellsLower, nVertCellsMiddle, nVertCellsUpper + 1 };
const std::vector<cvf::Vec3d> firstSteps = { step0to1, step1to2, step2to3 };
const std::vector<cvf::Vec3d> lastSteps = { step4to5, step5to6, step6to7 };
m_nodes.reserve( ( nVertCells + 1 ) * ( nHorzCells + 1 ) * ( nThicknessCells + 1 ) );
// ** generate nodes
m_boundaryNodes[Boundary::Bottom] = {};
m_boundaryNodes[Boundary::FarSide] = {};
m_nodes.reserve( (size_t)( ( nVertCells + 1 ) * ( nHorzCells + 1 ) ) );
cvf::Vec3d pFrom = inputPoints[0];
cvf::Vec3d pTo = inputPoints[4];
unsigned int layer = 0;
unsigned int nodeIndex = 0;
unsigned int layer = 0;
for ( int i = 0; i < (int)vertLines.size(); i++ )
cvf::Vec3d fromPos;
cvf::Vec3d toPos;
cvf::Vec3d fromStep;
cvf::Vec3d toStep;
for ( auto region : allRegions() )
{
for ( int v = 0; v < vertLines[i]; v++, layer++ )
switch ( region )
{
cvf::Vec3d stepHorz = stepVector( pFrom, pTo, nHorzCells );
cvf::Vec3d p = pFrom;
case Regions::LowerUnderburden:
fromPos = inputPoints[0];
toPos = inputPoints[6];
fromStep = cvf::Vec3d( 0, 0, 0 );
toStep = cvf::Vec3d( 0, 0, 0 );
break;
case Regions::UpperUnderburden:
fromPos = inputPoints[1];
toPos = inputPoints[7];
fromStep = stepVector( inputPoints[1], inputPoints[2], (int)layersPerRegion[region].size() );
toStep = stepVector( inputPoints[7], inputPoints[8], (int)layersPerRegion[region].size() );
break;
case Regions::Reservoir:
fromPos = inputPoints[2];
toPos = inputPoints[8];
break;
case Regions::LowerOverburden:
fromPos = inputPoints[3];
toPos = inputPoints[9];
fromStep = stepVector( inputPoints[3], inputPoints[4], (int)layersPerRegion[region].size() );
toStep = stepVector( inputPoints[9], inputPoints[10], (int)layersPerRegion[region].size() );
break;
case Regions::UpperOverburden:
fromPos = inputPoints[4];
toPos = inputPoints[10];
fromStep = cvf::Vec3d( 0, 0, 0 );
toStep = cvf::Vec3d( 0, 0, 0 );
break;
}
for ( int v = 0; v < (int)layersPerRegion[region].size(); v++, layer++ )
{
if ( ( region == Regions::LowerUnderburden ) || ( region == Regions::UpperOverburden ) )
{
fromPos.z() = layersPerRegion[region][v];
toPos.z() = layersPerRegion[region][v];
}
cvf::Vec3d p = fromPos;
cvf::Vec3d stepHorz = stepVector( fromPos, toPos, nHorzCells );
m_meshLines.push_back( { fromPos, toPos } );
for ( int h = 0; h <= nHorzCells; h++ )
{
for ( int t = 0; t <= nThicknessCells; t++, nodeIndex++ )
@@ -155,35 +296,63 @@ void RigGriddedPart3d::generateGeometry( std::vector<cvf::Vec3d> inputPoints,
p += stepHorz;
}
pFrom += firstSteps[i];
pTo += lastSteps[i];
if ( region == Regions::Reservoir )
{
toPos = reservoirLayers[v];
fromPos.z() = toPos.z();
}
else
{
fromPos += fromStep;
toPos += toStep;
}
}
}
// ** generate elements of type hex8
m_elementIndices.resize( (size_t)( nVertCells * nHorzCells * nThicknessCells ) );
m_elementIndices.resize( (size_t)( ( nVertCells - 1 ) * nHorzCells * nThicknessCells ) );
m_elementKLayer.resize( (size_t)( ( nVertCells - 1 ) * nHorzCells * nThicknessCells ) );
m_borderSurfaceElements[RimFaultReactivation::BorderSurface::UpperSurface] = {};
m_borderSurfaceElements[RimFaultReactivation::BorderSurface::FaultSurface] = {};
m_borderSurfaceElements[RimFaultReactivation::BorderSurface::LowerSurface] = {};
m_elementSets[ElementSets::OverBurden] = {};
m_elementSets[ElementSets::Reservoir] = {};
m_elementSets[ElementSets::IntraReservoir] = {};
m_elementSets[ElementSets::UnderBurden] = {};
m_boundaryElements[Boundary::Bottom] = {};
m_boundaryElements[Boundary::FarSide] = {};
int layerIndexOffset = 0;
int elementIdx = 0;
layer = 0;
int kLayer = 0;
const int nVertCellsLower = (int)layersPerRegion[Regions::LowerUnderburden].size();
const int nVertCellsFault = (int)( layersPerRegion[Regions::UpperUnderburden].size() + layersPerRegion[Regions::Reservoir].size() +
layersPerRegion[Regions::LowerOverburden].size() );
const int nVertCellsUnderburden =
(int)( layersPerRegion[Regions::LowerUnderburden].size() + layersPerRegion[Regions::UpperUnderburden].size() );
const int nVertCellsReservoir = nVertCellsUnderburden + (int)( layersPerRegion[Regions::Reservoir].size() );
RimFaultReactivation::BorderSurface currentSurfaceRegion = RimFaultReactivation::BorderSurface::LowerSurface;
RimFaultReactivation::ElementSets currentElementSet = RimFaultReactivation::ElementSets::UnderBurden;
const int nextLayerIdxOff = ( nHorzCells + 1 ) * ( nThicknessCells + 1 );
const int nThicknessOff = nThicknessCells + 1;
for ( int v = 0; v < nVertCells; v++, layer++ )
for ( int v = 0; v < (int)nVertCells - 1; v++, layer++ )
{
if ( v >= nVertCellsLower ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::FaultSurface;
if ( v >= nVertCellsLower + nVertCellsMiddle ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::UpperSurface;
if ( v >= nVertCellsLower + nVertCellsFault ) currentSurfaceRegion = RimFaultReactivation::BorderSurface::UpperSurface;
if ( v >= nVertCellsUnderburden ) currentElementSet = RimFaultReactivation::ElementSets::Reservoir;
if ( v >= nVertCellsReservoir ) currentElementSet = RimFaultReactivation::ElementSets::OverBurden;
int i = layerIndexOffset;
@@ -209,6 +378,24 @@ void RigGriddedPart3d::generateGeometry( std::vector<cvf::Vec3d> inputPoints,
{
m_boundaryElements[Boundary::FarSide].push_back( elementIdx );
}
if ( currentElementSet == RimFaultReactivation::ElementSets::Reservoir )
{
m_elementKLayer[elementIdx] = kLayers[kLayer];
if ( kLayers[kLayer] < 0 )
{
m_elementSets[RimFaultReactivation::ElementSets::IntraReservoir].push_back( elementIdx );
}
else
{
m_elementSets[currentElementSet].push_back( elementIdx );
}
}
else
{
m_elementSets[currentElementSet].push_back( elementIdx );
m_elementKLayer[elementIdx] = -2;
}
}
i += nThicknessOff;
}
@@ -217,20 +404,18 @@ void RigGriddedPart3d::generateGeometry( std::vector<cvf::Vec3d> inputPoints,
m_borderSurfaceElements[currentSurfaceRegion].push_back( elementIdx - 2 );
m_borderSurfaceElements[currentSurfaceRegion].push_back( elementIdx - 1 );
if ( currentElementSet == RimFaultReactivation::ElementSets::Reservoir )
{
kLayer++;
}
layerIndexOffset += nextLayerIdxOff;
}
// generate meshlines for 2d viz
generateMeshlines( { inputPoints[0], inputPoints[1], inputPoints[5], inputPoints[4] }, nHorzCells, nVertCellsLower );
generateMeshlines( { inputPoints[1], inputPoints[2], inputPoints[6], inputPoints[5] }, nHorzCells, nVertCellsMiddle );
generateMeshlines( { inputPoints[2], inputPoints[3], inputPoints[7], inputPoints[6] }, nHorzCells, nVertCellsUpper );
// store the reservoir part corners for later
m_reservoirRect.clear();
for ( auto i : { 1, 2, 6, 5 } )
// vertical mesh lines for 2d display
for ( int i = 0; i < 5; i++ )
{
m_reservoirRect.push_back( inputPoints[i] );
generateVerticalMeshlines( { inputPoints[i], inputPoints[i + 1], inputPoints[i + 7], inputPoints[i + 6] }, nHorzCells );
}
}
@@ -247,29 +432,13 @@ void RigGriddedPart3d::generateGeometry( std::vector<cvf::Vec3d> inputPoints,
///
/// Assumes 0->3 and 1->2 is parallel
//--------------------------------------------------------------------------------------------------
void RigGriddedPart3d::generateMeshlines( const std::vector<cvf::Vec3d>& cornerPoints, int numHorzCells, int numVertCells )
void RigGriddedPart3d::generateVerticalMeshlines( const std::vector<cvf::Vec3d>& cornerPoints, int numHorzCells )
{
cvf::Vec3d step0to1 = stepVector( cornerPoints[0], cornerPoints[1], numVertCells );
cvf::Vec3d step0to3 = stepVector( cornerPoints[0], cornerPoints[3], numHorzCells );
cvf::Vec3d step1to2 = stepVector( cornerPoints[1], cornerPoints[2], numHorzCells );
cvf::Vec3d step3to2 = stepVector( cornerPoints[3], cornerPoints[2], numVertCells );
// horizontal lines
cvf::Vec3d startP = cornerPoints[0];
cvf::Vec3d endP = cornerPoints[3];
for ( int v = 0; v <= numVertCells; v++ )
{
m_meshLines.push_back( { startP, endP } );
startP += step0to1;
endP += step3to2;
}
// vertical lines
startP = cornerPoints[0];
endP = cornerPoints[1];
auto startP = cornerPoints[0];
auto endP = cornerPoints[1];
for ( int h = 0; h <= numHorzCells; h++ )
{
@@ -330,6 +499,24 @@ const std::vector<std::vector<unsigned int>>& RigGriddedPart3d::elementIndices()
return m_elementIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<cvf::Vec3d> RigGriddedPart3d::elementCorners( size_t elementIndex ) const
{
if ( elementIndex >= m_elementIndices.size() ) return {};
std::vector<cvf::Vec3d> corners;
for ( auto nodeIdx : m_elementIndices[elementIndex] )
{
if ( nodeIdx >= m_nodes.size() ) continue;
corners.push_back( m_nodes[nodeIdx] );
}
return corners;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -346,6 +533,14 @@ const std::vector<std::vector<cvf::Vec3d>>& RigGriddedPart3d::meshLines() const
return m_meshLines;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<int> RigGriddedPart3d::elementKLayer() const
{
return m_elementKLayer;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -370,69 +565,6 @@ const std::map<RimFaultReactivation::ElementSets, std::vector<unsigned int>>& Ri
return m_elementSets;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, int> RigGriddedPart3d::reservoirZTopBottom( const RigMainGrid* grid ) const
{
cvf::BoundingBox resBb;
for ( const auto& p : m_reservoirRect )
{
resBb.add( p );
}
std::vector<size_t> intersectingCells;
grid->findIntersectingCells( resBb, &intersectingCells );
resBb.reset();
for ( auto cellIdx : intersectingCells )
{
resBb.add( grid->cell( cellIdx ).boundingBox() );
}
auto maxZ = resBb.max().z();
auto minZ = resBb.min().z();
return std::make_pair( maxZ, minZ );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGriddedPart3d::generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid )
{
m_elementSets[ElementSets::OverBurden] = {};
m_elementSets[ElementSets::Reservoir] = {};
m_elementSets[ElementSets::IntraReservoir] = {};
m_elementSets[ElementSets::UnderBurden] = {};
auto [topResZ, bottomResZ] = reservoirZTopBottom( grid );
for ( unsigned int i = 0; i < m_elementIndices.size(); i++ )
{
auto corners = elementCorners( i );
if ( dataAccess->elementHasValidData( corners ) )
{
m_elementSets[ElementSets::Reservoir].push_back( i );
}
else
{
if ( elementIsAboveReservoir( corners, topResZ ) )
{
m_elementSets[ElementSets::OverBurden].push_back( i );
}
else if ( elementIsBelowReservoir( corners, bottomResZ ) )
{
m_elementSets[ElementSets::UnderBurden].push_back( i );
}
else
{
m_elementSets[ElementSets::IntraReservoir].push_back( i );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -445,49 +577,3 @@ void RigGriddedPart3d::generateLocalNodes( const cvf::Mat4d transform )
m_localNodes.push_back( node.getTransformedPoint( transform ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RigGriddedPart3d::elementCorners( size_t elementIndex ) const
{
if ( elementIndex >= m_elementIndices.size() ) return {};
std::vector<cvf::Vec3d> corners;
for ( auto nodeIdx : m_elementIndices[elementIndex] )
{
if ( nodeIdx >= m_nodes.size() ) continue;
corners.push_back( m_nodes[nodeIdx] );
}
return corners;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigGriddedPart3d::elementIsAboveReservoir( const std::vector<cvf::Vec3d>& cornerPoints, double threshold ) const
{
int nValid = 0;
for ( auto& p : cornerPoints )
{
if ( p.z() > threshold ) nValid++;
}
return nValid > 4;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigGriddedPart3d::elementIsBelowReservoir( const std::vector<cvf::Vec3d>& cornerPoints, double threshold ) const
{
int nValid = 0;
for ( auto& p : cornerPoints )
{
if ( p.z() < threshold ) nValid++;
}
return nValid > 4;
}

View File

@@ -27,9 +27,6 @@
#include <map>
#include <vector>
class RigMainGrid;
class RimFaultReactivationDataAccess;
//==================================================================================================
///
///
@@ -40,21 +37,20 @@ class RigGriddedPart3d : public cvf::Object
using Boundary = RimFaultReactivation::Boundary;
public:
RigGriddedPart3d( bool flipFrontBack );
RigGriddedPart3d();
~RigGriddedPart3d() override;
void reset();
void generateGeometry( std::vector<cvf::Vec3d> inputPoints,
void generateGeometry( const std::array<cvf::Vec3d, 12>& inputPoints,
const std::vector<cvf::Vec3d>& reservoirLayers,
const std::vector<int>& kLayers,
double maxCellHeight,
double cellSizeFactor,
int nHorzCells,
int nVertCellsLower,
int nVertCellsMiddle,
int nVertCellsUpper,
double thickness );
double modelThickness );
void generateElementSets( const RimFaultReactivationDataAccess* dataAccess, const RigMainGrid* grid );
void generateLocalNodes( const cvf::Mat4d transform );
void extractModelData( RimFaultReactivationDataAccess* dataAccess, size_t outputTimeStep );
const std::vector<cvf::Vec3d>& nodes() const;
const std::vector<cvf::Vec3d>& globalNodes() const;
@@ -65,21 +61,31 @@ public:
const std::map<RimFaultReactivation::BorderSurface, std::vector<unsigned int>>& borderSurfaceElements() const;
const std::vector<std::vector<cvf::Vec3d>>& meshLines() const;
std::vector<cvf::Vec3d> elementCorners( size_t elementIndex ) const;
const std::map<Boundary, std::vector<unsigned int>>& boundaryElements() const;
const std::map<Boundary, std::vector<unsigned int>>& boundaryNodes() const;
const std::map<ElementSets, std::vector<unsigned int>>& elementSets() const;
const std::vector<int> elementKLayer() const;
const std::vector<cvf::Vec3d> elementCorners( size_t elementIndex ) const;
protected:
cvf::Vec3d stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps );
void generateMeshlines( const std::vector<cvf::Vec3d>& cornerPoints, int numHorzCells, int numVertCells );
static cvf::Vec3d stepVector( cvf::Vec3d start, cvf::Vec3d stop, int nSteps );
static std::vector<double> generateConstantLayers( double zFrom, double zTo, double maxSize );
static std::vector<double> generateGrowingLayers( double zFrom, double zTo, double maxSize, double growfactor );
static std::vector<double> extractZValues( std::vector<cvf::Vec3d> );
bool elementIsAboveReservoir( const std::vector<cvf::Vec3d>& cornerPoints, double threshold ) const;
bool elementIsBelowReservoir( const std::vector<cvf::Vec3d>& cornerPoints, double threshold ) const;
void generateVerticalMeshlines( const std::vector<cvf::Vec3d>& cornerPoints, int numHorzCells );
std::pair<int, int> reservoirZTopBottom( const RigMainGrid* grid ) const;
private:
enum class Regions
{
LowerUnderburden = 0, // deepest region goes first
UpperUnderburden,
Reservoir,
LowerOverburden,
UpperOverburden
};
static std::vector<Regions> allRegions();
private:
bool m_useLocalCoordinates;
@@ -87,11 +93,10 @@ private:
std::vector<cvf::Vec3d> m_nodes;
std::vector<cvf::Vec3d> m_localNodes;
std::vector<std::vector<unsigned int>> m_elementIndices;
std::vector<int> m_elementKLayer;
std::map<RimFaultReactivation::BorderSurface, std::vector<unsigned int>> m_borderSurfaceElements;
std::vector<std::vector<cvf::Vec3d>> m_meshLines;
std::map<Boundary, std::vector<unsigned int>> m_boundaryElements;
std::map<Boundary, std::vector<unsigned int>> m_boundaryNodes;
std::map<ElementSets, std::vector<unsigned int>> m_elementSets;
std::vector<cvf::Vec3d> m_reservoirRect;
};