mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-31 09:14:11 -05:00
Add BinningMode (Linear/Logarithmic) and OutOfRangeHandling (Exclude/Include in Boundary Bins) to RigHistogramCalculator, with defaulted constructor arguments so existing callers are unaffected. All four histogram plot data sources get shared options for binning mode and an optional user-defined bin range through new PDM fields on RimHistogramDataSource. The grid statistics data source computes non-default histograms through a new non-caching RigStatisticsDataCache::computeHistogram() pass-through, leaving the cached statistics used by the 3D overlay and the P10/P90/mean annotation lines untouched. Selecting logarithmic binning enables logarithmic scale on the plot X axis once, via a new signal handled by RimHistogramCurve. Also fix the bin index computation to use uniform bins of width range/nBins, consistent with calculatePercentil() and the bin edges drawn by the plots. The previous divisor (nBins - 1) shifted counts by up to one bin width relative to the drawn bars and slightly biased histogram-based percentile estimates.
273 lines
14 KiB
C++
273 lines
14 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2011- Statoil ASA
|
|
// Copyright (C) 2013- Ceetron Solutions AS
|
|
// Copyright (C) 2011-2012 Ceetron AS
|
|
//
|
|
// 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 "RiaPorosityModel.h"
|
|
|
|
#include "RigFormationNames.h"
|
|
#include "RigStatisticsDataCache.h"
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <cmath>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
class RifReaderInterface;
|
|
class RigActiveCellInfo;
|
|
class RigMainGrid;
|
|
class RigEclipseResultInfo;
|
|
class RigEclipseTimeStepInfo;
|
|
class RigEclipseCaseData;
|
|
class RigAllanDiagramData;
|
|
class RigEclipseResultAddress;
|
|
|
|
class RimEclipseCase;
|
|
|
|
//==================================================================================================
|
|
/// Class containing the results for the complete number of active cells. Both main grid and LGR's
|
|
//==================================================================================================
|
|
class RigCaseCellResultsData : public cvf::Object
|
|
{
|
|
public:
|
|
explicit RigCaseCellResultsData( RigEclipseCaseData* ownerCaseData, RiaDefines::PorosityModelType porosityModel );
|
|
|
|
// Initialization
|
|
|
|
void setReaderInterface( RifReaderInterface* readerInterface );
|
|
const RifReaderInterface* readerInterface() const;
|
|
void setHdf5Filename( const QString& hdf5SourSimFilename );
|
|
void setActiveFormationNames( const RigFormationNames* activeFormationNames );
|
|
const RigFormationNames* activeFormationNames() const;
|
|
RigAllanDiagramData* allanDiagramData();
|
|
|
|
void setMainGrid( RigMainGrid* ownerGrid );
|
|
RigMainGrid* mainGrid();
|
|
void setActiveCellInfo( RigActiveCellInfo* activeCellInfo );
|
|
RigActiveCellInfo* activeCellInfo();
|
|
const RigActiveCellInfo* activeCellInfo() const;
|
|
|
|
// Access the results data
|
|
|
|
const std::vector<std::vector<double>>& cellScalarResults( const RigEclipseResultAddress& resVarAddr ) const;
|
|
const std::vector<double>& cellScalarResults( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ) const;
|
|
std::vector<std::vector<double>>* modifiableCellScalarResultTimesteps( const RigEclipseResultAddress& resVarAddr );
|
|
std::vector<double>* modifiableCellScalarResult( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex );
|
|
|
|
bool isUsingGlobalActiveIndex( const RigEclipseResultAddress& resVarAddr ) const;
|
|
|
|
static const std::vector<double>* getResultIndexableStaticResult( RigActiveCellInfo* actCellInfo,
|
|
RigCaseCellResultsData* gridCellResults,
|
|
QString porvResultName,
|
|
std::vector<double>& activeCellsResultsTempContainer );
|
|
// Statistic values of the results
|
|
|
|
void recalculateStatistics( const RigEclipseResultAddress& resVarAddr, const std::set<int>& uniqueValuesOverride = {} );
|
|
void minMaxCellScalarValues( const RigEclipseResultAddress& resVarAddr, double& min, double& max );
|
|
void minMaxCellScalarValues( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& min, double& max );
|
|
void posNegClosestToZero( const RigEclipseResultAddress& resVarAddr, double& pos, double& neg );
|
|
void posNegClosestToZero( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& pos, double& neg );
|
|
const std::vector<size_t>& cellScalarValuesHistogram( const RigEclipseResultAddress& resVarAddr );
|
|
const std::vector<size_t>& cellScalarValuesHistogram( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex );
|
|
void p10p90CellScalarValues( const RigEclipseResultAddress& resVarAddr, double& p10, double& p90 );
|
|
void p10p90CellScalarValues( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& p10, double& p90 );
|
|
void meanCellScalarValues( const RigEclipseResultAddress& resVarAddr, double& meanValue );
|
|
void meanCellScalarValues( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& meanValue );
|
|
const std::vector<int>& uniqueCellScalarValues( const RigEclipseResultAddress& resVarAddr );
|
|
void sumCellScalarValues( const RigEclipseResultAddress& resVarAddr, double& sumValue );
|
|
void sumCellScalarValues( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& sumValue );
|
|
void mobileVolumeWeightedMean( const RigEclipseResultAddress& resVarAddr, double& meanValue );
|
|
void mobileVolumeWeightedMean( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex, double& meanValue );
|
|
|
|
// Return the number of double values allocated for each result
|
|
std::map<std::string, size_t> resultValueCount() const;
|
|
|
|
// Access meta-information about the results
|
|
|
|
size_t timeStepCount( const RigEclipseResultAddress& resVarAddr ) const;
|
|
size_t maxTimeStepCount( RigEclipseResultAddress* resultAddressWithMostTimeSteps = nullptr ) const;
|
|
|
|
std::vector<QDateTime> allTimeStepDatesFromEclipseReader() const;
|
|
std::vector<QDateTime> timeStepDates() const;
|
|
std::vector<QDateTime> timeStepDates( const RigEclipseResultAddress& resVarAddr ) const;
|
|
std::vector<double> daysSinceSimulationStart() const;
|
|
std::vector<double> daysSinceSimulationStart( const RigEclipseResultAddress& resVarAddr ) const;
|
|
int reportStepNumber( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex ) const;
|
|
|
|
std::vector<RigEclipseTimeStepInfo> timeStepInfos( const RigEclipseResultAddress& resVarAddr ) const;
|
|
void setTimeStepInfos( const RigEclipseResultAddress& resVarAddr, const std::vector<RigEclipseTimeStepInfo>& timeStepInfos );
|
|
|
|
void clearScalarResult( RiaDefines::ResultCatType type, const QString& resultName );
|
|
void clearScalarResult( const RigEclipseResultAddress& resultAddress );
|
|
void clearAllResults();
|
|
void freeAllocatedResultsData( const std::vector<RiaDefines::ResultCatType>& categoriesToExclude,
|
|
std::optional<size_t> timeStepIndexToRelease );
|
|
void eraseAllSourSimData();
|
|
void setRemovedTagOnGeneratedResult( const RigEclipseResultAddress& resultAddress );
|
|
|
|
QStringList resultNames( RiaDefines::ResultCatType type, bool includeAliases = true ) const;
|
|
std::vector<RigEclipseResultAddress> existingResults() const;
|
|
const RigEclipseResultInfo* resultInfo( const RigEclipseResultAddress& resVarAddr ) const;
|
|
bool updateResultName( RiaDefines::ResultCatType resultType, const QString& oldName, const QString& newName );
|
|
QString makeResultNameUnique( const QString& resultNameProposal ) const;
|
|
|
|
bool ensureKnownResultLoaded( const RigEclipseResultAddress& resultAddress );
|
|
bool findAndLoadResultByName( const QString& resultName, const std::vector<RiaDefines::ResultCatType>& resultCategorySearchOrder );
|
|
|
|
// Load result for a single time step. This can be used to process data for a single time step
|
|
// Other data access functions assume all time steps are loaded at the same time
|
|
size_t findOrLoadKnownScalarResultForTimeStep( const RigEclipseResultAddress& resVarAddr, size_t timeStepIndex );
|
|
|
|
bool hasResultEntry( const RigEclipseResultAddress& resultAddress ) const;
|
|
bool isResultLoaded( const RigEclipseResultAddress& resultAddress ) const;
|
|
void createResultEntry( const RigEclipseResultAddress& resultAddress, bool needsToBeStored );
|
|
bool updateResultDataType( const RigEclipseResultAddress& resultAddress, RiaDefines::ResultDataType dataType );
|
|
void createPlaceholderResultEntries();
|
|
|
|
// Compute depth-related geometry results (DEPTH/DX/DY/DZ/TOPS/BOTTOM) for both porosity models
|
|
// in a single traversal of the shared grid. The values are derived purely from the grid
|
|
// geometry, so a cell active in both models is computed only once and written to both.
|
|
static void computeDepthRelatedResults( RigCaseCellResultsData* matrixResults, RigCaseCellResultsData* fractureResults );
|
|
|
|
void computeCellVolumes();
|
|
bool hasFlowDiagUsableFluxes() const;
|
|
|
|
static void copyResultsMetaDataFromMainCase( RigEclipseCaseData* mainCaseResultsData,
|
|
RiaDefines::PorosityModelType poroModel,
|
|
std::vector<RimEclipseCase*> destinationCases );
|
|
|
|
void setStatisticsDataCacheNumBins( const RigEclipseResultAddress& resultAddress, size_t numBins );
|
|
|
|
RigStatisticsDataCache* statistics( const RigEclipseResultAddress& resVarAddr );
|
|
|
|
size_t addStaticScalarResult( RiaDefines::ResultCatType type, const QString& resultName, bool needsToBeStored, size_t resultValueCount );
|
|
|
|
RigEclipseResultAddress defaultResult() const;
|
|
|
|
void addResultAlias( QString originalResultName, QString aliasResultName );
|
|
void clearAllResultAliases();
|
|
|
|
private:
|
|
// Per-model buffers used by computeDepthRelatedResults(). Holds pointers to the result rows
|
|
// and per-property flags telling whether the row still needs to be computed. A buffer with
|
|
// actCellCount == 0 is disabled (the porosity model has no active cells).
|
|
struct DepthResultBuffers
|
|
{
|
|
RigActiveCellInfo* activeCellInfo = nullptr;
|
|
size_t actCellCount = 0;
|
|
std::vector<double>* depth = nullptr;
|
|
std::vector<double>* dx = nullptr;
|
|
std::vector<double>* dy = nullptr;
|
|
std::vector<double>* dz = nullptr;
|
|
std::vector<double>* tops = nullptr;
|
|
std::vector<double>* bottom = nullptr;
|
|
bool computeDepth = false;
|
|
bool computeDx = false;
|
|
bool computeDy = false;
|
|
bool computeDz = false;
|
|
bool computeTops = false;
|
|
bool computeBottom = false;
|
|
};
|
|
DepthResultBuffers prepareDepthRelatedResultArrays();
|
|
|
|
size_t findOrLoadKnownScalarResult( const RigEclipseResultAddress& resVarAddr );
|
|
size_t findOrLoadKnownScalarResultByResultTypeOrder( const RigEclipseResultAddress& resVarAddr,
|
|
const std::vector<RiaDefines::ResultCatType>& resultCategorySearchOrder );
|
|
|
|
// Add a friend class, as this way of loading data requires careful management of state
|
|
// All other data access assumes all time steps are loaded at the same time
|
|
friend class RimEclipseStatisticsCaseEvaluator;
|
|
friend class RigSoilResultCalculator;
|
|
friend class RigSwatResultCalculator;
|
|
friend class RigFaultDistanceResultCalculator;
|
|
friend class RigMobilePoreVolumeResultCalculator;
|
|
friend class RigIndexIjkResultCalculator;
|
|
friend class RigOilVolumeResultCalculator;
|
|
friend class RigCellVolumeResultCalculator;
|
|
friend class RigCellsWithNncsCalculator;
|
|
friend class RigPorvSoilSgasResultCalculator;
|
|
|
|
size_t findOrCreateScalarResultIndex( const RigEclipseResultAddress& resVarAddr, bool needsToBeStored );
|
|
|
|
size_t findScalarResultIndexFromAddress( const RigEclipseResultAddress& resVarAddr ) const;
|
|
|
|
const std::vector<RigEclipseResultInfo>& infoForEachResultIndex() const;
|
|
size_t resultCount() const;
|
|
|
|
bool mustBeCalculated( size_t scalarResultIndex ) const;
|
|
void setMustBeCalculated( size_t scalarResultIndex );
|
|
|
|
void computeSOILForTimeStep( size_t timeStepIndex );
|
|
void testAndComputeSgasForTimeStep( size_t timeStepIndex );
|
|
|
|
bool hasCompleteTransmissibilityResults() const;
|
|
|
|
void computeRiTransComponent( const QString& riTransComponentResultName );
|
|
void computeNncCombRiTrans();
|
|
|
|
void computeRiMULTComponent( const QString& riMultCompName );
|
|
void computeNncCombRiMULT();
|
|
void computeRiTRANSbyAreaComponent( const QString& riTransByAreaCompResultName );
|
|
void computeNncCombRiTRANSbyArea();
|
|
|
|
void computeCompletionTypeForTimeStep( size_t timeStep );
|
|
void computeStaticCompletionType();
|
|
void computeCompletionTypeForFrame( std::vector<double>& frameValues, size_t calcTimeStep );
|
|
void triggerGeneratedPermeabilityCalculations( RimEclipseCase* eclipseCase );
|
|
double darchysValue();
|
|
|
|
void computeOilVolumes();
|
|
void computeMobilePV();
|
|
void computePorvSoilSgas();
|
|
|
|
void computeIndexResults();
|
|
void computeFaultDistance();
|
|
void computeNncsCells();
|
|
|
|
bool isDataPresent( size_t scalarResultIndex ) const;
|
|
size_t allocatedValueCount( size_t scalarResultIndex ) const;
|
|
|
|
void assignValuesToTemporaryLgrs( const QString& resultName, std::vector<double>& values );
|
|
|
|
bool isRadialModel() const;
|
|
|
|
private:
|
|
cvf::ref<RifReaderInterface> m_readerInterface;
|
|
cvf::ref<RigAllanDiagramData> m_allanDiagramData;
|
|
|
|
std::vector<std::vector<std::vector<double>>> m_cellScalarResults; ///< Scalar results on the complete reservoir for
|
|
///< each Result index (ResultVariable) and timestep
|
|
cvf::Collection<RigStatisticsDataCache> m_statisticsDataCache;
|
|
std::vector<RigEclipseResultInfo> m_resultInfos;
|
|
std::map<RigEclipseResultAddress, size_t> m_addressToResultIndexMap;
|
|
|
|
std::map<QString, QString> m_resultAliasMap;
|
|
|
|
RigMainGrid* m_ownerMainGrid;
|
|
RigEclipseCaseData* m_ownerCaseData;
|
|
RigActiveCellInfo* m_activeCellInfo;
|
|
RiaDefines::PorosityModelType m_porosityModel;
|
|
// Stored by value, as the owning RimFormationNames can be reloaded or deleted while this data is in use
|
|
RigFormationNames m_activeFormationNamesData;
|
|
};
|