Fault Reactivation updates (#10727)

* Generate reservoir element sets
* Add support for materials
* Add local coordinate system support for exported model
This commit is contained in:
jonjenssen
2023-10-18 09:10:08 +02:00
committed by GitHub
parent 18e9ef0558
commit 7494302275
20 changed files with 613 additions and 188 deletions

View File

@@ -5,6 +5,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.h
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccess.h
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationEnums.h
)
set(SOURCE_GROUP_SOURCE_FILES

View File

@@ -75,18 +75,31 @@ void RimFaultReactivationDataAccess::useCellIndexAdjustment( std::map<size_t, si
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFaultReactivationDataAccess::porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient )
size_t RimFaultReactivationDataAccess::findAdjustedCellIndex( const cvf::Vec3d& position,
const RigMainGrid* grid,
const std::map<size_t, size_t>& cellIndexAdjustmentMap )
{
CAF_ASSERT( grid != nullptr );
size_t cellIdx = grid->findReservoirCellIndexFromPoint( position );
// adjust cell index if present in the map
if ( auto search = cellIndexAdjustmentMap.find( cellIdx ); search != cellIndexAdjustmentMap.end() )
{
cellIdx = search->second;
}
return cellIdx;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFaultReactivationDataAccess::porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient ) const
{
size_t cellIdx = cvf::UNDEFINED_SIZE_T;
if ( ( m_mainGrid != nullptr ) && m_resultAccessor.notNull() )
{
cellIdx = m_mainGrid->findReservoirCellIndexFromPoint( position );
// adjust cell index to be on correct side of fault
if ( auto search = m_cellIndexAdjustment.find( cellIdx ); search != m_cellIndexAdjustment.end() )
{
cellIdx = search->second;
}
auto cellIdx = findAdjustedCellIndex( position, m_mainGrid, m_cellIndexAdjustment );
if ( ( cellIdx != cvf::UNDEFINED_SIZE_T ) )
{
@@ -106,7 +119,7 @@ double RimFaultReactivationDataAccess::porePressureAtPosition( const cvf::Vec3d&
//--------------------------------------------------------------------------------------------------
double RimFaultReactivationDataAccess::calculatePorePressure( double depth, double gradient )
{
return gradient * 9.81 * depth * 1000;
return gradient * 9.81 * depth * 1000.0;
}
//--------------------------------------------------------------------------------------------------
@@ -116,3 +129,27 @@ size_t RimFaultReactivationDataAccess::timeStepIndex() const
{
return m_timeStepIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFaultReactivationDataAccess::elementHasValidData( std::vector<cvf::Vec3d> elementCorners ) const
{
int nValid = 0;
for ( auto& p : elementCorners )
{
auto cellIdx = findAdjustedCellIndex( p, m_mainGrid, m_cellIndexAdjustment );
if ( ( cellIdx != cvf::UNDEFINED_SIZE_T ) )
{
double value = m_resultAccessor->cellScalar( cellIdx );
if ( !std::isinf( value ) )
{
nValid++;
}
}
}
// if more than half of the nodes have valid data, we're ok
return nValid > 4;
}

View File

@@ -22,6 +22,7 @@
#include "cvfVector3.h"
#include <map>
#include <vector>
class RimEclipseCase;
class RigEclipseCaseData;
@@ -40,12 +41,17 @@ public:
void useCellIndexAdjustment( std::map<size_t, size_t> adjustments );
double porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient );
double porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient ) const;
size_t timeStepIndex() const;
static size_t
findAdjustedCellIndex( const cvf::Vec3d& position, const RigMainGrid* grid, const std::map<size_t, size_t>& cellIndexAdjustmentMap );
bool elementHasValidData( std::vector<cvf::Vec3d> elementCorners ) const;
protected:
double calculatePorePressure( double depth, double gradient );
static double calculatePorePressure( double depth, double gradient );
private:
RimEclipseCase* m_case;

View File

@@ -0,0 +1,61 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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
namespace RimFaultReactivation
{
enum class ModelParts
{
HiPart1,
MidPart1,
LowPart1,
HiPart2,
MidPart2,
LowPart2
};
enum class GridPart
{
PART1,
PART2
};
enum class BorderSurface
{
UpperSurface,
FaultSurface,
LowerSurface
};
enum class Boundary
{
FarSide,
Bottom
};
enum class ElementSets
{
OverBurden,
UnderBurden,
Reservoir,
IntraReservoir
};
} // namespace RimFaultReactivation

View File

@@ -24,6 +24,7 @@
#include "RiaQDateTimeTools.h"
#include "RifJsonEncodeDecode.h"
#include "RifParameterXmlReader.h"
#include "RigBasicPlane.h"
#include "RigFaultReactivationModel.h"
@@ -37,12 +38,14 @@
#include "RivFaultReactivationModelPartMgr.h"
#include "Rim3dView.h"
#include "RimDoubleParameter.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimFaultInView.h"
#include "RimFaultInViewCollection.h"
#include "RimFaultReactivationDataAccess.h"
#include "RimFaultReactivationTools.h"
#include "RimParameterGroup.h"
#include "RimPolylineTarget.h"
#include "RimTimeStepFilter.h"
#include "RimTools.h"
@@ -104,6 +107,8 @@ RimFaultReactivationModel::RimFaultReactivationModel()
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_useLocalCoordinates, "UseLocalCoordinates", false, "Export Using Local Coordinates" );
// Time Step Selection
CAF_PDM_InitFieldNoDefault( &m_timeStepFilter, "TimeStepFilter", "Available Time Steps" );
CAF_PDM_InitFieldNoDefault( &m_selectedTimeSteps, "TimeSteps", "Select Time Steps" );
@@ -113,11 +118,13 @@ RimFaultReactivationModel::RimFaultReactivationModel()
CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" );
m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
m_targets.uiCapability()->setUiTreeChildrenHidden( true );
m_targets.uiCapability()->setUiTreeHidden( true );
m_targets.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
m_targets.uiCapability()->setCustomContextMenuEnabled( false );
CAF_PDM_InitFieldNoDefault( &m_materialParameters, "MaterialParameters", "Materials", ":/Bullet.png" );
this->setUi3dEditorTypeName( RicPolyline3dEditor::uiEditorTypeName() );
this->uiCapability()->setUiTreeChildrenHidden( true );
setDeletable( true );
@@ -140,6 +147,23 @@ void RimFaultReactivationModel::initAfterRead()
updateVisualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFaultReactivationModel::initSettings( QString& outErrmsg )
{
RifParameterXmlReader basicreader( RiaPreferencesGeoMech::current()->geomechFRMDefaultXML() );
if ( !basicreader.parseFile( outErrmsg ) ) return false;
m_materialParameters.deleteChildren();
for ( auto group : basicreader.parameterGroups() )
{
m_materialParameters.push_back( group );
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -297,7 +321,19 @@ void RimFaultReactivationModel::updateVisualization()
m_numberOfCellsVertLow );
m_modelPlane->setThickness( m_modelThickness );
m_modelPlane->updateRects();
// 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();
view->scheduleCreateDisplayModelAndRedraw();
}
@@ -401,6 +437,13 @@ std::pair<cvf::Vec3d, cvf::Vec3d> RimFaultReactivationModel::localCoordSysNormal
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 );
}
@@ -438,6 +481,7 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm
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 );
@@ -560,16 +604,6 @@ std::vector<QDateTime> RimFaultReactivationModel::selectedTimeSteps() const
return dates;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFaultReactivationModel::isFirstTimeStepsSelected() const
{
if ( m_availableTimeSteps.empty() || selectedTimeSteps().empty() ) return false;
return m_availableTimeSteps.front() == selectedTimeSteps().front();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -660,6 +694,7 @@ bool RimFaultReactivationModel::extractAndExportModelData()
if ( !exportModelSettings() ) return false;
auto eCase = eclipseCase();
if ( eCase == nullptr ) return false;
// get the selected time step indexes
std::vector<size_t> selectedTimeStepIndexes;
@@ -671,6 +706,17 @@ bool RimFaultReactivationModel::extractAndExportModelData()
selectedTimeStepIndexes.push_back( idx - m_availableTimeSteps.begin() );
}
auto grid = eCase->mainGrid();
// generate cell index mappings for cells that ends up at the wrong side of the fault
model()->generateCellIndexMapping( grid );
// generate element sets for the various data parts of the model
{
RimFaultReactivationDataAccess dataAccess( eCase, 0 );
model()->generateElementSets( &dataAccess, grid );
}
// extract data for each timestep
size_t outputTimeStepIndex = 0;
for ( auto timeStepIdx : selectedTimeStepIndexes )
@@ -681,3 +727,30 @@ bool RimFaultReactivationModel::extractAndExportModelData()
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::array<double, 3> RimFaultReactivationModel::materialParameters( ElementSets elementSet )
{
std::array<double, 3> retVal = { 0.0, 0.0, 0.0 };
static std::map<ElementSets, std::string> groupMap = { { ElementSets::OverBurden, "material_overburden" },
{ ElementSets::Reservoir, "material_reservoir" },
{ ElementSets::IntraReservoir, "material_intrareservoir" },
{ ElementSets::UnderBurden, "material_underburden" } };
auto keyName = QString::fromStdString( groupMap[elementSet] );
for ( auto& grp : m_materialParameters )
{
if ( grp->name() != keyName ) continue;
retVal[0] = grp->parameterDoubleValue( "youngs_modulus", 0.0 );
retVal[1] = grp->parameterDoubleValue( "poissons_number", 0.0 );
retVal[2] = grp->parameterDoubleValue( "density", 0.0 );
break;
}
return retVal;
}

