From 1eac9f8a1f248cb90453857830eb266ed23a787d Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 13 Jan 2023 15:26:39 +0100 Subject: [PATCH] #9620 Pressure/depth data: add user interface. --- .../Commands/CMakeLists_files.cmake | 2 + .../RicImportPressureDepthDataFeature.cpp | 100 ++++++++ .../RicImportPressureDepthDataFeature.h | 40 ++++ .../FileInterface/CMakeLists_files.cmake | 2 + .../FileInterface/RifDataSourceForRftPlt.cpp | 20 ++ .../FileInterface/RifDataSourceForRftPlt.h | 6 +- .../RifPressureDepthTextFileReader.cpp | 26 ++- .../RifPressureDepthTextFileReader.h | 2 + .../RifReaderPressureDepthData.cpp | 221 ++++++++++++++++++ .../RifReaderPressureDepthData.h | 64 +++++ .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../Flow/RimWellPlotTools.cpp | 80 ++++++- .../ProjectDataModel/Flow/RimWellPlotTools.h | 4 + .../ProjectDataModel/Flow/RimWellRftPlot.cpp | 30 ++- .../RimContextCommandBuilder.cpp | 1 + .../RimObservedDataCollection.cpp | 31 +++ .../RimObservedDataCollection.h | 5 +- .../ProjectDataModel/RimPressureDepthData.cpp | 112 +++++++++ .../ProjectDataModel/RimPressureDepthData.h | 51 ++++ .../WellLog/RimWellLogRftCurve.cpp | 36 +++ .../WellLog/RimWellLogRftCurve.h | 6 + .../RigPressureDepthData.cpp | 40 ++++ .../ReservoirDataModel/RigPressureDepthData.h | 8 + .../RifPressureDepthTextFileReader-Test.cpp | 9 +- 24 files changed, 883 insertions(+), 15 deletions(-) create mode 100644 ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.cpp create mode 100644 ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.h create mode 100644 ApplicationLibCode/FileInterface/RifReaderPressureDepthData.cpp create mode 100644 ApplicationLibCode/FileInterface/RifReaderPressureDepthData.h create mode 100644 ApplicationLibCode/ProjectDataModel/RimPressureDepthData.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimPressureDepthData.h diff --git a/ApplicationLibCode/Commands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CMakeLists_files.cmake index 2d5a7e2c65..72429587e9 100644 --- a/ApplicationLibCode/Commands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CMakeLists_files.cmake @@ -86,6 +86,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicShowDataSourcesForRealization.h ${CMAKE_CURRENT_LIST_DIR}/RicDeleteUncheckedSubItemsFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicRenameSummaryCaseFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicImportPressureDepthDataFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -175,6 +176,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicShowDataSourcesForRealization.cpp ${CMAKE_CURRENT_LIST_DIR}/RicDeleteUncheckedSubItemsFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicRenameSummaryCaseFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicImportPressureDepthDataFeature.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.cpp b/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.cpp new file mode 100644 index 0000000000..266ed41eec --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.cpp @@ -0,0 +1,100 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicImportPressureDepthDataFeature.h" + +#include "RiaApplication.h" +#include "RiaGuiApplication.h" +#include "RiaLogging.h" + +#include "RicImportFormationNamesFeature.h" + +#include "RifReaderFmuRft.h" + +#include "RimFormationNames.h" +#include "RimObservedDataCollection.h" +#include "RimObservedSummaryData.h" +#include "RimOilField.h" +#include "RimPressureDepthData.h" +#include "RimProject.h" + +#include "RiuFileDialogTools.h" +#include "RiuPlotMainWindowTools.h" + +#include "cafPdmObject.h" +#include "cafSelectionManager.h" + +#include +#include +#include + +CAF_CMD_SOURCE_INIT( RicImportPressureDepthDataFeature, "RicImportPressureDepthDataFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportPressureDepthDataFeature::selectPressureDepthDataPathInDialog() +{ + RiaApplication* app = RiaApplication::instance(); + QString defaultDir = app->lastUsedDialogDirectory( "SUMMARY_CASE_DIR" ); + QString filePath = RiuFileDialogTools::getOpenFileName( nullptr, "Import Pressure/Depth Data", defaultDir ); + + RimProject* proj = app->project(); + RimObservedDataCollection* observedDataCollection = + proj->activeOilField() ? proj->activeOilField()->observedDataCollection() : nullptr; + if ( !observedDataCollection ) return; + + const RimPressureDepthData* importedData = observedDataCollection->createAndAddPressureDepthDataFromPath( filePath ); + + if ( importedData != nullptr ) + { + RiuPlotMainWindowTools::showPlotMainWindow(); + RiuPlotMainWindowTools::selectAsCurrentItem( importedData ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicImportPressureDepthDataFeature::isCommandEnabled() +{ + std::vector selectionObservedDataCollection; + caf::SelectionManager::instance()->objectsByType( &selectionObservedDataCollection ); + + std::vector selectionObservedData; + caf::SelectionManager::instance()->objectsByType( &selectionObservedData ); + + return ( !selectionObservedDataCollection.empty() || !selectionObservedData.empty() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportPressureDepthDataFeature::onActionTriggered( bool isChecked ) +{ + selectPressureDepthDataPathInDialog(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicImportPressureDepthDataFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setIcon( QIcon( ":/ObservedDataFile16x16.png" ) ); + actionToSetup->setText( "Import Pressure Depth Data" ); +} diff --git a/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.h b/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.h new file mode 100644 index 0000000000..acb3a74b99 --- /dev/null +++ b/ApplicationLibCode/Commands/RicImportPressureDepthDataFeature.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" +#include "cafPdmField.h" + +//================================================================================================== +// +// +// +//================================================================================================== +class RicImportPressureDepthDataFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +public: + static void selectPressureDepthDataPathInDialog(); + +private: + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake index 0501684119..8d55119700 100644 --- a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake @@ -76,6 +76,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmRft.h ${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.h ${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.h + ${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -153,6 +154,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RifReaderOpmRft.cpp ${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.cpp ${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.cpp b/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.cpp index aa2ebdd264..6b94312ec9 100644 --- a/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.cpp +++ b/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.cpp @@ -23,6 +23,7 @@ #include "RimEclipseCase.h" #include "RimEclipseResultCase.h" #include "RimObservedFmuRftData.h" +#include "RimPressureDepthData.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" #include "RimWellLogFile.h" @@ -100,6 +101,17 @@ RifDataSourceForRftPlt::RifDataSourceForRftPlt( SourceType sourceType, RimObserv m_observedFmuRftData = observedFmuRftData; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifDataSourceForRftPlt::RifDataSourceForRftPlt( SourceType sourceType, RimPressureDepthData* observedFmuRftData ) +{ + CVF_ASSERT( sourceType == SourceType::OBSERVED_FMU_RFT ); + + m_sourceType = sourceType; + m_pressureDepthData = observedFmuRftData; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -170,6 +182,14 @@ RimObservedFmuRftData* RifDataSourceForRftPlt::observedFmuRftData() const return m_observedFmuRftData; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPressureDepthData* RifDataSourceForRftPlt::pressureDepthData() const +{ + return m_pressureDepthData; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.h b/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.h index 344b1a355b..7830bef7d2 100644 --- a/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.h +++ b/ApplicationLibCode/FileInterface/RifDataSourceForRftPlt.h @@ -35,6 +35,7 @@ class RifReaderRftInterface; class RimSummaryCase; class RimSummaryCaseCollection; class RimObservedFmuRftData; +class RimPressureDepthData; //================================================================================================== /// @@ -60,6 +61,7 @@ public: RifDataSourceForRftPlt( SourceType sourceType, RimSummaryCase* summaryCase, RimSummaryCaseCollection* ensemble ); RifDataSourceForRftPlt( SourceType sourceType, RimWellLogFile* wellLogFile = nullptr ); RifDataSourceForRftPlt( SourceType sourceType, RimObservedFmuRftData* observedFmuRftData ); + RifDataSourceForRftPlt( SourceType sourceType, RimPressureDepthData* pressureDepthData ); SourceType sourceType() const; RimEclipseCase* eclCase() const; @@ -68,6 +70,7 @@ public: RimSummaryCase* summaryCase() const; RimWellLogFile* wellLogFile() const; RimObservedFmuRftData* observedFmuRftData() const; + RimPressureDepthData* pressureDepthData() const; static QString sourceTypeUiText( SourceType sourceType ); @@ -81,9 +84,10 @@ private: caf::PdmPointer m_ensemble; caf::PdmPointer m_wellLogFile; caf::PdmPointer m_observedFmuRftData; + caf::PdmPointer m_pressureDepthData; }; bool operator==( const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2 ); QTextStream& operator<<( QTextStream& str, const RifDataSourceForRftPlt& addr ); QTextStream& operator>>( QTextStream& str, RifDataSourceForRftPlt& addr ); -bool operator<( const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2 ); \ No newline at end of file +bool operator<( const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2 ); diff --git a/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.cpp b/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.cpp index b1ac1c2d48..5a60c8f6e8 100644 --- a/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.cpp +++ b/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.cpp @@ -18,6 +18,7 @@ #include "RifPressureDepthTextFileReader.h" +#include "RiaDateStringParser.h" #include "RiaDefines.h" #include "RigPressureDepthData.h" @@ -52,12 +53,15 @@ std::pair, QString> RifPressureDepthTextFileRe { QStringList headerValues = RifFileParseTools::splitLineAndTrim( line, separator ); RigPressureDepthData data; - data.setWellName( headerValues[1] ); + data.setWellName( headerValues[1].replace( "'", "" ) ); items.push_back( data ); } else if ( isDateLine( line ) ) { - // TODO: parse date + if ( std::optional date = parseDateLine( line ) ) + { + items.back().setTimeStep( date.value() ); + } } else if ( isPropertiesLine( line ) || isUnitsLine( line ) || isCommentLine( line ) ) { @@ -135,3 +139,21 @@ std::optional> RifPressureDepthTextFileReader::parseDa return std::make_pair( pressure, depth ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RifPressureDepthTextFileReader::parseDateLine( const QString& line ) +{ + // Expect two data values separated by one space + QStringList values = RifFileParseTools::splitLineAndTrim( line, " " ); + if ( values.size() != 2 ) return {}; + + CAF_ASSERT( values[0] == "DATE" ); + + // Second value is depth + QDateTime dateTime = RiaDateStringParser::parseDateString( values[1], RiaDateStringParser::OrderPreference::DAY_FIRST ); + if ( !dateTime.isValid() ) return {}; + + return dateTime; +} diff --git a/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.h b/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.h index 2173ec6911..030cec4b4c 100644 --- a/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.h +++ b/ApplicationLibCode/FileInterface/RifPressureDepthTextFileReader.h @@ -18,6 +18,7 @@ #pragma once +#include #include #include @@ -42,4 +43,5 @@ private: static bool isUnitsLine( const QString& line ); static std::optional> parseDataLine( const QString& line ); + static std::optional parseDateLine( const QString& line ); }; diff --git a/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.cpp b/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.cpp new file mode 100644 index 0000000000..4fc1441bc3 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.cpp @@ -0,0 +1,221 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- 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 "RifReaderPressureDepthData.h" + +#include "RiaLogging.h" + +#include "RifPressureDepthTextFileReader.h" + +#include "cafAssert.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifReaderPressureDepthData::RifReaderPressureDepthData( const QString& filePath ) + : m_filePath( filePath ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RifReaderPressureDepthData::labels( const RifEclipseRftAddress& rftAddress ) +{ + std::vector formationLabels; + + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + for ( const RigPressureDepthData& pressureDepthData : m_pressureDepthDataItems ) + { + if ( rftAddress.wellName() == pressureDepthData.wellName() && + rftAddress.timeStep().date() == pressureDepthData.timeStep().date() ) + { + formationLabels.push_back( QString( "%1 - Pressure: %2" ) + .arg( pressureDepthData.wellName() ) + .arg( pressureDepthData.timeStep().toString() ) ); + } + } + + return formationLabels; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RifReaderPressureDepthData::eclipseRftAddresses() +{ + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + std::set allAddresses; + for ( const RigPressureDepthData& pressureDepthData : m_pressureDepthDataItems ) + { + const QString& wellName = pressureDepthData.wellName(); + const QDateTime& dateTime = pressureDepthData.timeStep(); + + RifEclipseRftAddress tvdAddress = + RifEclipseRftAddress::createAddress( wellName, dateTime, RifEclipseRftAddress::RftWellLogChannelType::TVD ); + RifEclipseRftAddress pressureAddress = + RifEclipseRftAddress::createAddress( wellName, dateTime, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE ); + allAddresses.insert( tvdAddress ); + allAddresses.insert( pressureAddress ); + } + + return allAddresses; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderPressureDepthData::values( const RifEclipseRftAddress& rftAddress, std::vector* values ) +{ + CAF_ASSERT( values ); + + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + for ( const RigPressureDepthData& pressureDepthData : m_pressureDepthDataItems ) + { + if ( rftAddress.wellName() == pressureDepthData.wellName() && + rftAddress.timeStep().date() == pressureDepthData.timeStep().date() ) + { + switch ( rftAddress.wellLogChannel() ) + { + case RifEclipseRftAddress::RftWellLogChannelType::TVD: + *values = pressureDepthData.tvdmsl(); + break; + case RifEclipseRftAddress::RftWellLogChannelType::PRESSURE: + *values = pressureDepthData.pressure(); + break; + default: + *values = {}; + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RifReaderPressureDepthData::load() +{ + auto [pressureDepthDataItems, errorMsg] = RifPressureDepthTextFileReader::readFile( m_filePath ); + if ( !errorMsg.isEmpty() ) + { + RiaLogging::error( errorMsg ); + } + else + { + m_pressureDepthDataItems = pressureDepthDataItems; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set + RifReaderPressureDepthData::availableTimeSteps( const QString& wellName, + const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName ) +{ + if ( wellLogChannelName == RifEclipseRftAddress::RftWellLogChannelType::TVD || + wellLogChannelName == RifEclipseRftAddress::RftWellLogChannelType::PRESSURE ) + { + return availableTimeSteps( wellName ); + } + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RifReaderPressureDepthData::availableTimeSteps( const QString& wellName ) +{ + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + std::set timeSteps; + for ( const RigPressureDepthData& pressureDepthData : m_pressureDepthDataItems ) + { + if ( wellName == pressureDepthData.wellName() ) + { + timeSteps.insert( pressureDepthData.timeStep() ); + } + } + return timeSteps; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RifReaderPressureDepthData::availableTimeSteps( + const QString& wellName, + const std::set& relevantChannels ) +{ + if ( relevantChannels.count( RifEclipseRftAddress::RftWellLogChannelType::TVD ) || + relevantChannels.count( RifEclipseRftAddress::RftWellLogChannelType::PRESSURE ) ) + { + return availableTimeSteps( wellName ); + } + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set + RifReaderPressureDepthData::availableWellLogChannels( const QString& wellName ) +{ + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + if ( !m_pressureDepthDataItems.empty() ) + { + return { RifEclipseRftAddress::RftWellLogChannelType::TVD, RifEclipseRftAddress::RftWellLogChannelType::PRESSURE }; + } + + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RifReaderPressureDepthData::wellNames() +{ + if ( m_pressureDepthDataItems.empty() ) + { + load(); + } + + std::set wellNames; + for ( const RigPressureDepthData& pressureDepthData : m_pressureDepthDataItems ) + { + wellNames.insert( pressureDepthData.wellName() ); + } + return wellNames; +} diff --git a/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.h b/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.h new file mode 100644 index 0000000000..bc6a3c6b8d --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifReaderPressureDepthData.h @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "RifEclipseRftAddress.h" +#include "RifReaderRftInterface.h" + +#include "RigPressureDepthData.h" + +#include "cvfObject.h" + +#include +#include +#include + +#include +#include + +//================================================================================================== +// +// +//================================================================================================== +class RifReaderPressureDepthData : public RifReaderRftInterface, public cvf::Object +{ +public: + RifReaderPressureDepthData( const QString& filePath ); + ~RifReaderPressureDepthData() override = default; + + std::vector labels( const RifEclipseRftAddress& rftAddress ); + + std::set eclipseRftAddresses() override; + void values( const RifEclipseRftAddress& rftAddress, std::vector* values ) override; + + std::set + availableTimeSteps( const QString& wellName, + const std::set& relevantChannels ) override; + std::set availableTimeSteps( const QString& wellName ) override; + std::set availableTimeSteps( const QString& wellName, + const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName ) override; + + std::set availableWellLogChannels( const QString& wellName ) override; + std::set wellNames() override; + + void load(); + +private: + QString m_filePath; + std::vector m_pressureDepthDataItems; +}; diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index 2afec0e835..66ae1d9476 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -129,6 +129,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimRoffCase.h ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseTools.h ${CMAKE_CURRENT_LIST_DIR}/RimMultipleEclipseResults.h + ${CMAKE_CURRENT_LIST_DIR}/RimPressureDepthData.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -257,6 +258,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimRoffCase.cpp ${CMAKE_CURRENT_LIST_DIR}/RimEclipseCaseTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RimMultipleEclipseResults.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimPressureDepthData.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp index 49de5944cd..8a17561cf4 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.cpp @@ -32,6 +32,7 @@ #include "RimObservedDataCollection.h" #include "RimObservedFmuRftData.h" #include "RimOilField.h" +#include "RimPressureDepthData.h" #include "RimProject.h" #include "RimSummaryCase.h" #include "RimSummaryCaseCollection.h" @@ -486,6 +487,39 @@ std::vector RimWellPlotTools::observedFmuRftData() return {}; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPlotTools::pressureDepthDataForWell( const QString& simWellName ) +{ + std::vector observedDataForWell; + std::vector allObservedData = pressureDepthData(); + for ( RimPressureDepthData* observedData : allObservedData ) + { + if ( observedData->hasWell( simWellName ) ) + { + observedDataForWell.push_back( observedData ); + } + } + return observedDataForWell; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellPlotTools::pressureDepthData() +{ + const RimProject* project = RimProject::current(); + RimObservedDataCollection* observedDataCollection = + project->activeOilField() ? project->activeOilField()->observedDataCollection() : nullptr; + + if ( observedDataCollection ) + { + return observedDataCollection->allPressureDepthData(); + } + return {}; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -588,6 +622,7 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve( const RimWellLogCu RimSummaryCase* rftSummaryCase = rftCurve->summaryCase(); RimSummaryCaseCollection* rftEnsemble = rftCurve->ensemble(); RimObservedFmuRftData* rftFmuData = rftCurve->observedFmuRftData(); + RimPressureDepthData* pressureDepthData = rftCurve->pressureDepthData(); const RifEclipseRftAddress rftAddress = rftCurve->rftAddress(); const QString& wellName = rftAddress.wellName(); @@ -620,6 +655,13 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve( const RimWellLogCu wellName, timeStep ); } + else if ( pressureDepthData != nullptr ) + { + return RiaRftPltCurveDefinition( RifDataSourceForRftPlt( RifDataSourceForRftPlt::OBSERVED_FMU_RFT, + pressureDepthData ), + wellName, + timeStep ); + } } else if ( gridCurve != nullptr ) { @@ -765,6 +807,20 @@ std::set } } } + + RimPressureDepthData* pressureDepthData = addr.pressureDepthData(); + if ( pressureDepthData && pressureDepthData->rftReader() ) + { + std::set timeSteps = + pressureDepthData->rftReader()->availableTimeSteps( wellPathNameOrSimWellName ); + for ( const QDateTime& time : timeSteps ) + { + if ( selectedTimeStepSet.count( time ) ) + { + curveDefs.insert( RiaRftPltCurveDefinition( addr, wellPathNameOrSimWellName, time ) ); + } + } + } } else if ( addr.ensemble() ) { @@ -1082,13 +1138,27 @@ std::map> RimWellPlotTools::calculat { observedTimeStepsWithSources[source.wellLogFile()->date()].insert( source ); } - else if ( source.sourceType() == RifDataSourceForRftPlt::OBSERVED_FMU_RFT && source.observedFmuRftData() ) + else if ( source.sourceType() == RifDataSourceForRftPlt::OBSERVED_FMU_RFT ) { - std::set rftFmuTimes = - source.observedFmuRftData()->rftReader()->availableTimeSteps( wellPathNameOrSimWellName ); - for ( const QDateTime& date : rftFmuTimes ) { - observedTimeStepsWithSources[date].insert( source ); + if ( source.observedFmuRftData() ) + { + std::set rftFmuTimes = + source.observedFmuRftData()->rftReader()->availableTimeSteps( wellPathNameOrSimWellName ); + for ( const QDateTime& date : rftFmuTimes ) + { + observedTimeStepsWithSources[date].insert( source ); + } + } + else if ( source.pressureDepthData() ) + { + std::set rftFmuTimes = + source.pressureDepthData()->rftReader()->availableTimeSteps( wellPathNameOrSimWellName ); + for ( const QDateTime& date : rftFmuTimes ) + { + observedTimeStepsWithSources[date].insert( source ); + } + } } } } diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h index e24c47a46d..6fea52508b 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellPlotTools.h @@ -39,6 +39,7 @@ class RimWellLogCurve; class RimWellLogFileChannel; class RimWellLogPlot; class RimWellPath; +class RimPressureDepthData; class RiuWellRftPlot; class RigEclipseCaseData; class RigEclipseResultAddress; @@ -134,6 +135,9 @@ public: static bool hasFlowData( const RimWellPath* wellPath ); + static std::vector pressureDepthData(); + static std::vector pressureDepthDataForWell( const QString& simWellName ); + private: friend class StaticFieldsInitializer; static const std::set PRESSURE_DATA_NAMES; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp index 197b1dce6b..2a0bf12288 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp @@ -38,6 +38,7 @@ #include "RimEnsembleCurveSetColorManager.h" #include "RimObservedFmuRftData.h" #include "RimOilField.h" +#include "RimPressureDepthData.h" #include "RimProject.h" #include "RimRegularLegendConfig.h" #include "RimSummaryCaseCollection.h" @@ -516,11 +517,18 @@ void RimWellRftPlot::updateCurvesInPlot( const std::setsetErrorBarsVisible( m_showErrorInObservedData ); plotTrack->addCurve( curve ); - auto observedFmuRftData = curveDefToAdd.address().observedFmuRftData(); - curve->setObservedFmuRftData( observedFmuRftData ); + if ( auto observedFmuRftData = curveDefToAdd.address().observedFmuRftData() ) + { + curve->setErrorBarsVisible( m_showErrorInObservedData ); + curve->setObservedFmuRftData( observedFmuRftData ); + } + else if ( auto pressureDepthData = curveDefToAdd.address().pressureDepthData() ) + { + curve->setPressureDepthData( pressureDepthData ); + } + RifEclipseRftAddress address = RifEclipseRftAddress::createAddress( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep(), @@ -851,6 +859,22 @@ QList RimWellRftPlot::calculateValueOptions( const caf:: options.push_back( item ); } } + const std::vector pressureDepthData = + RimWellPlotTools::pressureDepthDataForWell( m_wellPathNameOrSimWellName ); + if ( !pressureDepthData.empty() ) + { + options.push_back( caf::PdmOptionItemInfo::createHeader( RifDataSourceForRftPlt::sourceTypeUiText( + RifDataSourceForRftPlt::OBSERVED_FMU_RFT ), + true ) ); + + for ( const auto& pd : pressureDepthData ) + { + auto addr = RifDataSourceForRftPlt( RifDataSourceForRftPlt::OBSERVED_FMU_RFT, pd ); + auto item = caf::PdmOptionItemInfo( pd->name(), QVariant::fromValue( addr ) ); + item.setLevel( 1 ); + options.push_back( item ); + } + } } else if ( fieldNeedingOptions == &m_selectedTimeSteps ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index 646c9ce5b6..379a83432e 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -1131,6 +1131,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() menuBuilder << "RicImportObservedDataFeature"; menuBuilder << "RicImportObservedFmuDataFeature"; + menuBuilder << "RicImportPressureDepthDataFeature"; menuBuilder << "RicRenameSummaryCaseFeature"; menuBuilder << "RicReloadSummaryCaseFeature"; menuBuilder << "RicReplaceSummaryCaseFeature"; diff --git a/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.cpp index 2839a6523f..5668cf0987 100644 --- a/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.cpp @@ -29,6 +29,7 @@ #include "RimObservedEclipseUserData.h" #include "RimObservedFmuRftData.h" #include "RimObservedSummaryData.h" +#include "RimPressureDepthData.h" #include "RimProject.h" #include "RimSummaryObservedDataFile.h" @@ -53,8 +54,10 @@ RimObservedDataCollection::RimObservedDataCollection() CAF_PDM_InitFieldNoDefault( &m_observedDataArray, "ObservedDataArray", "" ); CAF_PDM_InitFieldNoDefault( &m_observedFmuRftArray, "ObservedFmuRftDataArray", "" ); + CAF_PDM_InitFieldNoDefault( &m_observedPressureDepthArray, "PressureDepthDataArray", "" ); m_observedDataArray.uiCapability()->setUiTreeHidden( true ); m_observedFmuRftArray.uiCapability()->setUiTreeHidden( true ); + m_observedPressureDepthArray.uiCapability()->setUiTreeHidden( true ); } //-------------------------------------------------------------------------------------------------- @@ -64,6 +67,7 @@ RimObservedDataCollection::~RimObservedDataCollection() { m_observedDataArray.deleteChildren(); m_observedFmuRftArray.deleteChildren(); + m_observedPressureDepthArray.deleteChildren(); } //-------------------------------------------------------------------------------------------------- @@ -100,6 +104,14 @@ std::vector RimObservedDataCollection::allObservedFmuRft return m_observedFmuRftArray.children(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimObservedDataCollection::allPressureDepthData() const +{ + return m_observedPressureDepthArray.children(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -249,3 +261,22 @@ RimObservedFmuRftData* RimObservedDataCollection::createAndAddFmuRftDataFromPath return fmuRftData; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPressureDepthData* RimObservedDataCollection::createAndAddPressureDepthDataFromPath( const QString& filePath ) +{ + QString name = QString( "Imported Pressure/Depth Data %1" ).arg( m_observedPressureDepthArray.size() + 1 ); + + RimPressureDepthData* data = new RimPressureDepthData; + data->setFilePath( filePath ); + data->createRftReaderInterface(); + data->setName( name ); + m_observedPressureDepthArray.push_back( data ); + + updateNewObservedDataCreated( data ); + this->updateConnectedEditors(); + + return data; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.h b/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.h index 92f08c2059..969ca0d1da 100644 --- a/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimObservedDataCollection.h @@ -23,7 +23,7 @@ class RimObservedFmuRftData; class RimObservedSummaryData; -class QFile; +class RimPressureDepthData; //-------------------------------------------------------------------------------------------------- /// @@ -44,8 +44,10 @@ public: bool useSavedFieldsValuesInDialog, QString* errorText = nullptr ); RimObservedFmuRftData* createAndAddFmuRftDataFromPath( const QString& directoryPath ); + RimPressureDepthData* createAndAddPressureDepthDataFromPath( const QString& fileName ); std::vector allObservedSummaryData() const; std::vector allObservedFmuRftData() const; + std::vector allPressureDepthData() const; private: bool fileExists( const QString& fileName, QString* errorText = nullptr ); @@ -53,4 +55,5 @@ private: private: caf::PdmChildArrayField m_observedDataArray; caf::PdmChildArrayField m_observedFmuRftArray; + caf::PdmChildArrayField m_observedPressureDepthArray; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.cpp b/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.cpp new file mode 100644 index 0000000000..0f305d923f --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.cpp @@ -0,0 +1,112 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPressureDepthData.h" + +//================================================================================================== +// +// +// +//================================================================================================== +CAF_PDM_SOURCE_INIT( RimPressureDepthData, "ObservedPressureDepthData" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPressureDepthData::RimPressureDepthData() +{ + CAF_PDM_InitObject( "Observed Pressure/Depth Data", ":/ObservedRFTDataFile16x16.png" ); + CAF_PDM_InitFieldNoDefault( &m_filePath, "File", "File" ); + m_filePath.uiCapability()->setUiReadOnly( true ); + + CAF_PDM_InitFieldNoDefault( &m_wells, "Wells", "Wells" ); + m_wells.xmlCapability()->disableIO(); + m_wells.uiCapability()->setUiReadOnly( true ); + m_wells.registerGetMethod( this, &RimPressureDepthData::wells ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPressureDepthData::setFilePath( const QString& path ) +{ + m_filePath = path; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPressureDepthData::createRftReaderInterface() +{ + m_fmuRftReader = new RifReaderPressureDepthData( m_filePath ); + m_fmuRftReader->load(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RifReaderRftInterface* RimPressureDepthData::rftReader() +{ + if ( m_fmuRftReader.isNull() ) + { + createRftReaderInterface(); + } + + return m_fmuRftReader.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimPressureDepthData::hasWell( const QString& wellPathName ) const +{ + std::vector allWells = wells(); + for ( const QString& well : allWells ) + { + if ( well == wellPathName ) + { + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPressureDepthData::wells() const +{ + if ( m_fmuRftReader.p() ) + { + std::set wellNames = const_cast( m_fmuRftReader.p() )->wellNames(); + return std::vector( wellNames.begin(), wellNames.end() ); + } + return std::vector(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimPressureDepthData::labels( const RifEclipseRftAddress& rftAddress ) +{ + if ( m_fmuRftReader.p() ) + { + return const_cast( m_fmuRftReader.p() )->labels( rftAddress ); + } + return {}; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.h b/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.h new file mode 100644 index 0000000000..665ff8aa43 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimPressureDepthData.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2019- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifReaderFmuRft.h" + +#include "RimNamedObject.h" + +#include "RifReaderPressureDepthData.h" + +#include "cafPdmField.h" +#include "cafPdmObject.h" +#include "cafPdmProxyValueField.h" + +class RimPressureDepthData : public RimNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimPressureDepthData(); + + void setFilePath( const QString& path ); + void createRftReaderInterface(); + RifReaderRftInterface* rftReader(); + + bool hasWell( const QString& wellPathName ) const; + std::vector wells() const; + std::vector labels( const RifEclipseRftAddress& rftAddress ); + +private: + cvf::ref m_fmuRftReader; + + caf::PdmField m_filePath; + caf::PdmProxyValueField> m_wells; +}; diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp index a2b17438ce..e5e8f7284c 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp @@ -161,6 +161,9 @@ RimWellLogRftCurve::RimWellLogRftCurve() CAF_PDM_InitFieldNoDefault( &m_observedFmuRftData, "ObservedFmuRftData", "Observed FMU RFT Data" ); m_observedFmuRftData.uiCapability()->setUiTreeChildrenHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_pressureDepthData, "PressureDepthData", "Pressure Depth Data" ); + m_pressureDepthData.uiCapability()->setUiTreeChildrenHidden( true ); + CAF_PDM_InitFieldNoDefault( &m_timeStep, "TimeStep", "Time Step" ); CAF_PDM_InitFieldNoDefault( &m_wellName, "WellName", "Well Name" ); @@ -320,6 +323,22 @@ RimObservedFmuRftData* RimWellLogRftCurve::observedFmuRftData() const return m_observedFmuRftData; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellLogRftCurve::setPressureDepthData( RimPressureDepthData* observedFmuRftData ) +{ + m_pressureDepthData = observedFmuRftData; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPressureDepthData* RimWellLogRftCurve::pressureDepthData() const +{ + return m_pressureDepthData; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -671,6 +690,12 @@ void RimWellLogRftCurve::onLoadDataAndUpdate( bool updateParentPlot ) unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC; perPointLabels = this->perPointLabels(); } + else if ( m_pressureDepthData ) + { + // TODO: Read unit system for pressure data + unitSystem = RiaDefines::EclipseUnitSystem::UNITS_METRIC; + // perPointLabels = this->perPointLabels(); + } else { CVF_ASSERT( false && "Need to have either an eclipse result case, a summary case or an ensemble" ); @@ -1002,6 +1027,11 @@ RifReaderRftInterface* RimWellLogRftCurve::rftReader() const return m_observedFmuRftData()->rftReader(); } + if ( m_pressureDepthData() ) + { + return m_pressureDepthData()->rftReader(); + } + return nullptr; } @@ -1278,6 +1308,12 @@ std::vector RimWellLogRftCurve::measuredDepthValues() return values; } + if ( m_pressureDepthData && !m_ensemble && !m_summaryCase ) + { + // Pressure depth data does not have MD + return {}; + } + std::vector measuredDepthForCells; RigEclipseWellLogExtractor* eclExtractor = extractor(); diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.h b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.h index 13322c4ba4..ff86bca53f 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.h +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.h @@ -18,6 +18,7 @@ #pragma once +#include "RimPressureDepthData.h" #include "RimWellLogCurve.h" #include "RifEclipseRftAddress.h" @@ -38,6 +39,7 @@ class RimObservedFmuRftData; class RimSummaryCase; class RimSummaryCaseCollection; class RimWellPath; +class RimPressureDepthData; //================================================================================================== /// @@ -91,6 +93,9 @@ public: void setObservedFmuRftData( RimObservedFmuRftData* observedFmuRftData ); RimObservedFmuRftData* observedFmuRftData() const; + void setPressureDepthData( RimPressureDepthData* observedFmuRftData ); + RimPressureDepthData* pressureDepthData() const; + void setRftAddress( RifEclipseRftAddress address ); RifEclipseRftAddress rftAddress() const; @@ -149,6 +154,7 @@ private: caf::PdmPtrField m_summaryCase; caf::PdmPtrField m_ensemble; caf::PdmPtrField m_observedFmuRftData; + caf::PdmPtrField m_pressureDepthData; caf::PdmField m_timeStep; caf::PdmField m_wellName; caf::PdmField m_branchIndex; diff --git a/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.cpp b/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.cpp index 2e742246d1..416289e208 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.cpp @@ -48,6 +48,22 @@ QString RigPressureDepthData::wellName() const return m_wellName; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigPressureDepthData::setTimeStep( const QDateTime& timeStep ) +{ + m_timeStep = timeStep; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QDateTime RigPressureDepthData::timeStep() const +{ + return m_timeStep; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -63,3 +79,27 @@ std::vector> RigPressureDepthData::getPressureDepthVal { return m_values; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigPressureDepthData::tvdmsl() const +{ + std::vector vals; + std::transform( std::begin( m_values ), std::end( m_values ), std::back_inserter( vals ), []( auto const& v ) { + return v.second; + } ); + return vals; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigPressureDepthData::pressure() const +{ + std::vector vals; + std::transform( std::begin( m_values ), std::end( m_values ), std::back_inserter( vals ), []( auto const& v ) { + return v.first; + } ); + return vals; +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.h b/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.h index 9916ccc063..f183798c6b 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.h +++ b/ApplicationLibCode/ReservoirDataModel/RigPressureDepthData.h @@ -20,6 +20,7 @@ #include "RiaDefines.h" +#include #include #include @@ -36,10 +37,17 @@ public: void setWellName( const QString& name ); QString wellName() const; + void setTimeStep( const QDateTime& timeStep ); + QDateTime timeStep() const; + void addPressureAtDepth( double pressure, double depth ); std::vector> getPressureDepthValues() const; + std::vector tvdmsl() const; + std::vector pressure() const; + private: QString m_wellName; + QDateTime m_timeStep; std::vector> m_values; }; diff --git a/ApplicationLibCode/UnitTests/RifPressureDepthTextFileReader-Test.cpp b/ApplicationLibCode/UnitTests/RifPressureDepthTextFileReader-Test.cpp index 5787d74b62..8e9e075f11 100644 --- a/ApplicationLibCode/UnitTests/RifPressureDepthTextFileReader-Test.cpp +++ b/ApplicationLibCode/UnitTests/RifPressureDepthTextFileReader-Test.cpp @@ -23,14 +23,17 @@ TEST( RifPressureDepthTextFileReaderTest, LoadFile ) EXPECT_TRUE( errorMessage.isEmpty() ); ASSERT_EQ( 3u, items.size() ); - EXPECT_EQ( "'G-14'", items[0].wellName().toStdString() ); + EXPECT_EQ( "G-14", items[0].wellName().toStdString() ); + EXPECT_EQ( 28, items[0].timeStep().date().day() ); + EXPECT_EQ( 12, items[0].timeStep().date().month() ); + EXPECT_EQ( 1995, items[0].timeStep().date().year() ); std::vector> values0 = items[0].getPressureDepthValues(); EXPECT_EQ( 4u, values0.size() ); double delta = 0.001; EXPECT_NEAR( 418.88, values0[0].first, delta ); EXPECT_NEAR( 2726.91, values0[0].second, delta ); - EXPECT_EQ( "'G-14'", items[1].wellName().toStdString() ); + EXPECT_EQ( "G-14", items[1].wellName().toStdString() ); EXPECT_EQ( 28, items[1].timeStep().date().day() ); EXPECT_EQ( 12, items[1].timeStep().date().month() ); EXPECT_EQ( 1996, items[1].timeStep().date().year() ); @@ -38,7 +41,7 @@ TEST( RifPressureDepthTextFileReaderTest, LoadFile ) EXPECT_NEAR( 418.88, values1[0].first, delta ); EXPECT_NEAR( 2726.91, values1[0].second, delta ); - EXPECT_EQ( "'F-56'", items[2].wellName().toStdString() ); + EXPECT_EQ( "F-56", items[2].wellName().toStdString() ); EXPECT_EQ( 15, items[2].timeStep().date().day() ); EXPECT_EQ( 1, items[2].timeStep().date().month() ); EXPECT_EQ( 2012, items[2].timeStep().date().year() );