///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2018- 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 "RicNewWellBoreStabilityPlotFeature.h" #include "RiaColorTables.h" #include "RiaLogging.h" #include "RiaPlotDefines.h" #include "RiaResultNames.h" #include "RicNewWellLogPlotFeatureImpl.h" #include "RicWellLogTools.h" #include "RigFemPartResultsCollection.h" #include "RigFemResultAddress.h" #include "RigGeoMechCaseData.h" #include "RigWellPath.h" #include "RimGeoMechCase.h" #include "RimGeoMechView.h" #include "RimProject.h" #include "RimTools.h" #include "RimWellBoreStabilityPlot.h" #include "RimWellLogExtractionCurve.h" #include "RimWellLogFile.h" #include "RimWellLogFileChannel.h" #include "RimWellLogFileCurve.h" #include "RimWellLogPlotCollection.h" #include "RimWellLogTrack.h" #include "RimWellLogWbsCurve.h" #include "RimWellMeasurement.h" #include "RimWellMeasurementCollection.h" #include "RimWellMeasurementCurve.h" #include "RimWellPath.h" #include "RimWellPathCollection.h" #include "RicWellLogTools.h" #include "RiuPlotMainWindowTools.h" #include "RiaApplication.h" #include "cafProgressInfo.h" #include "cafSelectionManager.h" #include "cvfAssert.h" #include "cvfMath.h" #include #include #include #include CAF_CMD_SOURCE_INIT( RicNewWellBoreStabilityPlotFeature, "RicNewWellBoreStabilityPlotFeature" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimWellBoreStabilityPlot* RicNewWellBoreStabilityPlotFeature::createPlot( RimGeoMechCase* geoMechCase, RimWellPath* wellPath, int timeStep, const RimWbsParameters* parameters /* = nullptr*/ ) { caf::ProgressInfo progInfo( 100, "Creating Well Bore Stability Plot" ); RimWellBoreStabilityPlot* plot = RicNewWellLogPlotFeatureImpl::createWellBoreStabilityPlot( false, "Well Bore Stability", parameters ); plot->setCaseWellPathAndTimeStep( geoMechCase, wellPath, timeStep ); { auto task = progInfo.task( "Creating formation track", 2 ); createFormationTrack( plot, wellPath, geoMechCase ); } { auto task = progInfo.task( "Creating well design track", 3 ); createCasingShoeTrack( plot, wellPath, geoMechCase ); } { auto task = progInfo.task( "Creating parameters track", 15 ); createParametersTrack( plot, wellPath, geoMechCase, timeStep ); } { auto task = progInfo.task( "Creating stability curves track", 60 ); createStabilityCurvesTrack( plot, wellPath, geoMechCase, timeStep ); } { auto task = progInfo.task( "Creating angles track", 15 ); createAnglesTrack( plot, wellPath, geoMechCase, timeStep ); } { auto task = progInfo.task( "Updating all tracks", 5 ); QString templateText = QString( "Well Bore Stability: %1, %2, %3, %4, %5" ) .arg( RiaDefines::namingVariableCase() ) .arg( RiaDefines::namingVariableWell() ) .arg( RiaDefines::namingVariableTime() ) .arg( RiaDefines::namingVariableAirGap() ) .arg( RiaDefines::namingVariableWaterDepth() ); plot->setNameTemplateText( templateText ); plot->setNamingMethod( RiaDefines::ObjectNamingMethod::TEMPLATE ); plot->setPlotTitleVisible( true ); plot->setLegendsVisible( true ); plot->setLegendsHorizontal( true ); plot->setDepthType( RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH_RKB ); plot->setAutoScaleDepthValuesEnabled( true ); RicNewWellLogPlotFeatureImpl::updateAfterCreation( plot ); } RiuPlotMainWindowTools::showPlotMainWindow(); RiuPlotMainWindowTools::onObjectAppended( plot ); return plot; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RicNewWellBoreStabilityPlotFeature::isCommandEnabled() const { Rim3dView* view = RiaApplication::instance()->activeReservoirView(); if ( !view ) return false; RimGeoMechView* geoMechView = dynamic_cast( view ); return geoMechView != nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::onActionTriggered( bool isChecked ) { RimWellPath* wellPath = caf::SelectionManager::instance()->selectedItemAncestorOfType(); RimWellLogPlotCollection* plotCollection = caf::SelectionManager::instance()->selectedItemOfType(); if ( !wellPath ) { if ( plotCollection ) { RimProject* project = RimProject::current(); std::vector allWellPaths = project->allWellPaths(); if ( !allWellPaths.empty() ) { wellPath = allWellPaths.front(); } } } if ( !wellPath ) { return; } Rim3dView* view = RiaApplication::instance()->activeReservoirView(); if ( !view ) return; RimGeoMechView* geoMechView = dynamic_cast( view ); if ( !geoMechView ) return; RimGeoMechCase* geoMechCase = geoMechView->geoMechCase(); if ( !geoMechCase ) { return; } auto wellPathGeometry = wellPath->wellPathGeometry(); if ( !wellPathGeometry ) { RiaLogging::error( QString( "The well path %1 has no geometry. Cannot create a Well Bore Stability Plot" ).arg( wellPath->name() ) ); return; } if ( wellPathGeometry->rkbDiff() == HUGE_VAL ) { RiaLogging::error( QString( "The well path %1 has no datum elevation and we cannot estimate TVDRKB. Cannot " "create a Well Bore Stability Plot\nTo solve this issue, please activate the Property Editor, " "select Well Targets and activate Generate Well Target at Sea Level" ) .arg( wellPath->name() ) ); return; } createPlot( geoMechCase, wellPath, view->currentTimeStep() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::setupActionLook( QAction* actionToSetup ) { actionToSetup->setText( "New Well Bore Stability Plot" ); actionToSetup->setIcon( QIcon( ":/WellBoreStability16x16.png" ) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::createFormationTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase ) { RimWellLogTrack* formationTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Formations", plot ); formationTrack->setFormationWellPath( wellPath ); formationTrack->setFormationCase( geoMechCase ); formationTrack->setAnnotationType( RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ); formationTrack->setVisiblePropertyValueRange( 0.0, 0.0 ); formationTrack->enablePropertyAxis( false ); formationTrack->setColSpan( RimPlot::ONE ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::createCasingShoeTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase ) { RimWellLogTrack* casingShoeTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Well Design", plot ); casingShoeTrack->setColSpan( RimPlot::ONE ); casingShoeTrack->setFormationWellPath( wellPath ); casingShoeTrack->setFormationCase( geoMechCase ); casingShoeTrack->setAnnotationType( RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ); casingShoeTrack->setAnnotationDisplay( RiaDefines::COLOR_SHADING_AND_LINES ); casingShoeTrack->setShowRegionLabels( false ); casingShoeTrack->setShowWellPathAttributes( true ); casingShoeTrack->setShowBothSidesOfWell( false ); casingShoeTrack->setAnnotationTransparency( 90 ); casingShoeTrack->setWellPathAttributesSource( wellPath ); casingShoeTrack->setVisiblePropertyValueRange( 0.0, 0.0 ); casingShoeTrack->enablePropertyAxis( false ); casingShoeTrack->setAutoScalePropertyValuesEnabled( true ); casingShoeTrack->loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::createParametersTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase, int timeStep ) { RimWellLogTrack* paramCurvesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "WBS Parameters", plot ); paramCurvesTrack->setColSpan( RimPlot::TWO ); paramCurvesTrack->setVisiblePropertyValueRange( 0.0, 2.0 ); paramCurvesTrack->setAutoScalePropertyValuesEnabled( true ); paramCurvesTrack->setTickIntervals( 1.0, 0.2 ); paramCurvesTrack->setPropertyValueAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); paramCurvesTrack->setFormationWellPath( wellPath ); paramCurvesTrack->setFormationCase( geoMechCase ); paramCurvesTrack->setShowRegionLabels( true ); paramCurvesTrack->setShowWindow( false ); std::set parameters = RigWbsParameter::allParameters(); caf::ColorTable colors = RiaColorTables::contrastCategoryPaletteColors(); std::vector lineStyles = { RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID, RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_DASH, RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_DASH_DOT }; size_t i = 0; for ( const RigWbsParameter& param : parameters ) { if ( !param.hasExternalSource() || param == RigWbsParameter::waterDensity() ) continue; RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, param.name().toStdString(), "" ); RimWellLogExtractionCurve* curve = RicWellLogTools::addWellLogExtractionCurve( paramCurvesTrack, geoMechCase, nullptr, wellPath, nullptr, -1, false, false ); curve->setGeoMechResultAddress( resAddr ); curve->setCurrentTimeStep( timeStep ); curve->setColor( colors.cycledColor3f( i ) ); curve->setLineStyle( lineStyles[i % lineStyles.size()] ); curve->setLineThickness( 2 ); curve->loadDataAndUpdate( false ); curve->setAutoNameComponents( false, true, false, false, false ); i++; } paramCurvesTrack->setAutoScalePropertyValuesEnabled( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::createStabilityCurvesTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase, int timeStep ) { RimWellLogTrack* stabilityCurvesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Stability Curves", plot ); stabilityCurvesTrack->setVisiblePropertyValueRange( 0.0, 2.5 ); stabilityCurvesTrack->setColSpan( RimPlot::THREE ); stabilityCurvesTrack->setAutoScalePropertyValuesEnabled( true ); stabilityCurvesTrack->setTickIntervals( 1.0, 0.2 ); stabilityCurvesTrack->setPropertyValueAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); stabilityCurvesTrack->setFormationWellPath( wellPath ); stabilityCurvesTrack->setFormationCase( geoMechCase ); stabilityCurvesTrack->setAnnotationType( RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ); stabilityCurvesTrack->setAnnotationDisplay( RiaDefines::LIGHT_LINES ); stabilityCurvesTrack->setShowRegionLabels( false ); std::vector resultNames = RiaResultNames::wbsDerivedResultNames(); std::vector colors = { cvf::Color3f::BLUE, cvf::Color3f::BROWN, cvf::Color3f::RED, cvf::Color3f::PURPLE, cvf::Color3f::DARK_GREEN, cvf::Color3f::OLIVE }; std::vector lineStyles( resultNames.size(), RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID ); lineStyles.back() = RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_DASH; for ( size_t i = 0; i < resultNames.size(); ++i ) { const QString& resultName = resultNames[i]; RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, resultName.toStdString(), "" ); RimWellLogWbsCurve* curve = RicWellLogTools::addWellLogWbsCurve( stabilityCurvesTrack, geoMechCase, nullptr, wellPath, -1, false, false ); curve->setGeoMechResultAddress( resAddr ); curve->setCurrentTimeStep( timeStep ); curve->setAutoNameComponents( false, true, false, false, false ); curve->setColor( colors[i % colors.size()] ); curve->setLineStyle( lineStyles[i] ); curve->setLineThickness( 2 ); curve->loadDataAndUpdate( false ); curve->setSmoothCurve( true ); curve->setSmoothingThreshold( 0.002 ); if ( resultNames[i] == RiaResultNames::wbsSHMkResult() ) { curve->setCheckState( false ); } } RimWellPathCollection* wellPathCollection = RimTools::wellPathCollection(); const RimWellMeasurementCollection* measurementCollection = wellPathCollection->measurementCollection(); for ( QString wbsMeasurementKind : RimWellMeasurement::measurementKindsForWellBoreStability() ) { for ( RimWellMeasurement* measurement : measurementCollection->measurements() ) { if ( measurement->wellName() == wellPath->name() && measurement->kind() == wbsMeasurementKind ) { RimWellMeasurementCurve* curve = RicWellLogTools::addWellMeasurementCurve( stabilityCurvesTrack, wellPath, wbsMeasurementKind ); curve->loadDataAndUpdate( false ); break; // Only one per measurement kind } } } stabilityCurvesTrack->setAutoScalePropertyValuesEnabled( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RicNewWellBoreStabilityPlotFeature::createAnglesTrack( RimWellBoreStabilityPlot* plot, RimWellPath* wellPath, RimGeoMechCase* geoMechCase, int timeStep ) { RimWellLogTrack* wellPathAnglesTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, "Well Path Angles", plot ); double minValue = 360.0, maxValue = 0.0; const double angleIncrement = 90.0; std::vector resultNames = RiaResultNames::wbsAngleResultNames(); std::vector colors = { cvf::Color3f::GREEN, cvf::Color3f::DARK_ORANGE }; std::vector lineStyles = { RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_DASH, RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID }; for ( size_t i = 0; i < resultNames.size(); ++i ) { const QString& resultName = resultNames[i]; RigFemResultAddress resAddr( RIG_WELLPATH_DERIVED, resultName.toStdString(), "" ); RimWellLogExtractionCurve* curve = RicWellLogTools::addWellLogExtractionCurve( wellPathAnglesTrack, geoMechCase, nullptr, wellPath, nullptr, -1, false, false ); curve->setGeoMechResultAddress( resAddr ); curve->setCurrentTimeStep( timeStep ); curve->setCustomName( resultName ); curve->setColor( colors[i % colors.size()] ); curve->setLineStyle( lineStyles[i % lineStyles.size()] ); curve->setLineThickness( 2 ); curve->loadDataAndUpdate( false ); maxValue = cvf::Math::clamp( maxValue, angleIncrement, 720.0 ); minValue = cvf::Math::clamp( minValue, 0.0, maxValue - 90.0 ); } wellPathAnglesTrack->setColSpan( RimPlot::TWO ); wellPathAnglesTrack->setVisiblePropertyValueRange( minValue, maxValue ); wellPathAnglesTrack->setTickIntervals( 180.0, 45.0 ); wellPathAnglesTrack->setPropertyValueAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR ); wellPathAnglesTrack->setFormationWellPath( wellPath ); wellPathAnglesTrack->setFormationCase( geoMechCase ); wellPathAnglesTrack->setAnnotationType( RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ); wellPathAnglesTrack->setAnnotationDisplay( RiaDefines::LIGHT_LINES ); wellPathAnglesTrack->setShowRegionLabels( false ); }