From bd7f34f835689d3649c42e878e1f1ff1c7f20a8e Mon Sep 17 00:00:00 2001 From: jonjenssen <69144954+jonjenssen@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:29:28 +0200 Subject: [PATCH] Fault Reactivation Modeling updates (#10602) * Add timestep selection * Add import geomech model to context menu * Add command for running fault reactivation * Change order of nodes for exported elements * Add command to quickly show model in 3D view --- .../GeoMechCommands/CMakeLists_files.cmake | 4 + .../RicNewFaultReactModelingFeature.cpp | 1 + .../RicRunFaultReactModelingFeature.cpp | 135 ++++++++++++++++++ .../RicRunFaultReactModelingFeature.h | 34 +++++ .../RicShowFaultReactModelFeature.cpp | 102 +++++++++++++ .../RicShowFaultReactModelFeature.h | 34 +++++ .../Faults/RimFaultReactivationModel.cpp | 109 +++++++++++++- .../Faults/RimFaultReactivationModel.h | 23 +++ .../RimFaultReactivationModelCollection.cpp | 11 ++ .../RimFaultReactivationModelCollection.h | 2 + .../RimContextCommandBuilder.cpp | 9 ++ .../ProjectDataModel/RimEclipseView.cpp | 2 + .../ProjectDataModel/RimTimeStepFilter.cpp | 60 ++++++++ .../ProjectDataModel/RimTimeStepFilter.h | 11 +- .../ReservoirDataModel/RigGriddedPart3d.cpp | 10 +- 15 files changed, 536 insertions(+), 11 deletions(-) create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.h create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.cpp create mode 100644 ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.h diff --git a/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake index 540177f86a..556d4f23fe 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/GeoMechCommands/CMakeLists_files.cmake @@ -11,6 +11,8 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewWellIntegrityAnalysisFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicRunWellIntegrityAnalysisFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewFaultReactModelingFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicRunFaultReactModelingFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicShowFaultReactModelFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -26,6 +28,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewWellIntegrityAnalysisFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRunWellIntegrityAnalysisFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewFaultReactModelingFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicRunFaultReactModelingFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicShowFaultReactModelFeature.cpp ) list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp index f061674a4e..1f4adc7724 100644 --- a/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicNewFaultReactModelingFeature.cpp @@ -113,6 +113,7 @@ void RicNewFaultReactModelingFeature::onActionTriggered( bool isChecked ) auto model = eclView->faultReactivationModelCollection()->addNewModel( rimFault, target1, target2, baseDir ); if ( model != nullptr ) { + model->updateTimeSteps(); view->updateAllRequiredEditors(); Riu3DMainWindowTools::selectAsCurrentItem( model ); } diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp new file mode 100644 index 0000000000..3c1e718925 --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.cpp @@ -0,0 +1,135 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicRunFaultReactModelingFeature.h" + +#include "RiaApplication.h" +#include "RiaPreferencesGeoMech.h" + +#include "RifFaultReactivationModelExporter.h" + +#include "RimFaultReactivationModel.h" +#include "RimProcess.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuFileDialogTools.h" + +#include "cafProgressInfo.h" +#include "cafSelectionManagerTools.h" + +#include +#include + +CAF_CMD_SOURCE_INIT( RicRunFaultReactModelingFeature, "RicRunFaultReactModelingFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicRunFaultReactModelingFeature::isCommandEnabled() const +{ + return RiaPreferencesGeoMech::current()->validateFRMSettings(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicRunFaultReactModelingFeature::onActionTriggered( bool isChecked ) +{ + RimFaultReactivationModel* model = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); + if ( model == nullptr ) return; + + const QString frmTitle( "Fault Reactivation Modeling" ); + + caf::ProgressInfo runProgress( 3, frmTitle + " running , please wait..." ); + + runProgress.setProgressDescription( "Writing input files." ); + + if ( model->fault() == nullptr ) + { + QMessageBox::critical( nullptr, frmTitle, "A fault has not selected. Please check your model settings." ); + return; + } + + if ( !model->extractModelData() ) + { + QMessageBox::critical( nullptr, frmTitle, "Unable to get necessary data from the input model." ); + return; + } + + QString exportFile = model->inputFilename(); + auto [result, errText] = RifFaultReactivationModelExporter::exportToFile( exportFile.toStdString(), *model->model() ); + + if ( !result ) + { + QString outErrorText = + QString( "Failed to export INP model to file %1.\n\n%2" ).arg( exportFile ).arg( QString::fromStdString( errText ) ); + QMessageBox::critical( nullptr, frmTitle, outErrorText ); + return; + } + + if ( RiaPreferencesGeoMech::current()->waitBeforeRun() ) + { + runProgress.setProgressDescription( "Waiting for input file modifications." ); + + QString infoText = "Input parameter files can now be found in the working folder:"; + infoText += " \"" + model->baseDir() + "\"\n"; + infoText += "\nClick OK to start the Abaqus modeling or Cancel to stop."; + + auto reply = QMessageBox::information( nullptr, frmTitle, infoText, QMessageBox::Ok | QMessageBox::Cancel ); + + if ( reply != QMessageBox::Ok ) return; + } + + runProgress.incrementProgress(); + runProgress.setProgressDescription( "Running Abaqus modeling." ); + + QString command = RiaPreferencesGeoMech::current()->geomechFRMCommand(); + QStringList parameters = model->commandParameters(); + + RimProcess process; + process.setCommand( command ); + process.setParameters( parameters ); + + if ( !process.execute() ) + { + QMessageBox::critical( nullptr, frmTitle, "Failed to run modeling. Check log window for additional information." ); + return; + } + + runProgress.incrementProgress(); + runProgress.setProgressDescription( "Loading modeling results." ); + + RiaApplication* app = RiaApplication::instance(); + if ( !app->openOdbCaseFromFile( model->outputOdbFilename() ) ) + { + QMessageBox::critical( nullptr, + frmTitle, + "Failed to load modeling results from file \"" + model->outputOdbFilename() + + "\". Check log window for additional information." ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicRunFaultReactModelingFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setIcon( QIcon( ":/fault_react_24x24.png" ) ); + actionToSetup->setText( "Run..." ); +} diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.h b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.h new file mode 100644 index 0000000000..417639015b --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicRunFaultReactModelingFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicRunFaultReactModelingFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.cpp b/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.cpp new file mode 100644 index 0000000000..57a93614bb --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.cpp @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicShowFaultReactModelFeature.h" + +#include "RiaApplication.h" +#include "RiaPreferencesGeoMech.h" + +#include "RifFaultReactivationModelExporter.h" + +#include "RimFaultReactivationModel.h" +#include "RimGeoMechCase.h" +#include "RimGeoMechView.h" +#include "RimProject.h" + +#include "Riu3DMainWindowTools.h" + +#include "cafSelectionManagerTools.h" + +#include +#include + +CAF_CMD_SOURCE_INIT( RicShowFaultReactModelFeature, "RicShowFaultReactModelFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicShowFaultReactModelFeature::isCommandEnabled() const +{ + return RiaPreferencesGeoMech::current()->validateFRMSettings(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowFaultReactModelFeature::onActionTriggered( bool isChecked ) +{ + RimFaultReactivationModel* model = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); + if ( model == nullptr ) return; + + const QString frmTitle( "Fault Reactivation Modeling" ); + const QString exportFile = model->inputFilename(); + + auto [result, errText] = RifFaultReactivationModelExporter::exportToFile( exportFile.toStdString(), *model->model() ); + if ( !result ) + { + QString outErrorText = + QString( "Failed to export INP model to file %1.\n\n%2" ).arg( exportFile ).arg( QString::fromStdString( errText ) ); + QMessageBox::critical( nullptr, frmTitle, outErrorText ); + return; + } + + for ( auto gCase : RimProject::current()->geoMechCases() ) + { + if ( exportFile == gCase->gridFileName() ) + { + gCase->reloadDataAndUpdate(); + auto& views = gCase->geoMechViews(); + if ( views.size() > 0 ) + { + Riu3DMainWindowTools::selectAsCurrentItem( views[0] ); + } + else + { + Riu3DMainWindowTools::selectAsCurrentItem( gCase ); + } + return; + } + } + + RiaApplication* app = RiaApplication::instance(); + if ( !app->openOdbCaseFromFile( exportFile ) ) + { + QMessageBox::critical( nullptr, + frmTitle, + "Failed to load INP model from file \"" + exportFile + "\". Check log window for additional information." ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicShowFaultReactModelFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setIcon( QIcon( ":/fault_react_24x24.png" ) ); + actionToSetup->setText( "Show Model in 3D View..." ); +} diff --git a/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.h b/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.h new file mode 100644 index 0000000000..ae9baf0a87 --- /dev/null +++ b/ApplicationLibCode/Commands/GeoMechCommands/RicShowFaultReactModelFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicShowFaultReactModelFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp index 13c29a8deb..75e37df7f4 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.cpp @@ -19,7 +19,9 @@ #include "RimFaultReactivationModel.h" #include "RiaApplication.h" +#include "RiaPreferences.h" #include "RiaPreferencesGeoMech.h" +#include "RiaQDateTimeTools.h" #include "RigBasicPlane.h" #include "RigFaultReactivationModel.h" @@ -38,14 +40,19 @@ #include "RimFaultInView.h" #include "RimFaultInViewCollection.h" #include "RimPolylineTarget.h" +#include "RimTimeStepFilter.h" #include "RimTools.h" #include "cafPdmUiDoubleSliderEditor.h" #include "cafPdmUiTableViewEditor.h" +#include "cafPdmUiTreeSelectionEditor.h" #include "cvfPlane.h" #include "cvfTextureImage.h" +#include +#include + CAF_PDM_SOURCE_INIT( RimFaultReactivationModel, "FaultReactivationModel" ); //-------------------------------------------------------------------------------------------------- @@ -91,6 +98,12 @@ 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" ); + // Time Step Selection + CAF_PDM_InitFieldNoDefault( &m_timeStepFilter, "TimeStepFilter", "Available Time Steps" ); + CAF_PDM_InitFieldNoDefault( &m_selectedTimeSteps, "TimeSteps", "Select Time Steps" ); + m_selectedTimeSteps.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); + m_selectedTimeSteps.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); + CAF_PDM_InitFieldNoDefault( &m_targets, "Targets", "Targets" ); m_targets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() ); m_targets.uiCapability()->setUiTreeChildrenHidden( true ); @@ -301,6 +314,10 @@ QList RimFaultReactivationModel::calculateValueOptions( if ( coll != nullptr ) RimTools::faultOptionItems( &options, coll ); } } + else if ( fieldNeedingOptions == &m_selectedTimeSteps ) + { + RimTimeStepFilter::timeStepOptions( options, &m_selectedTimeSteps, m_availableTimeSteps, m_selectedTimeSteps, m_timeStepFilter() ); + } return options; } @@ -382,6 +399,10 @@ void RimFaultReactivationModel::defineUiOrdering( QString uiConfigName, caf::Pdm gridModelGrp->add( &m_numberOfCellsVertMid ); gridModelGrp->add( &m_numberOfCellsVertLow ); + auto timeStepGrp = uiOrdering.addNewGroup( "Time Steps" ); + timeStepGrp->add( &m_timeStepFilter ); + timeStepGrp->add( &m_selectedTimeSteps ); + auto appModelGrp = modelGrp->addNewGroup( "Appearance" ); appModelGrp->add( &m_modelPart1Color ); appModelGrp->add( &m_modelPart2Color ); @@ -449,12 +470,14 @@ void RimFaultReactivationModel::defineEditorAttribute( const caf::PdmFieldHandle //-------------------------------------------------------------------------------------------------- RimEclipseCase* RimFaultReactivationModel::eclipseCase() { - auto activeView = dynamic_cast( RiaApplication::instance()->activeGridView() ); - if ( activeView ) + auto eCase = firstAncestorOrThisOfType(); + + if ( eCase == nullptr ) { - return activeView->eclipseCase(); + eCase = dynamic_cast( RiaApplication::instance()->activeGridView()->ownerCase() ); } - return nullptr; + + return eCase; } //-------------------------------------------------------------------------------------------------- @@ -472,3 +495,81 @@ QString RimFaultReactivationModel::baseDir() const { return m_baseDir().path(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModel::updateTimeSteps() +{ + m_availableTimeSteps.clear(); + const auto eCase = eclipseCase(); + if ( eCase == nullptr ) return; + + m_availableTimeSteps = eCase->timeStepDates(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimFaultReactivationModel::selectedTimeSteps() const +{ + return m_selectedTimeSteps(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QStringList RimFaultReactivationModel::commandParameters() const +{ + QStringList retlist; + + retlist << baseDir(); + retlist << inputFilename(); + retlist << outputOdbFilename(); + + return retlist; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModel::outputOdbFilename() const +{ + QDir directory( baseDir() ); + return directory.absoluteFilePath( baseFilename() + ".odb" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModel::inputFilename() const +{ + QDir directory( baseDir() ); + return directory.absoluteFilePath( baseFilename() + ".inp" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFaultReactivationModel::baseFilename() const +{ + QString tmp = m_userDescription(); + + if ( tmp.isEmpty() ) return "faultReactivation"; + + tmp.replace( ' ', '_' ); + tmp.replace( '/', '_' ); + tmp.replace( '\\', '_' ); + tmp.replace( ':', '_' ); + + return tmp; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFaultReactivationModel::extractModelData() +{ + // TODO - get values from eclipse and geomech models here + return true; +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h index 2ad061a90d..68e543956c 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModel.h @@ -20,6 +20,7 @@ #include "RimCheckableNamedObject.h" #include "RimPolylinePickerInterface.h" #include "RimPolylinesDataInterface.h" +#include "RimTimeStepFilter.h" #include "cafFilePath.h" #include "cafPdmChildArrayField.h" @@ -31,7 +32,9 @@ #include "cvfColor3.h" #include "cvfVector3.h" +#include #include +#include #include #include @@ -40,6 +43,7 @@ class RicPolylineTargetsPickEventHandler; class RimEclipseCase; class RimFaultInView; class RimPolylineTarget; +class RimTimeStepFilter; class RivFaultReactivationModelPartMgr; class RigBasicPlane; class RigFaultReactivationModel; @@ -54,6 +58,8 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly { CAF_PDM_HEADER_INIT; + using TimeStepFilterEnum = caf::AppEnum; + public: RimFaultReactivationModel(); ~RimFaultReactivationModel() override; @@ -86,9 +92,19 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly cvf::ref model() const; bool showModel() const; + bool extractModelData(); + QString baseDir() const; void setBaseDir( QString path ); + std::vector selectedTimeSteps() const; + + QStringList commandParameters() const; + QString outputOdbFilename() const; + QString inputFilename() const; + + void updateTimeSteps(); + protected: caf::PdmFieldHandle* userDescriptionField() override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; @@ -101,6 +117,8 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly void initAfterRead() override; + QString baseFilename() const; + private: std::shared_ptr m_pickTargetsEventHandler; @@ -133,4 +151,9 @@ class RimFaultReactivationModel : public RimCheckableNamedObject, public RimPoly cvf::ref m_faultPlane; cvf::ref m_modelPlane; + + caf::PdmField m_timeStepFilter; + caf::PdmField> m_selectedTimeSteps; + + std::vector m_availableTimeSteps; }; diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp index 82fc498747..4ba6a0870e 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.cpp @@ -186,3 +186,14 @@ void RimFaultReactivationModelCollection::appendPartsToModel( Rim3dView* model->updateBoundingBoxesRecursive(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFaultReactivationModelCollection::syncTimeSteps() +{ + for ( auto& frm : m_models ) + { + frm->updateTimeSteps(); + } +} diff --git a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h index 0089a6b0e7..1be362fa81 100644 --- a/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Faults/RimFaultReactivationModelCollection.h @@ -65,6 +65,8 @@ class RimFaultReactivationModelCollection : public RimCheckableNamedObject caf::DisplayCoordTransform* transform, const cvf::BoundingBox& boundingBox ); + void syncTimeSteps(); + protected: caf::PdmFieldHandle* userDescriptionField() override; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 02933a5aa9..d5ce8911ce 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -83,6 +83,7 @@ #include "RimGeoMechCellColors.h" #include "RimGeoMechContourMapView.h" #include "RimGeoMechContourMapViewCollection.h" +#include "RimGeoMechModels.h" #include "RimGeoMechPropertyFilter.h" #include "RimGeoMechPropertyFilterCollection.h" #include "RimGeoMechView.h" @@ -271,6 +272,11 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "Separator"; menuBuilder << "RicNewStatisticsCaseFeature"; } + else if ( dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicImportGeoMechCaseFeature"; + menuBuilder << "Separator"; + } else if ( dynamic_cast( firstUiItem ) ) { menuBuilder << "RicNewViewFeature"; @@ -474,6 +480,9 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() } else if ( dynamic_cast( firstUiItem ) ) { + menuBuilder << "RicRunFaultReactModelingFeature"; + menuBuilder << "Separator"; + menuBuilder << "RicShowFaultReactModelFeature"; menuBuilder << "RicExportInpFileFeature"; } else if ( dynamic_cast( firstUiItem ) ) diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 3f114746d7..66b72eadd7 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -1115,6 +1115,8 @@ void RimEclipseView::onLoadDataAndUpdate() m_wellMeasurementCollection->syncWithChangesInWellMeasurementCollection(); + m_faultReactivationModelCollection->syncTimeSteps(); + scheduleCreateDisplayModelAndRedraw(); } diff --git a/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.cpp b/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.cpp index 104c337997..9a5a53908d 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.cpp @@ -18,6 +18,7 @@ #include "RimTimeStepFilter.h" +#include "RiaPreferences.h" #include "RiaQDateTimeTools.h" #include "RifReaderEclipseOutput.h" @@ -479,3 +480,62 @@ bool RimTimeStepFilter::readOnlyLastFrame() const { return m_readOnlyLastFrame; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimTimeStepFilter::timeStepOptions( QList& options, + const caf::PdmFieldHandle* timestepField, + std::vector availableTimeSteps, + std::vector selectedTimeSteps, + RimTimeStepFilter::TimeStepFilterTypeEnum filterType ) +{ + if ( availableTimeSteps.empty() ) return; + + std::set currentlySelectedTimeSteps( selectedTimeSteps.begin(), selectedTimeSteps.end() ); + std::set currentlySelectedTimeStepIndices; + std::vector allDateTimes; + for ( auto& dateTime : availableTimeSteps ) + { + if ( currentlySelectedTimeSteps.count( dateTime ) ) + { + currentlySelectedTimeStepIndices.insert( (int)allDateTimes.size() ); + } + allDateTimes.push_back( dateTime ); + } + + std::vector filteredTimeStepIndices = + RimTimeStepFilter::filteredTimeStepIndices( allDateTimes, 0, (int)allDateTimes.size() - 1, filterType, 1 ); + + // Add existing time steps to list of options to avoid removing them when changing filter. + filteredTimeStepIndices.insert( filteredTimeStepIndices.end(), + currentlySelectedTimeStepIndices.begin(), + currentlySelectedTimeStepIndices.end() ); + std::sort( filteredTimeStepIndices.begin(), filteredTimeStepIndices.end() ); + filteredTimeStepIndices.erase( std::unique( filteredTimeStepIndices.begin(), filteredTimeStepIndices.end() ), + filteredTimeStepIndices.end() ); + + QString dateFormatString = RiaQDateTimeTools::dateFormatString( RiaPreferences::current()->dateFormat(), + RiaDefines::DateFormatComponents::DATE_FORMAT_YEAR_MONTH_DAY ); + QString timeFormatString = RiaQDateTimeTools::timeFormatString( RiaPreferences::current()->timeFormat(), + RiaDefines::TimeFormatComponents::TIME_FORMAT_HOUR_MINUTE ); + QString dateTimeFormatString = QString( "%1 %2" ).arg( dateFormatString ).arg( timeFormatString ); + + bool showTime = ( filterType == RimTimeStepFilter::TS_ALL ) || ( filterType == RimTimeStepFilter::TS_INTERVAL_DAYS ); + + for ( auto timeStepIndex : filteredTimeStepIndices ) + { + QDateTime dateTime = allDateTimes[timeStepIndex]; + + if ( showTime && dateTime.time() != QTime( 0, 0, 0 ) ) + { + options.push_back( + caf::PdmOptionItemInfo( RiaQDateTimeTools::toStringUsingApplicationLocale( dateTime, dateTimeFormatString ), dateTime ) ); + } + else + { + options.push_back( + caf::PdmOptionItemInfo( RiaQDateTimeTools::toStringUsingApplicationLocale( dateTime, dateFormatString ), dateTime ) ); + } + } +} diff --git a/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.h b/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.h index 1f53a32015..c965fd3fe4 100644 --- a/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.h +++ b/ApplicationLibCode/ProjectDataModel/RimTimeStepFilter.h @@ -63,14 +63,21 @@ class RimTimeStepFilter : public caf::PdmObject void setReadOnlyLastFrame( bool onlyLast ); bool readOnlyLastFrame() const; + std::vector> allTimeSteps() const; + + static void timeStepOptions( QList& options, + const caf::PdmFieldHandle* timestepField, + std::vector availableTimeSteps, + std::vector selectedTimeSteps, + TimeStepFilterTypeEnum filterType ); + protected: void initAfterRead() override; private: static QDateTime incrementDateTime( const QDateTime& dateTime, TimeStepFilterTypeEnum filterType, int interval ); - std::vector> allTimeSteps() const; - std::vector filteredTimeStepIndicesFromUi() const; + std::vector filteredTimeStepIndicesFromUi() const; void updateFieldVisibility(); RimEclipseResultCase* parentEclipseResultCase() const; diff --git a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp index 55e574adb3..c748a11d1e 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGriddedPart3d.cpp @@ -198,16 +198,16 @@ void RigGriddedPart3d::generateGeometry( std::vector inputPoints, { for ( int t = 0; t < nThicknessCells; t++, elementIdx++ ) { - m_elementIndices[elementIdx].push_back( t + i ); - m_elementIndices[elementIdx].push_back( t + i + nThicknessOff ); - m_elementIndices[elementIdx].push_back( t + i + nThicknessOff + 1 ); - m_elementIndices[elementIdx].push_back( t + i + 1 ); - m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i ); m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + nThicknessOff ); m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + nThicknessOff + 1 ); m_elementIndices[elementIdx].push_back( t + nextLayerIdxOff + i + 1 ); + m_elementIndices[elementIdx].push_back( t + i ); + m_elementIndices[elementIdx].push_back( t + i + nThicknessOff ); + m_elementIndices[elementIdx].push_back( t + i + nThicknessOff + 1 ); + m_elementIndices[elementIdx].push_back( t + i + 1 ); + if ( layer == 0 ) { m_boundaryElements[Boundary::Bottom].push_back( elementIdx );