#9671 summary calculations for summary items

* Summary Calculation: use shorter name in title
* Sort summary addresses to group calculated results last.
* Summary Calculation: add option to distribute calculation to other items.
* Add support for summary calculation for RimGridSummaryCase.
* Use short name for calculations in plot titles.
* Update ensembles in Data Sources when calculation is added.
* Summary Calculation: allow drag-and-drop of ensembles
* Summary Plot: fix axis range aggregation for calculated ensemble addresses.

---------

Co-authored-by: Kristian Bendiksen <kristian.bendiksen@gmail.com>
This commit is contained in:
Magne Sjaastad
2023-02-26 08:08:06 +01:00
committed by GitHub
parent 69a668df50
commit 8768e186d8
51 changed files with 990 additions and 601 deletions

View File

@@ -34,7 +34,6 @@
#include "RifSummaryReaderInterface.h"
#include "RimAnalysisPlotDataEntry.h"
#include "RimCalculatedSummaryCase.h"
#include "RimDerivedSummaryCase.h"
#include "RimPlotAxisProperties.h"
#include "RimPlotAxisPropertiesInterface.h"
@@ -1590,10 +1589,7 @@ void RimAnalysisPlot::updatePlotTitle()
QStringList caseNameList;
for ( auto summaryCase : getOrCreateSelectedCurveDefAnalyser()->m_singleSummaryCases )
{
if ( !dynamic_cast<RimCalculatedSummaryCase*>( summaryCase ) )
{
caseNameList.push_back( summaryCase->displayCaseName() );
}
caseNameList.push_back( summaryCase->displayCaseName() );
}
QString root = RiaTextStringTools::commonRoot( caseNameList );

View File

