mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Fault Reactivation updates (#10665)
* Support getting pore pressure for all nodes * Misc fixes and updates in fault reactivation UI * Disable fault reactivation result unless you load an odb from a valid working folder
This commit is contained in:
@@ -4,6 +4,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccess.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -12,6 +13,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationModelCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimFaultReactivationDataAccess.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "RimFaultReactivationDataAccess.h"
|
||||
|
||||
#include "RiaPorosityModel.h"
|
||||
|
||||
#include "RigCaseCellResultsData.h"
|
||||
#include "RigEclipseCaseData.h"
|
||||
#include "RigEclipseResultAddress.h"
|
||||
#include "RigFault.h"
|
||||
#include "RigMainGrid.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFaultReactivationDataAccess::RimFaultReactivationDataAccess( RimEclipseCase* thecase, size_t timeStepIndex )
|
||||
: m_case( thecase )
|
||||
, m_caseData( nullptr )
|
||||
, m_mainGrid( nullptr )
|
||||
, m_timeStepIndex( timeStepIndex )
|
||||
{
|
||||
if ( m_case )
|
||||
{
|
||||
m_caseData = m_case->eclipseCaseData();
|
||||
m_mainGrid = m_case->mainGrid();
|
||||
}
|
||||
if ( m_caseData )
|
||||
{
|
||||
RigEclipseResultAddress resVarAddress( RiaDefines::ResultCatType::DYNAMIC_NATIVE, "PRESSURE" );
|
||||
|
||||
m_case->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( resVarAddress );
|
||||
|
||||
m_resultAccessor = RigResultAccessorFactory::createFromResultAddress( m_caseData,
|
||||
0,
|
||||
RiaDefines::PorosityModelType::MATRIX_MODEL,
|
||||
timeStepIndex,
|
||||
resVarAddress );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFaultReactivationDataAccess::~RimFaultReactivationDataAccess()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFaultReactivationDataAccess::useCellIndexAdjustment( std::map<size_t, size_t> adjustments )
|
||||
{
|
||||
m_cellIndexAdjustment = adjustments;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFaultReactivationDataAccess::porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if ( ( cellIdx != cvf::UNDEFINED_SIZE_T ) )
|
||||
{
|
||||
double value = m_resultAccessor->cellScalar( cellIdx );
|
||||
if ( !std::isinf( value ) )
|
||||
{
|
||||
return 100000.0 * m_resultAccessor->cellScalar( cellIdx ); // return in pascal, not bar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return calculatePorePressure( std::abs( position.z() ), defaultPorePressureGradient );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFaultReactivationDataAccess::calculatePorePressure( double depth, double gradient )
|
||||
{
|
||||
return gradient * 9.81 * depth * 1000;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimFaultReactivationDataAccess::timeStepIndex() const
|
||||
{
|
||||
return m_timeStepIndex;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2021 - 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 "cvfObject.h"
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class RimEclipseCase;
|
||||
class RigEclipseCaseData;
|
||||
class RigResultAccessor;
|
||||
class RigMainGrid;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimFaultReactivationDataAccess
|
||||
{
|
||||
public:
|
||||
RimFaultReactivationDataAccess( RimEclipseCase* thecase, size_t timeStepIndex );
|
||||
~RimFaultReactivationDataAccess();
|
||||
|
||||
void useCellIndexAdjustment( std::map<size_t, size_t> adjustments );
|
||||
|
||||
double porePressureAtPosition( const cvf::Vec3d& position, double defaultPorePressureGradient );
|
||||
|
||||
size_t timeStepIndex() const;
|
||||
|
||||
protected:
|
||||
double calculatePorePressure( double depth, double gradient );
|
||||
|
||||
private:
|
||||
RimEclipseCase* m_case;
|
||||
RigEclipseCaseData* m_caseData;
|
||||
const RigMainGrid* m_mainGrid;
|
||||
size_t m_timeStepIndex;
|
||||
cvf::ref<RigResultAccessor> m_resultAccessor;
|
||||
std::map<size_t, size_t> m_cellIndexAdjustment;
|
||||
};
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimFaultInView.h"
|
||||
#include "RimFaultInViewCollection.h"
|
||||
#include "RimFaultReactivationDataAccess.h"
|
||||
#include "RimFaultReactivationTools.h"
|
||||
#include "RimPolylineTarget.h"
|
||||
#include "RimTimeStepFilter.h"
|
||||
@@ -163,6 +164,29 @@ caf::PdmFieldHandle* RimFaultReactivationModel::userDescriptionField()
|
||||
return &m_userDescription;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<bool, std::string> RimFaultReactivationModel::validateBeforeRun() const
|
||||
{
|
||||
if ( fault() == nullptr )
|
||||
{
|
||||
return std::make_pair( false, "A fault has not been selected. Please check your model settings." );
|
||||
}
|
||||
|
||||
if ( selectedTimeSteps().size() < 2 )
|
||||
{
|
||||
return std::make_pair( false, "You need at least 2 selected timesteps. Please check your model settings." );
|
||||
}
|
||||
|
||||
if ( selectedTimeSteps()[0] != m_availableTimeSteps[0] )
|
||||
{
|
||||
return std::make_pair( false, "The first available timestep must always be selected. Please check your model settings." );
|
||||
}
|
||||
|
||||
return std::make_pair( true, "" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -527,7 +551,13 @@ void RimFaultReactivationModel::updateTimeSteps()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QDateTime> RimFaultReactivationModel::selectedTimeSteps() const
|
||||
{
|
||||
return m_selectedTimeSteps();
|
||||
std::vector<QDateTime> dates;
|
||||
for ( auto d : m_selectedTimeSteps() )
|
||||
dates.push_back( d );
|
||||
|
||||
// selected dates might come in the order they were selected, sort them
|
||||
std::sort( dates.begin(), dates.end() );
|
||||
return dates;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -625,8 +655,29 @@ bool RimFaultReactivationModel::exportModelSettings()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimFaultReactivationModel::extractAndExportModelData()
|
||||
{
|
||||
exportModelSettings();
|
||||
model()->clearModelData();
|
||||
|
||||
if ( !exportModelSettings() ) return false;
|
||||
|
||||
auto eCase = eclipseCase();
|
||||
|
||||
// get the selected time step indexes
|
||||
std::vector<size_t> selectedTimeStepIndexes;
|
||||
for ( auto& timeStep : selectedTimeSteps() )
|
||||
{
|
||||
auto idx = std::find( m_availableTimeSteps.begin(), m_availableTimeSteps.end(), timeStep );
|
||||
if ( idx == m_availableTimeSteps.end() ) return false;
|
||||
|
||||
selectedTimeStepIndexes.push_back( idx - m_availableTimeSteps.begin() );
|
||||
}
|
||||
|
||||
// extract data for each timestep
|
||||
size_t outputTimeStepIndex = 0;
|
||||
for ( auto timeStepIdx : selectedTimeStepIndexes )
|
||||
{
|
||||
RimFaultReactivationDataAccess dataAccess( eCase, timeStepIdx );
|
||||
model()->extractModelData( &dataAccess, outputTimeStepIndex++ );
|
||||
}
|
||||
|
||||
// TODO - get values from eclipse and geomech models here
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ public:
|
||||
QString userDescription();
|
||||
void setUserDescription( QString description );
|
||||
|
||||
std::pair<bool, std::string> validateBeforeRun() const;
|
||||
|
||||
void setFault( RimFaultInView* fault );
|
||||
RimFaultInView* fault() const;
|
||||
|
||||
|
||||
@@ -101,6 +101,14 @@ RimGeoMechFaultReactivationResult::~RimGeoMechFaultReactivationResult()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGeoMechFaultReactivationResult::isValid() const
|
||||
{
|
||||
return m_bHaveValidData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -109,7 +117,9 @@ void RimGeoMechFaultReactivationResult::onLoadDataAndUpdate()
|
||||
auto geomCase = geoMechCase();
|
||||
if ( geomCase == nullptr ) return;
|
||||
|
||||
auto filename = geomCase->gridFileName();
|
||||
auto filename = geomCase->gridFileName();
|
||||
if ( !filename.toLower().endsWith( ".odb" ) ) return;
|
||||
|
||||
QFileInfo fi( filename );
|
||||
auto folder = fi.path();
|
||||
auto basename = fi.baseName();
|
||||
|
||||
@@ -47,6 +47,8 @@ public:
|
||||
|
||||
void onLoadDataAndUpdate();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
@@ -201,7 +201,13 @@ void RimGeoMechView::onLoadDataAndUpdate()
|
||||
|
||||
if ( m_partsCollection ) m_partsCollection->syncWithCase( m_geomechCase );
|
||||
|
||||
if ( m_faultReactivationResult ) m_faultReactivationResult->onLoadDataAndUpdate();
|
||||
if ( m_faultReactivationResult )
|
||||
{
|
||||
if ( m_geomechCase->gridFileName().toLower().endsWith( ".odb" ) )
|
||||
{
|
||||
m_faultReactivationResult->onLoadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
scheduleCreateDisplayModelAndRedraw();
|
||||
|
||||
@@ -1025,7 +1031,11 @@ void RimGeoMechView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrderin
|
||||
uiTreeOrdering.add( m_tensorResults() );
|
||||
uiTreeOrdering.add( m_cellFilterCollection() );
|
||||
uiTreeOrdering.add( m_propertyFilterCollection() );
|
||||
uiTreeOrdering.add( m_faultReactivationResult() );
|
||||
|
||||
if ( ( m_faultReactivationResult() != nullptr ) && ( m_faultReactivationResult->isValid() ) )
|
||||
{
|
||||
uiTreeOrdering.add( m_faultReactivationResult() );
|
||||
}
|
||||
|
||||
addRequiredUiTreeObjects( uiTreeOrdering );
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "RigFemPartCollection.h"
|
||||
#include "RigFemPartResultsCollection.h"
|
||||
#include "RigGeoMechCaseData.h"
|
||||
#include "RigHexIntersectionTools.h"
|
||||
|
||||
#include "RimGeoMechCase.h"
|
||||
|
||||
#include "../cafHexInterpolator/cafHexInterpolator.h" // Use relative path, as this is a header only file not part of a library
|
||||
@@ -67,11 +69,21 @@ int RimWellIADataAccess::elementIndex( cvf::Vec3d position )
|
||||
cvf::BoundingBox bb;
|
||||
bb.add( position );
|
||||
|
||||
auto part = m_caseData->femParts()->part( 0 );
|
||||
|
||||
std::vector<size_t> closeElements;
|
||||
m_caseData->femParts()->part( 0 )->findIntersectingElementIndices( bb, &closeElements );
|
||||
part->findIntersectingElementIndices( bb, &closeElements );
|
||||
if ( closeElements.empty() ) return -1;
|
||||
|
||||
return (int)closeElements[0];
|
||||
for ( auto elmIdx : closeElements )
|
||||
{
|
||||
std::array<cvf::Vec3d, 8> coordinates;
|
||||
if ( !part->fillElementCoordinates( elmIdx, coordinates ) ) continue;
|
||||
|
||||
if ( RigHexIntersectionTools::isPointInCell( position, coordinates.data() ) ) return (int)elmIdx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user