Files

594 lines
21 KiB
C++
Raw Permalink Normal View History

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil 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.
//
/////////////////////////////////////////////////////////////////////////////////
2024-10-21 14:40:25 +02:00
#include "Summary/RiaSummaryAddressAnalyzer.h"
#include "RiaStdStringTools.h"
2024-10-21 14:40:25 +02:00
#include "Summary/RiaSummaryCurveDefinition.h"
2025-03-10 12:08:32 +01:00
#include "RifEclipseSummaryTools.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveCollection.h"
#include <QString>
using namespace RifEclipseSummaryAddressDefines;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSummaryAddressAnalyzer::RiaSummaryAddressAnalyzer()
: m_onlyCrossPlotCurves( false )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryAddressAnalyzer::appendAddresses( const std::vector<RifEclipseSummaryAddress>& allAddresses )
{
for ( const auto& adr : allAddresses )
{
analyzeSingleAddress( adr );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryAddressAnalyzer::appendAddresses( const std::set<RifEclipseSummaryAddress>& allAddresses )
{
for ( const auto& adr : allAddresses )
{
analyzeSingleAddress( adr );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryAddressAnalyzer::appendAddresses( const std::vector<RiaSummaryCurveAddress>& addresses )
{
// RiaSummaryCurveAddress can be used to represent cross plot curves. Count curves, and set the flag m_onlyCrossPlotCurves to true if
// all curves are cross plot curves
size_t crossPlotCurveCount = 0;
for ( const auto& adr : addresses )
{
auto adrX = adr.summaryAddressX();
if ( adrX.isValid() && adrX.category() != SummaryCategory::SUMMARY_TIME )
{
crossPlotCurveCount++;
}
// Use Y address first, to make sure the ordering of cross plot names is correct
analyzeSingleAddress( adr.summaryAddressY() );
analyzeSingleAddress( adr.summaryAddressX() );
}
m_onlyCrossPlotCurves = ( crossPlotCurveCount == addresses.size() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::string> RiaSummaryAddressAnalyzer::quantities() const
{
return m_quantities;
}
//--------------------------------------------------------------------------------------------------
2022-09-05 14:12:49 +02:00
///
//--------------------------------------------------------------------------------------------------
bool RiaSummaryAddressAnalyzer::isSingleQuantityIgnoreHistory() const
{
2025-03-10 12:08:32 +01:00
return quantities().size() == 1;
2022-09-05 14:12:49 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaSummaryAddressAnalyzer::onlyCrossPlotCurves() const
{
return m_onlyCrossPlotCurves;
}
2022-09-05 14:12:49 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RiaSummaryAddressAnalyzer::quantityNameForTitle() const
{
2022-05-03 11:30:09 +02:00
if ( quantities().size() == 1 )
{
2022-05-03 11:30:09 +02:00
return *quantities().begin();
}
if ( quantities().size() == 2 && m_onlyCrossPlotCurves )
{
// We have a cross plot with only one curve
std::string title;
for ( const auto& quantity : quantities() )
{
if ( !title.empty() ) title += " | ";
title += quantity;
}
return title;
}
// Strip off the extension(H or _DIFF) and return the unique quantity name if there is only one
std::set<std::string> quantitiesNoExtension;
for ( const auto& quantity : quantities() )
{
2025-04-01 11:58:25 +02:00
const auto [vectorName, suffix] = RifEclipseSummaryTools::splitVectorNameAndSuffix( quantity );
quantitiesNoExtension.insert( vectorName );
}
if ( quantitiesNoExtension.size() == 1 )
{
return *quantitiesNoExtension.begin();
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::wellNames() const
{
return keysInMap( m_wellNames );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::groupNames() const
{
return keysInMap( m_groupNames );
}
2023-08-14 11:18:10 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::networkNames() const
{
return keysInMap( m_networkNames );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RiaSummaryAddressAnalyzer::regionNumbers() const
{
return keysInMap( m_regionNumbers );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::wellConnections( const std::string& wellName ) const
{
std::set<std::string> connections;
for ( const auto& conn : m_wellConnections )
{
if ( conn.first == wellName )
{
connections.insert( conn.second );
}
}
return connections;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RiaSummaryAddressAnalyzer::wellSegmentNumbers( const std::string& wellName ) const
{
std::set<int> segmentNumberForWell;
for ( const auto& wellSegment : m_wellSegmentNumbers )
{
if ( wellName.empty() || std::get<0>( wellSegment ) == wellName )
{
segmentNumberForWell.insert( std::get<1>( wellSegment ) );
}
}
return segmentNumberForWell;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::blocks() const
{
return keysInMap( m_blocks );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RiaSummaryAddressAnalyzer::aquifers() const
{
return keysInMap( m_aquifers );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RiaSummaryAddressAnalyzer::wellCompletionNumbers( const std::string& wellName ) const
{
std::set<int> numbers;
for ( const auto& wellAndNumber : m_wellCompletionNumbers )
{
if ( wellName.empty() || std::get<0>( wellAndNumber ) == wellName )
{
numbers.insert( std::get<1>( wellAndNumber ) );
}
}
return numbers;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2023-09-18 09:28:29 +02:00
std::set<RifEclipseSummaryAddressDefines::SummaryCategory> RiaSummaryAddressAnalyzer::categories() const
{
2022-06-07 21:09:36 +02:00
return keysInMap( m_categories );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<RifEclipseSummaryAddress>> RiaSummaryAddressAnalyzer::addressesGroupedByObject() const
{
auto wellAdr = valuesInMap( m_wellNames );
auto groupAdr = valuesInMap( m_groupNames );
2023-08-14 11:18:10 +02:00
auto networkAdr = valuesInMap( m_networkNames );
auto regionAdr = valuesInMap( m_regionNumbers );
auto blockAdr = valuesInMap( m_blocks );
auto aquiferAdr = valuesInMap( m_aquifers );
std::vector<std::vector<RifEclipseSummaryAddress>> groupedByObject;
groupedByObject.insert( groupedByObject.end(), wellAdr.begin(), wellAdr.end() );
groupedByObject.insert( groupedByObject.end(), groupAdr.begin(), groupAdr.end() );
2023-08-14 11:18:10 +02:00
groupedByObject.insert( groupedByObject.end(), networkAdr.begin(), networkAdr.end() );
groupedByObject.insert( groupedByObject.end(), regionAdr.begin(), regionAdr.end() );
groupedByObject.insert( groupedByObject.end(), blockAdr.begin(), blockAdr.end() );
groupedByObject.insert( groupedByObject.end(), aquiferAdr.begin(), aquiferAdr.end() );
2022-05-22 11:27:51 +02:00
groupedByObject.push_back( m_otherCategory );
return groupedByObject;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2023-09-18 09:28:29 +02:00
std::vector<QString> RiaSummaryAddressAnalyzer::identifierTexts( RifEclipseSummaryAddressDefines::SummaryCategory category,
const std::string& secondaryIdentifier ) const
{
std::vector<QString> identifierStrings;
2023-09-18 09:28:29 +02:00
if ( category == SummaryCategory::SUMMARY_REGION )
{
auto keys = keysInMap( m_regionNumbers );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::number( key ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_WELL )
{
auto keys = keysInMap( m_wellNames );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::fromStdString( key ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_GROUP )
{
auto keys = keysInMap( m_groupNames );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::fromStdString( key ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_NETWORK )
2023-08-14 11:18:10 +02:00
{
auto keys = keysInMap( m_networkNames );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::fromStdString( key ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_BLOCK )
{
auto keys = keysInMap( m_blocks );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::fromStdString( key ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_WELL_SEGMENT )
{
auto segmentNumbers = wellSegmentNumbers( secondaryIdentifier );
for ( const auto& segment : segmentNumbers )
{
identifierStrings.push_back( QString::number( segment ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_WELL_COMPLETION )
{
auto numbers = wellCompletionNumbers( secondaryIdentifier );
for ( const auto& number : numbers )
{
identifierStrings.push_back( QString::number( number ) );
}
}
else if ( category == SummaryCategory::SUMMARY_WELL_CONNECTION )
{
auto connections = wellConnections( secondaryIdentifier );
for ( const auto& conn : connections )
{
identifierStrings.push_back( QString::fromStdString( conn ) );
}
}
2023-09-18 09:28:29 +02:00
else if ( category == SummaryCategory::SUMMARY_AQUIFER )
{
auto keys = keysInMap( m_aquifers );
for ( const auto& key : keys )
{
identifierStrings.push_back( QString::number( key ) );
}
}
return identifierStrings;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2023-09-18 07:29:37 +00:00
std::vector<RifEclipseSummaryAddress> RiaSummaryAddressAnalyzer::addressesForCategory( const std::set<RifEclipseSummaryAddress>& addresses,
RifEclipseSummaryAddressDefines::SummaryCategory category )
{
std::vector<RifEclipseSummaryAddress> filteredAddresses;
for ( const auto& adr : addresses )
{
if ( adr.category() == category )
{
filteredAddresses.push_back( adr );
}
}
return filteredAddresses;
}
2022-06-07 21:09:36 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2023-09-18 09:28:29 +02:00
std::set<std::string> RiaSummaryAddressAnalyzer::vectorNamesForCategory( RifEclipseSummaryAddressDefines::SummaryCategory category )
2022-06-07 21:09:36 +02:00
{
auto it = m_categories.find( category );
if ( it != m_categories.end() ) return it->second;
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryAddressAnalyzer::clear()
{
m_quantities.clear();
m_wellNames.clear();
m_groupNames.clear();
2023-08-14 11:18:10 +02:00
m_networkNames.clear();
m_regionNumbers.clear();
m_categories.clear();
m_wellConnections.clear();
m_wellSegmentNumbers.clear();
m_wellCompletionNumbers.clear();
m_blocks.clear();
m_aquifers.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaSummaryAddressAnalyzer::analyzeSingleAddress( const RifEclipseSummaryAddress& address )
{
if ( !address.isValid() ) return;
if ( address.category() == SummaryCategory::SUMMARY_TIME )
{
// A time address has no other information than SummaryCategory::SUMMARY_TIME
return;
}
const std::string& wellName = address.wellName();
if ( !wellName.empty() )
{
m_wellNames.insert( { wellName, address } );
}
const auto vectorNameToUse = address.vectorName();
2025-03-10 12:08:32 +01:00
if ( !vectorNameToUse.empty() )
{
// The ordering of the quantities is used when creating titles of plots
2025-03-10 12:08:32 +01:00
if ( std::find( m_quantities.begin(), m_quantities.end(), vectorNameToUse ) == m_quantities.end() )
{
2025-03-10 12:08:32 +01:00
m_quantities.push_back( vectorNameToUse );
}
}
if ( !address.groupName().empty() )
{
m_groupNames.insert( { address.groupName(), address } );
}
2023-08-14 11:18:10 +02:00
if ( !address.networkName().empty() )
{
m_networkNames.insert( { address.networkName(), address } );
}
if ( address.category() == SummaryCategory::SUMMARY_REGION || address.category() == SummaryCategory::SUMMARY_REGION_2_REGION )
{
if ( address.regionNumber() != -1 )
{
m_regionNumbers.insert( { address.regionNumber(), address } );
}
}
if ( address.category() == SummaryCategory::SUMMARY_WELL_CONNECTION )
{
auto wellNameAndConnection = std::make_pair( wellName, address.connectionAsString() );
m_wellConnections.insert( wellNameAndConnection );
}
2023-09-18 09:28:29 +02:00
else if ( address.category() == SummaryCategory::SUMMARY_WELL_SEGMENT )
{
auto wellNameAndSegment = std::make_pair( wellName, address.wellSegmentNumber() );
m_wellSegmentNumbers.insert( wellNameAndSegment );
}
2023-09-18 09:28:29 +02:00
else if ( address.category() == SummaryCategory::SUMMARY_BLOCK )
{
auto text = address.blockAsString();
m_blocks.insert( { text, address } );
}
2023-09-18 09:28:29 +02:00
else if ( address.category() == SummaryCategory::SUMMARY_AQUIFER )
{
m_aquifers.insert( { address.aquiferNumber(), address } );
}
else if ( address.category() == SummaryCategory::SUMMARY_WELL_COMPLETION )
{
auto wellNameAndCompletion = std::make_pair( wellName, address.wellCompletionNumber() );
m_wellCompletionNumbers.insert( wellNameAndCompletion );
}
2023-09-18 09:28:29 +02:00
else if ( address.category() == SummaryCategory::SUMMARY_FIELD || address.category() == SummaryCategory::SUMMARY_MISC )
2022-05-22 11:27:51 +02:00
{
m_otherCategory.push_back( address );
}
2023-09-18 09:28:29 +02:00
if ( address.category() != SummaryCategory::SUMMARY_INVALID )
{
2022-06-07 21:09:36 +02:00
if ( m_categories.count( address.category() ) == 0 )
{
2025-03-10 12:08:32 +01:00
m_categories[address.category()] = { vectorNameToUse };
2022-06-07 21:09:36 +02:00
}
else
2025-03-10 12:08:32 +01:00
m_categories[address.category()].insert( vectorNameToUse );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<std::string> RiaSummaryAddressAnalyzer::keysInMap( const std::multimap<std::string, RifEclipseSummaryAddress>& map )
{
std::set<std::string> keys;
for ( const auto& [key, value] : map )
{
keys.insert( key );
}
return keys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RiaSummaryAddressAnalyzer::keysInMap( const std::multimap<int, RifEclipseSummaryAddress>& map )
{
std::set<int> keys;
for ( const auto& [key, value] : map )
{
keys.insert( key );
}
return keys;
}
2022-06-07 21:09:36 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2023-09-18 09:28:29 +02:00
std::set<RifEclipseSummaryAddressDefines::SummaryCategory>
RiaSummaryAddressAnalyzer::keysInMap( const std::map<RifEclipseSummaryAddressDefines::SummaryCategory, std::set<std::string>>& map )
2022-06-07 21:09:36 +02:00
{
2023-09-18 09:28:29 +02:00
std::set<RifEclipseSummaryAddressDefines::SummaryCategory> keys;
2022-06-07 21:09:36 +02:00
for ( const auto& [key, value] : map )
{
keys.insert( key );
}
return keys;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<RifEclipseSummaryAddress>>
RiaSummaryAddressAnalyzer::valuesInMap( const std::multimap<std::string, RifEclipseSummaryAddress>& map )
{
std::vector<std::vector<RifEclipseSummaryAddress>> groupedAddresses;
auto uniqueKeys = keysInMap( map );
for ( const auto& key : uniqueKeys )
{
auto range = map.equal_range( key );
std::vector<RifEclipseSummaryAddress> addresses;
for ( auto i = range.first; i != range.second; ++i )
{
addresses.push_back( i->second );
}
groupedAddresses.push_back( addresses );
}
return groupedAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<RifEclipseSummaryAddress>>
RiaSummaryAddressAnalyzer::valuesInMap( const std::multimap<int, RifEclipseSummaryAddress>& map )
{
std::vector<std::vector<RifEclipseSummaryAddress>> groupedAddresses;
auto uniqueKeys = keysInMap( map );
for ( const auto& key : uniqueKeys )
{
auto range = map.equal_range( key );
std::vector<RifEclipseSummaryAddress> addresses;
for ( auto i = range.first; i != range.second; ++i )
{
addresses.push_back( i->second );
}
groupedAddresses.push_back( addresses );
}
return groupedAddresses;
}