Merge pull request #6372 from OPM/stimplan-detailed-fluid-loss-6364

Stimplan detailed fluid loss 6364
This commit is contained in:
Kristian Bendiksen 2020-08-26 12:50:43 +02:00 committed by GitHub
commit 100c1b9e14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 382 additions and 53 deletions

View File

@ -41,6 +41,16 @@ void AppEnum<RiaDefines::CurveProperty>::setUp()
addItem( RiaDefines::CurveProperty::K0, "K0", "k0" ); addItem( RiaDefines::CurveProperty::K0, "K0", "k0" );
addItem( RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT, "FLUID_LOSS_COEFFICIENT", "Fluid Loss Coefficient" ); addItem( RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT, "FLUID_LOSS_COEFFICIENT", "Fluid Loss Coefficient" );
addItem( RiaDefines::CurveProperty::SPURT_LOSS, "SPURT_LOSS", "Spurt Loss" ); addItem( RiaDefines::CurveProperty::SPURT_LOSS, "SPURT_LOSS", "Spurt Loss" );
addItem( RiaDefines::CurveProperty::TEMPERATURE, "TEMPERATURE", "Temperature" );
addItem( RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR,
"RELATIVE_PERMEABILITY_FACTOR",
"Relative Permeability Factor" );
addItem( RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT, "PORO_ELASTIC_CONSTANT", "Poro-Elastic Constant" );
addItem( RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT,
"THERMAL_EXPANSION_COEFFICIENT",
"Thermal Expansion Coefficient" );
addItem( RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION, "IMMOBILE_FLUID_SATURATION", "Immobile Fluid Saturation" );
setDefault( RiaDefines::CurveProperty::UNDEFINED ); setDefault( RiaDefines::CurveProperty::UNDEFINED );
} }
}; // namespace caf }; // namespace caf

View File

@ -43,6 +43,11 @@ enum class CurveProperty
BIOT_COEFFICIENT, BIOT_COEFFICIENT,
K0, K0,
FLUID_LOSS_COEFFICIENT, FLUID_LOSS_COEFFICIENT,
SPURT_LOSS SPURT_LOSS,
TEMPERATURE,
RELATIVE_PERMEABILITY_FACTOR,
PORO_ELASTIC_CONSTANT,
THERMAL_EXPANSION_COEFFICIENT,
IMMOBILE_FLUID_SATURATION,
}; };
}; // namespace RiaDefines }; // namespace RiaDefines

View File

@ -140,7 +140,11 @@ RimFractureModelPlot*
RiaDefines::CurveProperty::BIOT_COEFFICIENT, RiaDefines::CurveProperty::BIOT_COEFFICIENT,
RiaDefines::CurveProperty::K0, RiaDefines::CurveProperty::K0,
RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT, RiaDefines::CurveProperty::FLUID_LOSS_COEFFICIENT,
RiaDefines::CurveProperty::SPURT_LOSS}; RiaDefines::CurveProperty::SPURT_LOSS,
RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR,
RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT,
RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT,
RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION};
for ( auto result : results ) for ( auto result : results )
{ {
@ -152,6 +156,7 @@ RimFractureModelPlot*
auto task = progInfo.task( "Creating stress track", 2 ); auto task = progInfo.task( "Creating stress track", 2 );
createStressTrack( plot, fractureModel, eclipseCase, timeStep, RiaDefines::CurveProperty::STRESS ); createStressTrack( plot, fractureModel, eclipseCase, timeStep, RiaDefines::CurveProperty::STRESS );
createStressTrack( plot, fractureModel, eclipseCase, timeStep, RiaDefines::CurveProperty::STRESS_GRADIENT ); createStressTrack( plot, fractureModel, eclipseCase, timeStep, RiaDefines::CurveProperty::STRESS_GRADIENT );
createStressTrack( plot, fractureModel, eclipseCase, timeStep, RiaDefines::CurveProperty::TEMPERATURE );
} }
{ {

View File

@ -96,7 +96,8 @@ void RicElasticPropertiesImportTools::importElasticPropertiesFromFile( const QSt
item.biotCoefficient, item.biotCoefficient,
item.k0, item.k0,
item.fluidLossCoefficient, item.fluidLossCoefficient,
item.spurtLoss ); item.spurtLoss,
item.immobileFluidSaturation );
} }
rimElasticProperties->setPropertiesForFacies( key, rigElasticProperties ); rimElasticProperties->setPropertiesForFacies( key, rigElasticProperties );

View File

