#4117 Refactor Grid Cross plot result extraction and categorisation

This commit is contained in:
Gaute Lindkvist
2019-02-27 10:57:17 +01:00
parent b6348b8374
commit 1b9a0fe5a7
10 changed files with 383 additions and 240 deletions

View File

@@ -53,6 +53,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigCellGeometryTools.h
${CMAKE_CURRENT_LIST_DIR}/RigWellPathIntersectionTools.h
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultInfo.h
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultAddress.h
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultBinSorter.h
${CMAKE_CURRENT_LIST_DIR}/RigTofAccumulatedPhaseFractionsCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityEquations.h
${CMAKE_CURRENT_LIST_DIR}/RigNumberOfFloodedPoreVolumesCalculator.h
@@ -67,6 +68,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RigCaseRealizationParameters.h
${CMAKE_CURRENT_LIST_DIR}/RigGeoMechBoreHoleStressCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RigPolyLinesData.h
${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultCalculator.h
${CMAKE_CURRENT_LIST_DIR}/RigGridCrossPlotCurveCategorization.h
${CMAKE_CURRENT_LIST_DIR}/RigEclipseCrossPlotDataExtractor.h
)
@@ -118,6 +122,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigTesselatorTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RigCellGeometryTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellPathIntersectionTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultInfo.cpp
${CMAKE_CURRENT_LIST_DIR}/RigEclipseResultBinSorter.cpp
${CMAKE_CURRENT_LIST_DIR}/RigTofAccumulatedPhaseFractionsCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigTransmissibilityEquations.cpp
${CMAKE_CURRENT_LIST_DIR}/RigNumberOfFloodedPoreVolumesCalculator.cpp
@@ -132,6 +137,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigCaseRealizationParameters.cpp
${CMAKE_CURRENT_LIST_DIR}/RigGeoMechBoreHoleStressCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigPolyLinesData.cpp
${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultCalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/RigEclipseCrossPlotDataExtractor.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@@ -17,25 +17,147 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RigEclipseCrossPlotDataExtractor.h"
#include "RigEclipseCaseData.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseResultAddress.h"
#include "RigActiveCellInfo.h"
#include "RigActiveCellsResultAccessor.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseResultAddress.h"
#include "RigEclipseResultBinSorter.h"
#include "RigFormationNames.h"
#include "RigMainGrid.h"
#include <memory>
#include <set>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<double, double>> RigEclipseCrossPlotDataExtractor::extract(RigEclipseCaseData* caseData,
int timeStep,
const RigEclipseResultAddress& xAxisProperty,
const RigEclipseResultAddress& yAxisProperty)
RigEclipseCrossPlotResult RigEclipseCrossPlotDataExtractor::extract(RigEclipseCaseData* caseData,
int resultTimeStep,
const RigEclipseResultAddress& xAddress,
const RigEclipseResultAddress& yAddress,
RigGridCrossPlotCurveCategorization categorizationType,
const RigEclipseResultAddress& catAddress,
int categoryBinCount)
{
RigCaseCellResultsData* resultData = caseData->results(RiaDefines::MATRIX_MODEL);
std::vector<double> xValues = resultData->cellScalarResults(xAxisProperty)[timeStep];
std::vector<double> yValues = resultData->cellScalarResults(xAxisProperty)[timeStep];
size_t reservoirCellIndex = m_grid->reservoirCellIndex(gridLocalCellIndex);
size_t resultValueIndex = m_activeCellInfo->cellResultIndex(reservoirCellIndex);
if (resultValueIndex == cvf::UNDEFINED_SIZE_T) return HUGE_VAL;
RigEclipseCrossPlotResult result;
RigEclipseCrossPlotResult::CategorySamplesMap& categorySamplesMap = result.categorySamplesMap;
RigEclipseCrossPlotResult::CategoryNameMap& categoryNameMap = result.categoryNameMap;
if (resultValueIndex < m_reservoirResultValues->size()) return m_reservoirResultValues->at(resultValueIndex);
RigCaseCellResultsData* resultData = caseData->results(RiaDefines::MATRIX_MODEL);
RigFormationNames* activeFormationNames = resultData->activeFormationNames();
std::unique_ptr<RigEclipseResultBinSorter> catBinSorter;
const std::vector<std::vector<double>>* catValuesForAllSteps = nullptr;
if (xAddress.isValid() && yAddress.isValid())
{
RigActiveCellInfo* activeCellInfo = resultData->activeCellInfo();
const RigMainGrid* mainGrid = caseData->mainGrid();
resultData->ensureKnownResultLoaded(xAddress);
resultData->ensureKnownResultLoaded(yAddress);
const std::vector<std::vector<double>>& xValuesForAllSteps = resultData->cellScalarResults(xAddress);
const std::vector<std::vector<double>>& yValuesForAllSteps = resultData->cellScalarResults(yAddress);
if (categorizationType == RESULT_CATEGORIZATION && catAddress.isValid())
{
resultData->ensureKnownResultLoaded(catAddress);
catValuesForAllSteps = &resultData->cellScalarResults(catAddress);
catBinSorter.reset(new RigEclipseResultBinSorter(*catValuesForAllSteps, categoryBinCount));
}
std::set<int> timeStepsToInclude;
if (resultTimeStep == -1)
{
size_t nStepsInData = std::max(xValuesForAllSteps.size(), yValuesForAllSteps.size());
CVF_ASSERT(xValuesForAllSteps.size() == 1u || xValuesForAllSteps.size() == nStepsInData);
CVF_ASSERT(yValuesForAllSteps.size() == 1u || yValuesForAllSteps.size() == nStepsInData);
for (size_t i = 0; i < nStepsInData; ++i)
{
timeStepsToInclude.insert((int)i);
}
}
else
{
timeStepsToInclude.insert(static_cast<size_t>(resultTimeStep));
}
for (int timeStep : timeStepsToInclude)
{
int xIndex = timeStep >= (int)xValuesForAllSteps.size() ? 0 : timeStep;
int yIndex = timeStep >= (int)yValuesForAllSteps.size() ? 0 : timeStep;
RigActiveCellsResultAccessor xAccessor(mainGrid, &xValuesForAllSteps[xIndex], activeCellInfo);
RigActiveCellsResultAccessor yAccessor(mainGrid, &yValuesForAllSteps[yIndex], activeCellInfo);
std::unique_ptr<RigActiveCellsResultAccessor> catAccessor;
if (catValuesForAllSteps)
{
int catIndex = timeStep >= (int)catValuesForAllSteps->size() ? 0 : timeStep;
catAccessor.reset(
new RigActiveCellsResultAccessor(mainGrid, &(catValuesForAllSteps->at(catIndex)), activeCellInfo));
}
for (size_t globalCellIdx = 0; globalCellIdx < activeCellInfo->reservoirCellCount(); ++globalCellIdx)
{
double xValue = xAccessor.cellScalarGlobIdx(globalCellIdx);
double yValue = yAccessor.cellScalarGlobIdx(globalCellIdx);
int category = 0;
if (categorizationType == TIME_CATEGORIZATION)
{
category = timeStep;
}
else if (categorizationType == FORMATION_CATEGORIZATION && activeFormationNames)
{
size_t i(cvf::UNDEFINED_SIZE_T), j(cvf::UNDEFINED_SIZE_T), k(cvf::UNDEFINED_SIZE_T);
if (mainGrid->ijkFromCellIndex(globalCellIdx, &i, &j, &k))
{
category = activeFormationNames->formationIndexFromKLayerIdx(k);
}
}
else if (catAccessor && catBinSorter)
{
double catValue = catAccessor->cellScalarGlobIdx(globalCellIdx);
category = catBinSorter->binNumber(catValue);
}
if (xValue != HUGE_VAL && yValue != HUGE_VAL)
{
categorySamplesMap[category].first.push_back(xValue);
categorySamplesMap[category].second.push_back(yValue);
}
}
}
}
std::vector<QDateTime> timeStepDates = resultData->timeStepDates();
for (const auto& sampleCategory : categorySamplesMap)
{
QString categoryName;
if (categorizationType == TIME_CATEGORIZATION && categorySamplesMap.size() > 1u)
{
if (sampleCategory.first < timeStepDates.size())
{
categoryName = timeStepDates[sampleCategory.first].toString(Qt::ISODate);
}
}
else if (categorizationType == FORMATION_CATEGORIZATION && activeFormationNames)
{
categoryName = activeFormationNames->formationNameFromKLayerIdx(sampleCategory.first);
}
else if (catBinSorter)
{
std::pair<double, double> binRange = catBinSorter->binRange(sampleCategory.first);
categoryName = QString("%1 [%2, %3]")
.arg(catAddress.m_resultName)
.arg(binRange.first)
.arg(binRange.second);
}
categoryNameMap.insert(std::make_pair(sampleCategory.first, categoryName));
}
return result;
}

