diff --git a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp index d09db78ee5..155e97ef70 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.cpp @@ -69,6 +69,7 @@ RimFractureModelPlot* caf::ProgressInfo progInfo( 100, "Creating Fracture Model Plot" ); RimFractureModelPlot* plot = createFractureModelPlot( true, "Fracture Model" ); + plot->setFractureModel( fractureModel ); { auto task = progInfo.task( "Creating formation track", 2 ); @@ -88,29 +89,34 @@ RimFractureModelPlot* { auto task = progInfo.task( "Creating parameters track", 15 ); - std::vector> results = - {std::make_tuple( "PORO", - RiaDefines::ResultCatType::STATIC_NATIVE, - RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE ), - std::make_tuple( "PRESSURE", - RiaDefines::ResultCatType::DYNAMIC_NATIVE, - RimFractureModelCurve::MissingValueStrategy::LINEAR_INTERPOLATION ), - std::make_tuple( "PERMX", - RiaDefines::ResultCatType::STATIC_NATIVE, - RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE ), - std::make_tuple( "PERMZ", - RiaDefines::ResultCatType::STATIC_NATIVE, - RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE )}; + std::map plots; - for ( auto result : results ) + plots["Porosity"] = {std::make_tuple( "PORO", + RiaDefines::ResultCatType::STATIC_NATIVE, + RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE, + false )}; + + plots["Pressure"] = {std::make_tuple( "PRESSURE", + RiaDefines::ResultCatType::DYNAMIC_NATIVE, + RimFractureModelCurve::MissingValueStrategy::LINEAR_INTERPOLATION, + false ), + std::make_tuple( "PRESSURE", + RiaDefines::ResultCatType::DYNAMIC_NATIVE, + RimFractureModelCurve::MissingValueStrategy::LINEAR_INTERPOLATION, + true )}; + + plots["Permeability"] = {std::make_tuple( "PERMX", + RiaDefines::ResultCatType::STATIC_NATIVE, + RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE, + false ), + std::make_tuple( "PERMZ", + RiaDefines::ResultCatType::STATIC_NATIVE, + RimFractureModelCurve::MissingValueStrategy::DEFAULT_VALUE, + false )}; + + for ( auto result : plots ) { - createParametersTrack( plot, - fractureModel, - eclipseCase, - timeStep, - std::get<0>( result ), - std::get<1>( result ), - std::get<2>( result ) ); + createParametersTrack( plot, fractureModel, eclipseCase, timeStep, result.first, result.second ); } } @@ -121,7 +127,9 @@ RimFractureModelPlot* {RimElasticPropertiesCurve::PropertyType::YOUNGS_MODULUS, RimElasticPropertiesCurve::PropertyType::POISSONS_RATIO, RimElasticPropertiesCurve::PropertyType::K_IC, - RimElasticPropertiesCurve::PropertyType::PROPPANT_EMBEDMENT}; + RimElasticPropertiesCurve::PropertyType::PROPPANT_EMBEDMENT, + RimElasticPropertiesCurve::PropertyType::BIOT_COEFFICIENT, + RimElasticPropertiesCurve::PropertyType::K0}; for ( auto result : results ) { @@ -315,16 +323,14 @@ void RicNewFractureModelPlotFeature::createLayersTrack( RimFractureModelPlot* pl //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimFractureModelCurve* - RicNewFractureModelPlotFeature::createParametersTrack( RimFractureModelPlot* plot, - RimFractureModel* fractureModel, - RimEclipseCase* eclipseCase, - int timeStep, - const QString& resultVariable, - RiaDefines::ResultCatType resultCategoryType, - RimFractureModelCurve::MissingValueStrategy missingValueStrategy ) +void RicNewFractureModelPlotFeature::createParametersTrack( RimFractureModelPlot* plot, + RimFractureModel* fractureModel, + RimEclipseCase* eclipseCase, + int timeStep, + const QString& trackTitle, + const PlotDefVector& curveConfigurations ) { - RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, resultVariable, plot ); + RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, trackTitle, plot ); plotTrack->setFormationWellPath( fractureModel->thicknessDirectionWellPath() ); plotTrack->setColSpan( RimPlot::TWO ); plotTrack->setVisibleXRange( 0.0, 2.0 ); @@ -340,32 +346,54 @@ RimFractureModelCurve* RiuQwtPlotCurve::STYLE_DASH, RiuQwtPlotCurve::STYLE_DASH_DOT}; - RimFractureModelCurve* curve = new RimFractureModelCurve; - curve->setFractureModel( fractureModel ); - curve->setCase( eclipseCase ); - curve->setEclipseResultVariable( resultVariable ); - curve->setEclipseResultCategory( resultCategoryType ); - curve->setMissingValueStrategy( missingValueStrategy ); - curve->setColor( colors.cycledColor3f( 0 ) ); - curve->setLineStyle( lineStyles[0] ); - curve->setLineThickness( 2 ); - curve->setAutoNameComponents( false, true, false, false, false ); + int colorIndex = 0; + for ( auto curveConfig : curveConfigurations ) + { + QString resultVariable = std::get<0>( curveConfig ); + RiaDefines::ResultCatType resultCategoryType = std::get<1>( curveConfig ); + RimFractureModelCurve::MissingValueStrategy missingValueStrategy = std::get<2>( curveConfig ); + bool fixedInitialTimeStep = std::get<3>( curveConfig ); - plotTrack->addCurve( curve ); - plotTrack->setAutoScaleXEnabled( true ); - curve->loadDataAndUpdate( true ); + RimFractureModelCurve* curve = new RimFractureModelCurve; + + curve->setFractureModel( fractureModel ); + curve->setCase( eclipseCase ); + curve->setEclipseResultVariable( resultVariable ); + curve->setEclipseResultCategory( resultCategoryType ); + curve->setMissingValueStrategy( missingValueStrategy ); + curve->setColor( colors.cycledColor3f( colorIndex ) ); + curve->setLineStyle( lineStyles[0] ); + curve->setLineThickness( 2 ); + + if ( fixedInitialTimeStep ) + { + curve->setAutoNameComponents( false, false, false, false, false ); + curve->setCustomName( QString( "INITIAL %1" ).arg( resultVariable ) ); + curve->setCurrentTimeStep( 0 ); + } + else + { + curve->setAutoNameComponents( false, true, false, false, false ); + curve->setCurrentTimeStep( timeStep ); + } + + plotTrack->addCurve( curve ); + plotTrack->setAutoScaleXEnabled( true ); + curve->loadDataAndUpdate( true ); + + curve->updateConnectedEditors(); + + colorIndex++; + } - curve->updateConnectedEditors(); plotTrack->updateConnectedEditors(); plot->updateConnectedEditors(); RiaApplication::instance()->project()->updateConnectedEditors(); RiaGuiApplication::instance()->getOrCreateMainPlotWindow(); - RiuPlotMainWindowTools::selectAsCurrentItem( curve ); + // RiuPlotMainWindowTools::selectAsCurrentItem( curve ); RiuPlotMainWindowTools::showPlotMainWindow(); - - return curve; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h index 2c410c12a0..0d6002922d 100644 --- a/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h +++ b/ApplicationCode/Commands/CompletionCommands/RicNewFractureModelPlotFeature.h @@ -30,6 +30,9 @@ class RimFractureModelPlot; class RimFractureModelPlotCollection; class RimFractureModel; +typedef std::tuple PlotDef; +typedef std::vector PlotDefVector; + //================================================================================================== /// //================================================================================================== @@ -54,13 +57,12 @@ private: static void createLayersTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase ); - static RimFractureModelCurve* createParametersTrack( RimFractureModelPlot* plot, - RimFractureModel* fractureModel, - RimEclipseCase* eclipseCase, - int timeStep, - const QString& resultVariable, - RiaDefines::ResultCatType resultCategoryType, - RimFractureModelCurve::MissingValueStrategy missingValueStrategy ); + static void createParametersTrack( RimFractureModelPlot* plot, + RimFractureModel* fractureModel, + RimEclipseCase* eclipseCase, + int timeStep, + const QString& trackTitle, + const PlotDefVector& curveConfiguration ); static void createElasticPropertiesTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, diff --git a/ApplicationCode/Commands/RicElasticPropertiesImportTools.cpp b/ApplicationCode/Commands/RicElasticPropertiesImportTools.cpp index ab0b91f9df..ba28f4215e 100644 --- a/ApplicationCode/Commands/RicElasticPropertiesImportTools.cpp +++ b/ApplicationCode/Commands/RicElasticPropertiesImportTools.cpp @@ -62,7 +62,6 @@ void RicElasticPropertiesImportTools::importElasticPropertiesFromFile( const QSt } RimElasticProperties* rimElasticProperties = new RimElasticProperties; - // rimElasticProperties->setFilePath(); for ( FaciesKey key : faciesKeys ) { std::vector matchingFacies; @@ -93,7 +92,9 @@ void RicElasticPropertiesImportTools::importElasticPropertiesFromFile( const QSt item.youngsModulus, item.poissonsRatio, item.K_Ic, - item.proppantEmbedment ); + item.proppantEmbedment, + item.biotCoefficient, + item.k0 ); } rimElasticProperties->setPropertiesForFacies( key, rigElasticProperties ); diff --git a/ApplicationCode/FileInterface/RifElasticPropertiesReader.cpp b/ApplicationCode/FileInterface/RifElasticPropertiesReader.cpp index ed0d58d473..cbe611b6eb 100644 --- a/ApplicationCode/FileInterface/RifElasticPropertiesReader.cpp +++ b/ApplicationCode/FileInterface/RifElasticPropertiesReader.cpp @@ -79,7 +79,7 @@ RifElasticProperties { QStringList tokens = tokenize( line, "," ); - if ( tokens.size() != 8 ) + if ( tokens.size() != 10 ) { throw FileParseException( QString( "Incomplete data on line %1: %2" ).arg( lineNumber ).arg( filePath ) ); } @@ -93,7 +93,9 @@ RifElasticProperties << "Young's Modulus" << "Poisson's Ratio" << "K-Ic" - << "Proppant Embedment"; + << "Proppant Embedment" + << "Biot Coefficient" + << "k0"; verifyNonEmptyTokens( tokens, nameOfNonEmptyTokens, lineNumber, filePath ); RifElasticProperties elasticProperties; @@ -105,6 +107,8 @@ RifElasticProperties elasticProperties.poissonsRatio = parseDouble( tokens[5], "Poisson's Ratio", lineNumber, filePath ); elasticProperties.K_Ic = parseDouble( tokens[6], "K-Ic", lineNumber, filePath ); elasticProperties.proppantEmbedment = parseDouble( tokens[7], "Proppant Embedment", lineNumber, filePath ); + elasticProperties.biotCoefficient = parseDouble( tokens[8], "Biot Coefficient", lineNumber, filePath ); + elasticProperties.k0 = parseDouble( tokens[9], "k0", lineNumber, filePath ); return elasticProperties; } diff --git a/ApplicationCode/FileInterface/RifElasticPropertiesReader.h b/ApplicationCode/FileInterface/RifElasticPropertiesReader.h index a756ef8347..83c5a49e16 100644 --- a/ApplicationCode/FileInterface/RifElasticPropertiesReader.h +++ b/ApplicationCode/FileInterface/RifElasticPropertiesReader.h @@ -32,6 +32,8 @@ struct RifElasticProperties double poissonsRatio; double K_Ic; double proppantEmbedment; + double biotCoefficient; + double k0; }; //================================================================================================== diff --git a/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.cpp b/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.cpp index 9addc1f559..182def720c 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.cpp @@ -108,6 +108,13 @@ RimFractureModel::RimFractureModel() CAF_PDM_InitField( &m_defaultPorosity, "DefaultPorosity", 0.0, "Default Porosity", "", "", "" ); CAF_PDM_InitField( &m_defaultPermeability, "DefaultPermeability", 10.0e-6, "Default Permeability", "", "", "" ); + // Stress unit: bar + // Stress gradient unit: bar/m + // Depth is meter + CAF_PDM_InitField( &m_verticalStress, "VerticalStress", 879.0, "Vertical Stress", "", "", "" ); + CAF_PDM_InitField( &m_verticalStressGradient, "VerticalStressGradient", 0.238, "Vertical Stress Gradient", "", "", "" ); + CAF_PDM_InitField( &m_stressDepth, "StressDepth", 1000.0, "Stress Depth", "", "", "" ); + CAF_PDM_InitFieldNoDefault( &m_elasticProperties, "ElasticProperties", "Elastic Properties", "", "", "" ); m_elasticProperties.uiCapability()->setUiHidden( true ); m_elasticProperties.uiCapability()->setUiTreeHidden( true ); @@ -522,3 +529,27 @@ double RimFractureModel::getDefaultForMissingValue( const QString& keyword ) con return std::numeric_limits::infinity(); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModel::verticalStress() const +{ + return m_verticalStress; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModel::verticalStressGradient() const +{ + return m_verticalStressGradient; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModel::stressDepth() const +{ + return m_stressDepth; +} diff --git a/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.h b/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.h index 216210980d..8a2c9f71ca 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.h +++ b/ApplicationCode/ProjectDataModel/Completions/RimFractureModel.h @@ -63,6 +63,10 @@ public: double defaultPorosity() const; double defaultPermeability() const; + double verticalStress() const; + double verticalStressGradient() const; + double stressDepth() const; + // RimWellPathCompletionsInterface overrides. RiaDefines::WellPathComponentType componentType() const override; QString componentLabel() const override; @@ -105,4 +109,7 @@ protected: caf::PdmChildField m_elasticProperties; caf::PdmField m_defaultPorosity; caf::PdmField m_defaultPermeability; + caf::PdmField m_verticalStress; + caf::PdmField m_verticalStressGradient; + caf::PdmField m_stressDepth; }; diff --git a/ApplicationCode/ProjectDataModel/RimElasticProperties.cpp b/ApplicationCode/ProjectDataModel/RimElasticProperties.cpp index 6b44251a51..bb0c23c497 100644 --- a/ApplicationCode/ProjectDataModel/RimElasticProperties.cpp +++ b/ApplicationCode/ProjectDataModel/RimElasticProperties.cpp @@ -130,6 +130,8 @@ QString RimElasticProperties::generatePropertiesTable() " Poisson's
Ratio" " K-Ic" " Proppant
Embedment" + " Biot
Coefficient" + " k0" " " " " " " ); @@ -143,6 +145,8 @@ QString RimElasticProperties::generatePropertiesTable() const std::vector& poissonsRatio = prop.second.poissonsRatio(); const std::vector& K_Ic = prop.second.K_Ic(); const std::vector& proppantEmbedment = prop.second.proppantEmbedment(); + const std::vector& biotCoefficient = prop.second.biotCoefficient(); + const std::vector& k0 = prop.second.k0(); for ( size_t i = 0; i < porosity.size(); i++ ) { @@ -155,6 +159,8 @@ QString RimElasticProperties::generatePropertiesTable() " %6" " %7" " %8" + " %9" + " %10" "" ); QString line = format.arg( fieldName ) @@ -164,7 +170,9 @@ QString RimElasticProperties::generatePropertiesTable() .arg( youngsModulus[i] ) .arg( poissonsRatio[i] ) .arg( K_Ic[i] ) - .arg( proppantEmbedment[i] ); + .arg( proppantEmbedment[i] ) + .arg( biotCoefficient[i] ) + .arg( k0[i] ); body.append( line ); } diff --git a/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.cpp b/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.cpp index 1d10ec457e..4523af5771 100644 --- a/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.cpp +++ b/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.cpp @@ -67,6 +67,8 @@ void AppEnum::setUp() addItem( RimElasticPropertiesCurve::PropertyType::POISSONS_RATIO, "POISSONS_RATIO", "Poisson's Ratio" ); addItem( RimElasticPropertiesCurve::PropertyType::K_IC, "K_IC", "K-Ic" ); addItem( RimElasticPropertiesCurve::PropertyType::PROPPANT_EMBEDMENT, "PROPPANT_EMBEDMENT", "Proppant Embedment" ); + addItem( RimElasticPropertiesCurve::PropertyType::BIOT_COEFFICIENT, "BIOT_COEFFICIENT", "Biot Coefficient" ); + addItem( RimElasticPropertiesCurve::PropertyType::K0, "K0", "k0" ); setDefault( RimElasticPropertiesCurve::PropertyType::YOUNGS_MODULUS ); } }; // namespace caf @@ -255,6 +257,16 @@ void RimElasticPropertiesCurve::performDataExtraction( bool* isUsingPseudoLength double val = rigElasticProperties.getProppantEmbedment( porosity ); values.push_back( val ); } + else if ( m_propertyType() == PropertyType::BIOT_COEFFICIENT ) + { + double val = rigElasticProperties.getBiotCoefficient( porosity ); + values.push_back( val ); + } + else if ( m_propertyType() == PropertyType::K0 ) + { + double val = rigElasticProperties.getK0( porosity ); + values.push_back( val ); + } } else { diff --git a/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.h b/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.h index 133caf77b0..336e9fe108 100644 --- a/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.h +++ b/ApplicationCode/ProjectDataModel/RimElasticPropertiesCurve.h @@ -45,7 +45,9 @@ public: YOUNGS_MODULUS, POISSONS_RATIO, K_IC, - PROPPANT_EMBEDMENT + PROPPANT_EMBEDMENT, + BIOT_COEFFICIENT, + K0 }; RimElasticPropertiesCurve(); diff --git a/ApplicationCode/ProjectDataModel/RimFractureModelPlot.cpp b/ApplicationCode/ProjectDataModel/RimFractureModelPlot.cpp index 05d445517a..4ecd7d84bc 100644 --- a/ApplicationCode/ProjectDataModel/RimFractureModelPlot.cpp +++ b/ApplicationCode/ProjectDataModel/RimFractureModelPlot.cpp @@ -18,6 +18,8 @@ #include "RimFractureModelPlot.h" #include "RiaDefines.h" +#include "RiaLogging.h" + #include "RicfCommandObject.h" #include "RimEclipseCase.h" @@ -40,6 +42,18 @@ CAF_PDM_SOURCE_INIT( RimFractureModelPlot, "FractureModelPlot" ); RimFractureModelPlot::RimFractureModelPlot() { CAF_PDM_InitScriptableObject( "Fracture Model Plot", "", "", "A fracture model plot" ); + + CAF_PDM_InitFieldNoDefault( &m_fractureModel, "FractureModel", "Fracture Model", "", "", "" ); + m_fractureModel.uiCapability()->setUiTreeChildrenHidden( true ); + m_fractureModel.uiCapability()->setUiHidden( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimFractureModelPlot::setFractureModel( RimFractureModel* fractureModel ) +{ + m_fractureModel = fractureModel; } //-------------------------------------------------------------------------------------------------- @@ -75,6 +89,30 @@ void RimFractureModelPlot::applyDataSource() this->updateConnectedEditors(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModelPlot::convertToPsiPerFeetFromBarPerMeter( double value ) +{ + return value * 4.42075; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModelPlot::convertToFeetFromMeter( double value ) +{ + return value * 3.28084; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimFractureModelPlot::convertToPsiFromBar( double value ) +{ + return value * 14.5038; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -122,11 +160,30 @@ void RimFractureModelPlot::calculateLayers( std::vector& values, + std::vector>& layerBoundaryDepths, + double depth ) +{ + for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ ) + { + if ( layerBoundaryDepths[i].first <= depth && layerBoundaryDepths[i].second >= depth ) + { + return values[i]; + } + } + + RiaLogging::error( QString( "Failed to compute value at depth: %1" ).arg( depth ) ); + return std::numeric_limits::infinity(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -180,11 +237,10 @@ std::vector RimFractureModelPlot::calculateTrueVerticalDepth() const std::vector tvdTopZone; for ( auto p : layerBoundaryDepths ) { - std::cout << "Layer boundaries: " << p.first << " - " << p.second << std::endl; - tvdTopZone.push_back( p.first ); + double depthInFeet = convertToFeetFromMeter( p.first ); + tvdTopZone.push_back( depthInFeet ); } - // TODO: convert to feet!!!! return tvdTopZone; } @@ -196,7 +252,7 @@ std::vector RimFractureModelPlot::findCurveAndComputeLayeredAverage( con RimWellLogExtractionCurve* curve = findCurveByName( curveName ); if ( !curve ) { - std::cerr << "NO " << curveName.toStdString() << " FOUND!!!" << std::endl; + RiaLogging::error( QString( "No curve named '%1' found" ).arg( curveName ) ); return std::vector(); } @@ -248,7 +304,139 @@ std::vector RimFractureModelPlot::calculateVerticalPermeability() const //-------------------------------------------------------------------------------------------------- std::vector RimFractureModelPlot::calculateStress() const { - return std::vector(); + std::vector stress; + std::vector stressGradients; + calculateStressWithGradients( stress, stressGradients ); + return stress; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimFractureModelPlot::calculateStressWithGradients( std::vector& stress, + std::vector& stressGradients ) const +{ + // Reference stress + const double verticalStressRef = m_fractureModel->verticalStress(); + const double verticalStressGradientRef = m_fractureModel->verticalStressGradient(); + const double stressDepthRef = m_fractureModel->stressDepth(); + + std::vector> layerBoundaryDepths; + std::vector> layerBoundaryIndexes; + calculateLayers( layerBoundaryDepths, layerBoundaryIndexes ); + + // Biot coefficient + RimWellLogExtractionCurve* biotCurve = findCurveByName( "Biot Coefficient" ); + if ( !biotCurve ) + { + RiaLogging::error( "Biot coefficient data not found." ); + return false; + } + std::vector biotData = biotCurve->curveData()->xValues(); + + // Biot coefficient + RimWellLogExtractionCurve* k0Curve = findCurveByName( "k0" ); + if ( !k0Curve ) + { + RiaLogging::error( "k0 data not found." ); + return false; + } + std::vector k0Data = k0Curve->curveData()->xValues(); + + // Pressure at the give time step + RimWellLogExtractionCurve* timeStepPressureCurve = findCurveByName( "PRESSURE" ); + if ( !timeStepPressureCurve ) + { + RiaLogging::error( "Pressure data for time step not found." ); + return false; + } + std::vector timeStepPressureData = timeStepPressureCurve->curveData()->xValues(); + + // Initial pressure + RimWellLogExtractionCurve* initialPressureCurve = findCurveByName( "INITIAL PRESSURE" ); + if ( !initialPressureCurve ) + { + RiaLogging::error( "Initial pressure data not found." ); + return false; + } + std::vector initialPressureData = initialPressureCurve->curveData()->xValues(); + + // Poissons ratio + RimWellLogExtractionCurve* poissonsRatioCurve = findCurveByName( "Poisson's Ratio" ); + if ( !poissonsRatioCurve ) + { + RiaLogging::error( "Poisson's ratio data not found." ); + return false; + } + std::vector poissonsRatioData = poissonsRatioCurve->curveData()->xValues(); + + std::vector stressForGradients; + std::vector pressureForGradients; + std::vector depthForGradients; + + // Calculate the stress + for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ ) + { + double depthTopOfZone = layerBoundaryDepths[i].first; + double depthBottomOfZone = layerBoundaryDepths[i].second; + + // Data from curves at the top zone depth + double k0 = computeValueAtDepth( k0Data, layerBoundaryDepths, depthTopOfZone ); + double biot = computeValueAtDepth( biotData, layerBoundaryDepths, depthTopOfZone ); + double poissonsRatio = computeValueAtDepth( poissonsRatioData, layerBoundaryDepths, depthTopOfZone ); + double initialPressure = computeValueAtDepth( initialPressureData, layerBoundaryDepths, depthTopOfZone ); + double timeStepPressure = computeValueAtDepth( timeStepPressureData, layerBoundaryDepths, depthTopOfZone ); + + // Vertical stress + // Use difference between reference depth and depth of top of zone + double depthDiff = depthTopOfZone - stressDepthRef; + double Sv = verticalStressRef + verticalStressGradientRef * depthDiff; + + double Sh_init = k0 * Sv + initialPressure * ( 1.0 - k0 ); + double pressureDiff = timeStepPressure - initialPressure; + + // Vertical stress diff assumed to be zero + double Sv_diff = 0.0; + double deltaHorizontalStress = poissonsRatio / ( 1.0 - poissonsRatio ) * ( Sv_diff - biot * pressureDiff ) + + ( biot * pressureDiff ); + + double depletionStress = Sh_init + deltaHorizontalStress; + stress.push_back( convertToPsiFromBar( depletionStress ) ); + + // Cache some results for the gradients calculation + stressForGradients.push_back( Sv ); + pressureForGradients.push_back( initialPressure ); + depthForGradients.push_back( depthTopOfZone ); + + if ( i == layerBoundaryDepths.size() - 1 ) + { + // Use the bottom of the last layer to compute gradient for last layer + double bottomInitialPressure = + computeValueAtDepth( initialPressureData, layerBoundaryDepths, depthBottomOfZone ); + double bottomDepthDiff = depthBottomOfZone - stressDepthRef; + double bottomSv = verticalStressRef + verticalStressGradientRef * bottomDepthDiff; + stressForGradients.push_back( bottomSv ); + pressureForGradients.push_back( bottomInitialPressure ); + depthForGradients.push_back( depthBottomOfZone ); + } + } + + assert( stressForGradients.size() == layerBoundaryDepths.size() + 1 ); + assert( pressureForGradients.size() == layerBoundaryDepths.size() + 1 ); + assert( depthForGradients.size() == layerBoundaryDepths.size() + 1 ); + + // Second pass to calculate the stress gradients + for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ ) + { + double diffStress = stressForGradients[i + 1] - stressForGradients[i]; + double diffPressure = pressureForGradients[i + 1] - pressureForGradients[i]; + double diffDepth = depthForGradients[i + 1] - depthForGradients[i]; + double k0 = computeValueAtDepth( k0Data, layerBoundaryDepths, depthForGradients[i] ); + double gradient = ( diffStress * k0 + diffPressure * ( 1.0 - k0 ) ) / diffDepth; + stressGradients.push_back( convertToPsiPerFeetFromBarPerMeter( gradient ) ); + } + + return true; } //-------------------------------------------------------------------------------------------------- @@ -256,7 +444,10 @@ std::vector RimFractureModelPlot::calculateStress() const //-------------------------------------------------------------------------------------------------- std::vector RimFractureModelPlot::calculateStressGradient() const { - return std::vector(); + std::vector stress; + std::vector stressGradients; + calculateStressWithGradients( stress, stressGradients ); + return stressGradients; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimFractureModelPlot.h b/ApplicationCode/ProjectDataModel/RimFractureModelPlot.h index 5dfe50d453..7daea0b9f3 100644 --- a/ApplicationCode/ProjectDataModel/RimFractureModelPlot.h +++ b/ApplicationCode/ProjectDataModel/RimFractureModelPlot.h @@ -25,6 +25,7 @@ #include class RimWellLogExtractionCurve; +class RimFractureModel; class RimFractureModelPlot : public RimDepthTrackPlot { @@ -33,6 +34,8 @@ class RimFractureModelPlot : public RimDepthTrackPlot public: RimFractureModelPlot(); + void setFractureModel( RimFractureModel* fractureModel ); + void getPorosityValues( std::vector& values ) const; std::vector calculateTrueVerticalDepth() const; @@ -54,9 +57,17 @@ protected: void calculateLayers( std::vector>& layerBoundaryDepths, std::vector>& layerBoundaryIndexes ) const; RimWellLogExtractionCurve* findCurveByName( const QString& curveName ) const; - static void computeAverageByLayer( const std::vector>& layerBoundaryIndexes, - const std::vector& inputVector, - std::vector& result ); + bool calculateStressWithGradients( std::vector& stress, std::vector& stressGradients ) const; + + static double computeValueAtDepth( const std::vector& values, + std::vector>& layerBoundaryDepths, + double depth ); + static void computeAverageByLayer( const std::vector>& layerBoundaryIndexes, + const std::vector& inputVector, + std::vector& result ); + static double convertToPsiPerFeetFromBarPerMeter( double value ); + static double convertToFeetFromMeter( double value ); + static double convertToPsiFromBar( double value ); void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; @@ -64,4 +75,6 @@ protected: private: void applyDataSource(); + + caf::PdmPtrField m_fractureModel; }; diff --git a/ApplicationCode/ReservoirDataModel/RigElasticProperties.cpp b/ApplicationCode/ReservoirDataModel/RigElasticProperties.cpp index 82a5c45d05..fe8116ea48 100644 --- a/ApplicationCode/ReservoirDataModel/RigElasticProperties.cpp +++ b/ApplicationCode/ReservoirDataModel/RigElasticProperties.cpp @@ -94,6 +94,22 @@ const std::vector& RigElasticProperties::proppantEmbedment() const return m_proppantEmbedment; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RigElasticProperties::biotCoefficient() const +{ + return m_biotCoefficient; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RigElasticProperties::k0() const +{ + return m_k0; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -101,13 +117,17 @@ void RigElasticProperties::appendValues( double porosity, double youngsModulus, double poissonsRatio, double K_Ic, - double proppantEmbedment ) + double proppantEmbedment, + double biotCoefficient, + double k0 ) { m_porosity.push_back( porosity ); m_youngsModulus.push_back( youngsModulus ); m_poissonsRatio.push_back( poissonsRatio ); m_K_Ic.push_back( K_Ic ); m_proppantEmbedment.push_back( proppantEmbedment ); + m_biotCoefficient.push_back( biotCoefficient ); + m_k0.push_back( k0 ); } //-------------------------------------------------------------------------------------------------- @@ -141,3 +161,19 @@ double RigElasticProperties::getProppantEmbedment( double porosity ) const { return RiaInterpolationTools::linear( m_porosity, m_proppantEmbedment, porosity ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigElasticProperties::getBiotCoefficient( double porosity ) const +{ + return RiaInterpolationTools::linear( m_porosity, m_biotCoefficient, porosity ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigElasticProperties::getK0( double porosity ) const +{ + return RiaInterpolationTools::linear( m_porosity, m_k0, porosity ); +} diff --git a/ApplicationCode/ReservoirDataModel/RigElasticProperties.h b/ApplicationCode/ReservoirDataModel/RigElasticProperties.h index 5a61cf7d57..c731caeaf1 100644 --- a/ApplicationCode/ReservoirDataModel/RigElasticProperties.h +++ b/ApplicationCode/ReservoirDataModel/RigElasticProperties.h @@ -33,17 +33,27 @@ public: const QString& formationName() const; const QString& faciesName() const; - void appendValues( double porosity, double youngsModulus, double poissonsRatio, double m_K_Ic, double proppantEmbedment ); + void appendValues( double porosity, + double youngsModulus, + double poissonsRatio, + double m_K_Ic, + double proppantEmbedment, + double biotCoefficient, + double k0 ); double getYoungsModulus( double porosity ) const; double getPoissonsRatio( double porosity ) const; double getK_Ic( double porosity ) const; double getProppantEmbedment( double porosity ) const; + double getBiotCoefficient( double porosity ) const; + double getK0( double porosity ) const; const std::vector& porosity() const; const std::vector& youngsModulus() const; const std::vector& poissonsRatio() const; const std::vector& K_Ic() const; const std::vector& proppantEmbedment() const; + const std::vector& biotCoefficient() const; + const std::vector& k0() const; private: QString m_fieldName; @@ -55,4 +65,6 @@ private: std::vector m_poissonsRatio; std::vector m_K_Ic; std::vector m_proppantEmbedment; + std::vector m_biotCoefficient; + std::vector m_k0; };