Support different units when importing and exporting WBS LAS.

This commit is contained in:
Gaute Lindkvist
2020-01-29 12:52:07 +01:00
parent 3c05ae04e6
commit c9f5b47a90
40 changed files with 976 additions and 444 deletions

View File

@@ -112,6 +112,14 @@ QString RimWellFlowRateCurve::wellLogChannelUiName() const
return "AccumulatedFlowRate";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellFlowRateCurve::wellLogChannelUnits() const
{
return RiaWellLogUnitTools::noUnitString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -48,6 +48,7 @@ public:
int timeStep();
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelUnits() const override;
void setGroupId( int groupId );
int groupId() const;

View File

@@ -650,13 +650,51 @@ QString RimGeoMechResultDefinition::resultVariableName() const
RigWbsParameter param;
if ( RigWbsParameter::findParameter( resultFieldName(), &param ) )
{
QString lasName = param.sourceLabel( RigWbsParameter::LAS_FILE );
QString lasName = param.addressString( RigWbsParameter::LAS_FILE );
if ( !lasName.isEmpty() ) return lasName;
}
}
return resultVariableUiName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechResultDefinition::currentResultUnits() const
{
if ( this->resultFieldName() == "SE" || this->resultFieldName() == "ST" || this->resultFieldName() == "POR-Bar" ||
this->resultFieldName() == "SM" || this->resultFieldName() == "SEM" || this->resultFieldName() == "Q" )
{
return "Bar";
}
else if ( this->resultFieldName() == "MODULUS" )
{
return "GPa";
}
return RiaWellLogUnitTools::noUnitString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimGeoMechResultDefinition::defaultLasUnits() const
{
QString units;
if ( m_resultPositionType == RIG_WELLPATH_DERIVED )
{
RigWbsParameter param;
if ( RigWbsParameter::findParameter( resultFieldName(), &param ) )
{
units = param.units( RigWbsParameter::LAS_FILE );
}
}
if ( units.isEmpty() )
{
units = currentResultUnits();
}
return units;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -742,15 +780,10 @@ void RimGeoMechResultDefinition::updateLegendTextAndRanges( RimRegularLegendConf
legendTitle += ", " + this->resultComponentUiName();
}
if ( this->resultFieldName() == "SE" || this->resultFieldName() == "ST" || this->resultFieldName() == "POR-Bar" ||
this->resultFieldName() == "SM" || this->resultFieldName() == "SEM" || this->resultFieldName() == "Q" )
QString unitString = currentResultUnits();
if ( unitString != RiaWellLogUnitTools::noUnitString() )
{
legendTitle += " [Bar]";
}
if ( this->resultFieldName() == "MODULUS" )
{
legendTitle += " [GPa]";
legendTitle += QString( " [%1]" ).arg( unitString );
}
if ( !this->diffResultUiShortName().isEmpty() )

View File

@@ -68,6 +68,8 @@ public:
QString resultComponentUiName() const;
QString resultVariableUiName() const;
QString resultVariableName() const;
QString currentResultUnits() const;
QString defaultLasUnits() const;
bool hasCategoryResult() const
{

View File

@@ -387,7 +387,7 @@ bool RimWbsParameters::hasLasFileWithChannel( const QString& channel ) const
bool RimWbsParameters::hasElementPropertyEntry( const RigFemResultAddress& resAddr ) const
{
RigFemPartResultsCollection* femPartResults = nullptr;
if ( m_geoMechCase && m_timeStep > 0 )
if ( m_geoMechCase && m_geoMechCase->geoMechData() && m_timeStep > 0 )
{
femPartResults = m_geoMechCase->geoMechData()->femPartResults();
if ( femPartResults )

View File

@@ -131,6 +131,7 @@ void RimWellBoreStabilityPlot::childFieldChangedByUi( const caf::PdmFieldHandle*
//--------------------------------------------------------------------------------------------------
void RimWellBoreStabilityPlot::initAfterRead()
{
updateCommonDataSource();
applyDataSource();
}

View File

@@ -113,9 +113,11 @@ void RimWellLogCurve::setValuesAndDepths( const std::vector<double>& xValues,
RiaDefines::DepthTypeEnum depthType,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve )
bool isExtractionCurve,
const QString& xUnits )
{
m_curveData->setValuesAndDepths( xValues, depths, depthType, rkbDiff, depthUnit, isExtractionCurve );
m_curveData->setXUnits( xUnits );
calculateCurveDataXRange();
}
@@ -126,9 +128,11 @@ void RimWellLogCurve::setValuesAndDepths( const std::vector<double>&
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& depths,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve )
bool isExtractionCurve,
const QString& xUnits )
{
m_curveData->setValuesAndDepths( xValues, depths, rkbDiff, depthUnit, isExtractionCurve );
m_curveData->setXUnits( xUnits );
calculateCurveDataXRange();
}
@@ -140,11 +144,12 @@ void RimWellLogCurve::setValuesWithMdAndTVD( const std::vector<double>& xValues,
const std::vector<double>& tvdMSL,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve )
bool isExtractionCurve,
const QString& xUnits )
{
std::map<RiaDefines::DepthTypeEnum, std::vector<double>> depths = {{RiaDefines::MEASURED_DEPTH, measuredDepths},
{RiaDefines::TRUE_VERTICAL_DEPTH, tvdMSL}};
setValuesAndDepths( xValues, depths, rkbDiff, depthUnit, isExtractionCurve );
setValuesAndDepths( xValues, depths, rkbDiff, depthUnit, isExtractionCurve, xUnits );
}
//--------------------------------------------------------------------------------------------------

View File

@@ -20,6 +20,7 @@
#pragma once
#include "RiaDefines.h"
#include "RiaWellLogUnitTools.h"
#include "RimPlotCurve.h"
#include "cvfObject.h"
@@ -47,24 +48,28 @@ public:
RiaDefines::DepthTypeEnum depthType,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve );
bool isExtractionCurve,
const QString& xUnits = RiaWellLogUnitTools::noUnitString() );
void setValuesWithMdAndTVD( const std::vector<double>& xValues,
const std::vector<double>& measuredDepths,
const std::vector<double>& tvDepths,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve );
bool isExtractionCurve,
const QString& xUnits = RiaWellLogUnitTools::noUnitString() );
void setValuesAndDepths( const std::vector<double>& xValues,
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& depths,
double rkbDiff,
RiaDefines::DepthUnitType depthUnit,
bool isExtractionCurve );
bool isExtractionCurve,
const QString& xUnits = RiaWellLogUnitTools::noUnitString() );
const RigWellLogCurveData* curveData() const;
virtual QString wellName() const = 0;
virtual QString wellLogChannelUiName() const = 0;
virtual QString wellLogChannelName() const;
virtual QString wellLogChannelUnits() const = 0;
virtual QString wellDate() const
{
return "";

View File

@@ -20,8 +20,10 @@
#include "RimWellLogExtractionCurve.h"
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RiaSimWellBranchTools.h"
#include "RiaWellLogUnitTools.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseWellLogExtractor.h"
@@ -450,6 +452,7 @@ void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength,
double rkbDiff = 0.0;
RiaDefines::DepthUnitType depthUnit = RiaDefines::UNIT_METER;
QString xUnits = RiaWellLogUnitTools::noUnitString();
if ( eclExtractor.notNull() && eclipseCase )
{
@@ -498,7 +501,7 @@ void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength,
}
m_geomResultDefinition->loadResult();
geomExtractor->curveData( m_geomResultDefinition->resultAddress(), m_timeStep, &values );
xUnits = geomExtractor->curveData( m_geomResultDefinition->resultAddress(), m_timeStep, &values );
if ( performDataSmoothing )
{
geomExtractor->performCurveDataSmoothing( m_timeStep,
@@ -518,7 +521,8 @@ void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength,
RiaDefines::MEASURED_DEPTH,
0.0,
depthUnit,
!performDataSmoothing );
!performDataSmoothing,
xUnits );
}
else
{
@@ -527,7 +531,8 @@ void RimWellLogExtractionCurve::extractData( bool* isUsingPseudoLength,
tvDepthValues,
rkbDiff,
depthUnit,
!performDataSmoothing );
!performDataSmoothing,
xUnits );
}
}
}
@@ -541,88 +546,27 @@ void RimWellLogExtractionCurve::findAndLoadWbsParametersFromLasFiles( const RimW
auto allParams = RigWbsParameter::allParameters();
for ( const RigWbsParameter& parameter : allParams )
{
if ( parameter == RigWbsParameter::PP_Reservoir() || parameter == RigWbsParameter::PP_NonReservoir() )
{
findAndLoadPorePressuresFromLasFiles( wellPath, parameter, geomExtractor );
}
else if ( parameter == RigWbsParameter::UCS() )
{
findAndLoadUcsFromLasFiles( wellPath, geomExtractor );
}
else
{
// Generic LAS
QString lasAddress = parameter.addressString( RigWbsParameter::LAS_FILE );
QString lasAddress = parameter.addressString( RigWbsParameter::LAS_FILE );
std::vector<std::pair<double, double>> lasFileValues =
RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, lasAddress );
if ( !lasFileValues.empty() )
QString lasUnits;
std::vector<std::pair<double, double>> lasFileValues =
RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath, lasAddress, &lasUnits );
if ( !lasFileValues.empty() )
{
QString extractorUnits = geomExtractor->parameterInputUnits( parameter );
if ( RiaWellLogUnitTools::convertValues( &lasFileValues, lasUnits, extractorUnits, wellPath->wellPathGeometry() ) )
{
geomExtractor->setWbsLasValues( parameter, lasFileValues );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogExtractionCurve::findAndLoadUcsFromLasFiles( const RimWellPath* wellPath,
RigGeoMechWellLogExtractor* geomExtractor )
{
{
QString lasAddress = RigWbsParameter::UCS().addressString( RigWbsParameter::LAS_FILE );
std::vector<std::pair<double, double>> logFileUcs = RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath,
lasAddress );
if ( !logFileUcs.empty() )
{
// TODO: UCS is typically in MPa, but not necessarily.
// We need to at least give a warning if the units don't match
// ... and preferable do a conversion.
for ( auto& ucsValue : logFileUcs )
else
{
ucsValue.second *= 10.0; // MPa -> Bar
QString errMsg = QString( "Could not convert units of LAS-channel %1 from %2 to %3" )
.arg( lasAddress )
.arg( lasUnits )
.arg( extractorUnits );
RiaLogging::error( errMsg );
}
geomExtractor->setWbsLasValues( RigWbsParameter::UCS(), logFileUcs );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogExtractionCurve::findAndLoadPorePressuresFromLasFiles( const RimWellPath* wellPath,
const RigWbsParameter& parameter,
RigGeoMechWellLogExtractor* geomExtractor )
{
{
std::vector<std::pair<double, double>> logFileMudWeights =
RimWellLogFile::findMdAndChannelValuesForWellPath( wellPath,
parameter.addressString( RigWbsParameter::LAS_FILE ) );
if ( !logFileMudWeights.empty() )
{
std::vector<std::pair<double, double>> porePressuresBar;
porePressuresBar.reserve( logFileMudWeights.size() );
for ( auto& mudWeight : logFileMudWeights )
{
// Log file mud weights come in SG units (g / cm^3).
// We need SI as input (kg / m^3), so multiply by 1000:
double mudWeightsSI = mudWeight.second * 1000.0;
// To get specific mudWeight (N / m^3):
double specificMudWeight = mudWeightsSI * 9.81;
double md = mudWeight.first;
cvf::Vec3d point = wellPath->wellPathGeometry()->interpolatedPointAlongWellPath( md );
double depth = -point.z() + wellPath->wellPathGeometry()->rkbDiff();
// Pore pressure in pascal
double ppPascal = specificMudWeight * depth;
// Pore pressure in bar
porePressuresBar.emplace_back( mudWeight.first, ppPascal * 1.0e-5 );
}
geomExtractor->setWbsLasValues( parameter, porePressuresBar );
}
}
}
@@ -963,6 +907,27 @@ QString RimWellLogExtractionCurve::wellLogChannelName() const
return name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogExtractionCurve::wellLogChannelUnits() const
{
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( m_case.value() );
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case.value() );
QString name;
if ( eclipseCase )
{
name = RiaWellLogUnitTools::noUnitString();
}
else if ( geoMechCase )
{
name = m_geomResultDefinition->defaultLasUnits();
}
return name;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -66,6 +66,7 @@ public:
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelName() const override;
QString wellLogChannelUnits() const override;
QString wellDate() const override;
int branchIndex() const;
bool branchDetection() const;
@@ -87,12 +88,6 @@ public:
static void findAndLoadWbsParametersFromLasFiles( const RimWellPath* wellPath,
RigGeoMechWellLogExtractor* geomExtractor );
static void findAndLoadUcsFromLasFiles( const RimWellPath* wellPath, RigGeoMechWellLogExtractor* geomExtractor );
static void findAndLoadPorePressuresFromLasFiles( const RimWellPath* wellPath,
const RigWbsParameter& parameter,
RigGeoMechWellLogExtractor* geomExtractor );
void setAutoNameComponents( bool addCaseName, bool addProperty, bool addWellname, bool addTimeStep, bool addDate );
protected:

View File

@@ -257,7 +257,8 @@ void RimWellLogFile::updateFilePathsFromProjectPath( const QString& newProjectPa
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<double, double>> RimWellLogFile::findMdAndChannelValuesForWellPath( const RimWellPath* wellPath,
const QString& channelName )
const QString& channelName,
QString* unitString /*=nullptr*/ )
{
CVF_ASSERT( wellPath );
std::vector<RimWellLogFile*> wellLogFiles;
@@ -268,6 +269,10 @@ std::vector<std::pair<double, double>> RimWellLogFile::findMdAndChannelValuesFor
std::vector<double> channelValues = fileData->values( channelName );
if ( !channelValues.empty() )
{
if ( unitString )
{
*unitString = fileData->wellLogChannelUnitString( channelName );
}
std::vector<double> depthValues = fileData->depthValues();
CVF_ASSERT( depthValues.size() == channelValues.size() );
std::vector<std::pair<double, double>> depthValuePairs;

View File

@@ -85,7 +85,8 @@ public:
void updateFilePathsFromProjectPath( const QString& newProjectPath, const QString& oldProjectPath );
static std::vector<std::pair<double, double>> findMdAndChannelValuesForWellPath( const RimWellPath* wellPath,
const QString& channelName );
const QString& channelName,
QString* unitString = nullptr );
private:
void setupBeforeSave() override;

View File

@@ -57,7 +57,7 @@ RimWellLogFileCurve::RimWellLogFileCurve()
CAF_PDM_InitFieldNoDefault( &m_wellPath, "CurveWellPath", "Well Path", "", "", "" );
m_wellPath.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_wellLogChannnelName, "CurveWellLogChannel", "Well Log Channel", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_wellLogChannelName, "CurveWellLogChannel", "Well Log Channel", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_wellLogFile, "WellLogFile", "Well Log File", "", "", "" );
@@ -87,7 +87,7 @@ void RimWellLogFileCurve::onLoadDataAndUpdate( bool updateParentPlot )
RigWellLogFile* wellLogFile = m_wellLogFile->wellLogFileData();
if ( wellLogFile )
{
std::vector<double> values = wellLogFile->values( m_wellLogChannnelName );
std::vector<double> values = wellLogFile->values( m_wellLogChannelName );
std::vector<double> measuredDepthValues = wellLogFile->depthValues();
std::vector<double> tvdMslValues = wellLogFile->tvdMslValues();
std::vector<double> tvdRkbValues = wellLogFile->tvdRkbValues();
@@ -201,7 +201,7 @@ RimWellPath* RimWellLogFileCurve::wellPath() const
//--------------------------------------------------------------------------------------------------
void RimWellLogFileCurve::setWellLogChannelName( const QString& name )
{
m_wellLogChannnelName = name;
m_wellLogChannelName = name;
}
//--------------------------------------------------------------------------------------------------
@@ -225,7 +225,7 @@ void RimWellLogFileCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
{
this->loadDataAndUpdate( true );
}
else if ( changedField == &m_wellLogChannnelName )
else if ( changedField == &m_wellLogChannelName )
{
this->loadDataAndUpdate( true );
}
@@ -246,7 +246,7 @@ void RimWellLogFileCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Curve Data" );
curveDataGroup->add( &m_wellPath );
curveDataGroup->add( &m_wellLogFile );
curveDataGroup->add( &m_wellLogChannnelName );
curveDataGroup->add( &m_wellLogChannelName );
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" );
RimPlotCurve::appearanceUiOrdering( *appearanceGroup );
@@ -298,7 +298,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogFileCurve::calculateValueOptions( const
}
}
if ( fieldNeedingOptions == &m_wellLogChannnelName )
if ( fieldNeedingOptions == &m_wellLogChannelName )
{
if ( m_wellPath() )
{
@@ -372,9 +372,9 @@ QString RimWellLogFileCurve::createCurveAutoName()
name.push_back( wellName() );
name.push_back( "LAS" );
if ( !m_wellLogChannnelName().isEmpty() )
if ( !m_wellLogChannelName().isEmpty() )
{
name.push_back( m_wellLogChannnelName );
name.push_back( m_wellLogChannelName );
channelNameAvailable = true;
}
@@ -387,8 +387,7 @@ QString RimWellLogFileCurve::createCurveAutoName()
RimWellLogPlot* wellLogPlot;
firstAncestorOrThisOfType( wellLogPlot );
CVF_ASSERT( wellLogPlot );
QString unitName = wellLogFile->wellLogChannelUnitString( m_wellLogChannnelName,
wellLogPlot->depthUnit() );
QString unitName = wellLogFile->wellLogChannelUnitString( m_wellLogChannelName, wellLogPlot->depthUnit() );
if ( !unitName.isEmpty() )
{
@@ -414,7 +413,19 @@ QString RimWellLogFileCurve::createCurveAutoName()
//--------------------------------------------------------------------------------------------------
QString RimWellLogFileCurve::wellLogChannelUiName() const
{
return m_wellLogChannnelName;
return m_wellLogChannelName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogFileCurve::wellLogChannelUnits() const
{
if ( m_wellLogFile && m_wellLogFile->wellLogFileData() )
{
return m_wellLogFile->wellLogFileData()->wellLogChannelUnitString( m_wellLogChannelName );
}
return RiaWellLogUnitTools::noUnitString();
}
//--------------------------------------------------------------------------------------------------

View File

@@ -50,6 +50,7 @@ public:
// Overrides from RimWellLogPlotCurve
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelUnits() const override;
RimWellLogFile* wellLogFile() const;
@@ -73,6 +74,6 @@ protected:
protected:
caf::PdmPtrField<RimWellPath*> m_wellPath;
caf::PdmPtrField<RimWellLogFile*> m_wellLogFile;
caf::PdmField<QString> m_wellLogChannnelName;
caf::PdmField<QString> m_wellLogChannelName;
caf::PdmField<QString> m_wellLogChannnelUnit;
};

View File

@@ -144,6 +144,14 @@ QString RimWellLogRftCurve::wellLogChannelUiName() const
return m_wellLogChannelName().text();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogRftCurve::wellLogChannelUnits() const
{
return RiaWellLogUnitTools::noUnitString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -60,6 +60,7 @@ public:
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelUnits() const override;
void setEclipseResultCase( RimEclipseResultCase* eclipseResultCase );
RimEclipseResultCase* eclipseResultCase() const;

View File

@@ -278,6 +278,14 @@ QString RimWellMeasurementCurve::wellLogChannelUiName() const
return QString( "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellMeasurementCurve::wellLogChannelUnits() const
{
return RiaWellLogUnitTools::noUnitString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -49,6 +49,7 @@ public:
// Overrides from RimWellLogPlotCurve
QString wellName() const override;
QString wellLogChannelUiName() const override;
QString wellLogChannelUnits() const override;
protected:
// Overrides from RimWellLogCurve