@ -20,6 +20,7 @@
#include "RiaApplication.h" #include "RiaApplication.h"
#include "RimFractureModel.h"
#include "RimFractureModelPlot.h" #include "RimFractureModelPlot.h"
#include "RifFractureModelPlotExporter.h" #include "RifFractureModelPlotExporter.h"
@ -61,7 +62,9 @@ void RicExportFractureModelPlotToFileFeature::onActionTriggered( bool isChecked
if ( fileName.isEmpty() ) return; if ( fileName.isEmpty() ) return;
RifFractureModelPlotExporter::writeToFile( fractureModelPlot, fileName ); RifFractureModelPlotExporter::writeToFile( fractureModelPlot,
fractureModelPlot->fractureModel()->useDetailedFluidLoss(),
fileName );
// Remember the path to next time // Remember the path to next time
app->setLastUsedDialogDirectory( "FRACTURE_MODEL_PLOT", QFileInfo( fileName ).absolutePath() ); app->setLastUsedDialogDirectory( "FRACTURE_MODEL_PLOT", QFileInfo( fileName ).absolutePath() );

View File

@ -79,7 +79,7 @@ RifElasticProperties
{ {
QStringList tokens = tokenize( line, "," ); QStringList tokens = tokenize( line, "," );
if ( tokens.size() != 12 ) if ( tokens.size() != 13 )
{ {
throw FileParseException( QString( "Incomplete data on line %1: %2" ).arg( lineNumber ).arg( filePath ) ); throw FileParseException( QString( "Incomplete data on line %1: %2" ).arg( lineNumber ).arg( filePath ) );
} }
@ -97,7 +97,8 @@ RifElasticProperties
<< "Biot Coefficient" << "Biot Coefficient"
<< "k0" << "k0"
<< "Fluid Loss Coefficient" << "Fluid Loss Coefficient"
<< "Spurt Loss"; << "Spurt Loss"
<< "Immobile Fluid Saturation";
verifyNonEmptyTokens( tokens, nameOfNonEmptyTokens, lineNumber, filePath ); verifyNonEmptyTokens( tokens, nameOfNonEmptyTokens, lineNumber, filePath );
RifElasticProperties elasticProperties; RifElasticProperties elasticProperties;
@ -113,6 +114,8 @@ RifElasticProperties
elasticProperties.k0 = parseDouble( tokens[9], "k0", lineNumber, filePath ); elasticProperties.k0 = parseDouble( tokens[9], "k0", lineNumber, filePath );
elasticProperties.fluidLossCoefficient = parseDouble( tokens[10], "Fluid Loss Coefficient", lineNumber, filePath ); elasticProperties.fluidLossCoefficient = parseDouble( tokens[10], "Fluid Loss Coefficient", lineNumber, filePath );
elasticProperties.spurtLoss = parseDouble( tokens[11], "Spurt Loss", lineNumber, filePath ); elasticProperties.spurtLoss = parseDouble( tokens[11], "Spurt Loss", lineNumber, filePath );
elasticProperties.immobileFluidSaturation =
parseDouble( tokens[12], "Immobile Fluid Saturation", lineNumber, filePath );
return elasticProperties; return elasticProperties;
} }

View File

@ -36,6 +36,7 @@ struct RifElasticProperties
double k0; double k0;
double fluidLossCoefficient; double fluidLossCoefficient;
double spurtLoss; double spurtLoss;
double immobileFluidSaturation;
}; };
//================================================================================================== //==================================================================================================

View File

