From 4c1333e33df880bc43ccace09608f83b12da008e Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 10 Jun 2020 12:03:31 +0200 Subject: [PATCH] #6036 Add layers track. --- .../RicNewFractureModelPlotFeature.cpp | 60 ++++ .../RicNewFractureModelPlotFeature.h | 5 +- .../ProjectDataModel/CMakeLists_files.cmake | 2 + .../ProjectDataModel/RimLayerCurve.cpp | 276 ++++++++++++++++++ .../ProjectDataModel/RimLayerCurve.h | 56 ++++ 5 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 ApplicationCode/ProjectDataModel/RimLayerCurve.cpp create mode 100644 ApplicationCode/ProjectDataModel/RimLayerCurve.h diff --git a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp index 2e7b492869..67eb71bf5c 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp @@ -36,6 +36,7 @@ #include "RimFractureModelCurve.h" #include "RimFractureModelPlot.h" #include "RimFractureModelPlotCollection.h" +#include "RimLayerCurve.h" #include "RimMainPlotCollection.h" #include "RimModeledWellPath.h" #include "RimProject.h" @@ -79,6 +80,11 @@ RimFractureModelPlot* createFaciesTrack( plot, fractureModel, eclipseCase ); } + { + auto task = progInfo.task( "Creating layers track", 2 ); + createLayersTrack( plot, fractureModel, eclipseCase ); + } + { auto task = progInfo.task( "Creating parameters track", 15 ); @@ -249,6 +255,60 @@ void RicNewFractureModelPlotFeature::createFaciesTrack( RimFractureModelPlot* pl RiuPlotMainWindowTools::showPlotMainWindow(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFractureModelPlotFeature::createLayersTrack( RimFractureModelPlot* plot, + RimFractureModel* fractureModel, + RimEclipseCase* eclipseCase ) +{ + QString defaultProperty = "OPERNUM_1"; + + RimWellLogTrack* faciesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Layers", plot ); + faciesTrack->setFormationWellPath( fractureModel->thicknessDirectionWellPath() ); + faciesTrack->setFormationCase( eclipseCase ); + // faciesTrack->setAnnotationType( RiuPlotAnnotationTool::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS ); + // faciesTrack->setRegionPropertyResultType( RiaDefines::ResultCatType::INPUT_PROPERTY, defaultProperty ); + + RimColorLegend* faciesColors = RimProject::current()->colorLegendCollection()->findByName( "Facies colors" ); + if ( faciesColors ) + { + faciesTrack->setColorShadingLegend( faciesColors ); + } + + faciesTrack->setVisibleXRange( 0.0, 0.0 ); + faciesTrack->setColSpan( RimPlot::ONE ); + + caf::ColorTable colors = RiaColorTables::contrastCategoryPaletteColors(); + std::vector lineStyles = {RiuQwtPlotCurve::STYLE_SOLID, + RiuQwtPlotCurve::STYLE_DASH, + RiuQwtPlotCurve::STYLE_DASH_DOT}; + + RimLayerCurve* curve = new RimLayerCurve; + curve->setFractureModel( fractureModel ); + curve->setCase( eclipseCase ); + // curve->setEclipseResultCategory( RiaDefines::ResultCatType::INPUT_PROPERTY ); + // curve->setEclipseResultVariable( defaultProperty ); + curve->setColor( colors.cycledColor3f( 0 ) ); + curve->setLineStyle( lineStyles[0] ); + curve->setLineThickness( 2 ); + curve->setAutoNameComponents( false, true, false, false, false ); + + faciesTrack->addCurve( curve ); + faciesTrack->setAutoScaleXEnabled( true ); + curve->loadDataAndUpdate( true ); + + curve->updateConnectedEditors(); + faciesTrack->updateConnectedEditors(); + plot->updateConnectedEditors(); + + RiaApplication::instance()->project()->updateConnectedEditors(); + + RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); + RiuPlotMainWindowTools::selectAsCurrentItem( curve ); + RiuPlotMainWindowTools::showPlotMainWindow(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h index e23a4254e3..2c410c12a0 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h @@ -50,7 +50,10 @@ private: static void createFormationTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase ); static void - createFaciesTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase ); + createFaciesTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase ); + static void + createLayersTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase ); + static RimFractureModelCurve* createParametersTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase, diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 84ddc56f14..1c54674072 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -160,6 +160,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelPlotCollection.h ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.h ${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertiesCurve.h +${CMAKE_CURRENT_LIST_DIR}/RimLayerCurve.h ) @@ -324,6 +325,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelPlotCollection.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.cpp ${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertiesCurve.cpp +${CMAKE_CURRENT_LIST_DIR}/RimLayerCurve.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimLayerCurve.cpp b/ApplicationCode/ProjectDataModel/RimLayerCurve.cpp new file mode 100644 index 0000000000..e7d070f5bd --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimLayerCurve.cpp @@ -0,0 +1,276 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimLayerCurve.h" + +#include "RigEclipseCaseData.h" +#include "RigEclipseWellLogExtractor.h" +#include "RigElasticProperties.h" +#include "RigResultAccessorFactory.h" +#include "RigWellLogCurveData.h" +#include "RigWellPath.h" + +#include "RimCase.h" +#include "RimColorLegend.h" +#include "RimColorLegendCollection.h" +#include "RimColorLegendItem.h" +#include "RimEclipseCase.h" +#include "RimEclipseResultDefinition.h" +#include "RimElasticProperties.h" +#include "RimFractureModel.h" +#include "RimFractureModelPlot.h" +#include "RimModeledWellPath.h" +#include "RimProject.h" +#include "RimTools.h" +#include "RimWellLogFile.h" +#include "RimWellLogPlot.h" +#include "RimWellLogTrack.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" +#include "RimWellPlotTools.h" + +#include "RiuQwtPlotCurve.h" +#include "RiuQwtPlotWidget.h" + +#include "RiaApplication.h" +#include "RiaLogging.h" +#include "RiaPreferences.h" + +#include "cafPdmUiTreeOrdering.h" + +#include +#include + +CAF_PDM_SOURCE_INIT( RimLayerCurve, "LayerCurve" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimLayerCurve::RimLayerCurve() +{ + CAF_PDM_InitObject( "Fracture Model Curve", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_fractureModel, "FractureModel", "Fracture Model", "", "", "" ); + m_fractureModel.uiCapability()->setUiTreeChildrenHidden( true ); + m_fractureModel.uiCapability()->setUiHidden( true ); + + m_wellPath = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimLayerCurve::~RimLayerCurve() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimLayerCurve::setFractureModel( RimFractureModel* fractureModel ) +{ + m_fractureModel = fractureModel; + m_wellPath = fractureModel->thicknessDirectionWellPath(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +// void RimLayerCurve::setEclipseResultCategory( RiaDefines::ResultCatType catType ) +// { +// m_eclipseResultDefinition->setResultType( catType ); +// } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +// void RimLayerCurve::setPropertyType( PropertyType propertyType ) +// { +// m_propertyType = propertyType; +// } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimLayerCurve::performDataExtraction( bool* isUsingPseudoLength ) +{ + std::vector values; + std::vector measuredDepthValues; + std::vector tvDepthValues; + double rkbDiff = 0.0; + + RiaDefines::DepthUnitType depthUnit = RiaDefines::DepthUnitType::UNIT_METER; + QString xUnits = RiaWellLogUnitTools::noUnitString(); + + *isUsingPseudoLength = false; + + RimEclipseCase* eclipseCase = dynamic_cast( m_case.value() ); + if ( eclipseCase ) + { + RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), + m_fractureModel->thicknessDirectionWellPath()->wellPathGeometry(), + "fracture model" ); + + measuredDepthValues = eclExtractor.cellIntersectionMDs(); + tvDepthValues = eclExtractor.cellIntersectionTVDs(); + rkbDiff = eclExtractor.wellPathData()->rkbDiff(); + + // Extract formation data + cvf::ref formationResultAccessor = RigResultAccessorFactory:: + createFromResultAddress( eclipseCase->eclipseCaseData(), + 0, + RiaDefines::PorosityModelType::MATRIX_MODEL, + 0, + RigEclipseResultAddress( RiaDefines::ResultCatType::FORMATION_NAMES, + RiaDefines::activeFormationNamesResultName() ) ); + if ( !formationResultAccessor.notNull() ) + { + RiaLogging::error( QString( "No formation result found." ) ); + return; + } + + CurveSamplingPointData curveData = + RimWellLogTrack::curveSamplingPointData( &eclExtractor, formationResultAccessor.p() ); + + std::vector> yValues; + std::vector formationNamesVector = RimWellLogTrack::formationNamesVector( eclipseCase ); + + std::vector formationNamesToPlot; + RimWellLogTrack::findRegionNamesToPlot( curveData, + formationNamesVector, + RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH, + &formationNamesToPlot, + &yValues ); + + // Extract facies data + m_eclipseResultDefinition->setResultVariable( "OPERNUM_1" ); + m_eclipseResultDefinition->setResultType( RiaDefines::ResultCatType::INPUT_PROPERTY ); + m_eclipseResultDefinition->setEclipseCase( eclipseCase ); + m_eclipseResultDefinition->loadResult(); + + cvf::ref faciesResultAccessor = + RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(), + 0, + m_timeStep, + m_eclipseResultDefinition ); + + if ( !faciesResultAccessor.notNull() ) + { + RiaLogging::error( QString( "No facies result found." ) ); + return; + } + + std::vector faciesValues; + eclExtractor.curveData( faciesResultAccessor.p(), &faciesValues ); + + assert( faciesValues.size() == formationNamesToPlot.size() ); + + values.resize( faciesValues.size() ); // formationNamesToPlot.size() ); + + int layerNo = 0; + QString previousFormationName = ""; + double previousFacies = -1.0; + for ( size_t i = 0; i < faciesValues.size(); i++ ) + { + QString formationName = findFormationNameForDepth( formationNamesToPlot, yValues, tvDepthValues[i] ); + if ( previousFormationName != formationName || previousFacies != faciesValues[i] ) + { + layerNo++; + } + + values[i] = layerNo; + previousFormationName = formationName; + previousFacies = faciesValues[i]; + } + + RiaEclipseUnitTools::UnitSystem eclipseUnitsType = eclipseCase->eclipseCaseData()->unitsType(); + if ( eclipseUnitsType == RiaEclipseUnitTools::UnitSystem::UNITS_FIELD ) + { + // See https://github.com/OPM/ResInsight/issues/538 + + depthUnit = RiaDefines::DepthUnitType::UNIT_FEET; + } + } + + bool performDataSmoothing = false; + if ( !values.empty() && !measuredDepthValues.empty() ) + { + if ( tvDepthValues.empty() ) + { + this->setValuesAndDepths( values, + measuredDepthValues, + RiaDefines::DepthTypeEnum::MEASURED_DEPTH, + 0.0, + depthUnit, + !performDataSmoothing, + xUnits ); + } + else + { + this->setValuesWithMdAndTVD( values, + measuredDepthValues, + tvDepthValues, + rkbDiff, + depthUnit, + !performDataSmoothing, + xUnits ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +// QString RimLayerCurve::findFaciesName( const RimColorLegend& colorLegend, double value ) +// { +// for ( auto item : colorLegend.colorLegendItems() ) +// { +// if ( item->categoryValue() == static_cast( value ) ) return item->categoryName(); +// } + +// return "not found"; +// } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimLayerCurve::findFormationNameForDepth( const std::vector& formationNames, + const std::vector>& depthRanges, + double depth ) +{ + // assert(formationNames.size() == depthRanges.size()); + for ( size_t i = 0; i < formationNames.size(); i++ ) + { + double high = depthRanges[i].second; + double low = depthRanges[i].first; + if ( depth >= low && depth <= high ) + { + return formationNames[i]; + } + } + + return "not found"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimLayerCurve::createCurveAutoName() +{ + return "Layers"; +} diff --git a/ApplicationCode/ProjectDataModel/RimLayerCurve.h b/ApplicationCode/ProjectDataModel/RimLayerCurve.h new file mode 100644 index 0000000000..ebc5b2a61f --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimLayerCurve.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimWellLogExtractionCurve.h" + +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +class RimFractureModel; +class RimColorLegend; + +//================================================================================================== +/// +//================================================================================================== +class RimLayerCurve : public RimWellLogExtractionCurve +{ + CAF_PDM_HEADER_INIT; + +public: + RimLayerCurve(); + ~RimLayerCurve() override; + + void setFractureModel( RimFractureModel* fractureModel ); + + void setEclipseResultCategory( RiaDefines::ResultCatType catType ); + +protected: + QString createCurveAutoName() override; + + void performDataExtraction( bool* isUsingPseudoLength ) override; + + // static QString findFaciesName( const RimColorLegend& colorLegend, double value ); + static QString findFormationNameForDepth( const std::vector& formationNames, + const std::vector>& depthRanges, + double depth ); + + caf::PdmPtrField m_fractureModel; + // caf::PdmField> m_propertyType; +};