@@ -20,6 +20,7 @@
#include "RiaSummaryAddressAnalyzer.h"
#include "RifEclipseSummaryAddress.h"
#include "cafPdmUiFieldHandle.h"
#include "cvfAssert.h"
@@ -141,6 +142,19 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
return true;
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
{
std::string oldString = oldValue.toString().toStdString();
std::string newString = newValue.toString().toStdString();
if ( adr->formatUiTextRegionToRegion() == oldString )
{
auto [region1, region2] = RifEclipseSummaryAddress::regionToRegionPairFromUiText( newString );
adr->setRegion( region1 );
adr->setRegion2( region2 );
return true;
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT )
{
int oldInt = oldValue.toInt();

View File

@@ -378,20 +378,6 @@ void RimMainPlotCollection::ensureDefaultFlowPlotsAreCreated()
m_flowPlotCollection()->ensureDefaultFlowPlotsAreCreated();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMainPlotCollection::ensureCalculationIdsAreAssigned()
{
std::vector<RimSummaryAddress*> allAddresses;
this->descendantsIncludingThisOfType( allAddresses );
for ( RimSummaryAddress* adr : allAddresses )
{
adr->ensureCalculationIdIsAssigned();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -88,7 +88,6 @@ public:
void scheduleUpdatePlotsWithCompletions();
void deleteAllCachedData();
void ensureDefaultFlowPlotsAreCreated();
void ensureCalculationIdsAreAssigned();
void loadDataAndUpdateAllPlots();
void updateSelectedWell( QString wellName );

View File

@@ -891,7 +891,7 @@ void RimPlotCurve::updateLegendEntryVisibilityNoPlotUpdate()
bool anyCalculated = false;
for ( const auto c : summaryPlot->summaryCurves() )
{
if ( c->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( c->summaryAddressY().isCalculated() )
{
// Never hide the legend for calculated curves, as the curve legend is used to
// show some essential auto generated data

View File

@@ -18,16 +18,22 @@
#include "RimSummaryCalculation.h"
#include "expressionparser/ExpressionParser.h"
#include "RifEclipseSummaryAddress.h"
#include "RiaCurveMerger.h"
#include "RiaLogging.h"
#include "RiaSummaryCurveDefinition.h"
#include "RiaSummaryTools.h"
#include "RifSummaryReaderInterface.h"
#include "RimDataSourceSteppingTools.h"
#include "RimProject.h"
#include "RimSummaryAddress.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCalculationVariable.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimSummaryCurve.h"
#include "RimSummaryMultiPlot.h"
#include "RimSummaryMultiPlotCollection.h"
@@ -39,6 +45,8 @@
#include "cafPdmUiTableViewEditor.h"
#include "cafPdmUiTextEditor.h"
#include "expressionparser/ExpressionParser.h"
#include <algorithm>
CAF_PDM_SOURCE_INIT( RimSummaryCalculation, "RimSummaryCalculation" );
@@ -49,6 +57,11 @@ CAF_PDM_SOURCE_INIT( RimSummaryCalculation, "RimSummaryCalculation" );
RimSummaryCalculation::RimSummaryCalculation()
{
CAF_PDM_InitObject( "RimSummaryCalculation", ":/octave.png", "Calculation", "" );
CAF_PDM_InitField( &m_distributeToOtherItems,
"DistributeToOtherItems",
true,
"Distribute to other items (wells, groups, ..)" );
}
//--------------------------------------------------------------------------------------------------
@@ -62,12 +75,54 @@ RimSummaryCalculationVariable* RimSummaryCalculation::createVariable()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCalculation::calculate()
std::optional<std::vector<SummaryCalculationVariable>> RimSummaryCalculation::getVariables() const
{
QString leftHandSideVariableName = RimSummaryCalculation::findLeftHandSide( m_expression );
std::vector<SummaryCalculationVariable> variables;
RiaTimeHistoryCurveMerger timeHistoryCurveMerger;
for ( size_t i = 0; i < m_variables.size(); i++ )
{
RimSummaryCalculationVariable* v = dynamic_cast<RimSummaryCalculationVariable*>( m_variables[i] );
CAF_ASSERT( v != nullptr );
if ( !v->summaryCase() )
{
return {};
}
if ( !v->summaryAddress() )
{
return {};
}
if ( v->summaryAddress()->address().id() == id() )
{
return {};
}
if ( v->summaryAddress()->address().isCalculated() )
{
std::set<int> calcIds;
if ( detectCyclicCalculation( v->summaryAddress()->address().id(), calcIds ) )
{
return {};
}
}
SummaryCalculationVariable variable;
variable.name = v->name();
variable.summaryCase = v->summaryCase();
variable.summaryAddress = v->summaryAddress()->address();
variables.push_back( variable );
}
return variables;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCalculation::checkVariables() const
{
for ( size_t i = 0; i < m_variables.size(); i++ )
{
RimSummaryCalculationVariable* v = dynamic_cast<RimSummaryCalculationVariable*>( m_variables[i] );
@@ -78,7 +133,6 @@ bool RimSummaryCalculation::calculate()
RiaLogging::errorInMessageBox( nullptr,
"Expression Parser",
QString( "No summary case defined for variable : %1" ).arg( v->name() ) );
return false;
}
@@ -87,11 +141,180 @@ bool RimSummaryCalculation::calculate()
RiaLogging::errorInMessageBox( nullptr,
"Expression Parser",
QString( "No summary address defined for variable : %1" ).arg( v->name() ) );
return false;
}
RiaSummaryCurveDefinition curveDef( v->summaryCase(), v->summaryAddress()->address(), false );
if ( v->summaryAddress()->address().id() == id() )
{
RiaLogging::errorInMessageBox( nullptr,
"Expression Parser",
QString( "Recursive calculation detected for variable : %1" ).arg( v->name() ) );
return false;
}
if ( v->summaryAddress()->address().isCalculated() )
{
std::set<int> calcIds;
if ( detectCyclicCalculation( v->summaryAddress()->address().id(), calcIds ) )
{
RiaLogging::errorInMessageBox( nullptr,
"Expression Parser",
QString( "Cyclic calculation detected for variable : %1" ).arg( v->name() ) );
return false;
}
}
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCalculation::detectCyclicCalculation( int id, std::set<int>& ids ) const
{
if ( ids.count( id ) > 0 )
return true;
else
{
ids.insert( id );
// Get calculation for the referenced id
RimSummaryCalculationCollection* calcColl = RimProject::current()->calculationCollection();
auto calc = dynamic_cast<RimSummaryCalculation*>( calcColl->findCalculationById( id ) );
// Check if any of the variables references already seen calculations
auto vars = calc->variables();
for ( size_t i = 0; i < vars->size(); i++ )
{
auto variable = dynamic_cast<RimSummaryCalculationVariable*>( vars->at( i ) );
auto addr = variable->summaryAddress()->address();
if ( addr.id() != -1 && detectCyclicCalculation( addr.id(), ids ) ) return true;
}
return false;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCalculation::calculate()
{
auto isOk = checkVariables();
if ( !isOk ) return false;
// Not much to do for calculate: values and timesteps are generate when needed later.
m_isDirty = false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCalculation::substituteVariables( std::vector<SummaryCalculationVariable>& vars,
const RifEclipseSummaryAddress& address )
{
auto firstVariable = vars.front();
auto category = firstVariable.summaryAddress.category();
QVariant oldValue;
QVariant newValue;
bool isHandledBySteppingTools = false;
if ( category == RifEclipseSummaryAddress::SUMMARY_WELL )
{
oldValue = QString::fromStdString( firstVariable.summaryAddress.wellName() );
newValue = QString::fromStdString( address.wellName() );
isHandledBySteppingTools = true;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION )
{
oldValue = firstVariable.summaryAddress.regionNumber();
newValue = address.regionNumber();
isHandledBySteppingTools = true;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_GROUP )
{
oldValue = QString::fromStdString( firstVariable.summaryAddress.groupName() );
newValue = QString::fromStdString( address.groupName() );
isHandledBySteppingTools = true;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_AQUIFER )
{
oldValue = firstVariable.summaryAddress.aquiferNumber();
newValue = address.aquiferNumber();
isHandledBySteppingTools = true;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION ||
category == RifEclipseSummaryAddress::SUMMARY_BLOCK )
{
oldValue = QString::fromStdString( firstVariable.summaryAddress.blockAsString() );
newValue = QString::fromStdString( address.blockAsString() );
isHandledBySteppingTools = true;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_MISC || category == RifEclipseSummaryAddress::SUMMARY_FIELD )
{
// No need to do anything for these types
return;
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
{
oldValue = QString::fromStdString( firstVariable.summaryAddress.formatUiTextRegionToRegion() );
newValue = QString::fromStdString( address.formatUiTextRegionToRegion() );
isHandledBySteppingTools = true;
}
else
{
RiaLogging::error( QString( "Unhandled subst for category: %1" ).arg( address.uiText().c_str() ) );
}
if ( isHandledBySteppingTools )
{
for ( auto& v : vars )
{
if ( v.summaryAddress.category() == address.category() )
{
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, address.category(), &v.summaryAddress );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<std::pair<std::vector<double>, std::vector<time_t>>>
RimSummaryCalculation::calculateWithSubstitutions( RimSummaryCase* summaryCase, const RifEclipseSummaryAddress& addr )
{
auto variables = getVariables();
if ( !variables ) return {};
auto vars = variables.value();
substituteVariables( vars, addr );
return calculateResult( m_expression, vars, summaryCase );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<std::pair<std::vector<double>, std::vector<time_t>>>
RimSummaryCalculation::calculateResult( const QString& expression,
const std::vector<SummaryCalculationVariable>& variables,
RimSummaryCase* summaryCase )
{
QString leftHandSideVariableName = RimSummaryCalculation::findLeftHandSide( expression );
RiaTimeHistoryCurveMerger timeHistoryCurveMerger;
for ( size_t i = 0; i < variables.size(); i++ )
{
SummaryCalculationVariable v = variables[i];
RiaSummaryCurveDefinition curveDef( summaryCase, v.summaryAddress, false );
std::vector<double> curveValues;
RiaSummaryCurveDefinition::resultValues( curveDef, &curveValues );
@@ -102,17 +325,21 @@ bool RimSummaryCalculation::calculate()
{
timeHistoryCurveMerger.addCurveData( curveTimeSteps, curveValues );
}
else
{
// One variable is missing: not possible to complete the calculation.
// Can happen when stepping and substituting variables.
return {};
}
}
timeHistoryCurveMerger.computeInterpolatedValues();
ExpressionParser parser;
for ( size_t i = 0; i < m_variables.size(); i++ )
for ( size_t i = 0; i < variables.size(); i++ )
{
RimSummaryCalculationVariable* v = dynamic_cast<RimSummaryCalculationVariable*>( m_variables[i] );
CAF_ASSERT( v != nullptr );
parser.assignVector( v->name(), timeHistoryCurveMerger.interpolatedYValuesForAllXValues( i ) );
SummaryCalculationVariable v = variables[i];
parser.assignVector( v.name, timeHistoryCurveMerger.interpolatedYValuesForAllXValues( i ) );
}
std::vector<double> resultValues;
@@ -121,13 +348,10 @@ bool RimSummaryCalculation::calculate()
parser.assignVector( leftHandSideVariableName, resultValues );
QString errorText;
bool evaluatedOk = parser.expandIfStatementsAndEvaluate( m_expression, &errorText );
bool evaluatedOk = parser.expandIfStatementsAndEvaluate( expression, &errorText );
if ( evaluatedOk )
{
m_timesteps.v().clear();
m_calculatedValues.v().clear();
if ( timeHistoryCurveMerger.validIntervalsForAllXValues().size() > 0 )
{
size_t firstValidTimeStep = timeHistoryCurveMerger.validIntervalsForAllXValues().front().first;
@@ -141,12 +365,9 @@ bool RimSummaryCalculation::calculate()
std::vector<double> validValues( resultValues.begin() + firstValidTimeStep,
resultValues.begin() + lastValidTimeStep );
m_timesteps = validTimeSteps;
m_calculatedValues = validValues;
return std::make_pair( validValues, validTimeSteps );
}
}
m_isDirty = false;
}
else
{
@@ -156,7 +377,7 @@ bool RimSummaryCalculation::calculate()
RiaLogging::errorInMessageBox( nullptr, "Expression Parser", s );
}
return evaluatedOk;
return {};
}
//--------------------------------------------------------------------------------------------------
@@ -168,6 +389,23 @@ void RimSummaryCalculation::updateDependentObjects()
this->firstAncestorOrThisOfTypeAsserted( calcColl );
calcColl->rebuildCaseMetaData();
// Refresh data sources tree.
// TODO: refresh too much: would be enough to only refresh calculated resutls.
RimSummaryCaseMainCollection* summaryCaseCollection = RiaSummaryTools::summaryCaseMainCollection();
auto summaryCases = summaryCaseCollection->allSummaryCases();
for ( RimSummaryCase* summaryCase : summaryCases )
{
summaryCase->createSummaryReaderInterface();
summaryCase->createRftReaderInterface();
summaryCase->refreshMetaData();
}
auto summaryCaseCollections = summaryCaseCollection->summaryCaseCollections();
for ( RimSummaryCaseCollection* summaryCaseCollection : summaryCaseCollections )
{
summaryCaseCollection->refreshMetaData();
}
RimSummaryMultiPlotCollection* summaryPlotCollection = RiaSummaryTools::summaryMultiPlotCollection();
for ( auto multiPlot : summaryPlotCollection->multiPlots() )
{
@@ -177,7 +415,7 @@ void RimSummaryCalculation::updateDependentObjects()
for ( RimSummaryCurve* sumCurve : sumPlot->summaryCurves() )
{
if ( sumCurve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( sumCurve->summaryAddressY().isCalculated() )
{
sumCurve->updateConnectedEditors();
@@ -199,3 +437,216 @@ void RimSummaryCalculation::updateDependentObjects()
void RimSummaryCalculation::removeDependentObjects()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCalculationAddress> RimSummaryCalculation::allAddressesForSummaryCase( RimSummaryCase* summaryCase ) const
{
auto variables = getVariables();
if ( variables && !variables.value().empty() )
{
// The first variable is the substituable one. Use its category to
// provide all available addresses.
auto firstVariable = variables.value().front();
if ( m_distributeToOtherItems )
{
auto allResultAddresses = summaryCase->summaryReader()->allResultAddresses();
return allAddressesForCategory( firstVariable.summaryAddress.category(), allResultAddresses );
}
else
{
// Generate the result only for the first variable
return { RimSummaryCalculationAddress( singleAddressesForCategory( firstVariable.summaryAddress ) ) };
}
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCalculationAddress>
RimSummaryCalculation::allAddressesForCategory( RifEclipseSummaryAddress::SummaryVarCategory category,
const std::set<RifEclipseSummaryAddress>& allResultAddresses ) const
{
std::vector<RimSummaryCalculationAddress> addresses;
std::string name = shortName().toStdString();
if ( category == RifEclipseSummaryAddress::SUMMARY_FIELD )
{
addresses.push_back( RimSummaryCalculationAddress( RifEclipseSummaryAddress::fieldAddress( name, m_id ) ) );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_AQUIFER )
{
std::set<int> uniqueNumbers;
std::for_each( allResultAddresses.begin(), allResultAddresses.end(), [&]( const auto& addr ) {
uniqueNumbers.insert( addr.aquiferNumber() );
} );
for ( auto num : uniqueNumbers )
{
addresses.push_back(
RimSummaryCalculationAddress( RifEclipseSummaryAddress::aquiferAddress( name, num, m_id ) ) );
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_MISC )
{
addresses.push_back( RimSummaryCalculationAddress( RifEclipseSummaryAddress::miscAddress( name, m_id ) ) );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_NETWORK )
{
addresses.push_back( RimSummaryCalculationAddress( RifEclipseSummaryAddress::networkAddress( name, m_id ) ) );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_WELL )
{
std::set<std::string> uniqueWellNames;
std::for_each( allResultAddresses.begin(), allResultAddresses.end(), [&]( const auto& addr ) {
uniqueWellNames.insert( addr.wellName() );
} );
for ( auto wellName : uniqueWellNames )
{
addresses.push_back(
RimSummaryCalculationAddress( RifEclipseSummaryAddress::wellAddress( name, wellName, m_id ) ) );
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_GROUP )
{
std::set<std::string> uniqueGroupNames;
std::for_each( allResultAddresses.begin(), allResultAddresses.end(), [&]( const auto& addr ) {
uniqueGroupNames.insert( addr.groupName() );
} );
for ( auto groupName : uniqueGroupNames )
{
addresses.push_back(
RimSummaryCalculationAddress( RifEclipseSummaryAddress::groupAddress( name, groupName, m_id ) ) );
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION )
{
std::set<int> uniqueRegionNumbers;
std::for_each( allResultAddresses.begin(), allResultAddresses.end(), [&]( const auto& addr ) {
uniqueRegionNumbers.insert( addr.regionNumber() );
} );
for ( auto regionNumber : uniqueRegionNumbers )
{
addresses.push_back(
RimSummaryCalculationAddress( RifEclipseSummaryAddress::regionAddress( name, regionNumber, m_id ) ) );
}
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
{
std::set<std::pair<int, int>> uniqueRegionNumbers;
std::for_each( allResultAddresses.begin(), allResultAddresses.end(), [&]( const auto& addr ) {
uniqueRegionNumbers.insert( std::make_pair( addr.regionNumber(), addr.regionNumber2() ) );
} );
for ( auto regionNumber : uniqueRegionNumbers )
{
auto [r1, r2] = regionNumber;
addresses.push_back(
RimSummaryCalculationAddress( RifEclipseSummaryAddress::regionToRegionAddress( name, r1, r2, m_id ) ) );
}
}
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCalculationAddress RimSummaryCalculation::singleAddressesForCategory( const RifEclipseSummaryAddress& address ) const
{
std::string name = shortName().toStdString();
RifEclipseSummaryAddress::SummaryVarCategory category = address.category();
if ( category == RifEclipseSummaryAddress::SUMMARY_FIELD )
{
return RifEclipseSummaryAddress::fieldAddress( name, m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_AQUIFER )
{
return RifEclipseSummaryAddress::aquiferAddress( name, address.aquiferNumber(), m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_MISC )
{
return RifEclipseSummaryAddress::miscAddress( name, m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_NETWORK )
{
return RifEclipseSummaryAddress::networkAddress( name, m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_WELL )
{
return RifEclipseSummaryAddress::wellAddress( name, address.wellName(), m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_GROUP )
{
return RifEclipseSummaryAddress::groupAddress( name, address.groupName(), m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION )
{
return RifEclipseSummaryAddress::regionAddress( name, address.regionNumber(), m_id );
}
else if ( category == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
{
return RifEclipseSummaryAddress::regionToRegionAddress( name, address.regionNumber(), address.regionNumber2(), m_id );
}
return RifEclipseSummaryAddress();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimSummaryCalculation::values( RimSummaryCase* summaryCase, const RimSummaryCalculationAddress& address )
{
CAF_ASSERT( summaryCase );
const auto& result = calculateWithSubstitutions( summaryCase, address.address() );
if ( result )
{
auto [validValues, validTimeSteps] = result.value();
return validValues;
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<time_t> RimSummaryCalculation::timeSteps( RimSummaryCase* summaryCase,
const RimSummaryCalculationAddress& address )
{
CAF_ASSERT( summaryCase );
const auto& result = calculateWithSubstitutions( summaryCase, address.address() );
if ( result )
{
auto [validValues, validTimeSteps] = result.value();
return validTimeSteps;
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryCalculation::buildCalculationName() const
{
QString name = "Default Calculation Name";
if ( !m_expression.v().isEmpty() )
{
name = m_expression;
}
return name;
}

View File

@@ -25,6 +25,27 @@
///
///
//==================================================================================================
class RimSummaryCalculationAddress
{
public:
RimSummaryCalculationAddress( RifEclipseSummaryAddress summaryAddress )
: m_summaryAddress( summaryAddress )
{
}
RifEclipseSummaryAddress address() const { return m_summaryAddress; }
private:
RifEclipseSummaryAddress m_summaryAddress;
};
struct SummaryCalculationVariable
{
QString name;
RimSummaryCase* summaryCase;
RifEclipseSummaryAddress summaryAddress;
};
class RimSummaryCalculation : public RimUserDefinedCalculation
{
CAF_PDM_HEADER_INIT;
@@ -32,10 +53,42 @@ class RimSummaryCalculation : public RimUserDefinedCalculation
public:
RimSummaryCalculation();
std::vector<RimSummaryCalculationAddress> allAddressesForSummaryCase( RimSummaryCase* summaryCase ) const;
std::vector<double> values( RimSummaryCase* summaryCase, const RimSummaryCalculationAddress& addr );
std::vector<time_t> timeSteps( RimSummaryCase* summaryCase, const RimSummaryCalculationAddress& addr );
bool calculate() override;
void updateDependentObjects() override;
void removeDependentObjects() override;
QString buildCalculationName() const override;
protected:
RimSummaryCalculationVariable* createVariable() override;
static std::optional<std::pair<std::vector<double>, std::vector<time_t>>>
calculateResult( const QString& expression,
const std::vector<SummaryCalculationVariable>& variables,
RimSummaryCase* summaryCase );
std::optional<std::pair<std::vector<double>, std::vector<time_t>>>
calculateWithSubstitutions( RimSummaryCase* summaryCase, const RifEclipseSummaryAddress& addr );
static void substituteVariables( std::vector<SummaryCalculationVariable>& vars,
const RifEclipseSummaryAddress& address );
std::vector<RimSummaryCalculationAddress>
allAddressesForCategory( RifEclipseSummaryAddress::SummaryVarCategory category,
const std::set<RifEclipseSummaryAddress>& allResultAddresses ) const;
RimSummaryCalculationAddress singleAddressesForCategory( const RifEclipseSummaryAddress& address ) const;
std::optional<std::vector<SummaryCalculationVariable>> getVariables() const;
bool checkVariables() const;
bool detectCyclicCalculation( int id, std::set<int>& ids ) const;
caf::PdmField<bool> m_distributeToOtherItems;
};

View File

@@ -18,13 +18,8 @@
#include "RimSummaryCalculationCollection.h"
#include "RimCalculatedSummaryCase.h"
#include "RimProject.h"
#include "RimSummaryCalculation.h"
#include "cafPdmUiGroup.h"
#include "cafPdmUiTreeSelectionEditor.h"
CAF_PDM_SOURCE_INIT( RimSummaryCalculationCollection, "RimSummaryCalculationCollection" );
//--------------------------------------------------------------------------------------------------
///
@@ -32,10 +27,6 @@ CAF_PDM_SOURCE_INIT( RimSummaryCalculationCollection, "RimSummaryCalculationColl
RimSummaryCalculationCollection::RimSummaryCalculationCollection()
{
CAF_PDM_InitObject( "Calculation Collection", ":/chain.png" );
CAF_PDM_InitFieldNoDefault( &m_calcuationSummaryCase, "CalculationsSummaryCase", "Calculations Summary Case" );
m_calcuationSummaryCase.xmlCapability()->disableIO();
m_calcuationSummaryCase = new RimCalculatedSummaryCase;
}
//--------------------------------------------------------------------------------------------------
@@ -46,21 +37,12 @@ RimSummaryCalculation* RimSummaryCalculationCollection::createCalculation() cons
return new RimSummaryCalculation;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimSummaryCalculationCollection::calculationSummaryCase()
{
return m_calcuationSummaryCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryCalculationCollection::rebuildCaseMetaData()
{
ensureValidCalculationIds();
m_calcuationSummaryCase->buildMetaData();
}
//--------------------------------------------------------------------------------------------------

View File

@@ -21,8 +21,6 @@
#include "RimSummaryCalculation.h"
#include "RimUserDefinedCalculationCollection.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmObject.h"
class RimSummaryCase;
@@ -39,15 +37,10 @@ class RimSummaryCalculationCollection : public RimUserDefinedCalculationCollecti
public:
RimSummaryCalculationCollection();
RimSummaryCase* calculationSummaryCase();
void rebuildCaseMetaData() override;
RimSummaryCalculation* createCalculation() const override;
private:
void initAfterRead() override;
private:
caf::PdmChildField<RimCalculatedSummaryCase*> m_calcuationSummaryCase;
};

View File

@@ -28,6 +28,7 @@
#include "RimSummaryAddress.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCurve.h"
#include "RiuDragDrop.h"
@@ -69,6 +70,7 @@ void RimSummaryCalculationVariable::fieldChangedByUi( const caf::PdmFieldHandle*
{
RiuSummaryVectorSelectionDialog dlg( nullptr );
dlg.hideEnsembles();
dlg.hideCalculationIncompatibleCategories();
readDataFromApplicationStore( &dlg );
@@ -140,6 +142,16 @@ void RimSummaryCalculationVariable::setSummaryAddress( const RimSummaryAddress&
auto summaryCase = RiaSummaryTools::summaryCaseById( address.caseId() );
// Use first summary case for ensemble addresses
if ( address.isEnsemble() )
{
auto ensemble = RiaSummaryTools::ensembleById( address.ensembleId() );
if ( ensemble )
{
summaryCase = ensemble->firstSummaryCase();
}
}
if ( summaryCase ) m_case = summaryCase;
}

View File

@@ -67,9 +67,13 @@ RimUserDefinedCalculation::RimUserDefinedCalculation()
m_unit.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_variables, "Variables", "Variables" );
CAF_PDM_InitFieldNoDefault( &m_calculatedValues, "CalculatedValues", "Calculated Values" );
CAF_PDM_InitFieldNoDefault( &m_timesteps, "TimeSteps", "Time Steps" );
CAF_PDM_InitFieldNoDefault( &m_calculatedValues_OBSOLETE, "CalculatedValues", "Calculated Values" );
m_calculatedValues_OBSOLETE.xmlCapability()->disableIO();
CAF_PDM_InitFieldNoDefault( &m_timesteps_OBSOLETE, "TimeSteps", "Time Steps" );
m_timesteps_OBSOLETE.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_id, "Id", -1, "Id" );
m_id.uiCapability()->setUiHidden( true );
@@ -149,22 +153,6 @@ void RimUserDefinedCalculation::deleteVariable( RimUserDefinedCalculationVariabl
delete calcVariable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RimUserDefinedCalculation::values() const
{
return m_calculatedValues();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RimUserDefinedCalculation::timeSteps() const
{
return m_timesteps();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -421,3 +409,11 @@ std::vector<RimUserDefinedCalculationVariable*> RimUserDefinedCalculation::allVa
{
return m_variables.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimUserDefinedCalculation::shortName() const
{
return RimUserDefinedCalculation::findLeftHandSide( m_expression );
}

View File

@@ -51,9 +51,6 @@ public:
std::vector<RimUserDefinedCalculationVariable*> allVariables() const;
const std::vector<double>& values() const;
const std::vector<time_t>& timeSteps() const;
void setExpression( const QString& expr );
QString expression() const;
QString unitName() const;
@@ -68,6 +65,8 @@ public:
static QString findLeftHandSide( const QString& expression );
void attachToWidget();
QString shortName() const;
protected:
virtual RimUserDefinedCalculationVariable* createVariable() = 0;
@@ -81,7 +80,7 @@ protected:
RimUserDefinedCalculationVariable* addVariable( const QString& name );
void deleteVariable( RimUserDefinedCalculationVariable* calcVariable );
QString buildCalculationName() const;
virtual QString buildCalculationName() const;
protected:
caf::PdmField<QString> m_description;
@@ -92,8 +91,8 @@ protected:
caf::PdmChildArrayField<RimUserDefinedCalculationVariable*> m_variables;
caf::PdmField<std::vector<double>> m_calculatedValues;
caf::PdmField<std::vector<time_t>> m_timesteps;
caf::PdmField<std::vector<double>> m_calculatedValues_OBSOLETE;
caf::PdmField<std::vector<time_t>> m_timesteps_OBSOLETE;
caf::PdmField<int> m_id;
std::unique_ptr<RiuExpressionContextMenuManager> m_exprContextMenuMgr;

View File

@@ -18,7 +18,6 @@
#include "RimUserDefinedCalculationCollection.h"
#include "RimCalculatedSummaryCase.h"
#include "RimProject.h"
#include "RimUserDefinedCalculation.h"

View File

@@ -18,7 +18,6 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimObservedSummaryData.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryObservedDataFile.h
${CMAKE_CURRENT_LIST_DIR}/RimObservedEclipseUserData.h
${CMAKE_CURRENT_LIST_DIR}/RimCalculatedSummaryCase.h
${CMAKE_CURRENT_LIST_DIR}/RimCalculatedSummaryCurveReader.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddress.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryCrossPlot.h
@@ -70,7 +69,6 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimObservedSummaryData.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryObservedDataFile.cpp
${CMAKE_CURRENT_LIST_DIR}/RimObservedEclipseUserData.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCalculatedSummaryCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCalculatedSummaryCurveReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddress.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryCrossPlot.cpp

View File

@@ -1,88 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimCalculatedSummaryCase.h"
#include "RiaSummaryDefines.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCalculationCollection.h"
CAF_PDM_SOURCE_INIT( RimCalculatedSummaryCase, "CalculatedSummaryCase" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCalculatedSummaryCase::RimCalculatedSummaryCase()
{
CAF_PDM_InitObject( "Calculated", ":/SummaryCase.svg" );
m_calculatedCurveReader = nullptr;
m_displayName = RiaDefines::summaryCalculated();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCalculatedSummaryCase::~RimCalculatedSummaryCase()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimCalculatedSummaryCase::caseName() const
{
return RiaDefines::summaryCalculated();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCalculatedSummaryCase::createSummaryReaderInterface()
{
if ( !m_calculatedCurveReader )
{
RimSummaryCalculationCollection* calculationCollection = nullptr;
this->firstAncestorOrThisOfTypeAsserted( calculationCollection );
m_calculatedCurveReader.reset( new RifCalculatedSummaryCurveReader( calculationCollection ) );
m_calculatedCurveReader->buildMetaData();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifSummaryReaderInterface* RimCalculatedSummaryCase::summaryReader()
{
if ( !m_calculatedCurveReader ) createSummaryReaderInterface();
return m_calculatedCurveReader.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCalculatedSummaryCase::buildMetaData()
{
if ( !m_calculatedCurveReader ) createSummaryReaderInterface();
m_calculatedCurveReader->buildMetaData();
}

View File

@@ -1,50 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifSummaryReaderInterface.h"
#include "RimCalculatedSummaryCurveReader.h"
#include "RimSummaryCase.h"
#include <memory>
class RifCalculatedSummaryCurveReader;
class RimSummaryCalculation;
class RimSummaryCalculationCollection;
//==================================================================================================
//
//==================================================================================================
class RimCalculatedSummaryCase : public RimSummaryCase
{
CAF_PDM_HEADER_INIT;
public:
RimCalculatedSummaryCase();
~RimCalculatedSummaryCase() override;
QString caseName() const override;
void createSummaryReaderInterface() override;
RifSummaryReaderInterface* summaryReader() override;
void buildMetaData();
private:
std::unique_ptr<RifCalculatedSummaryCurveReader> m_calculatedCurveReader;
};

View File

@@ -18,15 +18,20 @@
#include "RimCalculatedSummaryCurveReader.h"
#include "RifEclipseSummaryAddress.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCalculationCollection.h"
#include "RimUserDefinedCalculation.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifCalculatedSummaryCurveReader::RifCalculatedSummaryCurveReader( RimSummaryCalculationCollection* calculationCollection )
RifCalculatedSummaryCurveReader::RifCalculatedSummaryCurveReader( RimSummaryCalculationCollection* calculationCollection,
RimSummaryCase* summaryCase )
: m_calculationCollection( calculationCollection )
, m_summaryCase( summaryCase )
{
CAF_ASSERT( summaryCase );
}
//--------------------------------------------------------------------------------------------------
@@ -35,9 +40,10 @@ RifCalculatedSummaryCurveReader::RifCalculatedSummaryCurveReader( RimSummaryCalc
std::vector<time_t> RifCalculatedSummaryCurveReader::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
{
RimSummaryCalculation* calc = findCalculationByName( resultAddress );
if ( calc )
if ( calc && m_summaryCase )
{
return calc->timeSteps();
RimSummaryCalculationAddress address( resultAddress );
return calc->timeSteps( m_summaryCase, address );
}
return {};
@@ -49,9 +55,10 @@ std::vector<time_t> RifCalculatedSummaryCurveReader::timeSteps( const RifEclipse
bool RifCalculatedSummaryCurveReader::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
{
RimSummaryCalculation* calc = findCalculationByName( resultAddress );
if ( calc )
if ( calc && m_summaryCase )
{
*values = calc->values();
RimSummaryCalculationAddress address( resultAddress );
*values = calc->values( m_summaryCase, address );
return true;
}
@@ -82,8 +89,17 @@ void RifCalculatedSummaryCurveReader::buildMetaData()
for ( RimUserDefinedCalculation* calc : m_calculationCollection->calculations() )
{
m_allResultAddresses.insert(
RifEclipseSummaryAddress::calculatedAddress( calc->description().toStdString(), calc->id() ) );
RimSummaryCalculation* sumCalc = dynamic_cast<RimSummaryCalculation*>( calc );
CAF_ASSERT( sumCalc );
const auto& allAddresses = sumCalc->allAddressesForSummaryCase( m_summaryCase );
for ( auto calculationAddress : allAddresses )
{
if ( calculationAddress.address().isValid() )
{
m_allResultAddresses.insert( calculationAddress.address() );
}
}
}
}
@@ -93,12 +109,9 @@ void RifCalculatedSummaryCurveReader::buildMetaData()
RimSummaryCalculation*
RifCalculatedSummaryCurveReader::findCalculationByName( const RifEclipseSummaryAddress& resultAddress ) const
{
if ( m_calculationCollection && resultAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{
return dynamic_cast<RimSummaryCalculation*>( m_calculationCollection->findCalculationById( resultAddress.id() ) );
}
if ( !m_calculationCollection || !resultAddress.isCalculated() ) return nullptr;
return nullptr;
return dynamic_cast<RimSummaryCalculation*>( m_calculationCollection->findCalculationById( resultAddress.id() ) );
}
//--------------------------------------------------------------------------------------------------

View File

@@ -33,7 +33,8 @@ class RimSummaryCalculationCollection;
class RifCalculatedSummaryCurveReader : public RifSummaryReaderInterface
{
public:
explicit RifCalculatedSummaryCurveReader( RimSummaryCalculationCollection* calculationCollection );
explicit RifCalculatedSummaryCurveReader( RimSummaryCalculationCollection* calculationCollection,
RimSummaryCase* summaryCase );
std::vector<time_t> timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
@@ -48,4 +49,5 @@ private:
private:
caf::PdmPointer<RimSummaryCalculationCollection> m_calculationCollection;
caf::PdmPointer<RimSummaryCase> m_summaryCase;
};

View File

@@ -27,6 +27,7 @@
#include "RiaSummaryCurveDefinition.h"
#include "RiaTimeTTools.h"
#include "RimSummaryCalculationCollection.h"
#include "SummaryPlotCommands/RicSummaryPlotEditorUi.h"
#include "RifEnsembleStatisticsReader.h"
@@ -46,6 +47,7 @@
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimSummaryAddress.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCurve.h"

View File

@@ -32,8 +32,10 @@
#include "RifReaderOpmRft.h"
#include "RifSummaryReaderMultipleFiles.h"
#include "RimCalculatedSummaryCurveReader.h"
#include "RimProject.h"
#include "RimRftCase.h"
#include "RimSummaryCalculationCollection.h"
#include "RimTools.h"
#include "cafPdmFieldScriptingCapability.h"
@@ -116,14 +118,20 @@ void RimFileSummaryCase::createSummaryReaderInterfaceThreadSafe( RiaThreadSafeLo
void RimFileSummaryCase::createSummaryReaderInterface()
{
RiaThreadSafeLogger threadSafeLogger;
m_fileSummaryReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_fileSummaryReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_includeRestartFiles,
&threadSafeLogger );
RimSummaryCalculationCollection* calcColl = RimProject::current()->calculationCollection();
m_calculatedSummaryReader = new RifCalculatedSummaryCurveReader( calcColl, this );
m_multiSummaryReader = new RifMultipleSummaryReaders;
m_multiSummaryReader->addReader( m_fileSummaryReader.p() );
openAndAttachAdditionalReader();
m_multiSummaryReader->addReader( m_calculatedSummaryReader.p() );
auto messages = threadSafeLogger.messages();
for ( const auto& m : messages )
{

View File

@@ -30,6 +30,7 @@ class RifOpmCommonEclipseSummary;
class RifEclipseSummaryAddress;
class RifMultipleSummaryReaders;
class RimRftCase;
class RifCalculatedSummaryCurveReader;
//==================================================================================================
//
@@ -77,10 +78,11 @@ private:
static RifReaderOpmRft* findRftDataAndCreateReader( const QString& rftFileName, const QString& dataDeckFileName );
private:
cvf::ref<RifSummaryReaderInterface> m_fileSummaryReader;
cvf::ref<RifMultipleSummaryReaders> m_multiSummaryReader;
cvf::ref<RifReaderOpmRft> m_summaryEclipseRftReader;
caf::PdmField<bool> m_includeRestartFiles;
cvf::ref<RifSummaryReaderInterface> m_fileSummaryReader;
cvf::ref<RifCalculatedSummaryCurveReader> m_calculatedSummaryReader;
cvf::ref<RifMultipleSummaryReaders> m_multiSummaryReader;
cvf::ref<RifReaderOpmRft> m_summaryEclipseRftReader;
caf::PdmField<bool> m_includeRestartFiles;
caf::PdmField<caf::FilePath> m_additionalSummaryFilePath;
cvf::ref<RifOpmCommonEclipseSummary> m_additionalSummaryFileReader;

View File

@@ -20,11 +20,14 @@
#include "RicfCommandObject.h"
#include "RifMultipleSummaryReaders.h"
#include "RifSummaryReaderInterface.h"
#include "RimCalculatedSummaryCurveReader.h"
#include "RimEclipseCase.h"
#include "RimFileSummaryCase.h"
#include "RimProject.h"
#include "RimSummaryCalculationCollection.h"
#include "cafPdmObjectScriptingCapability.h"
@@ -179,9 +182,16 @@ QString RimGridSummaryCase::eclipseGridFileName() const
//--------------------------------------------------------------------------------------------------
void RimGridSummaryCase::createSummaryReaderInterface()
{
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_fileSummaryReader = RimFileSummaryCase::findRelatedFilesAndCreateReader( this->summaryHeaderFilename(),
m_includeRestartFiles,
nullptr );
m_multiSummaryReader = new RifMultipleSummaryReaders;
m_multiSummaryReader->addReader( m_fileSummaryReader.p() );
RimSummaryCalculationCollection* calcColl = RimProject::current()->calculationCollection();
m_calculatedSummaryReader = new RifCalculatedSummaryCurveReader( calcColl, this );
m_multiSummaryReader->addReader( m_calculatedSummaryReader.p() );
}
//--------------------------------------------------------------------------------------------------
@@ -189,11 +199,11 @@ void RimGridSummaryCase::createSummaryReaderInterface()
//--------------------------------------------------------------------------------------------------
RifSummaryReaderInterface* RimGridSummaryCase::summaryReader()
{
if ( m_summaryFileReader.isNull() )
if ( m_multiSummaryReader.isNull() )
{
createSummaryReaderInterface();
}
return m_summaryFileReader.p();
return m_multiSummaryReader.p();
}
//--------------------------------------------------------------------------------------------------

View File

@@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifMultipleSummaryReaders.h"
#include "RimSummaryCase.h"
#include "cafPdmProxyValueField.h"
@@ -27,6 +28,8 @@
class RimEclipseCase;
class RifSummaryReaderInterface;
class RimFileSummaryCase;
class RifCalculatedSummaryCurveReader;
class RifMultipleSummaryReaders;
//==================================================================================================
//
@@ -63,6 +66,8 @@ private:
mutable caf::PdmField<QString> m_cachedCaseName;
caf::PdmProxyValueField<QString> m_eclipseGridFileName;
cvf::ref<RifSummaryReaderInterface> m_summaryFileReader;
caf::PdmField<bool> m_includeRestartFiles;
cvf::ref<RifSummaryReaderInterface> m_fileSummaryReader;
cvf::ref<RifCalculatedSummaryCurveReader> m_calculatedSummaryReader;
cvf::ref<RifMultipleSummaryReaders> m_multiSummaryReader;
caf::PdmField<bool> m_includeRestartFiles;
};

View File

@@ -47,7 +47,6 @@ void caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>::setUp()
addItem( RifAdr::SUMMARY_WELL_SEGMENT, "SUMMARY_SEGMENT", RiaDefines::summarySegment() );
addItem( RifAdr::SUMMARY_BLOCK, "SUMMARY_BLOCK", RiaDefines::summaryBlock() );
addItem( RifAdr::SUMMARY_BLOCK_LGR, "SUMMARY_BLOCK_LGR", RiaDefines::summaryLgrBlock() );
addItem( RifAdr::SUMMARY_CALCULATED, "SUMMARY_CALCULATED", RiaDefines::summaryCalculated() );
addItem( RifAdr::SUMMARY_IMPORTED, "SUMMARY_IMPORTED", "Imported" );
addItem( RifAdr::SUMMARY_ENSEMBLE_STATISTICS, "SUMMARY_ENSEMBLE_STATISTICS", "Ensemble Statistics" );
setDefault( RifAdr::SUMMARY_FIELD );
@@ -137,6 +136,7 @@ void RimSummaryAddress::setAddress( const RifEclipseSummaryAddress& addr )
m_calculationId = addr.id();
setUiName( m_vectorName );
setUiIconFromResourceString( iconResourceText() );
}
//--------------------------------------------------------------------------------------------------
@@ -160,27 +160,6 @@ RifEclipseSummaryAddress RimSummaryAddress::address() const
m_calculationId );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryAddress::ensureCalculationIdIsAssigned()
{
if ( m_category == RifEclipseSummaryAddress::SUMMARY_CALCULATED && m_calculationId == -1 )
{
RimSummaryCalculationCollection* calcColl = RimProject::current()->calculationCollection();
for ( const RimUserDefinedCalculation* c : calcColl->calculations() )
{
QString description = c->description();
if ( description == m_vectorName )
{
m_calculationId = c->id();
}
}
}
}
//--------------------------------------------------------------------------------------------------
/// Return phase type if the current result is known to be of a particular
/// fluid phase type. Otherwise the method will return PHASE_NOT_APPLICABLE.
@@ -271,3 +250,13 @@ bool RimSummaryAddress::isEnsemble() const
{
return m_ensembleId >= 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryAddress::iconResourceText() const
{
if ( m_calculationId != -1 ) return ":/summary/components/images/calculated.svg";
return ":/DataVector.png";
}

View File

@@ -68,6 +68,8 @@ public:
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QString iconResourceText() const;
private:
caf::PdmField<caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>> m_category;

View File

@@ -180,10 +180,22 @@ void RimSummaryAddressCollection::updateFolderStructure( const std::set<RifEclip
auto* lgrwell = getOrCreateSubfolder( CollectionContentType::WELL_LGR );
auto* lgrcompletion = getOrCreateSubfolder( CollectionContentType::WELL_COMPLETION_LGR );
auto* lgrblock = getOrCreateSubfolder( CollectionContentType::BLOCK_LGR );
auto* calculated = getOrCreateSubfolder( CollectionContentType::CALCULATED );
auto* imported = getOrCreateSubfolder( CollectionContentType::IMPORTED );
for ( const auto& address : addresses )
// Sort addresses to have calculated results last per category
std::vector<RifEclipseSummaryAddress> sortedAddresses( addresses.size() );
std::copy( addresses.begin(), addresses.end(), sortedAddresses.begin() );
std::sort( sortedAddresses.begin(),
sortedAddresses.end(),
[]( const RifEclipseSummaryAddress& a, const RifEclipseSummaryAddress& b ) -> bool {
if ( a.category() < b.category() ) return false;
// Calculated results are sorted last.
if ( a.isCalculated() && !b.isCalculated() ) return false;
if ( !a.isCalculated() && b.isCalculated() ) return true;
return a.vectorName() < b.vectorName();
} );
for ( const auto& address : sortedAddresses )
{
switch ( address.category() )
{
@@ -301,14 +313,6 @@ void RimSummaryAddressCollection::updateFolderStructure( const std::set<RifEclip
ensembleId );
break;
case RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_CALCULATED:
calculated->addToSubfolder( QString::fromStdString( address.itemUiText() ),
CollectionContentType::CALCULATED,
address,
caseId,
ensembleId );
break;
default:
continue;
}

View File

@@ -30,6 +30,7 @@
#include "RimProject.h"
#include "RimSummaryAddress.h"
#include "RimSummaryAddressCollection.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCaseCollection.h"
#include "cafPdmFieldScriptingCapability.h"
@@ -244,7 +245,8 @@ void RimSummaryCase::buildChildNodes()
RifSummaryReaderInterface* reader = summaryReader();
if ( !reader ) return;
m_dataVectorFolders->updateFolderStructure( reader->allResultAddresses(), m_caseId );
auto addresses = reader->allResultAddresses();
m_dataVectorFolders->updateFolderStructure( addresses, m_caseId );
}
//--------------------------------------------------------------------------------------------------

View File

@@ -34,6 +34,7 @@
#include "RimGridSummaryCase.h"
#include "RimProject.h"
#include "RimSummaryAddressCollection.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCase.h"
#include "RifReaderEclipseRft.h"
@@ -328,6 +329,7 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::ensembleSummaryAddr
const std::set<RifEclipseSummaryAddress>& addrs = m_cases[maxAddrIndex]->summaryReader()->allResultAddresses();
addresses.insert( addrs.begin(), addrs.end() );
}
return addresses;
}

View File

@@ -475,20 +475,25 @@ QList<caf::PdmOptionItemInfo> RimSummaryCurve::calculateValueOptions( const caf:
QList<caf::PdmOptionItemInfo> options = this->RimPlotCurve::calculateValueOptions( fieldNeedingOptions );
if ( !options.isEmpty() ) return options;
if ( fieldNeedingOptions == &m_yValuesSummaryCase || fieldNeedingOptions == &m_xValuesSummaryCase )
{
RimProject* proj = RimProject::current();
auto createOptionsForSummaryCase = []( RimSummaryCase* summaryCase, QList<caf::PdmOptionItemInfo>& options ) {
RimProject* proj = RimProject::current();
std::vector<RimSummaryCase*> cases = proj->allSummaryCases();
cases.push_back( proj->calculationCollection->calculationSummaryCase() );
options = RiaSummaryTools::optionsForSummaryCases( cases );
if ( options.size() > 0 )
{
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
};
if ( fieldNeedingOptions == &m_yValuesSummaryCase )
{
createOptionsForSummaryCase( m_yValuesSummaryCase, options );
}
else if ( fieldNeedingOptions == &m_xValuesSummaryCase )
{
createOptionsForSummaryCase( m_xValuesSummaryCase, options );
}
else if ( &m_yValuesSummaryAddressUiField == fieldNeedingOptions )
{

View File

@@ -214,7 +214,7 @@ QString RimSummaryCurveAutoName::buildCurveName( const RifEclipseSummaryAddress&
{
text = summaryAddress.vectorName();
}
else if ( summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
else if ( summaryAddress.isCalculated() )
{
// Need to add case name for calculated summary
RimProject* proj = RimProject::current();
@@ -223,7 +223,7 @@ QString RimSummaryCurveAutoName::buildCurveName( const RifEclipseSummaryAddress&
RimUserDefinedCalculation* calculation = calcColl->findCalculationById( summaryAddress.id() );
if ( calculation )
{
text = calculation->description().toStdString();
text = calculation->shortName().toStdString();
}
}
@@ -235,7 +235,7 @@ QString RimSummaryCurveAutoName::buildCurveName( const RifEclipseSummaryAddress&
appendAddressDetails( text, summaryAddress, plotNameHelper );
if ( !caseName.empty() )
if ( !caseName.empty() && !summaryAddress.isCalculated() )
{
bool skipSubString = plotNameHelper && plotNameHelper->isCaseInTitle();

View File

@@ -224,7 +224,7 @@ void RimSummaryCurvesData::populateSummaryCurvesData( std::vector<RimSummaryCurv
auto curveDataList = std::vector<CurveData>( { curveData } );
if ( hasErrorData ) curveDataList.push_back( errorCurveData );
if ( curve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( curve->summaryAddressY().isCalculated() )
{
// We have calculated data, and it we cannot assume identical time axis
curvesData->addCurveDataNoSearch( curveCaseName, ensembleName, curve->timeStepsY(), curveDataList );

View File

@@ -1000,10 +1000,10 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange()
auto addressesForCurve = []( RimSummaryCurve* curve, AxisRangeAggregation axisRangeAggregation ) {
std::vector<RifEclipseSummaryAddress> addresses;
auto addr = curve->summaryAddressY();
if ( axisRangeAggregation == AxisRangeAggregation::REALIZATIONS )
{
RifEclipseSummaryAddress addr = RifEclipseSummaryAddress::fieldAddress( curve->summaryAddressY().vectorName() );
addresses = { addr };
addresses = { RifEclipseSummaryAddress::fieldAddress( addr.vectorName(), addr.id() ) };
}
else if ( axisRangeAggregation == AxisRangeAggregation::WELLS ||
axisRangeAggregation == AxisRangeAggregation::REGIONS )
@@ -1032,7 +1032,7 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange()
for ( const auto& wellName : analyzer->wellNames() )
{
addresses.push_back(
RifEclipseSummaryAddress::wellAddress( curve->summaryAddressY().vectorName(), wellName ) );
RifEclipseSummaryAddress::wellAddress( addr.vectorName(), wellName, addr.id() ) );
}
}
@@ -1040,8 +1040,8 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange()
{
for ( auto regionNumber : analyzer->regionNumbers() )
{
addresses.push_back( RifEclipseSummaryAddress::regionAddress( curve->summaryAddressY().vectorName(),
regionNumber ) );
addresses.push_back(
RifEclipseSummaryAddress::regionAddress( addr.vectorName(), regionNumber, addr.id() ) );
}
}
}

View File

@@ -51,6 +51,7 @@
#include "RimProject.h"
#include "RimSummaryAddress.h"
#include "RimSummaryAddressCollection.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCurve.h"
@@ -640,8 +641,11 @@ void RimSummaryPlot::copyAxisPropertiesFromOther( const RimSummaryPlot& sourceSu
{
QString data = ap->writeObjectToXmlString();
axisPropertiesForPlotAxis( ap->plotAxisType() )
->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() );
auto axisProperty = axisPropertiesForPlotAxis( ap->plotAxisType() );
if ( axisProperty )
{
axisProperty->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() );
}
}
}
@@ -2755,7 +2759,7 @@ void RimSummaryPlot::updateNameHelperWithCurveData( RimSummaryPlotNameHelper* na
{
for ( RimSummaryCurve* curve : m_summaryCurveCollection->curves() )
{
if ( curve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( curve->summaryAddressY().isCalculated() )
{
RiaSummaryTools::getSummaryCasesAndAddressesForCalculation( curve->summaryAddressY().id(),
sumCases,

View File

@@ -219,7 +219,7 @@ QString RimSummaryPlotAxisFormatter::autoAxisTitle() const
std::string titleText;
const std::string& quantityName = sumAddress.vectorName().substr( cutPos + 1 );
if ( sumAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( sumAddress.isCalculated() )
{
titleText = shortCalculationName( quantityName );
}
@@ -352,7 +352,7 @@ QString RimSummaryPlotAxisFormatter::createAxisObjectName() const
std::string name;
const std::string& quantityName = sumAddress.vectorName().substr( cutPos + 1 );
if ( sumAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
if ( sumAddress.isCalculated() )
{
name = shortCalculationName( quantityName );
}

View File

@@ -400,9 +400,6 @@ std::vector<SummarySource*> RimSummaryPlotFilterTextCurveSetEditor::selectedSumm
sources.push_back( source );
}
// Always add the summary case for calculated curves as this case is not displayed in UI
sources.push_back( RimProject::current()->calculationCollection()->calculationSummaryCase() );
return sources;
}