From 01d88030d4c1ec0c105f81cd9bac8d254be2a915 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 28 Apr 2021 13:45:04 +0200 Subject: [PATCH] #7609 Calculate and display Ensemble Fracture Statistics plot. --- .../Commands/CMakeLists_files.cmake | 2 + ...eEnsembleFractureStatisticsPlotFeature.cpp | 71 ++++ ...ateEnsembleFractureStatisticsPlotFeature.h | 34 ++ .../ProjectDataModel/CMakeLists_files.cmake | 4 + .../RimEnsembleFractureStatistics.cpp | 8 + .../RimEnsembleFractureStatistics.h | 14 +- .../RimStimPlanFractureTemplate.cpp | 13 +- .../Completions/RimStimPlanFractureTemplate.h | 2 + .../RimContextCommandBuilder.cpp | 5 + .../RimEnsembleFractureStatisticsPlot.cpp | 161 +++++++++ .../RimEnsembleFractureStatisticsPlot.h | 62 ++++ ...sembleFractureStatisticsPlotCollection.cpp | 73 ++++ ...EnsembleFractureStatisticsPlotCollection.h | 48 +++ .../RimMainPlotCollection.cpp | 31 +- .../ProjectDataModel/RimMainPlotCollection.h | 7 +- .../ProjectDataModel/RimProject.cpp | 12 +- .../ReservoirDataModel/CMakeLists_files.cmake | 2 + ...igEnsembleFractureStatisticsCalculator.cpp | 324 ++++++++++++++++++ .../RigEnsembleFractureStatisticsCalculator.h | 68 ++++ .../ReservoirDataModel/RigFractureCell.cpp | 8 + .../ReservoirDataModel/RigFractureCell.h | 1 + 21 files changed, 937 insertions(+), 13 deletions(-) create mode 100644 ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.cpp create mode 100644 ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.h create mode 100644 ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.h create mode 100644 ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.h create mode 100644 ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.h diff --git a/ApplicationLibCode/Commands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CMakeLists_files.cmake index 51e3d1033d..0a5e33508d 100644 --- a/ApplicationLibCode/Commands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CMakeLists_files.cmake @@ -168,8 +168,10 @@ ${CMAKE_CURRENT_LIST_DIR}/RicImportGridModelFromSummaryCurveFeature.cpp if(Qt5Charts_FOUND) list(APPEND SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleFractureStatisticsPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicCreateGridStatisticsPlotFeature.h) list(APPEND SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleFractureStatisticsPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicCreateGridStatisticsPlotFeature.cpp) endif() diff --git a/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.cpp b/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.cpp new file mode 100644 index 0000000000..c895e81598 --- /dev/null +++ b/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.cpp @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "RicCreateEnsembleFractureStatisticsPlotFeature.h" + +#include "RiaGuiApplication.h" + +#include "RimEnsembleFractureStatisticsPlot.h" +#include "RimEnsembleFractureStatisticsPlotCollection.h" +#include "RimMainPlotCollection.h" +#include "RimProject.h" + +#include "RiuPlotMainWindow.h" +#include "RiuPlotMainWindowTools.h" + +#include + +CAF_CMD_SOURCE_INIT( RicCreateEnsembleFractureStatisticsPlotFeature, "RicCreateEnsembleFractureStatisticsPlotFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicCreateEnsembleFractureStatisticsPlotFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateEnsembleFractureStatisticsPlotFeature::onActionTriggered( bool isChecked ) +{ + RimProject* project = RimProject::current(); + + RimEnsembleFractureStatisticsPlotCollection* collection = + project->mainPlotCollection()->ensembleFractureStatisticsPlotCollection(); + + RimEnsembleFractureStatisticsPlot* plot = new RimEnsembleFractureStatisticsPlot(); + plot->zoomAll(); + plot->updateConnectedEditors(); + plot->setAsPlotMdiWindow(); + plot->loadDataAndUpdate(); + + collection->addEnsembleFractureStatisticsPlot( plot ); + collection->updateAllRequiredEditors(); + RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow(); + RiuPlotMainWindowTools::selectAsCurrentItem( plot ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicCreateEnsembleFractureStatisticsPlotFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Create Ensemble Fracture Statistics Plot" ); +} diff --git a/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.h b/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.h new file mode 100644 index 0000000000..b087127bd1 --- /dev/null +++ b/ApplicationLibCode/Commands/RicCreateEnsembleFractureStatisticsPlotFeature.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "cafCmdFeature.h" + +//================================================================================================== +/// +//================================================================================================== +class RicCreateEnsembleFractureStatisticsPlotFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; +}; diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index 19c9cc59a2..20284bf238 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -311,12 +311,16 @@ ${CMAKE_CURRENT_LIST_DIR}/RimWellPathTieIn.cpp if(Qt5Charts_FOUND) list(APPEND SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsPlot.h + ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsPlot.h + ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsPlot.h) list(APPEND SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsPlot.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsPlot.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleFractureStatisticsPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsPlot.cpp) endif() diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.cpp index 1400ffba5e..96af7674a9 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.cpp @@ -422,6 +422,14 @@ std::vector RimEnsembleFractureStatistics::computeStatistics() return xmlFilePaths; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RimEnsembleFractureStatistics::readFractureDefinitions() const +{ + return readFractureDefinitions( m_filePaths, RiaDefines::EclipseUnitSystem::UNITS_METRIC ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.h b/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.h index 5f388e0219..475b31b2ef 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimEnsembleFractureStatistics.h @@ -96,6 +96,14 @@ public: void addFilePath( const QString& filePath ); void loadAndUpdateData(); + std::vector> readFractureDefinitions() const; + + static std::vector> + createFractureGrids( const std::vector>& stimPlanFractureDefinitions, + RiaDefines::EclipseUnitSystem unitSystem, + const QString& resultName, + MeshAlignmentType meshAlignmentType ); + protected: void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, @@ -116,12 +124,6 @@ protected: readFractureDefinitions( const std::vector& filePaths, RiaDefines::EclipseUnitSystem unitSystem ) const; - std::vector> - createFractureGrids( const std::vector>& stimPlanFractureDefinitions, - RiaDefines::EclipseUnitSystem unitSystem, - const QString& resultName, - MeshAlignmentType meshAlignmentType ); - static std::set> findAllResultNames( const std::vector>& stimPlanFractureDefinitions ); diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp index c426c917b2..feb0c7b089 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp @@ -653,10 +653,19 @@ WellFractureIntersectionData //-------------------------------------------------------------------------------------------------- std::pair RimStimPlanFractureTemplate::widthParameterNameAndUnit() const { - if ( m_stimPlanFractureDefinitionData.notNull() ) + return widthParameterNameAndUnit( m_stimPlanFractureDefinitionData ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimStimPlanFractureTemplate::widthParameterNameAndUnit( + cvf::ref stimPlanFractureDefinitionData ) +{ + if ( stimPlanFractureDefinitionData.notNull() ) { std::vector> propertyNamesUnitsOnFile = - m_stimPlanFractureDefinitionData->getStimPlanPropertyNamesUnits(); + stimPlanFractureDefinitionData->getStimPlanPropertyNamesUnits(); for ( const auto& nameUnit : propertyNamesUnitsOnFile ) { diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h b/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h index 590ceebeb5..e6af8d7810 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.h @@ -101,6 +101,8 @@ public: double formationDip() const; + static std::pair widthParameterNameAndUnit( cvf::ref def ); + protected: void initAfterRead() override; diff --git a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp index ef9bf2c24a..aa5febfda4 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimContextCommandBuilder.cpp @@ -152,6 +152,7 @@ #include "RimWellPltPlot.h" #ifdef USE_QTCHARTS +#include "RimEnsembleFractureStatisticsPlotCollection.h" #include "RimGridStatisticsPlotCollection.h" #endif @@ -614,6 +615,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection() { menuBuilder << "RicCreateGridStatisticsPlotFeature"; } + else if ( dynamic_cast( firstUiItem ) ) + { + menuBuilder << "RicCreateEnsembleFractureStatisticsPlotFeature"; + } #endif else if ( dynamic_cast( firstUiItem ) ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.cpp b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.cpp new file mode 100644 index 0000000000..971b089763 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.cpp @@ -0,0 +1,161 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "RimEnsembleFractureStatisticsPlot.h" + +#include "RigEnsembleFractureStatisticsCalculator.h" +#include "RimEnsembleFractureStatistics.h" +#include "RimPlot.h" +#include "RimProject.h" + +#include "RigHistogramData.h" + +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" +#include "cafPdmUiComboBoxEditor.h" + +#include "cvfAssert.h" + +#include + +CAF_PDM_SOURCE_INIT( RimEnsembleFractureStatisticsPlot, "EnsembleFractureStatisticsPlot" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEnsembleFractureStatisticsPlot::RimEnsembleFractureStatisticsPlot() +{ + CAF_PDM_InitObject( "Ensemble Fracture Statistics Plot", "", "", "A Plot of Ensemble Fracture Statistics" ); + + CAF_PDM_InitFieldNoDefault( &m_ensembleFractureStatistics, + "EnsembleFractureStatistics", + "Ensemble Fracture Statistics", + "", + "", + "" ); + m_ensembleFractureStatistics.uiCapability()->setUiTreeChildrenHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_property, "Property", "Property", "", "", "" ); + + m_plotLegendsHorizontal.uiCapability()->setUiHidden( true ); + + setDefaults(); + + setDeletable( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEnsembleFractureStatisticsPlot::~RimEnsembleFractureStatisticsPlot() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlot::setDefaults() +{ + std::vector esfItems; + RimProject::current()->descendantsIncludingThisOfType( esfItems ); + if ( !esfItems.empty() ) m_ensembleFractureStatistics = esfItems.front(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, + const QVariant& oldValue, + const QVariant& newValue ) +{ + RimPlotWindow::fieldChangedByUi( changedField, oldValue, newValue ); + loadDataAndUpdate(); + updateConnectedEditors(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_ensembleFractureStatistics ); + uiOrdering.add( &m_property ); + + caf::PdmUiGroup* plotLayoutGroup = uiOrdering.addNewGroup( "Plot Layout" ); + RimPlotWindow::uiOrderingForPlotLayout( uiConfigName, *plotLayoutGroup ); + + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList + RimEnsembleFractureStatisticsPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) +{ + QList options = RimPlotWindow::calculateValueOptions( fieldNeedingOptions, useOptionsOnly ); + + if ( fieldNeedingOptions == &m_ensembleFractureStatistics ) + { + std::vector esfItems; + RimProject::current()->descendantsIncludingThisOfType( esfItems ); + for ( auto item : esfItems ) + { + options.push_back( caf::PdmOptionItemInfo( item->name(), item ) ); + } + } + + return options; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimEnsembleFractureStatisticsPlot::hasStatisticsData() const +{ + return ( m_viewer && m_ensembleFractureStatistics ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigHistogramData RimEnsembleFractureStatisticsPlot::createStatisticsData() const +{ + RigHistogramData histogramData = + RigEnsembleFractureStatisticsCalculator::createStatisticsData( m_ensembleFractureStatistics(), m_property() ); + + return histogramData; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimEnsembleFractureStatisticsPlot::createAutoName() const +{ + if ( m_ensembleFractureStatistics() == nullptr ) + { + return "Undefined"; + } + + QStringList nameTags; + nameTags += m_ensembleFractureStatistics()->name(); + nameTags += caf::AppEnum::uiText( m_property() ); + + return nameTags.join( ", " ); +} diff --git a/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.h b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.h new file mode 100644 index 0000000000..8b63156f23 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlot.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "RiaDefines.h" + +#include "RigEnsembleFractureStatisticsCalculator.h" + +#include "RimEnsembleFractureStatistics.h" +#include "RimStatisticsPlot.h" + +#include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +class RimEnsembleFractureStatistics; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimEnsembleFractureStatisticsPlot : public RimStatisticsPlot +{ + CAF_PDM_HEADER_INIT; + +public: + RimEnsembleFractureStatisticsPlot(); + ~RimEnsembleFractureStatisticsPlot() override; + +protected: + // Overridden PDM methods + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, + bool* useOptionsOnly ) override; + + QString createAutoName() const override; + + void setDefaults(); + bool hasStatisticsData() const override; + RigHistogramData createStatisticsData() const override; + +protected: + caf::PdmPtrField m_ensembleFractureStatistics; + caf::PdmField> m_property; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.cpp new file mode 100644 index 0000000000..a8572a0ea7 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.cpp @@ -0,0 +1,73 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "RimEnsembleFractureStatisticsPlotCollection.h" + +#include "RimEnsembleFractureStatisticsPlot.h" + +#include "cafPdmFieldScriptingCapability.h" +#include "cafPdmObjectScriptingCapability.h" + +CAF_PDM_SOURCE_INIT( RimEnsembleFractureStatisticsPlotCollection, "EnsembleFractureStatisticsPlotCollection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEnsembleFractureStatisticsPlotCollection::RimEnsembleFractureStatisticsPlotCollection() +{ + CAF_PDM_InitScriptableObject( "Ensemble Fracture Statistics Plots", ":/WellLogPlots16x16.png", "", "" ); + + CAF_PDM_InitScriptableFieldNoDefault( &m_ensembleFractureStatisticsPlots, "EnsembleFractureStatisticsPlots", "", "", "", "" ); + m_ensembleFractureStatisticsPlots.uiCapability()->setUiHidden( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlotCollection::reloadAllPlots() +{ + for ( const auto& w : m_ensembleFractureStatisticsPlots() ) + { + w->loadDataAndUpdate(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlotCollection::addEnsembleFractureStatisticsPlot( RimEnsembleFractureStatisticsPlot* newPlot ) +{ + m_ensembleFractureStatisticsPlots.push_back( newPlot ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector + RimEnsembleFractureStatisticsPlotCollection::ensembleFractureStatisticsPlots() const +{ + return m_ensembleFractureStatisticsPlots.childObjects(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleFractureStatisticsPlotCollection::deleteAllPlots() +{ + m_ensembleFractureStatisticsPlots.deleteAllChildObjects(); +} diff --git a/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.h b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.h new file mode 100644 index 0000000000..db08ef95e5 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimEnsembleFractureStatisticsPlotCollection.h @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021- 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 "cafPdmChildArrayField.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +class RimEnsembleFractureStatisticsPlot; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimEnsembleFractureStatisticsPlotCollection : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + RimEnsembleFractureStatisticsPlotCollection(); + + void addEnsembleFractureStatisticsPlot( RimEnsembleFractureStatisticsPlot* newPlot ); + + std::vector ensembleFractureStatisticsPlots() const; + + void reloadAllPlots(); + + void deleteAllPlots(); + +private: + caf::PdmChildArrayField m_ensembleFractureStatisticsPlots; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp index 5260752da5..19fa17a3a5 100644 --- a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.cpp @@ -44,6 +44,8 @@ #include "RimWellRftPlot.h" #ifdef USE_QTCHARTS +#include "RimEnsembleFractureStatisticsPlot.h" +#include "RimEnsembleFractureStatisticsPlotCollection.h" #include "RimGridStatisticsPlot.h" #include "RimGridStatisticsPlotCollection.h" #endif @@ -109,6 +111,14 @@ RimMainPlotCollection::RimMainPlotCollection() #ifdef USE_QTCHARTS CAF_PDM_InitFieldNoDefault( &m_gridStatisticsPlotCollection, "GridStatisticsPlotCollection", "", "", "", "" ); m_gridStatisticsPlotCollection.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_ensembleFractureStatisticsPlotCollection, + "EnsembleFractureStatisticsPlotCollection", + "", + "", + "", + "" ); + m_ensembleFractureStatisticsPlotCollection.uiCapability()->setUiHidden( true ); #endif m_wellLogPlotCollection = new RimWellLogPlotCollection(); @@ -125,7 +135,8 @@ RimMainPlotCollection::RimMainPlotCollection() m_stimPlanModelPlotCollection = new RimStimPlanModelPlotCollection; m_vfpPlotCollection = new RimVfpPlotCollection(); #ifdef USE_QTCHARTS - m_gridStatisticsPlotCollection = new RimGridStatisticsPlotCollection; + m_gridStatisticsPlotCollection = new RimGridStatisticsPlotCollection; + m_ensembleFractureStatisticsPlotCollection = new RimEnsembleFractureStatisticsPlotCollection; #endif } @@ -265,6 +276,14 @@ RimGridStatisticsPlotCollection* RimMainPlotCollection::gridStatisticsPlotCollec { return m_gridStatisticsPlotCollection(); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEnsembleFractureStatisticsPlotCollection* RimMainPlotCollection::ensembleFractureStatisticsPlotCollection() +{ + return m_ensembleFractureStatisticsPlotCollection(); +} #endif //-------------------------------------------------------------------------------------------------- @@ -287,6 +306,7 @@ void RimMainPlotCollection::deleteAllContainedObjects() m_stimPlanModelPlotCollection()->deleteAllPlots(); #ifdef USE_QTCHARTS m_gridStatisticsPlotCollection()->deleteAllPlots(); + m_ensembleFractureStatisticsPlotCollection()->deleteAllPlots(); #endif } @@ -364,6 +384,15 @@ void RimMainPlotCollection::updatePlotsWithFormations() gridStatisticsPlot->loadDataAndUpdate(); } } + + if ( m_ensembleFractureStatisticsPlotCollection ) + { + for ( RimEnsembleFractureStatisticsPlot* ensembleFractureStatisticsPlot : + m_ensembleFractureStatisticsPlotCollection->ensembleFractureStatisticsPlots() ) + { + ensembleFractureStatisticsPlot->loadDataAndUpdate(); + } + } #endif } diff --git a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.h b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.h index 30729aa3e3..ccfeeebcaf 100644 --- a/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimMainPlotCollection.h @@ -45,6 +45,7 @@ class RimVfpPlotCollection; #ifdef USE_QTCHARTS class RimGridStatisticsPlotCollection; +class RimEnsembleFractureStatisticsPlotCollection; #endif //================================================================================================== @@ -74,7 +75,8 @@ public: RimVfpPlotCollection* vfpPlotCollection(); #ifdef USE_QTCHARTS - RimGridStatisticsPlotCollection* gridStatisticsPlotCollection(); + RimGridStatisticsPlotCollection* gridStatisticsPlotCollection(); + RimEnsembleFractureStatisticsPlotCollection* ensembleFractureStatisticsPlotCollection(); #endif void deleteAllContainedObjects(); @@ -105,7 +107,8 @@ private: caf::PdmChildField m_stimPlanModelPlotCollection; caf::PdmChildField m_vfpPlotCollection; #ifdef USE_QTCHARTS - caf::PdmChildField m_gridStatisticsPlotCollection; + caf::PdmChildField m_gridStatisticsPlotCollection; + caf::PdmChildField m_ensembleFractureStatisticsPlotCollection; #endif caf::PdmField m_show; diff --git a/ApplicationLibCode/ProjectDataModel/RimProject.cpp b/ApplicationLibCode/ProjectDataModel/RimProject.cpp index a8cfefaba4..cff1b92eb6 100644 --- a/ApplicationLibCode/ProjectDataModel/RimProject.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimProject.cpp @@ -91,6 +91,8 @@ #include "RimWellPathCollection.h" #ifdef USE_QTCHARTS +#include "RimEnsembleFractureStatisticsPlot.h" +#include "RimEnsembleFractureStatisticsPlotCollection.h" #include "RimGridStatisticsPlot.h" #include "RimGridStatisticsPlotCollection.h" #endif @@ -1465,9 +1467,15 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q itemCollection->add( mainPlotCollection->vfpPlotCollection() ); } #ifdef USE_QTCHARTS - if ( mainPlotCollection->gridStatisticsPlotCollection() ) + if ( mainPlotCollection->gridStatisticsPlotCollection() || + mainPlotCollection->ensembleFractureStatisticsPlotCollection() ) { - itemCollection->add( mainPlotCollection->gridStatisticsPlotCollection() ); + auto statisticsItemCollection = itemCollection->add( "Statistics Plots", ":/Folder.png" ); + if ( mainPlotCollection->gridStatisticsPlotCollection() ) + statisticsItemCollection->add( mainPlotCollection->gridStatisticsPlotCollection() ); + + if ( mainPlotCollection->ensembleFractureStatisticsPlotCollection() ) + statisticsItemCollection->add( mainPlotCollection->ensembleFractureStatisticsPlotCollection() ); } #endif } diff --git a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake index b71bf2a794..3591e37513 100644 --- a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake @@ -81,6 +81,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.h ${CMAKE_CURRENT_LIST_DIR}/RigWellDiskData.h ${CMAKE_CURRENT_LIST_DIR}/RigGocadData.h ${CMAKE_CURRENT_LIST_DIR}/RigElasticProperties.h +${CMAKE_CURRENT_LIST_DIR}/RigEnsembleFractureStatisticsCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigHistogramData.h ${CMAKE_CURRENT_LIST_DIR}/RigVisibleTracerFilter.h ${CMAKE_CURRENT_LIST_DIR}/RigTracerPoint.h @@ -165,6 +166,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RigNncConnection.cpp ${CMAKE_CURRENT_LIST_DIR}/RigWellDiskData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigGocadData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigElasticProperties.cpp +${CMAKE_CURRENT_LIST_DIR}/RigEnsembleFractureStatisticsCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigHistogramData.cpp ${CMAKE_CURRENT_LIST_DIR}/RigVisibleTracerFilter.cpp ${CMAKE_CURRENT_LIST_DIR}/RigTracerPoint.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.cpp b/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.cpp new file mode 100644 index 0000000000..eada877417 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.cpp @@ -0,0 +1,324 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020 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 "RigEnsembleFractureStatisticsCalculator.h" + +#include "RiaDefines.h" +#include "RiaWeightedMeanCalculator.h" + +#include "RigFractureCell.h" +#include "RigFractureGrid.h" +#include "RigHistogramData.h" +#include "RigStatisticsMath.h" +#include "RigStimPlanFractureDefinition.h" +#include "RigTransmissibilityEquations.h" + +#include "RimEnsembleFractureStatistics.h" +#include "RimStimPlanFractureTemplate.h" + +#include "cafAppEnum.h" + +#include "cvfObject.h" + +#include + +namespace caf +{ +template <> +void caf::AppEnum::setUp() +{ + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::HEIGHT, "HEIGHT", "Height" ); + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::AREA, "AREA", "Area" ); + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::WIDTH, "WIDTH", "Width" ); + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::XF, "XF", "Xf" ); + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::KFWF, "KFWF", "KfWf" ); + addItem( RigEnsembleFractureStatisticsCalculator::PropertyType::PERMEABILITY, "PERMEABILITY", "Permeability" ); + setDefault( RigEnsembleFractureStatisticsCalculator::PropertyType::HEIGHT ); +} +}; // namespace caf + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigHistogramData RigEnsembleFractureStatisticsCalculator::createStatisticsData( RimEnsembleFractureStatistics* esf, + PropertyType propertyType ) +{ + std::vector> defs = esf->readFractureDefinitions(); + + std::vector samples; + if ( propertyType == PropertyType::HEIGHT ) + { + samples = calculateGridStatistics( defs, &RigEnsembleFractureStatisticsCalculator::calculateHeight ); + } + else if ( propertyType == PropertyType::AREA ) + { + samples = calculateGridStatistics( defs, &RigEnsembleFractureStatisticsCalculator::calculateArea ); + } + else if ( propertyType == PropertyType::WIDTH ) + { + samples = + calculateAreaWeightedStatistics( defs, &RigEnsembleFractureStatisticsCalculator::calculateAreaWeightedWidth ); + } + else if ( propertyType == PropertyType::PERMEABILITY ) + { + samples = + calculateAreaWeightedStatistics( defs, + &RigEnsembleFractureStatisticsCalculator::calculateAreaWeightedPermeability ); + } + else if ( propertyType == PropertyType::XF ) + { + samples = calculateGridStatistics( defs, &RigEnsembleFractureStatisticsCalculator::calculateXf ); + } + else if ( propertyType == PropertyType::KFWF ) + { + samples = calculateGridStatistics( defs, &RigEnsembleFractureStatisticsCalculator::calculateKfWf ); + } + + RigHistogramData histogramData; + + double sum; + double range; + double dev; + RigStatisticsMath::calculateBasicStatistics( samples, + &histogramData.min, + &histogramData.max, + &sum, + &range, + &histogramData.mean, + &dev ); + + double p50; + double mean; + RigStatisticsMath::calculateStatisticsCurves( samples, &histogramData.p10, &p50, &histogramData.p90, &mean ); + + // TODO: this leaks memory: api assume the the histogram is owned by someone else (which is kind-of-strange) + std::vector* histogram = new std::vector(); + RigHistogramCalculator histogramCalculator( histogramData.min, histogramData.max, 20, histogram ); + for ( auto s : samples ) + histogramCalculator.addValue( s ); + + histogramData.histogram = histogram; + + return histogramData; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigEnsembleFractureStatisticsCalculator::calculateGridStatistics( + const std::vector>& defs, + double( func )( cvf::cref ) ) +{ + std::vector samples; + if ( defs.empty() ) return samples; + + // TODO: heuristic to find conductivity name? + QString conductivityResultName = defs[0]->conductivityResultNames()[0]; + + std::vector> grids = + RimEnsembleFractureStatistics::createFractureGrids( defs, + RiaDefines::EclipseUnitSystem::UNITS_METRIC, + conductivityResultName, + RimEnsembleFractureStatistics::MeshAlignmentType::PERFORATION_DEPTH ); + + for ( auto grid : grids ) + { + double result = func( grid ); + samples.push_back( result ); + } + + return samples; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateHeight( cvf::cref fractureGrid ) +{ + double longestRange = 0.0; + + for ( size_t i = 0; i < fractureGrid->iCellCount(); i++ ) + { + double currentAggregatedDistanceY = 0.0; + for ( size_t j = 0; j < fractureGrid->jCellCount(); j++ ) + { + size_t idx = fractureGrid->getGlobalIndexFromIJ( i, j ); + auto fractureCell = fractureGrid->cellFromIndex( idx ); + + double conductivityValue = fractureCell.getConductivityValue(); + if ( conductivityValue > 0.0 ) + { + currentAggregatedDistanceY += fractureCell.cellSizeZ(); + } + else + { + longestRange = std::max( longestRange, currentAggregatedDistanceY ); + currentAggregatedDistanceY = 0.0; + } + } + + longestRange = std::max( longestRange, currentAggregatedDistanceY ); + } + + return longestRange; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateArea( cvf::cref fractureGrid ) +{ + double sum = 0.0; + for ( auto fractureCell : fractureGrid->fractureCells() ) + { + double value = fractureCell.getConductivityValue(); + if ( !std::isinf( value ) && value > 0.0 ) + { + sum += fractureCell.area(); + } + } + + return sum; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateKfWf( cvf::cref fractureGrid ) +{ + RiaWeightedMeanCalculator calc; + for ( auto fractureCell : fractureGrid->fractureCells() ) + { + double value = fractureCell.getConductivityValue(); + if ( !std::isinf( value ) && value > 0.0 ) + { + double area = fractureCell.area(); + calc.addValueAndWeight( value, area ); + } + } + + return calc.weightedMean(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigEnsembleFractureStatisticsCalculator::calculateAreaWeightedStatistics( + const std::vector>& defs, + double( func )( cvf::cref, cvf::cref ) ) +{ + std::vector samples; + if ( defs.empty() ) return samples; + + // TODO: heuristic to find conductivity name? + QString conductivityResultName = defs[0]->conductivityResultNames()[0]; + + std::vector> grids = + RimEnsembleFractureStatistics::createFractureGrids( defs, + RiaDefines::EclipseUnitSystem::UNITS_METRIC, + conductivityResultName, + RimEnsembleFractureStatistics::MeshAlignmentType::PERFORATION_DEPTH ); + + QString widthResultName = RimStimPlanFractureTemplate::widthParameterNameAndUnit( defs[0] ).first; + std::vector> widthGrids = + RimEnsembleFractureStatistics::createFractureGrids( defs, + RiaDefines::EclipseUnitSystem::UNITS_METRIC, + widthResultName, + RimEnsembleFractureStatistics::MeshAlignmentType::PERFORATION_DEPTH ); + + CAF_ASSERT( grids.size() == widthGrids.size() ); + + for ( size_t i = 0; i < grids.size(); i++ ) + { + double result = func( grids[i], widthGrids[i] ); + samples.push_back( result ); + } + + return samples; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateAreaWeightedWidth( cvf::cref conductivityGrid, + cvf::cref widthGrid ) +{ + RiaWeightedMeanCalculator calc; + const std::vector& conductivityCells = conductivityGrid->fractureCells(); + const std::vector& widthCells = widthGrid->fractureCells(); + CAF_ASSERT( conductivityCells.size() == widthCells.size() ); + + for ( size_t i = 0; i < conductivityCells.size(); i++ ) + { + double value = conductivityCells[i].getConductivityValue(); + if ( !std::isinf( value ) && value > 0.0 ) + { + double cellArea = conductivityCells[i].area(); + // TODO: conductivity is misleading here + double widthValue = widthCells[i].getConductivityValue(); + calc.addValueAndWeight( widthValue, cellArea ); + } + } + + return calc.weightedMean(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateAreaWeightedPermeability( cvf::cref conductivityGrid, + cvf::cref widthGrid ) +{ + RiaWeightedMeanCalculator calc; + const std::vector& conductivityCells = conductivityGrid->fractureCells(); + const std::vector& widthCells = widthGrid->fractureCells(); + CAF_ASSERT( conductivityCells.size() == widthCells.size() ); + + for ( size_t i = 0; i < conductivityCells.size(); i++ ) + { + double conductivity = conductivityCells[i].getConductivityValue(); + if ( !std::isinf( conductivity ) && conductivity > 0.0 ) + { + double cellArea = conductivityCells[i].area(); + // TODO: conductivity is misleading here + double width = widthCells[i].getConductivityValue(); + double permeability = RigTransmissibilityEquations::permeability( conductivity, width ); + calc.addValueAndWeight( permeability, cellArea ); + } + } + + return calc.weightedMean(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigEnsembleFractureStatisticsCalculator::calculateXf( cvf::cref fractureGrid ) +{ + double height = calculateHeight( fractureGrid ); + double area = calculateArea( fractureGrid ); + + if ( height > 0.0 ) + { + double length = area / height; + double halfLength = length / 2.0; + return halfLength; + } + + return 0.0; +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.h b/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.h new file mode 100644 index 0000000000..2fec3d50c2 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigEnsembleFractureStatisticsCalculator.h @@ -0,0 +1,68 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2021 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 "RigHistogramData.h" + +#include "cvfObject.h" + +#include +#include + +class RimEnsembleFractureStatistics; +class RigFractureGrid; +class RigStimPlanFractureDefinition; + +//================================================================================================== +/// +/// +//================================================================================================== +class RigEnsembleFractureStatisticsCalculator +{ +public: + enum class PropertyType + { + HEIGHT, + AREA, + WIDTH, + XF, + KFWF, + PERMEABILITY + }; + + static RigHistogramData createStatisticsData( RimEnsembleFractureStatistics* esf, PropertyType propertyType ); + +private: + static std::vector calculateGridStatistics( const std::vector>& defs, + double( func )( cvf::cref ) ); + + static std::vector + calculateAreaWeightedStatistics( const std::vector>& defs, + double( func )( cvf::cref, cvf::cref ) ); + + static double calculateHeight( cvf::cref fractureGrid ); + static double calculateArea( cvf::cref fractureGrid ); + static double calculateXf( cvf::cref fractureGrid ); + static double calculateKfWf( cvf::cref fractureGrid ); + + static double calculateAreaWeightedWidth( cvf::cref conductivityGrid, + cvf::cref widthGrid ); + static double calculateAreaWeightedPermeability( cvf::cref conductivityGrid, + cvf::cref widthGrid ); +}; diff --git a/ApplicationLibCode/ReservoirDataModel/RigFractureCell.cpp b/ApplicationLibCode/ReservoirDataModel/RigFractureCell.cpp index faab335854..8776aae6f4 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFractureCell.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigFractureCell.cpp @@ -99,3 +99,11 @@ double RigFractureCell::cellSizeZ() const if ( m_polygon.size() > 2 ) return ( m_polygon[2] - m_polygon[1] ).length(); return cvf::UNDEFINED_DOUBLE; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigFractureCell::area() const +{ + return cellSizeX() * cellSizeZ(); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigFractureCell.h b/ApplicationLibCode/ReservoirDataModel/RigFractureCell.h index 9cdf0c5866..de3558c849 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigFractureCell.h +++ b/ApplicationLibCode/ReservoirDataModel/RigFractureCell.h @@ -41,6 +41,7 @@ public: double cellSizeX() const; double cellSizeZ() const; + double area() const; private: std::vector m_polygon;