View File

@@ -18,6 +18,7 @@
#pragma once
#include "RimCheckableNamedObject.h"
#include "RimFaultReactivationEnums.h"
#include "RimPolylinePickerInterface.h"
#include "RimPolylinesDataInterface.h"
#include "RimTimeStepFilter.h"
@@ -42,6 +43,7 @@
class RicPolylineTargetsPickEventHandler;
class RimEclipseCase;
class RimFaultInView;
class RimParameterGroup;
class RimPolylineTarget;
class RimTimeStepFilter;
class RivFaultReactivationModelPartMgr;
@@ -59,11 +61,14 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly
CAF_PDM_HEADER_INIT;
using TimeStepFilterEnum = caf::AppEnum<RimTimeStepFilter::TimeStepFilterTypeEnum>;
using ElementSets = RimFaultReactivation::ElementSets;
public:
RimFaultReactivationModel();
~RimFaultReactivationModel() override;
bool initSettings( QString& outErrmsg );
QString userDescription();
void setUserDescription( QString description );
@@ -102,7 +107,8 @@ public:
void setBaseDir( QString path );
std::vector<QDateTime> selectedTimeSteps() const;
bool isFirstTimeStepsSelected() const;
std::array<double, 3> materialParameters( ElementSets elementSet );
QStringList commandParameters() const;
@@ -157,6 +163,7 @@ private:
caf::PdmField<int> m_numberOfCellsVertUp;
caf::PdmField<int> m_numberOfCellsVertMid;
caf::PdmField<int> m_numberOfCellsVertLow;
caf::PdmField<bool> m_useLocalCoordinates;
cvf::ref<RigBasicPlane> m_faultPlane;
cvf::ref<RigFaultReactivationModel> m_modelPlane;
@@ -164,5 +171,7 @@ private:
caf::PdmField<TimeStepFilterEnum> m_timeStepFilter;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
caf::PdmChildArrayField<RimParameterGroup*> m_materialParameters;
std::vector<QDateTime> m_availableTimeSteps;
};

