diff --git a/ApplicationCode/CMakeLists.txt b/ApplicationCode/CMakeLists.txt index 76bcf41931..eb9f7d239f 100644 --- a/ApplicationCode/CMakeLists.txt +++ b/ApplicationCode/CMakeLists.txt @@ -109,6 +109,7 @@ list( APPEND REFERENCED_CMAKE_FILES ProjectDataModel/CMakeLists_files.cmake ProjectDataModel/GridCrossPlots/CMakeLists_files.cmake + ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake ProjectDataModel/Summary/CMakeLists_files.cmake ProjectDataModel/Flow/CMakeLists_files.cmake ProjectDataModel/Annotations/CMakeLists_files.cmake diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake new file mode 100644 index 0000000000..46fc736a04 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/CMakeLists_files.cmake @@ -0,0 +1,22 @@ + +set (SOURCE_GROUP_HEADER_FILES +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellFilter.h +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellFilterCollection.h +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellPropertyFilter.h +) + +set (SOURCE_GROUP_SOURCE_FILES +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellFilter.cpp +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellFilterCollection.cpp +${CMAKE_CURRENT_LIST_DIR}/RimPlotCellPropertyFilter.cpp +) + +list(APPEND CODE_HEADER_FILES +${SOURCE_GROUP_HEADER_FILES} +) + +list(APPEND CODE_SOURCE_FILES +${SOURCE_GROUP_SOURCE_FILES} +) + +source_group( "ProjectDataModel\\GridCrossPlots\\CellFilters" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake ) diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.cpp new file mode 100644 index 0000000000..13bbd13950 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.cpp @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPlotCellFilter.h" + +namespace caf +{ +template<> +void caf::AppEnum::setUp() +{ + addItem(RimPlotCellFilter::INCLUDE, "INCLUDE", "Include"); + addItem(RimPlotCellFilter::EXCLUDE, "EXCLUDE", "Exclude"); + setDefault(RimPlotCellFilter::INCLUDE); +} +} // namespace caf + +CAF_PDM_ABSTRACT_SOURCE_INIT(RimPlotCellFilter, "RimPlotCellFilter"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotCellFilter::RimPlotCellFilter() +{ + CAF_PDM_InitFieldNoDefault(&m_filterType, "FilterType", "Filter Type", "", "", ""); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellFilter::updateCellVisibility(size_t timeStepIndex, cvf::UByteArray* cellVisibility) +{ + updateCellVisibilityFromFilter(timeStepIndex, cellVisibility); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotCellFilter::FilterModeType RimPlotCellFilter::filterType() const +{ + return m_filterType(); +} diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.h new file mode 100644 index 0000000000..7e6a9f24e9 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilter.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCheckableNamedObject.h" + +#include "cvfArray.h" +#include "cvfBase.h" + +//================================================================================================== +/// +//================================================================================================== +class RimPlotCellFilter : public RimCheckableNamedObject +{ + CAF_PDM_HEADER_INIT; + +public: + enum FilterModeType + { + INCLUDE, + EXCLUDE + }; + +public: + RimPlotCellFilter(); + + void updateCellVisibility(size_t timeStepIndex, cvf::UByteArray* cellVisibility); + FilterModeType filterType() const; + +protected: + virtual void updateCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* cellVisibility) = 0; + +private: + caf::PdmField> m_filterType; +}; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.cpp new file mode 100644 index 0000000000..6b945b5864 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.cpp @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPlotCellFilterCollection.h" + +CAF_PDM_SOURCE_INIT(RimPlotCellFilterCollection, "RimPlotCellFilterCollection"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotCellFilterCollection::RimPlotCellFilterCollection() +{ + CAF_PDM_InitObject("Plot Cell Filters", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_cellFilters, "CellFilters", "Cell Filters", "", "", ""); + // m_crossPlotCurveSets.uiCapability()->setUiHidden(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellFilterCollection::addCellFilter(RimPlotCellFilter* cellFilter) +{ + m_cellFilters.push_back(cellFilter); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RimPlotCellFilterCollection::cellFilterCount() const +{ + return m_cellFilters.size(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellFilterCollection::computeCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* cellVisibility) +{ + updateCellVisibilityFromFilter(timeStepIndex, cellVisibility); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellFilterCollection::updateCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* cellVisibility) +{ + for (RimPlotCellFilter* f : m_cellFilters()) + { + f->updateCellVisibility(timeStepIndex, cellVisibility); + } +} + diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.h new file mode 100644 index 0000000000..bdf5561d74 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellFilterCollection.h @@ -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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimPlotCellFilter.h" + +#include "cafPdmChildArrayField.h" + +//================================================================================================== +/// +//================================================================================================== +class RimPlotCellFilterCollection : public RimPlotCellFilter +{ + CAF_PDM_HEADER_INIT; + +public: + RimPlotCellFilterCollection(); + + void addCellFilter(RimPlotCellFilter* cellFilter); + size_t cellFilterCount() const; + + void computeCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* cellVisibility); + +protected: + void updateCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* cellVisibility) override; + +private: + caf::PdmChildArrayField m_cellFilters; +}; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.cpp new file mode 100644 index 0000000000..35131934f7 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.cpp @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimPlotCellPropertyFilter.h" + +#include "RimEclipseResultDefinition.h" +#include "RimGeoMechResultDefinition.h" + +#include "RigActiveCellInfo.h" +#include "RigResultAccessor.h" +#include "RigResultAccessorFactory.h" +#include "RimEclipseCase.h" +#include "cafPdmUiDoubleSliderEditor.h" + +CAF_PDM_SOURCE_INIT(RimPlotCellPropertyFilter, "RimPlotCellPropertyFilter"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimPlotCellPropertyFilter::RimPlotCellPropertyFilter() +{ + CAF_PDM_InitObject("Plot Cell Property Filter", "", "", ""); + + CAF_PDM_InitFieldNoDefault(&m_resultDefinition, "ResultDefinition", "Result Definition", "", "", ""); + + // Set to hidden to avoid this item to been displayed as a child item + // Fields in this object are displayed using defineUiOrdering() + m_resultDefinition.uiCapability()->setUiHidden(true); + m_resultDefinition.uiCapability()->setUiTreeChildrenHidden(true); + + CAF_PDM_InitField(&m_lowerBound, "LowerBound", 0.0, "Min", "", "", ""); + m_lowerBound.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName()); + + CAF_PDM_InitField(&m_upperBound, "UpperBound", 0.0, "Max", "", "", ""); + m_upperBound.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellPropertyFilter::setResultDefinition(caf::PdmObject* resultDefinition) +{ + m_resultDefinition = resultDefinition; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellPropertyFilter::setValueRange(double lowerBound, double upperBound) +{ + m_lowerBound = lowerBound; + m_upperBound = upperBound; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseResultDefinition* RimPlotCellPropertyFilter::eclipseResultDefinition() +{ + caf::PdmObject* pdmObj = m_resultDefinition; + + return dynamic_cast(pdmObj); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPlotCellPropertyFilter::updateCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* visibleCells) +{ + CVF_ASSERT(visibleCells); + + RimEclipseResultDefinition* resDef = eclipseResultDefinition(); + if (resDef) + { + resDef->loadResult(); + + RimEclipseCase* eclCase = resDef->eclipseCase(); + if (!eclCase) return; + + eclCase->ensureReservoirCaseIsOpen(); + RigEclipseCaseData* eclipseCaseData = eclCase->eclipseCaseData(); + if (!eclipseCaseData) return; + + RigCaseCellResultsData* cellResultsData = resDef->currentGridCellResults(); + if (!cellResultsData) return; + + const std::vector& cellResultValues = cellResultsData->cellScalarResults(resDef->eclipseResultAddress(), timeStepIndex); + + if (cellResultValues.empty()) return; + + const RigActiveCellInfo* actCellInfo = cellResultsData->activeCellInfo(); + size_t cellCount = actCellInfo->reservoirCellCount(); + + bool isUsingGlobalActiveIndex = cellResultsData->isUsingGlobalActiveIndex(resDef->eclipseResultAddress()); + + double lowerBound = m_lowerBound; + double upperBound = m_upperBound; + + for (size_t reservoirCellIndex = 0; reservoirCellIndex < cellCount; ++reservoirCellIndex) + { + if (!actCellInfo->isActive(reservoirCellIndex)) continue; + + size_t cellResultIndex = reservoirCellIndex; + if (isUsingGlobalActiveIndex) + { + cellResultIndex = actCellInfo->cellResultIndex(reservoirCellIndex); + } + + if (cellResultIndex != cvf::UNDEFINED_SIZE_T && cellResultIndex < cellResultValues.size()) + { + if ((*visibleCells)[reservoirCellIndex]) + { + double scalarValue = cellResultValues[cellResultIndex]; + if (lowerBound <= scalarValue && scalarValue <= upperBound) + { + if (filterType() == RimPlotCellFilter::EXCLUDE) + { + (*visibleCells)[reservoirCellIndex] = false; + } + } + else + { + if (filterType() == RimPlotCellFilter::INCLUDE) + { + (*visibleCells)[reservoirCellIndex] = false; + } + } + } + } + } + } +} diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.h new file mode 100644 index 0000000000..68d57b728e --- /dev/null +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/CellFilters/RimPlotCellPropertyFilter.h @@ -0,0 +1,57 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimPlotCellFilter.h" + +#include "cafPdmChildField.h" +#include "cafPdmField.h" + +#include "cvfArray.h" +#include "cvfBase.h" + +class RimEclipseResultDefinition; + +//================================================================================================== +/// +//================================================================================================== +class RimPlotCellPropertyFilter : public RimPlotCellFilter +{ + CAF_PDM_HEADER_INIT; + +public: + RimPlotCellPropertyFilter(); + + void setResultDefinition(caf::PdmObject* resultDefinition); + + void setValueRange(double lowerBound, double upperBound); + +protected: + void updateCellVisibilityFromFilter(size_t timeStepIndex, cvf::UByteArray* visibleCells) override; + +private: + RimEclipseResultDefinition* eclipseResultDefinition(); + +private: + caf::PdmChildField m_resultDefinition; + caf::PdmField m_lowerBound; + caf::PdmField m_upperBound; + + cvf::ref m_visibleCells; +}; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.cpp index 148b78676c..90bdc7f8f1 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.cpp @@ -37,9 +37,10 @@ #include "RimCase.h" #include "RimEclipseCase.h" -#include "RimEclipseView.h" #include "RimEclipseCellColors.h" +#include "RimEclipseResultCase.h" #include "RimEclipseResultDefinition.h" +#include "RimEclipseView.h" #include "RimGridCrossPlot.h" #include "RimGridCrossPlotCurve.h" #include "RimGridView.h" @@ -47,6 +48,8 @@ #include "RimRegularLegendConfig.h" #include "RimTools.h" +#include "CellFilters/RimPlotCellFilterCollection.h" + #include "cafCategoryMapper.h" #include "cafColorTable.h" #include "cafPdmUiComboBoxEditor.h" @@ -57,7 +60,6 @@ #include "cvfqtUtils.h" #include -#include "RimEclipseResultCase.h" CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurveSet, "GridCrossPlotCurveSet"); @@ -72,7 +74,7 @@ void RimGridCrossPlotCurveSet::CurveGroupingEnum::setUp() addItem(RigGridCrossPlotCurveGrouping::GROUP_BY_RESULT, "RESULT", "Result Property"); setDefault(RigGridCrossPlotCurveGrouping::GROUP_BY_TIME); } -} +} // namespace caf //-------------------------------------------------------------------------------------------------- /// @@ -118,6 +120,9 @@ RimGridCrossPlotCurveSet::RimGridCrossPlotCurveSet() CAF_PDM_InitField(&m_useCustomColor, "UseCustomColor", false, "Use Custom Color", "", "", ""); CAF_PDM_InitField(&m_customColor, "CustomColor", cvf::Color3f(cvf::Color3f::BLACK), "Custom Color", "", "", ""); + CAF_PDM_InitFieldNoDefault(&m_plotCellFilterCollection, "PlotCellFilterCollection", "Cell Filters", "", "", ""); + m_plotCellFilterCollection = new RimPlotCellFilterCollection; + setDefaults(); } @@ -203,7 +208,7 @@ QString RimGridCrossPlotCurveSet::createAutoName() const if (m_nameConfig->addTimestep() && !timeStepString().isEmpty()) { - nameTags += timeStepString(); + nameTags += timeStepString(); } if (m_nameConfig->addGrouping() && groupParameter() != "None") @@ -302,7 +307,7 @@ QString RimGridCrossPlotCurveSet::caseNameString() const //-------------------------------------------------------------------------------------------------- QString RimGridCrossPlotCurveSet::axisVariableString() const { - return QString("%1 x %2").arg(xAxisName(), yAxisName()); + return QString("%1 x %2").arg(xAxisName(), yAxisName()); } //-------------------------------------------------------------------------------------------------- @@ -341,18 +346,13 @@ std::vector RimGridCrossPlotCurveSet::groupStrings() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::map -RimGridCrossPlotCurveSet::nameComponents() const +std::map RimGridCrossPlotCurveSet::nameComponents() const { std::map componentNames; - if (m_nameConfig->addCaseName()) - componentNames[GCP_CASE_NAME] = caseNameString(); - if (m_nameConfig->addAxisVariables()) - componentNames[GCP_AXIS_VARIABLES] = axisVariableString(); - if (m_nameConfig->addTimestep()) - componentNames[GCP_TIME_STEP] = timeStepString(); - if (m_nameConfig->addGrouping()) - componentNames[GCP_GROUP_NAME] = groupTitle(); + if (m_nameConfig->addCaseName()) componentNames[GCP_CASE_NAME] = caseNameString(); + if (m_nameConfig->addAxisVariables()) componentNames[GCP_AXIS_VARIABLES] = axisVariableString(); + if (m_nameConfig->addTimestep()) componentNames[GCP_TIME_STEP] = timeStepString(); + if (m_nameConfig->addGrouping()) componentNames[GCP_GROUP_NAME] = groupTitle(); return componentNames; } @@ -377,7 +377,7 @@ void RimGridCrossPlotCurveSet::initAfterRead() void RimGridCrossPlotCurveSet::onLoadDataAndUpdate(bool updateParentPlot) { updateDataSetName(); - + detachAllCurves(); m_crossPlotCurves.deleteAllChildObjects(); @@ -385,7 +385,7 @@ void RimGridCrossPlotCurveSet::onLoadDataAndUpdate(bool updateParentPlot) { return; } - + RimEclipseCase* eclipseCase = dynamic_cast(m_case.value()); if (eclipseCase == nullptr) @@ -431,7 +431,6 @@ void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& res m_groupedResults.clear(); if (!groupingEnabled()) { - RimGridCrossPlotCurve* curve = new RimGridCrossPlotCurve(); if (m_useCustomColor) { @@ -458,10 +457,8 @@ void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& res { for (size_t i = 0; i < result.xValues.size(); ++i) { - int categoryNum = - m_grouping == GROUP_BY_RESULT - ? static_cast(result.groupValuesContinuous[i]) - : result.groupValuesDiscrete[i]; + int categoryNum = m_grouping == GROUP_BY_RESULT ? static_cast(result.groupValuesContinuous[i]) + : result.groupValuesDiscrete[i]; m_groupedResults[categoryNum].xValues.push_back(result.xValues[i]); m_groupedResults[categoryNum].yValues.push_back(result.yValues[i]); @@ -469,7 +466,6 @@ void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& res m_groupedResults[categoryNum].groupValuesContinuous.push_back(result.groupValuesContinuous[i]); if (!result.groupValuesDiscrete.empty()) m_groupedResults[categoryNum].groupValuesDiscrete.push_back(result.groupValuesDiscrete[i]); - } } else @@ -478,9 +474,9 @@ void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& res for (size_t i = 0; i < result.xValues.size(); ++i) { - auto upperBoundIt = std::lower_bound(tickValues.begin(), tickValues.end(), result.groupValuesContinuous[i]); + auto upperBoundIt = std::lower_bound(tickValues.begin(), tickValues.end(), result.groupValuesContinuous[i]); int upperBoundIndex = static_cast(upperBoundIt - tickValues.begin()); - int categoryNum = std::min((int) tickValues.size() - 2, std::max(0, upperBoundIndex - 1)); + int categoryNum = std::min((int)tickValues.size() - 2, std::max(0, upperBoundIndex - 1)); m_groupedResults[categoryNum].xValues.push_back(result.xValues[i]); m_groupedResults[categoryNum].yValues.push_back(result.yValues[i]); if (!result.groupValuesContinuous.empty()) @@ -496,7 +492,7 @@ void RimGridCrossPlotCurveSet::createCurves(const RigEclipseCrossPlotResult& res curve->setGroupingInformation(indexInPlot(), it->first); if (groupingByCategoryResult()) { - curve->setColor(cvf::Color3f(legendConfig()->scalarMapper()->mapToColor(it->first))); + curve->setColor(cvf::Color3f(legendConfig()->scalarMapper()->mapToColor(it->first))); } else { @@ -561,6 +557,44 @@ std::map RimGridCrossPlotCurveSet::calculateCellVisibility } } } + else if (m_plotCellFilterCollection->cellFilterCount() > 0) + { + std::set timeSteps; + if (m_timeStep() == -1) + { + for (int i = 0; i < (int)eclipseCase->timeStepDates().size(); ++i) + { + timeSteps.insert(i); + } + } + else + { + timeSteps.insert(m_timeStep()); + } + + RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData(); + if (eclipseCaseData) + { + RiaDefines::PorosityModelType porosityModel = RiaDefines::MATRIX_MODEL; + + RigCaseCellResultsData* cellResultsData = eclipseCaseData->results(porosityModel); + if (cellResultsData) + { + const RigActiveCellInfo* actCellInfo = cellResultsData->activeCellInfo(); + size_t cellCount = actCellInfo->reservoirCellCount(); + + for (int i : timeSteps) + { + cvf::UByteArray* cellVisibility = &timeStepCellVisibilityMap[i]; + cellVisibility->resize(cellCount); + cellVisibility->setAll(true); + + m_plotCellFilterCollection->computeCellVisibilityFromFilter(i, cellVisibility); + } + } + } + } + return timeStepCellVisibilityMap; } @@ -576,8 +610,7 @@ void RimGridCrossPlotCurveSet::defineUiOrdering(QString uiConfigName, caf::PdmUi uiOrdering.add(&m_cellFilterView); uiOrdering.add(&m_grouping); - if (m_grouping() == GROUP_BY_TIME && - !(m_xAxisProperty->hasDynamicResult() || m_yAxisProperty->hasDynamicResult())) + if (m_grouping() == GROUP_BY_TIME && !(m_xAxisProperty->hasDynamicResult() || m_yAxisProperty->hasDynamicResult())) { m_grouping = NO_GROUPING; } @@ -649,9 +682,8 @@ void RimGridCrossPlotCurveSet::fieldChangedByUi(const caf::PdmFieldHandle* chang { legendConfig()->setColorRange(RimRegularLegendConfig::NORMAL); legendConfig()->setMappingMode(RimRegularLegendConfig::LINEAR_DISCRETE); - } - + loadDataAndUpdate(true); } else if (changedField == &m_cellFilterView) @@ -710,7 +742,7 @@ QList RimGridCrossPlotCurveSet::calculateValueOptions(co } else if (fieldNeedingOptions == &m_grouping) { - std::set validOptions = { NO_GROUPING, GROUP_BY_TIME, GROUP_BY_FORMATION, GROUP_BY_RESULT }; + std::set validOptions = {NO_GROUPING, GROUP_BY_TIME, GROUP_BY_FORMATION, GROUP_BY_RESULT}; if (!hasMultipleTimeSteps()) { validOptions.erase(GROUP_BY_TIME); @@ -762,9 +794,9 @@ void RimGridCrossPlotCurveSet::updateLegend() } } } - else if (m_grouping() == GROUP_BY_TIME) + else if (m_grouping() == GROUP_BY_TIME) { - QStringList timeStepNames = m_case->timeStepStrings(); + QStringList timeStepNames = m_case->timeStepStrings(); std::vector categoryNames; for (auto name : timeStepNames) { @@ -837,7 +869,7 @@ void RimGridCrossPlotCurveSet::swapAxisProperties(bool updatePlot) m_yAxisProperty.removeChildObject(yAxisProperties); m_yAxisProperty = xAxisProperties; m_xAxisProperty = yAxisProperties; - + updateConnectedEditors(); loadDataAndUpdate(updatePlot); } @@ -847,8 +879,7 @@ void RimGridCrossPlotCurveSet::swapAxisProperties(bool updatePlot) //-------------------------------------------------------------------------------------------------- void RimGridCrossPlotCurveSet::exportFormattedData(RifEclipseDataTableFormatter& formatter) const { - if (m_groupedResults.empty()) - return; + if (m_groupedResults.empty()) return; if (m_grouping != NO_GROUPING) { @@ -881,8 +912,8 @@ void RimGridCrossPlotCurveSet::exportFormattedData(RifEclipseDataTableFormatter& } else { - int groupIndex = it->first; - QString groupName = createGroupName(groupIndex); + int groupIndex = it->first; + QString groupName = createGroupName(groupIndex); formatter.add(res.xValues[i]); formatter.add(res.yValues[i]); formatter.add(groupIndex); @@ -914,9 +945,10 @@ bool RimGridCrossPlotCurveSet::isYAxisLogarithmic() const } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void RimGridCrossPlotCurveSet::setFromCaseAndEquilibriumRegion(RimEclipseResultCase* eclipseCase, const QString& dynamicResultName) +void RimGridCrossPlotCurveSet::setFromCaseAndEquilibriumRegion(RimEclipseResultCase* eclipseCase, + const QString& dynamicResultName) { m_case = eclipseCase; @@ -932,13 +964,20 @@ void RimGridCrossPlotCurveSet::setFromCaseAndEquilibriumRegion(RimEclipseResultC } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +void RimGridCrossPlotCurveSet::addCellFilter(RimPlotCellFilter* cellFilter) +{ + m_plotCellFilterCollection->addCellFilter(cellFilter); +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- void RimGridCrossPlotCurveSet::setCustomColor(const cvf::Color3f color) { m_useCustomColor = true; - m_customColor = color; - + m_customColor = color; } //-------------------------------------------------------------------------------------------------- @@ -1015,7 +1054,7 @@ void RimGridCrossPlotCurveSet::setDefaults() if (!project->eclipseCases().empty()) { RimEclipseCase* eclipseCase = project->eclipseCases().front(); - m_case = eclipseCase; + m_case = eclipseCase; m_xAxisProperty->setEclipseCase(eclipseCase); m_yAxisProperty->setEclipseCase(eclipseCase); m_groupingProperty->setEclipseCase(eclipseCase); @@ -1026,7 +1065,7 @@ void RimGridCrossPlotCurveSet::setDefaults() m_yAxisProperty->setResultType(RiaDefines::DYNAMIC_NATIVE); m_yAxisProperty->setResultVariable("PRESSURE"); } - } + } } //-------------------------------------------------------------------------------------------------- @@ -1053,6 +1092,8 @@ void RimGridCrossPlotCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTr uiTreeOrdering.add(curve); } + uiTreeOrdering.add(&m_plotCellFilterCollection); + uiTreeOrdering.skipRemainingChildren(true); } @@ -1062,7 +1103,6 @@ void RimGridCrossPlotCurveSet::defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTr bool RimGridCrossPlotCurveSet::hasMultipleTimeSteps() const { return m_timeStep() == -1 && (m_xAxisProperty->hasDynamicResult() || m_yAxisProperty->hasDynamicResult()); - } //-------------------------------------------------------------------------------------------------- @@ -1075,13 +1115,12 @@ void RimGridCrossPlotCurveSet::filterInvalidCurveValues(RigEclipseCrossPlotResul if (xLog || yLog) { - RigEclipseCrossPlotResult validResult; for (size_t i = 0; i < result->xValues.size(); ++i) { - double xValue = result->xValues[i]; - double yValue = result->yValues[i]; - bool invalid = (xLog && xValue <= 0.0) || (yLog && yValue <= 0.0); + double xValue = result->xValues[i]; + double yValue = result->yValues[i]; + bool invalid = (xLog && xValue <= 0.0) || (yLog && yValue <= 0.0); if (!invalid) { validResult.xValues.push_back(xValue); diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.h index e14646197c..b41904d2aa 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.h +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimGridCrossPlotCurveSet.h @@ -50,6 +50,8 @@ class RimRegularLegendConfig; class QwtPlot; class QwtPlotCurve; class QString; +class RimPlotCellFilterCollection; +class RimPlotCellFilter; class RimGridCrossPlotCurveSetNameConfig : public RimNameConfig { @@ -125,8 +127,10 @@ public: bool isYAxisLogarithmic() const; void setFromCaseAndEquilibriumRegion(RimEclipseResultCase* eclipseResultCase, const QString& dynamicResultName); + void addCellFilter(RimPlotCellFilter* cellFilter); void setCustomColor(const cvf::Color3f color); + protected: void initAfterRead() override; void onLoadDataAndUpdate(bool updateParentPlot); @@ -168,4 +172,6 @@ private: caf::PdmField m_useCustomColor; caf::PdmField m_customColor; + caf::PdmChildField m_plotCellFilterCollection;; + }; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.cpp index df0179511d..7151ade6ab 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.cpp @@ -18,11 +18,18 @@ #include "RimSaturationPressurePlot.h" +#include "RigEclipseCaseData.h" +#include "RigEquil.h" + #include "RimEclipseResultCase.h" +#include "RimEclipseResultDefinition.h" #include "RimGridCrossPlotCurveSet.h" #include "RimPlotAxisAnnotation.h" #include "RimPlotAxisProperties.h" +#include "CellFilters/RimPlotCellPropertyFilter.h" +#include "RigCaseCellResultsData.h" + CAF_PDM_SOURCE_INIT(RimSaturationPressurePlot, "RimSaturationPressurePlot"); //-------------------------------------------------------------------------------------------------- @@ -36,29 +43,144 @@ RimSaturationPressurePlot::RimSaturationPressurePlot() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSaturationPressurePlot::assignCaseAndEquilibriumRegion(RimEclipseResultCase* eclipseResultCase, int equilibriumRegion) +void RimSaturationPressurePlot::assignCaseAndEquilibriumRegion(RiaDefines::PorosityModelType porosityType, + RimEclipseResultCase* eclipseResultCase, + int zeroBasedEquilRegionIndex) { nameConfig()->addDataSetNames = false; - - QString caseName = eclipseResultCase->caseUserDescription(); - QString plotTitle = QString("%1 - EQLNUM %2").arg(caseName).arg(equilibriumRegion); + + QString caseName = eclipseResultCase->caseUserDescription(); + QString plotTitle = QString("%1 - EQLNUM %2").arg(caseName).arg(zeroBasedEquilRegionIndex + 1); nameConfig()->setCustomName(plotTitle); + auto equilData = eclipseResultCase->eclipseCaseData()->equilData(); + auto eq = equilData[zeroBasedEquilRegionIndex]; + + double gasOilContactDepth = eq.gasOilContactDepth(); + double waterOilContactDepth = eq.waterOilContactDepth(); + { RimGridCrossPlotCurveSet* curveSet = createCurveSet(); curveSet->setFromCaseAndEquilibriumRegion(eclipseResultCase, "PRESSURE"); curveSet->setCustomColor(cvf::Color3::BLUE); + + RimPlotCellPropertyFilter* cellFilter = new RimPlotCellPropertyFilter(); + { + RimEclipseResultDefinition* resultDefinition = new RimEclipseResultDefinition(); + resultDefinition->setEclipseCase(eclipseResultCase); + resultDefinition->setResultType(RiaDefines::STATIC_NATIVE); + resultDefinition->setResultVariable("EQLNUM"); + + cellFilter->setResultDefinition(resultDefinition); + } + + cellFilter->setValueRange(zeroBasedEquilRegionIndex + 1, zeroBasedEquilRegionIndex + 1); + + curveSet->addCellFilter(cellFilter); } { RimGridCrossPlotCurveSet* curveSet = createCurveSet(); curveSet->setFromCaseAndEquilibriumRegion(eclipseResultCase, "PDEW"); curveSet->setCustomColor(cvf::Color3::RED); + + { + RimPlotCellPropertyFilter* cellFilter = new RimPlotCellPropertyFilter(); + { + RimEclipseResultDefinition* resultDefinition = new RimEclipseResultDefinition(); + resultDefinition->setEclipseCase(eclipseResultCase); + resultDefinition->setResultType(RiaDefines::STATIC_NATIVE); + resultDefinition->setResultVariable("EQLNUM"); + + cellFilter->setResultDefinition(resultDefinition); + } + + cellFilter->setValueRange(zeroBasedEquilRegionIndex + 1, zeroBasedEquilRegionIndex + 1); + + curveSet->addCellFilter(cellFilter); + } + + { + RigCaseCellResultsData* caseCellResultsData = eclipseResultCase->eclipseCaseData()->results(porosityType); + if (caseCellResultsData) + { + RigEclipseResultAddress depthResultAddress(RiaDefines::STATIC_NATIVE, "DEPTH"); + + double minDepth = 0.0; + double maxDepth = 0.0; + caseCellResultsData->minMaxCellScalarValues(depthResultAddress, minDepth, maxDepth); + + maxDepth = gasOilContactDepth; + + RimPlotCellPropertyFilter* depthCellFilter = new RimPlotCellPropertyFilter(); + { + RimEclipseResultDefinition* resultDefinition = new RimEclipseResultDefinition(); + resultDefinition->setPorosityModel(porosityType); + resultDefinition->setEclipseCase(eclipseResultCase); + resultDefinition->setResultType(depthResultAddress.m_resultCatType); + resultDefinition->setResultVariable(depthResultAddress.m_resultName); + + depthCellFilter->setResultDefinition(resultDefinition); + } + + depthCellFilter->setValueRange(minDepth, maxDepth); + + curveSet->addCellFilter(depthCellFilter); + } + } } + { RimGridCrossPlotCurveSet* curveSet = createCurveSet(); curveSet->setFromCaseAndEquilibriumRegion(eclipseResultCase, "PBUB"); curveSet->setCustomColor(cvf::Color3::GREEN); + + { + RimPlotCellPropertyFilter* cellFilter = new RimPlotCellPropertyFilter(); + { + RimEclipseResultDefinition* resultDefinition = new RimEclipseResultDefinition(); + resultDefinition->setEclipseCase(eclipseResultCase); + resultDefinition->setResultType(RiaDefines::STATIC_NATIVE); + resultDefinition->setResultVariable("EQLNUM"); + + cellFilter->setResultDefinition(resultDefinition); + } + + cellFilter->setValueRange(zeroBasedEquilRegionIndex + 1, zeroBasedEquilRegionIndex + 1); + + curveSet->addCellFilter(cellFilter); + } + + { + RigCaseCellResultsData* caseCellResultsData = eclipseResultCase->eclipseCaseData()->results(porosityType); + if (caseCellResultsData) + { + RigEclipseResultAddress depthResultAddress(RiaDefines::STATIC_NATIVE, "DEPTH"); + + double minDepth = 0.0; + double maxDepth = 0.0; + caseCellResultsData->minMaxCellScalarValues(depthResultAddress, minDepth, maxDepth); + + minDepth = gasOilContactDepth; + maxDepth = waterOilContactDepth; + + RimPlotCellPropertyFilter* depthCellFilter = new RimPlotCellPropertyFilter(); + { + RimEclipseResultDefinition* resultDefinition = new RimEclipseResultDefinition(); + resultDefinition->setPorosityModel(porosityType); + resultDefinition->setEclipseCase(eclipseResultCase); + resultDefinition->setResultType(depthResultAddress.m_resultCatType); + resultDefinition->setResultVariable(depthResultAddress.m_resultName); + + depthCellFilter->setResultDefinition(resultDefinition); + } + + depthCellFilter->setValueRange(minDepth, maxDepth); + + curveSet->addCellFilter(depthCellFilter); + } + } + } RimPlotAxisProperties* yAxisProps = yAxisProperties(); @@ -67,13 +189,15 @@ void RimSaturationPressurePlot::assignCaseAndEquilibriumRegion(RimEclipseResultC { RimPlotAxisAnnotation* annotation = new RimPlotAxisAnnotation; - annotation->setEquilibriumData(eclipseResultCase, equilibriumRegion, RimPlotAxisAnnotation::PL_EQUIL_GAS_OIL_CONTACT); + annotation->setEquilibriumData( + eclipseResultCase, zeroBasedEquilRegionIndex, RimPlotAxisAnnotation::PL_EQUIL_GAS_OIL_CONTACT); yAxisProps->appendAnnotation(annotation); } { RimPlotAxisAnnotation* annotation = new RimPlotAxisAnnotation; - annotation->setEquilibriumData(eclipseResultCase, equilibriumRegion, RimPlotAxisAnnotation::PL_EQUIL_WATER_OIL_CONTACT); + annotation->setEquilibriumData( + eclipseResultCase, zeroBasedEquilRegionIndex, RimPlotAxisAnnotation::PL_EQUIL_WATER_OIL_CONTACT); yAxisProps->appendAnnotation(annotation); } diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.h b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.h index 60e154e8fd..abb295e83e 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.h +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlot.h @@ -19,6 +19,7 @@ #pragma once #include "RimGridCrossPlot.h" +#include "RiaPorosityModel.h" class RimEclipseResultCase; @@ -32,7 +33,9 @@ class RimSaturationPressurePlot : public RimGridCrossPlot public: RimSaturationPressurePlot(); - void assignCaseAndEquilibriumRegion(RimEclipseResultCase* eclipseResultCase, int equilibriumRegion); + void assignCaseAndEquilibriumRegion(RiaDefines::PorosityModelType porosityType, + RimEclipseResultCase* eclipseResultCase, + int zeroBasedEquilRegionIndex); protected: void initAfterRead() override; diff --git a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlotCollection.cpp b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlotCollection.cpp index 18b6c5f8a8..c8d587ee4e 100644 --- a/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlotCollection.cpp +++ b/ApplicationCode/ProjectDataModel/GridCrossPlots/RimSaturationPressurePlotCollection.cpp @@ -58,8 +58,8 @@ void RimSaturationPressurePlotCollection::createSaturationPressurePlots(RimEclip RimSaturationPressurePlot* plot = new RimSaturationPressurePlot(); plot->setAsPlotMdiWindow(); - int equilibriumRegion = static_cast(i) + 1; - plot->assignCaseAndEquilibriumRegion(eclipseResultCase, equilibriumRegion); + int equilibriumRegion = static_cast(i); + plot->assignCaseAndEquilibriumRegion(RiaDefines::MATRIX_MODEL, eclipseResultCase, equilibriumRegion); m_saturationPressurePlots.push_back(plot); } diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp index 2d485413d9..c6c6981dc1 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -186,6 +186,14 @@ void RimEclipseResultDefinition::setEclipseCase(RimEclipseCase* eclipseCase) assignFlowSolutionFromCase(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimEclipseResultDefinition::eclipseCase() +{ + return m_eclipseCase; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h index dd72a0d3c6..1d68a89ef7 100644 --- a/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h +++ b/ApplicationCode/ProjectDataModel/RimEclipseResultDefinition.h @@ -76,6 +76,7 @@ public: void simpleCopy(const RimEclipseResultDefinition* other); void setEclipseCase(RimEclipseCase* eclipseCase); + RimEclipseCase* eclipseCase(); RiaDefines::ResultCatType resultType() const { return m_resultType(); } void setResultType(RiaDefines::ResultCatType val); diff --git a/doc/cell_filter_classes.plantuml b/doc/cell_filter_classes.plantuml new file mode 100644 index 0000000000..c034d9d6e4 --- /dev/null +++ b/doc/cell_filter_classes.plantuml @@ -0,0 +1,13 @@ +@startuml +package Rim { + +PdmObject <|-- RimPlotCellFilter +RimPlotCellFilter <|-- RimPlotCellRangeFilter +RimPlotCellFilter <|-- RimPlotCellPropertyFilter +RimPlotCellFilter <|-- RimPlotCellRegionFilter + +class RimPlotCellFilter +{ + bool isCellAcceptedByFilter(size_t reservoirCellIndex); +} +@enduml