mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#7512 Support optimized summary reader
This commit is contained in:
parent
53dbb33e86
commit
f5547dd551
@ -403,6 +403,33 @@ RiaPreferences::RiaPreferences( void )
|
|||||||
m_multiLateralWellPattern.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
|
m_multiLateralWellPattern.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
|
||||||
|
|
||||||
CAF_PDM_InitFieldNoDefault( &m_guiTheme, "guiTheme", "GUI theme", "", "", "" );
|
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 ||
|
if ( field == &octaveShowHeaderInfoWhenExecutingScripts || field == &autocomputeDepthRelatedProperties ||
|
||||||
field == &loadAndShowSoil || field == &m_useShaders || field == &m_showHud ||
|
field == &loadAndShowSoil || field == &m_useShaders || field == &m_showHud ||
|
||||||
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText ||
|
field == &m_appendClassNameToUiText || field == &m_appendFieldKeywordToToolTipText || field == &m_showTestToolbar ||
|
||||||
field == &m_showTestToolbar || field == &m_includeFractureDebugInfoFile ||
|
field == &m_includeFractureDebugInfoFile || field == &showLasCurveWithoutTvdWarning ||
|
||||||
field == &showLasCurveWithoutTvdWarning || field == &holoLensDisableCertificateVerification ||
|
field == &holoLensDisableCertificateVerification || field == &m_showProjectChangedDialog ||
|
||||||
field == &m_showProjectChangedDialog || field == &m_searchPlotTemplateFoldersRecursively ||
|
field == &m_searchPlotTemplateFoldersRecursively || field == &m_showLegendBackground ||
|
||||||
field == &m_showLegendBackground || field == &m_showSummaryTimeAsLongString ||
|
field == &m_showSummaryTimeAsLongString || field == &m_showViewIdInProjectTree ||
|
||||||
field == &m_showViewIdInProjectTree || field == &m_useMultipleThreadsWhenLoadingSummaryData ||
|
field == &m_useMultipleThreadsWhenLoadingSummaryData || field == &m_enableFaultsByDefault ||
|
||||||
field == &m_enableFaultsByDefault || field == &m_showProgressBar || field == &m_openExportedPdfInViewer ||
|
field == &m_showProgressBar || field == &m_openExportedPdfInViewer || field == &m_showInfoBox ||
|
||||||
field == &m_showInfoBox || field == &m_showGridBox || field == &m_useUndoRedo )
|
field == &m_showGridBox || field == &m_useUndoRedo || field == &m_useOptimizedSummaryDataFileReader ||
|
||||||
|
field == &m_createOptimizedSummaryDataFile || field == &m_useOptimizedSummaryDataFile )
|
||||||
{
|
{
|
||||||
caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast<caf::PdmUiCheckBoxEditorAttribute*>( attribute );
|
caf::PdmUiCheckBoxEditorAttribute* myAttr = dynamic_cast<caf::PdmUiCheckBoxEditorAttribute*>( attribute );
|
||||||
if ( myAttr )
|
if ( myAttr )
|
||||||
@ -576,6 +604,18 @@ void RiaPreferences::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering&
|
|||||||
m_pageRightMargin.uiCapability()->setUiName( "Right Margin" + unitLabel );
|
m_pageRightMargin.uiCapability()->setUiName( "Right Margin" + unitLabel );
|
||||||
m_pageTopMargin.uiCapability()->setUiName( "Top Margin" + unitLabel );
|
m_pageTopMargin.uiCapability()->setUiName( "Top Margin" + unitLabel );
|
||||||
m_pageBottomMargin.uiCapability()->setUiName( "Bottom 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() )
|
else if ( uiConfigName == RiaPreferences::tabNameScripting() )
|
||||||
@ -1171,6 +1211,30 @@ QString RiaPreferences::octaveExecutable() const
|
|||||||
return m_octaveExecutable().trimmed();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
@ -138,6 +138,11 @@ public:
|
|||||||
QString pythonExecutable() const;
|
QString pythonExecutable() const;
|
||||||
QString octaveExecutable() const;
|
QString octaveExecutable() const;
|
||||||
|
|
||||||
|
// Summary readers
|
||||||
|
bool useOptimizedSummaryDataReader() const;
|
||||||
|
bool useOptimizedSummaryDataFiles() const;
|
||||||
|
bool createOptimizedSummaryDataFiles() const;
|
||||||
|
|
||||||
public: // Pdm Fields
|
public: // Pdm Fields
|
||||||
caf::PdmField<bool> enableGrpcServer;
|
caf::PdmField<bool> enableGrpcServer;
|
||||||
caf::PdmField<int> defaultGrpcPortNumber;
|
caf::PdmField<int> defaultGrpcPortNumber;
|
||||||
@ -243,6 +248,11 @@ private:
|
|||||||
// Well Path Import
|
// Well Path Import
|
||||||
caf::PdmField<QString> m_multiLateralWellPattern;
|
caf::PdmField<QString> m_multiLateralWellPattern;
|
||||||
|
|
||||||
|
// Summary data
|
||||||
|
caf::PdmField<bool> m_useOptimizedSummaryDataFileReader;
|
||||||
|
caf::PdmField<bool> m_createOptimizedSummaryDataFile;
|
||||||
|
caf::PdmField<bool> m_useOptimizedSummaryDataFile;
|
||||||
|
|
||||||
// 3d view
|
// 3d view
|
||||||
caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType;
|
caf::PdmField<caf::AppEnum<RiaDefines::MeshModeType>> m_defaultMeshModeType;
|
||||||
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> m_navigationPolicy;
|
caf::PdmField<caf::AppEnum<RiaGuiApplication::RINavigationPolicy>> m_navigationPolicy;
|
||||||
|
@ -60,6 +60,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter.h
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.h
|
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelPerfsFrkExporter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.h
|
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.h
|
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
# 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}/RifStimPlanModelPerfsFrkExporter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelAsymmetricFrkExporter.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifSurfaceExporter.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifOpmCommonSummary.cpp
|
||||||
|
|
||||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
||||||
|
245
ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp
Normal file
245
ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp
Normal 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();
|
||||||
|
}
|
85
ApplicationLibCode/FileInterface/RifOpmCommonSummary.h
Normal file
85
ApplicationLibCode/FileInterface/RifOpmCommonSummary.h
Normal 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;
|
||||||
|
};
|
@ -19,10 +19,13 @@
|
|||||||
#include "RifReaderEclipseSummary.h"
|
#include "RifReaderEclipseSummary.h"
|
||||||
|
|
||||||
#include "RiaFilePathTools.h"
|
#include "RiaFilePathTools.h"
|
||||||
|
#include "RiaLogging.h"
|
||||||
|
#include "RiaPreferences.h"
|
||||||
#include "RiaStdStringTools.h"
|
#include "RiaStdStringTools.h"
|
||||||
#include "RiaStringEncodingTools.h"
|
#include "RiaStringEncodingTools.h"
|
||||||
|
|
||||||
#include "RifEclipseSummaryTools.h"
|
#include "RifEclipseSummaryTools.h"
|
||||||
|
#include "RifOpmCommonSummary.h"
|
||||||
#include "RifReaderEclipseOutput.h"
|
#include "RifReaderEclipseOutput.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -86,7 +89,7 @@ ecl_sum_type* openEclSum( const QString& inHeaderFileName, bool includeRestartFi
|
|||||||
QString nativeHeaderFileName = QDir::toNativeSeparators( inHeaderFileName );
|
QString nativeHeaderFileName = QDir::toNativeSeparators( inHeaderFileName );
|
||||||
RifEclipseSummaryTools::findSummaryFiles( nativeHeaderFileName, &headerFileName, &dataFileNames );
|
RifEclipseSummaryTools::findSummaryFiles( nativeHeaderFileName, &headerFileName, &dataFileNames );
|
||||||
|
|
||||||
if ( headerFileName.isEmpty() || dataFileNames.size() == 0 ) return nullptr;
|
if ( headerFileName.isEmpty() || dataFileNames.isEmpty() ) return nullptr;
|
||||||
|
|
||||||
assert( !headerFileName.isEmpty() );
|
assert( !headerFileName.isEmpty() );
|
||||||
assert( dataFileNames.size() > 0 );
|
assert( dataFileNames.size() > 0 );
|
||||||
@ -126,7 +129,7 @@ RifReaderEclipseSummary::RifReaderEclipseSummary()
|
|||||||
, m_ecl_SmSpec( nullptr )
|
, m_ecl_SmSpec( nullptr )
|
||||||
, m_unitSystem( RiaDefines::EclipseUnitSystem::UNITS_METRIC )
|
, 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 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 );
|
assert( m_ecl_sum == nullptr );
|
||||||
|
|
||||||
m_ecl_sum = openEclSum( headerFileName, includeRestartFiles );
|
m_ecl_sum = openEclSum( headerFileName, includeRestartFiles );
|
||||||
@ -241,7 +268,7 @@ RifRestartFileInfo RifReaderEclipseSummary::getFileInfo( const QString& headerFi
|
|||||||
RifRestartFileInfo fileInfo;
|
RifRestartFileInfo fileInfo;
|
||||||
ecl_sum_type* ecl_sum = openEclSum( headerFileName, false );
|
ecl_sum_type* ecl_sum = openEclSum( headerFileName, false );
|
||||||
std::vector<time_t> timeSteps = getTimeSteps( ecl_sum );
|
std::vector<time_t> timeSteps = getTimeSteps( ecl_sum );
|
||||||
if ( timeSteps.size() > 0 )
|
if ( !timeSteps.empty() )
|
||||||
{
|
{
|
||||||
fileInfo.fileName = headerFileName;
|
fileInfo.fileName = headerFileName;
|
||||||
fileInfo.startDate = timeSteps.front();
|
fileInfo.startDate = timeSteps.front();
|
||||||
@ -426,21 +453,32 @@ RifEclipseSummaryAddress addressFromErtSmSpecNode( const ecl::smspec_node& ertSu
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
bool RifReaderEclipseSummary::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||||
{
|
{
|
||||||
assert( m_ecl_sum != nullptr );
|
|
||||||
|
|
||||||
values->clear();
|
values->clear();
|
||||||
values->reserve( timeStepCount() );
|
values->reserve( timeStepCount() );
|
||||||
|
|
||||||
|
// assert( m_ecl_sum != nullptr );
|
||||||
|
|
||||||
const std::vector<double>& cachedValues = m_valuesCache->getValues( resultAddress );
|
const std::vector<double>& cachedValues = m_valuesCache->getValues( resultAddress );
|
||||||
if ( !cachedValues.empty() )
|
if ( !cachedValues.empty() )
|
||||||
{
|
{
|
||||||
values->insert( values->begin(), cachedValues.begin(), cachedValues.end() );
|
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 ) )
|
if ( m_differenceAddresses.count( resultAddress ) )
|
||||||
{
|
{
|
||||||
std::string quantityName = resultAddress.quantityName();
|
const std::string& quantityName = resultAddress.quantityName();
|
||||||
auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) +
|
auto historyQuantity = quantityName.substr( 0, quantityName.size() - differenceIdentifier().size() ) +
|
||||||
historyIdentifier();
|
historyIdentifier();
|
||||||
|
|
||||||
@ -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 );
|
assert( m_ecl_sum != nullptr );
|
||||||
|
|
||||||
if ( m_ecl_SmSpec == nullptr ) return 0;
|
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
|
const std::vector<time_t>& RifReaderEclipseSummary::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||||
{
|
{
|
||||||
assert( m_ecl_sum != nullptr );
|
// assert( m_ecl_sum != nullptr );
|
||||||
|
|
||||||
return m_timeSteps;
|
return m_timeSteps;
|
||||||
}
|
}
|
||||||
@ -535,6 +578,15 @@ void RifReaderEclipseSummary::buildMetaData()
|
|||||||
m_allResultAddresses.clear();
|
m_allResultAddresses.clear();
|
||||||
m_resultAddressToErtNodeIdx.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 )
|
if ( m_ecl_SmSpec )
|
||||||
{
|
{
|
||||||
int varCount = ecl_smspec_num_nodes( m_ecl_SmSpec );
|
int varCount = ecl_smspec_num_nodes( m_ecl_SmSpec );
|
||||||
@ -556,7 +608,7 @@ void RifReaderEclipseSummary::buildMetaData()
|
|||||||
RifEclipseSummaryAddress adrWithoutHistory;
|
RifEclipseSummaryAddress adrWithoutHistory;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string s = adr.quantityName();
|
const std::string& s = adr.quantityName();
|
||||||
if ( !RiaStdStringTools::endsWith( s, historyIdentifier() ) )
|
if ( !RiaStdStringTools::endsWith( s, historyIdentifier() ) )
|
||||||
{
|
{
|
||||||
RifEclipseSummaryAddress candidate = adr;
|
RifEclipseSummaryAddress candidate = adr;
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class RifOpmCommonEclipseSummary;
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@ -82,7 +84,7 @@ public:
|
|||||||
static const std::string historyIdentifier() { return "H"; }
|
static const std::string historyIdentifier() { return "H"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int timeStepCount() const;
|
size_t timeStepCount() const;
|
||||||
int indexFromAddress( const RifEclipseSummaryAddress& resultAddress ) const;
|
int indexFromAddress( const RifEclipseSummaryAddress& resultAddress ) const;
|
||||||
void buildMetaData();
|
void buildMetaData();
|
||||||
RifRestartFileInfo getRestartFile( const QString& headerFileName );
|
RifRestartFileInfo getRestartFile( const QString& headerFileName );
|
||||||
@ -104,6 +106,8 @@ private:
|
|||||||
|
|
||||||
std::set<RifEclipseSummaryAddress> m_differenceAddresses;
|
std::set<RifEclipseSummaryAddress> m_differenceAddresses;
|
||||||
|
|
||||||
|
std::unique_ptr<RifOpmCommonEclipseSummary> m_opmCommonReader;
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
//
|
//
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
@ -15,13 +15,15 @@
|
|||||||
// for more details.
|
// for more details.
|
||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "RimSummaryCaseMainCollection.h"
|
#include "RimSummaryCaseMainCollection.h"
|
||||||
|
|
||||||
|
#include "RiaLogging.h"
|
||||||
#include "RiaSummaryTools.h"
|
#include "RiaSummaryTools.h"
|
||||||
#include "RimSummaryPlotCollection.h"
|
|
||||||
|
|
||||||
#include "RifCaseRealizationParametersReader.h"
|
#include "RifCaseRealizationParametersReader.h"
|
||||||
#include "RifEclipseSummaryTools.h"
|
#include "RifEclipseSummaryTools.h"
|
||||||
|
#include "RifOpmCommonSummary.h"
|
||||||
#include "RifSummaryCaseRestartSelector.h"
|
#include "RifSummaryCaseRestartSelector.h"
|
||||||
|
|
||||||
#include "RimCaseDisplayNameTools.h"
|
#include "RimCaseDisplayNameTools.h"
|
||||||
@ -35,8 +37,10 @@
|
|||||||
#include "RimSummaryCaseCollection.h"
|
#include "RimSummaryCaseCollection.h"
|
||||||
#include "RimSummaryCurve.h"
|
#include "RimSummaryCurve.h"
|
||||||
#include "RimSummaryPlot.h"
|
#include "RimSummaryPlot.h"
|
||||||
|
#include "RimSummaryPlotCollection.h"
|
||||||
|
|
||||||
#include "cafProgressInfo.h"
|
#include "cafProgressInfo.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
CAF_PDM_SOURCE_INIT( RimSummaryCaseMainCollection, "SummaryCaseCollection" );
|
CAF_PDM_SOURCE_INIT( RimSummaryCaseMainCollection, "SummaryCaseCollection" );
|
||||||
@ -435,6 +439,8 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vector<RimFileS
|
|||||||
|
|
||||||
caf::ProgressInfo progInfo( fileSummaryCases.size(), "Loading Summary Cases" );
|
caf::ProgressInfo progInfo( fileSummaryCases.size(), "Loading Summary Cases" );
|
||||||
|
|
||||||
|
RifOpmCommonEclipseSummary::resetLodCount();
|
||||||
|
|
||||||
#pragma omp parallel for schedule( dynamic )
|
#pragma omp parallel for schedule( dynamic )
|
||||||
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
|
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
|
||||||
{
|
{
|
||||||
@ -447,6 +453,13 @@ void RimSummaryCaseMainCollection::loadFileSummaryCaseData( std::vector<RimFileS
|
|||||||
progInfo.setProgress( cIdx );
|
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 )
|
for ( int cIdx = 0; cIdx < static_cast<int>( fileSummaryCases.size() ); ++cIdx )
|
||||||
{
|
{
|
||||||
RimFileSummaryCase* fileSummaryCase = fileSummaryCases[cIdx];
|
RimFileSummaryCase* fileSummaryCase = fileSummaryCases[cIdx];
|
||||||
|
@ -74,6 +74,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools-Test.cpp
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanXmlReader-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanXmlReader-Test.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RigWellPathGeometryExporter-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RigWellPathGeometryExporter-Test.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter-Test.cpp
|
${CMAKE_CURRENT_LIST_DIR}/RifStimPlanModelDeviationFrkExporter-Test.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/RifSummaryDataReader-Test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (RESINSIGHT_ENABLE_GRPC)
|
if (RESINSIGHT_ENABLE_GRPC)
|
||||||
|
113
ApplicationLibCode/UnitTests/RifSummaryDataReader-Test.cpp
Normal file
113
ApplicationLibCode/UnitTests/RifSummaryDataReader-Test.cpp
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
ThirdParty/custom-opm-common/CMakeLists.txt
vendored
4
ThirdParty/custom-opm-common/CMakeLists.txt
vendored
@ -78,6 +78,8 @@ add_library(${PROJECT_NAME}
|
|||||||
opm-common/src/opm/io/eclipse/EclOutput.cpp
|
opm-common/src/opm/io/eclipse/EclOutput.cpp
|
||||||
opm-common/src/opm/io/eclipse/EclUtil.cpp
|
opm-common/src/opm/io/eclipse/EclUtil.cpp
|
||||||
opm-common/src/opm/io/eclipse/EGrid.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
|
# Required for use of static function RstConnection::inverse_peaceman
|
||||||
opm-common/src/opm/io/eclipse/rst/connection.cpp
|
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/Well/WListManager.cpp
|
||||||
opm-common/src/opm/parser/eclipse/EclipseState/Schedule/MSW/SpiralICD.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/EclOutput.cpp
|
||||||
|
opm-common/src/opm/io/eclipse/ESmry.cpp
|
||||||
|
opm-common/src/opm/io/eclipse/EGrid.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(fileToExclude ${UNITY_EXCLUDE_FILES})
|
foreach(fileToExclude ${UNITY_EXCLUDE_FILES})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include "Substitutes.hpp"
|
#include "Substitutes.hpp"
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
fnmatch(const char* pattern, const char* string, int flags)
|
fnmatch(const char* pattern, const char* string, int flags)
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <Shlwapi.h>
|
|
||||||
#define NOMINMAX
|
|
||||||
#include <windows.h>
|
|
||||||
#undef NOMINMAX
|
|
||||||
// IGNORE is used in InputErrorAction.hpp, as an enum value,
|
// 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.
|
// 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.
|
// It is not required here, so we can undefine it.
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define OPM_IO_EGRID_HPP
|
#define OPM_IO_EGRID_HPP
|
||||||
|
|
||||||
#include <opm/io/eclipse/EclFile.hpp>
|
#include <opm/io/eclipse/EclFile.hpp>
|
||||||
|
#include <opm/common/utility/FileSystem.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -34,7 +35,7 @@ namespace Opm { namespace EclIO {
|
|||||||
class EGrid : public EclFile
|
class EGrid : public EclFile
|
||||||
{
|
{
|
||||||
public:
|
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 global_index(int i, int j, int k) const;
|
||||||
int active_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_active_index(int actInd) const;
|
||||||
std::array<int, 3> ijk_from_global_index(int globInd) 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(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) const;
|
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 activeCells() const { return nactive; }
|
||||||
int totalNumberOfCells() const { return nijk[0] * nijk[1] * nijk[2]; }
|
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:
|
private:
|
||||||
|
Opm::filesystem::path inputFileName, initFileName;
|
||||||
|
std::string m_grid_name;
|
||||||
|
bool m_radial;
|
||||||
|
|
||||||
std::array<int, 3> nijk;
|
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> act_index;
|
||||||
std::vector<int> glob_index;
|
std::vector<int> glob_index;
|
||||||
|
|
||||||
std::vector<float> coord_array;
|
std::vector<float> coord_array;
|
||||||
std::vector<float> zcorn_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
|
}} // namespace Opm::EclIO
|
||||||
|
102
ThirdParty/custom-opm-common/opm-common/opm/io/eclipse/EInit.hpp
vendored
Normal file
102
ThirdParty/custom-opm-common/opm-common/opm/io/eclipse/EInit.hpp
vendored
Normal 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
|
@ -27,6 +27,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace Opm { namespace EclIO { namespace OutputStream {
|
namespace Opm { namespace EclIO { namespace OutputStream {
|
||||||
class Restart;
|
class Restart;
|
||||||
}}}
|
}}}
|
||||||
@ -37,38 +38,68 @@ class ERst : public EclFile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ERst(const std::string& filename);
|
explicit ERst(const std::string& filename);
|
||||||
|
|
||||||
bool hasReportStepNumber(int number) const;
|
bool hasReportStepNumber(int number) const;
|
||||||
|
bool hasLGR(const std::string& gridname, int reportStepNumber) const;
|
||||||
|
|
||||||
void loadReportStepNumber(int number);
|
void loadReportStepNumber(int number);
|
||||||
|
|
||||||
template <typename T>
|
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>
|
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);
|
auto indRange = this->getIndexRange(reportStepNumber);
|
||||||
return this->get<T>(index + std::get<0>(indRange));
|
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(); };
|
size_t numberOfReportSteps() const { return seqnum.size(); };
|
||||||
|
|
||||||
const std::vector<int>& listOfReportStepNumbers() const { return seqnum; }
|
const std::vector<int>& listOfReportStepNumbers() const { return seqnum; }
|
||||||
|
|
||||||
std::vector<EclEntry> listOfRstArrays(int reportStepNumber);
|
std::vector<EclEntry> listOfRstArrays(int reportStepNumber);
|
||||||
|
std::vector<EclEntry> listOfRstArrays(int reportStepNumber, const std::string& lgr_name);
|
||||||
|
|
||||||
friend class OutputStream::Restart;
|
friend class OutputStream::Restart;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int nReports;
|
int nReports;
|
||||||
std::vector<int> seqnum; // report step numbers, from SEQNUM array in restart file
|
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::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 initUnified();
|
||||||
void initSeparate(const int number);
|
void initSeparate(const int number);
|
||||||
|
|
||||||
int getArrayIndex(const std::string& name, int seqnum, int occurrence) 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::tuple<int,int> getIndexRange(int reportStepNumber) const;
|
||||||
|
|
||||||
std::streampos
|
std::streampos
|
||||||
|
@ -40,7 +40,7 @@ class ESmry
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// input is smspec (or fsmspec file)
|
// 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; }
|
int numberOfVectors() const { return nVect; }
|
||||||
|
|
||||||
@ -57,6 +57,11 @@ public:
|
|||||||
void LoadData(const std::vector<std::string>& vectList) const;
|
void LoadData(const std::vector<std::string>& vectList) const;
|
||||||
void LoadData() 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; }
|
std::chrono::system_clock::time_point startdate() const { return startdat; }
|
||||||
|
|
||||||
const std::vector<std::string>& keywordList() const;
|
const std::vector<std::string>& keywordList() const;
|
||||||
@ -65,7 +70,7 @@ public:
|
|||||||
|
|
||||||
int timestepIdxAtReportstepStart(const int reportStep) const;
|
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 std::string& name) const;
|
||||||
const std::string& get_unit(const SummaryNode& node) const;
|
const std::string& get_unit(const SummaryNode& node) const;
|
||||||
@ -73,10 +78,16 @@ public:
|
|||||||
void write_rsm(std::ostream&) const;
|
void write_rsm(std::ostream&) const;
|
||||||
void write_rsm_file(std::optional<Opm::filesystem::path> = std::nullopt) 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:
|
private:
|
||||||
Opm::filesystem::path inputFileName;
|
|
||||||
|
bool useLodsmryFile; // Added by ResInsight use
|
||||||
|
|
||||||
|
Opm::filesystem::path inputFileName, lodFileName;
|
||||||
int nI, nJ, nK, nSpecFiles;
|
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<bool> formattedFiles;
|
||||||
std::vector<std::string> dataFileList;
|
std::vector<std::string> dataFileList;
|
||||||
@ -92,7 +103,6 @@ private:
|
|||||||
|
|
||||||
std::vector<int> seqIndex;
|
std::vector<int> seqIndex;
|
||||||
|
|
||||||
void ijk_from_global_index(int glob, int &i, int &j, int &k) const;
|
|
||||||
|
|
||||||
std::vector<SummaryNode> summaryNodes;
|
std::vector<SummaryNode> summaryNodes;
|
||||||
std::unordered_map<std::string, std::string> kwunits;
|
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<std::tuple <std::string, uint64_t>> getListOfArrays(std::string filename, bool formatted);
|
||||||
std::vector<int> makeKeywPosVector(int speInd) const;
|
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
|
}} // namespace Opm::EclIO
|
||||||
|
@ -36,7 +36,7 @@ class EclFile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EclFile(const std::string& filename, bool preload = false);
|
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(); // load all data
|
||||||
void loadData(const std::string& arrName); // load all arrays with array name equal to arrName
|
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>;
|
using EclEntry = std::tuple<std::string, eclArrType, int64_t>;
|
||||||
std::vector<EclEntry> getList() const;
|
std::vector<EclEntry> getList() const;
|
||||||
|
|
||||||
|
const std::vector<int>& getElementSizeList() const { return array_element_size; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const std::vector<T>& get(int arrIndex);
|
const std::vector<T>& get(int arrIndex);
|
||||||
|
|
||||||
@ -66,6 +68,7 @@ public:
|
|||||||
|
|
||||||
const std::vector<std::string>& arrayNames() const { return array_name; }
|
const std::vector<std::string>& arrayNames() const { return array_name; }
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
|
bool is_ix() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool formatted;
|
bool formatted;
|
||||||
@ -80,6 +83,7 @@ protected:
|
|||||||
std::vector<std::string> array_name;
|
std::vector<std::string> array_name;
|
||||||
std::vector<eclArrType> array_type;
|
std::vector<eclArrType> array_type;
|
||||||
std::vector<int64_t> array_size;
|
std::vector<int64_t> array_size;
|
||||||
|
std::vector<int> array_element_size;
|
||||||
|
|
||||||
std::vector<uint64_t> ifStreamPos;
|
std::vector<uint64_t> ifStreamPos;
|
||||||
|
|
||||||
@ -111,6 +115,9 @@ private:
|
|||||||
void loadBinaryArray(std::fstream& fileH, std::size_t arrIndex);
|
void loadBinaryArray(std::fstream& fileH, std::size_t arrIndex);
|
||||||
void loadFormattedArray(const std::string& fileStr, std::size_t arrIndex, int64_t fromPos);
|
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
|
}} // namespace Opm::EclIO
|
||||||
|
@ -26,13 +26,15 @@ namespace Opm { namespace EclIO {
|
|||||||
|
|
||||||
// type MESS have no assisiated data
|
// type MESS have no assisiated data
|
||||||
enum eclArrType {
|
enum eclArrType {
|
||||||
INTE, REAL, DOUB, CHAR, LOGI, MESS
|
INTE, REAL, DOUB, CHAR, LOGI, MESS, C0NN
|
||||||
};
|
};
|
||||||
|
|
||||||
// named constants related to binary file format
|
// 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 unsigned int false_value = 0x00000000;
|
||||||
|
|
||||||
|
|
||||||
const int sizeOfInte = 4; // number of bytes pr integer (inte) element
|
const int sizeOfInte = 4; // number of bytes pr integer (inte) element
|
||||||
const int sizeOfReal = 4; // number of bytes pr float (real) 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 sizeOfDoub = 8; // number of bytes pr double (doub) element
|
||||||
|
@ -47,59 +47,71 @@ public:
|
|||||||
const std::vector<T>& data)
|
const std::vector<T>& data)
|
||||||
{
|
{
|
||||||
eclArrType arrType = MESS;
|
eclArrType arrType = MESS;
|
||||||
|
int element_size = 4;
|
||||||
|
|
||||||
if (typeid(T) == typeid(int))
|
if (typeid(T) == typeid(int))
|
||||||
arrType = INTE;
|
arrType = INTE;
|
||||||
else if (typeid(T) == typeid(float))
|
else if (typeid(T) == typeid(float))
|
||||||
arrType = REAL;
|
arrType = REAL;
|
||||||
else if (typeid(T) == typeid(double))
|
else if (typeid(T) == typeid(double)){
|
||||||
arrType = DOUB;
|
arrType = DOUB;
|
||||||
else if (typeid(T) == typeid(bool))
|
element_size = 8;
|
||||||
|
} else if (typeid(T) == typeid(bool))
|
||||||
arrType = LOGI;
|
arrType = LOGI;
|
||||||
else if (typeid(T) == typeid(char))
|
else if (typeid(T) == typeid(char))
|
||||||
arrType = MESS;
|
arrType = MESS;
|
||||||
|
|
||||||
if (isFormatted)
|
if (isFormatted)
|
||||||
{
|
{
|
||||||
writeFormattedHeader(name, data.size(), arrType);
|
writeFormattedHeader(name, data.size(), arrType, element_size);
|
||||||
if (arrType != MESS)
|
if (arrType != MESS)
|
||||||
writeFormattedArray(data);
|
writeFormattedArray(data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writeBinaryHeader(name, data.size(), arrType);
|
writeBinaryHeader(name, data.size(), arrType, element_size);
|
||||||
if (arrType != MESS)
|
if (arrType != MESS)
|
||||||
writeBinaryArray(data);
|
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 message(const std::string& msg);
|
||||||
void flushStream();
|
void flushStream();
|
||||||
|
|
||||||
|
void set_ix() { ix_standard = true; }
|
||||||
|
|
||||||
friend class OutputStream::Restart;
|
friend class OutputStream::Restart;
|
||||||
friend class OutputStream::SummarySpecification;
|
friend class OutputStream::SummarySpecification;
|
||||||
|
|
||||||
private:
|
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>
|
template <typename T>
|
||||||
void writeBinaryArray(const std::vector<T>& data);
|
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 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>
|
template <typename T>
|
||||||
void writeFormattedArray(const std::vector<T>& data);
|
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 writeFormattedCharArray(const std::vector<PaddedOutputString<8>>& data);
|
||||||
|
|
||||||
void writeArrayType(const eclArrType arrType);
|
void writeArrayType(const eclArrType arrType);
|
||||||
std::string make_real_string(float value) const;
|
std::string make_real_string_ecl(float value) const;
|
||||||
std::string make_doub_string(double 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;
|
std::ofstream ofileH;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace Opm { namespace EclIO {
|
namespace Opm { namespace EclIO {
|
||||||
|
|
||||||
@ -31,24 +33,52 @@ namespace Opm { namespace EclIO {
|
|||||||
float flipEndianFloat(float num);
|
float flipEndianFloat(float num);
|
||||||
double flipEndianDouble(double num);
|
double flipEndianDouble(double num);
|
||||||
bool isEOF(std::fstream* fileH);
|
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> block_size_data_binary(eclArrType arrType);
|
||||||
std::tuple<int, int, int> block_size_data_formatted(eclArrType arrType);
|
std::tuple<int, int, int> block_size_data_formatted(eclArrType arrType);
|
||||||
|
|
||||||
std::string trimr(const std::string &str1);
|
std::string trimr(const std::string &str1);
|
||||||
|
|
||||||
uint64_t sizeOnDiskBinary(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);
|
uint64_t sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrType arrType, int elementSize);
|
||||||
|
|
||||||
void readBinaryHeader(std::fstream& fileH, std::string& tmpStrName,
|
void readBinaryHeader(std::fstream& fileH, std::string& tmpStrName,
|
||||||
int& tmpSize, std::string& tmpStrType);
|
int& tmpSize, std::string& tmpStrType);
|
||||||
|
|
||||||
void readBinaryHeader(std::fstream& fileH, std::string& arrName,
|
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,
|
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
|
}} // namespace Opm::EclIO
|
||||||
|
|
||||||
|
@ -25,11 +25,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Opm::EclIO {
|
namespace Opm { namespace EclIO {
|
||||||
|
|
||||||
struct SummaryNode {
|
struct SummaryNode {
|
||||||
enum class Category {
|
enum class Category {
|
||||||
Aquifer,
|
|
||||||
Well,
|
Well,
|
||||||
Group,
|
Group,
|
||||||
Field,
|
Field,
|
||||||
@ -37,6 +36,8 @@ struct SummaryNode {
|
|||||||
Block,
|
Block,
|
||||||
Connection,
|
Connection,
|
||||||
Segment,
|
Segment,
|
||||||
|
Aquifer,
|
||||||
|
Node,
|
||||||
Miscellaneous,
|
Miscellaneous,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ struct SummaryNode {
|
|||||||
Pressure,
|
Pressure,
|
||||||
Count,
|
Count,
|
||||||
Mode,
|
Mode,
|
||||||
|
ProdIndex,
|
||||||
Undefined,
|
Undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ struct SummaryNode {
|
|||||||
std::string wgname;
|
std::string wgname;
|
||||||
int number;
|
int number;
|
||||||
|
|
||||||
|
std::optional<std::string> fip_region;
|
||||||
|
|
||||||
constexpr static int default_number { std::numeric_limits<int>::min() };
|
constexpr static int default_number { std::numeric_limits<int>::min() };
|
||||||
|
|
||||||
std::string unique_key() const;
|
std::string unique_key() const;
|
||||||
@ -72,6 +76,6 @@ struct SummaryNode {
|
|||||||
std::optional<std::string> display_number(number_renderer) const;
|
std::optional<std::string> display_number(number_renderer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Opm::EclIO
|
}} // namespace Opm::EclIO
|
||||||
|
|
||||||
#endif // OPM_IO_SUMMARYNODE_HPP
|
#endif // OPM_IO_SUMMARYNODE_HPP
|
||||||
|
@ -32,12 +32,21 @@ struct RstHeader;
|
|||||||
|
|
||||||
struct RstGroup {
|
struct RstGroup {
|
||||||
RstGroup(const UnitSystem& unit_system,
|
RstGroup(const UnitSystem& unit_system,
|
||||||
|
const RstHeader& header,
|
||||||
const std::string* zwel,
|
const std::string* zwel,
|
||||||
const int * igrp,
|
const int * igrp,
|
||||||
const float * sgrp,
|
const float * sgrp,
|
||||||
const double * xgrp);
|
const double * xgrp);
|
||||||
|
|
||||||
std::string name;
|
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 oil_rate_limit;
|
||||||
float water_rate_limit;
|
float water_rate_limit;
|
||||||
float gas_rate_limit;
|
float gas_rate_limit;
|
||||||
|
@ -24,10 +24,12 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
class UnitSystem;
|
||||||
|
|
||||||
namespace RestartIO {
|
namespace RestartIO {
|
||||||
|
|
||||||
struct RstHeader {
|
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 nx;
|
||||||
int ny;
|
int ny;
|
||||||
@ -82,10 +84,8 @@ struct RstHeader {
|
|||||||
int nilbrz;
|
int nilbrz;
|
||||||
int ntfip ;
|
int ntfip ;
|
||||||
int nmfipr;
|
int nmfipr;
|
||||||
int nrfreg;
|
|
||||||
int ntfreg;
|
|
||||||
int nplmix;
|
|
||||||
int ngroup;
|
int ngroup;
|
||||||
|
int nwgmax;
|
||||||
|
|
||||||
bool e300_radial;
|
bool e300_radial;
|
||||||
bool e100_radial;
|
bool e100_radial;
|
||||||
@ -100,6 +100,7 @@ struct RstHeader {
|
|||||||
bool dir_eps;
|
bool dir_eps;
|
||||||
bool reversible_eps;
|
bool reversible_eps;
|
||||||
bool alt_eps;
|
bool alt_eps;
|
||||||
|
bool group_control_active;
|
||||||
|
|
||||||
double next_timestep1;
|
double next_timestep1;
|
||||||
double next_timestep2;
|
double next_timestep2;
|
||||||
@ -110,6 +111,8 @@ struct RstHeader {
|
|||||||
double guide_rate_d;
|
double guide_rate_d;
|
||||||
double guide_rate_e;
|
double guide_rate_e;
|
||||||
double guide_rate_f;
|
double guide_rate_f;
|
||||||
|
double guide_rate_delay;
|
||||||
|
double guide_rate_damping;
|
||||||
double udq_range;
|
double udq_range;
|
||||||
double udq_undefined;
|
double udq_undefined;
|
||||||
double udq_eps;
|
double udq_eps;
|
||||||
|
@ -35,6 +35,11 @@ namespace Opm {
|
|||||||
|
|
||||||
namespace RestartIO {
|
namespace RestartIO {
|
||||||
struct RstState {
|
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,
|
RstState(const ::Opm::UnitSystem& unit_system,
|
||||||
const std::vector<int>& intehead,
|
const std::vector<int>& intehead,
|
||||||
const std::vector<bool>& logihead,
|
const std::vector<bool>& logihead,
|
||||||
|
@ -66,14 +66,16 @@ struct RstWell {
|
|||||||
std::array<int, 2> ij;
|
std::array<int, 2> ij;
|
||||||
std::pair<int,int> k1k2;
|
std::pair<int,int> k1k2;
|
||||||
WellType wtype;
|
WellType wtype;
|
||||||
|
int well_status;
|
||||||
int active_control;
|
int active_control;
|
||||||
int vfp_table;
|
int vfp_table;
|
||||||
int pred_requested_control;
|
|
||||||
bool allow_xflow;
|
bool allow_xflow;
|
||||||
|
int preferred_phase;
|
||||||
int hist_requested_control;
|
int hist_requested_control;
|
||||||
int msw_index;
|
int msw_index;
|
||||||
int completion_ordering;
|
int completion_ordering;
|
||||||
int pvt_table;
|
int pvt_table;
|
||||||
|
int msw_pressure_drop_model;
|
||||||
|
|
||||||
float orat_target;
|
float orat_target;
|
||||||
float wrat_target;
|
float wrat_target;
|
||||||
@ -88,12 +90,14 @@ struct RstWell {
|
|||||||
float datum_depth;
|
float datum_depth;
|
||||||
float drainage_radius;
|
float drainage_radius;
|
||||||
float efficiency_factor;
|
float efficiency_factor;
|
||||||
|
float alq_value;
|
||||||
|
|
||||||
double oil_rate;
|
double oil_rate;
|
||||||
double water_rate;
|
double water_rate;
|
||||||
double gas_rate;
|
double gas_rate;
|
||||||
double liquid_rate;
|
double liquid_rate;
|
||||||
double void_rate;
|
double void_rate;
|
||||||
|
double thp;
|
||||||
double flow_bhp;
|
double flow_bhp;
|
||||||
double wct;
|
double wct;
|
||||||
double gor;
|
double gor;
|
||||||
|
@ -16,7 +16,12 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
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/EGrid.hpp>
|
||||||
|
#include <opm/io/eclipse/EInit.hpp>
|
||||||
|
#include <opm/io/eclipse/EclUtil.hpp>
|
||||||
|
|
||||||
#include <opm/common/ErrorMacros.hpp>
|
#include <opm/common/ErrorMacros.hpp>
|
||||||
|
|
||||||
@ -30,21 +35,86 @@
|
|||||||
|
|
||||||
namespace Opm { namespace EclIO {
|
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";
|
||||||
|
|
||||||
|
std::string lgrname = "global";
|
||||||
|
|
||||||
|
m_nncs_loaded = false;
|
||||||
|
actnum_array_index = -1;
|
||||||
|
nnc1_array_index = -1;
|
||||||
|
nnc2_array_index = -1;
|
||||||
|
m_radial = false;
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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[0] = gridhead[1];
|
||||||
nijk[1] = gridhead[2];
|
nijk[1] = gridhead[2];
|
||||||
nijk[2] = gridhead[3];
|
nijk[2] = gridhead[3];
|
||||||
|
|
||||||
if (file.hasKey("ACTNUM")) {
|
if (gridhead.size() > 26)
|
||||||
auto actnum = get<int>("ACTNUM");
|
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;
|
nactive = 0;
|
||||||
for (unsigned int i = 0; i < actnum.size(); i++) {
|
for (size_t i = 0; i < actnum.size(); i++) {
|
||||||
if (actnum[i] > 0) {
|
if (actnum[i] > 0) {
|
||||||
act_index.push_back(nactive);
|
act_index.push_back(nactive);
|
||||||
glob_index.push_back(i);
|
glob_index.push_back(i);
|
||||||
@ -61,10 +131,104 @@ EGrid::EGrid(const std::string &filename) : EclFile(filename)
|
|||||||
std::iota(glob_index.begin(), glob_index.end(), 0);
|
std::iota(glob_index.begin(), glob_index.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
coord_array = get<float>("COORD");
|
if (hostnum_index > -1){
|
||||||
zcorn_array = get<float>("ZCORN");
|
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
|
int EGrid::global_index(int i, int j, int k) const
|
||||||
{
|
{
|
||||||
@ -129,12 +293,14 @@ std::array<int, 3> EGrid::ijk_from_global_index(int globInd) const
|
|||||||
void EGrid::getCellCorners(const std::array<int, 3>& ijk,
|
void EGrid::getCellCorners(const std::array<int, 3>& ijk,
|
||||||
std::array<double,8>& X,
|
std::array<double,8>& X,
|
||||||
std::array<double,8>& Y,
|
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> zind;
|
||||||
std::vector<int> pind;
|
std::vector<int> pind;
|
||||||
|
|
||||||
|
|
||||||
// calculate indices for grid pillars in COORD arrray
|
// calculate indices for grid pillars in COORD arrray
|
||||||
pind.push_back(ijk[1]*(nijk[0]+1)*6 + ijk[0]*6);
|
pind.push_back(ijk[1]*(nijk[0]+1)*6 + ijk[0]*6);
|
||||||
pind.push_back(pind[0] + 6);
|
pind.push_back(pind[0] + 6);
|
||||||
@ -147,23 +313,33 @@ void EGrid::getCellCorners(const std::array<int, 3>& ijk,
|
|||||||
zind.push_back(zind[0] + nijk[0]*2);
|
zind.push_back(zind[0] + nijk[0]*2);
|
||||||
zind.push_back(zind[2] + 1);
|
zind.push_back(zind[2] + 1);
|
||||||
|
|
||||||
for (int n = 0; n < 4; n++) {
|
for (int n = 0; n < 4; n++)
|
||||||
zind.push_back(zind[n] + nijk[0]*nijk[1]*4);
|
zind.push_back(zind[n] + nijk[0]*nijk[1]*4);
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; n< 8; n++){
|
for (int n = 0; n< 8; n++)
|
||||||
Z[n] = zcorn_array[zind[n]];
|
Z[n] = zcorn_array[zind[n]];
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; n < 4; n++) {
|
for (int n = 0; n < 4; n++) {
|
||||||
double xt = coord_array[pind[n]];
|
double xt;
|
||||||
double yt = coord_array[pind[n] + 1];
|
double yt;
|
||||||
double zt = coord_array[pind[n] + 2];
|
double xb;
|
||||||
|
double yb;
|
||||||
|
|
||||||
double xb = coord_array[pind[n] + 3];
|
double zt = coord_array[pind[n] + 2];
|
||||||
double yb = coord_array[pind[n] + 4];
|
|
||||||
double zb = coord_array[pind[n] + 5];
|
double zb = coord_array[pind[n] + 5];
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
X[n] = xt + (xb-xt) / (zt-zb) * (zt - Z[n]);
|
X[n] = xt + (xb-xt) / (zt-zb) * (zt - Z[n]);
|
||||||
X[n+4] = xt + (xb-xt) / (zt-zb) * (zt-Z[n+4]);
|
X[n+4] = xt + (xb-xt) / (zt-zb) * (zt-Z[n+4]);
|
||||||
|
|
||||||
@ -173,8 +349,9 @@ void EGrid::getCellCorners(const std::array<int, 3>& ijk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void EGrid::getCellCorners(int globindex, std::array<double,8>& X,
|
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);
|
return getCellCorners(ijk_from_global_index(globindex),X,Y,Z);
|
||||||
}
|
}
|
||||||
|
161
ThirdParty/custom-opm-common/opm-common/src/opm/io/eclipse/EInit.cpp
vendored
Normal file
161
ThirdParty/custom-opm-common/opm-common/src/opm/io/eclipse/EInit.cpp
vendored
Normal 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
|
@ -22,6 +22,8 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <opm/io/eclipse/ERsm.hpp>
|
#include <opm/io/eclipse/ERsm.hpp>
|
||||||
#include <opm/io/eclipse/ESmry.hpp>
|
#include <opm/io/eclipse/ESmry.hpp>
|
||||||
#include <opm/common/utility/FileSystem.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::category_from_keyword(kw_list[kw_index]),
|
||||||
SummaryNode::Type::Undefined,
|
SummaryNode::Type::Undefined,
|
||||||
wgnames[kw_index],
|
wgnames[kw_index],
|
||||||
make_num(nums_list[kw_index])};
|
make_num(nums_list[kw_index]),
|
||||||
|
""};
|
||||||
block_data.emplace_back( node, vector_length );
|
block_data.emplace_back( node, vector_length );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,22 +257,30 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
|
|||||||
const auto& summary_dates = smry.dates();
|
const auto& summary_dates = smry.dates();
|
||||||
if (rsm.has_dates()) {
|
if (rsm.has_dates()) {
|
||||||
const auto& rsm_dates = rsm.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;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t time_index = 0; time_index < rsm_dates.size(); time_index++) {
|
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 smry_ts = TimeStampUTC( std::chrono::system_clock::to_time_t(summary_dates[time_index]) );
|
||||||
const auto rsm_ts = rsm_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;
|
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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const auto& rsm_days = rsm.days();
|
const auto& rsm_days = rsm.days();
|
||||||
if (rsm_days.size() != summary_dates.size())
|
if (rsm_days.size() != summary_dates.size())
|
||||||
@ -280,10 +291,12 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
|
|||||||
using TP = time_point<system_clock>;
|
using TP = time_point<system_clock>;
|
||||||
auto smry_days = duration_cast<TP::duration>(summary_dates[time_index] - summary_dates[0]).count() / 86400.0 ;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& node : smry.summaryNodeList()) {
|
for (const auto& node : smry.summaryNodeList()) {
|
||||||
const auto& key = node.unique_key();
|
const auto& key = node.unique_key();
|
||||||
@ -309,13 +322,16 @@ bool cmp(const ESmry& smry, const ERsm& rsm) {
|
|||||||
const auto& smry_vector = smry.get(node);
|
const auto& smry_vector = smry.get(node);
|
||||||
const auto& rsm_vector = rsm.get(key);
|
const auto& rsm_vector = rsm.get(key);
|
||||||
for (std::size_t index = 0; index < smry_vector.size(); index++) {
|
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 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]);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int seqnumFromSeparateFilename(const std::string& filename)
|
int seqnumFromSeparateFilename(const std::string& filename)
|
||||||
@ -80,9 +78,9 @@ void ERst::loadReportStepNumber(int number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> arrayIndexList;
|
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);
|
arrayIndexList.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +91,12 @@ void ERst::loadReportStepNumber(int number)
|
|||||||
|
|
||||||
|
|
||||||
std::vector<EclFile::EclEntry> ERst::listOfRstArrays(int reportStepNumber)
|
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;
|
std::vector<EclEntry> list;
|
||||||
|
|
||||||
@ -101,19 +105,49 @@ std::vector<EclFile::EclEntry> ERst::listOfRstArrays(int reportStepNumber)
|
|||||||
OPM_THROW(std::invalid_argument, message);
|
OPM_THROW(std::invalid_argument, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& rng = this->arrIndexRange[reportStepNumber];
|
if ((lgr_name != "global") && (!this->hasLGR(lgr_name, reportStepNumber))) {
|
||||||
list.reserve(rng.second - rng.first);
|
std::string message = "Trying to get list of arrays from non existing LGR " + lgr_name;
|
||||||
|
OPM_THROW(std::invalid_argument, message);
|
||||||
for (int i = rng.first; i < rng.second; i++) {
|
|
||||||
list.emplace_back(array_name[i], array_type[i], array_size[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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)) {
|
if (!hasReportStepNumber(reportStepNumber)) {
|
||||||
std::string message = "Trying to count vectors of name " + name + " from non existing sequence " + std::to_string(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);
|
OPM_THROW(std::invalid_argument, message);
|
||||||
@ -145,9 +179,14 @@ void ERst::initUnified()
|
|||||||
auto seqn = get<int>(i);
|
auto seqn = get<int>(i);
|
||||||
seqnum.push_back(seqn[0]);
|
seqnum.push_back(seqn[0]);
|
||||||
firstIndex.push_back(i);
|
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++) {
|
for (size_t i = 0; i < seqnum.size(); i++) {
|
||||||
std::pair<int,int> range;
|
std::pair<int,int> range;
|
||||||
@ -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)
|
void ERst::initSeparate(const int number)
|
||||||
{
|
{
|
||||||
auto& range = this->arrIndexRange[number];
|
auto& range = this->arrIndexRange[number];
|
||||||
@ -178,6 +232,41 @@ void ERst::initSeparate(const int number)
|
|||||||
this->seqnum.assign(1, number);
|
this->seqnum.assign(1, number);
|
||||||
this->nReports = 1;
|
this->nReports = 1;
|
||||||
this->reportLoaded[number] = false;
|
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 {
|
std::tuple<int,int> ERst::getIndexRange(int reportStepNumber) const {
|
||||||
@ -192,13 +281,14 @@ std::tuple<int,int> ERst::getIndexRange(int reportStepNumber) const {
|
|||||||
return range_it->second;
|
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)) {
|
if (!hasReportStepNumber(number)) {
|
||||||
std::string message = "Trying to get vector " + name + " from non existing sequence " + std::to_string(number);
|
std::string message = "Trying to get vector " + name + " from non existing sequence " + std::to_string(number);
|
||||||
OPM_THROW(std::invalid_argument, message);
|
OPM_THROW(std::invalid_argument, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto range_it = arrIndexRange.find(number);
|
auto range_it = arrIndexRange.find(number);
|
||||||
|
|
||||||
std::pair<int,int> indexRange = range_it->second;
|
std::pair<int,int> indexRange = range_it->second;
|
||||||
@ -218,6 +308,25 @@ int ERst::getArrayIndex(const std::string& name, int number, int occurrenc) cons
|
|||||||
return std::distance(array_name.begin(), it);
|
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
|
std::streampos
|
||||||
ERst::restartStepWritePosition(const int seqnumValue) const
|
ERst::restartStepWritePosition(const int seqnumValue) const
|
||||||
{
|
{
|
||||||
@ -229,38 +338,74 @@ ERst::restartStepWritePosition(const int seqnumValue) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
int ind = getArrayIndex(name, reportStepNumber, occurrence);
|
||||||
return getImpl(ind, INTE, inte_array, "integer");
|
return getImpl(ind, INTE, inte_array, "integer");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
int ind = getArrayIndex(name, reportStepNumber, occurrence);
|
||||||
return getImpl(ind, REAL, real_array, "float");
|
return getImpl(ind, REAL, real_array, "float");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
int ind = getArrayIndex(name, reportStepNumber, occurrence);
|
||||||
return getImpl(ind, DOUB, doub_array, "double");
|
return getImpl(ind, DOUB, doub_array, "double");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
int ind = getArrayIndex(name, reportStepNumber, occurrence);
|
||||||
return getImpl(ind, LOGI, logi_array, "bool");
|
return getImpl(ind, LOGI, logi_array, "bool");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
int ind = getArrayIndex(name, reportStepNumber, occurrence);
|
||||||
return getImpl(ind, CHAR, char_array, "string");
|
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
|
}} // namespace Opm::ecl
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <opm/common/utility/TimeService.hpp>
|
#include <opm/common/utility/TimeService.hpp>
|
||||||
#include <opm/io/eclipse/EclFile.hpp>
|
#include <opm/io/eclipse/EclFile.hpp>
|
||||||
#include <opm/io/eclipse/EclUtil.hpp>
|
#include <opm/io/eclipse/EclUtil.hpp>
|
||||||
|
#include <opm/io/eclipse/EclOutput.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -30,9 +31,18 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "cross-platform/windows/Substitutes.hpp"
|
||||||
|
#else
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <ciso646>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -83,14 +93,17 @@ std::chrono::system_clock::time_point make_date(const std::vector<int>& datetime
|
|||||||
|
|
||||||
namespace Opm { namespace EclIO {
|
namespace Opm { namespace EclIO {
|
||||||
|
|
||||||
ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
ESmry::ESmry(const std::string &filename, bool loadBaseRunData , bool uselodsmry ) :
|
||||||
inputFileName { filename },
|
inputFileName { filename },
|
||||||
summaryNodes { }
|
summaryNodes { },
|
||||||
|
useLodsmryFile(uselodsmry)
|
||||||
{
|
{
|
||||||
|
fromSingleRun = !loadBaseRunData;
|
||||||
|
|
||||||
Opm::filesystem::path rootName = inputFileName.parent_path() / inputFileName.stem();
|
Opm::filesystem::path rootName = inputFileName.parent_path() / inputFileName.stem();
|
||||||
|
|
||||||
// if root name (without any extension) given as first argument in constructor, binary will then be assumed
|
// if only root name (without any extension) given as first argument in constructor
|
||||||
|
// binary will then be assumed
|
||||||
|
|
||||||
if (inputFileName.extension()=="")
|
if (inputFileName.extension()=="")
|
||||||
inputFileName+=".SMSPEC";
|
inputFileName+=".SMSPEC";
|
||||||
@ -101,6 +114,16 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
const bool formatted = inputFileName.extension()==".SMSPEC" ? false : true;
|
const bool formatted = inputFileName.extension()==".SMSPEC" ? false : true;
|
||||||
formattedFiles.push_back(formatted);
|
formattedFiles.push_back(formatted);
|
||||||
|
|
||||||
|
if (formatted)
|
||||||
|
lodFileName = rootName += ".FLODSMRY";
|
||||||
|
else
|
||||||
|
lodFileName = rootName += ".LODSMRY";
|
||||||
|
|
||||||
|
if ((!loadBaseRunData) && (Opm::filesystem::exists(lodFileName)))
|
||||||
|
lodEnabeled = true;
|
||||||
|
else
|
||||||
|
lodEnabeled = false;
|
||||||
|
|
||||||
Opm::filesystem::path path = Opm::filesystem::current_path();
|
Opm::filesystem::path path = Opm::filesystem::current_path();
|
||||||
|
|
||||||
updatePathAndRootName(path, rootName);
|
updatePathAndRootName(path, rootName);
|
||||||
@ -120,28 +143,44 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
"SUMTHIN",
|
"SUMTHIN",
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
std::vector<EclFile> smspecList;
|
||||||
|
std::vector<std::string> vectList = {"DIMENS", "RESTART", "KEYWORDS", "NUMS", "UNITS"};
|
||||||
|
|
||||||
// Read data from the summary into local data members.
|
// Read data from the summary into local data members.
|
||||||
{
|
{
|
||||||
EclFile smspec(smspec_file.string());
|
smspecList.emplace_back(EclFile(smspec_file.string()));
|
||||||
|
|
||||||
smspec.loadData(); // loading all data
|
auto arrays = smspecList.back().getList();
|
||||||
|
std::vector<int> vectIndices;
|
||||||
|
|
||||||
const std::vector<int> dimens = smspec.get<int>("DIMENS");
|
for (size_t n = 0; n < arrays.size(); n++)
|
||||||
|
if(std::find(vectList.begin(), vectList.end(), std::get<0>(arrays[n])) != vectList.end())
|
||||||
|
vectIndices.push_back(static_cast<int>(n));
|
||||||
|
|
||||||
|
smspecList.back().loadData(vectIndices);
|
||||||
|
|
||||||
|
const std::vector<int> dimens = smspecList.back().get<int>("DIMENS");
|
||||||
|
|
||||||
nI = dimens[1]; // This is correct -- dimens[0] is something else!
|
nI = dimens[1]; // This is correct -- dimens[0] is something else!
|
||||||
nJ = dimens[2];
|
nJ = dimens[2];
|
||||||
nK = dimens[3];
|
nK = dimens[3];
|
||||||
|
|
||||||
const std::vector<std::string> restartArray = smspec.get<std::string>("RESTART");
|
const std::vector<std::string> restartArray = smspecList.back().get<std::string>("RESTART");
|
||||||
const std::vector<std::string> keywords = smspec.get<std::string>("KEYWORDS");
|
const std::vector<std::string> keywords = smspecList.back().get<std::string>("KEYWORDS");
|
||||||
const std::vector<std::string> wgnames = smspec.get<std::string>("WGNAMES");
|
std::vector<std::string> wgnames;
|
||||||
const std::vector<int> nums = smspec.get<int>("NUMS");
|
|
||||||
const std::vector<std::string> units = smspec.get<std::string>("UNITS");
|
if (smspecList.back().hasKey("WGNAMES"))
|
||||||
|
wgnames = smspecList.back().get<std::string>("WGNAMES");
|
||||||
|
else
|
||||||
|
wgnames = smspecList.back().get<std::string>("NAMES");
|
||||||
|
|
||||||
|
const std::vector<int> nums = smspecList.back().get<int>("NUMS");
|
||||||
|
const std::vector<std::string> units = smspecList.back().get<std::string>("UNITS");
|
||||||
|
|
||||||
std::vector<std::string> combindKeyList;
|
std::vector<std::string> combindKeyList;
|
||||||
combindKeyList.reserve(dimens[0]);
|
combindKeyList.reserve(dimens[0]);
|
||||||
|
|
||||||
this->startdat = make_date(smspec.get<int>("STARTDAT"));
|
this->startdat = make_date(smspecList.back().get<int>("STARTDAT"));
|
||||||
|
|
||||||
for (unsigned int i=0; i<keywords.size(); i++) {
|
for (unsigned int i=0; i<keywords.size(); i++) {
|
||||||
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
||||||
@ -153,7 +192,8 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
SummaryNode::category_from_keyword(keywords[i], segmentExceptions),
|
SummaryNode::category_from_keyword(keywords[i], segmentExceptions),
|
||||||
SummaryNode::Type::Undefined,
|
SummaryNode::Type::Undefined,
|
||||||
wgnames[i],
|
wgnames[i],
|
||||||
nums[i]
|
nums[i],
|
||||||
|
""
|
||||||
});
|
});
|
||||||
|
|
||||||
keywList.insert(keyString);
|
keywList.insert(keyString);
|
||||||
@ -170,7 +210,6 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
// checking if this is a restart run. Supporting nested restarts (restart, from restart, ...)
|
// checking if this is a restart run. Supporting nested restarts (restart, from restart, ...)
|
||||||
// std::set keywList is storing keywords from all runs involved
|
// std::set keywList is storing keywords from all runs involved
|
||||||
|
|
||||||
|
|
||||||
while ((rstRootN.string() != "") && (loadBaseRunData)) {
|
while ((rstRootN.string() != "") && (loadBaseRunData)) {
|
||||||
|
|
||||||
Opm::filesystem::path rstFile = pathRstFile / rstRootN;
|
Opm::filesystem::path rstFile = pathRstFile / rstRootN;
|
||||||
@ -185,20 +224,34 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
baseRunFmt = true;
|
baseRunFmt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EclFile smspec_rst(rstFile.string());
|
smspecList.emplace_back(EclFile(rstFile.string()));
|
||||||
smspec_rst.loadData();
|
|
||||||
|
|
||||||
const std::vector<int> dimens = smspec_rst.get<int>("DIMENS");
|
auto arrays = smspecList.back().getList();
|
||||||
const std::vector<std::string> restartArray = smspec_rst.get<std::string>("RESTART");
|
std::vector<int> vectIndices;
|
||||||
const std::vector<std::string> keywords = smspec_rst.get<std::string>("KEYWORDS");
|
|
||||||
const std::vector<std::string> wgnames = smspec_rst.get<std::string>("WGNAMES");
|
for (size_t n = 0; n < arrays.size(); n++)
|
||||||
const std::vector<int> nums = smspec_rst.get<int>("NUMS");
|
if(std::find(vectList.begin(), vectList.end(), std::get<0>(arrays[n])) != vectList.end())
|
||||||
const std::vector<std::string> units = smspec_rst.get<std::string>("UNITS");
|
vectIndices.push_back(static_cast<int>(n));
|
||||||
|
|
||||||
|
smspecList.back().loadData(vectIndices);
|
||||||
|
|
||||||
|
const std::vector<int> dimens = smspecList.back().get<int>("DIMENS");
|
||||||
|
const std::vector<std::string> restartArray = smspecList.back().get<std::string>("RESTART");
|
||||||
|
const std::vector<std::string> keywords = smspecList.back().get<std::string>("KEYWORDS");
|
||||||
|
std::vector<std::string> wgnames;
|
||||||
|
|
||||||
|
if (smspecList.back().hasKey("WGNAMES"))
|
||||||
|
wgnames = smspecList.back().get<std::string>("WGNAMES");
|
||||||
|
else
|
||||||
|
wgnames = smspecList.back().get<std::string>("NAMES");
|
||||||
|
|
||||||
|
const std::vector<int> nums = smspecList.back().get<int>("NUMS");
|
||||||
|
const std::vector<std::string> units = smspecList.back().get<std::string>("UNITS");
|
||||||
|
|
||||||
std::vector<std::string> combindKeyList;
|
std::vector<std::string> combindKeyList;
|
||||||
combindKeyList.reserve(dimens[0]);
|
combindKeyList.reserve(dimens[0]);
|
||||||
|
|
||||||
this->startdat = make_date(smspec_rst.get<int>("STARTDAT"));
|
this->startdat = make_date(smspecList.back().get<int>("STARTDAT"));
|
||||||
|
|
||||||
for (size_t i = 0; i < keywords.size(); i++) {
|
for (size_t i = 0; i < keywords.size(); i++) {
|
||||||
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
||||||
@ -209,7 +262,8 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
SummaryNode::category_from_keyword(keywords[i], segmentExceptions),
|
SummaryNode::category_from_keyword(keywords[i], segmentExceptions),
|
||||||
SummaryNode::Type::Undefined,
|
SummaryNode::Type::Undefined,
|
||||||
wgnames[i],
|
wgnames[i],
|
||||||
nums[i]
|
nums[i],
|
||||||
|
""
|
||||||
});
|
});
|
||||||
|
|
||||||
keywList.insert(keyString);
|
keywList.insert(keyString);
|
||||||
@ -243,10 +297,7 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
|
|
||||||
auto smry = smryArray[specInd];
|
auto smry = smryArray[specInd];
|
||||||
|
|
||||||
EclFile smspec(std::get<0>(smry));
|
const std::vector<int> dimens = smspecList[specInd].get<int>("DIMENS");
|
||||||
smspec.loadData();
|
|
||||||
|
|
||||||
const std::vector<int> dimens = smspec.get<int>("DIMENS");
|
|
||||||
|
|
||||||
nI = dimens[1];
|
nI = dimens[1];
|
||||||
nJ = dimens[2];
|
nJ = dimens[2];
|
||||||
@ -254,9 +305,15 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
|
|
||||||
nParamsSpecFile[specInd] = dimens[0];
|
nParamsSpecFile[specInd] = dimens[0];
|
||||||
|
|
||||||
const std::vector<std::string> keywords = smspec.get<std::string>("KEYWORDS");
|
const std::vector<std::string> keywords = smspecList[specInd].get<std::string>("KEYWORDS");
|
||||||
const std::vector<std::string> wgnames = smspec.get<std::string>("WGNAMES");
|
std::vector<std::string> wgnames;
|
||||||
const std::vector<int> nums = smspec.get<int>("NUMS");
|
|
||||||
|
if (smspecList.back().hasKey("WGNAMES"))
|
||||||
|
wgnames = smspecList.back().get<std::string>("WGNAMES");
|
||||||
|
else
|
||||||
|
wgnames = smspecList.back().get<std::string>("NAMES");
|
||||||
|
|
||||||
|
const std::vector<int> nums = smspecList[specInd].get<int>("NUMS");
|
||||||
|
|
||||||
for (size_t i=0; i < keywords.size(); i++) {
|
for (size_t i=0; i < keywords.size(); i++) {
|
||||||
const std::string keyw = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
const std::string keyw = makeKeyString(keywords[i], wgnames[i], nums[i]);
|
||||||
@ -288,6 +345,18 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
vectorLoaded.push_back(false);
|
vectorLoaded.push_back(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useLodsmryFile && lodEnabeled)
|
||||||
|
{
|
||||||
|
// inspecting formatted or binary lod file. lodsmry possible only if
|
||||||
|
// loadBaseRunData=false
|
||||||
|
|
||||||
|
inspect_lodsmry();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// inspecting time step data, unified summary or multiple summary files both formatted or binary.
|
||||||
|
// this also include base run data if loadBaseRunData=true and restart runs exists.
|
||||||
|
|
||||||
int dataFileIndex = -1;
|
int dataFileIndex = -1;
|
||||||
|
|
||||||
while (specInd >= 0) {
|
while (specInd >= 0) {
|
||||||
@ -336,8 +405,6 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
resultsFileList=multFileList;
|
resultsFileList=multFileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make array list with reference to source files (unifed or non unified)
|
|
||||||
|
|
||||||
std::vector<ArrSourceEntry> arraySourceList;
|
std::vector<ArrSourceEntry> arraySourceList;
|
||||||
|
|
||||||
for (std::string fileName : resultsFileList)
|
for (std::string fileName : resultsFileList)
|
||||||
@ -406,14 +473,158 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
|
|||||||
fromReportStepNumber = toReportStepNumber;
|
fromReportStepNumber = toReportStepNumber;
|
||||||
|
|
||||||
specInd--;
|
specInd--;
|
||||||
|
|
||||||
|
nTstep = timeStepList.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESmry::inspect_lodsmry()
|
||||||
|
{
|
||||||
|
std::string arrName;
|
||||||
|
int64_t arr_size;
|
||||||
|
Opm::EclIO::eclArrType arrType;
|
||||||
|
int sizeOfElement;
|
||||||
|
|
||||||
|
std::fstream fileH;
|
||||||
|
|
||||||
|
if (formattedFiles[0]) {
|
||||||
|
fileH.open(lodFileName, std::ios::in);
|
||||||
|
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
|
||||||
|
} else {
|
||||||
|
fileH.open(lodFileName, std::ios::in | std::ios::binary);
|
||||||
|
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((arrName != "KEYCHECK") or (arrType != Opm::EclIO::CHAR))
|
||||||
|
OPM_THROW(std::invalid_argument, "reading keycheck, invalid lod file");
|
||||||
|
|
||||||
|
std::vector<std::string> keycheck;
|
||||||
|
|
||||||
|
if (formattedFiles[0]) {
|
||||||
|
uint64_t size = Opm::EclIO::sizeOnDiskFormatted(arr_size, Opm::EclIO::CHAR, sizeOfChar) + 1;
|
||||||
|
std::string fileStr = read_string_from_disk(fileH, size);
|
||||||
|
|
||||||
|
keycheck = Opm::EclIO::readFormattedCharArray(fileStr, arr_size, 0, sizeOfChar);
|
||||||
|
} else {
|
||||||
|
keycheck = Opm::EclIO::readBinaryCharArray(fileH, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((arr_size / nVect != 3) or (arr_size % nVect != 0))
|
||||||
|
OPM_THROW(std::invalid_argument, "reading keycheck, invalid lod file");
|
||||||
|
|
||||||
|
for (size_t n = 0; n < nVect; n++) {
|
||||||
|
size_t ind = n*3;
|
||||||
|
std::string test_str = keycheck[ind] + keycheck[ind+1] + keycheck[ind+2];
|
||||||
|
|
||||||
|
if (keyword[n].size() > 24) {
|
||||||
|
if (keyword[n].substr(0,24) != test_str) {
|
||||||
|
OPM_THROW(std::invalid_argument, "keycheck not maching keyword array");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (keyword[n] != test_str) {
|
||||||
|
OPM_THROW(std::invalid_argument, "keycheck not maching keyword array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
|
||||||
|
else
|
||||||
|
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
|
||||||
|
|
||||||
|
if ((arrName != "RSTEP ") or (arrType != Opm::EclIO::LOGI))
|
||||||
|
OPM_THROW(std::invalid_argument, "reading rstep, invalid lod file");
|
||||||
|
|
||||||
|
std::vector<bool> rstep;
|
||||||
|
|
||||||
|
if (formattedFiles[0]) {
|
||||||
|
uint64_t size = Opm::EclIO::sizeOnDiskFormatted(arr_size, Opm::EclIO::LOGI, sizeOfLogi) + 1;
|
||||||
|
std::string fileStr = read_string_from_disk(fileH, size);
|
||||||
|
|
||||||
|
rstep = Opm::EclIO::readFormattedLogiArray(fileStr, arr_size, 0);
|
||||||
|
} else {
|
||||||
|
rstep = readBinaryLogiArray(fileH, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t m = 0; m < rstep.size(); m++)
|
||||||
|
if (rstep[m])
|
||||||
|
seqIndex.push_back(m);
|
||||||
|
|
||||||
|
lod_offset = static_cast<uint64_t>(fileH.tellg());
|
||||||
|
nTstep = rstep.size();
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
lod_arr_size = sizeOnDiskFormatted(nTstep, Opm::EclIO::REAL, sizeOfReal);
|
||||||
|
else
|
||||||
|
lod_arr_size = sizeOnDiskBinary(nTstep, Opm::EclIO::REAL, sizeOfReal);
|
||||||
|
|
||||||
|
fileH.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ESmry::read_string_from_disk(std::fstream& fileH, uint64_t size) const
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
buffer = new char [size];
|
||||||
|
fileH.read (buffer, size);
|
||||||
|
std::string fileStr = std::string(buffer, size);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return fileStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESmry::Load_from_lodsmry(const std::vector<int>& keywIndVect) const
|
||||||
|
{
|
||||||
|
std::fstream fileH;
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
fileH.open(lodFileName, std::ios::in);
|
||||||
|
else
|
||||||
|
fileH.open(lodFileName, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
for (auto ind : keywIndVect) {
|
||||||
|
std::string arrName;
|
||||||
|
int64_t size;
|
||||||
|
Opm::EclIO::eclArrType arrType;
|
||||||
|
int sizeOfElement;
|
||||||
|
|
||||||
|
uint64_t pos = lod_offset + lod_arr_size*static_cast<uint64_t>(ind);
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
pos = pos + static_cast<uint64_t>(ind * 31); // adding size of formatted headers
|
||||||
|
else
|
||||||
|
pos = pos + static_cast<uint64_t>(ind * 24); // adding size of binary headers
|
||||||
|
|
||||||
|
fileH.seekg (pos, fileH.beg);
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
readFormattedHeader(fileH, arrName, size, arrType, sizeOfElement);
|
||||||
|
else
|
||||||
|
readBinaryHeader(fileH, arrName, size, arrType, sizeOfElement);
|
||||||
|
|
||||||
|
arrName = Opm::EclIO::trimr(arrName);
|
||||||
|
|
||||||
|
std::string checkName = "V" + std::to_string(ind);
|
||||||
|
|
||||||
|
if (arrName != checkName)
|
||||||
|
OPM_THROW(std::invalid_argument, "lodsmry, wrong header expecting " + checkName + " found " + arrName);
|
||||||
|
|
||||||
|
if (formattedFiles[0]) {
|
||||||
|
uint64_t size_buffer = lod_arr_size + 1;
|
||||||
|
std::string fileStr = read_string_from_disk(fileH, size_buffer);
|
||||||
|
vectorData[ind] = Opm::EclIO::readFormattedRealArray(fileStr, nTstep, 0);
|
||||||
|
} else {
|
||||||
|
vectorData[ind] = readBinaryRealArray(fileH, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileH.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
||||||
{
|
{
|
||||||
size_t nvect = vectList.size();
|
size_t nvect = vectList.size();
|
||||||
size_t ntstep = timeStepList.size();
|
|
||||||
|
|
||||||
std::vector<int> keywIndVect;
|
std::vector<int> keywIndVect;
|
||||||
keywIndVect.reserve(nvect);
|
keywIndVect.reserve(nvect);
|
||||||
@ -427,13 +638,30 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto ind : keywIndVect)
|
for (auto ind : keywIndVect)
|
||||||
vectorData[ind].reserve(ntstep);
|
vectorData[ind].reserve(nTstep);
|
||||||
|
|
||||||
|
if (useLodsmryFile && lodEnabeled)
|
||||||
|
{
|
||||||
|
Load_from_lodsmry(keywIndVect);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
std::fstream fileH;
|
std::fstream fileH;
|
||||||
|
|
||||||
auto specInd = std::get<0>(timeStepList[0]);
|
auto specInd = std::get<0>(timeStepList[0]);
|
||||||
auto dataFileIndex = std::get<1>(timeStepList[0]);
|
auto dataFileIndex = std::get<1>(timeStepList[0]);
|
||||||
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
|
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
|
||||||
|
uint64_t blockSize_f;
|
||||||
|
|
||||||
|
{
|
||||||
|
int nLinesBlock = MaxBlockSizeReal / numColumnsReal;
|
||||||
|
int rest = MaxBlockSizeReal % numColumnsReal;
|
||||||
|
|
||||||
|
if (rest > 0)
|
||||||
|
nLinesBlock++;
|
||||||
|
|
||||||
|
blockSize_f= static_cast<uint64_t>(MaxNumBlockReal * numColumnsReal * columnWidthReal + nLinesBlock);
|
||||||
|
}
|
||||||
|
|
||||||
if (formattedFiles[specInd])
|
if (formattedFiles[specInd])
|
||||||
fileH.open(dataFileList[dataFileIndex], std::ios::in);
|
fileH.open(dataFileList[dataFileIndex], std::ios::in);
|
||||||
@ -441,6 +669,7 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
|
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
for (auto ministep : timeStepList) {
|
for (auto ministep : timeStepList) {
|
||||||
|
|
||||||
if (dataFileIndex != std::get<1>(ministep)) {
|
if (dataFileIndex != std::get<1>(ministep)) {
|
||||||
fileH.close();
|
fileH.close();
|
||||||
specInd = std::get<0>(ministep);
|
specInd = std::get<0>(ministep);
|
||||||
@ -455,6 +684,7 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
stepFilePos = std::get<2>(ministep);;
|
stepFilePos = std::get<2>(ministep);;
|
||||||
|
|
||||||
for (auto ind : keywIndVect) {
|
for (auto ind : keywIndVect) {
|
||||||
|
|
||||||
auto it = arrayPos[specInd].find(ind);
|
auto it = arrayPos[specInd].find(ind);
|
||||||
|
|
||||||
if (it == arrayPos[specInd].end()) {
|
if (it == arrayPos[specInd].end()) {
|
||||||
@ -469,16 +699,8 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
int nBlocks = paramPos / MaxBlockSizeReal;
|
int nBlocks = paramPos / MaxBlockSizeReal;
|
||||||
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
|
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
|
||||||
|
|
||||||
if (nBlocks > 0) {
|
if (nBlocks > 0)
|
||||||
int nLinesBlock = MaxNumBlockReal / numColumnsReal;
|
elementPos = static_cast<uint64_t>(nBlocks * blockSize_f);
|
||||||
int rest = MaxNumBlockReal % numColumnsReal;
|
|
||||||
|
|
||||||
if (rest > 0)
|
|
||||||
nLinesBlock++;
|
|
||||||
|
|
||||||
uint64_t blockSize = static_cast<uint64_t>(MaxNumBlockReal * numColumnsReal + nLinesBlock);
|
|
||||||
elementPos = static_cast<uint64_t>(nBlocks * blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
int nLines = sizeOfLastBlock / numColumnsReal;
|
int nLines = sizeOfLastBlock / numColumnsReal;
|
||||||
elementPos = stepFilePos + elementPos + static_cast<uint64_t>(sizeOfLastBlock * columnWidthReal + nLines);
|
elementPos = stepFilePos + elementPos + static_cast<uint64_t>(sizeOfLastBlock * columnWidthReal + nLines);
|
||||||
@ -499,10 +721,12 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
uint64_t nFullBlocks = static_cast<uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
|
uint64_t nFullBlocks = static_cast<uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
|
||||||
uint64_t elementPos = ((2 * nFullBlocks) + 1)*static_cast<uint64_t>(sizeOfInte);
|
uint64_t elementPos = ((2 * nFullBlocks) + 1)*static_cast<uint64_t>(sizeOfInte);
|
||||||
elementPos += static_cast<uint64_t>(paramPos)* static_cast<uint64_t>(sizeOfReal) + stepFilePos;
|
elementPos += static_cast<uint64_t>(paramPos)* static_cast<uint64_t>(sizeOfReal) + stepFilePos;
|
||||||
|
|
||||||
fileH.seekg (elementPos, fileH.beg);
|
fileH.seekg (elementPos, fileH.beg);
|
||||||
|
|
||||||
float value;
|
float value;
|
||||||
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
|
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
|
||||||
|
|
||||||
vectorData[ind].push_back(Opm::EclIO::flipEndianFloat(value));
|
vectorData[ind].push_back(Opm::EclIO::flipEndianFloat(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,6 +734,7 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileH.close();
|
fileH.close();
|
||||||
|
}
|
||||||
|
|
||||||
for (auto ind : keywIndVect)
|
for (auto ind : keywIndVect)
|
||||||
vectorLoaded[ind] = true;
|
vectorLoaded[ind] = true;
|
||||||
@ -538,6 +763,11 @@ std::vector<int> ESmry::makeKeywPosVector(int specInd) const {
|
|||||||
|
|
||||||
void ESmry::LoadData() const
|
void ESmry::LoadData() const
|
||||||
{
|
{
|
||||||
|
if (useLodsmryFile && lodEnabeled) {
|
||||||
|
|
||||||
|
this ->LoadData(keyword);
|
||||||
|
|
||||||
|
} else {
|
||||||
std::fstream fileH;
|
std::fstream fileH;
|
||||||
|
|
||||||
auto specInd = std::get<0>(timeStepList[0]);
|
auto specInd = std::get<0>(timeStepList[0]);
|
||||||
@ -574,8 +804,9 @@ void ESmry::LoadData() const
|
|||||||
fileH.seekg (stepFilePos, fileH.beg);
|
fileH.seekg (stepFilePos, fileH.beg);
|
||||||
|
|
||||||
if (formattedFiles[specInd]) {
|
if (formattedFiles[specInd]) {
|
||||||
|
|
||||||
char* buffer;
|
char* buffer;
|
||||||
size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL)+1;
|
size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL, sizeOfReal) + 1;
|
||||||
buffer = new char [size];
|
buffer = new char [size];
|
||||||
fileH.read (buffer, size);
|
fileH.read (buffer, size);
|
||||||
|
|
||||||
@ -587,7 +818,7 @@ void ESmry::LoadData() const
|
|||||||
p1 = fileStr.find_first_not_of(' ',p1);
|
p1 = fileStr.find_first_not_of(' ',p1);
|
||||||
int64_t p2 = fileStr.find_first_of(' ', p1);
|
int64_t p2 = fileStr.find_first_of(' ', p1);
|
||||||
|
|
||||||
if (keywpos[p] > -1) {
|
if ((keywpos[p] > -1) && (!vectorLoaded[keywpos[p]])) {
|
||||||
double dtmpv = std::stod(fileStr.substr(p1, p2-p1));
|
double dtmpv = std::stod(fileStr.substr(p1, p2-p1));
|
||||||
vectorData[keywpos[p]].push_back(static_cast<float>(dtmpv));
|
vectorData[keywpos[p]].push_back(static_cast<float>(dtmpv));
|
||||||
}
|
}
|
||||||
@ -597,6 +828,7 @@ void ESmry::LoadData() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
|
int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
|
||||||
size_t p = 0;
|
size_t p = 0;
|
||||||
@ -614,7 +846,7 @@ void ESmry::LoadData() const
|
|||||||
float value;
|
float value;
|
||||||
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
|
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
|
||||||
|
|
||||||
if (keywpos[p] > -1)
|
if ((keywpos[p] > -1) && (!vectorLoaded[keywpos[p]]))
|
||||||
vectorData[keywpos[p]].push_back(Opm::EclIO::flipEndianFloat(value));
|
vectorData[keywpos[p]].push_back(Opm::EclIO::flipEndianFloat(value));
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
@ -641,30 +873,87 @@ void ESmry::LoadData() const
|
|||||||
for (size_t n=0; n < nVect; n++)
|
for (size_t n=0; n < nVect; n++)
|
||||||
vectorLoaded[n] = true;
|
vectorLoaded[n] = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::tuple <std::string, uint64_t>>
|
std::vector<std::tuple <std::string, uint64_t>>
|
||||||
ESmry::getListOfArrays(std::string filename, bool formatted)
|
ESmry::getListOfArrays(std::string filename, bool formatted)
|
||||||
{
|
{
|
||||||
std::vector<std::tuple <std::string, uint64_t>> resultVect;
|
std::vector<std::tuple <std::string, uint64_t>> resultVect;
|
||||||
std::fstream fileH;
|
|
||||||
|
|
||||||
if (formatted)
|
FILE *ptr;
|
||||||
fileH.open(filename, std::ios::in);
|
char arrName[9];
|
||||||
else
|
char numstr[13];
|
||||||
fileH.open(filename, std::ios::in | std::ios::binary);
|
|
||||||
|
|
||||||
while (!Opm::EclIO::isEOF(&fileH)) {
|
|
||||||
std::string arrName(8,' ');
|
|
||||||
Opm::EclIO::eclArrType arrType;
|
|
||||||
|
|
||||||
int64_t num;
|
int64_t num;
|
||||||
if (formatted)
|
|
||||||
Opm::EclIO::readFormattedHeader(fileH,arrName,num,arrType);
|
|
||||||
else
|
|
||||||
Opm::EclIO::readBinaryHeader(fileH,arrName,num,arrType);
|
|
||||||
|
|
||||||
uint64_t filePos = fileH.tellg();
|
if (formatted)
|
||||||
|
ptr = fopen(filename.c_str(),"r"); // r for read, files opened as text files
|
||||||
|
else
|
||||||
|
ptr = fopen(filename.c_str(),"rb"); // r for read, b for binary
|
||||||
|
|
||||||
|
bool endOfFile = false;
|
||||||
|
|
||||||
|
while (!endOfFile)
|
||||||
|
{
|
||||||
|
Opm::EclIO::eclArrType arrType;
|
||||||
|
|
||||||
|
if (formatted)
|
||||||
|
{
|
||||||
|
fseek(ptr, 2, SEEK_CUR);
|
||||||
|
|
||||||
|
if (fread(arrName, 8, 1, ptr) != 1 )
|
||||||
|
throw std::runtime_error("fread error when loading summary data");
|
||||||
|
|
||||||
|
arrName[8]='\0';
|
||||||
|
|
||||||
|
fseek(ptr, 1, SEEK_CUR);
|
||||||
|
|
||||||
|
if (fread(numstr, 12, 1, ptr) != 1)
|
||||||
|
throw std::runtime_error("fread error when loading summary data");
|
||||||
|
|
||||||
|
numstr[12]='\0';
|
||||||
|
|
||||||
|
int num_int = std::stoi(numstr);
|
||||||
|
num = static_cast<int64_t>(num_int);
|
||||||
|
|
||||||
|
fseek(ptr, 8, SEEK_CUR);
|
||||||
|
|
||||||
|
if ((strcmp(arrName, "SEQHDR ") == 0) || (strcmp(arrName, "MINISTEP") == 0))
|
||||||
|
arrType = Opm::EclIO::INTE;
|
||||||
|
else if (strcmp(arrName, "PARAMS ") == 0)
|
||||||
|
arrType = Opm::EclIO::REAL;
|
||||||
|
else {
|
||||||
|
throw std::invalid_argument("unknown array in summary data file ");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int num_int;
|
||||||
|
|
||||||
|
fseek(ptr, 4, SEEK_CUR);
|
||||||
|
|
||||||
|
if (fread(arrName, 8, 1, ptr) != 1)
|
||||||
|
throw std::runtime_error("fread error when loading summary data");
|
||||||
|
|
||||||
|
arrName[8]='\0';
|
||||||
|
|
||||||
|
if (fread(&num_int, 4, 1, ptr) != 1)
|
||||||
|
throw std::runtime_error("fread error when loading summary data");
|
||||||
|
|
||||||
|
num = static_cast<int64_t>(Opm::EclIO::flipEndianInt(num_int));
|
||||||
|
|
||||||
|
fseek(ptr, 8, SEEK_CUR);
|
||||||
|
|
||||||
|
if ((strcmp(arrName, "SEQHDR ") == 0) || (strcmp(arrName, "MINISTEP") == 0))
|
||||||
|
arrType = Opm::EclIO::INTE;
|
||||||
|
else if (strcmp(arrName, "PARAMS ") == 0)
|
||||||
|
arrType = Opm::EclIO::REAL;
|
||||||
|
else {
|
||||||
|
throw std::invalid_argument("unknown array in UNSMRY file ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t filePos = static_cast<uint64_t>(ftell(ptr));
|
||||||
|
|
||||||
std::tuple <std::string, uint64_t> t1;
|
std::tuple <std::string, uint64_t> t1;
|
||||||
t1 = std::make_tuple(Opm::EclIO::trimr(arrName), filePos);
|
t1 = std::make_tuple(Opm::EclIO::trimr(arrName), filePos);
|
||||||
@ -672,21 +961,115 @@ ESmry::getListOfArrays(std::string filename, bool formatted)
|
|||||||
|
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
if (formatted) {
|
if (formatted) {
|
||||||
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType);
|
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType, 4);
|
||||||
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
|
fseek(ptr, static_cast<long int>(sizeOfNextArray), SEEK_CUR);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
uint64_t sizeOfNextArray = sizeOnDiskBinary(num, arrType);
|
uint64_t sizeOfNextArray = sizeOnDiskBinary(num, arrType, 4);
|
||||||
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
|
fseek(ptr, static_cast<long int>(sizeOfNextArray), SEEK_CUR);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileH.close();
|
if (fgetc(ptr) == EOF)
|
||||||
|
endOfFile = true;
|
||||||
|
else
|
||||||
|
fseek(ptr, -1, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ptr);
|
||||||
|
|
||||||
return resultVect;
|
return resultVect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ESmry::make_lodsmry_file()
|
||||||
|
{
|
||||||
|
// check that loadBaseRunData is not set, this function only works for single smspec files
|
||||||
|
// function will not replace existing lodsmry files (since this is already loaded by this class)
|
||||||
|
// if lodsmry file exist, this function will return false and do nothing.
|
||||||
|
|
||||||
|
if (!fromSingleRun)
|
||||||
|
OPM_THROW(std::invalid_argument, "creating lodsmry file only possible when loadBaseRunData=false");
|
||||||
|
|
||||||
|
Opm::filesystem::path path = inputFileName.parent_path();
|
||||||
|
Opm::filesystem::path rootName = inputFileName.stem();
|
||||||
|
Opm::filesystem::path smryDataFile;
|
||||||
|
|
||||||
|
if (formattedFiles[0])
|
||||||
|
smryDataFile = path / rootName += ".FLODSMRY";
|
||||||
|
else
|
||||||
|
smryDataFile = path / rootName += ".LODSMRY";
|
||||||
|
|
||||||
|
if (Opm::EclIO::fileExists(smryDataFile.string()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::vector<std::string> keycheck;
|
||||||
|
keycheck.reserve(keyword.size());
|
||||||
|
|
||||||
|
std::string str1;
|
||||||
|
std::string str2;
|
||||||
|
std::string str3;
|
||||||
|
|
||||||
|
for (auto key : keyword){
|
||||||
|
|
||||||
|
str2="";
|
||||||
|
str3="";
|
||||||
|
|
||||||
|
if (key.size() > 24)
|
||||||
|
str1 = key.substr(0,24);
|
||||||
|
else
|
||||||
|
str1 = key;
|
||||||
|
|
||||||
|
if (str1.size() > 8){
|
||||||
|
str2 = str1.substr(8);
|
||||||
|
str1 = str1.substr(0,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str2.size() > 8){
|
||||||
|
str3 = str2.substr(8);
|
||||||
|
str2 = str2.substr(0,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
keycheck.push_back(str1);
|
||||||
|
keycheck.push_back(str2);
|
||||||
|
keycheck.push_back(str3);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<bool> is_rstep;
|
||||||
|
is_rstep.reserve(timeStepList.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < timeStepList.size(); i++)
|
||||||
|
if(std::find(seqIndex.begin(), seqIndex.end(), i) != seqIndex.end())
|
||||||
|
is_rstep.push_back(true);
|
||||||
|
else
|
||||||
|
is_rstep.push_back(false);
|
||||||
|
|
||||||
|
this->LoadData();
|
||||||
|
|
||||||
|
{
|
||||||
|
Opm::EclIO::EclOutput outFile(smryDataFile.string(), formattedFiles[0], std::ios::out);
|
||||||
|
outFile.write<std::string>("KEYCHECK", keycheck);
|
||||||
|
outFile.write<bool>("RSTEP", is_rstep);
|
||||||
|
|
||||||
|
for (size_t n = 0; n < vectorData.size(); n++ ) {
|
||||||
|
std::string vect_name="V" + std::to_string(n);
|
||||||
|
outFile.write<float>(vect_name, vectorData[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void ESmry::use_lodsmry_file(bool enable)
|
||||||
|
{
|
||||||
|
useLodsmryFile = enable;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> ESmry::checkForMultipleResultFiles(const Opm::filesystem::path& rootN, bool formatted) const {
|
std::vector<std::string> ESmry::checkForMultipleResultFiles(const Opm::filesystem::path& rootN, bool formatted) const {
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <opm/io/eclipse/EclUtil.hpp>
|
#include <opm/io/eclipse/EclUtil.hpp>
|
||||||
#include <opm/common/ErrorMacros.hpp>
|
#include <opm/common/ErrorMacros.hpp>
|
||||||
|
|
||||||
|
//#include <fmt/format.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -34,256 +35,13 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#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 {
|
namespace Opm { namespace EclIO {
|
||||||
|
|
||||||
EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(filename)
|
EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(filename)
|
||||||
{
|
{
|
||||||
if (!fileExists(filename)){
|
if (!fileExists(filename))
|
||||||
std::string message="Could not open EclFile: " + filename;
|
throw std::runtime_error("Can not open EclFile: {}");
|
||||||
OPM_THROW(std::invalid_argument, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::fstream fileH;
|
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);
|
fileH.open(filename, std::ios::in | std::ios::binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fileH) {
|
if (!fileH)
|
||||||
std::string message="Could not open file: " + filename;
|
throw std::runtime_error("Can not open EclFile: {}");
|
||||||
OPM_THROW(std::runtime_error, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (!isEOF(&fileH)) {
|
while (!isEOF(&fileH)) {
|
||||||
std::string arrName(8,' ');
|
std::string arrName(8,' ');
|
||||||
eclArrType arrType;
|
eclArrType arrType;
|
||||||
int64_t num;
|
int64_t num;
|
||||||
|
int sizeOfElement;
|
||||||
|
|
||||||
if (formatted) {
|
if (formatted) {
|
||||||
readFormattedHeader(fileH,arrName,num,arrType);
|
readFormattedHeader(fileH,arrName,num,arrType, sizeOfElement);
|
||||||
} else {
|
} else {
|
||||||
readBinaryHeader(fileH,arrName,num,arrType);
|
readBinaryHeader(fileH,arrName,num, arrType, sizeOfElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_size.push_back(num);
|
array_size.push_back(num);
|
||||||
array_type.push_back(arrType);
|
array_type.push_back(arrType);
|
||||||
|
|
||||||
array_name.push_back(trimr(arrName));
|
array_name.push_back(trimr(arrName));
|
||||||
|
array_element_size.push_back(sizeOfElement);
|
||||||
|
|
||||||
array_index[array_name[n]] = n;
|
array_index[array_name[n]] = n;
|
||||||
|
|
||||||
uint64_t pos = fileH.tellg();
|
uint64_t pos = fileH.tellg();
|
||||||
@ -325,15 +83,14 @@ EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(file
|
|||||||
|
|
||||||
if (num > 0){
|
if (num > 0){
|
||||||
if (formatted) {
|
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);
|
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
|
||||||
} else {
|
} 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);
|
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -366,6 +123,9 @@ void EclFile::loadBinaryArray(std::fstream& fileH, std::size_t arrIndex)
|
|||||||
case CHAR:
|
case CHAR:
|
||||||
char_array[arrIndex] = readBinaryCharArray(fileH, array_size[arrIndex]);
|
char_array[arrIndex] = readBinaryCharArray(fileH, array_size[arrIndex]);
|
||||||
break;
|
break;
|
||||||
|
case C0NN:
|
||||||
|
char_array[arrIndex] = readBinaryC0nnArray(fileH, array_size[arrIndex], array_element_size[arrIndex]);
|
||||||
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
break;
|
break;
|
||||||
default:
|
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);
|
logi_array[arrIndex] = readFormattedLogiArray(fileStr, array_size[arrIndex], fromPos);
|
||||||
break;
|
break;
|
||||||
case CHAR:
|
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;
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
break;
|
break;
|
||||||
@ -449,7 +212,7 @@ void EclFile::loadData(const std::string& name)
|
|||||||
inFile.seekg(ifStreamPos[arrIndex]);
|
inFile.seekg(ifStreamPos[arrIndex]);
|
||||||
|
|
||||||
char* buffer;
|
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];
|
buffer = new char [size];
|
||||||
inFile.read (buffer, size);
|
inFile.read (buffer, size);
|
||||||
|
|
||||||
@ -494,7 +257,7 @@ void EclFile::loadData(const std::vector<int>& arrIndex)
|
|||||||
inFile.seekg(ifStreamPos[ind]);
|
inFile.seekg(ifStreamPos[ind]);
|
||||||
|
|
||||||
char* buffer;
|
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];
|
buffer = new char [size];
|
||||||
inFile.read (buffer, size);
|
inFile.read (buffer, size);
|
||||||
|
|
||||||
@ -525,7 +288,6 @@ void EclFile::loadData(const std::vector<int>& arrIndex)
|
|||||||
|
|
||||||
void EclFile::loadData(int arrIndex)
|
void EclFile::loadData(int arrIndex)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (formatted) {
|
if (formatted) {
|
||||||
|
|
||||||
std::ifstream inFile(inputFilename);
|
std::ifstream inFile(inputFilename);
|
||||||
@ -533,7 +295,7 @@ void EclFile::loadData(int arrIndex)
|
|||||||
inFile.seekg(ifStreamPos[arrIndex]);
|
inFile.seekg(ifStreamPos[arrIndex]);
|
||||||
|
|
||||||
char* buffer;
|
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];
|
buffer = new char [size];
|
||||||
inFile.read (buffer, 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<EclFile::EclEntry> EclFile::getList() const
|
||||||
{
|
{
|
||||||
std::vector<EclEntry> list;
|
std::vector<EclEntry> list;
|
||||||
@ -603,7 +468,12 @@ const std::vector<bool>& EclFile::get<bool>(int arrIndex)
|
|||||||
template<>
|
template<>
|
||||||
const std::vector<std::string>& EclFile::get<std::string>(int arrIndex)
|
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);
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ EclOutput::EclOutput(const std::string& filename,
|
|||||||
: isFormatted{formatted}
|
: isFormatted{formatted}
|
||||||
{
|
{
|
||||||
const auto binmode = mode | std::ios_base::binary;
|
const auto binmode = mode | std::ios_base::binary;
|
||||||
|
ix_standard = false;
|
||||||
|
|
||||||
this->ofileH.open(filename, this->isFormatted ? mode : binmode);
|
this->ofileH.open(filename, this->isFormatted ? mode : binmode);
|
||||||
}
|
}
|
||||||
@ -50,15 +51,79 @@ template<>
|
|||||||
void EclOutput::write<std::string>(const std::string& name,
|
void EclOutput::write<std::string>(const std::string& name,
|
||||||
const std::vector<std::string>& data)
|
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)
|
if (isFormatted)
|
||||||
{
|
{
|
||||||
writeFormattedHeader(name, data.size(), CHAR);
|
if (maximum_length > sizeOfChar){
|
||||||
writeFormattedCharArray(data);
|
writeFormattedHeader(name, data.size(), C0NN, maximum_length);
|
||||||
|
writeFormattedCharArray(data, maximum_length);
|
||||||
|
} else {
|
||||||
|
writeFormattedHeader(name, data.size(), CHAR, sizeOfChar);
|
||||||
|
writeFormattedCharArray(data, sizeOfChar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writeBinaryHeader(name, data.size(), CHAR);
|
if (maximum_length > sizeOfChar){
|
||||||
writeBinaryCharArray(data);
|
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)
|
const std::vector<PaddedOutputString<8>>& data)
|
||||||
{
|
{
|
||||||
if (this->isFormatted) {
|
if (this->isFormatted) {
|
||||||
writeFormattedHeader(name, data.size(), CHAR);
|
writeFormattedHeader(name, data.size(), CHAR, sizeOfChar);
|
||||||
writeFormattedCharArray(data);
|
writeFormattedCharArray(data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writeBinaryHeader(name, data.size(), CHAR);
|
writeBinaryHeader(name, data.size(), CHAR, sizeOfChar);
|
||||||
writeBinaryCharArray(data);
|
writeBinaryCharArray(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +156,7 @@ void EclOutput::flushStream()
|
|||||||
this->ofileH.flush();
|
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);
|
int bhead = flipEndianInt(16);
|
||||||
std::string name = arrName + std::string(8 - arrName.size(),' ');
|
std::string name = arrName + std::string(8 - arrName.size(),' ');
|
||||||
@ -119,6 +184,14 @@ void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclAr
|
|||||||
ofileH.write(name.c_str(), 8);
|
ofileH.write(name.c_str(), 8);
|
||||||
ofileH.write(reinterpret_cast<char*>(&flippedSize), sizeof(flippedSize));
|
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) {
|
switch(arrType) {
|
||||||
case INTE:
|
case INTE:
|
||||||
ofileH.write("INTE", 4);
|
ofileH.write("INTE", 4);
|
||||||
@ -135,6 +208,9 @@ void EclOutput::writeBinaryHeader(const std::string&arrName, int64_t size, eclAr
|
|||||||
case CHAR:
|
case CHAR:
|
||||||
ofileH.write("CHAR", 4);
|
ofileH.write("CHAR", 4);
|
||||||
break;
|
break;
|
||||||
|
case C0NN:
|
||||||
|
ofileH.write(c0nn_str.c_str(), 4);
|
||||||
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
ofileH.write("MESS", 4);
|
ofileH.write("MESS", 4);
|
||||||
break;
|
break;
|
||||||
@ -178,6 +254,8 @@ void EclOutput::writeBinaryArray(const std::vector<T>& data)
|
|||||||
OPM_THROW(std::runtime_error, "fstream fileH not open for writing");
|
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);
|
rest = size * static_cast<int64_t>(sizeOfElement);
|
||||||
while (rest > 0) {
|
while (rest > 0) {
|
||||||
if (rest > maxBlockSize) {
|
if (rest > maxBlockSize) {
|
||||||
@ -203,7 +281,7 @@ void EclOutput::writeBinaryArray(const std::vector<T>& data)
|
|||||||
value_d = flipEndianDouble(data[n]);
|
value_d = flipEndianDouble(data[n]);
|
||||||
ofileH.write(reinterpret_cast<char*>(&value_d), sizeof(value_d));
|
ofileH.write(reinterpret_cast<char*>(&value_d), sizeof(value_d));
|
||||||
} else if (arrType == LOGI) {
|
} 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);
|
ofileH.write(reinterpret_cast<char*>(&intVal), sizeOfElement);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "type not supported in write binaryarray\n";
|
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);
|
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;
|
int num,dhead;
|
||||||
|
|
||||||
@ -234,6 +312,11 @@ void EclOutput::writeBinaryCharArray(const std::vector<std::string>& data)
|
|||||||
|
|
||||||
auto sizeData = block_size_data_binary(CHAR);
|
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 sizeOfElement = std::get<0>(sizeData);
|
||||||
int maxBlockSize = std::get<1>(sizeData);
|
int maxBlockSize = std::get<1>(sizeData);
|
||||||
int maxNumberOfElements = maxBlockSize / sizeOfElement;
|
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));
|
ofileH.write(reinterpret_cast<char*>(&dhead), sizeof(dhead));
|
||||||
|
|
||||||
for (int i = 0; i < num; i++) {
|
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);
|
ofileH.write(tmpStr.c_str(), sizeOfElement);
|
||||||
n++;
|
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(),' ');
|
std::string name = arrName + std::string(8 - arrName.size(),' ');
|
||||||
|
|
||||||
ofileH << " '" << name << "' " << std::setw(11) << 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) {
|
switch (arrType) {
|
||||||
case INTE:
|
case INTE:
|
||||||
ofileH << " 'INTE'" << std::endl;
|
ofileH << " 'INTE'" << std::endl;
|
||||||
@ -325,6 +417,9 @@ void EclOutput::writeFormattedHeader(const std::string& arrName, int size, eclAr
|
|||||||
case CHAR:
|
case CHAR:
|
||||||
ofileH << " 'CHAR'" << std::endl;
|
ofileH << " 'CHAR'" << std::endl;
|
||||||
break;
|
break;
|
||||||
|
case C0NN:
|
||||||
|
ofileH << " '" << c0nn_str << "'" << std::endl;
|
||||||
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
ofileH << " 'MESS'" << std::endl;
|
ofileH << " 'MESS'" << std::endl;
|
||||||
break;
|
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];
|
char buffer [15];
|
||||||
std::sprintf (buffer, "%10.7E", value);
|
std::sprintf (buffer, "%10.7E", value);
|
||||||
@ -367,11 +462,35 @@ std::string EclOutput::make_real_string(float value) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EclOutput::make_real_string_ix(float value) const
|
||||||
std::string EclOutput::make_doub_string(double value) const
|
|
||||||
{
|
{
|
||||||
char buffer [21];
|
char buffer [15];
|
||||||
std::sprintf (buffer, "%19.13E", value);
|
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) {
|
if (value == 0.0) {
|
||||||
return "0.00000000000000D+00";
|
return "0.00000000000000D+00";
|
||||||
@ -388,27 +507,52 @@ std::string EclOutput::make_doub_string(double value) const
|
|||||||
|
|
||||||
std::string tmpstr(buffer);
|
std::string tmpstr(buffer);
|
||||||
int exp = value < 0.0 ? std::stoi(tmpstr.substr(17, 4)) : std::stoi(tmpstr.substr(16, 4));
|
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 (value < 0.0) {
|
||||||
if (std::abs(exp) < 100) {
|
if (use_exp_char) {
|
||||||
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13) + "D";
|
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13) + "D";
|
||||||
} else {
|
} else {
|
||||||
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13);
|
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (std::abs(exp) < 100) {
|
if (use_exp_char) {
|
||||||
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13) + "D";
|
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13) + "D";
|
||||||
} else {
|
} else {
|
||||||
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13);
|
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;
|
tmpstr = tmpstr + buffer;
|
||||||
return tmpstr;
|
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>
|
template <typename T>
|
||||||
void EclOutput::writeFormattedArray(const std::vector<T>& data)
|
void EclOutput::writeFormattedArray(const std::vector<T>& data)
|
||||||
@ -427,6 +571,7 @@ void EclOutput::writeFormattedArray(const std::vector<T>& data)
|
|||||||
arrType = LOGI;
|
arrType = LOGI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto sizeData = block_size_data_formatted(arrType);
|
auto sizeData = block_size_data_formatted(arrType);
|
||||||
|
|
||||||
int maxBlockSize = std::get<0>(sizeData);
|
int maxBlockSize = std::get<0>(sizeData);
|
||||||
@ -441,10 +586,16 @@ void EclOutput::writeFormattedArray(const std::vector<T>& data)
|
|||||||
ofileH << std::setw(columnWidth) << data[i];
|
ofileH << std::setw(columnWidth) << data[i];
|
||||||
break;
|
break;
|
||||||
case REAL:
|
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;
|
break;
|
||||||
case DOUB:
|
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;
|
break;
|
||||||
case LOGI:
|
case LOGI:
|
||||||
if (data[i]) {
|
if (data[i]) {
|
||||||
@ -479,18 +630,34 @@ template void EclOutput::writeFormattedArray<bool>(const std::vector<bool>& data
|
|||||||
template void EclOutput::writeFormattedArray<char>(const std::vector<char>& 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);
|
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);
|
||||||
|
|
||||||
|
int rest = data.size();
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
while (rest > 0) {
|
||||||
|
int size = rest;
|
||||||
|
|
||||||
|
if (size > maxBlockSize)
|
||||||
|
size = maxBlockSize;
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
std::string str1(8,' ');
|
std::string str1(element_size,' ');
|
||||||
str1 = data[i] + std::string(8 - data[i].size(),' ');
|
str1 = data[n] + std::string(element_size - data[n].size(),' ');
|
||||||
|
|
||||||
|
n++;
|
||||||
ofileH << " '" << str1 << "'";
|
ofileH << " '" << str1 << "'";
|
||||||
|
|
||||||
if ((i+1) % nColumns == 0) {
|
if ((i+1) % nColumns == 0) {
|
||||||
@ -501,7 +668,11 @@ void EclOutput::writeFormattedCharArray(const std::vector<std::string>& data)
|
|||||||
if ((size % nColumns) != 0) {
|
if ((size % nColumns) != 0) {
|
||||||
ofileH << std::endl;
|
ofileH << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rest = (rest > maxBlockSize) ? rest - maxBlockSize : 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EclOutput::writeFormattedCharArray(const std::vector<PaddedOutputString<8>>& data)
|
void EclOutput::writeFormattedCharArray(const std::vector<PaddedOutputString<8>>& data)
|
||||||
{
|
{
|
||||||
|
@ -23,10 +23,14 @@
|
|||||||
#include <cross-platform/PortableEndian.hpp>
|
#include <cross-platform/PortableEndian.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
//temporary
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
int Opm::EclIO::flipEndianInt(int num)
|
int Opm::EclIO::flipEndianInt(int num)
|
||||||
{
|
{
|
||||||
@ -61,6 +65,21 @@ double Opm::EclIO::flipEndianDouble(double num)
|
|||||||
return value;
|
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)
|
bool Opm::EclIO::isEOF(std::fstream* fileH)
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
@ -96,6 +115,9 @@ std::tuple<int, int> Opm::EclIO::block_size_data_binary(eclArrType arrType)
|
|||||||
case CHAR:
|
case CHAR:
|
||||||
return BlockSizeTuple{sizeOfChar, MaxBlockSizeChar};
|
return BlockSizeTuple{sizeOfChar, MaxBlockSizeChar};
|
||||||
break;
|
break;
|
||||||
|
case C0NN:
|
||||||
|
return BlockSizeTuple{sizeOfChar, MaxBlockSizeChar};
|
||||||
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data");
|
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data");
|
||||||
break;
|
break;
|
||||||
@ -126,6 +148,9 @@ std::tuple<int, int, int> Opm::EclIO::block_size_data_formatted(eclArrType arrTy
|
|||||||
case CHAR:
|
case CHAR:
|
||||||
return BlockSizeTuple{MaxNumBlockChar,numColumnsChar, columnWidthChar};
|
return BlockSizeTuple{MaxNumBlockChar,numColumnsChar, columnWidthChar};
|
||||||
break;
|
break;
|
||||||
|
case C0NN:
|
||||||
|
return BlockSizeTuple{MaxNumBlockChar,numColumnsChar, columnWidthChar};
|
||||||
|
break;
|
||||||
case MESS:
|
case MESS:
|
||||||
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data") ;
|
OPM_THROW(std::invalid_argument, "Type 'MESS' have no associated data") ;
|
||||||
break;
|
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;
|
uint64_t size = 0;
|
||||||
|
|
||||||
@ -160,6 +185,11 @@ uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrTyp
|
|||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
auto sizeData = Opm::EclIO::block_size_data_binary(arrType);
|
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 sizeOfElement = std::get<0>(sizeData);
|
||||||
int maxBlockSize = std::get<1>(sizeData);
|
int maxBlockSize = std::get<1>(sizeData);
|
||||||
int maxNumberOfElements = maxBlockSize / sizeOfElement;
|
int maxNumberOfElements = maxBlockSize / sizeOfElement;
|
||||||
@ -182,7 +212,7 @@ uint64_t Opm::EclIO::sizeOnDiskBinary(int64_t num, Opm::EclIO::eclArrType arrTyp
|
|||||||
return size;
|
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;
|
uint64_t size = 0;
|
||||||
|
|
||||||
@ -193,6 +223,11 @@ uint64_t Opm::EclIO::sizeOnDiskFormatted(const int64_t num, Opm::EclIO::eclArrTy
|
|||||||
} else {
|
} else {
|
||||||
auto sizeData = block_size_data_formatted(arrType);
|
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 maxBlockSize = std::get<0>(sizeData);
|
||||||
int nColumns = std::get<1>(sizeData);
|
int nColumns = std::get<1>(sizeData);
|
||||||
int columnWidth = std::get<2>(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,
|
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 tmpStrName(8,' ');
|
||||||
std::string tmpStrType(4,' ');
|
std::string tmpStrType(4,' ');
|
||||||
@ -282,15 +317,25 @@ void Opm::EclIO::readBinaryHeader(std::fstream& fileH, std::string& arrName,
|
|||||||
size = static_cast<int64_t>(tmpSize);
|
size = static_cast<int64_t>(tmpSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elementSize = 4;
|
||||||
|
|
||||||
arrName = tmpStrName;
|
arrName = tmpStrName;
|
||||||
if (tmpStrType == "INTE")
|
if (tmpStrType == "INTE")
|
||||||
arrType = Opm::EclIO::INTE;
|
arrType = Opm::EclIO::INTE;
|
||||||
else if (tmpStrType == "REAL")
|
else if (tmpStrType == "REAL")
|
||||||
arrType = Opm::EclIO::REAL;
|
arrType = Opm::EclIO::REAL;
|
||||||
else if (tmpStrType == "DOUB")
|
else if (tmpStrType == "DOUB"){
|
||||||
arrType = Opm::EclIO::DOUB;
|
arrType = Opm::EclIO::DOUB;
|
||||||
else if (tmpStrType == "CHAR")
|
elementSize = 8;
|
||||||
|
}
|
||||||
|
else if (tmpStrType == "CHAR"){
|
||||||
arrType = Opm::EclIO::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")
|
else if (tmpStrType =="LOGI")
|
||||||
arrType = Opm::EclIO::LOGI;
|
arrType = Opm::EclIO::LOGI;
|
||||||
else if (tmpStrType == "MESS")
|
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,
|
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::string line;
|
||||||
std::getline(fileH,line);
|
std::getline(fileH,line);
|
||||||
@ -321,14 +366,24 @@ void Opm::EclIO::readFormattedHeader(std::fstream& fileH, std::string& arrName,
|
|||||||
|
|
||||||
num = std::stol(antStr);
|
num = std::stol(antStr);
|
||||||
|
|
||||||
|
elementSize = 4;
|
||||||
|
|
||||||
if (arrTypeStr == "INTE")
|
if (arrTypeStr == "INTE")
|
||||||
arrType = Opm::EclIO::INTE;
|
arrType = Opm::EclIO::INTE;
|
||||||
else if (arrTypeStr == "REAL")
|
else if (arrTypeStr == "REAL")
|
||||||
arrType = Opm::EclIO::REAL;
|
arrType = Opm::EclIO::REAL;
|
||||||
else if (arrTypeStr == "DOUB")
|
else if (arrTypeStr == "DOUB"){
|
||||||
arrType = Opm::EclIO::DOUB;
|
arrType = Opm::EclIO::DOUB;
|
||||||
else if (arrTypeStr == "CHAR")
|
elementSize = 8;
|
||||||
|
}
|
||||||
|
else if (arrTypeStr == "CHAR"){
|
||||||
arrType = Opm::EclIO::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")
|
else if (arrTypeStr == "LOGI")
|
||||||
arrType = Opm::EclIO::LOGI;
|
arrType = Opm::EclIO::LOGI;
|
||||||
else if (arrTypeStr == "MESS")
|
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");
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <opm/io/eclipse/SummaryNode.hpp>
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <opm/io/eclipse/SummaryNode.hpp>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr bool use_number(Opm::EclIO::SummaryNode::Category category) {
|
constexpr bool use_number(Opm::EclIO::SummaryNode::Category category) {
|
||||||
@ -37,6 +37,7 @@ constexpr bool use_number(Opm::EclIO::SummaryNode::Category category) {
|
|||||||
return true;
|
return true;
|
||||||
case Opm::EclIO::SummaryNode::Category::Field: [[fallthrough]];
|
case Opm::EclIO::SummaryNode::Category::Field: [[fallthrough]];
|
||||||
case Opm::EclIO::SummaryNode::Category::Group: [[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::Miscellaneous: [[fallthrough]];
|
||||||
case Opm::EclIO::SummaryNode::Category::Well:
|
case Opm::EclIO::SummaryNode::Category::Well:
|
||||||
return false;
|
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::Connection: [[fallthrough]];
|
||||||
case Opm::EclIO::SummaryNode::Category::Group: [[fallthrough]];
|
case Opm::EclIO::SummaryNode::Category::Group: [[fallthrough]];
|
||||||
case Opm::EclIO::SummaryNode::Category::Segment: [[fallthrough]];
|
case Opm::EclIO::SummaryNode::Category::Segment: [[fallthrough]];
|
||||||
|
case Opm::EclIO::SummaryNode::Category::Node: [[fallthrough]];
|
||||||
case Opm::EclIO::SummaryNode::Category::Well:
|
case Opm::EclIO::SummaryNode::Category::Well:
|
||||||
return true;
|
return true;
|
||||||
case Opm::EclIO::SummaryNode::Category::Aquifer: [[fallthrough]];
|
case Opm::EclIO::SummaryNode::Category::Aquifer: [[fallthrough]];
|
||||||
@ -69,8 +71,24 @@ std::string default_number_renderer(const Opm::EclIO::SummaryNode& node) {
|
|||||||
return std::to_string(node.number);
|
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::string Opm::EclIO::SummaryNode::unique_key(number_renderer render_number) const {
|
||||||
std::vector<std::string> key_parts { keyword } ;
|
std::vector<std::string> key_parts { keyword } ;
|
||||||
|
|
||||||
@ -120,7 +138,7 @@ bool Opm::EclIO::SummaryNode::is_user_defined() const {
|
|||||||
"SURFWNUM",
|
"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 matched { std::regex_match(keyword, user_defined_regex) } ;
|
||||||
const bool blacklisted { udq_blacklist.find(keyword) != udq_blacklist.end() } ;
|
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 'B': return Category::Block;
|
||||||
case 'C': return Category::Connection;
|
case 'C': return Category::Connection;
|
||||||
case 'F': return Category::Field;
|
case 'F': return Category::Field;
|
||||||
case 'G': return Category::Group;
|
case 'G': return distinguish_group_from_node(keyword);
|
||||||
case 'R': return Category::Region;
|
case 'R': return Category::Region;
|
||||||
case 'S': return Category::Segment;
|
case 'S': return Category::Segment;
|
||||||
case 'W': return Category::Well;
|
case 'W': return Category::Well;
|
||||||
|
@ -32,24 +32,42 @@ namespace RestartIO {
|
|||||||
|
|
||||||
using M = ::Opm::UnitSystem::measure;
|
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,
|
RstGroup::RstGroup(const ::Opm::UnitSystem& unit_system,
|
||||||
|
const RstHeader& header,
|
||||||
const std::string* zwel,
|
const std::string* zwel,
|
||||||
const int *,
|
const int * igrp,
|
||||||
const float * sgrp,
|
const float * sgrp,
|
||||||
const double * xgrp) :
|
const double * xgrp) :
|
||||||
name(trim_copy(zwel[0])),
|
name(trim_copy(zwel[0])),
|
||||||
oil_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::OilRateLimit])),
|
parent_group(igrp[header.nwgmax + VI::IGroup::ParentGroup] ),
|
||||||
water_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::WatRateLimit])),
|
prod_active_cmode(igrp[header.nwgmax + VI::IGroup::ProdActiveCMode]),
|
||||||
gas_rate_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::GasRateLimit])),
|
gconprod_cmode(igrp[header.nwgmax + VI::IGroup::GConProdCMode]),
|
||||||
liquid_rate_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::LiqRateLimit])),
|
winj_cmode(igrp[header.nwgmax + VI::IGroup::WInjCMode]),
|
||||||
water_surface_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterSurfRateLimit])),
|
ginj_cmode(igrp[header.nwgmax + VI::IGroup::GInjCMode]),
|
||||||
water_reservoir_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterResRateLimit])),
|
guide_rate_def(igrp[header.nwgmax + VI::IGroup::GuideRateDef]),
|
||||||
water_reinject_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterReinjectionLimit])),
|
// The values oil_rate_limit -> gas_voidage_limit will be used in UDA
|
||||||
water_voidage_limit( unit_system.to_si(M::liquid_surface_rate, sgrp[VI::SGroup::waterVoidageLimit])),
|
// values. The UDA values are responsible for unit conversion and raw values
|
||||||
gas_surface_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::gasSurfRateLimit])),
|
// are internalized here.
|
||||||
gas_reservoir_limit( unit_system.to_si(M::geometric_volume_rate, sgrp[VI::SGroup::gasResRateLimit])),
|
oil_rate_limit( sgrp_value(sgrp[VI::SGroup::OilRateLimit])),
|
||||||
gas_reinject_limit( unit_system.to_si(M::gas_surface_rate, sgrp[VI::SGroup::gasReinjectionLimit])),
|
water_rate_limit( sgrp_value(sgrp[VI::SGroup::WatRateLimit])),
|
||||||
gas_voidage_limit( unit_system.to_si(M::geometric_volume_rate, sgrp[VI::SGroup::gasVoidageLimit])),
|
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])),
|
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])),
|
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])),
|
gas_production_rate( unit_system.to_si(M::gas_surface_rate, xgrp[VI::XGroup::GasPrRate])),
|
||||||
|
@ -23,13 +23,15 @@
|
|||||||
#include <opm/output/eclipse/VectorItems/logihead.hpp>
|
#include <opm/output/eclipse/VectorItems/logihead.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/doubhead.hpp>
|
#include <opm/output/eclipse/VectorItems/doubhead.hpp>
|
||||||
#include <opm/common/utility/TimeService.hpp>
|
#include <opm/common/utility/TimeService.hpp>
|
||||||
|
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
namespace RestartIO {
|
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]),
|
nx(intehead[VI::intehead::NX]),
|
||||||
ny(intehead[VI::intehead::NY]),
|
ny(intehead[VI::intehead::NY]),
|
||||||
nz(intehead[VI::intehead::NZ]),
|
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]),
|
ntfip(intehead[VI::intehead::NTFIP]),
|
||||||
nmfipr(intehead[VI::intehead::NMFIPR]),
|
nmfipr(intehead[VI::intehead::NMFIPR]),
|
||||||
ngroup(intehead[VI::intehead::NGRP]),
|
ngroup(intehead[VI::intehead::NGRP]),
|
||||||
|
nwgmax(intehead[VI::intehead::NWGMAX]),
|
||||||
//
|
//
|
||||||
e300_radial(logihead[VI::logihead::E300Radial]),
|
e300_radial(logihead[VI::logihead::E300Radial]),
|
||||||
e100_radial(logihead[VI::logihead::E100Radial]),
|
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]),
|
dir_eps(logihead[VI::logihead::DirEPS]),
|
||||||
reversible_eps(logihead[VI::logihead::RevEPS]),
|
reversible_eps(logihead[VI::logihead::RevEPS]),
|
||||||
alt_eps(logihead[VI::logihead::AltEPS]),
|
alt_eps(logihead[VI::logihead::AltEPS]),
|
||||||
|
group_control_active(intehead[VI::intehead::NGRNPH] == 1),
|
||||||
//
|
//
|
||||||
next_timestep1(doubhead[VI::doubhead::TsInit]),
|
next_timestep1(unit_system.to_si(M::time, doubhead[VI::doubhead::TsInit])),
|
||||||
next_timestep2(doubhead[VI::doubhead::TsMaxz]),
|
next_timestep2(0),
|
||||||
max_timestep(doubhead[VI::doubhead::TsMinz]),
|
max_timestep(unit_system.to_si(M::time, doubhead[VI::doubhead::TsMaxz])),
|
||||||
guide_rate_a(doubhead[VI::doubhead::GRpar_a]),
|
guide_rate_a(doubhead[VI::doubhead::GRpar_a]),
|
||||||
guide_rate_b(doubhead[VI::doubhead::GRpar_b]),
|
guide_rate_b(doubhead[VI::doubhead::GRpar_b]),
|
||||||
guide_rate_c(doubhead[VI::doubhead::GRpar_c]),
|
guide_rate_c(doubhead[VI::doubhead::GRpar_c]),
|
||||||
guide_rate_d(doubhead[VI::doubhead::GRpar_d]),
|
guide_rate_d(doubhead[VI::doubhead::GRpar_d]),
|
||||||
guide_rate_e(doubhead[VI::doubhead::GRpar_e]),
|
guide_rate_e(doubhead[VI::doubhead::GRpar_e]),
|
||||||
guide_rate_f(doubhead[VI::doubhead::GRpar_f]),
|
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_range(doubhead[VI::doubhead::UdqPar_2]),
|
||||||
udq_undefined(doubhead[VI::doubhead::UdqPar_3]),
|
udq_undefined(doubhead[VI::doubhead::UdqPar_3]),
|
||||||
udq_eps(doubhead[VI::doubhead::UdqPar_4])
|
udq_eps(doubhead[VI::doubhead::UdqPar_4])
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp>
|
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp>
|
||||||
#include <opm/parser/eclipse/Units/UnitSystem.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 VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
@ -34,6 +34,16 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
|||||||
namespace Opm {
|
namespace Opm {
|
||||||
namespace RestartIO {
|
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_,
|
RstState::RstState(const ::Opm::UnitSystem& unit_system_,
|
||||||
const std::vector<int>& intehead,
|
const std::vector<int>& intehead,
|
||||||
const std::vector<bool>& logihead,
|
const std::vector<bool>& logihead,
|
||||||
@ -49,11 +59,9 @@ RstState::RstState(const ::Opm::UnitSystem& unit_system_,
|
|||||||
const std::vector<int>& icon,
|
const std::vector<int>& icon,
|
||||||
const std::vector<float>& scon,
|
const std::vector<float>& scon,
|
||||||
const std::vector<double>& xcon):
|
const std::vector<double>& xcon):
|
||||||
unit_system(unit_system_),
|
RstState(unit_system_, intehead, logihead, doubhead)
|
||||||
header(intehead, logihead, doubhead)
|
|
||||||
{
|
{
|
||||||
this->add_groups(zgrp, igrp, sgrp, xgrp);
|
this->add_groups(zgrp, igrp, sgrp, xgrp);
|
||||||
this->load_tuning(intehead, doubhead);
|
|
||||||
|
|
||||||
for (int iw = 0; iw < this->header.num_wells; iw++) {
|
for (int iw = 0; iw < this->header.num_wells; iw++) {
|
||||||
std::size_t zwel_offset = iw * this->header.nzwelz;
|
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<double>& xcon,
|
||||||
const std::vector<int>& iseg,
|
const std::vector<int>& iseg,
|
||||||
const std::vector<double>& rseg) :
|
const std::vector<double>& rseg) :
|
||||||
unit_system(unit_system_),
|
RstState(unit_system_, intehead, logihead, doubhead)
|
||||||
header(intehead, logihead, doubhead)
|
|
||||||
{
|
{
|
||||||
this->add_groups(zgrp, igrp, sgrp, xgrp);
|
this->add_groups(zgrp, igrp, sgrp, xgrp);
|
||||||
this->load_tuning(intehead, doubhead);
|
|
||||||
|
|
||||||
for (int iw = 0; iw < this->header.num_wells; iw++) {
|
for (int iw = 0; iw < this->header.num_wells; iw++) {
|
||||||
std::size_t zwel_offset = iw * this->header.nzwelz;
|
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;
|
std::size_t xgrp_offset = ig * this->header.nxgrpz;
|
||||||
|
|
||||||
this->groups.emplace_back(this->unit_system,
|
this->groups.emplace_back(this->unit_system,
|
||||||
|
this->header,
|
||||||
zgrp.data() + zgrp_offset,
|
zgrp.data() + zgrp_offset,
|
||||||
igrp.data() + igrp_offset,
|
igrp.data() + igrp_offset,
|
||||||
sgrp.data() + sgrp_offset,
|
sgrp.data() + sgrp_offset,
|
||||||
@ -202,30 +209,32 @@ const RstWell& RstState::get_well(const std::string& wname) const {
|
|||||||
|
|
||||||
RstState RstState::load(EclIO::ERst& rst_file, int report_step) {
|
RstState RstState::load(EclIO::ERst& rst_file, int report_step) {
|
||||||
rst_file.loadReportStepNumber(report_step);
|
rst_file.loadReportStepNumber(report_step);
|
||||||
const auto& intehead = rst_file.getRst<int>("INTEHEAD", report_step, 0);
|
const auto& intehead = rst_file.getRestartData<int>("INTEHEAD", report_step, 0);
|
||||||
const auto& logihead = rst_file.getRst<bool>("LOGIHEAD", report_step, 0);
|
const auto& logihead = rst_file.getRestartData<bool>("LOGIHEAD", report_step, 0);
|
||||||
const auto& doubhead = rst_file.getRst<double>("DOUBHEAD", report_step, 0);
|
const auto& doubhead = rst_file.getRestartData<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);
|
|
||||||
|
|
||||||
auto unit_id = intehead[VI::intehead::UNIT];
|
auto unit_id = intehead[VI::intehead::UNIT];
|
||||||
::Opm::UnitSystem unit_system(unit_id);
|
::Opm::UnitSystem unit_system(unit_id);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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")) {
|
if (rst_file.hasKey("ISEG")) {
|
||||||
const auto& iseg = rst_file.getRst<int>("ISEG", report_step, 0);
|
const auto& iseg = rst_file.getRestartData<int>("ISEG", report_step, 0);
|
||||||
const auto& rseg = rst_file.getRst<double>("RSEG", report_step, 0);
|
const auto& rseg = rst_file.getRestartData<double>("RSEG", report_step, 0);
|
||||||
|
|
||||||
return RstState(unit_system,
|
return RstState(unit_system,
|
||||||
intehead, logihead, doubhead,
|
intehead, logihead, doubhead,
|
||||||
@ -239,6 +248,8 @@ RstState RstState::load(EclIO::ERst& rst_file, int report_step) {
|
|||||||
zgrp, igrp, sgrp, xgrp,
|
zgrp, igrp, sgrp, xgrp,
|
||||||
zwel, iwel, swel, xwel,
|
zwel, iwel, swel, xwel,
|
||||||
icon, scon, xcon);
|
icon, scon, xcon);
|
||||||
|
} else
|
||||||
|
return RstState(unit_system, intehead, logihead, doubhead);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,32 +61,39 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
|||||||
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
|
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)),
|
k1k2( std::make_pair(iwel[VI::IWell::FirstK] - 1, iwel[VI::IWell::LastK] - 1)),
|
||||||
wtype( iwel[VI::IWell::WType], def_ecl_phase),
|
wtype( iwel[VI::IWell::WType], def_ecl_phase),
|
||||||
|
well_status( iwel[VI::IWell::Status]),
|
||||||
active_control( iwel[VI::IWell::ActWCtrl]),
|
active_control( iwel[VI::IWell::ActWCtrl]),
|
||||||
vfp_table( iwel[VI::IWell::VFPTab]),
|
vfp_table( iwel[VI::IWell::VFPTab]),
|
||||||
pred_requested_control( iwel[VI::IWell::PredReqWCtrl]),
|
|
||||||
allow_xflow( iwel[VI::IWell::XFlow] == 1),
|
allow_xflow( iwel[VI::IWell::XFlow] == 1),
|
||||||
|
preferred_phase( iwel[VI::IWell::PreferredPhase]),
|
||||||
hist_requested_control( iwel[VI::IWell::HistReqWCtrl]),
|
hist_requested_control( iwel[VI::IWell::HistReqWCtrl]),
|
||||||
msw_index( iwel[VI::IWell::MsWID]),
|
msw_index( iwel[VI::IWell::MsWID]),
|
||||||
completion_ordering( iwel[VI::IWell::CompOrd]),
|
completion_ordering( iwel[VI::IWell::CompOrd]),
|
||||||
pvt_table( def_pvt_table),
|
pvt_table( def_pvt_table),
|
||||||
orat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::OilRateTarget]))),
|
msw_pressure_drop_model( iwel[VI::IWell::MSW_PlossMod]),
|
||||||
wrat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::WatRateTarget]))),
|
// The values orat_target -> bhp_target_flow will be used in UDA values. The
|
||||||
grat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::GasRateTarget]))),
|
// UDA values are responsible for unit conversion and raw values are
|
||||||
lrat_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::LiqRateTarget]))),
|
// internalized here.
|
||||||
resv_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::ResVRateTarget]))),
|
orat_target( swel_value(swel[VI::SWell::OilRateTarget])),
|
||||||
thp_target( unit_system.to_si(M::identity, swel_value(swel[VI::SWell::THPTarget]))),
|
wrat_target( swel_value(swel[VI::SWell::WatRateTarget])),
|
||||||
bhp_target_float( unit_system.to_si(M::identity, swel[VI::SWell::BHPTarget])),
|
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_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_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])),
|
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])),
|
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]))),
|
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])),
|
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])),
|
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])),
|
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])),
|
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])),
|
liquid_rate( unit_system.to_si(M::rate, xwel[VI::XWell::LiqPrRate])),
|
||||||
void_rate( unit_system.to_si(M::rate, xwel[VI::XWell::VoidPrRate])),
|
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])),
|
flow_bhp( unit_system.to_si(M::pressure, xwel[VI::XWell::FlowBHP])),
|
||||||
wct( unit_system.to_si(M::water_cut, xwel[VI::XWell::WatCut])),
|
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])),
|
gor( unit_system.to_si(M::gas_oil_ratio, xwel[VI::XWell::GORatio])),
|
||||||
|
@ -129,7 +129,7 @@ Well::Well(const RestartIO::RstWell& rst_well,
|
|||||||
guide_rate(def_guide_rate),
|
guide_rate(def_guide_rate),
|
||||||
efficiency_factor(rst_well.efficiency_factor),
|
efficiency_factor(rst_well.efficiency_factor),
|
||||||
solvent_fraction(def_solvent_fraction),
|
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>()),
|
econ_limits(std::make_shared<WellEconProductionLimits>()),
|
||||||
foam_properties(std::make_shared<WellFoamProperties>()),
|
foam_properties(std::make_shared<WellFoamProperties>()),
|
||||||
polymer_properties(std::make_shared<WellPolymerProperties>()),
|
polymer_properties(std::make_shared<WellPolymerProperties>()),
|
||||||
|
Loading…
Reference in New Issue
Block a user