Adaption of #8356 Summary Data : Add support for use of summary summary data from Python

This commit is contained in:
Magne Sjaastad 2022-03-26 16:57:46 +01:00
parent a08014e018
commit 7c4e81f59f
14 changed files with 810 additions and 7 deletions

View File

@ -32,6 +32,7 @@
#include "RiaProjectModifier.h"
#include "RiaRegressionTestRunner.h"
#include "RiaSocketServer.h"
#include "RiaSummaryTools.h"
#include "RiaVersionInfo.h"
#include "RiaViewRedrawScheduler.h"
@ -1338,6 +1339,8 @@ void RiaGuiApplication::onProjectBeingSaved()
{
setLastUsedDialogDirectory( "BINARY_GRID", QFileInfo( m_project->fileName() ).absolutePath() );
storeTreeViewState();
RiaSummaryTools::summaryCaseMainCollection()->onProjectBeingSaved();
}
//--------------------------------------------------------------------------------------------------

View File

@ -69,6 +69,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RifWellIAFileWriter.h
${CMAKE_CURRENT_LIST_DIR}/RifEclipseTextFileReader.h
${CMAKE_CURRENT_LIST_DIR}/RifEclipseKeywordContent.h
${CMAKE_CURRENT_LIST_DIR}/RifMultipleSummaryReaders.h
${CMAKE_CURRENT_LIST_DIR}/RifProjectSummaryDataWriter.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -139,6 +141,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RifEclEclipseSummary.cpp
${CMAKE_CURRENT_LIST_DIR}/RifWellIAFileWriter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifEclipseTextFileReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifMultipleSummaryReaders.cpp
${CMAKE_CURRENT_LIST_DIR}/RifProjectSummaryDataWriter.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@ -0,0 +1,121 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifMultipleSummaryReaders.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifMultipleSummaryReaders::RifMultipleSummaryReaders() = default;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifMultipleSummaryReaders::addReader( RifSummaryReaderInterface* reader )
{
for ( auto existingReader : m_readers )
{
if ( existingReader.p() == reader ) return;
}
m_readers.push_back( reader );
rebuildMetaData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifMultipleSummaryReaders::removeReader( RifSummaryReaderInterface* reader )
{
m_readers.erase( reader );
rebuildMetaData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RifMultipleSummaryReaders::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
{
for ( const auto& r : m_readers )
{
if ( r->hasAddress( resultAddress ) ) return r->timeSteps( resultAddress );
}
static std::vector<time_t> empty;
return empty;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifMultipleSummaryReaders::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
{
for ( const auto& r : m_readers )
{
if ( r->hasAddress( resultAddress ) ) return r->values( resultAddress, values );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RifMultipleSummaryReaders::unitName( const RifEclipseSummaryAddress& resultAddress ) const
{
for ( const auto& r : m_readers )
{
if ( r->hasAddress( resultAddress ) ) return r->unitName( resultAddress );
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::EclipseUnitSystem RifMultipleSummaryReaders::unitSystem() const
{
CVF_ASSERT( !m_readers.empty() );
return m_readers.at( 0 )->unitSystem();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifMultipleSummaryReaders::rebuildMetaData()
{
m_allErrorAddresses.clear();
m_allResultAddresses.clear();
for ( const auto& reader : m_readers )
{
{
auto resultAddresses = reader->allResultAddresses();
m_allResultAddresses.insert( resultAddresses.begin(), resultAddresses.end() );
}
{
auto errorResultAddresses = reader->allErrorAddresses();
m_allErrorAddresses.insert( errorResultAddresses.begin(), errorResultAddresses.end() );
}
}
}

View File

@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifSummaryReaderInterface.h"
#include "cvfCollection.h"
#include <list>
//==================================================================================================
///
//==================================================================================================
class RifMultipleSummaryReaders : public RifSummaryReaderInterface
{
public:
RifMultipleSummaryReaders();
void addReader( RifSummaryReaderInterface* reader );
void removeReader( RifSummaryReaderInterface* reader );
const std::vector<time_t>& timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override;
RiaDefines::EclipseUnitSystem unitSystem() const override;
void rebuildMetaData();
private:
cvf::Collection<RifSummaryReaderInterface> m_readers;
};

View File

@ -0,0 +1,220 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifProjectSummaryDataWriter.h"
#include "RifSummaryReaderInterface.h"
#include "opm/common/utility/TimeService.hpp"
#include "opm/io/eclipse/EclOutput.hpp"
#include "opm/io/eclipse/ExtESmry.hpp"
#include "cafAssert.h"
#include <numeric>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifProjectSummaryDataWriter::RifProjectSummaryDataWriter()
: m_timeStepCount( 0 )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifProjectSummaryDataWriter::importFromSourceSummaryReader( const RifSummaryReaderInterface* reader )
{
if ( !reader ) return;
std::string keyword = "TIME";
auto summaryAddress = RifEclipseSummaryAddress::miscAddress( keyword );
if ( reader->hasAddress( summaryAddress ) )
{
auto timeSteps = reader->timeSteps( summaryAddress );
if ( !timeSteps.empty() )
{
Opm::TimeStampUTC ts( timeSteps.front() );
m_startTime = { ts.day(), ts.month(), ts.year(), ts.hour(), ts.minutes(), ts.seconds(), 0 };
}
std::vector<double> values;
reader->values( summaryAddress, &values );
const auto& unitString = reader->unitName( summaryAddress );
m_keywords.push_back( keyword );
m_units.push_back( unitString );
std::vector<float> floatValues;
floatValues.reserve( values.size() );
for ( const auto& v : values )
{
floatValues.push_back( v );
}
m_values.push_back( floatValues );
m_timeStepCount = values.size();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifProjectSummaryDataWriter::importFromProjectSummaryFile( const std::string& projectSummaryFileName )
{
try
{
Opm::EclIO::ExtESmry sourceSummary( projectSummaryFileName );
Opm::TimeStampUTC ts( std::chrono::system_clock::to_time_t( sourceSummary.startdate() ) );
m_startTime = { ts.day(), ts.month(), ts.year(), ts.hour(), ts.minutes(), ts.seconds(), 0 };
auto keywords = sourceSummary.keywordList();
for ( const auto& keyword : keywords )
{
const auto& values = sourceSummary.get( keyword );
const auto& unitString = sourceSummary.get_unit( keyword );
m_keywords.push_back( keyword );
m_units.push_back( unitString );
m_values.push_back( values );
if ( m_timeStepCount == 0 )
{
m_timeStepCount = values.size();
}
}
}
catch ( ... )
{
std::string txt = "Error detected during import of data from " + projectSummaryFileName;
m_errorMessages.push_back( txt );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifProjectSummaryDataWriter::setData( const std::vector<std::string>& keywords,
const std::vector<std::string>& units,
const std::vector<std::vector<float>>& values )
{
if ( keywords.empty() ) return;
CAF_ASSERT( keywords.size() == units.size() );
CAF_ASSERT( keywords.size() == values.size() );
for ( size_t i = 0; i < keywords.size(); i++ )
{
auto existingIndex = indexForKeyword( keywords[i] );
if ( existingIndex == -1 )
{
m_keywords.push_back( keywords[i] );
m_units.push_back( units[i] );
m_values.push_back( values[i] );
}
else
{
// Overwrite existing data
m_keywords[existingIndex] = keywords[i];
m_units[existingIndex] = units[i];
m_values[existingIndex] = values[i];
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifProjectSummaryDataWriter::writeDataToFile( const std::string& fileName )
{
// Reference to other locations writing to ESMRY files
// ESmry::make_esmry_file()
// ExtSmryOutput::write()
try
{
// The ExtESmry reader supports only binary mode, set formatted to false
bool formatted = false;
Opm::EclIO::EclOutput outFile( fileName, formatted, std::ios::out );
outFile.write<int>( "START", m_startTime );
outFile.write( "KEYCHECK", m_keywords );
outFile.write( "UNITS", m_units );
{
// Bool array 1 means RSTEP, 0 means no RSTEP
// Dummy values, but required by the reader
std::vector<int> intValues( m_timeStepCount, 1 );
outFile.write<int>( "RSTEP", intValues );
}
{
// TSTEP represents time steps
// Dummy values, but required by the reader
std::vector<int> intValues;
intValues.resize( m_timeStepCount );
std::iota( intValues.begin(), intValues.end(), 0 );
outFile.write<int>( "TSTEP", intValues );
}
for ( size_t i = 0; i < static_cast<size_t>( m_keywords.size() ); i++ )
{
std::string vect_name = "V" + std::to_string( i );
outFile.write<float>( vect_name, m_values[i] );
}
}
catch ( ... )
{
std::string txt = "Error detected during export of data to " + fileName;
m_errorMessages.push_back( txt );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::string> RifProjectSummaryDataWriter::errorMessages() const
{
return m_errorMessages;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifProjectSummaryDataWriter::clearErrorMessages()
{
m_errorMessages.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifProjectSummaryDataWriter::indexForKeyword( const std::string& keyword ) const
{
for ( int i = 0; i < static_cast<int>( m_keywords.size() ); i++ )
{
if ( m_keywords[i] == keyword ) return i;
}
return -1;
}

View File

@ -0,0 +1,67 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
#include <vector>
class RifEclipseSummaryAddress;
class RifSummaryReaderInterface;
//==================================================================================================
//
//
//==================================================================================================
class RifProjectSummaryDataWriter
{
public:
RifProjectSummaryDataWriter();
// Import start time, time values, and time step count from a source summary case
void importFromSourceSummaryReader( const RifSummaryReaderInterface* reader );
// Import all data from project summary file. This file can than be overwritten using writeDataToFile()
void importFromProjectSummaryFile( const std::string& projectSummaryFileName );
// Set data for a list of keyword/unit/values. If a keyword exist, the data will be overwritten
void setData( const std::vector<std::string>& keywords,
const std::vector<std::string>& units,
const std::vector<std::vector<float>>& values );
void writeDataToFile( const std::string& fileName );
std::vector<std::string> errorMessages() const;
void clearErrorMessages();
private:
int indexForKeyword( const std::string& keyword ) const;
private:
// Structure used to represent start time defined in the following order
// [DAY, MONTH, YEAR, HOUR, MINUTE, SECOND, MILLI_SEC]
std::vector<int> m_startTime;
std::vector<std::string> m_keywords;
std::vector<std::string> m_units;
std::vector<std::vector<float>> m_values;
size_t m_timeStepCount;
std::vector<std::string> m_errorMessages;
};

View File

@ -18,21 +18,29 @@
#include "RimFileSummaryCase.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RicfCommandObject.h"
#include "RifEclipseSummaryTools.h"
#include "RifMultipleSummaryReaders.h"
#include "RifOpmCommonSummary.h"
#include "RifProjectSummaryDataWriter.h"
#include "RifReaderEclipseRft.h"
#include "RifReaderEclipseSummary.h"
#include "RifSummaryReaderMultipleFiles.h"
#include "RimProject.h"
#include "RimTools.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiFilePathEditor.h"
#include <QDir>
#include <QFileInfo>
#include <QUuid>
//==================================================================================================
//
@ -47,9 +55,13 @@ CAF_PDM_SOURCE_INIT( RimFileSummaryCase, "FileSummaryCase" );
RimFileSummaryCase::RimFileSummaryCase()
{
CAF_PDM_InitScriptableObject( "File Summary Case ", ":/SummaryCases16x16.png", "", "A Summary Case based on SMSPEC files" );
CAF_PDM_InitScriptableField( &m_includeRestartFiles, "IncludeRestartFiles", false, "Include Restart Files", "", "", "" );
CAF_PDM_InitScriptableField( &m_includeRestartFiles, "IncludeRestartFiles", false, "Include Restart Files" );
m_includeRestartFiles.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_additionalSummaryFilePath,
"AdditionalSummaryFilePath",
"Additional File Path (set invisible when ready)" );
m_additionalSummaryFilePath.uiCapability()->setUiHidden( true );
}
//--------------------------------------------------------------------------------------------------
@ -91,9 +103,14 @@ void RimFileSummaryCase::updateFilePathsFromProjectPath( const QString& newProje
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::createSummaryReaderInterfaceThreadSafe( RiaThreadSafeLogger* threadSafeLogger )
{
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_fileSummaryReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_includeRestartFiles,
threadSafeLogger );
m_multiSummaryReader = new RifMultipleSummaryReaders;
m_multiSummaryReader->addReader( m_fileSummaryReader.p() );
openAndAttachAdditionalReader();
}
//--------------------------------------------------------------------------------------------------
@ -102,9 +119,13 @@ void RimFileSummaryCase::createSummaryReaderInterfaceThreadSafe( RiaThreadSafeLo
void RimFileSummaryCase::createSummaryReaderInterface()
{
RiaThreadSafeLogger threadSafeLogger;
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_fileSummaryReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_includeRestartFiles,
&threadSafeLogger );
m_multiSummaryReader = new RifMultipleSummaryReaders;
m_multiSummaryReader->addReader( m_fileSummaryReader.p() );
openAndAttachAdditionalReader();
auto messages = threadSafeLogger.messages();
for ( const auto& m : messages )
@ -190,16 +211,52 @@ RifReaderEclipseRft* RimFileSummaryCase::findRftDataAndCreateReader( const QStri
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_additionalSummaryFilePath )
{
caf::PdmUiFilePathEditorAttribute* myAttr = dynamic_cast<caf::PdmUiFilePathEditorAttribute*>( attribute );
if ( myAttr )
{
myAttr->m_selectSaveFileName = true;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::openAndAttachAdditionalReader()
{
QString additionalSummaryFilePath = m_additionalSummaryFilePath().path();
cvf::ref<RifOpmCommonEclipseSummary> opmCommonReader = new RifOpmCommonEclipseSummary;
opmCommonReader->useEnhancedSummaryFiles( true );
bool includeRestartFiles = false;
auto isValid = opmCommonReader->open( additionalSummaryFilePath, includeRestartFiles, nullptr );
if ( isValid )
{
m_multiSummaryReader->addReader( opmCommonReader.p() );
m_additionalSummaryFileReader = opmCommonReader;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryReaderInterface* RimFileSummaryCase::summaryReader()
{
if ( m_summaryFileReader.isNull() )
if ( m_multiSummaryReader.isNull() )
{
createSummaryReaderInterface();
}
return m_summaryFileReader.p();
return m_multiSummaryReader.p();
}
//--------------------------------------------------------------------------------------------------
@ -221,3 +278,136 @@ void RimFileSummaryCase::setIncludeRestartFiles( bool includeRestartFiles )
{
m_includeRestartFiles = includeRestartFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::setSummaryData( const std::string& keyword, const std::string& unit, const std::vector<float>& values )
{
size_t mainSummaryFileValueCount = m_fileSummaryReader->timeSteps( RifEclipseSummaryAddress() ).size();
if ( values.size() != mainSummaryFileValueCount )
{
QString txt = QString( "Wrong size of summary data for keyword %1. Expected %2 values, received %3 values" )
.arg( QString::fromStdString( keyword ) )
.arg( mainSummaryFileValueCount )
.arg( values.size() );
RiaLogging::error( txt );
return;
}
// Remove existing reader to be able to write to the summary file
m_multiSummaryReader->removeReader( m_additionalSummaryFileReader.p() );
m_additionalSummaryFileReader = nullptr;
RifProjectSummaryDataWriter projectSummaryDataWriter;
QString tmpAdditionalSummaryFilePath = m_additionalSummaryFilePath().path();
QFileInfo fi( tmpAdditionalSummaryFilePath );
if ( fi.exists() )
{
projectSummaryDataWriter.importFromProjectSummaryFile( tmpAdditionalSummaryFilePath.toStdString() );
}
else
{
projectSummaryDataWriter.importFromSourceSummaryReader( m_fileSummaryReader.p() );
auto tempFilePath = additionalSummaryDataFilePath();
m_additionalSummaryFilePath = tempFilePath;
tmpAdditionalSummaryFilePath = tempFilePath;
}
projectSummaryDataWriter.setData( { keyword }, { unit }, { values } );
std::string outputFilePath = tmpAdditionalSummaryFilePath.toStdString();
projectSummaryDataWriter.writeDataToFile( outputFilePath );
for ( const auto& txt : projectSummaryDataWriter.errorMessages() )
{
RiaLogging::error( QString::fromStdString( txt ) );
}
projectSummaryDataWriter.clearErrorMessages();
openAndAttachAdditionalReader();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::onProjectBeingSaved()
{
// If additional data is stored in temp folder, copy to project folder and remove file in temp folder
auto existingFilePath = m_additionalSummaryFilePath().path();
if ( QFile::exists( existingFilePath ) )
{
auto currentFilePath = additionalSummaryDataFilePath();
if ( existingFilePath != currentFilePath )
{
if ( QFile::copy( existingFilePath, currentFilePath ) )
{
QFile::remove( existingFilePath );
m_additionalSummaryFilePath = currentFilePath;
openAndAttachAdditionalReader();
}
else
{
QString txt = "Error when copying temporary file to " + currentFilePath;
RiaLogging::error( txt );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFileSummaryCase::createAdditionalSummaryFileName()
{
QUuid uuid = QUuid::createUuid();
QString uuidString = uuid.toString();
uuidString.remove( '{' ).remove( '}' );
auto filePath = "RI_SUMMARY_DATA_" + uuidString + ".ESMRY";
return filePath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFileSummaryCase::additionalSummaryDataFilePath() const
{
QDir storageDir;
RiaApplication* app = RiaApplication::instance();
if ( app->isProjectSavedToDisc() )
{
QString projectFileName = RimProject::current()->fileName();
QFileInfo fileInfo( projectFileName );
storageDir = fileInfo.dir();
}
else
{
// If project is not saved, use the temp folder
storageDir = QDir::temp();
}
QString fileName;
auto cacheSummaryFilePath = m_additionalSummaryFilePath().path();
if ( cacheSummaryFilePath.isEmpty() )
{
fileName = createAdditionalSummaryFileName();
}
else
{
QFileInfo fi( cacheSummaryFilePath );
fileName = fi.fileName();
}
auto filePath = storageDir.absoluteFilePath( fileName );
return filePath;
}

View File

@ -26,6 +26,9 @@ class RifReaderRftInterface;
class RifReaderEclipseRft;
class RifReaderEclipseSummary;
class RiaThreadSafeLogger;
class RifOpmCommonEclipseSummary;
class RifEclipseSummaryAddress;
class RifMultipleSummaryReaders;
//==================================================================================================
//
@ -52,14 +55,31 @@ public:
void setIncludeRestartFiles( bool includeRestartFiles );
void setSummaryData( const std::string& keyword, const std::string& unit, const std::vector<float>& values );
void onProjectBeingSaved();
static RifSummaryReaderInterface* findRelatedFilesAndCreateReader( const QString& headerFileName,
bool includeRestartFiles,
RiaThreadSafeLogger* threadSafeLogger );
static RifReaderEclipseRft* findRftDataAndCreateReader( const QString& headerFileName );
protected:
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
private:
cvf::ref<RifSummaryReaderInterface> m_summaryFileReader;
void openAndAttachAdditionalReader();
QString additionalSummaryDataFilePath() const;
static QString createAdditionalSummaryFileName();
private:
cvf::ref<RifSummaryReaderInterface> m_fileSummaryReader;
cvf::ref<RifMultipleSummaryReaders> m_multiSummaryReader;
cvf::ref<RifReaderEclipseRft> m_summaryEclipseRftReader;
caf::PdmField<bool> m_includeRestartFiles;
caf::PdmField<caf::FilePath> m_additionalSummaryFilePath;
cvf::ref<RifOpmCommonEclipseSummary> m_additionalSummaryFileReader;
};

View File

@ -738,3 +738,19 @@ void RimSummaryCaseMainCollection::updateAutoShortName()
s->updateAutoShortName();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCaseMainCollection::onProjectBeingSaved()
{
auto sumCases = allSummaryCases();
for ( auto s : sumCases )
{
auto fileSumCase = dynamic_cast<RimFileSummaryCase*>( s );
if ( fileSumCase )
{
fileSumCase->onProjectBeingSaved();
}
}
}

View File

@ -73,6 +73,7 @@ public:
void updateFilePathsFromProjectPath( const QString& newProjectPath, const QString& oldProjectPath );
void updateAutoShortName();
void onProjectBeingSaved();
private:
static void loadSummaryCaseData( std::vector<RimSummaryCase*> summaryCases );

View File

@ -22,6 +22,8 @@
#include "RiaSummaryTools.h"
#include "RifSummaryReaderInterface.h"
#include "RimFileSummaryCase.h"
#include "RimSummaryCase.h"
#include "RimcDataContainerDouble.h"
@ -257,3 +259,57 @@ std::unique_ptr<caf::PdmObjectHandle> RimSummaryCase_resampleValues::defaultResu
{
return std::unique_ptr<caf::PdmObjectHandle>( new RimcSummaryResampleData );
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimSummaryCase, RimSummaryCase_setSummaryVectorValues, "setSummaryValues" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase_setSummaryVectorValues::RimSummaryCase_setSummaryVectorValues( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self )
{
CAF_PDM_InitObject( "Set Summary Values" );
CAF_PDM_InitScriptableFieldNoDefault( &m_addressString, "Address", "", "", "", "Formatted address specifying the summary vector" );
CAF_PDM_InitScriptableFieldNoDefault( &m_unitString, "Unit", "", "", "", "Unit" );
CAF_PDM_InitScriptableFieldNoDefault( &m_values, "Values", "", "", "", "Values" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmObjectHandle* RimSummaryCase_setSummaryVectorValues::execute()
{
auto* summaryCase = self<RimSummaryCase>();
auto* fileSummaryCase = dynamic_cast<RimFileSummaryCase*>( summaryCase );
if ( fileSummaryCase )
{
fileSummaryCase->setSummaryData( m_addressString().toStdString(), m_unitString().toStdString(), m_values() );
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCase_setSummaryVectorValues::resultIsPersistent() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<caf::PdmObjectHandle> RimSummaryCase_setSummaryVectorValues::defaultResult() const
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCase_setSummaryVectorValues::isNullptrValidResult() const
{
return true;
}

View File

@ -92,3 +92,24 @@ private:
caf::PdmField<QString> m_addressString;
caf::PdmField<QString> m_resamplingPeriod;
};
//==================================================================================================
///
//==================================================================================================
class RimSummaryCase_setSummaryVectorValues : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryCase_setSummaryVectorValues( caf::PdmObjectHandle* self );
caf::PdmObjectHandle* execute() override;
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
bool isNullptrValidResult() const override;
private:
caf::PdmField<QString> m_addressString;
caf::PdmField<QString> m_unitString;
caf::PdmField<std::vector<float>> m_values;
};

View File

@ -29,3 +29,8 @@ print("\nResampled data")
for t, value in zip(summary_data_sampled.time_steps, summary_data_sampled.values):
print(time.strftime("%a, %d %b %Y ", time.gmtime(t)) + " | " + str(value))
summary_case.set_summary_values("FOPT_M1", "myUnit", summary_data.values)
summary_case.set_summary_values("FOPT_M2", "myUnit", summary_data.values)
summary_case.set_summary_values("FOPT_M3", "myUnit", summary_data.values)
summary_case.set_summary_values("FOPT_M4", "myUnit", summary_data.values)

View File

@ -123,3 +123,35 @@ def test_summary_set_values(rips_instance, initialize_test):
addresses = summary_case.available_addresses()
current_keyword_count = len(addresses.values)
assert current_keyword_count == original_keyword_count + 1
def test_summary_set_values(rips_instance, initialize_test):
casePath = dataroot.PATH + "/flow_diagnostics_test/SIMPLE_SUMMARY2.SMSPEC"
summary_case = rips_instance.project.import_summary_case(casePath)
assert summary_case.id == 1
addresses = summary_case.available_addresses()
original_keyword_count = len(addresses.values)
summary_data = summary_case.summary_vector_values("FOPT")
assert len(summary_data.values) == 60
summary_case.set_summary_values("FOPT_1", "", summary_data.values)
generated_summary_data = summary_case.summary_vector_values("FOPT_1")
assert len(generated_summary_data.values) == 60
addresses = summary_case.available_addresses()
current_keyword_count = len(addresses.values)
assert current_keyword_count == original_keyword_count + 1
# Using existing keyword will overwrite existing data
summary_case.set_summary_values("FOPT_1", "", summary_data.values)
addresses = summary_case.available_addresses()
current_keyword_count = len(addresses.values)
assert current_keyword_count == original_keyword_count + 1
# invalid value count, check that available addresses are unchanged
summary_case.set_summary_values("FOPT_2", "", [])
addresses = summary_case.available_addresses()
current_keyword_count = len(addresses.values)
assert current_keyword_count == original_keyword_count + 1