///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2020- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimWbsParameters.h" #include "RicfCommandObject.h" #include "RigFemPartResultsCollection.h" #include "RigGeoMechCaseData.h" #include "RimGeoMechCase.h" #include "RimWellLogFile.h" #include "RimWellPath.h" #include "cafPdmFieldScriptingCapability.h" CAF_PDM_SOURCE_INIT( RimWbsParameters, "WbsParameters" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWbsParameters::RimWbsParameters() { CAF_PDM_InitScriptableObject( "Well Bore Stability Parameters", ":/WellLogPlot16x16.png" ); CAF_PDM_InitScriptableFieldNoDefault( &m_porePressureSource, "PorePressureReservoirSource", "Reservoir Pore Pressure", "", "Data source for Pore Pressure in reservoir", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_porePressureNonReservoirSource, "PorePressureNonReservoirSource", "Non-Reservoir Pore Pressure", "", "Data source for Non-Reservoir Pore Pressure", "" ); CAF_PDM_InitScriptableField( &m_userDefinedPPShale, "UserPPNonReservoir", 1.0, " Multiplier of hydrostatic PP" ); CAF_PDM_InitScriptableFieldNoDefault( &m_poissonRatioSource, "PoissionRatioSource", "Poisson Ratio", "", "Data source for Poisson Ratio", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_ucsSource, "UcsSource", "Uniaxial Compressive Strength", "", "Data source for UCS", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_OBG0Source, "OBG0Source", "Initial Overburden Gradient", "", "Data source for OBG0", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_DFSource, "DFSource", "Depletion Factor (DF)", "", "Data source for Depletion Factor", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_K0SHSource, "K0SHSource", "K0_SH", "", "SH from Matthews & Kelly = K0_SH * (OBG0-PP0) + PP0 + DF * " "(PP-PP0)\nK0_SH = " "(SH - PP)/(OBG-PP)", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_FGShaleSource, "FGShaleSource", "FG in Shale Calculation" ); CAF_PDM_InitScriptableFieldNoDefault( &m_K0FGSource, "K0FGSource", "K0_FG", "", "FG in shale = K0_FG * (OBG0-PP0)\nK0_FG = (FG-PP)/(OBG-PP)", "" ); CAF_PDM_InitFieldNoDefault( &m_waterDensitySource, "WaterDensitySource", "Water Density" ); m_waterDensitySource.uiCapability()->setUiHidden( true ); CAF_PDM_InitScriptableField( &m_userDefinedPoissionRatio, "UserPoissonRatio", 0.35, "User Defined Poisson Ratio", "", "User Defined Poisson Ratio", "" ); // Typical UCS: http://ceae.colorado.edu/~amadei/CVEN5768/PDF/NOTES8.pdf // Typical UCS for Shale is 5 - 100 MPa -> 50 - 1000 bar. CAF_PDM_InitScriptableField( &m_userDefinedUcs, "UserUcs", 100.0, "User Defined UCS [bar]", "", "User Defined UCS [bar]", "" ); CAF_PDM_InitScriptableField( &m_userDefinedDF, "UserDF", 0.7, "User Defined DF", "", "User Defined Depletion Factor", "" ); CAF_PDM_InitScriptableField( &m_userDefinedK0FG, "UserK0FG", 0.75, "User Defined K0_FG" ); CAF_PDM_InitScriptableField( &m_userDefinedK0SH, "UserK0SH", 0.65, "User Defined K0_SH" ); CAF_PDM_InitScriptableField( &m_FGShaleMultiplier, "FGMultiplier", 1.05, "SH Multiplier for FG in Shale", "", "FG in Shale = Multiplier * SH", "" ); CAF_PDM_InitScriptableField( &m_userDefinedDensity, "WaterDensity", 1.03, "Density of Sea Water [g/cm^3]", "", "Units: g/cm^3", "" ); CAF_PDM_InitFieldNoDefault( &m_geoMechCase, "GeoMechCase", "GeoMechCase" ); m_geoMechCase.uiCapability()->setUiHidden( true ); CAF_PDM_InitFieldNoDefault( &m_wellPath, "WellPath", "WellPath" ); m_wellPath.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_timeStep, "TimeStep", -1, "TimeStep" ); m_timeStep.uiCapability()->setUiHidden( true ); CAF_PDM_InitField( &m_frameIndex, "FrameIndex", -1, "FrameIndex" ); m_frameIndex.uiCapability()->setUiHidden( true ); m_parameterSourceFields = { { RigWbsParameter::PP_Reservoir(), &m_porePressureSource }, { RigWbsParameter::PP_NonReservoir(), &m_porePressureNonReservoirSource }, { RigWbsParameter::poissonRatio(), &m_poissonRatioSource }, { RigWbsParameter::UCS(), &m_ucsSource }, { RigWbsParameter::OBG0(), &m_OBG0Source }, { RigWbsParameter::DF(), &m_DFSource }, { RigWbsParameter::K0_FG(), &m_K0FGSource }, { RigWbsParameter::K0_SH(), &m_K0SHSource }, { RigWbsParameter::FG_Shale(), &m_FGShaleSource }, { RigWbsParameter::waterDensity(), &m_waterDensitySource } }; m_userDefinedValueFields = { { RigWbsParameter::PP_NonReservoir(), &m_userDefinedPPShale }, { RigWbsParameter::poissonRatio(), &m_userDefinedPoissionRatio }, { RigWbsParameter::UCS(), &m_userDefinedUcs }, { RigWbsParameter::DF(), &m_userDefinedDF }, { RigWbsParameter::K0_FG(), &m_userDefinedK0FG }, { RigWbsParameter::K0_SH(), &m_userDefinedK0SH }, { RigWbsParameter::FG_Shale(), &m_FGShaleMultiplier }, { RigWbsParameter::waterDensity(), &m_userDefinedDensity } }; for ( auto parameterFieldPair : m_parameterSourceFields ) { auto sources = parameterFieldPair.first.sources(); if ( !sources.empty() ) { setParameterSource( parameterFieldPair.first, sources.front() ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWbsParameters::RimWbsParameters( const RimWbsParameters& copyFrom ) { *this = copyFrom; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWbsParameters& RimWbsParameters::operator=( const RimWbsParameters& copyFrom ) { m_geoMechCase = copyFrom.m_geoMechCase(); m_wellPath = copyFrom.m_wellPath(); m_timeStep = copyFrom.m_timeStep(); m_frameIndex = copyFrom.m_frameIndex(); for ( auto parameterSourcePair : m_parameterSourceFields ) { auto paramSource = copyFrom.parameterSource( parameterSourcePair.first ); if ( paramSource != RigWbsParameter::UNDEFINED ) { setParameterSource( parameterSourcePair.first, paramSource ); } } for ( auto parameterUserDefinedValuePair : m_userDefinedValueFields ) { setUserDefinedValue( parameterUserDefinedValuePair.first, copyFrom.userDefinedValue( parameterUserDefinedValuePair.first ) ); } return *this; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWbsParameters::~RimWbsParameters() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setGeoMechCase( RimGeoMechCase* geoMechCase ) { m_geoMechCase = geoMechCase; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setWellPath( RimWellPath* wellPath ) { m_wellPath = wellPath; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setTimeStep( int timeStep ) { m_timeStep = timeStep; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setFrameIndex( int frameIndex ) { m_frameIndex = frameIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::applyWbsParametersToExtractor( RigGeoMechWellLogExtractor* extractor ) { for ( auto parameterSourcePair : m_parameterSourceFields ) { extractor->setWbsParametersSource( parameterSourcePair.first, ( *parameterSourcePair.second )() ); } for ( auto parameterUserDefinedValuePair : m_userDefinedValueFields ) { extractor->setWbsUserDefinedValue( parameterUserDefinedValuePair.first, ( *parameterUserDefinedValuePair.second ) ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWbsParameters::ParameterSource RimWbsParameters::parameterSource( const RigWbsParameter& parameter ) const { auto field = sourceField( parameter ); if ( field ) { return ( *field )(); } return RigWbsParameter::UNDEFINED; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimWbsParameters::userDefinedValue( const RigWbsParameter& parameter ) const { auto it = m_userDefinedValueFields.find( parameter ); if ( it != m_userDefinedValueFields.end() ) { return *it->second; } return std::numeric_limits::infinity(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setParameterSource( const RigWbsParameter& parameter, ParameterSource source ) { auto field = sourceField( parameter ); if ( field ) { *field = source; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::setUserDefinedValue( const RigWbsParameter& parameter, double value ) { auto it = m_userDefinedValueFields.find( parameter ); if ( it != m_userDefinedValueFields.end() ) { it->second->setValue( value ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmField* RimWbsParameters::sourceField( const RigWbsParameter& parameter ) const { auto it = m_parameterSourceFields.find( parameter ); if ( it != m_parameterSourceFields.end() ) { return it->second; } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RimWbsParameters::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) { QList options; std::set allParameters = RigWbsParameter::allParameters(); for ( const RigWbsParameter& parameter : allParameters ) { caf::PdmField* field = sourceField( parameter ); if ( field == fieldNeedingOptions ) { std::vector sources = supportedSources( parameter ); for ( int i = 0; i < (int)sources.size(); ++i ) { if ( parameter.exclusiveOptions() || i == (int)sources.size() - 1 || sources[i] == RigWbsParameter::HYDROSTATIC ) { options.push_back( caf::PdmOptionItemInfo( ParameterSourceEnum::uiText( sources[i] ), sources[i] ) ); } else { QStringList cumulativeSourceLabels; for ( int j = i; j < (int)sources.size(); ++j ) { int index = 1 + ( j - i ); cumulativeSourceLabels.push_back( QString( "%1. %2" ).arg( index ).arg( ParameterSourceEnum::uiText( sources[j] ) ) ); } options.push_back( caf::PdmOptionItemInfo( cumulativeSourceLabels.join( ", " ), sources[i] ) ); } } break; } } return options; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::loadDataAndUpdate() { std::set allParameters = RigWbsParameter::allParameters(); for ( const RigWbsParameter& parameter : allParameters ) { caf::PdmField* field = sourceField( parameter ); if ( field ) { assignValidSource( field, supportedSources( parameter ) ); } } this->updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { uiOrdering.add( &m_userDefinedDensity ); uiOrdering.add( &m_porePressureSource ); uiOrdering.add( &m_porePressureNonReservoirSource ); if ( m_porePressureNonReservoirSource == RigWbsParameter::HYDROSTATIC ) { uiOrdering.add( &m_userDefinedPPShale ); } uiOrdering.add( &m_poissonRatioSource ); uiOrdering.add( &m_userDefinedPoissionRatio ); uiOrdering.add( &m_ucsSource ); uiOrdering.add( &m_userDefinedUcs ); uiOrdering.add( &m_OBG0Source ); uiOrdering.add( &m_DFSource ); uiOrdering.add( &m_userDefinedDF ); uiOrdering.add( &m_K0SHSource ); uiOrdering.add( &m_userDefinedK0SH ); uiOrdering.add( &m_FGShaleSource ); if ( m_FGShaleSource == RigWbsParameter::PROPORTIONAL_TO_SH ) { uiOrdering.add( &m_FGShaleMultiplier ); } else { uiOrdering.add( &m_K0FGSource ); uiOrdering.add( &m_userDefinedK0FG ); } uiOrdering.skipRemainingFields( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimWbsParameters::hasLasFileWithChannel( const QString& channel ) const { if ( m_wellPath && !RimWellLogFile::findMdAndChannelValuesForWellPath( m_wellPath, channel ).empty() ) { return true; } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimWbsParameters::hasElementPropertyEntry( const RigFemResultAddress& resAddr ) const { RigFemPartResultsCollection* femPartResults = nullptr; if ( m_geoMechCase && m_geoMechCase->geoMechData() && m_timeStep() >= 0 ) { femPartResults = m_geoMechCase->geoMechData()->femPartResults(); if ( femPartResults ) { return !femPartResults->resultValues( resAddr, 0, m_timeStep, m_frameIndex ).empty(); } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimWbsParameters::assignValidSource( caf::PdmField* parameterSourceField, const std::vector& validSources ) { CAF_ASSERT( parameterSourceField ); if ( std::find( validSources.begin(), validSources.end(), ( *parameterSourceField )() ) == validSources.end() ) { *parameterSourceField = validSources.front(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimWbsParameters::supportedSources( const RigWbsParameter& parameter ) const { std::vector sources; std::set sourcesAlreadyAdded; for ( auto source : parameter.sources() ) { if ( sourcesAlreadyAdded.count( source ) ) continue; if ( source == RigWbsParameter::LAS_FILE ) { if ( hasLasFileWithChannel( parameter.addressString( RigWbsParameter::LAS_FILE ) ) ) { sources.push_back( source ); sourcesAlreadyAdded.insert( source ); } } else if ( source == RigWbsParameter::ELEMENT_PROPERTY_TABLE ) { RigFemResultAddress resAddr = parameter.femAddress( RigWbsParameter::ELEMENT_PROPERTY_TABLE ); if ( hasElementPropertyEntry( resAddr ) ) { sources.push_back( source ); sourcesAlreadyAdded.insert( source ); } } else { sources.push_back( source ); sourcesAlreadyAdded.insert( source ); } } return sources; }