View File

@@ -46,6 +46,7 @@ RimFaultReactivationModelCollection::RimFaultReactivationModelCollection()
CAF_PDM_InitFieldNoDefault( &m_models, "FaultReactivationModels", "Models" );
m_models.uiCapability()->setUiTreeHidden( true );
m_models.uiCapability()->setUiHidden( true );
setName( "Fault Reactivation Models" );
}
@@ -60,8 +61,11 @@ RimFaultReactivationModelCollection::~RimFaultReactivationModelCollection()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFaultReactivationModel*
RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2, QString baseDir )
RimFaultReactivationModel* RimFaultReactivationModelCollection::addNewModel( RimFaultInView* fault,
cvf::Vec3d target1,
cvf::Vec3d target2,
QString baseDir,
QString& outErrMsg )
{
auto newModel = new RimFaultReactivationModel();
newModel->setFault( fault );
@@ -69,11 +73,20 @@ RimFaultReactivationModel*
newModel->setUserDescription( fault->name() );
newModel->setTargets( target1, target2 );
QString errmsg;
if ( !newModel->initSettings( errmsg ) )
{
delete newModel;
outErrMsg = "Unable to load default parameters from the Fault Reactivation Model default parameter XML file:\n" + errmsg;
return nullptr;
}
m_models.push_back( newModel );
updateConnectedEditors();
newModel->updateVisualization();
// updateView();
return newModel;
}

View File

@@ -50,7 +50,7 @@ public:
RimFaultReactivationModelCollection();
~RimFaultReactivationModelCollection() override;
RimFaultReactivationModel* addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2, QString baseDir );
RimFaultReactivationModel* addNewModel( RimFaultInView* fault, cvf::Vec3d target1, cvf::Vec3d target2, QString baseDir, QString& errMsg );
bool empty();
int size();

View File

@@ -345,3 +345,13 @@ QVariant RimParameterGroup::parameterValue( QString name ) const
}
return QVariant();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimParameterGroup::parameterDoubleValue( QString name, double defaultValue ) const
{
RimDoubleParameter* p = dynamic_cast<RimDoubleParameter*>( parameter( name ) );
if ( p == nullptr ) return defaultValue;
return p->value();
}

View File

@@ -69,6 +69,7 @@ public:
RimGenericParameter* parameter( QString name ) const;
QVariant parameterValue( QString name ) const;
double parameterDoubleValue( QString name, double defaultValue ) const;
private:
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;