mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Adaption of #8356 Summary Data : Add support for use of summary summary data from Python
This commit is contained in:
@@ -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})
|
||||
|
||||
121
ApplicationLibCode/FileInterface/RifMultipleSummaryReaders.cpp
Normal file
121
ApplicationLibCode/FileInterface/RifMultipleSummaryReaders.cpp
Normal 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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
47
ApplicationLibCode/FileInterface/RifMultipleSummaryReaders.h
Normal file
47
ApplicationLibCode/FileInterface/RifMultipleSummaryReaders.h
Normal 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;
|
||||
};
|
||||
220
ApplicationLibCode/FileInterface/RifProjectSummaryDataWriter.cpp
Normal file
220
ApplicationLibCode/FileInterface/RifProjectSummaryDataWriter.cpp
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user