///////////////////////////////////////////////////////////////////////////////// // // 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 // 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 #include CAF_PDM_SOURCE_INIT( RimGeoMechCase, "ResInsightGeoMechCase" ); namespace caf { template <> void caf::AppEnum::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::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 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 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 ); m_displayNameOption = RimCaseDisplayNameTools::DisplayName::CUSTOM; m_displayNameOption.uiCapability()->setUiHidden( 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( 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( 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 geoMechCaseData = new RigGeoMechCaseData( m_caseFileName().path().toStdString() ); bool fileOpenSuccess = geoMechCaseData->open( errorMessage ); if ( !fileOpenSuccess ) { return CASE_OPEN_ERROR; } std::vector stepNames; if ( !geoMechCaseData->readTimeSteps( errorMessage, &stepNames ) ) { return CASE_OPEN_ERROR; } std::vector> 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 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 RimGeoMechCase::allSpecialViews() const { std::vector 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 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 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 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 stepNames = rigCaseData->femPartResults()->filteredStepNames(); if ( frameIdx < static_cast( 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& 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::infinity(); if ( validPorValue ) { std::array 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& fileNames ) { std::vector 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 RimGeoMechCase::vectorOfValidDateTimesFromTimeStepStrings( const QStringList& timeStepStrings ) { std::vector 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 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 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 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 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 views = this->views(); for ( Rim3dView* view : views ) { RimGeoMechView* geomView = dynamic_cast( 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 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 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 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 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( attribute )->m_buttonText = "Import Element Property"; } if ( field == &m_reloadElementPropertyFileCommand ) { dynamic_cast( attribute )->m_buttonText = "Reload Element Property"; } if ( field == &m_closeElementPropertyFileCommand ) { dynamic_cast( attribute )->m_buttonText = "Close Element Property"; } if ( field == &m_biotFixedCoefficient ) { auto uiDoubleValueEditorAttr = dynamic_cast( attribute ); if ( uiDoubleValueEditorAttr ) { uiDoubleValueEditorAttr->m_decimals = 2; uiDoubleValueEditorAttr->m_validator = new QDoubleValidator( 0.0, 1.0, 2 ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RimGeoMechCase::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) { QList 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 elementProperties = possibleElementPropertyFieldNames(); std::vector paths; for ( auto path : m_elementPropertyFileNames.v() ) { paths.push_back( path.path() ); } std::map 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 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 views = this->views(); for ( Rim3dView* view : views ) { if ( view ) { view->scheduleCreateDisplayModelAndRedraw(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimGeoMechCase::possibleElementPropertyFieldNames() { std::vector fieldNames; if ( geoMechData() ) { std::map> fieldWithComponentNames = geoMechData()->femPartResults()->scalarFieldAndComponentNames( RIG_ELEMENT ); std::map>::const_iterator fieldIt; for ( fieldIt = fieldWithComponentNames.begin(); fieldIt != fieldWithComponentNames.end(); ++fieldIt ) { fieldNames.push_back( fieldIt->first ); } } return fieldNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimGeoMechCase::elementPropertyFileNames() const { return m_elementPropertyFileNames(); }