mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Merge pull request #6079 from OPM/layers-fracture-model-plot-6036
Layers fracture model plot 6036
This commit is contained in:
commit
034f75f64e
@ -45,6 +45,9 @@ public:
|
||||
static double mmToMeter( double mm ) { return mm / 1000.0; }
|
||||
static double meterToMm( double meter ) { return 1000.0 * meter; }
|
||||
|
||||
static double barToPsi( double bar ) { return bar * 14.5038; }
|
||||
static double barPerMeterToPsiPerFeet( double barPerMeter ) { return barPerMeter * 4.42075; }
|
||||
|
||||
static double darcysConstant( UnitSystem unitSystem );
|
||||
|
||||
static RiaDefines::DepthUnitType depthUnit( UnitSystem unit );
|
||||
|
@ -92,6 +92,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicDeleteTemporaryLgrsFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextUi.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPlotFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureModelPlotToFileFeature.h
|
||||
)
|
||||
|
||||
|
||||
@ -182,6 +183,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicDeleteTemporaryLgrsFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportContourMapToTextUi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewMultiPlotFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicExportFractureModelPlotToFileFeature.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"
|
||||
@ -68,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 );
|
||||
@ -79,29 +81,42 @@ 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 );
|
||||
|
||||
std::vector<std::tuple<QString, RiaDefines::ResultCatType, RimFractureModelCurve::MissingValueStrategy>> 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::map<QString, PlotDefVector> 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 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +127,11 @@ 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,
|
||||
RimElasticPropertiesCurve::PropertyType::FLUID_LOSS_COEFFICIENT,
|
||||
RimElasticPropertiesCurve::PropertyType::SPURT_LOSS};
|
||||
|
||||
for ( auto result : results )
|
||||
{
|
||||
@ -252,16 +271,68 @@ void RicNewFractureModelPlotFeature::createFaciesTrack( RimFractureModelPlot* pl
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimFractureModelCurve*
|
||||
RicNewFractureModelPlotFeature::createParametersTrack( RimFractureModelPlot* plot,
|
||||
RimFractureModel* fractureModel,
|
||||
RimEclipseCase* eclipseCase,
|
||||
int timeStep,
|
||||
const QString& resultVariable,
|
||||
RiaDefines::ResultCatType resultCategoryType,
|
||||
RimFractureModelCurve::MissingValueStrategy missingValueStrategy )
|
||||
void RicNewFractureModelPlotFeature::createLayersTrack( RimFractureModelPlot* plot,
|
||||
RimFractureModel* fractureModel,
|
||||
RimEclipseCase* eclipseCase )
|
||||
{
|
||||
RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, resultVariable, plot );
|
||||
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<RiuQwtPlotCurve::LineStyleEnum> 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();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewFractureModelPlotFeature::createParametersTrack( RimFractureModelPlot* plot,
|
||||
RimFractureModel* fractureModel,
|
||||
RimEclipseCase* eclipseCase,
|
||||
int timeStep,
|
||||
const QString& trackTitle,
|
||||
const PlotDefVector& curveConfigurations )
|
||||
{
|
||||
RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, trackTitle, plot );
|
||||
plotTrack->setFormationWellPath( fractureModel->thicknessDirectionWellPath() );
|
||||
plotTrack->setColSpan( RimPlot::TWO );
|
||||
plotTrack->setVisibleXRange( 0.0, 2.0 );
|
||||
@ -277,32 +348,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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -30,6 +30,9 @@ class RimFractureModelPlot;
|
||||
class RimFractureModelPlotCollection;
|
||||
class RimFractureModel;
|
||||
|
||||
typedef std::tuple<QString, RiaDefines::ResultCatType, RimFractureModelCurve::MissingValueStrategy, bool> PlotDef;
|
||||
typedef std::vector<PlotDef> PlotDefVector;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
@ -50,14 +53,16 @@ private:
|
||||
static void
|
||||
createFormationTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase );
|
||||
static void
|
||||
createFaciesTrack( 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 );
|
||||
createFaciesTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase );
|
||||
static void
|
||||
createLayersTrack( RimFractureModelPlot* plot, RimFractureModel* fractureModel, RimEclipseCase* eclipseCase );
|
||||
|
||||
static void createParametersTrack( RimFractureModelPlot* plot,
|
||||
RimFractureModel* fractureModel,
|
||||
RimEclipseCase* eclipseCase,
|
||||
int timeStep,
|
||||
const QString& trackTitle,
|
||||
const PlotDefVector& curveConfiguration );
|
||||
|
||||
static void createElasticPropertiesTrack( RimFractureModelPlot* plot,
|
||||
RimFractureModel* fractureModel,
|
||||
|
@ -62,7 +62,6 @@ void RicElasticPropertiesImportTools::importElasticPropertiesFromFile( const QSt
|
||||
}
|
||||
|
||||
RimElasticProperties* rimElasticProperties = new RimElasticProperties;
|
||||
// rimElasticProperties->setFilePath();
|
||||
for ( FaciesKey key : faciesKeys )
|
||||
{
|
||||
std::vector<RifElasticProperties> matchingFacies;
|
||||
@ -93,7 +92,11 @@ void RicElasticPropertiesImportTools::importElasticPropertiesFromFile( const QSt
|
||||
item.youngsModulus,
|
||||
item.poissonsRatio,
|
||||
item.K_Ic,
|
||||
item.proppantEmbedment );
|
||||
item.proppantEmbedment,
|
||||
item.biotCoefficient,
|
||||
item.k0,
|
||||
item.fluidLossCoefficient,
|
||||
item.spurtLoss );
|
||||
}
|
||||
|
||||
rimElasticProperties->setPropertiesForFacies( key, rigElasticProperties );
|
||||
|
@ -0,0 +1,77 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RicExportFractureModelPlotToFileFeature.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
|
||||
#include "RimFractureModelPlot.h"
|
||||
|
||||
#include "RifFractureModelPlotExporter.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
#include "cafUtils.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicExportFractureModelPlotToFileFeature, "RicExportFractureModelPlotToFileFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicExportFractureModelPlotToFileFeature::isCommandEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicExportFractureModelPlotToFileFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
RimFractureModelPlot* fractureModelPlot =
|
||||
caf::SelectionManager::instance()->selectedItemOfType<RimFractureModelPlot>();
|
||||
if ( !fractureModelPlot ) return;
|
||||
|
||||
RiaApplication* app = RiaApplication::instance();
|
||||
QString defaultDir = app->lastUsedDialogDirectory( "FRACTURE_MODEL_PLOT" );
|
||||
|
||||
QString fileNameCandidate = "Geological";
|
||||
QString defaultFileName = defaultDir + "/" + caf::Utils::makeValidFileBasename( fileNameCandidate ) + ".frk";
|
||||
QString fileName = QFileDialog::getSaveFileName( nullptr,
|
||||
"Select File for Fracture Model Plot Export",
|
||||
defaultFileName,
|
||||
"Geologic Model File(*.frk);;All files(*.*)" );
|
||||
|
||||
if ( fileName.isEmpty() ) return;
|
||||
|
||||
RifFractureModelPlotExporter::writeToFile( fractureModelPlot, fileName );
|
||||
|
||||
// Remember the path to next time
|
||||
app->setLastUsedDialogDirectory( "FRACTURE_MODEL_PLOT", QFileInfo( fileName ).absolutePath() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicExportFractureModelPlotToFileFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "Export Fracture Model Plot to File" );
|
||||
actionToSetup->setIcon( QIcon( ":/Save.png" ) );
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicExportFractureModelPlotToFileFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
// Overrides
|
||||
bool isCommandEnabled() override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
@ -54,6 +54,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRoffReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifColorLegendData.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifElasticPropertiesReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFractureModelPlotExporter.h
|
||||
|
||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
|
||||
@ -112,6 +113,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifSurfaceReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRoffReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifColorLegendData.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifElasticPropertiesReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFractureModelPlotExporter.cpp
|
||||
|
||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
||||
|
@ -79,7 +79,7 @@ RifElasticProperties
|
||||
{
|
||||
QStringList tokens = tokenize( line, "," );
|
||||
|
||||
if ( tokens.size() != 8 )
|
||||
if ( tokens.size() != 12 )
|
||||
{
|
||||
throw FileParseException( QString( "Incomplete data on line %1: %2" ).arg( lineNumber ).arg( filePath ) );
|
||||
}
|
||||
@ -93,18 +93,26 @@ RifElasticProperties
|
||||
<< "Young's Modulus"
|
||||
<< "Poisson's Ratio"
|
||||
<< "K-Ic"
|
||||
<< "Proppant Embedment";
|
||||
<< "Proppant Embedment"
|
||||
<< "Biot Coefficient"
|
||||
<< "k0"
|
||||
<< "Fluid Loss Coefficient"
|
||||
<< "Spurt Loss";
|
||||
verifyNonEmptyTokens( tokens, nameOfNonEmptyTokens, lineNumber, filePath );
|
||||
|
||||
RifElasticProperties elasticProperties;
|
||||
elasticProperties.fieldName = tokens[0];
|
||||
elasticProperties.formationName = tokens[1];
|
||||
elasticProperties.faciesName = tokens[2];
|
||||
elasticProperties.porosity = parseDouble( tokens[3], "Porosity", lineNumber, filePath );
|
||||
elasticProperties.youngsModulus = parseDouble( tokens[4], "Young's Modulus", lineNumber, filePath );
|
||||
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.fieldName = tokens[0];
|
||||
elasticProperties.formationName = tokens[1];
|
||||
elasticProperties.faciesName = tokens[2];
|
||||
elasticProperties.porosity = parseDouble( tokens[3], "Porosity", lineNumber, filePath );
|
||||
elasticProperties.youngsModulus = parseDouble( tokens[4], "Young's Modulus", lineNumber, filePath );
|
||||
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 );
|
||||
elasticProperties.fluidLossCoefficient = parseDouble( tokens[10], "Fluid Loss Coefficient", lineNumber, filePath );
|
||||
elasticProperties.spurtLoss = parseDouble( tokens[11], "Spurt Loss", lineNumber, filePath );
|
||||
|
||||
return elasticProperties;
|
||||
}
|
||||
|
@ -32,6 +32,10 @@ struct RifElasticProperties
|
||||
double poissonsRatio;
|
||||
double K_Ic;
|
||||
double proppantEmbedment;
|
||||
double biotCoefficient;
|
||||
double k0;
|
||||
double fluidLossCoefficient;
|
||||
double spurtLoss;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
|
127
ApplicationCode/FileInterface/RifFractureModelPlotExporter.cpp
Normal file
127
ApplicationCode/FileInterface/RifFractureModelPlotExporter.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifFractureModelPlotExporter.h"
|
||||
|
||||
#include "RimFractureModelPlot.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, const QString& filepath )
|
||||
{
|
||||
std::vector<QString> labels;
|
||||
// TVD depth of top of zone (ft)
|
||||
labels.push_back( "dpthlyr" );
|
||||
|
||||
// Stress at top of zone (psi)
|
||||
labels.push_back( "strs" );
|
||||
|
||||
// Stress gradient (psi/ft)
|
||||
labels.push_back( "strsg" );
|
||||
|
||||
// Young's modulus (MMpsi)
|
||||
labels.push_back( "elyr" );
|
||||
|
||||
// Poisson's Ratio
|
||||
labels.push_back( "poissonr" );
|
||||
|
||||
// K-Ic (psi*sqrt(in)
|
||||
labels.push_back( "tuflyr" );
|
||||
|
||||
// Fluid Loss Coefficient
|
||||
labels.push_back( "clyrc" );
|
||||
|
||||
// Spurt loss (gal/100f^2)
|
||||
labels.push_back( "clyrs" );
|
||||
|
||||
// Proppand Embedmeent (lb/ft^2)
|
||||
labels.push_back( "pembed" );
|
||||
|
||||
bool useDetailedLoss = false;
|
||||
if ( useDetailedLoss )
|
||||
{
|
||||
// B2 Detailed Loss
|
||||
// Reservoir Pressure (psi)
|
||||
labels.push_back( "zoneResPres" );
|
||||
|
||||
// Porosity (fraction)
|
||||
labels.push_back( "zonePorosity" );
|
||||
|
||||
// Horizontal Perm (md)
|
||||
labels.push_back( "zoneHorizPerm" );
|
||||
|
||||
// Vertical Perm (md)
|
||||
labels.push_back( "zoneVertPerm" );
|
||||
}
|
||||
|
||||
std::map<QString, std::vector<double>> values;
|
||||
values["dpthlyr"] = plot->calculateTrueVerticalDepth();
|
||||
values["strs"] = plot->calculateStress();
|
||||
values["strsg"] = plot->calculateStressGradient();
|
||||
values["elyr"] = plot->calculateYoungsModulus();
|
||||
values["poissonr"] = plot->calculatePoissonsRatio();
|
||||
values["tuflyr"] = plot->calculateKIc();
|
||||
values["clyrc"] = plot->calculateFluidLossCoefficient();
|
||||
values["clyrs"] = plot->calculateSpurtLoss();
|
||||
values["pembed"] = plot->calculateProppandEmbedment();
|
||||
values["zoneResPres"] = plot->calculateReservoirPressure();
|
||||
values["zonePorosity"] = plot->calculatePorosity();
|
||||
values["zoneHorizPerm"] = plot->calculateHorizontalPermeability();
|
||||
values["zoneVertPerm"] = plot->calculateVerticalPermeability();
|
||||
|
||||
QFile data( filepath );
|
||||
if ( !data.open( QFile::WriteOnly | QFile::Truncate ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream( &data );
|
||||
|
||||
for ( QString label : labels )
|
||||
{
|
||||
appendToStream( stream, label, values[label] );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RifFractureModelPlotExporter::appendToStream( QTextStream& stream, const QString& label, const std::vector<double>& values )
|
||||
{
|
||||
stream << "<cNamedSet>"
|
||||
<< "\n"
|
||||
<< label << "\n"
|
||||
<< "<dimCount>"
|
||||
<< "\n"
|
||||
<< 1 << "\n"
|
||||
<< "<sizes>"
|
||||
<< "\n"
|
||||
<< values.size() << "\n"
|
||||
<< "<data>"
|
||||
<< "\n";
|
||||
for ( auto val : values )
|
||||
{
|
||||
stream << val << "\n";
|
||||
}
|
||||
|
||||
stream << "</cNamedSet>"
|
||||
<< "\n";
|
||||
}
|
37
ApplicationCode/FileInterface/RifFractureModelPlotExporter.h
Normal file
37
ApplicationCode/FileInterface/RifFractureModelPlotExporter.h
Normal file
@ -0,0 +1,37 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimFractureModelPlot;
|
||||
class QString;
|
||||
class QTextStream;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//==================================================================================================
|
||||
class RifFractureModelPlotExporter
|
||||
{
|
||||
public:
|
||||
static bool writeToFile( RimFractureModelPlot* plot, const QString& filepath );
|
||||
|
||||
private:
|
||||
static void appendToStream( QTextStream& stream, const QString& label, const std::vector<double>& values );
|
||||
};
|
@ -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
|
||||
|
@ -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 );
|
||||
@ -512,7 +519,7 @@ double RimFractureModel::getDefaultForMissingValue( const QString& keyword ) con
|
||||
{
|
||||
return defaultPorosity();
|
||||
}
|
||||
else if ( keyword == QString( "PERMX" ) )
|
||||
else if ( keyword == QString( "PERMX" ) || keyword == QString( "PERMZ" ) )
|
||||
{
|
||||
return defaultPermeability();
|
||||
}
|
||||
@ -522,3 +529,27 @@ double RimFractureModel::getDefaultForMissingValue( const QString& keyword ) con
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFractureModel::verticalStress() const
|
||||
{
|
||||
return m_verticalStress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFractureModel::verticalStressGradient() const
|
||||
{
|
||||
return m_verticalStressGradient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFractureModel::stressDepth() const
|
||||
{
|
||||
return m_stressDepth;
|
||||
}
|
||||
|
@ -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<RimElasticProperties*> m_elasticProperties;
|
||||
caf::PdmField<double> m_defaultPorosity;
|
||||
caf::PdmField<double> m_defaultPermeability;
|
||||
caf::PdmField<double> m_verticalStress;
|
||||
caf::PdmField<double> m_verticalStressGradient;
|
||||
caf::PdmField<double> m_stressDepth;
|
||||
};
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "RimFormationNames.h"
|
||||
#include "RimFormationNamesCollection.h"
|
||||
#include "RimFractureModel.h"
|
||||
#include "RimFractureModelPlot.h"
|
||||
#include "RimFractureTemplate.h"
|
||||
#include "RimFractureTemplateCollection.h"
|
||||
#include "RimGeoMechCase.h"
|
||||
@ -433,6 +434,10 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicImportFaciesFeature";
|
||||
menuBuilder << "RicImportElasticPropertiesFeature";
|
||||
}
|
||||
else if ( dynamic_cast<RimFractureModelPlot*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder << "RicExportFractureModelPlotToFileFeature";
|
||||
}
|
||||
else if ( dynamic_cast<Rim3dWellLogCurveCollection*>( firstUiItem ) ||
|
||||
dynamic_cast<Rim3dWellLogExtractionCurve*>( firstUiItem ) ||
|
||||
dynamic_cast<Rim3dWellLogFileCurve*>( firstUiItem ) ||
|
||||
|
@ -130,6 +130,10 @@ QString RimElasticProperties::generatePropertiesTable()
|
||||
" <th>Poisson's<br>Ratio</th>"
|
||||
" <th>K-Ic</th>"
|
||||
" <th>Proppant<br>Embedment</th>"
|
||||
" <th>Biot<br>Coefficient</th>"
|
||||
" <th>k0</th>"
|
||||
" <th>Fluid Loss<br>Coefficient</th>"
|
||||
" <th>Spurt Loss</th>"
|
||||
" </tr>"
|
||||
" </thead>"
|
||||
" <tbody>" );
|
||||
@ -137,12 +141,16 @@ QString RimElasticProperties::generatePropertiesTable()
|
||||
QString body;
|
||||
for ( auto prop : m_properties )
|
||||
{
|
||||
const QString& fieldName = prop.second.fieldName();
|
||||
const std::vector<double>& porosity = prop.second.porosity();
|
||||
const std::vector<double>& youngsModulus = prop.second.youngsModulus();
|
||||
const std::vector<double>& poissonsRatio = prop.second.poissonsRatio();
|
||||
const std::vector<double>& K_Ic = prop.second.K_Ic();
|
||||
const std::vector<double>& proppantEmbedment = prop.second.proppantEmbedment();
|
||||
const QString& fieldName = prop.second.fieldName();
|
||||
const std::vector<double>& porosity = prop.second.porosity();
|
||||
const std::vector<double>& youngsModulus = prop.second.youngsModulus();
|
||||
const std::vector<double>& poissonsRatio = prop.second.poissonsRatio();
|
||||
const std::vector<double>& K_Ic = prop.second.K_Ic();
|
||||
const std::vector<double>& proppantEmbedment = prop.second.proppantEmbedment();
|
||||
const std::vector<double>& biotCoefficient = prop.second.biotCoefficient();
|
||||
const std::vector<double>& k0 = prop.second.k0();
|
||||
const std::vector<double>& fluidLossCoefficient = prop.second.fluidLossCoefficient();
|
||||
const std::vector<double>& spurtLoss = prop.second.spurtLoss();
|
||||
|
||||
for ( size_t i = 0; i < porosity.size(); i++ )
|
||||
{
|
||||
@ -155,6 +163,10 @@ QString RimElasticProperties::generatePropertiesTable()
|
||||
" <td align=right>%6</td>"
|
||||
" <td align=right>%7</td>"
|
||||
" <td align=right>%8</td>"
|
||||
" <td align=right>%9</td>"
|
||||
" <td align=right>%10</td>"
|
||||
" <td align=right>%11</td>"
|
||||
" <td align=right>%12</td>"
|
||||
"</tr>" );
|
||||
|
||||
QString line = format.arg( fieldName )
|
||||
@ -164,7 +176,11 @@ 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] )
|
||||
.arg( fluidLossCoefficient[i] )
|
||||
.arg( spurtLoss[i] );
|
||||
|
||||
body.append( line );
|
||||
}
|
||||
|
@ -67,6 +67,12 @@ void AppEnum<RimElasticPropertiesCurve::PropertyType>::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" );
|
||||
addItem( RimElasticPropertiesCurve::PropertyType::FLUID_LOSS_COEFFICIENT,
|
||||
"FLUID_LOSS_COEFFICIENT",
|
||||
"Fluid Loss Coefficient" );
|
||||
addItem( RimElasticPropertiesCurve::PropertyType::SPURT_LOSS, "SPURT_LOSS", "Spurt Loss" );
|
||||
setDefault( RimElasticPropertiesCurve::PropertyType::YOUNGS_MODULUS );
|
||||
}
|
||||
}; // namespace caf
|
||||
@ -255,6 +261,26 @@ 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 if ( m_propertyType() == PropertyType::FLUID_LOSS_COEFFICIENT )
|
||||
{
|
||||
double val = rigElasticProperties.getFluidLossCoefficient( porosity );
|
||||
values.push_back( val );
|
||||
}
|
||||
else if ( m_propertyType() == PropertyType::SPURT_LOSS )
|
||||
{
|
||||
double val = rigElasticProperties.getSpurtLoss( porosity );
|
||||
values.push_back( val );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -45,7 +45,11 @@ public:
|
||||
YOUNGS_MODULUS,
|
||||
POISSONS_RATIO,
|
||||
K_IC,
|
||||
PROPPANT_EMBEDMENT
|
||||
PROPPANT_EMBEDMENT,
|
||||
BIOT_COEFFICIENT,
|
||||
K0,
|
||||
FLUID_LOSS_COEFFICIENT,
|
||||
SPURT_LOSS
|
||||
};
|
||||
|
||||
RimElasticPropertiesCurve();
|
||||
|
@ -18,11 +18,14 @@
|
||||
#include "RimFractureModelPlot.h"
|
||||
|
||||
#include "RiaDefines.h"
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "RicfCommandObject.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimFractureModel.h"
|
||||
#include "RimFractureModelCurve.h"
|
||||
#include "RimLayerCurve.h"
|
||||
|
||||
#include "RigWellLogCurveData.h"
|
||||
|
||||
@ -39,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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -90,3 +105,378 @@ void RimFractureModelPlot::getPorosityValues( std::vector<double>& values ) cons
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFractureModelPlot::calculateLayers( std::vector<std::pair<double, double>>& layerBoundaryDepths,
|
||||
std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes ) const
|
||||
{
|
||||
std::vector<RimLayerCurve*> curves;
|
||||
descendantsIncludingThisOfType( curves );
|
||||
|
||||
if ( curves.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Expect to have only one of these
|
||||
RimLayerCurve* layerCurve = curves[0];
|
||||
|
||||
const RigWellLogCurveData* curveData = layerCurve->curveData();
|
||||
|
||||
// Find
|
||||
std::vector<double> depths = curveData->depths( RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH );
|
||||
std::vector<double> layerValues = curveData->xValues();
|
||||
|
||||
size_t startIndex = 0;
|
||||
for ( size_t i = 0; i < depths.size(); i++ )
|
||||
{
|
||||
if ( startIndex != i && ( layerValues[startIndex] != layerValues[i] || i == depths.size() - 1 ) )
|
||||
{
|
||||
layerBoundaryDepths.push_back( std::make_pair( depths[startIndex], depths[i] ) );
|
||||
layerBoundaryIndexes.push_back( std::make_pair( startIndex, i ) );
|
||||
startIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimFractureModelPlot::computeValueAtDepth( const std::vector<double>& values,
|
||||
std::vector<std::pair<double, double>>& 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<double>::infinity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimFractureModelPlot::computeAverageByLayer( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result )
|
||||
{
|
||||
for ( auto boundaryIndex : layerBoundaryIndexes )
|
||||
{
|
||||
double sum = 0.0;
|
||||
int nValues = 0;
|
||||
for ( size_t i = boundaryIndex.first; i < boundaryIndex.second; i++ )
|
||||
{
|
||||
sum += inputVector[i];
|
||||
nValues++;
|
||||
}
|
||||
result.push_back( sum / nValues );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellLogExtractionCurve* RimFractureModelPlot::findCurveByName( const QString& curveName ) const
|
||||
{
|
||||
std::vector<RimWellLogExtractionCurve*> curves;
|
||||
descendantsIncludingThisOfType( curves );
|
||||
|
||||
for ( auto curve : curves )
|
||||
{
|
||||
// TODO: This will not work if the user has changed the name of the curve: do something smarter.
|
||||
if ( curve->curveName() == curveName )
|
||||
{
|
||||
return curve;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateTrueVerticalDepth() const
|
||||
{
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
std::vector<double> tvdTopZone;
|
||||
for ( auto p : layerBoundaryDepths )
|
||||
{
|
||||
double depthInFeet = RiaEclipseUnitTools::meterToFeet( p.first );
|
||||
tvdTopZone.push_back( depthInFeet );
|
||||
}
|
||||
|
||||
return tvdTopZone;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::findCurveAndComputeLayeredAverage( const QString& curveName ) const
|
||||
{
|
||||
RimWellLogExtractionCurve* curve = findCurveByName( curveName );
|
||||
if ( !curve )
|
||||
{
|
||||
RiaLogging::error( QString( "No curve named '%1' found" ).arg( curveName ) );
|
||||
return std::vector<double>();
|
||||
}
|
||||
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
const RigWellLogCurveData* curveData = curve->curveData();
|
||||
std::vector<double> values = curveData->xValues();
|
||||
std::vector<double> result;
|
||||
computeAverageByLayer( layerBoundaryIndexes, values, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculatePorosity() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "PORO" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateReservoirPressure() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "PRESSURE" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateHorizontalPermeability() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "PERMX" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateVerticalPermeability() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "PERMZ" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateStress() const
|
||||
{
|
||||
std::vector<double> stress;
|
||||
std::vector<double> stressGradients;
|
||||
calculateStressWithGradients( stress, stressGradients );
|
||||
return stress;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimFractureModelPlot::calculateStressWithGradients( std::vector<double>& stress,
|
||||
std::vector<double>& stressGradients ) const
|
||||
{
|
||||
// Reference stress
|
||||
const double verticalStressRef = m_fractureModel->verticalStress();
|
||||
const double verticalStressGradientRef = m_fractureModel->verticalStressGradient();
|
||||
const double stressDepthRef = m_fractureModel->stressDepth();
|
||||
|
||||
std::vector<std::pair<double, double>> layerBoundaryDepths;
|
||||
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
|
||||
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
|
||||
|
||||
// Biot coefficient
|
||||
RimWellLogExtractionCurve* biotCurve = findCurveByName( "Biot Coefficient" );
|
||||
if ( !biotCurve )
|
||||
{
|
||||
RiaLogging::error( "Biot coefficient data not found." );
|
||||
return false;
|
||||
}
|
||||
std::vector<double> biotData = biotCurve->curveData()->xValues();
|
||||
|
||||
// Biot coefficient
|
||||
RimWellLogExtractionCurve* k0Curve = findCurveByName( "k0" );
|
||||
if ( !k0Curve )
|
||||
{
|
||||
RiaLogging::error( "k0 data not found." );
|
||||
return false;
|
||||
}
|
||||
std::vector<double> 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<double> timeStepPressureData = timeStepPressureCurve->curveData()->xValues();
|
||||
|
||||
// Initial pressure
|
||||
RimWellLogExtractionCurve* initialPressureCurve = findCurveByName( "INITIAL PRESSURE" );
|
||||
if ( !initialPressureCurve )
|
||||
{
|
||||
RiaLogging::error( "Initial pressure data not found." );
|
||||
return false;
|
||||
}
|
||||
std::vector<double> 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<double> poissonsRatioData = poissonsRatioCurve->curveData()->xValues();
|
||||
|
||||
std::vector<double> stressForGradients;
|
||||
std::vector<double> pressureForGradients;
|
||||
std::vector<double> 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( RiaEclipseUnitTools::barToPsi( 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( RiaEclipseUnitTools::barPerMeterToPsiPerFeet( gradient ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateStressGradient() const
|
||||
{
|
||||
std::vector<double> stress;
|
||||
std::vector<double> stressGradients;
|
||||
calculateStressWithGradients( stress, stressGradients );
|
||||
return stressGradients;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateYoungsModulus() const
|
||||
{
|
||||
std::vector<double> valuesGPa = findCurveAndComputeLayeredAverage( "Young's Modulus" );
|
||||
std::vector<double> valuesMMpsi;
|
||||
for ( auto value : valuesGPa )
|
||||
{
|
||||
valuesMMpsi.push_back( value * 0.000145037737 );
|
||||
}
|
||||
|
||||
return valuesMMpsi;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculatePoissonsRatio() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "Poisson's Ratio" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateKIc() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "K-Ic" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateFluidLossCoefficient() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "Fluid Loss Coefficient" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateSpurtLoss() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "Spurt Loss" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimFractureModelPlot::calculateProppandEmbedment() const
|
||||
{
|
||||
return findCurveAndComputeLayeredAverage( "Proppant Embedment" );
|
||||
}
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimWellLogExtractionCurve;
|
||||
class RimFractureModel;
|
||||
|
||||
class RimFractureModelPlot : public RimDepthTrackPlot
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
@ -29,13 +34,44 @@ class RimFractureModelPlot : public RimDepthTrackPlot
|
||||
public:
|
||||
RimFractureModelPlot();
|
||||
|
||||
void setFractureModel( RimFractureModel* fractureModel );
|
||||
|
||||
void getPorosityValues( std::vector<double>& values ) const;
|
||||
|
||||
std::vector<double> calculateTrueVerticalDepth() const;
|
||||
std::vector<double> calculatePorosity() const;
|
||||
std::vector<double> calculateVerticalPermeability() const;
|
||||
std::vector<double> calculateHorizontalPermeability() const;
|
||||
std::vector<double> calculateReservoirPressure() const;
|
||||
std::vector<double> calculateStress() const;
|
||||
std::vector<double> calculateStressGradient() const;
|
||||
std::vector<double> calculateYoungsModulus() const;
|
||||
std::vector<double> calculatePoissonsRatio() const;
|
||||
std::vector<double> calculateKIc() const;
|
||||
std::vector<double> calculateFluidLossCoefficient() const;
|
||||
std::vector<double> calculateSpurtLoss() const;
|
||||
std::vector<double> calculateProppandEmbedment() const;
|
||||
|
||||
protected:
|
||||
std::vector<double> findCurveAndComputeLayeredAverage( const QString& curveName ) const;
|
||||
void calculateLayers( std::vector<std::pair<double, double>>& layerBoundaryDepths,
|
||||
std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes ) const;
|
||||
RimWellLogExtractionCurve* findCurveByName( const QString& curveName ) const;
|
||||
bool calculateStressWithGradients( std::vector<double>& stress, std::vector<double>& stressGradients ) const;
|
||||
|
||||
static double computeValueAtDepth( const std::vector<double>& values,
|
||||
std::vector<std::pair<double, double>>& layerBoundaryDepths,
|
||||
double depth );
|
||||
static void computeAverageByLayer( const std::vector<std::pair<size_t, size_t>>& layerBoundaryIndexes,
|
||||
const std::vector<double>& inputVector,
|
||||
std::vector<double>& result );
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
void onLoadDataAndUpdate() override;
|
||||
|
||||
private:
|
||||
void applyDataSource();
|
||||
|
||||
caf::PdmPtrField<RimFractureModel*> m_fractureModel;
|
||||
};
|
||||
|
276
ApplicationCode/ProjectDataModel/RimLayerCurve.cpp
Normal file
276
ApplicationCode/ProjectDataModel/RimLayerCurve.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// 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 <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
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<double> values;
|
||||
std::vector<double> measuredDepthValues;
|
||||
std::vector<double> tvDepthValues;
|
||||
double rkbDiff = 0.0;
|
||||
|
||||
RiaDefines::DepthUnitType depthUnit = RiaDefines::DepthUnitType::UNIT_METER;
|
||||
QString xUnits = RiaWellLogUnitTools<double>::noUnitString();
|
||||
|
||||
*isUsingPseudoLength = false;
|
||||
|
||||
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( 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<RigResultAccessor> 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<std::pair<double, double>> yValues;
|
||||
std::vector<QString> formationNamesVector = RimWellLogTrack::formationNamesVector( eclipseCase );
|
||||
|
||||
std::vector<QString> 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<RigResultAccessor> faciesResultAccessor =
|
||||
RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(),
|
||||
0,
|
||||
m_timeStep,
|
||||
m_eclipseResultDefinition );
|
||||
|
||||
if ( !faciesResultAccessor.notNull() )
|
||||
{
|
||||
RiaLogging::error( QString( "No facies result found." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<double> 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<int>( value ) ) return item->categoryName();
|
||||
// }
|
||||
|
||||
// return "not found";
|
||||
// }
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimLayerCurve::findFormationNameForDepth( const std::vector<QString>& formationNames,
|
||||
const std::vector<std::pair<double, double>>& 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";
|
||||
}
|
56
ApplicationCode/ProjectDataModel/RimLayerCurve.h
Normal file
56
ApplicationCode/ProjectDataModel/RimLayerCurve.h
Normal file
@ -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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// 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<QString>& formationNames,
|
||||
const std::vector<std::pair<double, double>>& depthRanges,
|
||||
double depth );
|
||||
|
||||
caf::PdmPtrField<RimFractureModel*> m_fractureModel;
|
||||
// caf::PdmField<caf::AppEnum<PropertyType>> m_propertyType;
|
||||
};
|
@ -94,6 +94,38 @@ const std::vector<double>& RigElasticProperties::proppantEmbedment() const
|
||||
return m_proppantEmbedment;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RigElasticProperties::biotCoefficient() const
|
||||
{
|
||||
return m_biotCoefficient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RigElasticProperties::k0() const
|
||||
{
|
||||
return m_k0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RigElasticProperties::fluidLossCoefficient() const
|
||||
{
|
||||
return m_fluidLossCoefficient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RigElasticProperties::spurtLoss() const
|
||||
{
|
||||
return m_spurtLoss;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -101,13 +133,21 @@ void RigElasticProperties::appendValues( double porosity,
|
||||
double youngsModulus,
|
||||
double poissonsRatio,
|
||||
double K_Ic,
|
||||
double proppantEmbedment )
|
||||
double proppantEmbedment,
|
||||
double biotCoefficient,
|
||||
double k0,
|
||||
double fluidLossCoefficient,
|
||||
double spurtLoss )
|
||||
{
|
||||
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 );
|
||||
m_fluidLossCoefficient.push_back( fluidLossCoefficient );
|
||||
m_spurtLoss.push_back( spurtLoss );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -141,3 +181,35 @@ 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 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigElasticProperties::getFluidLossCoefficient( double porosity ) const
|
||||
{
|
||||
return RiaInterpolationTools::linear( m_porosity, m_fluidLossCoefficient, porosity );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RigElasticProperties::getSpurtLoss( double porosity ) const
|
||||
{
|
||||
return RiaInterpolationTools::linear( m_porosity, m_spurtLoss, porosity );
|
||||
}
|
||||
|
@ -33,17 +33,33 @@ 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 fluidLossCoefficient,
|
||||
double spurtLoss );
|
||||
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;
|
||||
double getFluidLossCoefficient( double porosity ) const;
|
||||
double getSpurtLoss( double porosity ) const;
|
||||
|
||||
const std::vector<double>& porosity() const;
|
||||
const std::vector<double>& youngsModulus() const;
|
||||
const std::vector<double>& poissonsRatio() const;
|
||||
const std::vector<double>& K_Ic() const;
|
||||
const std::vector<double>& proppantEmbedment() const;
|
||||
const std::vector<double>& biotCoefficient() const;
|
||||
const std::vector<double>& k0() const;
|
||||
const std::vector<double>& fluidLossCoefficient() const;
|
||||
const std::vector<double>& spurtLoss() const;
|
||||
|
||||
private:
|
||||
QString m_fieldName;
|
||||
@ -55,4 +71,8 @@ private:
|
||||
std::vector<double> m_poissonsRatio;
|
||||
std::vector<double> m_K_Ic;
|
||||
std::vector<double> m_proppantEmbedment;
|
||||
std::vector<double> m_biotCoefficient;
|
||||
std::vector<double> m_k0;
|
||||
std::vector<double> m_fluidLossCoefficient;
|
||||
std::vector<double> m_spurtLoss;
|
||||
};
|
||||
|
@ -37,8 +37,8 @@ TEST( RifElasticPropertiesReaderTest, ReadCorrectInputFile )
|
||||
|
||||
{
|
||||
QTextStream out( &file );
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2\n"
|
||||
<< "Norne,Not,Sand,0.10,19,0.27,2099,0.3\n";
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"
|
||||
<< "Norne,Not,Sand,0.10,19,0.27,2099,0.3,0.4,0.5,0.2,0.5\n";
|
||||
}
|
||||
|
||||
QStringList filePaths;
|
||||
@ -119,7 +119,7 @@ TEST( RifElasticPropertiesReaderTest, ReadShortLinesFileThrows )
|
||||
|
||||
{
|
||||
QTextStream out( &file );
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2\n"
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"
|
||||
<< "Norne,Not,Sand,0.10,19,0.27\n";
|
||||
}
|
||||
|
||||
@ -140,8 +140,8 @@ TEST( RifElasticPropertiesReaderTest, ReadEmptyFieldNameThrows )
|
||||
|
||||
{
|
||||
QTextStream out( &file );
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2\n"
|
||||
<< ",Not,Sand,0.10,19,0.27,2099,0.3\n";
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"
|
||||
<< ",Not,Sand,0.10,19,0.27,2099,0.3,0.3,0.4,0.5,0.6\n";
|
||||
}
|
||||
|
||||
QStringList filePaths;
|
||||
@ -161,8 +161,8 @@ TEST( RifElasticPropertiesReaderTest, ReadInvalidMeasureDepthThrows )
|
||||
|
||||
{
|
||||
QTextStream out( &file );
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2\n"
|
||||
<< "Norne,Not,Sand, not a number,23.4,0.27,2099,0.3\n";
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"
|
||||
<< "Norne,Not,Sand, not a number,23.4,0.27,2099,0.3,0.3,0.4,0.5,0.6\n";
|
||||
}
|
||||
|
||||
QStringList filePaths;
|
||||
@ -191,14 +191,14 @@ TEST( RifElasticPropertiesReaderTest, CommentsAndEmptyLinesAreIgnored )
|
||||
out << "\t\n";
|
||||
out << " \n";
|
||||
// Then some data
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2\n";
|
||||
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n";
|
||||
// Comment in-between data should be ignored
|
||||
out << "# One more comment in-between the data\n";
|
||||
out << "Norne,Not,Silt,0.00,25,0.25,2000,0.2\n";
|
||||
out << "Norne,Not,Silt,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n";
|
||||
// Empty line in-between data should be ignored
|
||||
out << "\n";
|
||||
// Data with comment sign inside it is not ignored
|
||||
out << "Norne,Not,Shale,0.00,25,0.25,2000,0.2\n";
|
||||
out << "Norne,Not,Shale,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n";
|
||||
// Trailing empty lines should be ignored
|
||||
out << "\n\n\n";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user