#7512 Support optimized summary reader

This commit is contained in:
Magne Sjaastad 2021-03-25 12:56:09 +01:00 committed by GitHub
parent 53dbb33e86
commit f5547dd551
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 2996 additions and 835 deletions

View File

@ -403,6 +403,33 @@ RiaPreferences::RiaPreferences( void )
m_multiLateralWellPattern.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_guiTheme, "guiTheme", "GUI theme", "", "", "" );
CAF_PDM_InitField( &m_useOptimizedSummaryDataFileReader,
"useOptimizedSummaryDataFileReader",
false,
"Use Optimized Summary Data Reader [BETA]",
"",
"",
"" );
m_useOptimizedSummaryDataFileReader.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
CAF_PDM_InitField( &m_createOptimizedSummaryDataFile,
"createOptimizedSummaryDataFile",
true,
"Create Optimized Summary Data Files [BETA]",
"",
"If not present, create optimized file with extension '*.LODSMRY'",
"" );
m_createOptimizedSummaryDataFile.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
CAF_PDM_InitField( &m_useOptimizedSummaryDataFile,
"useOptimizedSummaryDataFile",
true,
"Use Optimized Summary Data Files [BETA]",
"",
"If not present, read optimized file with extension '*.LODSMRY'",
"" );
m_useOptimizedSummaryDataFile.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
}
//--------------------------------------------------------------------------------------------------
@ -444,14 +471,15 @@ void RiaPreferences::defineEditorAttribute( const caf::PdmFieldHandle* field,
if ( field == &octaveShowHeaderInfoWhenExecutingScripts || field == &autocomputeDepthRelatedProperties ||
field == &loadAndShowSoil || field == &m_useShaders || field == &m_showHud ||
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText ||
field == &m_showTestToolbar || field == &m_includeFractureDebugInfoFile ||
field == &showLasCurveWithoutTvdWarning || field == &holoLensDisableCertificateVerification ||
field == &m_showProjectChangedDialog || field == &m_searchPlotTemplateFoldersRecursively ||
field == &m_showLegendBackground || field == &m_showSummaryTimeAsLongString ||
field == &m_showViewIdInProjectTree || field == &m_useMultipleThreadsWhenLoadingSummaryData ||
field == &m_enableFaultsByDefault || field == &m_showProgressBar || field == &m_openExportedPdfInViewer ||
field == &m_showInfoBox || field == &m_showGridBox || field == &m_useUndoRedo )
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText || field == &m_showTestToolbar ||
field == &m_includeFractureDebugInfoFile || field == &showLasCurveWithoutTvdWarning ||
field == &holoLensDisableCertificateVerification || field == &m_showProjectChangedDialog ||
field == &m_searchPlotTemplateFoldersRecursively || field == &m_showLegendBackground ||
field == &m_showSummaryTimeAsLongString || field == &m_showViewIdInProjectTree ||
field == &m_useMultipleThreadsWhenLoadingSummaryData || field == &m_enableFaultsByDefault ||
field == &m_showProgressBar || field == &m_openExportedPdfInViewer || field == &m_showInfoBox ||
field == &m_showGridBox || field == &m_useUndoRedo || field == &m_useOptimizedSummaryDataFileReader ||
field == &m_createOptimizedSummaryDataFile || field == &m_useOptimizedSummaryDataFile )
{
caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast<caf::PdmUiCheckBoxEditorAttribute*>( attribute );
if ( myAttr )
@ -576,6 +604,18 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
m_pageRightMargin.uiCapability()->setUiName( "Right Margin" + unitLabel );
m_pageTopMargin.uiCapability()->setUiName( "Top Margin" + unitLabel );
m_pageBottomMargin.uiCapability()->setUiName( "Bottom Margin" + unitLabel );
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "[BETA] Optimized Summary Reader" );
group->setCollapsedByDefault( true );
group->add( &m_useOptimizedSummaryDataFileReader );
group->add( &m_createOptimizedSummaryDataFile );
group->add( &m_useOptimizedSummaryDataFile );
m_createOptimizedSummaryDataFile.uiCapability()->setUiReadOnly( !m_useOptimizedSummaryDataFileReader );
m_useOptimizedSummaryDataFile.uiCapability()->setUiReadOnly( !m_useOptimizedSummaryDataFileReader );
}
}
else if ( uiConfigName == RiaPreferences::tabNameScripting() )
@ -1171,6 +1211,30 @@ QString RiaPreferences::octaveExecutable() const
return m_octaveExecutable().trimmed();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferences::useOptimizedSummaryDataReader() const
{
return m_useOptimizedSummaryDataFileReader();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferences::useOptimizedSummaryDataFiles() const
{
return m_useOptimizedSummaryDataFileReader();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferences::createOptimizedSummaryDataFiles() const
{
return m_createOptimizedSummaryDataFile();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -138,6 +138,11 @@ public:
QString pythonExecutable() const;
QString octaveExecutable() const;
// Summary readers
bool useOptimizedSummaryDataReader() const;
bool useOptimizedSummaryDataFiles() const;
bool createOptimizedSummaryDataFiles() const;
public: // Pdm Fields
caf::PdmField<bool> enableGrpcServer;
caf::PdmField<int> defaultGrpcPortNumber;
@ -243,6 +248,11 @@ private:
// Well Path Import
caf::PdmField<QString> m_multiLateralWellPattern;
// Summary data
caf::PdmField<bool> m_useOptimizedSummaryDataFileReader;
caf::PdmField<bool> m_createOptimizedSummaryDataFile;
caf::PdmField<bool> m_useOptimizedSummaryDataFile;
// 3d view
caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType;
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> m_navigationPolicy;

View File

@ -60,6 +60,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.h
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.h
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
@ -125,6 +127,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.cpp
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp

View File

@ -0,0 +1,245 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RifOpmCommonSummary.h"
#include "opm/io/eclipse/ESmry.hpp"
#ifdef USE_OPENMP
#include <omp.h>
#endif
size_t RifOpmCommonEclipseSummary::sm_createdLodFileCount = 0;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifOpmCommonEclipseSummary::RifOpmCommonEclipseSummary()
: m_useLodsmryFiles( false )
, m_createLodsmryFiles( false )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifOpmCommonEclipseSummary::~RifOpmCommonEclipseSummary()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmCommonEclipseSummary::useLodsmaryFiles( bool enable )
{
m_useLodsmryFiles = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmCommonEclipseSummary::createLodsmaryFiles( bool enable )
{
m_createLodsmryFiles = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmCommonEclipseSummary::resetLodCount()
{
sm_createdLodFileCount = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RifOpmCommonEclipseSummary::numberOfLodFilesCreated()
{
return sm_createdLodFileCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifOpmCommonEclipseSummary::open( const QString& headerFileName, bool includeRestartFiles )
{
m_eSmry = std::make_unique<Opm::EclIO::ESmry>( headerFileName.toStdString(), includeRestartFiles, m_useLodsmryFiles );
if ( m_createLodsmryFiles && !includeRestartFiles )
{
// Create the lodsmry file, no-op if already present.
bool hasFileBeenCreated = m_eSmry->make_lodsmry_file();
if ( hasFileBeenCreated )
{
RifOpmCommonEclipseSummary::increaseLodFileCount();
}
}
if ( !m_eSmry ) return false;
buildMetaData();
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RifOpmCommonEclipseSummary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
{
return m_timeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifOpmCommonEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
{
if ( m_eSmry )
{
auto it = m_adrToSummaryNodeIndex.find( resultAddress );
if ( it != m_adrToSummaryNodeIndex.end() )
{
auto index = it->second;
auto node = m_eSmry->summaryNodeList()[index];
auto fileValues = m_eSmry->get( node );
values->insert( values->begin(), fileValues.begin(), fileValues.end() );
}
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RifOpmCommonEclipseSummary::unitName( const RifEclipseSummaryAddress& resultAddress ) const
{
if ( m_eSmry )
{
auto it = m_adrToSummaryNodeIndex.find( resultAddress );
if ( it != m_adrToSummaryNodeIndex.end() )
{
auto index = it->second;
auto node = m_eSmry->summaryNodeList()[index];
return m_eSmry->get_unit( node );
}
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::EclipseUnitSystem RifOpmCommonEclipseSummary::unitSystem() const
{
// TODO: Not implemented
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmCommonEclipseSummary::buildMetaData()
{
if ( m_eSmry )
{
auto dates = m_eSmry->dates();
for ( const auto& d : dates )
{
auto timeAsTimeT = std::chrono::system_clock::to_time_t( d );
m_timeSteps.push_back( timeAsTimeT );
}
auto nodes = m_eSmry->summaryNodeList();
for ( size_t i = 0; i < nodes.size(); i++ )
{
auto summaryNode = nodes[i];
auto eclAdr = createAddressFromSummaryNode( summaryNode, m_eSmry.get() );
if ( eclAdr.isValid() )
{
m_allResultAddresses.insert( eclAdr );
m_adrToSummaryNodeIndex[eclAdr] = i;
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmCommonEclipseSummary::increaseLodFileCount()
{
// This function can be called from a parallel loop, make it thread safe
#pragma omp critical
sm_createdLodFileCount++;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RifOpmCommonEclipseSummary::createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& node,
Opm::EclIO::ESmry* summaryFile )
{
int i = -1;
int j = -1;
int k = -1;
switch ( node.category )
{
case Opm::EclIO::SummaryNode::Category::Aquifer:
return RifEclipseSummaryAddress::aquiferAddress( node.keyword, node.number );
break;
case Opm::EclIO::SummaryNode::Category::Well:
return RifEclipseSummaryAddress::wellAddress( node.keyword, node.wgname );
break;
case Opm::EclIO::SummaryNode::Category::Group:
return RifEclipseSummaryAddress::wellGroupAddress( node.keyword, node.wgname );
break;
case Opm::EclIO::SummaryNode::Category::Field:
return RifEclipseSummaryAddress::fieldAddress( node.keyword );
break;
case Opm::EclIO::SummaryNode::Category::Region:
return RifEclipseSummaryAddress::regionAddress( node.keyword, node.number );
break;
case Opm::EclIO::SummaryNode::Category::Block:
summaryFile->ijk_from_global_index( node.number, i, j, k );
return RifEclipseSummaryAddress::blockAddress( node.keyword, i, j, k );
break;
case Opm::EclIO::SummaryNode::Category::Connection:
summaryFile->ijk_from_global_index( node.number, i, j, k );
return RifEclipseSummaryAddress::wellCompletionAddress( node.keyword, node.wgname, i, j, k );
break;
case Opm::EclIO::SummaryNode::Category::Segment:
return RifEclipseSummaryAddress::wellSegmentAddress( node.keyword, node.wgname, node.number );
break;
case Opm::EclIO::SummaryNode::Category::Miscellaneous:
return RifEclipseSummaryAddress::miscAddress( node.keyword );
break;
default:
break;
}
return RifEclipseSummaryAddress();
}

View File

@ -0,0 +1,85 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaDefines.h"
#include "RifEclipseSummaryAddress.h"
#include "RifSummaryReaderInterface.h"
#include <QString>
#include <QStringList>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace Opm
{
namespace EclIO
{
class ESmry;
struct SummaryNode;
} // namespace EclIO
} // namespace Opm
//==================================================================================================
//
//
//==================================================================================================
class RifOpmCommonEclipseSummary : public RifSummaryReaderInterface
{
public:
RifOpmCommonEclipseSummary();
~RifOpmCommonEclipseSummary();
void useLodsmaryFiles( bool enable );
void createLodsmaryFiles( bool enable );
static void resetLodCount();
static size_t numberOfLodFilesCreated();
bool open( const QString& headerFileName, bool includeRestartFiles );
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;
private:
void buildMetaData();
static void increaseLodFileCount();
static RifEclipseSummaryAddress createAddressFromSummaryNode( const Opm::EclIO::SummaryNode& summaryNode,
Opm::EclIO::ESmry* summaryFile );
private:
std::unique_ptr<Opm::EclIO::ESmry> m_eSmry;
std::vector<std::string> m_eSmryKeywords;
std::map<RifEclipseSummaryAddress, size_t> m_adrToSummaryNodeIndex;
std::vector<time_t> m_timeSteps;
static size_t sm_createdLodFileCount;
bool m_useLodsmryFiles;
bool m_createLodsmryFiles;
};

View File

@ -19,10 +19,13 @@
#include "RifReaderEclipseSummary.h"
#include "RiaFilePathTools.h"
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RiaStdStringTools.h"
#include "RiaStringEncodingTools.h"
#include "RifEclipseSummaryTools.h"
#include "RifOpmCommonSummary.h"
#include "RifReaderEclipseOutput.h"
#include <cassert>
@ -86,7 +89,7 @@ ecl_sum_type* openEclSum( const QString& inHeaderFileName, bool includeRestartFi
QString nativeHeaderFileName = QDir::toNativeSeparators( inHeaderFileName );
RifEclipseSummaryTools::findSummaryFiles( nativeHeaderFileName, &headerFileName, &dataFileNames );
if ( headerFileName.isEmpty() || dataFileNames.size() == 0 ) return nullptr;
if ( headerFileName.isEmpty() || dataFileNames.isEmpty() ) return nullptr;
assert( !headerFileName.isEmpty() );
assert( dataFileNames.size() > 0 );
@ -126,7 +129,7 @@ RifReaderEclipseSummary::RifReaderEclipseSummary()
, m_ecl_SmSpec( nullptr )
, m_unitSystem( RiaDefines::EclipseUnitSystem::UNITS_METRIC )
{
m_valuesCache.reset( new ValuesCache() );
m_valuesCache = std::make_unique<ValuesCache>();
}
//--------------------------------------------------------------------------------------------------
@ -146,6 +149,30 @@ RifReaderEclipseSummary::~RifReaderEclipseSummary()
//--------------------------------------------------------------------------------------------------
bool RifReaderEclipseSummary::open( const QString& headerFileName, bool includeRestartFiles )
{
bool useOpmCommonReader = RiaPreferences::current()->useOptimizedSummaryDataReader();
if ( useOpmCommonReader )
{
bool useLodsmryFiles = RiaPreferences::current()->useOptimizedSummaryDataFiles();
if ( useLodsmryFiles && includeRestartFiles )
{
RiaLogging::error(
"LODSMRY file loading for summary restart files is not supported. Disable one of the options" );
return false;
}
m_opmCommonReader = std::make_unique<RifOpmCommonEclipseSummary>();
m_opmCommonReader->useLodsmaryFiles( RiaPreferences::current()->useOptimizedSummaryDataFiles() );
m_opmCommonReader->createLodsmaryFiles( RiaPreferences::current()->createOptimizedSummaryDataFiles() );
m_opmCommonReader->open( headerFileName, includeRestartFiles );
buildMetaData();
return true;
}
assert( m_ecl_sum == nullptr );
m_ecl_sum = openEclSum( headerFileName, includeRestartFiles );
@ -241,7 +268,7 @@ RifRestartFileInfo RifReaderEclipseSummary::getFileInfo( const QString& headerFi
RifRestartFileInfo fileInfo;
ecl_sum_type* ecl_sum = openEclSum( headerFileName, false );
std::vector<time_t> timeSteps = getTimeSteps( ecl_sum );
if ( timeSteps.size() > 0 )
if ( !timeSteps.empty() )
{
fileInfo.fileName = headerFileName;
fileInfo.startDate = timeSteps.front();
@ -426,22 +453,33 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode( const ecl::smspec_node& ertSu
//--------------------------------------------------------------------------------------------------
bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
{
assert( m_ecl_sum != nullptr );
values->clear();
values->reserve( timeStepCount() );
// assert( m_ecl_sum != nullptr );
const std::vector<double>& cachedValues = m_valuesCache->getValues( resultAddress );
if ( !cachedValues.empty() )
{
values->insert( values->begin(), cachedValues.begin(), cachedValues.end() );
return true;
}
else if ( m_ecl_SmSpec )
if ( m_opmCommonReader )
{
m_opmCommonReader->values( resultAddress, values );
m_valuesCache->insertValues( resultAddress, *values );
return true;
}
if ( m_ecl_SmSpec )
{
if ( m_differenceAddresses.count( resultAddress ) )
{
std::string quantityName = resultAddress.quantityName();
auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) +
const std::string& quantityName = resultAddress.quantityName();
auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) +
historyIdentifier();
RifEclipseSummaryAddress nativeAdrNoHistory = resultAddress;
@ -494,13 +532,18 @@ bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddr
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RifReaderEclipseSummary::timeStepCount() const
size_t RifReaderEclipseSummary::timeStepCount() const
{
if ( m_opmCommonReader )
{
return m_timeSteps.size();
}
assert( m_ecl_sum != nullptr );
if ( m_ecl_SmSpec == nullptr ) return 0;
return ecl_sum_get_data_length( m_ecl_sum );
return static_cast<size_t>( ecl_sum_get_data_length( m_ecl_sum ) );
}
//--------------------------------------------------------------------------------------------------
@ -508,7 +551,7 @@ int RifReaderEclipseSummary::timeStepCount() const
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RifReaderEclipseSummary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
{
assert( m_ecl_sum != nullptr );
// assert( m_ecl_sum != nullptr );
return m_timeSteps;
}
@ -535,6 +578,15 @@ void RifReaderEclipseSummary::buildMetaData()
m_allResultAddresses.clear();
m_resultAddressToErtNodeIdx.clear();
if ( m_opmCommonReader )
{
m_allResultAddresses = m_opmCommonReader->allResultAddresses();
m_allErrorAddresses = m_opmCommonReader->allErrorAddresses();
m_timeSteps = m_opmCommonReader->timeSteps( RifEclipseSummaryAddress() );
return;
}
if ( m_ecl_SmSpec )
{
int varCount = ecl_smspec_num_nodes( m_ecl_SmSpec );
@ -556,7 +608,7 @@ void RifReaderEclipseSummary::buildMetaData()
RifEclipseSummaryAddress adrWithoutHistory;
{
std::string s = adr.quantityName();
const std::string& s = adr.quantityName();
if ( !RiaStdStringTools::endsWith( s, historyIdentifier() ) )
{
RifEclipseSummaryAddress candidate = adr;

View File

@ -31,6 +31,8 @@
#include <string>
#include <vector>
class RifOpmCommonEclipseSummary;
//==================================================================================================
//
//
@ -82,7 +84,7 @@ public:
static const std::string historyIdentifier() { return "H"; }
private:
int timeStepCount() const;
size_t timeStepCount() const;
int indexFromAddress( const RifEclipseSummaryAddress& resultAddress ) const;
void buildMetaData();
RifRestartFileInfo getRestartFile( const QString& headerFileName );
@ -104,6 +106,8 @@ private:
std::set<RifEclipseSummaryAddress> m_differenceAddresses;
std::unique_ptr<RifOpmCommonEclipseSummary> m_opmCommonReader;
//==================================================================================================
//
//==================================================================================================

View File

@ -15,13 +15,15 @@
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimSummaryCaseMainCollection.h"
#include "RiaLogging.h"
#include "RiaSummaryTools.h"
#include "RimSummaryPlotCollection.h"
#include "RifCaseRealizationParametersReader.h"
#include "RifEclipseSummaryTools.h"
#include "RifOpmCommonSummary.h"
#include "RifSummaryCaseRestartSelector.h"
#include "RimCaseDisplayNameTools.h"
@ -35,8 +37,10 @@
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCurve.h"
#include "RimSummaryPlot.h"
#include "RimSummaryPlotCollection.h"
#include "cafProgressInfo.h"
#include <QDir>
CAF_PDM_SOURCE_INIT( RimSummaryCaseMainCollection, "SummaryCaseCollection" );
@ -435,6 +439,8 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vector<RimFileS
caf::ProgressInfo progInfo( fileSummaryCases.size(), "Loading Summary Cases" );
RifOpmCommonEclipseSummary::resetLodCount();
#pragma omp parallel for schedule( dynamic )
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
{
@ -447,6 +453,13 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vector<RimFileS
progInfo.setProgress( cIdx );
}
auto numberOfLodFilesCreated = RifOpmCommonEclipseSummary::numberOfLodFilesCreated();
if ( numberOfLodFilesCreated > 0 )
{
RiaLogging::info( QString( "Optimized Summary Reader : Converted and created %1 '*.LODSMRY' files on disk." )
.arg( numberOfLodFilesCreated ) );
}
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
{
RimFileSummaryCase* fileSummaryCase = fileSummaryCases[cIdx];

View File

@ -74,6 +74,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanXmlReader-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellPathGeometryExporter-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifSummaryDataReader-Test.cpp
)
if (RESINSIGHT_ENABLE_GRPC)

View File

@ -0,0 +1,113 @@
#include "gtest/gtest.h"
//#include "RiaTestDataDirectory.h"
#include "RifOpmCommonSummary.h"
#include "RifReaderEclipseSummary.h"
#include <chrono>
size_t iterationCount = 5;
size_t maxCount = 500;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( DISABLED_RifSummaryDataTest, OpmCommonAllData )
{
QString filename = "e:/models/reek_history_match_large/realization-1/iter-0/eclipse/model/R001_REEK-1.SMSPEC";
for ( size_t iteration = 0; iteration < iterationCount; iteration++ )
{
RifOpmCommonEclipseSummary reader;
{
auto start = std::chrono::high_resolution_clock::now();
reader.open( filename, true );
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "OPM : Open " << std::setw( 9 ) << diff.count() << " s\n";
}
// for ( auto adr : reader.allResultAddresses() )
// {
// std::cout << adr.uiText();
// std::cout << std::endl;
// }
{
auto start = std::chrono::high_resolution_clock::now();
size_t totalValuesRead = 0;
// do some work
size_t i = 0;
for ( auto adr : reader.allResultAddresses() )
{
std::vector<double> values;
reader.values( adr, &values );
totalValuesRead += values.size();
i++;
if ( i > maxCount ) break;
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "OPM Read data " << std::setw( 9 ) << totalValuesRead << "totalValueCount" << diff.count()
<< " s\n";
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( DISABLED_RifSummaryDataTest, LibEclAllData )
{
QString filename = "e:/models/reek_history_match_large/realization-1/iter-0/eclipse/model/R001_REEK-1.SMSPEC";
for ( size_t iteration = 0; iteration < iterationCount; iteration++ )
{
RifReaderEclipseSummary reader;
{
auto start = std::chrono::high_resolution_clock::now();
reader.open( filename, true );
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "LibEcl : Open " << std::setw( 9 ) << diff.count() << " s\n";
}
// for ( auto adr : reader.allResultAddresses() )
// {
// std::cout << adr.uiText();
// std::cout << std::endl;
// }
{
auto start = std::chrono::high_resolution_clock::now();
size_t totalValuesRead = 0;
size_t i = 0;
for ( auto adr : reader.allResultAddresses() )
{
std::vector<double> values;
reader.values( adr, &values );
totalValuesRead += values.size();
i++;
if ( i > maxCount ) break;
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "LibEcl read data" << std::setw( 9 ) << totalValuesRead << "totalValueCount" << diff.count()
<< " s\n";
}
}
}

View File

@ -78,6 +78,8 @@ add_library(${PROJECT_NAME}
opm-common/src/opm/io/eclipse/EclOutput.cpp
opm-common/src/opm/io/eclipse/EclUtil.cpp
opm-common/src/opm/io/eclipse/EGrid.cpp
opm-common/src/opm/io/eclipse/ESmry.cpp
opm-common/src/opm/io/eclipse/EInit.cpp
# Required for use of static function RstConnection::inverse_peaceman
opm-common/src/opm/io/eclipse/rst/connection.cpp
@ -95,6 +97,8 @@ if(RESINSIGHT_ENABLE_UNITY_BUILD)
opm-common/src/opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.cpp
opm-common/src/opm/parser/eclipse/EclipseState/Schedule/MSW/SpiralICD.cpp
opm-common/src/opm/io/eclipse/EclOutput.cpp
opm-common/src/opm/io/eclipse/ESmry.cpp
opm-common/src/opm/io/eclipse/EGrid.cpp
)
foreach(fileToExclude ${UNITY_EXCLUDE_FILES})

View File

@ -1,6 +1,7 @@
#ifdef _WIN32
#include "Substitutes.hpp"
#include <Shlwapi.h>
int
fnmatch(const char* pattern, const char* string, int flags)

View File

@ -2,10 +2,6 @@
#ifdef _WIN32
#include <Shlwapi.h>
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
// IGNORE is used in InputErrorAction.hpp, as an enum value,
// but is defined as a #def in WinBase.h which is included by Shlwapi.h.
// It is not required here, so we can undefine it.

View File

@ -20,6 +20,7 @@
#define OPM_IO_EGRID_HPP
#include <opm/io/eclipse/EclFile.hpp>
#include <opm/common/utility/FileSystem.hpp>
#include <array>
#include <iostream>
@ -34,7 +35,7 @@ namespace Opm { namespace EclIO {
class EGrid : public EclFile
{
public:
explicit EGrid(const std::string& filename);
explicit EGrid(const std::string& filename, std::string grid_name = "global");
int global_index(int i, int j, int k) const;
int active_index(int i, int j, int k) const;
@ -44,20 +45,54 @@ public:
std::array<int, 3> ijk_from_active_index(int actInd) const;
std::array<int, 3> ijk_from_global_index(int globInd) const;
void getCellCorners(int globindex, std::array<double,8>& X, std::array<double,8>& Y, std::array<double,8>& Z) const;
void getCellCorners(const std::array<int, 3>& ijk, std::array<double,8>& X, std::array<double,8>& Y, std::array<double,8>& Z) const;
void getCellCorners(int globindex, std::array<double,8>& X, std::array<double,8>& Y, std::array<double,8>& Z);
void getCellCorners(const std::array<int, 3>& ijk, std::array<double,8>& X, std::array<double,8>& Y, std::array<double,8>& Z);
int activeCells() const { return nactive; }
int totalNumberOfCells() const { return nijk[0] * nijk[1] * nijk[2]; }
void load_grid_data();
void load_nnc_data();
bool is_radial() const { return m_radial; }
const std::vector<int>& hostCellsGlobalIndex() const { return host_cells; }
std::vector<std::array<int, 3>> hostCellsIJK();
// zero based: i1, j1,k1, i2,j2,k2, transmisibility
using NNCentry = std::tuple<int, int, int, int, int, int, float>;
std::vector<NNCentry> get_nnc_ijk();
const std::vector<std::string>& list_of_lgrs() const { return lgr_names; }
private:
Opm::filesystem::path inputFileName, initFileName;
std::string m_grid_name;
bool m_radial;
std::array<int, 3> nijk;
int nactive;
std::array<int, 3> host_nijk;
int nactive, m_nncs;
mutable bool m_nncs_loaded;
std::vector<int> act_index;
std::vector<int> glob_index;
std::vector<float> coord_array;
std::vector<float> zcorn_array;
std::vector<int> nnc1_array;
std::vector<int> nnc2_array;
std::vector<float> transnnc_array;
std::vector<int> host_cells;
std::vector<std::string> lgr_names;
int zcorn_array_index;
int coord_array_index;
int actnum_array_index;
int nnc1_array_index;
int nnc2_array_index;
};
}} // namespace Opm::EclIO

View File

@ -0,0 +1,102 @@
/*
Copyright 2020 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM 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.
OPM 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 for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_IO_EINIT_HPP
#define OPM_IO_EINIT_HPP
#include <opm/io/eclipse/EclFile.hpp>
#include <array>
#include <vector>
#include <map>
namespace Opm { namespace EclIO {
class EInit : public EclFile
{
public:
explicit EInit(const std::string& filename);
const std::vector<std::string>& list_of_lgrs() const { return lgr_names; }
std::vector<EclFile::EclEntry> list_arrays() const;
std::vector<EclFile::EclEntry> list_arrays(const std::string& grid_name) const;
const std::array<int, 3>& grid_dimension(const std::string& grid_name = "global") const;
int activeCells(const std::string& grid_name = "global") const;
bool hasLGR(const std::string& name) const;
template <typename T>
const std::vector<T>& getInitData(const std::string& name, const std::string& grid_name = "global")
{
return this->ImplgetInitData<T>(name, grid_name);
}
protected:
template <typename T>
const std::vector<T>& ImplgetInitData(const std::string& name, const std::string& grid_name = "global")
{
int arr_ind = get_array_index(name, grid_name);
if constexpr (std::is_same_v<T, int>)
return getImpl(arr_ind, INTE, inte_array, "integer");
if constexpr (std::is_same_v<T, float>)
return getImpl(arr_ind, REAL, real_array, "float");
if constexpr (std::is_same_v<T, double>)
return getImpl(arr_ind, DOUB, doub_array, "double");
if constexpr (std::is_same_v<T, bool>)
return getImpl(arr_ind, LOGI, logi_array, "bool");
if constexpr (std::is_same_v<T, std::string>)
{
if (array_type[arr_ind] == Opm::EclIO::CHAR)
return getImpl(arr_ind, array_type[arr_ind], char_array, "char");
if (array_type[arr_ind] == Opm::EclIO::C0NN)
return getImpl(arr_ind, array_type[arr_ind], char_array, "c0nn");
OPM_THROW(std::runtime_error, "Array not of type CHAR or C0nn");
}
OPM_THROW(std::runtime_error, "type not supported");
}
private:
std::array<int, 3> global_nijk;
std::vector<std::array<int, 3>> lgr_nijk;
int global_nactive;
std::vector<int> lgr_nactive;
std::vector<std::string> lgr_names;
std::map<std::string,int> global_array_index;
std::vector<std::map<std::string,int>> lgr_array_index;
int get_array_index(const std::string& name, const std::string& grid_name) const;
int get_lgr_index(const std::string& grid_name) const;
};
}} // namespace Opm::EclIO
#endif // OPM_IO_EINIT_HPP

View File

@ -27,6 +27,7 @@
#include <unordered_map>
#include <vector>
namespace Opm { namespace EclIO { namespace OutputStream {
class Restart;
}}}
@ -37,43 +38,73 @@ class ERst : public EclFile
{
public:
explicit ERst(const std::string& filename);
bool hasReportStepNumber(int number) const;
bool hasLGR(const std::string& gridname, int reportStepNumber) const;
void loadReportStepNumber(int number);
template <typename T>
const std::vector<T>& getRst(const std::string& name, int reportStepNumber, int occurrence);
const std::vector<T>& getRestartData(const std::string& name, int reportStepNumber)
{
return getRestartData<T>(name,reportStepNumber, 0);
}
template <typename T>
const std::vector<T>& getRst(int index, int reportStepNumber){
const std::vector<T>& getRestartData(const std::string& name, int reportStepNumber, int occurrence);
template <typename T>
const std::vector<T>& getRestartData(const std::string& name, int reportStepNumber, const std::string& lgr_name);
template <typename T>
const std::vector<T>& getRestartData(int index, int reportStepNumber)
{
auto indRange = this->getIndexRange(reportStepNumber);
return this->get<T>(index + std::get<0>(indRange));
}
int count(const std::string& name, int reportStepNumber) const;
template <typename T>
const std::vector<T>& getRestartData(int index, int reportStepNumber, const std::string& lgr_name)
{
auto indRange = this->getIndexRange(reportStepNumber);
if ((std::get<0>(indRange) + index) > std::get<1>(indRange))
OPM_THROW(std::invalid_argument, "getRestartData, index out of range");
int start_ind = get_start_index_lgrname(reportStepNumber, lgr_name);
return this->get<T>(index + start_ind);
}
int occurrence_count(const std::string& name, int reportStepNumber) const;
size_t numberOfReportSteps() const { return seqnum.size(); };
const std::vector<int>& listOfReportStepNumbers() const { return seqnum; }
std::vector<EclEntry> listOfRstArrays(int reportStepNumber);
std::vector<EclEntry> listOfRstArrays(int reportStepNumber, const std::string& lgr_name);
friend class OutputStream::Restart;
private:
int nReports;
std::vector<int> seqnum; // report step numbers, from SEQNUM array in restart file
std::unordered_map<int,bool> reportLoaded;
mutable std::unordered_map<int,bool> reportLoaded;
std::map<int, std::pair<int,int>> arrIndexRange; // mapping report step number to array indeces (start and end)
std::vector<std::vector<std::string>> lgr_names; // report step numbers, from SEQNUM array in restart file
void initUnified();
void initSeparate(const int number);
int getArrayIndex(const std::string& name, int seqnum, int occurrence) const;
std::tuple<int,int> getIndexRange(int reportStepNumber) const;
int get_start_index_lgrname(int number, const std::string& lgr_name);
int getArrayIndex(const std::string& name, int seqnum, int occurrence);
int getArrayIndex(const std::string& name, int number, const std::string& lgr_name);
std::tuple<int,int> getIndexRange(int reportStepNumber) const;
std::streampos
restartStepWritePosition(const int seqnumValue) const;
};
}} // namespace Opm::EclIO

View File

@ -40,7 +40,7 @@ class ESmry
public:
// input is smspec (or fsmspec file)
explicit ESmry(const std::string& filename, bool loadBaseRunData=false);
explicit ESmry(const std::string& filename, bool loadBaseRunData=false, bool uselodsmry=false);
int numberOfVectors() const { return nVect; }
@ -57,6 +57,11 @@ public:
void LoadData(const std::vector<std::string>& vectList) const;
void LoadData() const;
bool make_lodsmry_file();
// Added based on requirements from ResInsight
void use_lodsmry_file(bool enable);
std::chrono::system_clock::time_point startdate() const { return startdat; }
const std::vector<std::string>& keywordList() const;
@ -65,7 +70,7 @@ public:
int timestepIdxAtReportstepStart(const int reportStep) const;
size_t numberOfTimeSteps() const { return timeStepList.size(); }
size_t numberOfTimeSteps() const { return nTstep; }
const std::string& get_unit(const std::string& name) const;
const std::string& get_unit(const SummaryNode& node) const;
@ -73,10 +78,16 @@ public:
void write_rsm(std::ostream&) const;
void write_rsm_file(std::optional<Opm::filesystem::path> = std::nullopt) const;
void ijk_from_global_index(int glob, int &i, int &j, int &k) const;
private:
Opm::filesystem::path inputFileName;
bool useLodsmryFile; // Added by ResInsight use
Opm::filesystem::path inputFileName, lodFileName;
int nI, nJ, nK, nSpecFiles;
size_t nVect;
bool fromSingleRun, lodEnabeled;
uint64_t lod_offset, lod_arr_size;
size_t nVect, nTstep;
std::vector<bool> formattedFiles;
std::vector<std::string> dataFileList;
@ -92,7 +103,6 @@ private:
std::vector<int> seqIndex;
void ijk_from_global_index(int glob, int &i, int &j, int &k) const;
std::vector<SummaryNode> summaryNodes;
std::unordered_map<std::string, std::string> kwunits;
@ -129,6 +139,9 @@ private:
std::vector<std::tuple <std::string, uint64_t>> getListOfArrays(std::string filename, bool formatted);
std::vector<int> makeKeywPosVector(int speInd) const;
std::string read_string_from_disk(std::fstream& fileH, uint64_t size) const;
void inspect_lodsmry();
void Load_from_lodsmry(const std::vector<int>& keywIndVect) const;
};
}} // namespace Opm::EclIO

View File

@ -36,7 +36,7 @@ class EclFile
{
public:
explicit EclFile(const std::string& filename, bool preload = false);
bool formattedInput() { return formatted; }
bool formattedInput() const { return formatted; }
void loadData(); // load all data
void loadData(const std::string& arrName); // load all arrays with array name equal to arrName
@ -55,6 +55,8 @@ public:
using EclEntry = std::tuple<std::string, eclArrType, int64_t>;
std::vector<EclEntry> getList() const;
const std::vector<int>& getElementSizeList() const { return array_element_size; }
template <typename T>
const std::vector<T>& get(int arrIndex);
@ -66,6 +68,7 @@ public:
const std::vector<std::string>& arrayNames() const { return array_name; }
std::size_t size() const;
bool is_ix() const;
protected:
bool formatted;
@ -80,6 +83,7 @@ protected:
std::vector<std::string> array_name;
std::vector<eclArrType> array_type;
std::vector<int64_t> array_size;
std::vector<int> array_element_size;
std::vector<uint64_t> ifStreamPos;
@ -110,7 +114,10 @@ private:
void loadBinaryArray(std::fstream& fileH, std::size_t arrIndex);
void loadFormattedArray(const std::string& fileStr, std::size_t arrIndex, int64_t fromPos);
std::vector<unsigned int> get_bin_logi_raw_values(int arrIndex) const;
std::vector<std::string> get_fmt_real_raw_str_values(int arrIndex) const;
};
}} // namespace Opm::EclIO

View File

@ -24,26 +24,28 @@
namespace Opm { namespace EclIO {
// type MESS have no assisiated data
// type MESS have no assisiated data
enum eclArrType {
INTE, REAL, DOUB, CHAR, LOGI, MESS
INTE, REAL, DOUB, CHAR, LOGI, MESS, C0NN
};
// named constants related to binary file format
const unsigned int true_value = 0xffffffff;
const unsigned int true_value_ecl = 0xffffffff;
const unsigned int true_value_ix = 0x1000000;
const unsigned int false_value = 0x00000000;
const int sizeOfInte = 4; // number of bytes pr integer (inte) element
const int sizeOfReal = 4; // number of bytes pr float (real) element
const int sizeOfDoub = 8; // number of bytes pr double (doub) element
const int sizeOfLogi = 4; // number of bytes pr bool (logi) element
const int sizeOfChar = 8; // number of bytes pr string (char) element
const int MaxBlockSizeInte = 4000; // Maximum block size for INTE arrays in binary files
const int MaxBlockSizeReal = 4000; // Maximum block size for REAL arrays in binary files
const int MaxBlockSizeDoub = 8000; // Maximum block size for DOUB arrays in binary files
const int MaxBlockSizeLogi = 4000; // Maximum block size for LOGI arrays in binary files
const int MaxBlockSizeChar = 840; // Maximum block size for CHAR arrays in binary files
const int MaxBlockSizeInte = 4000; // Maximum block size for INTE arrays in binary files
const int MaxBlockSizeReal = 4000; // Maximum block size for REAL arrays in binary files
const int MaxBlockSizeDoub = 8000; // Maximum block size for DOUB arrays in binary files
const int MaxBlockSizeLogi = 4000; // Maximum block size for LOGI arrays in binary files
const int MaxBlockSizeChar = 840; // Maximum block size for CHAR arrays in binary files
// named constants related to formatted file file format
const int MaxNumBlockInte = 1000; // maximum number of Inte values in block => hard line shift
@ -52,17 +54,17 @@ namespace Opm { namespace EclIO {
const int MaxNumBlockLogi = 1000; // maximum number of Logi values in block => hard line shift
const int MaxNumBlockChar = 105; // maximum number of Char values in block => hard line shift
const int numColumnsInte = 6; // number of columns for Inte values
const int numColumnsReal = 4; // number of columns for Real values
const int numColumnsDoub = 3; // number of columns for Doub values
const int numColumnsLogi = 25; // number of columns for Logi values
const int numColumnsChar = 7; // number of columns for Char values
const int numColumnsInte = 6; // number of columns for Inte values
const int numColumnsReal = 4; // number of columns for Real values
const int numColumnsDoub = 3; // number of columns for Doub values
const int numColumnsLogi = 25; // number of columns for Logi values
const int numColumnsChar = 7; // number of columns for Char values
const int columnWidthInte = 12; // number of characters fore each Inte Element
const int columnWidthReal = 17; // number of characters fore each Inte Element
const int columnWidthDoub = 23; // number of characters fore each Inte Element
const int columnWidthLogi = 3; // number of characters fore each Inte Element
const int columnWidthChar = 11; // number of characters fore each Inte Element
const int columnWidthInte = 12; // number of characters fore each Inte Element
const int columnWidthReal = 17; // number of characters fore each Inte Element
const int columnWidthDoub = 23; // number of characters fore each Inte Element
const int columnWidthLogi = 3; // number of characters fore each Inte Element
const int columnWidthChar = 11; // number of characters fore each Inte Element
}} // namespace Opm::EclIO

View File

@ -47,59 +47,71 @@ public:
const std::vector<T>& data)
{
eclArrType arrType = MESS;
int element_size = 4;
if (typeid(T) == typeid(int))
arrType = INTE;
else if (typeid(T) == typeid(float))
arrType = REAL;
else if (typeid(T) == typeid(double))
else if (typeid(T) == typeid(double)){
arrType = DOUB;
else if (typeid(T) == typeid(bool))
element_size = 8;
} else if (typeid(T) == typeid(bool))
arrType = LOGI;
else if (typeid(T) == typeid(char))
arrType = MESS;
if (isFormatted)
{
writeFormattedHeader(name, data.size(), arrType);
writeFormattedHeader(name, data.size(), arrType, element_size);
if (arrType != MESS)
writeFormattedArray(data);
}
else
{
writeBinaryHeader(name, data.size(), arrType);
writeBinaryHeader(name, data.size(), arrType, element_size);
if (arrType != MESS)
writeBinaryArray(data);
}
}
// when this function is used array type will be assumed C0NN (not CHAR).
// Also in cases where element size is 8 or less, element size will be 8.
void write(const std::string& name, const std::vector<std::string>& data, int element_size);
void message(const std::string& msg);
void flushStream();
void set_ix() { ix_standard = true; }
friend class OutputStream::Restart;
friend class OutputStream::SummarySpecification;
private:
void writeBinaryHeader(const std::string& arrName, int64_t size, eclArrType arrType);
void writeBinaryHeader(const std::string& arrName, int64_t size, eclArrType arrType, int element_size);
template <typename T>
void writeBinaryArray(const std::vector<T>& data);
void writeBinaryCharArray(const std::vector<std::string>& data);
void writeBinaryCharArray(const std::vector<std::string>& data, int element_size);
void writeBinaryCharArray(const std::vector<PaddedOutputString<8>>& data);
void writeFormattedHeader(const std::string& arrName, int size, eclArrType arrType);
void writeFormattedHeader(const std::string& arrName, int size, eclArrType arrType, int element_size);
template <typename T>
void writeFormattedArray(const std::vector<T>& data);
void writeFormattedCharArray(const std::vector<std::string>& data);
void writeFormattedCharArray(const std::vector<std::string>& data, int element_size);
void writeFormattedCharArray(const std::vector<PaddedOutputString<8>>& data);
void writeArrayType(const eclArrType arrType);
std::string make_real_string(float value) const;
std::string make_doub_string(double value) const;
std::string make_real_string_ecl(float value) const;
std::string make_real_string_ix(float value) const;
std::string make_doub_string_ecl(double value) const;
std::string make_doub_string_ix(double value) const;
bool isFormatted;
bool isFormatted, ix_standard;
std::ofstream ofileH;
};

View File

@ -23,6 +23,8 @@
#include <string>
#include <tuple>
#include <vector>
#include <functional>
namespace Opm { namespace EclIO {
@ -31,24 +33,52 @@ namespace Opm { namespace EclIO {
float flipEndianFloat(float num);
double flipEndianDouble(double num);
bool isEOF(std::fstream* fileH);
bool fileExists(const std::string& filename);
bool isFormatted(const std::string& filename);
std::tuple<int, int> block_size_data_binary(eclArrType arrType);
std::tuple<int, int, int> block_size_data_formatted(eclArrType arrType);
std::string trimr(const std::string &str1);
uint64_t sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrType);
uint64_t sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrType arrType);
uint64_t sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrType, int elementSize);
uint64_t sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrType arrType, int elementSize);
void readBinaryHeader(std::fstream& fileH, std::string& tmpStrName,
int& tmpSize, std::string& tmpStrType);
void readBinaryHeader(std::fstream& fileH, std::string& arrName,
int64_t& size, Opm::EclIO::eclArrType &arrType);
int64_t& size, Opm::EclIO::eclArrType &arrType, int& elementSize);
void readFormattedHeader(std::fstream& fileH, std::string& arrName,
int64_t &num, Opm::EclIO::eclArrType &arrType);
int64_t &num, Opm::EclIO::eclArrType &arrType, int& elementSize);
template<typename T, typename T2>
std::vector<T> readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip, int elementSize);
std::vector<int> readBinaryInteArray(std::fstream &fileH, const int64_t size);
std::vector<float> readBinaryRealArray(std::fstream& fileH, const int64_t size);
std::vector<double> readBinaryDoubArray(std::fstream& fileH, const int64_t size);
std::vector<bool> readBinaryLogiArray(std::fstream &fileH, const int64_t size);
std::vector<unsigned int> readBinaryRawLogiArray(std::fstream &fileH, const int64_t size);
std::vector<std::string> readBinaryCharArray(std::fstream& fileH, const int64_t size);
std::vector<std::string> readBinaryC0nnArray(std::fstream& fileH, const int64_t size, int elementSize);
template<typename T>
std::vector<T> readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process);
std::vector<int> readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<std::string> readFormattedCharArray(const std::string& file_str, const int64_t size,
int64_t fromPos, int elementSize);
std::vector<float> readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<std::string> readFormattedRealRawStrings(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<bool> readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<double> readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos);
}} // namespace Opm::EclIO

View File

@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef OPM_IO_SUMMARYNODE_HPP
#define OPM_IO_SUMMARYNODE_HPP
@ -25,11 +25,10 @@
#include <string>
#include <unordered_set>
namespace Opm::EclIO {
namespace Opm { namespace EclIO {
struct SummaryNode {
enum class Category {
Aquifer,
Well,
Group,
Field,
@ -37,6 +36,8 @@ struct SummaryNode {
Block,
Connection,
Segment,
Aquifer,
Node,
Miscellaneous,
};
@ -47,6 +48,7 @@ struct SummaryNode {
Pressure,
Count,
Mode,
ProdIndex,
Undefined,
};
@ -56,6 +58,8 @@ struct SummaryNode {
std::string wgname;
int number;
std::optional<std::string> fip_region;
constexpr static int default_number { std::numeric_limits<int>::min() };
std::string unique_key() const;
@ -72,6 +76,6 @@ struct SummaryNode {
std::optional<std::string> display_number(number_renderer) const;
};
} // namespace Opm::EclIO
}} // namespace Opm::EclIO
#endif // OPM_IO_SUMMARYNODE_HPP

View File

@ -32,12 +32,21 @@ struct RstHeader;
struct RstGroup {
RstGroup(const UnitSystem& unit_system,
const RstHeader& header,
const std::string* zwel,
const int * igrp,
const float * sgrp,
const double * xgrp);
std::string name;
int parent_group;
int prod_active_cmode;
int gconprod_cmode;
int winj_cmode;
int ginj_cmode;
int guide_rate_def;
float oil_rate_limit;
float water_rate_limit;
float gas_rate_limit;

View File

@ -24,10 +24,12 @@
#include <cstddef>
namespace Opm {
class UnitSystem;
namespace RestartIO {
struct RstHeader {
RstHeader(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead);
RstHeader(const UnitSystem& unit_system, const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead);
int nx;
int ny;
@ -82,10 +84,8 @@ struct RstHeader {
int nilbrz;
int ntfip ;
int nmfipr;
int nrfreg;
int ntfreg;
int nplmix;
int ngroup;
int nwgmax;
bool e300_radial;
bool e100_radial;
@ -100,6 +100,7 @@ struct RstHeader {
bool dir_eps;
bool reversible_eps;
bool alt_eps;
bool group_control_active;
double next_timestep1;
double next_timestep2;
@ -110,6 +111,8 @@ struct RstHeader {
double guide_rate_d;
double guide_rate_e;
double guide_rate_f;
double guide_rate_delay;
double guide_rate_damping;
double udq_range;
double udq_undefined;
double udq_eps;

View File

@ -35,6 +35,11 @@ namespace Opm {
namespace RestartIO {
struct RstState {
RstState(const ::Opm::UnitSystem& unit_system,
const std::vector<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead);
RstState(const ::Opm::UnitSystem& unit_system,
const std::vector<int>& intehead,
const std::vector<bool>& logihead,

View File

@ -66,14 +66,16 @@ struct RstWell {
std::array<int, 2> ij;
std::pair<int,int> k1k2;
WellType wtype;
int well_status;
int active_control;
int vfp_table;
int pred_requested_control;
bool allow_xflow;
int preferred_phase;
int hist_requested_control;
int msw_index;
int completion_ordering;
int pvt_table;
int msw_pressure_drop_model;
float orat_target;
float wrat_target;
@ -88,12 +90,14 @@ struct RstWell {
float datum_depth;
float drainage_radius;
float efficiency_factor;
float alq_value;
double oil_rate;
double water_rate;
double gas_rate;
double liquid_rate;
double void_rate;
double thp;
double flow_bhp;
double wct;
double gor;

View File

@ -16,7 +16,12 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#define _USE_MATH_DEFINES
#include <cmath> // For definition of M_PI
#include <opm/io/eclipse/EGrid.hpp>
#include <opm/io/eclipse/EInit.hpp>
#include <opm/io/eclipse/EclUtil.hpp>
#include <opm/common/ErrorMacros.hpp>
@ -30,41 +35,200 @@
namespace Opm { namespace EclIO {
EGrid::EGrid(const std::string &filename) : EclFile(filename)
using NNCentry = std::tuple<int, int, int, int, int,int, float>;
EGrid::EGrid(const std::string &filename, std::string grid_name) :
EclFile(filename), inputFileName { filename }, m_grid_name {grid_name}
{
EclFile file(filename);
initFileName = inputFileName.parent_path() / inputFileName.stem();
auto gridhead = get<int>("GRIDHEAD");
if (this->formattedInput())
initFileName += ".FINIT";
else
initFileName += ".INIT";
nijk[0] = gridhead[1];
nijk[1] = gridhead[2];
nijk[2] = gridhead[3];
std::string lgrname = "global";
if (file.hasKey("ACTNUM")) {
auto actnum = get<int>("ACTNUM");
m_nncs_loaded = false;
actnum_array_index = -1;
nnc1_array_index = -1;
nnc2_array_index = -1;
m_radial = false;
nactive = 0;
for (unsigned int i = 0; i < actnum.size(); i++) {
if (actnum[i] > 0) {
act_index.push_back(nactive);
glob_index.push_back(i);
nactive++;
} else {
act_index.push_back(-1);
}
int hostnum_index = -1;
for (size_t n = 0; n < array_name.size(); n++) {
if (array_name[n] == "ENDLGR")
lgrname = "global";
if (array_name[n] == "LGR") {
auto lgr = this->get<std::string>(n);
lgrname = lgr[0];
lgr_names.push_back(lgr[0]);
}
} else {
int nCells = nijk[0] * nijk[1] * nijk[2];
act_index.resize(nCells);
glob_index.resize(nCells);
std::iota(act_index.begin(), act_index.end(), 0);
std::iota(glob_index.begin(), glob_index.end(), 0);
}
coord_array = get<float>("COORD");
zcorn_array = get<float>("ZCORN");
if (array_name[n] == "NNCHEAD"){
auto nnchead = this->get<int>(n);
if (nnchead[1] == 0)
lgrname = "global";
else
lgrname = lgr_names[nnchead[1] - 1];
}
if (lgrname == grid_name) {
if (array_name[n] == "GRIDHEAD") {
auto gridhead = get<int>(n);
nijk[0] = gridhead[1];
nijk[1] = gridhead[2];
nijk[2] = gridhead[3];
if (gridhead.size() > 26)
m_radial = gridhead[26] > 0 ? true: false;
}
if (array_name[n] == "COORD")
coord_array_index= n;
else if (array_name[n] == "ZCORN")
zcorn_array_index= n;
else if (array_name[n] == "ACTNUM")
actnum_array_index= n;
else if (array_name[n] == "NNC1")
nnc1_array_index= n;
else if (array_name[n] == "NNC2")
nnc2_array_index= n;
else if (array_name[n] == "HOSTNUM")
hostnum_index= n;
}
if ((lgrname == "global") && (array_name[n] == "GRIDHEAD")) {
auto gridhead = get<int>(n);
host_nijk[0] = gridhead[1];
host_nijk[1] = gridhead[2];
host_nijk[2] = gridhead[3];
}
}
if (actnum_array_index != -1) {
auto actnum = this->get<int>(actnum_array_index);
nactive = 0;
for (size_t i = 0; i < actnum.size(); i++) {
if (actnum[i] > 0) {
act_index.push_back(nactive);
glob_index.push_back(i);
nactive++;
} else {
act_index.push_back(-1);
}
}
} else {
int nCells = nijk[0] * nijk[1] * nijk[2];
act_index.resize(nCells);
glob_index.resize(nCells);
std::iota(act_index.begin(), act_index.end(), 0);
std::iota(glob_index.begin(), glob_index.end(), 0);
}
if (hostnum_index > -1){
auto hostnum = getImpl(hostnum_index, INTE, inte_array, "integer");
host_cells.reserve(hostnum.size());
for (auto val : hostnum)
host_cells.push_back(val -1);
}
}
std::vector<std::array<int, 3>> EGrid::hostCellsIJK()
{
std::vector<std::array<int, 3>> res_vect;
res_vect.reserve(host_cells.size());
for (auto val : host_cells){
std::array<int, 3> tmp;
tmp[2] = val / (host_nijk[0] * host_nijk[1]);
int rest = val % (host_nijk[0] * host_nijk[1]);
tmp[1] = rest / host_nijk[0];
tmp[0] = rest % host_nijk[0];
res_vect.push_back(tmp);
}
return res_vect;
}
std::vector<NNCentry> EGrid::get_nnc_ijk()
{
if (!m_nncs_loaded)
load_nnc_data();
std::vector<NNCentry> res_vect;
res_vect.reserve(nnc1_array.size());
for (size_t n=0; n< nnc1_array.size(); n++){
auto ijk1 = ijk_from_global_index(nnc1_array[n] - 1);
auto ijk2 = ijk_from_global_index(nnc2_array[n] - 1);
if (transnnc_array.size() > 0)
res_vect.push_back({ijk1[0], ijk1[1], ijk1[2], ijk2[0], ijk2[1], ijk2[2], transnnc_array[n]});
else
res_vect.push_back({ijk1[0], ijk1[1], ijk1[2], ijk2[0], ijk2[1], ijk2[2], -1.0 });
}
return res_vect;
}
void EGrid::load_grid_data()
{
coord_array = getImpl(coord_array_index, REAL, real_array, "float");
zcorn_array = getImpl(zcorn_array_index, REAL, real_array, "float");
}
void EGrid::load_nnc_data()
{
if ((nnc1_array_index > -1) && (nnc2_array_index > -1)) {
nnc1_array = getImpl(nnc1_array_index, Opm::EclIO::INTE, inte_array, "inte");
nnc2_array = getImpl(nnc2_array_index, Opm::EclIO::INTE, inte_array, "inte");
if ((Opm::filesystem::exists(initFileName)) && (nnc1_array.size() > 0)){
Opm::EclIO::EInit init(initFileName.string());
auto init_dims = init.grid_dimension(m_grid_name);
int init_nactive = init.activeCells(m_grid_name);
if (init_dims != nijk){
std::string message = "Dimensions of Egrid differ from dimensions found in init file. ";
std::string grid_str = std::to_string(nijk[0]) + "x" + std::to_string(nijk[1]) + "x" + std::to_string(nijk[2]);
std::string init_str = std::to_string(init_dims[0]) + "x" + std::to_string(init_dims[1]) + "x" + std::to_string(init_dims[2]);
message = message + "Egrid: " + grid_str + ". INIT file: " + init_str;
OPM_THROW(std::invalid_argument, message);
}
if (init_nactive != nactive){
std::string message = "Number of active cells are different in Egrid and Init file.";
message = message + " Egrid: " + std::to_string(nactive) + ". INIT file: " + std::to_string(init_nactive);
OPM_THROW(std::invalid_argument, message);
}
auto trans_data = init.getInitData<float>("TRANNNC", m_grid_name);
if (trans_data.size() != nnc1_array.size()){
std::string message = "inconsistent size of array TRANNNC in init file. ";
message = message + " Size of NNC1 and NNC2: " + std::to_string(nnc1_array.size());
message = message + " Size of TRANNNC: " + std::to_string(trans_data.size());
OPM_THROW(std::invalid_argument, message);
}
transnnc_array = trans_data;
}
m_nncs_loaded = true;
}
}
int EGrid::global_index(int i, int j, int k) const
{
@ -129,52 +293,65 @@ std::array<int, 3> EGrid::ijk_from_global_index(int globInd) const
void EGrid::getCellCorners(const std::array<int, 3>& ijk,
std::array<double,8>& X,
std::array<double,8>& Y,
std::array<double,8>& Z) const
std::array<double,8>& Z)
{
if (coord_array.empty())
load_grid_data();
std::vector<int> zind;
std::vector<int> pind;
// calculate indices for grid pillars in COORD arrray
pind.push_back(ijk[1]*(nijk[0]+1)*6 + ijk[0]*6);
pind.push_back(pind[0] + 6);
pind.push_back(pind[0] + (nijk[0]+1)*6);
pind.push_back(pind[2] + 6);
pind.push_back(ijk[1]*(nijk[0]+1)*6 + ijk[0]*6);
pind.push_back(pind[0] + 6);
pind.push_back(pind[0] + (nijk[0]+1)*6);
pind.push_back(pind[2] + 6);
// get depths from zcorn array in ZCORN array
zind.push_back(ijk[2]*nijk[0]*nijk[1]*8 + ijk[1]*nijk[0]*4 + ijk[0]*2);
zind.push_back(zind[0] + 1);
zind.push_back(zind[0] + nijk[0]*2);
zind.push_back(zind[2] + 1);
// get depths from zcorn array in ZCORN array
zind.push_back(ijk[2]*nijk[0]*nijk[1]*8 + ijk[1]*nijk[0]*4 + ijk[0]*2);
zind.push_back(zind[0] + 1);
zind.push_back(zind[0] + nijk[0]*2);
zind.push_back(zind[2] + 1);
for (int n = 0; n < 4; n++) {
zind.push_back(zind[n] + nijk[0]*nijk[1]*4);
}
for (int n = 0; n < 4; n++)
zind.push_back(zind[n] + nijk[0]*nijk[1]*4);
for (int n = 0; n< 8; n++){
Z[n] = zcorn_array[zind[n]];
}
for (int n = 0; n< 8; n++)
Z[n] = zcorn_array[zind[n]];
for (int n = 0; n < 4; n++) {
double xt = coord_array[pind[n]];
double yt = coord_array[pind[n] + 1];
double zt = coord_array[pind[n] + 2];
for (int n = 0; n < 4; n++) {
double xt;
double yt;
double xb;
double yb;
double xb = coord_array[pind[n] + 3];
double yb = coord_array[pind[n] + 4];
double zb = coord_array[pind[n]+5];
double zt = coord_array[pind[n] + 2];
double zb = coord_array[pind[n] + 5];
X[n] = xt + (xb-xt) / (zt-zb) * (zt - Z[n]);
X[n+4] = xt + (xb-xt) / (zt-zb) * (zt-Z[n+4]);
if (m_radial) {
xt = coord_array[pind[n]] * cos(coord_array[pind[n] + 1] / 180.0 * M_PI);
yt = coord_array[pind[n]] * sin(coord_array[pind[n] + 1] / 180.0 * M_PI);
xb = coord_array[pind[n]+3] * cos(coord_array[pind[n] + 4] / 180.0 * M_PI);
yb = coord_array[pind[n]+3] * sin(coord_array[pind[n] + 4] / 180.0 * M_PI);
} else {
xt = coord_array[pind[n]];
yt = coord_array[pind[n] + 1];
xb = coord_array[pind[n] + 3];
yb = coord_array[pind[n] + 4];
}
Y[n] = yt+(yb-yt)/(zt-zb)*(zt-Z[n]);
Y[n+4] = yt+(yb-yt)/(zt-zb)*(zt-Z[n+4]);
}
X[n] = xt + (xb-xt) / (zt-zb) * (zt - Z[n]);
X[n+4] = xt + (xb-xt) / (zt-zb) * (zt-Z[n+4]);
Y[n] = yt+(yb-yt)/(zt-zb)*(zt-Z[n]);
Y[n+4] = yt+(yb-yt)/(zt-zb)*(zt-Z[n+4]);
}
}
void EGrid::getCellCorners(int globindex, std::array<double,8>& X,
std::array<double,8>& Y, std::array<double,8>& Z) const
std::array<double,8>& Y, std::array<double,8>& Z)
{
return getCellCorners(ijk_from_global_index(globindex),X,Y,Z);
}

View File

@ -0,0 +1,161 @@
/*
Copyright 2020 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM 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.
OPM 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 for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/io/eclipse/EInit.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <algorithm>
namespace Opm { namespace EclIO {
EInit::EInit(const std::string &filename) : EclFile(filename)
{
std::string lgrname;
std::string nncname;
lgrname = "global";
for (size_t n = 0; n < array_name.size(); n++) {
if (array_name[n] == "LGR"){
auto lgr = this->get<std::string>(n);
lgrname = lgr[0];
if (std::find(lgr_names.begin(), lgr_names.end(), lgrname) == lgr_names.end()){
lgr_names.push_back(lgrname);
lgr_array_index.push_back({});
lgr_nijk.push_back({});
lgr_nactive.push_back(0);
}
}
if (array_name[n] == "LGRSGONE")
lgrname = "global";
if ((lgrname == "global") && (array_name[n] != "LGRSGONE"))
global_array_index[array_name[n]] = n;
if ((lgrname != "global") && (array_name[n] != "LGRSGONE") && (array_name[n] != "LGR"))
{
auto it = std::find(lgr_names.begin(), lgr_names.end(), lgrname);
size_t ind = std::distance(lgr_names.begin(), it);
lgr_array_index[ind][array_name[n]] = n;
}
if (array_name[n] == "INTEHEAD")
{
auto inteh = getImpl(n, INTE, inte_array, "integer");
if (lgrname == "global") {
global_nijk = {inteh[8], inteh[9], inteh[10]};
global_nactive = inteh[11];
} else {
auto it = std::find(lgr_names.begin(), lgr_names.end(), lgrname);
size_t lgr_ind = std::distance(lgr_names.begin(), it);
lgr_nijk[lgr_ind] = {inteh[8], inteh[9], inteh[10]};
lgr_nactive[lgr_ind] = inteh[11];
}
}
}
}
int EInit::get_array_index(const std::string& name, const std::string& grid_name) const
{
if (grid_name == "global"){
if (global_array_index.count(name) == 0)
OPM_THROW(std::runtime_error, "Map key '" + name + "' not found in global_array_index");
return global_array_index.at(name);
} else {
int lgr_index = get_lgr_index(grid_name);
if (lgr_array_index[lgr_index].count(name) == 0)
OPM_THROW(std::invalid_argument, "Map key '" + name + "' not found in lgr_array_index");
return lgr_array_index[lgr_index].at(name);
}
};
int EInit::activeCells(const std::string& grid_name) const
{
if (grid_name == "global")
return global_nactive;
else
return lgr_nactive[get_lgr_index(grid_name)];
}
const std::array<int, 3>& EInit::grid_dimension(const std::string& grid_name) const
{
if (grid_name == "global")
return global_nijk;
else
return lgr_nijk[get_lgr_index(grid_name)];
}
bool EInit::hasLGR(const std::string& name) const{
if (std::find(lgr_names.begin(), lgr_names.end(), name) == lgr_names.end())
return false;
else
return true;
}
int EInit::get_lgr_index(const std::string& grid_name) const
{
auto it = std::find(lgr_names.begin(), lgr_names.end(), grid_name);
if (it == lgr_names.end()) {
std::string message = "LGR '" + grid_name + "' not found in init file.";
OPM_THROW(std::invalid_argument, message);
}
return std::distance(lgr_names.begin(), it);
}
std::vector<EclFile::EclEntry> EInit::list_arrays(const std::string& grid_name) const
{
std::vector<EclEntry> array_list;
int lgr_index = this->get_lgr_index(grid_name);
for (auto const& x : lgr_array_index[lgr_index])
{
int ind = x.second;
array_list.push_back(std::make_tuple(array_name[ind], array_type[ind], array_size[ind]));
}
return array_list;
}
std::vector<EclFile::EclEntry> EInit::list_arrays() const
{
std::vector<EclEntry> array_list;
for (auto const& x : global_array_index)
{
int ind = x.second;
array_list.push_back(std::make_tuple(array_name[ind], array_type[ind], array_size[ind]));
}
return array_list;
}
}} // namespace Opm::EclIO

View File

@ -22,6 +22,8 @@
#include <cmath>
#include <chrono>
#include <fmt/format.h>
#include <opm/io/eclipse/ERsm.hpp>
#include <opm/io/eclipse/ESmry.hpp>
#include <opm/common/utility/FileSystem.hpp>
@ -174,7 +176,8 @@ void ERsm::load_block(std::deque<std::string>& lines, std::size_t& vector_length
SummaryNode::category_from_keyword(kw_list[kw_index]),
SummaryNode::Type::Undefined,
wgnames[kw_index],
make_num(nums_list[kw_index])};
make_num(nums_list[kw_index]),
""};
block_data.emplace_back( node, vector_length );
}
@ -254,21 +257,29 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
const auto& summary_dates = smry.dates();
if (rsm.has_dates()) {
const auto& rsm_dates = rsm.dates();
if (rsm_dates.size() != summary_dates.size())
if (rsm_dates.size() != summary_dates.size()) {
fmt::print(stderr, "len(summary) = {} len(rsm) = {}", summary_dates.size(), rsm_dates.size());
return false;
}
for (std::size_t time_index = 0; time_index < rsm_dates.size(); time_index++) {
const auto smry_ts = TimeStampUTC( std::chrono::system_clock::to_time_t(summary_dates[time_index]) );
const auto rsm_ts = rsm_dates[time_index];
if (smry_ts.year() != rsm_ts.year())
if (smry_ts.year() != rsm_ts.year()) {
fmt::print(stderr, "time_index: {} summary.year: {} rsm.year: {}", time_index, smry_ts.year(), rsm_ts.year());
return false;
}
if (smry_ts.month() != rsm_ts.month())
if (smry_ts.month() != rsm_ts.month()) {
fmt::print(stderr, "time_index: {} summary.month: {} rsm.month: {}", time_index, smry_ts.month(), rsm_ts.month());
return false;
}
if (smry_ts.day() != rsm_ts.day())
if (smry_ts.day() != rsm_ts.day()) {
fmt::print(stderr, "time_index: {} summary.day: {} rsm.day: {}", time_index, smry_ts.day(), rsm_ts.day());
return false;
}
}
} else {
const auto& rsm_days = rsm.days();
@ -280,8 +291,10 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
using TP = time_point<system_clock>;
auto smry_days = duration_cast<TP::duration>(summary_dates[time_index] - summary_dates[0]).count() / 86400.0 ;
if (!cmp::scalar_equal(smry_days, rsm_days[time_index]))
if (!cmp::scalar_equal(smry_days, rsm_days[time_index])) {
fmt::print(stderr, "time_index: {} summary.days: {} rsm.days: {}", time_index, smry_days, rsm_days[time_index]);
return false;
}
}
}
@ -309,11 +322,14 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
const auto& smry_vector = smry.get(node);
const auto& rsm_vector = rsm.get(key);
for (std::size_t index = 0; index < smry_vector.size(); index++) {
const double eps = 5e-5;
const double diff = static_cast<double>(smry_vector[index]) - rsm_vector[index];
const double sum = std::fabs(static_cast<double>(smry_vector[index])) + std::fabs(rsm_vector[index]);
if (diff > 1e-5 * sum)
if (diff > eps * sum) {
fmt::print(stderr, "time_index: {} key: {} summary: {} rsm: {}", index, key, smry_vector[index], rsm_vector[index]);
return false;
}
}
}

View File

@ -28,8 +28,6 @@
#include <stdexcept>
#include <string>
#include <iostream>
namespace {
int seqnumFromSeparateFilename(const std::string& filename)
@ -80,9 +78,9 @@ void ERst::loadReportStepNumber(int number)
}
std::vector<int> arrayIndexList;
arrayIndexList.reserve(arrIndexRange[number].second - arrIndexRange[number].first + 1);
arrayIndexList.reserve(arrIndexRange.at(number).second - arrIndexRange.at(number).first + 1);
for (int i = arrIndexRange[number].first; i < arrIndexRange[number].second; i++) {
for (int i = arrIndexRange.at(number).first; i < arrIndexRange.at(number).second; i++) {
arrayIndexList.push_back(i);
}
@ -93,6 +91,12 @@ void ERst::loadReportStepNumber(int number)
std::vector<EclFile::EclEntry> ERst::listOfRstArrays(int reportStepNumber)
{
return this->listOfRstArrays(reportStepNumber, "global");
}
std::vector<EclFile::EclEntry> ERst::listOfRstArrays(int reportStepNumber, const std::string& lgr_name)
{
std::vector<EclEntry> list;
@ -101,36 +105,66 @@ std::vector<EclFile::EclEntry> ERst::listOfRstArrays(int reportStepNumber)
OPM_THROW(std::invalid_argument, message);
}
const auto& rng = this->arrIndexRange[reportStepNumber];
list.reserve(rng.second - rng.first);
for (int i = rng.first; i < rng.second; i++) {
list.emplace_back(array_name[i], array_type[i], array_size[i]);
if ((lgr_name != "global") && (!this->hasLGR(lgr_name, reportStepNumber))) {
std::string message = "Trying to get list of arrays from non existing LGR " + lgr_name;
OPM_THROW(std::invalid_argument, message);
}
std::string lgr_name_upper = lgr_name;
std::transform(lgr_name_upper.begin(), lgr_name_upper.end(),lgr_name_upper.begin(), ::toupper);
int start_ind_lgr;
std::string last_array_name;
if ((lgr_name == "") or (lgr_name_upper == "GLOBAL")){
auto rng = this->arrIndexRange.at(reportStepNumber);
start_ind_lgr = std::get<0>(rng);
// if keyword LGR not found, loop will be stopped with keyword SEQNUM (next report step)
// or last array (end of file)
// Opm flow can have extra keywords after ENDSOL, which maks ENDSOL
// not usable for a global arrays end signal.
last_array_name = "LGR";
} else {
start_ind_lgr = get_start_index_lgrname(reportStepNumber, lgr_name);
last_array_name = "ENDLGR";
}
int n = start_ind_lgr;
list.emplace_back(array_name[n], array_type[n], array_size[n]);
do {
n++;
if ((array_name[n] != "SEQNUM") && (array_name[n] != "LGR"))
list.emplace_back(array_name[n], array_type[n], array_size[n]);
} while ((array_name[n] != "SEQNUM") && (array_name[n] != last_array_name) && (n < static_cast<int>(array_name.size()) -1 ));
return list;
}
int ERst::count(const std::string& name, int reportStepNumber) const
{
int ERst::occurrence_count(const std::string& name, int reportStepNumber) const
{
if (!hasReportStepNumber(reportStepNumber)) {
std::string message = "Trying to count vectors of name " + name + " from non existing sequence " + std::to_string(reportStepNumber);
OPM_THROW(std::invalid_argument, message);
}
int count = 0;
auto range_it = arrIndexRange.find(reportStepNumber);
std::pair<int,int> indexRange = range_it->second;
for (int i=std::get<0>(indexRange); i<std::get<1>(indexRange);i++){
if (array_name[i] == name){
count++;
}
}
return count;
}
@ -145,10 +179,15 @@ void ERst::initUnified()
auto seqn = get<int>(i);
seqnum.push_back(seqn[0]);
firstIndex.push_back(i);
lgr_names.push_back({});
}
if (array_name[i] == "LGRNAMES") {
auto names = getImpl(i, CHAR, char_array, "string");
lgr_names[seqnum.size() -1 ] = names;
}
}
for (size_t i = 0; i < seqnum.size(); i++) {
std::pair<int,int> range;
range.first = firstIndex[i];
@ -169,6 +208,21 @@ void ERst::initUnified()
}
}
bool ERst::hasLGR(const std::string& gridname, int reportStepNumber) const
{
if (!hasReportStepNumber(reportStepNumber)) {
std::string message = "Checking for LGR name in non existing sequence " + std::to_string(reportStepNumber);
OPM_THROW(std::invalid_argument, message);
}
auto it_seqnum = std::find(seqnum.begin(), seqnum.end(), reportStepNumber);
int report_index = std::distance(seqnum.begin(), it_seqnum);
auto it_lgrname = std::find(lgr_names[report_index].begin(), lgr_names[report_index].end(), gridname);
return (it_lgrname != lgr_names[report_index].end());
}
void ERst::initSeparate(const int number)
{
auto& range = this->arrIndexRange[number];
@ -178,6 +232,41 @@ void ERst::initSeparate(const int number)
this->seqnum.assign(1, number);
this->nReports = 1;
this->reportLoaded[number] = false;
this->lgr_names.push_back({});
for (int i = range.first; i < range.second; i++) {
if (array_name[i] == "LGRNAMES") {
auto names = getImpl(i, CHAR, char_array, "string");
lgr_names[0] = names;
}
}
}
int ERst::get_start_index_lgrname(int number, const std::string& lgr_name)
{
if (!hasReportStepNumber(number)) {
std::string message = "Trying to get a restart vector from non report step " + std::to_string(number);
OPM_THROW(std::invalid_argument, message);
}
auto range_it = arrIndexRange.find(number);
std::pair<int,int> indexRange = range_it->second;
int start_ind_lgr = -1;
for (int n = indexRange.first; n < indexRange.second; n++) {
if (array_name[n] == "LGR") {
auto arr = getImpl(n, CHAR, char_array, "string");
if (arr[0] == lgr_name)
start_ind_lgr = n;
}
}
if (start_ind_lgr == -1){
std::string message = "LGR '" + lgr_name + "'not found in restart file";
OPM_THROW(std::runtime_error, message);
}
return start_ind_lgr;
}
std::tuple<int,int> ERst::getIndexRange(int reportStepNumber) const {
@ -186,19 +275,20 @@ std::tuple<int,int> ERst::getIndexRange(int reportStepNumber) const {
std::string message = "Trying to get index range for non existing sequence " + std::to_string(reportStepNumber);
OPM_THROW(std::invalid_argument, message);
}
auto range_it = arrIndexRange.find(reportStepNumber);
return range_it->second;
}
int ERst::getArrayIndex(const std::string& name, int number, int occurrenc) const
int ERst::getArrayIndex(const std::string& name, int number, int occurrenc)
{
if (!hasReportStepNumber(number)) {
std::string message = "Trying to get vector " + name + " from non existing sequence " + std::to_string(number);
OPM_THROW(std::invalid_argument, message);
}
auto range_it = arrIndexRange.find(number);
std::pair<int,int> indexRange = range_it->second;
@ -209,7 +299,7 @@ int ERst::getArrayIndex(const std::string& name, int number, int occurrenc) cons
for (int t = 0; t < occurrenc; t++){
it = std::find(it + 1 , array_name.begin() + indexRange.second, name);
}
if (std::distance(array_name.begin(),it) == indexRange.second) {
std::string message = "Array " + name + " not found in sequence " + std::to_string(number);
OPM_THROW(std::runtime_error, message);
@ -218,6 +308,25 @@ int ERst::getArrayIndex(const std::string& name, int number, int occurrenc) cons
return std::distance(array_name.begin(), it);
}
int ERst::getArrayIndex(const std::string& name, int number, const std::string& lgr_name)
{
auto range_it = arrIndexRange.find(number);
std::pair<int,int> indexRange = range_it->second;
int start_ind_lgr = get_start_index_lgrname(number, lgr_name);
auto it = std::find(array_name.begin() + start_ind_lgr,
array_name.begin() + indexRange.second, name);
if (std::distance(array_name.begin(),it) == indexRange.second) {
std::string message = "Array " + name + " not found for " + lgr_name;
OPM_THROW(std::runtime_error, message);
}
return std::distance(array_name.begin(), it);
}
std::streampos
ERst::restartStepWritePosition(const int seqnumValue) const
{
@ -229,38 +338,74 @@ ERst::restartStepWritePosition(const int seqnumValue) const
}
template<>
const std::vector<int>& ERst::getRst<int>(const std::string& name, int reportStepNumber, int occurrence)
const std::vector<int>& ERst::getRestartData<int>(const std::string& name, int reportStepNumber, int occurrence)
{
int ind = getArrayIndex(name, reportStepNumber, occurrence);
return getImpl(ind, INTE, inte_array, "integer");
}
template<>
const std::vector<float>& ERst::getRst<float>(const std::string& name, int reportStepNumber, int occurrence)
const std::vector<float>& ERst::getRestartData<float>(const std::string& name, int reportStepNumber, int occurrence)
{
int ind = getArrayIndex(name, reportStepNumber, occurrence);
return getImpl(ind, REAL, real_array, "float");
}
template<>
const std::vector<double>& ERst::getRst<double>(const std::string& name, int reportStepNumber, int occurrence)
const std::vector<double>& ERst::getRestartData<double>(const std::string& name, int reportStepNumber, int occurrence)
{
int ind = getArrayIndex(name, reportStepNumber, occurrence);
return getImpl(ind, DOUB, doub_array, "double");
}
template<>
const std::vector<bool>& ERst::getRst<bool>(const std::string& name, int reportStepNumber, int occurrence)
const std::vector<bool>& ERst::getRestartData<bool>(const std::string& name, int reportStepNumber, int occurrence)
{
int ind = getArrayIndex(name, reportStepNumber, occurrence);
return getImpl(ind, LOGI, logi_array, "bool");
}
template<>
const std::vector<std::string>& ERst::getRst<std::string>(const std::string& name, int reportStepNumber, int occurrence)
const std::vector<std::string>& ERst::getRestartData<std::string>(const std::string& name, int reportStepNumber, int occurrence)
{
int ind = getArrayIndex(name, reportStepNumber, occurrence);
return getImpl(ind, CHAR, char_array, "string");
}
template<>
const std::vector<float>& ERst::getRestartData<float>(const std::string& name, int reportStepNumber,const std::string& lgr_name)
{
int ind = getArrayIndex(name, reportStepNumber, lgr_name);
return getImpl(ind, REAL, real_array, "float");
}
template<>
const std::vector<double>& ERst::getRestartData<double>(const std::string& name, int reportStepNumber,const std::string& lgr_name)
{
int ind = getArrayIndex(name, reportStepNumber, lgr_name);
return getImpl(ind, DOUB, doub_array, "double");
}
template<>
const std::vector<int>& ERst::getRestartData<int>(const std::string& name, int reportStepNumber,const std::string& lgr_name)
{
int ind = getArrayIndex(name, reportStepNumber, lgr_name);
return getImpl(ind, INTE, inte_array, "int");
}
template<>
const std::vector<bool>& ERst::getRestartData<bool>(const std::string& name, int reportStepNumber,const std::string& lgr_name)
{
int ind = getArrayIndex(name, reportStepNumber, lgr_name);
return getImpl(ind, LOGI, logi_array, "bool");
}
template<>
const std::vector<std::string>& ERst::getRestartData<std::string>(const std::string& name, int reportStepNumber,const std::string& lgr_name)
{
int ind = getArrayIndex(name, reportStepNumber, lgr_name);
return getImpl(ind, CHAR, char_array, "char");
}
}} // namespace Opm::ecl

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
#include <opm/io/eclipse/EclUtil.hpp>
#include <opm/common/ErrorMacros.hpp>
//#include <fmt/format.h>
#include <algorithm>
#include <array>
#include <cstring>
@ -34,256 +35,13 @@
#include <iostream>
// anonymous namespace for EclFile
namespace {
bool fileExists(const std::string& filename){
std::ifstream fileH(filename.c_str());
return fileH.good();
}
bool isFormatted(const std::string& filename)
{
const auto p = filename.find_last_of(".");
if (p == std::string::npos)
OPM_THROW(std::invalid_argument,
"Purported ECLIPSE Filename'" + filename + "'does not contain extension");
return std::strchr("ABCFGH", static_cast<int>(filename[p+1])) != nullptr;
}
template<typename T, typename T2>
std::vector<T> readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip)
{
std::vector<T> arr;
auto sizeData = block_size_data_binary(type);
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
arr.reserve(size);
int64_t rest = size;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
int num = dhead / sizeOfElement;
if ((num > maxNumberOfElements) || (num < 0)) {
OPM_THROW(std::runtime_error, "Error reading binary data, inconsistent header data or incorrect number of elements");
}
for (int i = 0; i < num; i++) {
T2 value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfElement);
arr.push_back(flip(value));
}
rest -= num;
if (( num < maxNumberOfElements && rest != 0) ||
(num == maxNumberOfElements && rest < 0)) {
std::string message = "Error reading binary data, incorrect number of elements";
OPM_THROW(std::runtime_error, message);
}
int dtail;
fileH.read(reinterpret_cast<char*>(&dtail), sizeof(dtail));
dtail = Opm::EclIO::flipEndianInt(dtail);
if (dhead != dtail) {
OPM_THROW(std::runtime_error, "Error reading binary data, tail not matching header.");
}
}
return arr;
}
std::vector<int> readBinaryInteArray(std::fstream &fileH, const int64_t size)
{
std::function<int(int)> f = Opm::EclIO::flipEndianInt;
return readBinaryArray<int,int>(fileH, size, Opm::EclIO::INTE, f);
}
std::vector<float> readBinaryRealArray(std::fstream& fileH, const int64_t size)
{
std::function<float(float)> f = Opm::EclIO::flipEndianFloat;
return readBinaryArray<float,float>(fileH, size, Opm::EclIO::REAL, f);
}
std::vector<double> readBinaryDoubArray(std::fstream& fileH, const int64_t size)
{
std::function<double(double)> f = Opm::EclIO::flipEndianDouble;
return readBinaryArray<double,double>(fileH, size, Opm::EclIO::DOUB, f);
}
std::vector<bool> readBinaryLogiArray(std::fstream &fileH, const int64_t size)
{
std::function<bool(unsigned int)> f = [](unsigned int intVal)
{
bool value;
if (intVal == Opm::EclIO::true_value) {
value = true;
} else if (intVal == Opm::EclIO::false_value) {
value = false;
} else {
OPM_THROW(std::runtime_error, "Error reading logi value");
}
return value;
};
return readBinaryArray<bool,unsigned int>(fileH, size, Opm::EclIO::LOGI, f);
}
std::vector<std::string> readBinaryCharArray(std::fstream& fileH, const int64_t size)
{
using Char8 = std::array<char, 8>;
std::function<std::string(Char8)> f = [](const Char8& val)
{
std::string res(val.begin(), val.end());
return Opm::EclIO::trimr(res);
};
return readBinaryArray<std::string,Char8>(fileH, size, Opm::EclIO::CHAR, f);
}
template<typename T>
std::vector<T> readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process)
{
std::vector<T> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_not_of(' ',p1);
int64_t p2 = file_str.find_first_of(' ', p1);
arr.push_back(process(file_str.substr(p1, p2-p1)));
p1 = file_str.find_first_not_of(' ',p2);
}
return arr;
}
std::vector<int> readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<int(const std::string&)> f = [](const std::string& val)
{
return std::stoi(val);
};
return readFormattedArray(file_str, size, fromPos, f);
}
std::vector<std::string> readFormattedCharArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::vector<std::string> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_of('\'',p1);
std::string value = file_str.substr(p1 + 1, 8);
if (value == " ") {
arr.push_back("");
} else {
arr.push_back(Opm::EclIO::trimr(value));
}
p1 = p1+10;
}
return arr;
}
std::vector<float> readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<float(const std::string&)> f = [](const std::string& val)
{
// tskille: temporary fix, need to be discussed. OPM flow writes numbers
// that are outside valid range for float, and function stof will fail
double dtmpv = std::stod(val);
return dtmpv;
};
return readFormattedArray<float>(file_str, size, fromPos, f);
}
std::vector<bool> readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<bool(const std::string&)> f = [](const std::string& val)
{
if (val[0] == 'T') {
return true;
} else if (val[0] == 'F') {
return false;
} else {
std::string message="Could not convert '" + val + "' to a bool value ";
OPM_THROW(std::invalid_argument, message);
}
};
return readFormattedArray<bool>(file_str, size, fromPos, f);
}
std::vector<double> readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<double(const std::string&)> f = [](std::string val)
{
auto p1 = val.find_first_of("D");
if (p1 == std::string::npos) {
auto p2 = val.find_first_of("-+", 1);
if (p2 != std::string::npos) {
val = val.insert(p2,"E");
}
} else {
val.replace(p1,1,"E");
}
return std::stod(val);
};
return readFormattedArray<double>(file_str, size, fromPos, f);
}
} // anonymous namespace
// ==========================================================================
namespace Opm { namespace EclIO {
EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(filename)
{
if (!fileExists(filename)){
std::string message="Could not open EclFile: " + filename;
OPM_THROW(std::invalid_argument, message);
}
if (!fileExists(filename))
throw std::runtime_error("Can not open EclFile: {}");
std::fstream fileH;
@ -295,27 +53,27 @@ EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(file
fileH.open(filename, std::ios::in | std::ios::binary);
}
if (!fileH) {
std::string message="Could not open file: " + filename;
OPM_THROW(std::runtime_error, message);
}
if (!fileH)
throw std::runtime_error("Can not open EclFile: {}");
int n = 0;
while (!isEOF(&fileH)) {
std::string arrName(8,' ');
eclArrType arrType;
int64_t num;
int sizeOfElement;
if (formatted) {
readFormattedHeader(fileH,arrName,num,arrType);
readFormattedHeader(fileH,arrName,num,arrType, sizeOfElement);
} else {
readBinaryHeader(fileH,arrName,num,arrType);
readBinaryHeader(fileH,arrName,num, arrType, sizeOfElement);
}
array_size.push_back(num);
array_type.push_back(arrType);
array_name.push_back(trimr(arrName));
array_element_size.push_back(sizeOfElement);
array_index[array_name[n]] = n;
uint64_t pos = fileH.tellg();
@ -323,17 +81,16 @@ EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(file
arrayLoaded.push_back(false);
if (num > 0){
if (num > 0){
if (formatted) {
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType);
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType, sizeOfElement);
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
} else {
uint64_t sizeOfNextArray = sizeOnDiskBinary(num, arrType);
uint64_t sizeOfNextArray = sizeOnDiskBinary(num, arrType, sizeOfElement);
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
}
}
n++;
};
@ -366,6 +123,9 @@ void EclFile::loadBinaryArray(std::fstream& fileH, std::size_t arrIndex)
case CHAR:
char_array[arrIndex] = readBinaryCharArray(fileH, array_size[arrIndex]);
break;
case C0NN:
char_array[arrIndex] = readBinaryC0nnArray(fileH, array_size[arrIndex], array_element_size[arrIndex]);
break;
case MESS:
break;
default:
@ -393,7 +153,10 @@ void EclFile::loadFormattedArray(const std::string& fileStr, std::size_t arrInde
logi_array[arrIndex] = readFormattedLogiArray(fileStr, array_size[arrIndex], fromPos);
break;
case CHAR:
char_array[arrIndex] = readFormattedCharArray(fileStr, array_size[arrIndex], fromPos);
char_array[arrIndex] = readFormattedCharArray(fileStr, array_size[arrIndex], fromPos, sizeOfChar);
break;
case C0NN:
char_array[arrIndex] = readFormattedCharArray(fileStr, array_size[arrIndex], fromPos, array_element_size[arrIndex]);
break;
case MESS:
break;
@ -449,7 +212,7 @@ void EclFile::loadData(const std::string& name)
inFile.seekg(ifStreamPos[arrIndex]);
char* buffer;
size_t size = sizeOnDiskFormatted(array_size[arrIndex], array_type[arrIndex])+1;
size_t size = sizeOnDiskFormatted(array_size[arrIndex], array_type[arrIndex], array_element_size[arrIndex])+1;
buffer = new char [size];
inFile.read (buffer, size);
@ -494,7 +257,7 @@ void EclFile::loadData(const std::vector<int>& arrIndex)
inFile.seekg(ifStreamPos[ind]);
char* buffer;
size_t size = sizeOnDiskFormatted(array_size[ind], array_type[ind])+1;
size_t size = sizeOnDiskFormatted(array_size[ind], array_type[ind], array_element_size[ind])+1;
buffer = new char [size];
inFile.read (buffer, size);
@ -525,7 +288,6 @@ void EclFile::loadData(const std::vector<int>& arrIndex)
void EclFile::loadData(int arrIndex)
{
if (formatted) {
std::ifstream inFile(inputFilename);
@ -533,7 +295,7 @@ void EclFile::loadData(int arrIndex)
inFile.seekg(ifStreamPos[arrIndex]);
char* buffer;
size_t size = sizeOnDiskFormatted(array_size[arrIndex], array_type[arrIndex])+1;
size_t size = sizeOnDiskFormatted(array_size[arrIndex], array_type[arrIndex], array_element_size[arrIndex])+1;
buffer = new char [size];
inFile.read (buffer, size);
@ -559,6 +321,109 @@ void EclFile::loadData(int arrIndex)
}
}
bool EclFile::is_ix() const
{
// assuming that array data type C0nn only are used in IX. This may change in future.
// Formatted files,
// >> use real arrays. Example Ecl = '0.70000000E-01', IX = '7.0000000E-02'
// Binary files,
// >> if logi array exists in file, look for IX spes binary representation of true value
if (formatted) {
for (size_t n=0; n < array_type.size(); n++) {
if (array_type[n] == Opm::EclIO::C0NN) {
return true;
} else if (array_type[n] == Opm::EclIO::REAL) {
auto realStr = get_fmt_real_raw_str_values(n);
int p, first;
for (auto val : realStr) {
double dtmpv = fabs(std::stod(val));
if (dtmpv > 0.0) {
p = val.find_first_of(".");
first = abs(std::stoi(val.substr(0, p)));
if (first > 0)
return true;
else
return false;
}
}
}
}
} else {
for (size_t n=0; n < array_type.size(); n++) {
if (array_type[n] == Opm::EclIO::C0NN) {
return true;
} else if (array_type[n] == Opm::EclIO::LOGI) {
auto raw_logi_values = get_bin_logi_raw_values(n);
for (unsigned int val : raw_logi_values) {
if (val == Opm::EclIO::true_value_ix)
return true;
}
}
}
return false;
}
return false;
}
std::vector<unsigned int> EclFile::get_bin_logi_raw_values(int arrIndex) const
{
if (array_type[arrIndex] != Opm::EclIO::LOGI)
OPM_THROW(std::runtime_error, "Error, selected array is not of type LOGI");
std::fstream fileH;
fileH.open(inputFilename, std::ios::in | std::ios::binary);
if (!fileH) {
std::string message="Could not open file: '" + inputFilename +"'";
OPM_THROW(std::runtime_error, message);
}
fileH.seekg (ifStreamPos[arrIndex], fileH.beg);
std::vector<unsigned int> raw_logi = readBinaryRawLogiArray(fileH, array_size[arrIndex]);
return raw_logi;
}
std::vector<std::string> EclFile::get_fmt_real_raw_str_values(int arrIndex) const
{
std::vector<std::string> real_vect;
if (array_type[arrIndex] != Opm::EclIO::REAL)
OPM_THROW(std::runtime_error, "Error, selected array is not of type REAL");
std::ifstream inFile(inputFilename);
if (!inFile) {
std::string message="Could not open file: '" + inputFilename +"'";
OPM_THROW(std::runtime_error, message);
}
inFile.seekg(ifStreamPos[arrIndex]);
char* buffer;
size_t size = sizeOnDiskFormatted(array_size[arrIndex], array_type[arrIndex], array_element_size[arrIndex])+1;
buffer = new char [size];
inFile.read (buffer, size);
std::string fileStr = std::string(buffer, size);
std::vector<std::string> real_vect_str;
real_vect_str = readFormattedRealRawStrings(fileStr, array_size[arrIndex], 0);
delete buffer;
return real_vect_str;
}
std::vector<EclFile::EclEntry> EclFile::getList() const
{
std::vector<EclEntry> list;
@ -603,7 +468,12 @@ const std::vector<bool>& EclFile::get<bool>(int arrIndex)
template<>
const std::vector<std::string>& EclFile::get<std::string>(int arrIndex)
{
return getImpl(arrIndex, CHAR, char_array, "string");
if ((array_type[arrIndex] != Opm::EclIO::C0NN) && (array_type[arrIndex] != Opm::EclIO::CHAR)){
std::string message = "Array with index " + std::to_string(arrIndex) + " is not of type " + "std::string";
OPM_THROW(std::runtime_error, message);
}
return getImpl(arrIndex, array_type[arrIndex], char_array, "string");
}
@ -739,7 +609,12 @@ const std::vector<std::string>& EclFile::get<std::string>(const std::string &nam
OPM_THROW(std::invalid_argument, message);
}
return getImpl(search->second, CHAR, char_array, "string");
if ((array_type[search->second] != Opm::EclIO::C0NN) && (array_type[search->second] != Opm::EclIO::CHAR)){
std::string message = "Array with index " + std::to_string(search->second) + " is not of type " + "std::string";
OPM_THROW(std::runtime_error, message);
}
return getImpl(search->second, array_type[search->second], char_array, "string");
}

View File

@ -41,6 +41,7 @@ EclOutput::EclOutput(const std::string& filename,
: isFormatted{formatted}
{
const auto binmode = mode | std::ios_base::binary;
ix_standard = false;
this->ofileH.open(filename, this->isFormatted ? mode : binmode);
}
@ -50,15 +51,79 @@ template<>
void EclOutput::write<std::string>(const std::string& name,
const std::vector<std::string>& data)
{
// array type will be assumed CHAR if maximum string length is 8 or less
// If maximum string length is > 8, C0nn will be used with element size equal to
// maximum string length
int maximum_length = 8;
if (data.size() > 0) {
auto it = std::max_element(data.begin(), data.end(), []
(const std::string& str1, const std::string& str2)
{
return str2.size() > str1.size();
});
maximum_length = it->size();
}
if (isFormatted)
{
writeFormattedHeader(name, data.size(), CHAR);
writeFormattedCharArray(data);
if (maximum_length > sizeOfChar){
writeFormattedHeader(name, data.size(), C0NN, maximum_length);
writeFormattedCharArray(data, maximum_length);
} else {
writeFormattedHeader(name, data.size(), CHAR, sizeOfChar);
writeFormattedCharArray(data, sizeOfChar);
}
}
else
{
writeBinaryHeader(name, data.size(), CHAR);
writeBinaryCharArray(data);
if (maximum_length > sizeOfChar){
writeBinaryHeader(name, data.size(), C0NN, maximum_length);
writeBinaryCharArray(data, maximum_length);
} else {
writeBinaryHeader(name, data.size(), CHAR, sizeOfChar);
writeBinaryCharArray(data, sizeOfChar);
}
}
}
void EclOutput::write(const std::string& name, const std::vector<std::string>& data, int element_size)
{
// array type will be assumed C0NN (not CHAR). Also in cases where element size is 8 or less
if (data.size() > 0) {
auto it = std::max_element(data.begin(), data.end(), []
(const std::string& str1, const std::string& str2)
{
return str2.size() > str1.size();
});
if (it->size() > static_cast<size_t>(element_size))
OPM_THROW(std::runtime_error, "specified element size for type C0NN less than maximum string length in ouput data");
}
if (isFormatted)
{
if (element_size > sizeOfChar){
writeFormattedHeader(name, data.size(), C0NN, element_size);
writeFormattedCharArray(data, element_size);
} else {
writeFormattedHeader(name, data.size(), C0NN, sizeOfChar);
writeFormattedCharArray(data, sizeOfChar);
}
}
else
{
if (element_size > sizeOfChar){
writeBinaryHeader(name, data.size(), C0NN, element_size);
writeBinaryCharArray(data, element_size);
} else {
writeBinaryHeader(name, data.size(), C0NN, sizeOfChar);
writeBinaryCharArray(data, sizeOfChar);
}
}
}
@ -68,11 +133,11 @@ void EclOutput::write<PaddedOutputString<8>>
const std::vector<PaddedOutputString<8>>& data)
{
if (this->isFormatted) {
writeFormattedHeader(name, data.size(), CHAR);
writeFormattedHeader(name, data.size(), CHAR, sizeOfChar);
writeFormattedCharArray(data);
}
else {
writeBinaryHeader(name, data.size(), CHAR);
writeBinaryHeader(name, data.size(), CHAR, sizeOfChar);
writeBinaryCharArray(data);
}
}
@ -91,7 +156,7 @@ void EclOutput::flushStream()
this->ofileH.flush();
}
void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclArrType arrType)
void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclArrType arrType, int element_size)
{
int bhead = flipEndianInt(16);
std::string name = arrName + std::string(8 - arrName.size(),' ');
@ -102,13 +167,13 @@ void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclAr
int64_t x231 = size / val231;
int flippedx231 = flipEndianInt(static_cast<int>( (-1)*x231 ));
ofileH.write(reinterpret_cast<char*>(&bhead), sizeof(bhead));
ofileH.write(name.c_str(), 8);
ofileH.write(reinterpret_cast<char*>(&flippedx231), sizeof(flippedx231));
ofileH.write("X231", 4);
ofileH.write(reinterpret_cast<char*>(&bhead), sizeof(bhead));
size = size - (x231 * val231);
}
@ -119,6 +184,14 @@ void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclAr
ofileH.write(name.c_str(), 8);
ofileH.write(reinterpret_cast<char*>(&flippedSize), sizeof(flippedSize));
std::string c0nn_str;
if (arrType == C0NN){
std::ostringstream ss;
ss << "C" << std::setw(3) << std::setfill('0') << element_size;
c0nn_str = ss.str();
}
switch(arrType) {
case INTE:
ofileH.write("INTE", 4);
@ -135,6 +208,9 @@ void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclAr
case CHAR:
ofileH.write("CHAR", 4);
break;
case C0NN:
ofileH.write(c0nn_str.c_str(), 4);
break;
case MESS:
ofileH.write("MESS", 4);
break;
@ -178,6 +254,8 @@ void EclOutput::writeBinaryArray(const std::vector<T>& data)
OPM_THROW(std::runtime_error, "fstream fileH not open for writing");
}
int logi_true_val = ix_standard ? true_value_ix : true_value_ecl;
rest = size * static_cast<int64_t>(sizeOfElement);
while (rest > 0) {
if (rest > maxBlockSize) {
@ -203,7 +281,7 @@ void EclOutput::writeBinaryArray(const std::vector<T>& data)
value_d = flipEndianDouble(data[n]);
ofileH.write(reinterpret_cast<char*>(&value_d), sizeof(value_d));
} else if (arrType == LOGI) {
intVal = data[n] ? true_value : false_value;
intVal = data[n] ? logi_true_val : false_value;
ofileH.write(reinterpret_cast<char*>(&intVal), sizeOfElement);
} else {
std::cerr << "type not supported in write binaryarray\n";
@ -225,7 +303,7 @@ template void EclOutput::writeBinaryArray<bool>(const std::vector<bool>& data);
template void EclOutput::writeBinaryArray<char>(const std::vector<char>& data);
void EclOutput::writeBinaryCharArray(const std::vector<std::string>& data)
void EclOutput::writeBinaryCharArray(const std::vector<std::string>& data, int element_size)
{
int num,dhead;
@ -234,6 +312,11 @@ void EclOutput::writeBinaryCharArray(const std::vector<std::string>& data)
auto sizeData = block_size_data_binary(CHAR);
if (element_size > sizeOfChar){
std::get<1>(sizeData)= std::get<1>(sizeData) / std::get<0>(sizeData) * element_size;
std::get<0>(sizeData) = element_size;
}
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
@ -258,7 +341,7 @@ void EclOutput::writeBinaryCharArray(const std::vector<std::string>& data)
ofileH.write(reinterpret_cast<char*>(&dhead), sizeof(dhead));
for (int i = 0; i < num; i++) {
std::string tmpStr = data[n] + std::string(8 - data[n].size(),' ');
std::string tmpStr = data[n] + std::string(sizeOfElement - data[n].size(),' ');
ofileH.write(tmpStr.c_str(), sizeOfElement);
n++;
}
@ -303,12 +386,21 @@ void EclOutput::writeBinaryCharArray(const std::vector<PaddedOutputString<8>>& d
}
}
void EclOutput::writeFormattedHeader(const std::string& arrName, int size, eclArrType arrType)
void EclOutput::writeFormattedHeader(const std::string& arrName, int size, eclArrType arrType, int element_size)
{
std::string name = arrName + std::string(8 - arrName.size(),' ');
ofileH << " '" << name << "' " << std::setw(11) << size;
std::string c0nn_str;
if (arrType == C0NN){
std::ostringstream ss;
ss << "C" << std::setw(3) << std::setfill('0') << element_size;
c0nn_str = ss.str();
}
switch (arrType) {
case INTE:
ofileH << " 'INTE'" << std::endl;
@ -325,6 +417,9 @@ void EclOutput::writeFormattedHeader(const std::string& arrName, int size, eclAr
case CHAR:
ofileH << " 'CHAR'" << std::endl;
break;
case C0NN:
ofileH << " '" << c0nn_str << "'" << std::endl;
break;
case MESS:
ofileH << " 'MESS'" << std::endl;
break;
@ -332,7 +427,7 @@ void EclOutput::writeFormattedHeader(const std::string& arrName, int size, eclAr
}
std::string EclOutput::make_real_string(float value) const
std::string EclOutput::make_real_string_ecl(float value) const
{
char buffer [15];
std::sprintf (buffer, "%10.7E", value);
@ -367,11 +462,35 @@ std::string EclOutput::make_real_string(float value) const
}
}
std::string EclOutput::make_doub_string(double value) const
std::string EclOutput::make_real_string_ix(float value) const
{
char buffer [21];
std::sprintf (buffer, "%19.13E", value);
char buffer [15];
std::sprintf (buffer, "%10.7E", value);
if (value == 0.0) {
return " 0.0000000E+00";
} else {
if (std::isnan(value))
return "NAN";
if (std::isinf(value)) {
if (value > 0)
return "INF";
else
return "-INF";
}
std::string tmpstr(buffer);
return tmpstr;
}
}
std::string EclOutput::make_doub_string_ecl(double value) const
{
char buffer [21 + 1];
std::snprintf (buffer, sizeof buffer, "%19.13E", value);
if (value == 0.0) {
return "0.00000000000000D+00";
@ -388,27 +507,52 @@ std::string EclOutput::make_doub_string(double value) const
std::string tmpstr(buffer);
int exp = value < 0.0 ? std::stoi(tmpstr.substr(17, 4)) : std::stoi(tmpstr.substr(16, 4));
const bool use_exp_char = (exp >= -100) && (exp < 99);
if (value < 0.0) {
if (std::abs(exp) < 100) {
if (use_exp_char) {
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13) + "D";
} else {
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13);
}
} else {
if (std::abs(exp) < 100) {
if (use_exp_char) {
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13) + "D";
} else {
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13);
}
}
std::sprintf(buffer, "%+03i", exp + 1);
std::snprintf(buffer, sizeof buffer, "%+03i", exp + 1);
tmpstr = tmpstr + buffer;
return tmpstr;
}
}
std::string EclOutput::make_doub_string_ix(double value) const
{
char buffer [21];
std::sprintf (buffer, "%19.13E", value);
if (value == 0.0) {
return " 0.0000000000000E+00";
} else {
if (std::isnan(value))
return "NAN";
if (std::isinf(value)) {
if (value > 0)
return "INF";
else
return "-INF";
}
std::string tmpstr(buffer);
return tmpstr;
}
}
template <typename T>
void EclOutput::writeFormattedArray(const std::vector<T>& data)
@ -427,6 +571,7 @@ void EclOutput::writeFormattedArray(const std::vector<T>& data)
arrType = LOGI;
}
auto sizeData = block_size_data_formatted(arrType);
int maxBlockSize = std::get<0>(sizeData);
@ -441,10 +586,16 @@ void EclOutput::writeFormattedArray(const std::vector<T>& data)
ofileH << std::setw(columnWidth) << data[i];
break;
case REAL:
ofileH << std::setw(columnWidth) << make_real_string(data[i]);
if (ix_standard)
ofileH << std::setw(columnWidth) << make_real_string_ix(data[i]);
else
ofileH << std::setw(columnWidth) << make_real_string_ecl(data[i]);
break;
case DOUB:
ofileH << std::setw(columnWidth) << make_doub_string(data[i]);
if (ix_standard)
ofileH << std::setw(columnWidth) << make_doub_string_ix(data[i]);
else
ofileH << std::setw(columnWidth) << make_doub_string_ecl(data[i]);
break;
case LOGI:
if (data[i]) {
@ -479,30 +630,50 @@ template void EclOutput::writeFormattedArray<bool>(const std::vector<bool>& data
template void EclOutput::writeFormattedArray<char>(const std::vector<char>& data);
void EclOutput::writeFormattedCharArray(const std::vector<std::string>& data)
void EclOutput::writeFormattedCharArray(const std::vector<std::string>& data, int element_size)
{
auto sizeData = block_size_data_formatted(CHAR);
int maxBlockSize = std::get<0>(sizeData);
int nColumns = std::get<1>(sizeData);
int nColumns;
int size = data.size();
if (element_size < 9)
{
element_size = 8;
nColumns = std::get<1>(sizeData);
} else
nColumns = 80 / (element_size + 3);
for (int i = 0; i < size; i++) {
std::string str1(8,' ');
str1 = data[i] + std::string(8 - data[i].size(),' ');
int rest = data.size();
int n = 0;
ofileH << " '" << str1 << "'";
while (rest > 0) {
int size = rest;
if ((i+1) % nColumns == 0) {
if (size > maxBlockSize)
size = maxBlockSize;
for (int i = 0; i < size; i++) {
std::string str1(element_size,' ');
str1 = data[n] + std::string(element_size - data[n].size(),' ');
n++;
ofileH << " '" << str1 << "'";
if ((i+1) % nColumns == 0) {
ofileH << std::endl;
}
}
if ((size % nColumns) != 0) {
ofileH << std::endl;
}
}
if ((size % nColumns) != 0) {
ofileH << std::endl;
rest = (rest > maxBlockSize) ? rest - maxBlockSize : 0;
}
}
void EclOutput::writeFormattedCharArray(const std::vector<PaddedOutputString<8>>& data)
{
const auto sizeData = block_size_data_formatted(CHAR);

View File

@ -23,10 +23,14 @@
#include <cross-platform/PortableEndian.hpp>
#include <algorithm>
#include <array>
#include <stdexcept>
#include <cmath>
#include <fstream>
#include <cstring>
//temporary
#include <iostream>
int Opm::EclIO::flipEndianInt(int num)
{
@ -61,6 +65,21 @@ double Opm::EclIO::flipEndianDouble(double num)
return value;
}
bool Opm::EclIO::fileExists(const std::string& filename){
std::ifstream fileH(filename.c_str());
return fileH.good();
}
bool Opm::EclIO::isFormatted(const std::string& filename)
{
const auto p = filename.find_last_of(".");
if (p == std::string::npos)
OPM_THROW(std::invalid_argument,
"Purported ECLIPSE Filename'" + filename + "'does not contain extension");
return std::strchr("ABCFGH", static_cast<int>(filename[p+1])) != nullptr;
}
bool Opm::EclIO::isEOF(std::fstream* fileH)
{
int num;
@ -96,6 +115,9 @@ std::tuple<int, int> Opm::EclIO::block_size_data_binary(eclArrType arrType)
case CHAR:
return BlockSizeTuple{sizeOfChar, MaxBlockSizeChar};
break;
case C0NN:
return BlockSizeTuple{sizeOfChar, MaxBlockSizeChar};
break;
case MESS:
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data");
break;
@ -126,6 +148,9 @@ std::tuple<int, int, int> Opm::EclIO::block_size_data_formatted(eclArrType arrTy
case CHAR:
return BlockSizeTuple{MaxNumBlockChar,numColumnsChar, columnWidthChar};
break;
case C0NN:
return BlockSizeTuple{MaxNumBlockChar,numColumnsChar, columnWidthChar};
break;
case MESS:
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data") ;
break;
@ -147,7 +172,7 @@ std::string Opm::EclIO::trimr(const std::string &str1)
}
}
uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrType)
uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrType, int elementSize)
{
uint64_t size = 0;
@ -160,6 +185,11 @@ uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrTyp
if (num > 0) {
auto sizeData = Opm::EclIO::block_size_data_binary(arrType);
if (arrType == Opm::EclIO::C0NN){
std::get<1>(sizeData)= std::get<1>(sizeData) / std::get<0>(sizeData) * elementSize;
std::get<0>(sizeData) = elementSize;
}
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
@ -182,7 +212,7 @@ uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrTyp
return size;
}
uint64_t Opm::EclIO::sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrType arrType)
uint64_t Opm::EclIO::sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrType arrType, int elementSize)
{
uint64_t size = 0;
@ -193,6 +223,11 @@ uint64_t Opm::EclIO::sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrTy
} else {
auto sizeData = block_size_data_formatted(arrType);
if (arrType == Opm::EclIO::C0NN){
std::get<2>(sizeData) = elementSize + 3;
std::get<1>(sizeData) = 80 / std::get<2>(sizeData);
}
int maxBlockSize = std::get<0>(sizeData);
int nColumns = std::get<1>(sizeData);
int columnWidth = std::get<2>(sizeData);
@ -257,7 +292,7 @@ void Opm::EclIO::readBinaryHeader(std::fstream& fileH, std::string& tmpStrName,
}
void Opm::EclIO::readBinaryHeader(std::fstream& fileH, std::string& arrName,
int64_t& size, Opm::EclIO::eclArrType &arrType)
int64_t& size, Opm::EclIO::eclArrType &arrType, int& elementSize)
{
std::string tmpStrName(8,' ');
std::string tmpStrType(4,' ');
@ -282,15 +317,25 @@ void Opm::EclIO::readBinaryHeader(std::fstream& fileH, std::string& arrName,
size = static_cast<int64_t>(tmpSize);
}
elementSize = 4;
arrName = tmpStrName;
if (tmpStrType == "INTE")
arrType = Opm::EclIO::INTE;
else if (tmpStrType == "REAL")
arrType = Opm::EclIO::REAL;
else if (tmpStrType == "DOUB")
else if (tmpStrType == "DOUB"){
arrType = Opm::EclIO::DOUB;
else if (tmpStrType == "CHAR")
elementSize = 8;
}
else if (tmpStrType == "CHAR"){
arrType = Opm::EclIO::CHAR;
elementSize = 8;
}
else if (tmpStrType.substr(0,1)=="C"){
arrType = Opm::EclIO::C0NN;
elementSize = std::stoi(tmpStrType.substr(1,3));
}
else if (tmpStrType =="LOGI")
arrType = Opm::EclIO::LOGI;
else if (tmpStrType == "MESS")
@ -301,7 +346,7 @@ void Opm::EclIO::readBinaryHeader(std::fstream& fileH, std::string& arrName,
void Opm::EclIO::readFormattedHeader(std::fstream& fileH, std::string& arrName,
int64_t &num, Opm::EclIO::eclArrType &arrType)
int64_t &num, Opm::EclIO::eclArrType &arrType, int& elementSize)
{
std::string line;
std::getline(fileH,line);
@ -321,14 +366,24 @@ void Opm::EclIO::readFormattedHeader(std::fstream& fileH, std::string& arrName,
num = std::stol(antStr);
elementSize = 4;
if (arrTypeStr == "INTE")
arrType = Opm::EclIO::INTE;
else if (arrTypeStr == "REAL")
arrType = Opm::EclIO::REAL;
else if (arrTypeStr == "DOUB")
else if (arrTypeStr == "DOUB"){
arrType = Opm::EclIO::DOUB;
else if (arrTypeStr == "CHAR")
elementSize = 8;
}
else if (arrTypeStr == "CHAR"){
arrType = Opm::EclIO::CHAR;
elementSize = 8;
}
else if (arrTypeStr.substr(0,1)=="C"){
arrType = Opm::EclIO::C0NN;
elementSize = std::stoi(arrTypeStr.substr(1,3));
}
else if (arrTypeStr == "LOGI")
arrType = Opm::EclIO::LOGI;
else if (arrTypeStr == "MESS")
@ -340,3 +395,271 @@ void Opm::EclIO::readFormattedHeader(std::fstream& fileH, std::string& arrName,
OPM_THROW(std::runtime_error, "Header name should be 8 characters");
}
}
template<typename T, typename T2>
std::vector<T> Opm::EclIO::readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip, int elementSize)
{
std::vector<T> arr;
auto sizeData = block_size_data_binary(type);
if (type == Opm::EclIO::C0NN){
std::get<1>(sizeData)= std::get<1>(sizeData) / std::get<0>(sizeData) * elementSize;
std::get<0>(sizeData) = elementSize;
}
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
arr.reserve(size);
int64_t rest = size;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
int num = dhead / sizeOfElement;
if ((num > maxNumberOfElements) || (num < 0)) {
OPM_THROW(std::runtime_error, "Error reading binary data, inconsistent header data or incorrect number of elements");
}
for (int i = 0; i < num; i++) {
T2 value;
if constexpr (std::is_same_v<T2, std::string>) {
value.resize(sizeOfElement) ;
fileH.read(&value[0], sizeOfElement);
} else
fileH.read(reinterpret_cast<char*>(&value), sizeOfElement);
arr.push_back(flip(value));
}
rest -= num;
if (( num < maxNumberOfElements && rest != 0) ||
(num == maxNumberOfElements && rest < 0)) {
std::string message = "Error reading binary data, incorrect number of elements";
OPM_THROW(std::runtime_error, message);
}
int dtail;
fileH.read(reinterpret_cast<char*>(&dtail), sizeof(dtail));
dtail = Opm::EclIO::flipEndianInt(dtail);
if (dhead != dtail) {
OPM_THROW(std::runtime_error, "Error reading binary data, tail not matching header.");
}
}
return arr;
}
std::vector<int> Opm::EclIO::readBinaryInteArray(std::fstream &fileH, const int64_t size)
{
std::function<int(int)> f = Opm::EclIO::flipEndianInt;
return readBinaryArray<int,int>(fileH, size, Opm::EclIO::INTE, f, sizeOfInte);
}
std::vector<float> Opm::EclIO::readBinaryRealArray(std::fstream& fileH, const int64_t size)
{
std::function<float(float)> f = Opm::EclIO::flipEndianFloat;
return readBinaryArray<float,float>(fileH, size, Opm::EclIO::REAL, f, sizeOfReal);
}
std::vector<double> Opm::EclIO::readBinaryDoubArray(std::fstream& fileH, const int64_t size)
{
std::function<double(double)> f = Opm::EclIO::flipEndianDouble;
return readBinaryArray<double,double>(fileH, size, Opm::EclIO::DOUB, f, sizeOfDoub);
}
std::vector<bool> Opm::EclIO::readBinaryLogiArray(std::fstream &fileH, const int64_t size)
{
std::function<bool(unsigned int)> f = [](unsigned int intVal)
{
bool value;
if (intVal == Opm::EclIO::true_value_ecl) {
value = true;
} else if (intVal == Opm::EclIO::false_value) {
value = false;
} else if (intVal == Opm::EclIO::true_value_ix) {
value = true;
} else {
OPM_THROW(std::runtime_error, "Error reading logi value");
}
return value;
};
return readBinaryArray<bool,unsigned int>(fileH, size, Opm::EclIO::LOGI, f, sizeOfLogi);
}
std::vector<unsigned int> Opm::EclIO::readBinaryRawLogiArray(std::fstream &fileH, const int64_t size)
{
std::function<unsigned int(unsigned int)> f = [](unsigned int intVal)
{
return intVal;
};
return readBinaryArray<unsigned int, unsigned int>(fileH, size, Opm::EclIO::LOGI, f, sizeOfLogi);
}
std::vector<std::string> Opm::EclIO::readBinaryCharArray(std::fstream& fileH, const int64_t size)
{
using Char8 = std::array<char, 8>;
std::function<std::string(Char8)> f = [](const Char8& val)
{
std::string res(val.begin(), val.end());
return Opm::EclIO::trimr(res);
};
return readBinaryArray<std::string,Char8>(fileH, size, Opm::EclIO::CHAR, f, sizeOfChar);
}
std::vector<std::string> Opm::EclIO::readBinaryC0nnArray(std::fstream& fileH, const int64_t size, int elementSize)
{
std::function<std::string(std::string)> f = [](const std::string& val)
{
return Opm::EclIO::trimr(val);
};
return readBinaryArray<std::string,std::string>(fileH, size, Opm::EclIO::C0NN, f, elementSize);
}
template<typename T>
std::vector<T> Opm::EclIO::readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process)
{
std::vector<T> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_not_of(' ',p1);
int64_t p2 = file_str.find_first_of(' ', p1);
arr.push_back(process(file_str.substr(p1, p2-p1)));
p1 = file_str.find_first_not_of(' ',p2);
}
return arr;
}
std::vector<int> Opm::EclIO::readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<int(const std::string&)> f = [](const std::string& val)
{
return std::stoi(val);
};
return readFormattedArray(file_str, size, fromPos, f);
}
std::vector<std::string> Opm::EclIO::readFormattedCharArray(const std::string& file_str, const int64_t size,
int64_t fromPos, int elementSize)
{
std::vector<std::string> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_of('\'',p1);
std::string value = file_str.substr(p1 + 1, elementSize);
if (value == " ") {
arr.push_back("");
} else {
arr.push_back(Opm::EclIO::trimr(value));
}
p1 = p1 + elementSize + 2;
}
return arr;
}
std::vector<float> Opm::EclIO::readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<float(const std::string&)> f = [](const std::string& val)
{
// tskille: temporary fix, need to be discussed. OPM flow writes numbers
// that are outside valid range for float, and function stof will fail
double dtmpv = std::stod(val);
return dtmpv;
};
return readFormattedArray<float>(file_str, size, fromPos, f);
}
std::vector<std::string> Opm::EclIO::readFormattedRealRawStrings(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<std::string(const std::string&)> f = [](const std::string& val)
{
return val;
};
return readFormattedArray<std::string>(file_str, size, fromPos, f);
}
std::vector<bool> Opm::EclIO::readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<bool(const std::string&)> f = [](const std::string& val)
{
if (val[0] == 'T') {
return true;
} else if (val[0] == 'F') {
return false;
} else {
std::string message="Could not convert '" + val + "' to a bool value ";
OPM_THROW(std::invalid_argument, message);
}
};
return readFormattedArray<bool>(file_str, size, fromPos, f);
}
std::vector<double> Opm::EclIO::readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<double(const std::string&)> f = [](std::string val)
{
auto p1 = val.find_first_of("D");
if (p1 != std::string::npos) {
val.replace(p1,1,"E");
}
p1 = val.find_first_of("E");
if (p1 == std::string::npos) {
auto p2 = val.find_first_of("-+", 1);
if (p2 != std::string::npos)
val = val.insert(p2,"E");
}
return std::stod(val);
};
return readFormattedArray<double>(file_str, size, fromPos, f);
}

View File

@ -15,7 +15,9 @@
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include <opm/io/eclipse/SummaryNode.hpp>
#include <numeric>
#include <regex>
@ -23,8 +25,6 @@
#include <unordered_set>
#include <vector>
#include <opm/io/eclipse/SummaryNode.hpp>
namespace {
constexpr bool use_number(Opm::EclIO::SummaryNode::Category category) {
@ -37,6 +37,7 @@ constexpr bool use_number(Opm::EclIO::SummaryNode::Category category) {
return true;
case Opm::EclIO::SummaryNode::Category::Field: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Group: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Node: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Miscellaneous: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Well:
return false;
@ -51,6 +52,7 @@ constexpr bool use_name(Opm::EclIO::SummaryNode::Category category) {
case Opm::EclIO::SummaryNode::Category::Connection: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Group: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Segment: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Node: [[fallthrough]];
case Opm::EclIO::SummaryNode::Category::Well:
return true;
case Opm::EclIO::SummaryNode::Category::Aquifer: [[fallthrough]];
@ -69,7 +71,23 @@ std::string default_number_renderer(const Opm::EclIO::SummaryNode& node) {
return std::to_string(node.number);
}
};
bool is_node_keyword(const std::string& keyword)
{
static const auto node_kw = std::unordered_set<std::string> {
"GPR",
};
return node_kw.find(keyword) != node_kw.end();
}
Opm::EclIO::SummaryNode::Category
distinguish_group_from_node(const std::string& keyword)
{
return is_node_keyword(keyword)
? Opm::EclIO::SummaryNode::Category::Node
: Opm::EclIO::SummaryNode::Category::Group;
}
}
std::string Opm::EclIO::SummaryNode::unique_key(number_renderer render_number) const {
std::vector<std::string> key_parts { keyword } ;
@ -120,7 +138,7 @@ bool Opm::EclIO::SummaryNode::is_user_defined() const {
"SURFWNUM",
} ;
static const std::regex user_defined_regex { "[ABCFGRSW]U[A-Z]+" } ;
static const std::regex user_defined_regex { "[ABCFGRSW]U[A-Z0-9_]+" } ;
const bool matched { std::regex_match(keyword, user_defined_regex) } ;
const bool blacklisted { udq_blacklist.find(keyword) != udq_blacklist.end() } ;
@ -145,7 +163,7 @@ Opm::EclIO::SummaryNode::Category Opm::EclIO::SummaryNode::category_from_keyword
case 'B': return Category::Block;
case 'C': return Category::Connection;
case 'F': return Category::Field;
case 'G': return Category::Group;
case 'G': return distinguish_group_from_node(keyword);
case 'R': return Category::Region;
case 'S': return Category::Segment;
case 'W': return Category::Well;

View File

@ -32,24 +32,42 @@ namespace RestartIO {
using M = ::Opm::UnitSystem::measure;
double sgrp_value(float raw_value) {
const auto infty = 1.0e+20f;
if (std::abs(raw_value) == infty)
return 0;
else
return raw_value;
}
RstGroup::RstGroup(const ::Opm::UnitSystem& unit_system,
const RstHeader& header,
const std::string* zwel,
const int *,
const int * igrp,
const float * sgrp,
const double * xgrp) :
name(trim_copy(zwel[0])),
oil_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::OilRateLimit])),
water_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::WatRateLimit])),
gas_rate_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::GasRateLimit])),
liquid_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::LiqRateLimit])),
water_surface_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterSurfRateLimit])),
water_reservoir_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterResRateLimit])),
water_reinject_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterReinjectionLimit])),
water_voidage_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterVoidageLimit])),
gas_surface_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::gasSurfRateLimit])),
gas_reservoir_limit( unit_system.to_si(M::geometric_volume_rate, sgrp[VI::SGroup::gasResRateLimit])),
gas_reinject_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::gasReinjectionLimit])),
gas_voidage_limit( unit_system.to_si(M::geometric_volume_rate, sgrp[VI::SGroup::gasVoidageLimit])),
parent_group(igrp[header.nwgmax + VI::IGroup::ParentGroup] ),
prod_active_cmode(igrp[header.nwgmax + VI::IGroup::ProdActiveCMode]),
gconprod_cmode(igrp[header.nwgmax + VI::IGroup::GConProdCMode]),
winj_cmode(igrp[header.nwgmax + VI::IGroup::WInjCMode]),
ginj_cmode(igrp[header.nwgmax + VI::IGroup::GInjCMode]),
guide_rate_def(igrp[header.nwgmax + VI::IGroup::GuideRateDef]),
// The values oil_rate_limit -> gas_voidage_limit will be used in UDA
// values. The UDA values are responsible for unit conversion and raw values
// are internalized here.
oil_rate_limit( sgrp_value(sgrp[VI::SGroup::OilRateLimit])),
water_rate_limit( sgrp_value(sgrp[VI::SGroup::WatRateLimit])),
gas_rate_limit( sgrp_value(sgrp[VI::SGroup::GasRateLimit])),
liquid_rate_limit( sgrp_value(sgrp[VI::SGroup::LiqRateLimit])),
water_surface_limit( sgrp_value(sgrp[VI::SGroup::waterSurfRateLimit])),
water_reservoir_limit( sgrp_value(sgrp[VI::SGroup::waterResRateLimit])),
water_reinject_limit( sgrp_value(sgrp[VI::SGroup::waterReinjectionLimit])),
water_voidage_limit( sgrp_value(sgrp[VI::SGroup::waterVoidageLimit])),
gas_surface_limit( sgrp_value(sgrp[VI::SGroup::gasSurfRateLimit])),
gas_reservoir_limit( sgrp_value(sgrp[VI::SGroup::gasResRateLimit])),
gas_reinject_limit( sgrp_value(sgrp[VI::SGroup::gasReinjectionLimit])),
gas_voidage_limit( sgrp_value(sgrp[VI::SGroup::gasVoidageLimit])),
oil_production_rate( unit_system.to_si(M::liquid_surface_rate, xgrp[VI::XGroup::OilPrRate])),
water_production_rate( unit_system.to_si(M::liquid_surface_rate, xgrp[VI::XGroup::WatPrRate])),
gas_production_rate( unit_system.to_si(M::gas_surface_rate, xgrp[VI::XGroup::GasPrRate])),

View File

@ -23,13 +23,15 @@
#include <opm/output/eclipse/VectorItems/logihead.hpp>
#include <opm/output/eclipse/VectorItems/doubhead.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
using M = ::Opm::UnitSystem::measure;
namespace Opm {
namespace RestartIO {
RstHeader::RstHeader(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead) :
RstHeader::RstHeader(const Opm::UnitSystem& unit_system, const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead) :
nx(intehead[VI::intehead::NX]),
ny(intehead[VI::intehead::NY]),
nz(intehead[VI::intehead::NZ]),
@ -84,6 +86,7 @@ RstHeader::RstHeader(const std::vector<int>& intehead, const std::vector<bool>&
ntfip(intehead[VI::intehead::NTFIP]),
nmfipr(intehead[VI::intehead::NMFIPR]),
ngroup(intehead[VI::intehead::NGRP]),
nwgmax(intehead[VI::intehead::NWGMAX]),
//
e300_radial(logihead[VI::logihead::E300Radial]),
e100_radial(logihead[VI::logihead::E100Radial]),
@ -98,16 +101,19 @@ RstHeader::RstHeader(const std::vector<int>& intehead, const std::vector<bool>&
dir_eps(logihead[VI::logihead::DirEPS]),
reversible_eps(logihead[VI::logihead::RevEPS]),
alt_eps(logihead[VI::logihead::AltEPS]),
group_control_active(intehead[VI::intehead::NGRNPH] == 1),
//
next_timestep1(doubhead[VI::doubhead::TsInit]),
next_timestep2(doubhead[VI::doubhead::TsMaxz]),
max_timestep(doubhead[VI::doubhead::TsMinz]),
next_timestep1(unit_system.to_si(M::time, doubhead[VI::doubhead::TsInit])),
next_timestep2(0),
max_timestep(unit_system.to_si(M::time, doubhead[VI::doubhead::TsMaxz])),
guide_rate_a(doubhead[VI::doubhead::GRpar_a]),
guide_rate_b(doubhead[VI::doubhead::GRpar_b]),
guide_rate_c(doubhead[VI::doubhead::GRpar_c]),
guide_rate_d(doubhead[VI::doubhead::GRpar_d]),
guide_rate_e(doubhead[VI::doubhead::GRpar_e]),
guide_rate_f(doubhead[VI::doubhead::GRpar_f]),
guide_rate_delay(unit_system.to_si(M::time, doubhead[VI::doubhead::GRpar_int])),
guide_rate_damping(doubhead[VI::doubhead::GRpar_damp]),
udq_range(doubhead[VI::doubhead::UdqPar_2]),
udq_undefined(doubhead[VI::doubhead::UdqPar_3]),
udq_eps(doubhead[VI::doubhead::UdqPar_4])

View File

@ -23,6 +23,8 @@
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include "src/opm/parser/eclipse/EclipseState/Schedule/MSW/icd_convert.hpp"
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm {

View File

@ -34,6 +34,16 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm {
namespace RestartIO {
RstState::RstState(const ::Opm::UnitSystem& unit_system_,
const std::vector<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead):
unit_system(unit_system_),
header(unit_system_, intehead, logihead, doubhead)
{
this->load_tuning(intehead, doubhead);
}
RstState::RstState(const ::Opm::UnitSystem& unit_system_,
const std::vector<int>& intehead,
const std::vector<bool>& logihead,
@ -49,11 +59,9 @@ RstState::RstState(const ::Opm::UnitSystem& unit_system_,
const std::vector<int>& icon,
const std::vector<float>& scon,
const std::vector<double>& xcon):
unit_system(unit_system_),
header(intehead, logihead, doubhead)
RstState(unit_system_, intehead, logihead, doubhead)
{
this->add_groups(zgrp, igrp, sgrp, xgrp);
this->load_tuning(intehead, doubhead);
for (int iw = 0; iw < this->header.num_wells; iw++) {
std::size_t zwel_offset = iw * this->header.nzwelz;
@ -99,11 +107,9 @@ RstState::RstState(const ::Opm::UnitSystem& unit_system_,
const std::vector<double>& xcon,
const std::vector<int>& iseg,
const std::vector<double>& rseg) :
unit_system(unit_system_),
header(intehead, logihead, doubhead)
RstState(unit_system_, intehead, logihead, doubhead)
{
this->add_groups(zgrp, igrp, sgrp, xgrp);
this->load_tuning(intehead, doubhead);
for (int iw = 0; iw < this->header.num_wells; iw++) {
std::size_t zwel_offset = iw * this->header.nzwelz;
@ -181,6 +187,7 @@ void RstState::add_groups(const std::vector<std::string>& zgrp,
std::size_t xgrp_offset = ig * this->header.nxgrpz;
this->groups.emplace_back(this->unit_system,
this->header,
zgrp.data() + zgrp_offset,
igrp.data() + igrp_offset,
sgrp.data() + sgrp_offset,
@ -202,43 +209,47 @@ const RstWell& RstState::get_well(const std::string& wname) const {
RstState RstState::load(EclIO::ERst& rst_file, int report_step) {
rst_file.loadReportStepNumber(report_step);
const auto& intehead = rst_file.getRst<int>("INTEHEAD", report_step, 0);
const auto& logihead = rst_file.getRst<bool>("LOGIHEAD", report_step, 0);
const auto& doubhead = rst_file.getRst<double>("DOUBHEAD", report_step, 0);
const auto& zgrp = rst_file.getRst<std::string>("ZGRP", report_step, 0);
const auto& igrp = rst_file.getRst<int>("IGRP", report_step, 0);
const auto& sgrp = rst_file.getRst<float>("SGRP", report_step, 0);
const auto& xgrp = rst_file.getRst<double>("XGRP", report_step, 0);
const auto& zwel = rst_file.getRst<std::string>("ZWEL", report_step, 0);
const auto& iwel = rst_file.getRst<int>("IWEL", report_step, 0);
const auto& swel = rst_file.getRst<float>("SWEL", report_step, 0);
const auto& xwel = rst_file.getRst<double>("XWEL", report_step, 0);
const auto& icon = rst_file.getRst<int>("ICON", report_step, 0);
const auto& scon = rst_file.getRst<float>("SCON", report_step, 0);
const auto& xcon = rst_file.getRst<double>("XCON", report_step, 0);
const auto& intehead = rst_file.getRestartData<int>("INTEHEAD", report_step, 0);
const auto& logihead = rst_file.getRestartData<bool>("LOGIHEAD", report_step, 0);
const auto& doubhead = rst_file.getRestartData<double>("DOUBHEAD", report_step, 0);
auto unit_id = intehead[VI::intehead::UNIT];
::Opm::UnitSystem unit_system(unit_id);
if (rst_file.hasKey("ISEG")) {
const auto& iseg = rst_file.getRst<int>("ISEG", report_step, 0);
const auto& rseg = rst_file.getRst<double>("RSEG", report_step, 0);
if (intehead[VI::intehead::NWELLS] != 0) {
const auto& zgrp = rst_file.getRestartData<std::string>("ZGRP", report_step, 0);
const auto& igrp = rst_file.getRestartData<int>("IGRP", report_step, 0);
const auto& sgrp = rst_file.getRestartData<float>("SGRP", report_step, 0);
const auto& xgrp = rst_file.getRestartData<double>("XGRP", report_step, 0);
return RstState(unit_system,
intehead, logihead, doubhead,
zgrp, igrp, sgrp, xgrp,
zwel, iwel, swel, xwel,
icon, scon, xcon,
iseg, rseg);
const auto& zwel = rst_file.getRestartData<std::string>("ZWEL", report_step, 0);
const auto& iwel = rst_file.getRestartData<int>("IWEL", report_step, 0);
const auto& swel = rst_file.getRestartData<float>("SWEL", report_step, 0);
const auto& xwel = rst_file.getRestartData<double>("XWEL", report_step, 0);
const auto& icon = rst_file.getRestartData<int>("ICON", report_step, 0);
const auto& scon = rst_file.getRestartData<float>("SCON", report_step, 0);
const auto& xcon = rst_file.getRestartData<double>("XCON", report_step, 0);
if (rst_file.hasKey("ISEG")) {
const auto& iseg = rst_file.getRestartData<int>("ISEG", report_step, 0);
const auto& rseg = rst_file.getRestartData<double>("RSEG", report_step, 0);
return RstState(unit_system,
intehead, logihead, doubhead,
zgrp, igrp, sgrp, xgrp,
zwel, iwel, swel, xwel,
icon, scon, xcon,
iseg, rseg);
} else
return RstState(unit_system,
intehead, logihead, doubhead,
zgrp, igrp, sgrp, xgrp,
zwel, iwel, swel, xwel,
icon, scon, xcon);
} else
return RstState(unit_system,
intehead, logihead, doubhead,
zgrp, igrp, sgrp, xgrp,
zwel, iwel, swel, xwel,
icon, scon, xcon);
return RstState(unit_system, intehead, logihead, doubhead);
}
}

View File

@ -61,32 +61,39 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
k1k2( std::make_pair(iwel[VI::IWell::FirstK] - 1, iwel[VI::IWell::LastK] - 1)),
wtype( iwel[VI::IWell::WType], def_ecl_phase),
well_status( iwel[VI::IWell::Status]),
active_control( iwel[VI::IWell::ActWCtrl]),
vfp_table( iwel[VI::IWell::VFPTab]),
pred_requested_control( iwel[VI::IWell::PredReqWCtrl]),
allow_xflow( iwel[VI::IWell::XFlow] == 1),
preferred_phase( iwel[VI::IWell::PreferredPhase]),
hist_requested_control( iwel[VI::IWell::HistReqWCtrl]),
msw_index( iwel[VI::IWell::MsWID]),
completion_ordering( iwel[VI::IWell::CompOrd]),
pvt_table( def_pvt_table),
orat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::OilRateTarget]))),
wrat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::WatRateTarget]))),
grat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::GasRateTarget]))),
lrat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::LiqRateTarget]))),
resv_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::ResVRateTarget]))),
thp_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::THPTarget]))),
bhp_target_float( unit_system.to_si(M::identity, swel[VI::SWell::BHPTarget])),
msw_pressure_drop_model( iwel[VI::IWell::MSW_PlossMod]),
// The values orat_target -> bhp_target_flow will be used in UDA values. The
// UDA values are responsible for unit conversion and raw values are
// internalized here.
orat_target( swel_value(swel[VI::SWell::OilRateTarget])),
wrat_target( swel_value(swel[VI::SWell::WatRateTarget])),
grat_target( swel_value(swel[VI::SWell::GasRateTarget])),
lrat_target( swel_value(swel[VI::SWell::LiqRateTarget])),
resv_target( swel_value(swel[VI::SWell::ResVRateTarget])),
thp_target( swel_value(swel[VI::SWell::THPTarget])),
bhp_target_float( swel[VI::SWell::BHPTarget]),
hist_lrat_target( unit_system.to_si(M::liquid_surface_rate, swel[VI::SWell::HistLiqRateTarget])),
hist_grat_target( unit_system.to_si(M::gas_surface_rate, swel[VI::SWell::HistGasRateTarget])),
hist_bhp_target( unit_system.to_si(M::pressure, swel[VI::SWell::HistBHPTarget])),
datum_depth( unit_system.to_si(M::length, swel[VI::SWell::DatumDepth])),
drainage_radius( unit_system.to_si(M::length, swel_value(swel[VI::SWell::DrainageRadius]))),
efficiency_factor( unit_system.to_si(M::identity, swel[VI::SWell::EfficiencyFactor1])),
alq_value( swel[VI::SWell::Alq_value]),
oil_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::OilPrRate])),
water_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::WatPrRate])),
gas_rate( unit_system.to_si(M::gas_surface_rate, xwel[VI::XWell::GasPrRate])),
liquid_rate( unit_system.to_si(M::rate, xwel[VI::XWell::LiqPrRate])),
void_rate( unit_system.to_si(M::rate, xwel[VI::XWell::VoidPrRate])),
thp( unit_system.to_si(M::pressure, xwel[VI::XWell::TubHeadPr])),
flow_bhp( unit_system.to_si(M::pressure, xwel[VI::XWell::FlowBHP])),
wct( unit_system.to_si(M::water_cut, xwel[VI::XWell::WatCut])),
gor( unit_system.to_si(M::gas_oil_ratio, xwel[VI::XWell::GORatio])),

View File

@ -129,7 +129,7 @@ Well::Well(const RestartIO::RstWell& rst_well,
guide_rate(def_guide_rate),
efficiency_factor(rst_well.efficiency_factor),
solvent_fraction(def_solvent_fraction),
prediction_mode(rst_well.pred_requested_control != 0),
// prediction_mode(rst_well.pred_requested_control != 0),
econ_limits(std::make_shared<WellEconProductionLimits>()),
foam_properties(std::make_shared<WellFoamProperties>()),
polymer_properties(std::make_shared<WellPolymerProperties>()),