///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2018- Equinor ASA // Copyright (C) 2015-2018 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 "RimGeoMechResultDefinition.h" #include "RiaDefines.h" #include "RiaMedianCalculator.h" #include "RifGeoMechReaderInterface.h" #include "RigFemPartCollection.h" #include "RigFemPartGrid.h" #include "RigFemPartResultsCollection.h" #include "RigFemResultAddress.h" #include "RigFormationNames.h" #include "RigGeoMechCaseData.h" #include "RigWbsParameter.h" #include "RigWellPath.h" #include "Rim3dWellLogCurve.h" #include "RimGeoMechCase.h" #include "RimGeoMechCellColors.h" #include "RimGeoMechPropertyFilter.h" #include "RimGeoMechView.h" #include "RimIntersectionCollection.h" #include "RimPlotCurve.h" #include "RimProject.h" #include "RimRegularLegendConfig.h" #include "RimViewLinker.h" #include "RimWellPath.h" #include "cafPdmUiDoubleValueEditor.h" #include "cafPdmUiListEditor.h" #include namespace caf { template <> void caf::AppEnum::setUp() { addItem( RIG_NODAL, "NODAL", "Nodal" ); addItem( RIG_ELEMENT_NODAL, "ELEMENT_NODAL", "Element Nodal" ); addItem( RIG_INTEGRATION_POINT, "INTEGRATION_POINT", "Integration Point" ); addItem( RIG_ELEMENT_NODAL_FACE, "ELEMENT_NODAL_FACE", "Element Nodal On Face" ); addItem( RIG_FORMATION_NAMES, "FORMATION_NAMES", "Formation Names" ); addItem( RIG_ELEMENT, "ELEMENT", "Element" ); addItem( RIG_WELLPATH_DERIVED, "WELLPATH_DERIVED", "Well Path Derived" ); addItem( RIG_DIFFERENTIALS, "DIFFERENTIALS", "Differentials" ); setDefault( RIG_NODAL ); } } // namespace caf CAF_PDM_SOURCE_INIT( RimGeoMechResultDefinition, "GeoMechResultDefinition" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimGeoMechResultDefinition::RimGeoMechResultDefinition( void ) { CAF_PDM_InitObject( "Color Result", ":/CellResult.png", "", "" ); CAF_PDM_InitFieldNoDefault( &m_resultPositionType, "ResultPositionType", "Result Position", "", "", "" ); m_resultPositionType.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_resultFieldName, "ResultFieldName", QString( "" ), "Field Name", "", "", "" ); m_resultFieldName.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_resultComponentName, "ResultComponentName", QString( "" ), "Component", "", "", "" ); m_resultComponentName.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_timeLapseBaseTimestep, "TimeLapseBaseTimeStep", RigFemResultAddress::noTimeLapseValue(), "Base Time Step", "", "", "" ); CAF_PDM_InitField( &m_referenceTimeStep, "ReferenceTimeStep", 0, "Reference Time Step", "", "", "" ); CAF_PDM_InitField( &m_compactionRefLayer, "CompactionRefLayer", 0, "Compaction Ref Layer", "", "", "" ); m_compactionRefLayer.uiCapability()->setUiHidden( true ); CAF_PDM_InitFieldNoDefault( &m_resultPositionTypeUiField, "ResultPositionTypeUi", "Result Position", "", "", "" ); m_resultPositionTypeUiField.xmlCapability()->disableIO(); CAF_PDM_InitField( &m_resultVariableUiField, "ResultVariableUI", QString( "" ), "Value", "", "", "" ); m_resultVariableUiField.xmlCapability()->disableIO(); m_resultVariableUiField.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() ); m_resultVariableUiField.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP ); CAF_PDM_InitField( &m_normalizeByHydrostaticPressure, "NormalizeByHSP", false, "Normalize by Hydrostatic Pressure", "", "", "" ); CAF_PDM_InitField( &m_normalizationAirGap, "NormalizationAirGap", 0.0, "Air Gap", "", "", "" ); m_normalizationAirGap.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() ); CAF_PDM_InitField( &m_compactionRefLayerUiField, "CompactionRefLayerUi", RigFemResultAddress::noCompactionValue(), "Compaction Ref Layer", "", "The compaction is calculated with reference to this layer. Default layer is the topmost " "layer " "with POR", "" ); m_compactionRefLayerUiField.xmlCapability()->disableIO(); // OBSOLETE FIELDS CAF_PDM_InitField( &m_isTimeLapseResult_OBSOLETE, "IsTimeLapseResult", true, "TimeLapseResult", "", "", "" ); m_isTimeLapseResult_OBSOLETE.xmlCapability()->setIOWritable( false ); m_isTimeLapseResult_OBSOLETE.uiCapability()->setUiHidden( true ); m_isChangedByField = false; m_addWellPathDerivedResults = false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimGeoMechResultDefinition::~RimGeoMechResultDefinition( void ) { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_resultPositionTypeUiField ); uiOrdering.add( &m_resultVariableUiField ); QString valueLabel = "Value"; if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() ) { valueLabel += QString( " (%1)" ).arg( diffResultUiName() ); } m_resultVariableUiField.uiCapability()->setUiName( valueLabel ); if ( normalizableResultSelected() ) { caf::PdmUiGroup* normalizationGroup = uiOrdering.addNewGroup( "Result Normalization" ); normalizationGroup->add( &m_normalizeByHydrostaticPressure ); if ( m_normalizeByHydrostaticPressure ) { normalizationGroup->add( &m_normalizationAirGap ); } } if ( m_resultPositionTypeUiField() != RIG_FORMATION_NAMES ) { bool isReferenceCaseDependent = referenceCaseDependentResultSelected(); if ( isReferenceCaseDependent ) { caf::PdmUiGroup* referenceCaseGr = uiOrdering.addNewGroup( "Reference Case" ); referenceCaseGr->add( &m_referenceTimeStep ); } else { caf::PdmUiGroup* timeLapseGr = uiOrdering.addNewGroup( "Difference Options" ); timeLapseGr->add( &m_timeLapseBaseTimestep ); } } if ( m_resultPositionTypeUiField() == RIG_NODAL ) { caf::PdmUiGroup* compactionGroup = uiOrdering.addNewGroup( "Compaction Options" ); compactionGroup->add( &m_compactionRefLayerUiField ); if ( m_compactionRefLayerUiField == RigFemResultAddress::noCompactionValue() ) { if ( m_geomCase && m_geomCase->geoMechData() ) { m_compactionRefLayerUiField = (int)m_geomCase->geoMechData() ->femParts() ->part( 0 ) ->getOrCreateStructGrid() ->reservoirIJKBoundingBox() .first.z(); } } } if ( !m_isChangedByField ) { m_resultPositionTypeUiField = m_resultPositionType; m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); } m_isChangedByField = false; uiOrdering.skipRemainingFields( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RimGeoMechResultDefinition::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly ) { QList options; *useOptionsOnly = true; if ( m_geomCase ) { if ( &m_resultPositionTypeUiField == fieldNeedingOptions ) { std::vector optionItems = { RIG_NODAL, RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT, RIG_ELEMENT_NODAL_FACE, RIG_FORMATION_NAMES, RIG_ELEMENT, RIG_DIFFERENTIALS }; if ( m_addWellPathDerivedResults ) { optionItems.push_back( RIG_WELLPATH_DERIVED ); } for ( RigFemResultPosEnum value : optionItems ) { options.push_back( caf::PdmOptionItemInfo( caf::AppEnum::uiText( value ), QVariant( value ) ) ); } } else if ( &m_resultVariableUiField == fieldNeedingOptions ) { std::map> fieldCompNames = getResultMetaDataForUIFieldSetting(); QStringList uiVarNames; QStringList varNames; getUiAndResultVariableStringList( &uiVarNames, &varNames, fieldCompNames ); for ( int oIdx = 0; oIdx < uiVarNames.size(); ++oIdx ) { options.push_back( caf::PdmOptionItemInfo( uiVarNames[oIdx], varNames[oIdx] ) ); } } else if ( &m_timeLapseBaseTimestep == fieldNeedingOptions ) { std::vector stepNames; if ( m_geomCase->geoMechData() ) { stepNames = m_geomCase->geoMechData()->femPartResults()->filteredStepNames(); } options.push_back( caf::PdmOptionItemInfo( QString( "Disabled" ), RigFemResultAddress::noTimeLapseValue() ) ); for ( size_t stepIdx = 0; stepIdx < stepNames.size(); ++stepIdx ) { options.push_back( caf::PdmOptionItemInfo( QString( "%1 (#%2)" ).arg( QString::fromStdString( stepNames[stepIdx] ) ).arg( stepIdx ), static_cast( stepIdx ) ) ); } } else if ( &m_referenceTimeStep == fieldNeedingOptions ) { std::vector stepNames; if ( m_geomCase->geoMechData() ) { stepNames = m_geomCase->geoMechData()->femPartResults()->filteredStepNames(); } for ( size_t stepIdx = 0; stepIdx < stepNames.size(); ++stepIdx ) { options.push_back( caf::PdmOptionItemInfo( QString( "%1 (#%2)" ).arg( QString::fromStdString( stepNames[stepIdx] ) ).arg( stepIdx ), static_cast( stepIdx ) ) ); } } else if ( &m_compactionRefLayerUiField == fieldNeedingOptions ) { if ( m_geomCase->geoMechData() ) { size_t kCount = m_geomCase->geoMechData()->femParts()->part( 0 )->getOrCreateStructGrid()->gridPointCountK() - 1; for ( size_t layerIdx = 0; layerIdx < kCount; ++layerIdx ) { options.push_back( caf::PdmOptionItemInfo( QString::number( layerIdx + 1 ), (int)layerIdx ) ); } } } } return options; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::setGeoMechCase( RimGeoMechCase* geomCase ) { m_geomCase = geomCase; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimGeoMechCase* RimGeoMechResultDefinition::geoMechCase() const { return m_geomCase; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { m_isChangedByField = true; if ( &m_resultPositionTypeUiField == changedField ) { if ( m_resultPositionTypeUiField() == RIG_WELLPATH_DERIVED || m_resultPositionType() == RIG_FORMATION_NAMES ) { m_timeLapseBaseTimestep = RigFemResultAddress::noTimeLapseValue(); m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( true ); } else { m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( false ); } } if ( &m_resultPositionTypeUiField == changedField || &m_timeLapseBaseTimestep == changedField || &m_referenceTimeStep == changedField ) { std::map> fieldCompNames = getResultMetaDataForUIFieldSetting(); QStringList uiVarNames; QStringList varNames; getUiAndResultVariableStringList( &uiVarNames, &varNames, fieldCompNames ); if ( m_resultPositionTypeUiField() == m_resultPositionType() && varNames.contains( composeFieldCompString( m_resultFieldName(), m_resultComponentName() ) ) ) { m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); } else { m_resultVariableUiField = ""; } if ( &m_referenceTimeStep == changedField ) { m_geomCase->geoMechData()->femPartResults()->setReferenceTimeStep( m_referenceTimeStep() ); } } if ( &m_normalizeByHydrostaticPressure == changedField && m_normalizationAirGap == 0.0 ) { calculateNormalizationAirGapDefault(); if ( m_normalizeByHydrostaticPressure ) { m_geomCase->geoMechData()->femPartResults()->setNormalizationAirGap( m_normalizationAirGap ); } } // Get the possible property filter owner RimGeoMechPropertyFilter* propFilter = dynamic_cast( this->parentField()->ownerObject() ); RimGridView* view = nullptr; this->firstAncestorOrThisOfType( view ); RimPlotCurve* curve = nullptr; this->firstAncestorOrThisOfType( curve ); Rim3dWellLogCurve* rim3dWellLogCurve = nullptr; this->firstAncestorOrThisOfType( rim3dWellLogCurve ); if ( &m_resultVariableUiField == changedField || &m_compactionRefLayerUiField == changedField || &m_timeLapseBaseTimestep == changedField || &m_normalizeByHydrostaticPressure == changedField || &m_normalizationAirGap == changedField || &m_referenceTimeStep == changedField ) { QStringList fieldComponentNames = m_resultVariableUiField().split( QRegExp( "\\s+" ) ); if ( fieldComponentNames.size() > 0 ) { m_resultPositionType = m_resultPositionTypeUiField; if ( m_resultPositionType() == RIG_FORMATION_NAMES ) { // Complete string of selected formation is stored in m_resultFieldName m_resultFieldName = m_resultVariableUiField(); m_resultComponentName = ""; } else { m_resultFieldName = fieldComponentNames[0]; if ( fieldComponentNames.size() > 1 ) { m_resultComponentName = fieldComponentNames[1]; } else { m_resultComponentName = ""; } m_compactionRefLayer = m_compactionRefLayerUiField(); } if ( m_geomCase->geoMechData() && m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( this->resultAddress() ) ) { if ( view ) view->hasUserRequestedAnimation = true; } if ( propFilter ) { propFilter->setToDefaultValues(); if ( view ) view->scheduleGeometryRegen( PROPERTY_FILTERED ); } if ( view ) { view->scheduleCreateDisplayModelAndRedraw(); view->intersectionCollection()->scheduleCreateDisplayModelAndRedraw2dIntersectionViews(); } if ( dynamic_cast( this ) ) { this->updateLegendCategorySettings(); if ( view ) { RimViewLinker* viewLinker = view->assosiatedViewLinker(); if ( viewLinker ) { viewLinker->updateCellResult(); } } } if ( curve ) { curve->loadDataAndUpdate( true ); } if ( rim3dWellLogCurve ) { rim3dWellLogCurve->updateCurveIn3dView(); } } } if ( rim3dWellLogCurve ) { rim3dWellLogCurve->resetMinMaxValues(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::calculateNormalizationAirGapDefault() { RiaMedianCalculator airGapCalc; for ( auto wellPath : RimProject::current()->allWellPaths() ) { if ( wellPath->wellPathGeometry() ) { double airGap = wellPath->wellPathGeometry()->rkbDiff(); if ( airGap > 0.0 ) { airGapCalc.add( airGap ); } } } if ( airGapCalc.valid() ) { m_normalizationAirGap = airGapCalc.median(); } else { m_normalizationAirGap = 0.0; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RimGeoMechResultDefinition::getResultMetaDataForUIFieldSetting() { RimGeoMechCase* gmCase = m_geomCase; std::map> fieldWithComponentNames; if ( gmCase && gmCase->geoMechData() ) { fieldWithComponentNames = gmCase->geoMechData()->femPartResults()->scalarFieldAndComponentNames( m_resultPositionTypeUiField() ); } return fieldWithComponentNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::getUiAndResultVariableStringList( QStringList* uiNames, QStringList* variableNames, const std::map>& fieldCompNames ) { CVF_ASSERT( uiNames && variableNames ); std::map>::const_iterator fieldIt; for ( fieldIt = fieldCompNames.begin(); fieldIt != fieldCompNames.end(); ++fieldIt ) { QString resultFieldName = QString::fromStdString( fieldIt->first ); if ( resultFieldName == "E" || resultFieldName == "S" || resultFieldName == "POR" ) continue; // We will not show the native POR, Stress and Strain QString resultFieldUiName = convertToUiResultFieldName( resultFieldName ); uiNames->push_back( resultFieldUiName ); variableNames->push_back( resultFieldName ); std::vector::const_iterator compIt; for ( compIt = fieldIt->second.begin(); compIt != fieldIt->second.end(); ++compIt ) { QString resultCompName = QString::fromStdString( *compIt ); uiNames->push_back( " " + resultCompName ); variableNames->push_back( composeFieldCompString( resultFieldName, resultCompName ) ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::composeFieldCompString( const QString& resultFieldName, const QString& resultComponentName ) { if ( resultComponentName.isEmpty() ) return resultFieldName; else return resultFieldName + " " + resultComponentName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::initAfterRead() { if ( !m_isTimeLapseResult_OBSOLETE() ) { m_timeLapseBaseTimestep = RigFemResultAddress::noTimeLapseValue(); } if ( m_resultComponentName == "STM" || m_resultComponentName == "SEM" ) m_resultComponentName = "SM"; m_resultPositionTypeUiField = m_resultPositionType; m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); m_compactionRefLayerUiField = m_compactionRefLayer; m_timeLapseBaseTimestep.uiCapability()->setUiReadOnly( resultPositionType() == RIG_WELLPATH_DERIVED ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) { if ( field == &m_normalizationAirGap ) { auto attr = dynamic_cast( attribute ); if ( attr ) { attr->m_decimals = 2; attr->m_validator = new QDoubleValidator( 0.0, std::numeric_limits::max(), 2 ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::loadResult() { if ( m_geomCase && m_geomCase->geoMechData() ) { if ( this->resultAddress().fieldName == RiaResultNames::wbsFGResult().toStdString() || this->resultAddress().fieldName == RiaResultNames::wbsSFGResult().toStdString() ) { RigFemResultAddress stressResAddr( RIG_ELEMENT_NODAL, std::string( "ST" ), "" ); RigFemResultAddress porBarResAddr( RIG_ELEMENT_NODAL, std::string( "POR-Bar" ), "" ); m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( stressResAddr ); m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( porBarResAddr ); } else { m_geomCase->geoMechData()->femPartResults()->assertResultsLoaded( this->resultAddress() ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::setAddWellPathDerivedResults( bool addWellPathDerivedResults ) { m_addWellPathDerivedResults = addWellPathDerivedResults; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemResultAddress RimGeoMechResultDefinition::resultAddress() const { // Convert differentials to their underlying position type if ( resultPositionType() == RIG_DIFFERENTIALS ) { RigFemResultPosEnum resultPositionType = RIG_ELEMENT_NODAL; if ( resultFieldName().toStdString() == "POR-Bar" ) { resultPositionType = RIG_NODAL; } return RigFemResultAddress( resultPositionType, resultFieldName().toStdString(), resultComponentName().toStdString(), m_timeLapseBaseTimestep(), RigFemResultAddress::noCompactionValue() ); } else { RigFemResultAddress address( resultPositionType(), resultFieldName().toStdString(), resultComponentName().toStdString(), m_timeLapseBaseTimestep(), resultFieldName().toStdString() == RigFemPartResultsCollection::FIELD_NAME_COMPACTION ? m_compactionRefLayer() : RigFemResultAddress::noCompactionValue(), m_normalizeByHydrostaticPressure ); if ( !RigFemPartResultsCollection::isNormalizableResult( address ) ) { address.normalizedByHydrostaticPressure = false; } if ( RigFemPartResultsCollection::isReferenceCaseDependentResult( address ) ) { address.timeLapseBaseFrameIdx = RigFemResultAddress::noTimeLapseValue(); } return address; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimGeoMechResultDefinition::observedResults() const { return std::vector( 1, resultAddress() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigFemResultPosEnum RimGeoMechResultDefinition::resultPositionType() const { return m_resultPositionType(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultFieldName() const { return m_resultFieldName(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultComponentName() const { return m_resultComponentName(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::diffResultUiName() const { QString diffResultString; if ( m_geomCase->geoMechData() ) { if ( referenceCaseDependentResultSelected() ) { std::vector stepNames = m_geomCase->geoMechData()->femPartResults()->filteredStepNames(); QString timeStepString = QString::fromStdString( stepNames[m_referenceTimeStep()] ); diffResultString += QString( "Reference Time Step: %1" ).arg( timeStepString ); } else if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() ) { std::vector stepNames = m_geomCase->geoMechData()->femPartResults()->filteredStepNames(); QString timeStepString = QString::fromStdString( stepNames[m_timeLapseBaseTimestep()] ); diffResultString += QString( "Base Time Step: %1" ).arg( timeStepString ); } } return diffResultString; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::diffResultUiShortName() const { QString diffResultString; if ( m_geomCase->geoMechData() ) { if ( referenceCaseDependentResultSelected() ) { diffResultString += QString( "Ref. Time: #%1" ).arg( m_referenceTimeStep() ); } else if ( m_timeLapseBaseTimestep != RigFemResultAddress::noTimeLapseValue() ) { diffResultString += QString( "Base Time: #%1" ).arg( m_timeLapseBaseTimestep() ); } } return diffResultString; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigGeoMechCaseData* RimGeoMechResultDefinition::ownerCaseData() const { return m_geomCase ? m_geomCase->geoMechData() : nullptr; } //-------------------------------------------------------------------------------------------------- /// Is the result probably valid and possible to load //-------------------------------------------------------------------------------------------------- bool RimGeoMechResultDefinition::hasResult() { RigGeoMechCaseData* caseData = ownerCaseData(); if ( caseData ) { RigFemPartResultsCollection* results = caseData->femPartResults(); if ( results ) { return results->assertResultsLoaded( this->resultAddress() ); } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultFieldUiName() const { return convertToUiResultFieldName( m_resultFieldName() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultComponentUiName() const { return m_resultComponentName(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultVariableUiName() const { QString name = resultFieldName(); QString resCompName = resultComponentName(); if ( !resCompName.isEmpty() ) { name += "." + resCompName; } return name; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::resultVariableName() const { if ( m_resultPositionType == RIG_WELLPATH_DERIVED ) { RigWbsParameter param; if ( RigWbsParameter::findParameter( resultFieldName(), ¶m ) ) { QString lasName = param.addressString( RigWbsParameter::LAS_FILE ); if ( !lasName.isEmpty() ) return lasName; } } return resultVariableUiName(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::currentResultUnits() const { if ( this->resultFieldName() == "SE" || this->resultFieldName() == "ST" || this->resultFieldName() == "POR-Bar" || this->resultFieldName() == "SM" || this->resultFieldName() == "SEM" || this->resultFieldName() == "Q" ) { return "Bar"; } else if ( this->resultFieldName() == "MODULUS" ) { return "GPa"; } else if ( this->resultFieldName() == "COMPRESSIBILITY" && ( this->resultComponentName() == "PORE" || this->resultComponentName() == "VERTICAL" ) ) { return "1/GPa"; } else if ( this->resultFieldName() == "PORO-PERM" && this->resultComponentName() == "PERM" ) { return "mD"; } else { for ( auto resultName : RiaResultNames::wbsDerivedResultNames() ) { if ( resultName == this->resultFieldName() ) { return RiaWellLogUnitTools::sg_emwUnitString(); } } } return RiaWellLogUnitTools::noUnitString(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::defaultLasUnits() const { if ( m_resultPositionType == RIG_WELLPATH_DERIVED ) { RigWbsParameter param; if ( RigWbsParameter::findParameter( resultFieldName(), ¶m ) ) { return param.units( RigWbsParameter::LAS_FILE ); } } return currentResultUnits(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimGeoMechResultDefinition::normalizationAirGap() const { return m_normalizationAirGap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::setNormalizationAirGap( double airGap ) { m_normalizationAirGap = airGap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimGeoMechResultDefinition::convertToUiResultFieldName( QString resultFieldName ) { QString newName( resultFieldName ); if ( resultFieldName == "E" ) newName = "NativeAbaqus Strain"; if ( resultFieldName == "S" ) newName = "NativeAbaqus Stress"; if ( resultFieldName == "NE" ) newName = "E"; // Make NE and NS appear as E and SE if ( resultFieldName == "POR-Bar" ) newName = "POR"; // POR-Bar appear as POR if ( resultFieldName == "MODULUS" ) newName = "Young's Modulus"; if ( resultFieldName == "RATIO" ) newName = "Poisson's Ratio"; if ( resultFieldName == "UCS" ) newName = "UCS bar/ 100"; return newName; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimGeoMechResultDefinition::normalizableResultSelected() const { return RigFemPartResultsCollection::isNormalizableResult( this->resultAddress() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimGeoMechResultDefinition::referenceCaseDependentResultSelected() const { return RigFemPartResultsCollection::isReferenceCaseDependentResult( this->resultAddress() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::setResultAddress( const RigFemResultAddress& resultAddress ) { m_resultPositionType = resultAddress.resultPosType; m_resultFieldName = QString::fromStdString( resultAddress.fieldName ); m_resultComponentName = QString::fromStdString( resultAddress.componentName ); m_timeLapseBaseTimestep = resultAddress.timeLapseBaseFrameIdx; m_compactionRefLayer = resultAddress.refKLayerIndex; m_normalizeByHydrostaticPressure = resultAddress.normalizedByHydrostaticPressure; m_resultPositionTypeUiField = m_resultPositionType; m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); m_compactionRefLayerUiField = m_compactionRefLayer; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimGeoMechResultDefinition::updateLegendTextAndRanges( RimRegularLegendConfig* legendConfigToUpdate, const QString& legendHeading, int timeStepIndex ) { if ( !this->ownerCaseData() || !( this->resultAddress().isValid() ) ) { return; } double localMin, localMax; double localPosClosestToZero, localNegClosestToZero; double globalMin, globalMax; double globalPosClosestToZero, globalNegClosestToZero; RigGeoMechCaseData* gmCase = this->ownerCaseData(); CVF_ASSERT( gmCase ); RigFemResultAddress resVarAddress = this->resultAddress(); gmCase->femPartResults()->minMaxScalarValues( resVarAddress, timeStepIndex, &localMin, &localMax ); gmCase->femPartResults()->posNegClosestToZero( resVarAddress, timeStepIndex, &localPosClosestToZero, &localNegClosestToZero ); gmCase->femPartResults()->minMaxScalarValues( resVarAddress, &globalMin, &globalMax ); gmCase->femPartResults()->posNegClosestToZero( resVarAddress, &globalPosClosestToZero, &globalNegClosestToZero ); legendConfigToUpdate->setClosestToZeroValues( globalPosClosestToZero, globalNegClosestToZero, localPosClosestToZero, localNegClosestToZero ); legendConfigToUpdate->setAutomaticRanges( globalMin, globalMax, localMin, localMax ); if ( this->hasCategoryResult() ) { std::vector fnVector = gmCase->femPartResults()->formationNames(); legendConfigToUpdate->setNamedCategories( fnVector ); } QString legendTitle = legendHeading + caf::AppEnum( this->resultPositionType() ).uiText() + "\n" + this->resultFieldUiName(); if ( !this->resultComponentUiName().isEmpty() ) { legendTitle += ", " + this->resultComponentUiName(); } QString unitString = currentResultUnits(); if ( unitString != RiaWellLogUnitTools::noUnitString() ) { legendTitle += QString( " [%1]" ).arg( unitString ); } if ( !this->diffResultUiShortName().isEmpty() ) { legendTitle += QString( "\nTime Diff:\n%1" ).arg( this->diffResultUiShortName() ); } legendConfigToUpdate->setTitle( legendTitle ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimGeoMechResultDefinition::isBiotCoefficientDependent() const { return ( this->resultFieldName() == "COMPRESSIBILITY" || this->resultFieldName() == "PORO-PERM" ); }