diff --git a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp index 0c002319be..3e335f76ad 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp @@ -144,6 +144,12 @@ RimFractureModelPlot* } } + { + auto task = progInfo.task( "Creating stress track", 2 ); + createStressTrack( plot, fractureModel, eclipseCase, timeStep, RimFractureModelStressCurve::PropertyType::STRESS ); + createStressTrack( plot, fractureModel, eclipseCase, timeStep, RimFractureModelStressCurve::PropertyType::STRESS_GRADIENT ); + } + { auto task = progInfo.task( "Updating all tracks", 5 ); @@ -438,6 +444,50 @@ void RicNewFractureModelPlotFeature::createElasticPropertiesTrack( RimFractureMo RiuPlotMainWindowTools::showPlotMainWindow(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewFractureModelPlotFeature::createStressTrack( RimFractureModelPlot* plot, + RimFractureModel* fractureModel, + RimEclipseCase* eclipseCase, + int timeStep, + RimFractureModelStressCurve::PropertyType propertyType ) +{ + QString trackName = caf::AppEnum::uiText( propertyType ); + RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, trackName, plot ); + plotTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR ); + plotTrack->setLogarithmicScale( false ); + plotTrack->setShowRegionLabels( true ); + plotTrack->setShowWindow( true ); + plotTrack->setColSpan( RimPlot::TWO ); + + caf::ColorTable colors = RiaColorTables::wellLogPlotPaletteColors(); + + RimFractureModelStressCurve* curve = new RimFractureModelStressCurve; + curve->setPropertyType( propertyType ); + curve->setFractureModel( fractureModel ); + curve->setCase( eclipseCase ); + curve->setColor( colors.cycledColor3f( 0 ) ); + curve->setLineStyle( RiuQwtPlotCurve::STYLE_SOLID ); + curve->setLineThickness( 2 ); + curve->setUiName( trackName ); + curve->setAutoNameComponents( false, false, false, false, false ); + + plotTrack->addCurve( curve ); + plotTrack->setAutoScaleXEnabled( true ); + curve->loadDataAndUpdate( true ); + + curve->updateConnectedEditors(); + plotTrack->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 1cf82942e9..2e617afe5e 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h @@ -24,6 +24,7 @@ #include "RimElasticPropertiesCurve.h" #include "RimFractureModelCurve.h" +#include "RimFractureModelStressCurve.h" class RimEclipseCase; class RimFractureModelPlot; @@ -71,6 +72,12 @@ private: int timeStep, RimElasticPropertiesCurve::PropertyType propertyType ); + static void createStressTrack( RimFractureModelPlot* plot, + RimFractureModel* fractureModel, + RimEclipseCase* eclipseCase, + int timeStep, + RimFractureModelStressCurve::PropertyType propertyType ); + static RimFractureModelPlot* createFractureModelPlot( bool showAfterCreation, const QString& plotDescription ); static RimFractureModelPlotCollection* fractureModelPlotCollection(); diff --git a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake index 1c54674072..0f32a2902d 100644 --- a/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationCode/ProjectDataModel/CMakeLists_files.cmake @@ -161,6 +161,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.h ${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertiesCurve.h ${CMAKE_CURRENT_LIST_DIR}/RimLayerCurve.h +${CMAKE_CURRENT_LIST_DIR}/RimFractureModelStressCurve.h ) @@ -326,6 +327,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimFractureModelCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimElasticProperties.cpp ${CMAKE_CURRENT_LIST_DIR}/RimElasticPropertiesCurve.cpp ${CMAKE_CURRENT_LIST_DIR}/RimLayerCurve.cpp +${CMAKE_CURRENT_LIST_DIR}/RimFractureModelStressCurve.cpp ) list(APPEND CODE_HEADER_FILES diff --git a/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.cpp b/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.cpp new file mode 100644 index 0000000000..e7d0139b6e --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.cpp @@ -0,0 +1,192 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RimFractureModelStressCurve.h" + +#include "RiaDefines.h" +#include "RigEclipseCaseData.h" +#include "RigEclipseWellLogExtractor.h" +#include "RigResultAccessorFactory.h" +#include "RigWellLogCurveData.h" +#include "RigWellPath.h" +#include "RigWellPathGeometryTools.h" + +#include "RimCase.h" +#include "RimEclipseCase.h" +#include "RimFractureModel.h" +#include "RimFractureModelPlot.h" +#include "RimModeledWellPath.h" +#include "RimWellLogFile.h" +#include "RimWellLogPlot.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" +#include "RimWellPlotTools.h" + +#include "RiaLogging.h" + +#include "cafPdmUiTreeOrdering.h" + +CAF_PDM_SOURCE_INIT( RimFractureModelStressCurve, "RimFractureModelStressCurve" ); + +namespace caf +{ +template <> +void AppEnum::setUp() +{ + addItem( RimFractureModelStressCurve::PropertyType::STRESS, "STRESS", "Stress" ); + addItem( RimFractureModelStressCurve::PropertyType::STRESS_GRADIENT, "STRESS_GRADIENT", "Stress Gradient" ); + setDefault( RimFractureModelStressCurve::PropertyType::STRESS ); +} +}; // namespace caf + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFractureModelStressCurve::RimFractureModelStressCurve() +{ + CAF_PDM_InitObject( "Fracture Model Curve", "", "", "" ); + + CAF_PDM_InitFieldNoDefault( &m_fractureModel, "FractureModel", "Fracture Model", "", "", "" ); + m_fractureModel.uiCapability()->setUiTreeChildrenHidden( true ); + m_fractureModel.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_propertyType, "PropertyType", "Property Type", "", "", "" ); + + m_wellPath = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimFractureModelStressCurve::~RimFractureModelStressCurve() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFractureModelStressCurve::setPropertyType( PropertyType propertyType ) +{ + m_propertyType = propertyType; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFractureModelStressCurve::setFractureModel( RimFractureModel* fractureModel ) +{ + m_fractureModel = fractureModel; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFractureModelStressCurve::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; + + // Extract porosity data: get the porosity values from parent + RimFractureModelPlot* fractureModelPlot; + firstAncestorOrThisOfType( fractureModelPlot ); + if ( !fractureModelPlot ) + { + RiaLogging::error( QString( "No fracture model plot found." ) ); + return; + } + + std::vector tvDepthInFeet = fractureModelPlot->calculateTrueVerticalDepth(); + for ( double f : tvDepthInFeet ) + { + tvDepthValues.push_back( RiaEclipseUnitTools::feetToMeter( f ) ); + } + + if ( m_propertyType() == PropertyType::STRESS ) + { + values = fractureModelPlot->calculateStress(); + } + else + { + values = fractureModelPlot->calculateStressGradient(); + } + + RimEclipseCase* eclipseCase = dynamic_cast( m_case.value() ); + if ( eclipseCase ) + { + RigWellPath* wellPathGeometry = m_fractureModel->thicknessDirectionWellPath()->wellPathGeometry(); + RigEclipseWellLogExtractor eclExtractor( eclipseCase->eclipseCaseData(), wellPathGeometry, "fracture model" ); + + rkbDiff = eclExtractor.wellPathData()->rkbDiff(); + + // Generate MD data by interpolation + const std::vector& mdValuesOfWellPath = wellPathGeometry->measureDepths(); + std::vector tvdValuesOfWellPath = wellPathGeometry->trueVerticalDepths(); + + measuredDepthValues = + RigWellPathGeometryTools::interpolateMdFromTvd( mdValuesOfWellPath, tvdValuesOfWellPath, tvDepthValues ); + CVF_ASSERT( measuredDepthValues.size() == tvDepthValues.size() ); + } + + 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 RimFractureModelStressCurve::createCurveAutoName() +{ + return caf::AppEnum::uiText( m_propertyType() ); +} diff --git a/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.h b/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.h new file mode 100644 index 0000000000..4eeb125e47 --- /dev/null +++ b/ApplicationCode/ProjectDataModel/RimFractureModelStressCurve.h @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 "RiuQwtSymbol.h" + +#include "cafPdmField.h" +#include "cafPdmPtrField.h" + +#include + +class RimWellPath; +class RimWellMeasurement; +class RimFractureModel; +class RimColorLegend; + +//================================================================================================== +/// +//================================================================================================== +class RimFractureModelStressCurve : public RimWellLogExtractionCurve +{ + CAF_PDM_HEADER_INIT; + +public: + enum class PropertyType + { + STRESS, + STRESS_GRADIENT + }; + + RimFractureModelStressCurve(); + ~RimFractureModelStressCurve() override; + + void setFractureModel( RimFractureModel* fractureModel ); + + void setPropertyType( PropertyType propertyType ); + +protected: + QString createCurveAutoName() override; + + void performDataExtraction( bool* isUsingPseudoLength ) override; + + caf::PdmPtrField m_fractureModel; + caf::PdmField> m_propertyType; +};