ResInsight/ApplicationCode/ProjectDataModel/RimGeoMechCase.cpp

1305 lines
52 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// 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 "RimGeoMechCase.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RicImportElementPropertyFeature.h"
#include "RicfCommandObject.h"
#include "RifOdbReader.h"
#include "RigFemPart.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
#include "RigFemPartResultsCollection.h"
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "Rim2dIntersectionViewCollection.h"
#include "RimFormationNames.h"
#include "RimGeoMechCellColors.h"
#include "RimGeoMechContourMapView.h"
#include "RimGeoMechContourMapViewCollection.h"
#include "RimGeoMechPropertyFilter.h"
#include "RimGeoMechPropertyFilterCollection.h"
#include "RimGeoMechResultDefinition.h"
#include "RimGeoMechView.h"
#include "RimIntersectionCollection.h"
#include "RimMainPlotCollection.h"
#include "RimMudWeightWindowParameters.h"
#include "RimProject.h"
#include "RimTimeStepFilter.h"
#include "RimTools.h"
#include "RimWellLogPlotCollection.h"
#include "cafCmdFeatureManager.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cafUtils.h"
#include "cvfVector3.h"
#include <QFileInfo>
#include <array>
CAF_PDM_SOURCE_INIT( RimGeoMechCase, "ResInsightGeoMechCase" );
namespace caf
{
template <>
void caf::AppEnum<RimGeoMechCase::BiotCoefficientType>::setUp()
{
addItem( RimGeoMechCase::BiotCoefficientType::BIOT_NONE, "BIOT_NONE", "None" );
addItem( RimGeoMechCase::BiotCoefficientType::BIOT_FIXED, "BIOT_FIXED", "Fixed Biot Coefficient" );
addItem( RimGeoMechCase::BiotCoefficientType::BIOT_PER_ELEMENT,
"BIOT_PER_ELEMENT",
"Biot coefficient from element properties" );
setDefault( RimGeoMechCase::BiotCoefficientType::BIOT_NONE );
}
template <>
void caf::AppEnum<RimGeoMechCase::InitialPermeabilityType>::setUp()
{
addItem( RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED,
"INITIAL_PERMEABILITY_FIXED",
"Fixed Initial Permeability" );
addItem( RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_PER_ELEMENT,
"INITIAL_PERMEABILITY_PER_ELEMENT",
"Initial permeability from element properties" );
setDefault( RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED );
}
} // End namespace caf
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechCase::RimGeoMechCase( void )
: m_applyTimeFilter( false )
{
CAF_PDM_InitScriptableObjectWithNameAndComment( "GeoMechanical Case",
":/GeoMechCase48x48.png",
"",
"The GeoMechanical Results Case",
"GeoMechCase",
"The Abaqus Based GeoMech Case" );
CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault( &geoMechViews,
"GeoMechViews",
"Views",
"",
"",
"",
"All GeoMech Views in the Case" );
geoMechViews.uiCapability()->setUiHidden( true );
CAF_PDM_InitField( &m_cohesion, "CaseCohesion", 10.0, "Cohesion", "", "Used to calculate the SE:SFI result", "" );
CAF_PDM_InitField( &m_frictionAngleDeg,
"FrctionAngleDeg",
30.0,
"Friction Angle [Deg]",
"",
"Used to calculate the SE:SFI result",
"" );
CAF_PDM_InitFieldNoDefault( &m_elementPropertyFileNames, "ElementPropertyFileNames", "Element Property Files", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_elementPropertyFileNameIndexUiSelection,
"ElementPropertyFileNameIndexUiSelection",
"",
"",
"",
"" );
m_elementPropertyFileNameIndexUiSelection.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_importElementPropertyFileCommand, "importElementPropertyFileCommad", false, "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_importElementPropertyFileCommand );
CAF_PDM_InitField( &m_closeElementPropertyFileCommand, "closeElementPropertyFileCommad", false, "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_closeElementPropertyFileCommand );
CAF_PDM_InitField( &m_reloadElementPropertyFileCommand, "reloadElementPropertyFileCommand", false, "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_reloadElementPropertyFileCommand );
caf::AppEnum<BiotCoefficientType> defaultBiotCoefficientType = RimGeoMechCase::BiotCoefficientType::BIOT_NONE;
CAF_PDM_InitField( &m_biotCoefficientType, "BiotCoefficientType", defaultBiotCoefficientType, "Biot Coefficient", "", "", "" );
CAF_PDM_InitField( &m_biotFixedCoefficient, "BiotFixedCoefficient", 1.0, "Fixed Coefficient", "", "", "" );
m_biotFixedCoefficient.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_biotResultAddress, "BiotResultAddress", QString( "" ), "Value", "", "", "" );
m_biotResultAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
caf::AppEnum<InitialPermeabilityType> defaultInitialPermeabilityType =
RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED;
CAF_PDM_InitField( &m_initialPermeabilityType,
"InitialPermeabilityType",
defaultInitialPermeabilityType,
"Initial Permeability",
"",
"",
"" );
CAF_PDM_InitField( &m_initialPermeabilityFixed,
"InitialPermeabilityFixed",
1.0,
"Fixed Initial Permeability [mD]",
"",
"",
"" );
m_initialPermeabilityFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_initialPermeabilityResultAddress, "InitialPermeabilityAddress", QString( "" ), "Value", "", "", "" );
m_initialPermeabilityResultAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_permeabilityExponent, "PermeabilityExponent", 1.0, "Permeability Exponent", "", "", "" );
m_permeabilityExponent.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_waterDensityShearSlipIndicator, "WaterDensityShearSlipIndicator", 1.03, "Water Density", "", "", "" );
m_waterDensityShearSlipIndicator.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_contourMapCollection, "ContourMaps", "2d Contour Maps", "", "", "" );
m_contourMapCollection = new RimGeoMechContourMapViewCollection;
m_contourMapCollection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_mudWeightWindowParameters,
"MudWeightWindowParameters",
"Mud Weight Window Parameters",
"",
"",
"" );
m_mudWeightWindowParameters = new RimMudWeightWindowParameters;
m_mudWeightWindowParameters.uiCapability()->setUiTreeHidden( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechCase::~RimGeoMechCase( void )
{
geoMechViews.deleteAllChildObjects();
RimProject* project = RimProject::current();
if ( project )
{
if ( project->mainPlotCollection() )
{
RimWellLogPlotCollection* plotCollection = project->mainPlotCollection()->wellLogPlotCollection();
if ( plotCollection )
{
plotCollection->removeExtractors( this->geoMechData() );
}
}
}
if ( this->geoMechData() )
{
// At this point, we assume that memory should be released
CVF_ASSERT( this->geoMechData()->refCount() == 1 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigGeoMechCaseData* RimGeoMechCase::geoMechData()
{
return m_geoMechCaseData.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RigGeoMechCaseData* RimGeoMechCase::geoMechData() const
{
return m_geoMechCaseData.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::reloadDataAndUpdate()
{
if ( this->geoMechData() )
{
m_geoMechCaseData = nullptr;
std::string errMsg;
if ( this->openGeoMechCase( &errMsg ) == CASE_OPEN_ERROR )
{
RiaLogging::error( QString::fromStdString( errMsg ) );
}
for ( auto v : geoMechViews() )
{
v->loadDataAndUpdate();
v->setCurrentTimeStep( v->currentTimeStep() );
}
for ( RimGeoMechContourMapView* contourMap : m_contourMapCollection->views() )
{
CVF_ASSERT( contourMap );
contourMap->loadDataAndUpdate();
contourMap->updateGridBoxData();
contourMap->updateAnnotationItems();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechView* RimGeoMechCase::createAndAddReservoirView()
{
RimGeoMechView* gmv = new RimGeoMechView();
gmv->setGeoMechCase( this );
geoMechViews.push_back( gmv );
return gmv;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechView* RimGeoMechCase::createCopyAndAddView( const RimGeoMechView* sourceView )
{
RimGeoMechView* rimGeoMechView = dynamic_cast<RimGeoMechView*>(
sourceView->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) );
CVF_ASSERT( rimGeoMechView );
rimGeoMechView->setGeoMechCase( this );
caf::PdmDocument::updateUiIconStateRecursively( rimGeoMechView );
geoMechViews.push_back( rimGeoMechView );
// Resolve references after reservoir view has been inserted into Rim structures
rimGeoMechView->resolveReferencesRecursively();
rimGeoMechView->initAfterReadRecursively();
return rimGeoMechView;
}
RimGeoMechCase* RimGeoMechCase::createCopy( const QString& newInputFileName )
{
RiaApplication* app = RiaApplication::instance();
RimProject* project = app->project();
RimGeoMechCase* copycase = dynamic_cast<RimGeoMechCase*>(
this->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) );
CVF_ASSERT( copycase );
QFileInfo filenameInfo( newInputFileName );
QString newCaseName = filenameInfo.completeBaseName();
copycase->caseUserDescription.setValue( newCaseName + " (copy of " + caseUserDescription.value() + ")" );
copycase->setGridFileName( newInputFileName );
project->assignCaseIdToCase( copycase );
return copycase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechCase::CaseOpenStatus RimGeoMechCase::openGeoMechCase( std::string* errorMessage )
{
// If read already, return
if ( this->m_geoMechCaseData.notNull() ) return CASE_OPEN_OK;
if ( !caf::Utils::fileExists( m_caseFileName().path() ) )
{
return CASE_OPEN_ERROR;
}
cvf::ref<RigGeoMechCaseData> geoMechCaseData = new RigGeoMechCaseData( m_caseFileName().path().toStdString() );
bool fileOpenSuccess = geoMechCaseData->open( errorMessage );
if ( !fileOpenSuccess )
{
return CASE_OPEN_ERROR;
}
std::vector<std::string> stepNames;
if ( !geoMechCaseData->readTimeSteps( errorMessage, &stepNames ) )
{
return CASE_OPEN_ERROR;
}
std::vector<std::pair<QString, QDateTime>> timeSteps;
for ( const std::string& timeStepStringStdString : stepNames )
{
QString timeStepString = QString::fromStdString( timeStepStringStdString );
timeSteps.push_back( std::make_pair( timeStepString, dateTimeFromTimeStepString( timeStepString ) ) );
}
m_timeStepFilter->setTimeStepsFromFile( timeSteps );
if ( m_applyTimeFilter )
{
m_applyTimeFilter = false; // Clear when we've done this once.
caf::PdmUiPropertyViewDialog propertyDialog( nullptr,
m_timeStepFilter,
"Time Step Filter",
"",
QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
propertyDialog.resize( QSize( 400, 400 ) );
// Push arrow cursor onto the cursor stack so it takes over from the wait cursor.
QApplication::setOverrideCursor( QCursor( Qt::ArrowCursor ) );
int propertyReturnValue = propertyDialog.exec();
// Pop arrow cursor off the cursor stack so that the previous (wait) cursor takes over.
QApplication::restoreOverrideCursor();
if ( propertyReturnValue != QDialog::Accepted )
{
return CASE_OPEN_CANCELLED;
}
m_timeStepFilter->updateFilteredTimeStepsFromUi();
}
// Continue reading the open file
if ( !geoMechCaseData->readFemParts( errorMessage, m_timeStepFilter->filteredTimeSteps() ) )
{
return CASE_OPEN_ERROR;
}
if ( activeFormationNames() )
{
geoMechCaseData->femPartResults()->setActiveFormationNames( activeFormationNames()->formationNamesData() );
}
else
{
geoMechCaseData->femPartResults()->setActiveFormationNames( nullptr );
}
std::vector<QString> fileNames;
for ( const caf::FilePath& fileName : m_elementPropertyFileNames.v() )
{
fileNames.push_back( fileName.path() );
}
geoMechCaseData->femPartResults()->addElementPropertyFiles( fileNames );
geoMechCaseData->femPartResults()->setCalculationParameters( m_cohesion, cvf::Math::toRadians( m_frictionAngleDeg() ) );
geoMechCaseData->femPartResults()->setWaterDensityShearSlipIndicator( m_waterDensityShearSlipIndicator );
m_geoMechCaseData = geoMechCaseData;
m_mudWeightWindowParameters->updateFemPartResults();
return CASE_OPEN_OK;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::updateFilePathsFromProjectPath( const QString& newProjectPath, const QString& oldProjectPath )
{
// No longer in use. Filepaths are now of type caf::FilePath, and updated in RimProject on load.
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<Rim3dView*> RimGeoMechCase::allSpecialViews() const
{
std::vector<Rim3dView*> views;
for ( size_t vIdx = 0; vIdx < geoMechViews.size(); ++vIdx )
{
views.push_back( geoMechViews[vIdx] );
}
for ( RimGeoMechContourMapView* view : m_contourMapCollection->views() )
{
views.push_back( view );
}
return views;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ )
{
std::vector<PdmObjectHandle*> children;
geoMechViews.childObjects( &children );
for ( auto child : children )
uiTreeOrdering.add( child );
if ( !m_2dIntersectionViewCollection->views().empty() )
{
uiTreeOrdering.add( &m_2dIntersectionViewCollection );
}
if ( !m_contourMapCollection->views().empty() )
{
uiTreeOrdering.add( &m_contourMapCollection );
}
uiTreeOrdering.skipRemainingChildren( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechContourMapViewCollection* RimGeoMechCase::contourMapCollection()
{
return m_contourMapCollection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QDateTime> RimGeoMechCase::timeStepDates() const
{
QStringList timeStrings = timeStepStrings();
return RimGeoMechCase::vectorOfValidDateTimesFromTimeStepStrings( timeStrings );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::initAfterRead()
{
RimCase::initAfterRead();
for ( RimGeoMechView* riv : geoMechViews() )
{
CVF_ASSERT( riv );
riv->setGeoMechCase( this );
}
for ( RimGeoMechContourMapView* contourMap : m_contourMapCollection->views() )
{
contourMap->setGeoMechCase( this );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RimGeoMechCase::timeStepStrings() const
{
QStringList stringList;
const RigGeoMechCaseData* rigCaseData = geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() )
{
std::vector<std::string> stepNames = rigCaseData->femPartResults()->filteredStepNames();
for ( size_t i = 0; i < stepNames.size(); i++ )
{
stringList += QString::fromStdString( stepNames[i] );
}
}
return stringList;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechCase::timeStepName( int frameIdx ) const
{
const RigGeoMechCaseData* rigCaseData = geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() )
{
std::vector<std::string> stepNames = rigCaseData->femPartResults()->filteredStepNames();
if ( frameIdx < static_cast<int>( stepNames.size() ) )
{
return QString::fromStdString( stepNames[frameIdx] );
}
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::BoundingBox RimGeoMechCase::reservoirBoundingBox()
{
cvf::BoundingBox boundingBox;
RigGeoMechCaseData* rigCaseData = this->geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() && rigCaseData->femParts()->part( 0 ) )
{
RigFemPart* femPart = rigCaseData->femParts()->part( 0 );
const RigFemPartGrid* femPartGrid = femPart->getOrCreateStructGrid();
RigFemResultAddress porBarAddr( RigFemResultPosEnum::RIG_ELEMENT_NODAL, "POR-Bar", "" );
const std::vector<float>& resultValues = rigCaseData->femPartResults()->resultValues( porBarAddr, 0, 0 );
for ( int i = 0; i < femPart->elementCount(); ++i )
{
size_t resValueIdx = femPart->elementNodeResultIdx( (int)i, 0 );
CVF_ASSERT( resValueIdx < resultValues.size() );
double scalarValue = resultValues[resValueIdx];
bool validPorValue = scalarValue != std::numeric_limits<double>::infinity();
if ( validPorValue )
{
std::array<cvf::Vec3d, 8> hexCorners;
femPartGrid->cellCornerVertices( i, hexCorners.data() );
for ( size_t c = 0; c < 8; ++c )
{
boundingBox.add( hexCorners[c] );
}
}
}
}
return boundingBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::BoundingBox RimGeoMechCase::activeCellsBoundingBox() const
{
return allCellsBoundingBox();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::BoundingBox RimGeoMechCase::allCellsBoundingBox() const
{
if ( m_geoMechCaseData.notNull() && m_geoMechCaseData->femParts() )
{
return m_geoMechCaseData->femParts()->boundingBox();
}
else
{
return cvf::BoundingBox();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::characteristicCellSize() const
{
if ( geoMechData() && geoMechData()->femParts() )
{
double cellSize = geoMechData()->femParts()->characteristicElementSize();
return cellSize;
}
return 10.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::addElementPropertyFiles( const std::vector<caf::FilePath>& fileNames )
{
std::vector<QString> newFileNames;
for ( const caf::FilePath& newFileNameToPossiblyAdd : fileNames )
{
bool fileAlreadyAdded = false;
for ( const caf::FilePath& existingFileName : m_elementPropertyFileNames() )
{
if ( existingFileName == newFileNameToPossiblyAdd )
{
fileAlreadyAdded = true;
break;
}
}
if ( !fileAlreadyAdded )
{
newFileNames.push_back( newFileNameToPossiblyAdd.path() );
m_elementPropertyFileNames.v().push_back( newFileNameToPossiblyAdd );
}
}
this->updateConnectedEditors();
if ( m_geoMechCaseData.notNull() )
{
geoMechData()->femPartResults()->addElementPropertyFiles( newFileNames );
geoMechData()->femPartResults()->deleteAllScalarResults();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::cohesion() const
{
return m_cohesion;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::frictionAngleDeg() const
{
return m_frictionAngleDeg;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechCase::BiotCoefficientType RimGeoMechCase::biotCoefficientType() const
{
return m_biotCoefficientType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::biotFixedCoefficient() const
{
return m_biotFixedCoefficient;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechCase::biotResultAddress() const
{
return m_biotResultAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimGeoMechCase::InitialPermeabilityType RimGeoMechCase::initialPermeabilityType() const
{
return m_initialPermeabilityType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::initialPermeabilityFixed() const
{
return m_initialPermeabilityFixed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechCase::initialPermeabilityAddress() const
{
return m_initialPermeabilityResultAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimGeoMechCase::permeabilityExponent() const
{
return m_permeabilityExponent;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::setApplyTimeFilter( bool applyTimeFilter )
{
m_applyTimeFilter = applyTimeFilter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RimGeoMechCase::displayModelOffset() const
{
auto bb = this->allCellsBoundingBox();
if ( bb.isValid() )
{
return this->allCellsBoundingBox().min();
}
return cvf::Vec3d::ZERO;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QDateTime> RimGeoMechCase::vectorOfValidDateTimesFromTimeStepStrings( const QStringList& timeStepStrings )
{
std::vector<QDateTime> dates;
for ( const QString& timeStepString : timeStepStrings )
{
QDateTime dateTime = dateTimeFromTimeStepString( timeStepString );
if ( dateTime.isValid() )
{
dates.push_back( dateTime );
}
}
return dates;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QDateTime RimGeoMechCase::dateTimeFromTimeStepString( const QString& timeStepString )
{
QString dateFormat = "yyyyMMdd";
QString dateStr = subStringOfDigits( timeStepString, dateFormat.size() );
return QDateTime::fromString( dateStr, dateFormat );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_activeFormationNames )
{
updateFormationNamesData();
}
RigGeoMechCaseData* rigCaseData = geoMechData();
if ( changedField == &m_cohesion || changedField == &m_frictionAngleDeg )
{
if ( rigCaseData && rigCaseData->femPartResults() )
{
rigCaseData->femPartResults()->setCalculationParameters( m_cohesion(),
cvf::Math::toRadians( m_frictionAngleDeg() ) );
}
updateConnectedViews();
}
else if ( changedField == &m_biotFixedCoefficient || changedField == &m_biotCoefficientType ||
changedField == &m_biotResultAddress )
{
if ( rigCaseData && rigCaseData->femPartResults() )
{
if ( m_biotCoefficientType() == RimGeoMechCase::BiotCoefficientType::BIOT_NONE )
{
rigCaseData->femPartResults()->setBiotCoefficientParameters( 1.0, "" );
}
else if ( m_biotCoefficientType() == RimGeoMechCase::BiotCoefficientType::BIOT_FIXED )
{
rigCaseData->femPartResults()->setBiotCoefficientParameters( m_biotFixedCoefficient(), "" );
}
else if ( m_biotCoefficientType() == RimGeoMechCase::BiotCoefficientType::BIOT_PER_ELEMENT )
{
if ( changedField == &m_biotCoefficientType )
{
// Show info message to user when selecting "from file" option before
// an element property has been imported
std::vector<std::string> elementProperties = possibleElementPropertyFieldNames();
if ( elementProperties.empty() )
{
QString importMessage =
QString( "Please import biot coefficients from file (typically called alpha.inp) by "
"selecting 'Import Element Property Table' on the Geomechanical Model." );
RiaLogging::info( importMessage );
// Set back to default value
m_biotCoefficientType = RimGeoMechCase::BiotCoefficientType::BIOT_NONE;
return;
}
}
if ( biotResultAddress().isEmpty() )
{
// Automatically select the first available property element if empty
std::vector<std::string> elementProperties = possibleElementPropertyFieldNames();
if ( !elementProperties.empty() )
{
m_biotResultAddress = QString::fromStdString( elementProperties[0] );
}
}
rigCaseData->femPartResults()->setBiotCoefficientParameters( 1.0, biotResultAddress() );
}
}
updateConnectedViews();
}
else if ( changedField == &m_initialPermeabilityFixed || changedField == &m_initialPermeabilityType ||
changedField == &m_initialPermeabilityResultAddress || changedField == &m_permeabilityExponent )
{
if ( rigCaseData && rigCaseData->femPartResults() )
{
if ( m_initialPermeabilityType() == RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED )
{
rigCaseData->femPartResults()->setPermeabilityParameters( initialPermeabilityFixed(),
"",
permeabilityExponent() );
}
else if ( m_initialPermeabilityType() ==
RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_PER_ELEMENT )
{
if ( changedField == &m_initialPermeabilityType )
{
// Show info message to user when selecting "from file" option before
// an element property has been imported
std::vector<std::string> elementProperties = possibleElementPropertyFieldNames();
if ( elementProperties.empty() )
{
QString importMessage =
QString( "Please import initial permeability from file (typically called perm.inp) by "
"selecting 'Import Element Property Table' on the Geomechanical Model." );
RiaLogging::info( importMessage );
// Set back to default value
m_initialPermeabilityType = RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED;
return;
}
}
if ( initialPermeabilityAddress().isEmpty() )
{
// Automatically select the first available property element if empty
std::vector<std::string> elementProperties = possibleElementPropertyFieldNames();
if ( !elementProperties.empty() )
{
m_initialPermeabilityResultAddress = QString::fromStdString( elementProperties[0] );
}
}
rigCaseData->femPartResults()->setPermeabilityParameters( initialPermeabilityFixed(),
initialPermeabilityAddress(),
permeabilityExponent() );
}
}
updateConnectedViews();
}
else if ( changedField == &m_waterDensityShearSlipIndicator )
{
rigCaseData->femPartResults()->setWaterDensityShearSlipIndicator( m_waterDensityShearSlipIndicator );
updateConnectedViews();
}
else if ( changedField == &m_reloadElementPropertyFileCommand )
{
m_reloadElementPropertyFileCommand = false;
reloadSelectedElementPropertyFiles();
if ( rigCaseData && rigCaseData->femPartResults() )
{
rigCaseData->femPartResults()->deleteAllScalarResults();
}
updateConnectedEditors();
updateConnectedViews();
}
else if ( changedField == &m_closeElementPropertyFileCommand )
{
m_closeElementPropertyFileCommand = false;
closeSelectedElementPropertyFiles();
if ( rigCaseData && rigCaseData->femPartResults() )
{
rigCaseData->femPartResults()->deleteAllScalarResults();
}
updateConnectedEditors();
updateConnectedViews();
}
else if ( changedField == &m_importElementPropertyFileCommand )
{
m_importElementPropertyFileCommand = false;
importElementPropertyFile();
if ( rigCaseData && rigCaseData->femPartResults() )
{
rigCaseData->femPartResults()->deleteAllScalarResults();
}
updateConnectedEditors();
updateConnectedViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::updateFormationNamesData()
{
RigGeoMechCaseData* rigCaseData = geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() )
{
if ( activeFormationNames() )
{
rigCaseData->femPartResults()->setActiveFormationNames( activeFormationNames()->formationNamesData() );
}
else
{
rigCaseData->femPartResults()->setActiveFormationNames( nullptr );
}
std::vector<Rim3dView*> views = this->views();
for ( Rim3dView* view : views )
{
RimGeoMechView* geomView = dynamic_cast<RimGeoMechView*>( view );
if ( geomView && geomView->isUsingFormationNames() )
{
if ( !activeFormationNames() )
{
if ( geomView->cellResult()->resultPositionType() == RIG_FORMATION_NAMES )
{
geomView->cellResult()->setResultAddress( RigFemResultAddress( RIG_FORMATION_NAMES, "", "" ) );
geomView->cellResult()->updateConnectedEditors();
}
RimGeoMechPropertyFilterCollection* eclFilColl = geomView->geoMechPropertyFilterCollection();
for ( RimGeoMechPropertyFilter* propFilter : eclFilColl->propertyFilters )
{
if ( propFilter->resultDefinition()->resultPositionType() == RIG_FORMATION_NAMES )
{
propFilter->resultDefinition()->setResultAddress(
RigFemResultAddress( RIG_FORMATION_NAMES, "", "" ) );
}
}
}
RimGeoMechPropertyFilterCollection* eclFilColl = geomView->geoMechPropertyFilterCollection();
for ( RimGeoMechPropertyFilter* propFilter : eclFilColl->propertyFilters )
{
if ( propFilter->resultDefinition->resultPositionType() == RIG_FORMATION_NAMES )
{
propFilter->setToDefaultValues();
propFilter->updateConnectedEditors();
}
}
geomView->cellResult()->updateConnectedEditors();
view->scheduleGeometryRegen( PROPERTY_FILTERED );
view->scheduleCreateDisplayModelAndRedraw();
geomView->intersectionCollection()->scheduleCreateDisplayModelAndRedraw2dIntersectionViews();
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechCase::subStringOfDigits( const QString& inputString, int numberOfDigitsToFind )
{
for ( int j = 0; j < inputString.size(); j++ )
{
if ( inputString.at( j ).isDigit() )
{
QString digitString;
for ( int k = 0; k < numberOfDigitsToFind; k++ )
{
if ( j + k < inputString.size() && inputString.at( j + k ).isDigit() )
{
digitString += inputString.at( j + k );
}
}
if ( digitString.size() == numberOfDigitsToFind )
{
return digitString;
}
}
}
return "";
}
struct descendingComparator
{
template <class T>
bool operator()( T const& a, T const& b ) const
{
return a > b;
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::closeSelectedElementPropertyFiles()
{
std::sort( m_elementPropertyFileNameIndexUiSelection.v().begin(),
m_elementPropertyFileNameIndexUiSelection.v().end(),
descendingComparator() );
std::vector<QString> filesToClose;
for ( size_t idx : m_elementPropertyFileNameIndexUiSelection.v() )
{
filesToClose.push_back( m_elementPropertyFileNames.v().at( idx ).path() );
m_elementPropertyFileNames.v().erase( m_elementPropertyFileNames.v().begin() + idx );
}
m_elementPropertyFileNameIndexUiSelection.v().clear();
std::vector<RigFemResultAddress> addressesToDelete;
if ( m_geoMechCaseData.notNull() )
{
addressesToDelete = geoMechData()->femPartResults()->removeElementPropertyFiles( filesToClose );
geoMechData()->femPartResults()->deleteAllScalarResults();
}
for ( RimGeoMechView* view : geoMechViews() )
{
for ( RigFemResultAddress address : addressesToDelete )
{
if ( address == view->cellResultResultDefinition()->resultAddress() )
{
view->cellResult()->setResultAddress( RigFemResultAddress() );
}
if ( address.fieldName == biotResultAddress().toStdString() )
{
// If the used biot value is being removed we need to change the biot type back to default
m_biotCoefficientType = RimGeoMechCase::BiotCoefficientType::BIOT_NONE;
}
for ( RimGeoMechPropertyFilter* propertyFilter : view->geoMechPropertyFilterCollection()->propertyFilters() )
{
if ( address == propertyFilter->resultDefinition->resultAddress() )
{
propertyFilter->resultDefinition->setResultAddress( RigFemResultAddress() );
}
}
}
view->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::reloadSelectedElementPropertyFiles()
{
std::vector<QString> filesToReload;
for ( size_t idx : m_elementPropertyFileNameIndexUiSelection.v() )
{
filesToReload.push_back( m_elementPropertyFileNames.v().at( idx ).path() );
}
m_elementPropertyFileNameIndexUiSelection.v().clear();
if ( m_geoMechCaseData.notNull() )
{
geoMechData()->femPartResults()->removeElementPropertyFiles( filesToReload );
geoMechData()->femPartResults()->addElementPropertyFiles( filesToReload );
}
for ( RimGeoMechView* view : geoMechViews() )
{
view->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::importElementPropertyFile()
{
RicImportElementPropertyFeature::importElementProperties();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &caseUserDescription );
uiOrdering.add( &caseId );
uiOrdering.add( &m_caseFileName );
caf::PdmUiGroup* caseGroup = uiOrdering.addNewGroup( "Case Options" );
caseGroup->add( &m_activeFormationNames );
caseGroup->add( &m_cohesion );
caseGroup->add( &m_frictionAngleDeg );
caf::PdmUiGroup* elmPropGroup = uiOrdering.addNewGroup( "Element Properties" );
elmPropGroup->add( &m_elementPropertyFileNameIndexUiSelection );
elmPropGroup->add( &m_importElementPropertyFileCommand );
elmPropGroup->add( &m_reloadElementPropertyFileCommand );
elmPropGroup->add( &m_closeElementPropertyFileCommand );
caf::PdmUiGroup* biotGroup = uiOrdering.addNewGroup( "Biot Coefficient" );
biotGroup->add( &m_biotCoefficientType );
biotGroup->add( &m_biotFixedCoefficient );
biotGroup->add( &m_biotResultAddress );
m_biotFixedCoefficient.uiCapability()->setUiHidden( m_biotCoefficientType !=
RimGeoMechCase::BiotCoefficientType::BIOT_FIXED );
m_biotResultAddress.uiCapability()->setUiHidden( m_biotCoefficientType !=
RimGeoMechCase::BiotCoefficientType::BIOT_PER_ELEMENT );
caf::PdmUiGroup* permeabilityGroup = uiOrdering.addNewGroup( "Permeability" );
permeabilityGroup->add( &m_initialPermeabilityType );
permeabilityGroup->add( &m_initialPermeabilityFixed );
permeabilityGroup->add( &m_initialPermeabilityResultAddress );
m_initialPermeabilityFixed.uiCapability()->setUiHidden(
m_initialPermeabilityType != RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_FIXED );
m_initialPermeabilityResultAddress.uiCapability()->setUiHidden(
m_initialPermeabilityType != RimGeoMechCase::InitialPermeabilityType::INITIAL_PERMEABILITY_PER_ELEMENT );
permeabilityGroup->add( &m_permeabilityExponent );
caf::PdmUiGroup* mudWeightWindowGroup = uiOrdering.addNewGroup( "Mud Weight Window" );
m_mudWeightWindowParameters->uiOrdering( uiConfigName, *mudWeightWindowGroup );
caf::PdmUiGroup* shearSlipIndicatorGroup = uiOrdering.addNewGroup( "Shear Slip Indicator" );
shearSlipIndicatorGroup->add( &m_waterDensityShearSlipIndicator );
caf::PdmUiGroup* timeStepFilterGroup = uiOrdering.addNewGroup( "Time Step Filter" );
timeStepFilterGroup->setCollapsedByDefault( true );
m_timeStepFilter->uiOrdering( uiConfigName, *timeStepFilterGroup );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_importElementPropertyFileCommand )
{
dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute )->m_buttonText = "Import Element Property";
}
if ( field == &m_reloadElementPropertyFileCommand )
{
dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute )->m_buttonText = "Reload Element Property";
}
if ( field == &m_closeElementPropertyFileCommand )
{
dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute )->m_buttonText = "Close Element Property";
}
if ( field == &m_biotFixedCoefficient )
{
auto uiDoubleValueEditorAttr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
if ( uiDoubleValueEditorAttr )
{
uiDoubleValueEditorAttr->m_decimals = 2;
uiDoubleValueEditorAttr->m_validator = new QDoubleValidator( 0.0, 1.0, 2 );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimGeoMechCase::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
options = RimCase::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
if ( fieldNeedingOptions == &m_elementPropertyFileNameIndexUiSelection )
{
for ( size_t i = 0; i < m_elementPropertyFileNames.v().size(); i++ )
{
options.push_back( caf::PdmOptionItemInfo( m_elementPropertyFileNames.v().at( i ).path(), (int)i, true ) );
}
}
else if ( fieldNeedingOptions == &m_biotResultAddress || fieldNeedingOptions == &m_initialPermeabilityResultAddress )
{
std::vector<std::string> elementProperties = possibleElementPropertyFieldNames();
std::vector<QString> paths;
for ( auto path : m_elementPropertyFileNames.v() )
{
paths.push_back( path.path() );
}
std::map<std::string, QString> addressesInFile =
geoMechData()->femPartResults()->addressesInElementPropertyFiles( paths );
for ( const std::string& elementProperty : elementProperties )
{
QString result = QString::fromStdString( elementProperty );
QString filename = findFileNameForElementProperty( elementProperty, addressesInFile );
options.push_back( caf::PdmOptionItemInfo( result + " (" + filename + ")", result ) );
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechCase::findFileNameForElementProperty( const std::string& elementProperty,
const std::map<std::string, QString> addressesInFiles ) const
{
auto it = addressesInFiles.find( elementProperty );
if ( it != addressesInFiles.end() )
{
QFileInfo fileInfo( it->second );
return fileInfo.fileName();
}
else
{
return QString( "Unknown file" );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::updateConnectedViews()
{
std::vector<Rim3dView*> views = this->views();
for ( Rim3dView* view : views )
{
if ( view )
{
view->scheduleCreateDisplayModelAndRedraw();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::string> RimGeoMechCase::possibleElementPropertyFieldNames()
{
std::vector<std::string> fieldNames;
if ( geoMechData() )
{
std::map<std::string, std::vector<std::string>> fieldWithComponentNames =
geoMechData()->femPartResults()->scalarFieldAndComponentNames( RIG_ELEMENT );
std::map<std::string, std::vector<std::string>>::const_iterator fieldIt;
for ( fieldIt = fieldWithComponentNames.begin(); fieldIt != fieldWithComponentNames.end(); ++fieldIt )
{
fieldNames.push_back( fieldIt->first );
}
}
return fieldNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::FilePath> RimGeoMechCase::elementPropertyFileNames() const
{
return m_elementPropertyFileNames();
}