View File

@@ -17,17 +17,36 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RigGridCrossPlotCurveCategorization.h"
#include <map>
#include <utility>
#include <vector>
class RigEclipseCaseData;
class RigEclipseResultAddress;
class RigEclipseCrossPlotDataExtractor
class QString;
struct RigEclipseCrossPlotResult
{
static std::vector<std::pair<double, double>> extract(RigEclipseCaseData* caseData,
int timeStep,
const RigEclipseResultAddress& xAxisProperty,
const RigEclipseResultAddress& yAxisProperty);
typedef std::pair<std::vector<double>, std::vector<double>> ResultXYValues;
typedef std::map<int, ResultXYValues> CategorySamplesMap;
typedef std::map<int, QString> CategoryNameMap;
CategorySamplesMap categorySamplesMap;
CategoryNameMap categoryNameMap;
};
class RigEclipseCrossPlotDataExtractor
{
public:
static RigEclipseCrossPlotResult extract(RigEclipseCaseData* eclipseCase,
int resultTimeStep,
const RigEclipseResultAddress& xAddress,
const RigEclipseResultAddress& yAddress,
RigGridCrossPlotCurveCategorization categorizationType,
const RigEclipseResultAddress& categoryAddress,
int categoryBinCount);
};

View File

@@ -0,0 +1,79 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigEclipseResultBinSorter.h"
#include <algorithm>
#include <limits>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigEclipseResultBinSorter::RigEclipseResultBinSorter(const std::vector<std::vector<double>>& allDataValues, int binCount)
: m_allDataValues(allDataValues)
, m_binCount(binCount)
, m_minValue(std::numeric_limits<double>::infinity())
, m_maxValue(-std::numeric_limits<double>::infinity())
, m_binSize(0.0)
{
calculateRange();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RigEclipseResultBinSorter::binNumber(double value) const
{
double distFromMin = value - m_minValue;
return std::min(m_binCount - 1, static_cast<int>(distFromMin / m_binSize));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double> RigEclipseResultBinSorter::binRange(int binNumber) const
{
double minBinValue = m_minValue + m_binSize * binNumber;
double maxBinBalue = minBinValue + m_binSize;
return std::make_pair(minBinValue, maxBinBalue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigEclipseResultBinSorter::calculateRange()
{
for (const std::vector<double>& doubleRange : m_allDataValues)
{
if (!doubleRange.empty())
{
for (double value : doubleRange)
{
if (value != std::numeric_limits<double>::infinity())
{
m_minValue = std::min(m_minValue, value);
m_maxValue = std::max(m_maxValue, value);
}
}
}
}
if (m_maxValue > m_minValue)
{
m_binSize = (m_maxValue - m_minValue) / m_binCount;
}
}

View File

@@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <utility>
#include <vector>
//==================================================================================================
///
///
//==================================================================================================
class RigEclipseResultBinSorter
{
public:
RigEclipseResultBinSorter(const std::vector<std::vector<double>>& allDataValues, int binCount);
int binNumber(double value) const;
std::pair<double, double> binRange(int binNumber) const;
private:
void calculateRange();
private:
const std::vector<std::vector<double>>& m_allDataValues;
int m_binCount;
double m_minValue;
double m_maxValue;
double m_binSize;
};

View File

@@ -0,0 +1,27 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
enum RigGridCrossPlotCurveCategorization
{
NO_CATEGORIZATION,
TIME_CATEGORIZATION,
FORMATION_CATEGORIZATION,
RESULT_CATEGORIZATION
};