@ -26,7 +26,7 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, const QString& filepath ) bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, bool useDetailedLoss, const QString& filepath )
{ {
std::vector<QString> labels; std::vector<QString> labels;
// TVD depth of top of zone (ft) // TVD depth of top of zone (ft)
@ -56,13 +56,15 @@ bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, cons
// Proppand Embedmeent (lb/ft^2) // Proppand Embedmeent (lb/ft^2)
labels.push_back( "pembed" ); labels.push_back( "pembed" );
bool useDetailedLoss = false;
if ( useDetailedLoss ) if ( useDetailedLoss )
{ {
// B2 Detailed Loss // B2 Detailed Loss
// Reservoir Pressure (psi) // Reservoir Pressure (psi)
labels.push_back( "zoneResPres" ); labels.push_back( "zoneResPres" );
// Immobile Fluid Saturation (fraction)
labels.push_back( "zoneWaterSat" );
// Porosity (fraction) // Porosity (fraction)
labels.push_back( "zonePorosity" ); labels.push_back( "zonePorosity" );
@ -71,6 +73,18 @@ bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, cons
// Vertical Perm (md) // Vertical Perm (md)
labels.push_back( "zoneVertPerm" ); labels.push_back( "zoneVertPerm" );
// Temperature (F)
labels.push_back( "zoneTemp" );
// Relative permeability
labels.push_back( "zoneRelPerm" );
// Poro-Elastic constant
labels.push_back( "zonePoroElas" );
// Thermal Epansion Coefficient (1/F)
labels.push_back( "zoneThermalExp" );
} }
std::map<QString, std::vector<double>> values; std::map<QString, std::vector<double>> values;
@ -84,9 +98,14 @@ bool RifFractureModelPlotExporter::writeToFile( RimFractureModelPlot* plot, cons
values["clyrs"] = plot->calculateSpurtLoss(); values["clyrs"] = plot->calculateSpurtLoss();
values["pembed"] = plot->calculateProppandEmbedment(); values["pembed"] = plot->calculateProppandEmbedment();
values["zoneResPres"] = plot->calculateReservoirPressure(); values["zoneResPres"] = plot->calculateReservoirPressure();
values["zoneWaterSat"] = plot->calculateImmobileFluidSaturation();
values["zonePorosity"] = plot->calculatePorosity(); values["zonePorosity"] = plot->calculatePorosity();
values["zoneHorizPerm"] = plot->calculateHorizontalPermeability(); values["zoneHorizPerm"] = plot->calculateHorizontalPermeability();
values["zoneVertPerm"] = plot->calculateVerticalPermeability(); values["zoneVertPerm"] = plot->calculateVerticalPermeability();
values["zoneTemp"] = plot->calculateTemperature();
values["zoneRelPerm"] = plot->calculateRelativePermeabilityFactor();
values["zonePoroElas"] = plot->calculatePoroElasticConstant();
values["zoneThermalExp"] = plot->calculateThermalExpansionCoefficient();
QFile data( filepath ); QFile data( filepath );
if ( !data.open( QFile::WriteOnly | QFile::Truncate ) ) if ( !data.open( QFile::WriteOnly | QFile::Truncate ) )

View File

@ -30,7 +30,7 @@ class QTextStream;
class RifFractureModelPlotExporter class RifFractureModelPlotExporter
{ {
public: public:
static bool writeToFile( RimFractureModelPlot* plot, const QString& filepath ); static bool writeToFile( RimFractureModelPlot* plot, bool useDetailedFluidLoss, const QString& filepath );
private: private:
static void appendToStream( QTextStream& stream, const QString& label, const std::vector<double>& values ); static void appendToStream( QTextStream& stream, const QString& label, const std::vector<double>& values );

View File

@ -85,7 +85,7 @@ RigFemScalarResultFrames*
frameCountProgress.incrementProgress(); frameCountProgress.incrementProgress();
// Biot porelastic coeffisient (alpha) // Biot porelastic coefficient (alpha)
frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() ); frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() );
RigFemScalarResultFrames* biotCoefficient = nullptr; RigFemScalarResultFrames* biotCoefficient = nullptr;
if ( !m_resultCollection->biotResultAddress().isEmpty() ) if ( !m_resultCollection->biotResultAddress().isEmpty() )

View File

@ -168,6 +168,40 @@ RimFractureModel::RimFractureModel()
"", "",
"" ); "" );
CAF_PDM_InitScriptableField( &m_referenceTemperature, "ReferenceTemperature", 20.0, "Temperature [C]", "", "", "" );
CAF_PDM_InitScriptableField( &m_referenceTemperatureGradient,
"ReferenceTemperatureGradient",
0.025,
"Temperature Gradient [C/m]",
"",
"",
"" );
CAF_PDM_InitScriptableField( &m_referenceTemperatureDepth,
"ReferenceTemperatureDepth",
1000.0,
"Temperature Depth [m]",
"",
"",
"" );
CAF_PDM_InitScriptableField( &m_useDetailedFluidLoss, "UseDetailedFluidLoss", true, "Use Detailed Fluid Loss", "", "", "" );
CAF_PDM_InitScriptableField( &m_relativePermeabilityFactorDefault,
"RelativePermeabilityFactor",
0.5,
"Relative Permeability Factor",
"",
"",
"" );
CAF_PDM_InitScriptableField( &m_poroElasticConstantDefault, "PoroElasticConstant", 0.0, "Poro-Elastic Constant", "", "", "" );
CAF_PDM_InitScriptableField( &m_thermalExpansionCoeffientDefault,
"ThermalExpansionCoefficient",
0.0,
"Thermal Expansion Coefficient [1/C]",
"",
"",
"" );
CAF_PDM_InitScriptableFieldNoDefault( &m_elasticProperties, "ElasticProperties", "Elastic Properties", "", "", "" ); CAF_PDM_InitScriptableFieldNoDefault( &m_elasticProperties, "ElasticProperties", "Elastic Properties", "", "", "" );
m_elasticProperties.uiCapability()->setUiHidden( true ); m_elasticProperties.uiCapability()->setUiHidden( true );
m_elasticProperties.uiCapability()->setUiTreeHidden( true ); m_elasticProperties.uiCapability()->setUiTreeHidden( true );
@ -188,6 +222,14 @@ bool RimFractureModel::isEnabled() const
return isChecked(); return isChecked();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFractureModel::useDetailedFluidLoss() const
{
return m_useDetailedFluidLoss();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -712,6 +754,42 @@ double RimFractureModel::getUnderburdenGradient( const QString& keyword ) const
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureModel::getDefaultValueForProperty( RiaDefines::CurveProperty curveProperty ) const
{
if ( curveProperty == RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR )
{
return m_relativePermeabilityFactorDefault;
}
else if ( curveProperty == RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT )
{
return m_poroElasticConstantDefault;
}
else if ( curveProperty == RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT )
{
return m_thermalExpansionCoeffientDefault;
}
else
{
RiaLogging::error(
QString( "Missing default for %1." ).arg( caf::AppEnum<RiaDefines::CurveProperty>( curveProperty ).uiText() ) );
return std::numeric_limits<double>::infinity();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimFractureModel::hasDefaultValueForProperty( RiaDefines::CurveProperty curveProperty ) const
{
auto withDefaults = {RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR,
RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT,
RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT};
return std::find( withDefaults.begin(), withDefaults.end(), curveProperty ) != withDefaults.end();
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -840,3 +918,27 @@ void RimFractureModel::setMD( double md )
updatePositionFromMeasuredDepth(); updatePositionFromMeasuredDepth();
updateThicknessDirection(); updateThicknessDirection();
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureModel::referenceTemperature() const
{
return m_referenceTemperature;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureModel::referenceTemperatureGradient() const
{
return m_referenceTemperatureGradient;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFractureModel::referenceTemperatureDepth() const
{
return m_referenceTemperatureDepth;
}

View File

@ -85,6 +85,12 @@ public:
QString underburdenFormation() const; QString underburdenFormation() const;
QString underburdenFacies() const; QString underburdenFacies() const;
double referenceTemperature() const;
double referenceTemperatureGradient() const;
double referenceTemperatureDepth() const;
bool useDetailedFluidLoss() const;
// RimWellPathCompletionsInterface overrides. // RimWellPathCompletionsInterface overrides.
RiaDefines::WellPathComponentType componentType() const override; RiaDefines::WellPathComponentType componentType() const override;
QString componentLabel() const override; QString componentLabel() const override;
@ -103,6 +109,9 @@ public:
void setElasticProperties( RimElasticProperties* elasticProperties ); void setElasticProperties( RimElasticProperties* elasticProperties );
RimElasticProperties* elasticProperties() const; RimElasticProperties* elasticProperties() const;
double getDefaultValueForProperty( RiaDefines::CurveProperty ) const;
bool hasDefaultValueForProperty( RiaDefines::CurveProperty ) const;
RiaDefines::CurveProperty getDefaultPropertyForMissingValues( const QString& keyword ) const; RiaDefines::CurveProperty getDefaultPropertyForMissingValues( const QString& keyword ) const;
double getDefaultForMissingOverburdenValue( const QString& keyword ) const; double getDefaultForMissingOverburdenValue( const QString& keyword ) const;
double getDefaultForMissingUnderburdenValue( const QString& keyword ) const; double getDefaultForMissingUnderburdenValue( const QString& keyword ) const;
@ -151,4 +160,11 @@ protected:
caf::PdmField<QString> m_underburdenFormation; caf::PdmField<QString> m_underburdenFormation;
caf::PdmField<QString> m_underburdenFacies; caf::PdmField<QString> m_underburdenFacies;
caf::PdmField<double> m_underburdenFluidDensity; caf::PdmField<double> m_underburdenFluidDensity;
caf::PdmField<double> m_referenceTemperature;
caf::PdmField<double> m_referenceTemperatureGradient;
caf::PdmField<double> m_referenceTemperatureDepth;
caf::PdmField<double> m_relativePermeabilityFactorDefault;
caf::PdmField<double> m_poroElasticConstantDefault;
caf::PdmField<double> m_thermalExpansionCoeffientDefault;
caf::PdmField<bool> m_useDetailedFluidLoss;
}; };

View File

@ -136,6 +136,7 @@ QString RimElasticProperties::generatePropertiesTable()
" <th>k0</th>" " <th>k0</th>"
" <th>Fluid Loss<br>Coefficient</th>" " <th>Fluid Loss<br>Coefficient</th>"
" <th>Spurt Loss</th>" " <th>Spurt Loss</th>"
" <th>Immobile Fluid<br>Saturation</th>"
" </tr>" " </tr>"
" </thead>" " </thead>"
" <tbody>" ); " <tbody>" );
@ -153,6 +154,7 @@ QString RimElasticProperties::generatePropertiesTable()
const std::vector<double>& k0 = prop.second.k0(); const std::vector<double>& k0 = prop.second.k0();
const std::vector<double>& fluidLossCoefficient = prop.second.fluidLossCoefficient(); const std::vector<double>& fluidLossCoefficient = prop.second.fluidLossCoefficient();
const std::vector<double>& spurtLoss = prop.second.spurtLoss(); const std::vector<double>& spurtLoss = prop.second.spurtLoss();
const std::vector<double>& immobileFluidSaturation = prop.second.immobileFluidSaturation();
for ( size_t i = 0; i < porosity.size(); i++ ) for ( size_t i = 0; i < porosity.size(); i++ )
{ {
@ -169,6 +171,7 @@ QString RimElasticProperties::generatePropertiesTable()
" <td align=right>%10</td>" " <td align=right>%10</td>"
" <td align=right>%11</td>" " <td align=right>%11</td>"
" <td align=right>%12</td>" " <td align=right>%12</td>"
" <td align=right>%13</td>"
"</tr>" ); "</tr>" );
QString line = format.arg( fieldName ) QString line = format.arg( fieldName )
@ -182,7 +185,8 @@ QString RimElasticProperties::generatePropertiesTable()
.arg( biotCoefficient[i] ) .arg( biotCoefficient[i] )
.arg( k0[i] ) .arg( k0[i] )
.arg( fluidLossCoefficient[i] ) .arg( fluidLossCoefficient[i] )
.arg( spurtLoss[i] ); .arg( spurtLoss[i] )
.arg( immobileFluidSaturation[i] );
body.append( line ); body.append( line );
} }

View File

@ -309,6 +309,16 @@ void RimElasticPropertiesCurve::performDataExtraction( bool* isUsingPseudoLength
double val = rigElasticProperties.getSpurtLoss( porosity ); double val = rigElasticProperties.getSpurtLoss( porosity );
values.push_back( val ); values.push_back( val );
} }
else if ( m_curveProperty() == RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION )
{
double val = rigElasticProperties.getImmobileFluidSaturation( porosity );
values.push_back( val );
}
else if ( m_fractureModel->hasDefaultValueForProperty( curveProperty() ) )
{
double val = m_fractureModel->getDefaultValueForProperty( curveProperty() );
values.push_back( val );
}
} }
else else
{ {

View File

@ -18,6 +18,7 @@
#include "RimFractureModelPlot.h" #include "RimFractureModelPlot.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaFractureModelDefines.h"
#include "RiaLogging.h" #include "RiaLogging.h"
#include "RicfCommandObject.h" #include "RicfCommandObject.h"
@ -59,6 +60,14 @@ void RimFractureModelPlot::setFractureModel( RimFractureModel* fractureModel )
m_fractureModel = fractureModel; m_fractureModel = fractureModel;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFractureModel* RimFractureModelPlot::fractureModel()
{
return m_fractureModel;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -310,7 +319,15 @@ std::vector<double> RimFractureModelPlot::calculatePorosity() const
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculateReservoirPressure() const std::vector<double> RimFractureModelPlot::calculateReservoirPressure() const
{ {
return findCurveAndComputeTopOfLayer( RiaDefines::CurveProperty::PRESSURE ); std::vector<double> pressureBar = findCurveAndComputeTopOfLayer( RiaDefines::CurveProperty::PRESSURE );
std::vector<double> pressurePsi;
for ( double p : pressureBar )
{
pressurePsi.push_back( RiaEclipseUnitTools::barToPsi( p ) );
}
return pressurePsi;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -472,6 +489,37 @@ std::vector<double> RimFractureModelPlot::calculateStressGradient() const
return stressGradients; return stressGradients;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimFractureModelPlot::calculateTemperature( std::vector<double>& temperatures ) const
{
// Reference temperature. Unit: degrees celsius
const double referenceTemperature = m_fractureModel->referenceTemperature();
// Reference temperature gradient. Unit: degrees Celsius per meter
const double referenceTemperatureGradient = m_fractureModel->referenceTemperatureGradient();
// Reference depth for temperature. Unit: meter.
const double referenceTemperatureDepth = m_fractureModel->referenceTemperatureDepth();
std::vector<std::pair<double, double>> layerBoundaryDepths;
std::vector<std::pair<size_t, size_t>> layerBoundaryIndexes;
calculateLayers( layerBoundaryDepths, layerBoundaryIndexes );
// Calculate the temperatures
for ( size_t i = 0; i < layerBoundaryDepths.size(); i++ )
{
double depthTopOfZone = layerBoundaryDepths[i].first;
// Use difference between reference depth and depth of top of zone
double depthDiff = depthTopOfZone - referenceTemperatureDepth;
double temperature = referenceTemperature + referenceTemperatureGradient * depthDiff;
temperatures.push_back( temperature );
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -526,3 +574,64 @@ std::vector<double> RimFractureModelPlot::calculateProppandEmbedment() const
{ {
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PROPPANT_EMBEDMENT ); return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PROPPANT_EMBEDMENT );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculateImmobileFluidSaturation() const
{
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::IMMOBILE_FLUID_SATURATION );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculateTemperature() const
{
std::vector<double> temperaturesCelsius;
calculateTemperature( temperaturesCelsius );
// Convert to Fahrenheit
std::vector<double> temperaturesFahrenheit;
for ( double t : temperaturesCelsius )
{
temperaturesFahrenheit.push_back( t * 1.8 + 32.0 );
}
return temperaturesFahrenheit;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculateRelativePermeabilityFactor() const
{
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::RELATIVE_PERMEABILITY_FACTOR );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculatePoroElasticConstant() const
{
return findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::PORO_ELASTIC_CONSTANT );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimFractureModelPlot::calculateThermalExpansionCoefficient() const
{
// SI unit is 1/Celsius
std::vector<double> coefficientCelsius =
findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty::THERMAL_EXPANSION_COEFFICIENT );
// Field unit is 1/Fahrenheit
std::vector<double> coefficientFahrenheit;
for ( double c : coefficientCelsius )
{
coefficientFahrenheit.push_back( c / 1.8 );
}
return coefficientFahrenheit;
}

View File

@ -57,6 +57,7 @@ public:
RimFractureModelPlot(); RimFractureModelPlot();
void setFractureModel( RimFractureModel* fractureModel ); void setFractureModel( RimFractureModel* fractureModel );
RimFractureModel* fractureModel();
void getPorosityValues( std::vector<double>& values ) const; void getPorosityValues( std::vector<double>& values ) const;
void getFaciesValues( std::vector<double>& values ) const; void getFaciesValues( std::vector<double>& values ) const;
@ -76,6 +77,14 @@ public:
std::vector<double> calculateSpurtLoss() const; std::vector<double> calculateSpurtLoss() const;
std::vector<double> calculateProppandEmbedment() const; std::vector<double> calculateProppandEmbedment() const;
std::vector<double> calculateImmobileFluidSaturation() const;
std::vector<double> calculateTemperature() const;
std::vector<double> calculateRelativePermeabilityFactor() const;
std::vector<double> calculatePoroElasticConstant() const;
std::vector<double> calculateThermalExpansionCoefficient() const;
void calculateTemperature( std::vector<double>& temperatures ) const;
protected: protected:
std::vector<double> findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty curveProperty ) const; std::vector<double> findCurveAndComputeLayeredAverage( RiaDefines::CurveProperty curveProperty ) const;
std::vector<double> findCurveXValuesByProperty( RiaDefines::CurveProperty curveProperty ) const; std::vector<double> findCurveXValuesByProperty( RiaDefines::CurveProperty curveProperty ) const;

View File

@ -19,6 +19,7 @@
#include "RimFractureModelStressCurve.h" #include "RimFractureModelStressCurve.h"
#include "RiaDefines.h" #include "RiaDefines.h"
#include "RiaFractureModelDefines.h"
#include "RigEclipseCaseData.h" #include "RigEclipseCaseData.h"
#include "RigEclipseWellLogExtractor.h" #include "RigEclipseWellLogExtractor.h"
#include "RigResultAccessorFactory.h" #include "RigResultAccessorFactory.h"
@ -121,15 +122,19 @@ void RimFractureModelStressCurve::performDataExtraction( bool* isUsingPseudoLeng
tvDepthValues.push_back( RiaEclipseUnitTools::feetToMeter( f ) ); tvDepthValues.push_back( RiaEclipseUnitTools::feetToMeter( f ) );
} }
std::vector<double> stressGradients = fractureModelPlot->calculateStressGradient();
if ( m_curveProperty() == RiaDefines::CurveProperty::STRESS ) if ( m_curveProperty() == RiaDefines::CurveProperty::STRESS )
{ {
values = fractureModelPlot->calculateStress(); values = fractureModelPlot->calculateStress();
std::vector<double> stressGradients = fractureModelPlot->calculateStressGradient();
addDatapointsForBottomOfLayers( tvDepthValues, values, stressGradients ); addDatapointsForBottomOfLayers( tvDepthValues, values, stressGradients );
} }
else else if ( m_curveProperty() == RiaDefines::CurveProperty::STRESS_GRADIENT )
{ {
values = stressGradients; values = fractureModelPlot->calculateStressGradient();
}
else if ( m_curveProperty() == RiaDefines::CurveProperty::TEMPERATURE )
{
fractureModelPlot->calculateTemperature( values );
} }
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case.value() ); RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case.value() );

View File

@ -44,7 +44,9 @@ caf::PdmObjectHandle* RimcFractureModelPlot_exportToFile::execute()
{ {
RimFractureModelPlot* fractureModelPlot = self<RimFractureModelPlot>(); RimFractureModelPlot* fractureModelPlot = self<RimFractureModelPlot>();
RifFractureModelPlotExporter::writeToFile( fractureModelPlot, m_filePath() ); RifFractureModelPlotExporter::writeToFile( fractureModelPlot,
fractureModelPlot->fractureModel()->useDetailedFluidLoss(),
m_filePath() );
return nullptr; return nullptr;
} }

View File

@ -126,6 +126,14 @@ const std::vector<double>& RigElasticProperties::spurtLoss() const
return m_spurtLoss; return m_spurtLoss;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RigElasticProperties::immobileFluidSaturation() const
{
return m_immobileFluidSaturation;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -137,7 +145,8 @@ void RigElasticProperties::appendValues( double porosity,
double biotCoefficient, double biotCoefficient,
double k0, double k0,
double fluidLossCoefficient, double fluidLossCoefficient,
double spurtLoss ) double spurtLoss,
double immobileFluidSaturation )
{ {
m_porosity.push_back( porosity ); m_porosity.push_back( porosity );
m_youngsModulus.push_back( youngsModulus ); m_youngsModulus.push_back( youngsModulus );
@ -148,6 +157,7 @@ void RigElasticProperties::appendValues( double porosity,
m_k0.push_back( k0 ); m_k0.push_back( k0 );
m_fluidLossCoefficient.push_back( fluidLossCoefficient ); m_fluidLossCoefficient.push_back( fluidLossCoefficient );
m_spurtLoss.push_back( spurtLoss ); m_spurtLoss.push_back( spurtLoss );
m_immobileFluidSaturation.push_back( immobileFluidSaturation );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -213,3 +223,11 @@ double RigElasticProperties::getSpurtLoss( double porosity ) const
{ {
return RiaInterpolationTools::linear( m_porosity, m_spurtLoss, porosity ); return RiaInterpolationTools::linear( m_porosity, m_spurtLoss, porosity );
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigElasticProperties::getImmobileFluidSaturation( double porosity ) const
{
return RiaInterpolationTools::linear( m_porosity, m_immobileFluidSaturation, porosity );
}

View File

@ -41,7 +41,8 @@ public:
double biotCoefficient, double biotCoefficient,
double k0, double k0,
double fluidLossCoefficient, double fluidLossCoefficient,
double spurtLoss ); double spurtLoss,
double immobileFluidSaturation );
double getYoungsModulus( double porosity ) const; double getYoungsModulus( double porosity ) const;
double getPoissonsRatio( double porosity ) const; double getPoissonsRatio( double porosity ) const;
double getK_Ic( double porosity ) const; double getK_Ic( double porosity ) const;
@ -50,6 +51,7 @@ public:
double getK0( double porosity ) const; double getK0( double porosity ) const;
double getFluidLossCoefficient( double porosity ) const; double getFluidLossCoefficient( double porosity ) const;
double getSpurtLoss( double porosity ) const; double getSpurtLoss( double porosity ) const;
double getImmobileFluidSaturation( double porosity ) const;
const std::vector<double>& porosity() const; const std::vector<double>& porosity() const;
const std::vector<double>& youngsModulus() const; const std::vector<double>& youngsModulus() const;
@ -60,6 +62,7 @@ public:
const std::vector<double>& k0() const; const std::vector<double>& k0() const;
const std::vector<double>& fluidLossCoefficient() const; const std::vector<double>& fluidLossCoefficient() const;
const std::vector<double>& spurtLoss() const; const std::vector<double>& spurtLoss() const;
const std::vector<double>& immobileFluidSaturation() const;
private: private:
QString m_fieldName; QString m_fieldName;
@ -75,4 +78,5 @@ private:
std::vector<double> m_k0; std::vector<double> m_k0;
std::vector<double> m_fluidLossCoefficient; std::vector<double> m_fluidLossCoefficient;
std::vector<double> m_spurtLoss; std::vector<double> m_spurtLoss;
std::vector<double> m_immobileFluidSaturation;
}; };

View File

@ -37,8 +37,8 @@ TEST( RifElasticPropertiesReaderTest, ReadCorrectInputFile )
{ {
QTextStream out( &file ); QTextStream out( &file );
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n" out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.4\n"
<< "Norne,Not,Sand,0.10,19,0.27,2099,0.3,0.4,0.5,0.2,0.5\n"; << "Norne,Not,Sand,0.10,19,0.27,2099,0.3,0.4,0.5,0.2,0.5,0.55\n";
} }
QStringList filePaths; QStringList filePaths;
@ -72,6 +72,9 @@ TEST( RifElasticPropertiesReaderTest, ReadCorrectInputFile )
ASSERT_DOUBLE_EQ( 0.2, elasticProperties[0].proppantEmbedment ); ASSERT_DOUBLE_EQ( 0.2, elasticProperties[0].proppantEmbedment );
ASSERT_DOUBLE_EQ( 0.3, elasticProperties[1].proppantEmbedment ); ASSERT_DOUBLE_EQ( 0.3, elasticProperties[1].proppantEmbedment );
ASSERT_DOUBLE_EQ( 0.4, elasticProperties[0].immobileFluidSaturation );
ASSERT_DOUBLE_EQ( 0.55, elasticProperties[1].immobileFluidSaturation );
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -119,7 +122,7 @@ TEST( RifElasticPropertiesReaderTest, ReadShortLinesFileThrows )
{ {
QTextStream out( &file ); QTextStream out( &file );
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n" out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.7\n"
<< "Norne,Not,Sand,0.10,19,0.27\n"; << "Norne,Not,Sand,0.10,19,0.27\n";
} }
@ -140,8 +143,8 @@ TEST( RifElasticPropertiesReaderTest, ReadEmptyFieldNameThrows )
{ {
QTextStream out( &file ); QTextStream out( &file );
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n" out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.89\n"
<< ",Not,Sand,0.10,19,0.27,2099,0.3,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,0.89\n";
} }
QStringList filePaths; QStringList filePaths;
@ -161,8 +164,8 @@ TEST( RifElasticPropertiesReaderTest, ReadInvalidMeasureDepthThrows )
{ {
QTextStream out( &file ); QTextStream out( &file );
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n" out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.9\n"
<< "Norne,Not,Sand, not a number,23.4,0.27,2099,0.3,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,0.77\n";
} }
QStringList filePaths; QStringList filePaths;
@ -191,14 +194,14 @@ TEST( RifElasticPropertiesReaderTest, CommentsAndEmptyLinesAreIgnored )
out << "\t\n"; out << "\t\n";
out << " \n"; out << " \n";
// Then some data // Then some data
out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"; out << "Norne,Not,Sand,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.7\n";
// Comment in-between data should be ignored // Comment in-between data should be ignored
out << "# One more comment in-between the data\n"; out << "# One more comment in-between the data\n";
out << "Norne,Not,Silt,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"; out << "Norne,Not,Silt,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.7\n";
// Empty line in-between data should be ignored // Empty line in-between data should be ignored
out << "\n"; out << "\n";
// Data with comment sign inside it is not ignored // Data with comment sign inside it is not ignored
out << "Norne,Not,Shale,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6\n"; out << "Norne,Not,Shale,0.00,25,0.25,2000,0.2,0.3,0.4,0.5,0.6,0.8\n";
// Trailing empty lines should be ignored // Trailing empty lines should be ignored
out << "\n\n\n"; out << "\n\n\n";
} }