#5470 Add normalized result for stress and POR-Bar

This commit is contained in:
Gaute Lindkvist
2020-02-11 10:11:15 +01:00
parent df14cfce06
commit 1a7d0a901c
5 changed files with 198 additions and 37 deletions

View File

@@ -103,6 +103,7 @@ RigFemPartResultsCollection::RigFemPartResultsCollection( RifGeoMechReaderInterf
m_cohesion = 10.0; m_cohesion = 10.0;
m_frictionAngleRad = cvf::Math::toRadians( 30.0 ); m_frictionAngleRad = cvf::Math::toRadians( 30.0 );
m_normalizationAirGap = 0.0;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -735,6 +736,10 @@ RigFemScalarResultFrames* RigFemPartResultsCollection::calculateTimeLapseResult(
frameCountProgress.incrementProgress(); frameCountProgress.incrementProgress();
calculateGammaFromFrames( partIndex, srcDataFrames, srcPORDataFrames, dstDataFrames, &frameCountProgress ); calculateGammaFromFrames( partIndex, srcDataFrames, srcPORDataFrames, dstDataFrames, &frameCountProgress );
if ( resVarAddr.normalizeByHydrostaticPressure() )
{
dstDataFrames = calculateNormalizedResult( partIndex, resVarAddr );
}
return dstDataFrames; return dstDataFrames;
} }
@@ -1203,6 +1208,77 @@ RigFemScalarResultFrames* RigFemPartResultsCollection::calculateNodalGradients(
return requestedGradient; return requestedGradient;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFemScalarResultFrames* RigFemPartResultsCollection::calculateNormalizedResult( int partIndex,
const RigFemResultAddress& resVarAddr )
{
CVF_ASSERT( resVarAddr.normalizeByHydrostaticPressure() && isNormalizableResult( resVarAddr ) );
RigFemResultAddress unscaledResult = resVarAddr;
unscaledResult.normalizedByHydrostaticPressure = false;
caf::ProgressInfo frameCountProgress( this->frameCount() * 3, "Calculating Normalized Result" );
RigFemScalarResultFrames* srcDataFrames = nullptr;
RigFemScalarResultFrames* dstDataFrames = nullptr;
{
auto task = frameCountProgress.task( "Loading Unscaled Result", this->frameCount() );
srcDataFrames = this->findOrLoadScalarResult( partIndex, unscaledResult );
if ( !srcDataFrames ) return nullptr;
}
{
auto task = frameCountProgress.task( "Creating Space for Normalized Result", this->frameCount() );
dstDataFrames = m_femPartResults[partIndex]->createScalarResult( RigFemResultAddress( resVarAddr ) );
if ( !dstDataFrames ) return nullptr;
}
frameCountProgress.setNextProgressIncrement( 1u );
const RigFemPart* femPart = m_femParts->part( partIndex );
float inf = std::numeric_limits<float>::infinity();
int elmNodeCount = femPart->elementCount();
const std::vector<cvf::Vec3f>& nodeCoords = femPart->nodes().coordinates;
int frameCount = srcDataFrames->frameCount();
for ( int fIdx = 0; fIdx < frameCount; ++fIdx )
{
const std::vector<float>& srcFrameData = srcDataFrames->frameData( fIdx );
std::vector<float>& dstFrameData = dstDataFrames->frameData( fIdx );
size_t resultCount = srcFrameData.size();
dstFrameData.resize( resultCount );
if ( resVarAddr.resultPosType == RIG_ELEMENT_NODAL )
{
#pragma omp parallel for schedule( dynamic )
for ( int elmNodeResIdx = 0; elmNodeResIdx < resultCount; ++elmNodeResIdx )
{
const int nodeIdx = femPart->nodeIdxFromElementNodeResultIdx( elmNodeResIdx );
const cvf::Vec3f node = nodeCoords[nodeIdx];
double tvdRKB = std::abs( node.z() ) + m_normalizationAirGap;
double hydrostaticPressure = RiaWellLogUnitTools::hydrostaticPorePressureBar( tvdRKB );
dstFrameData[elmNodeResIdx] = srcFrameData[elmNodeResIdx] / hydrostaticPressure;
}
}
else if ( resVarAddr.resultPosType == RIG_NODAL )
{
#pragma omp parallel for schedule( dynamic )
for ( int nodeResIdx = 0; nodeResIdx < resultCount; ++nodeResIdx )
{
const cvf::Vec3f node = nodeCoords[nodeResIdx];
double tvdRKB = std::abs( node.z() ) + m_normalizationAirGap;
double hydrostaticPressure = RiaWellLogUnitTools::hydrostaticPorePressureBar( tvdRKB );
dstFrameData[nodeResIdx] = srcFrameData[nodeResIdx] / hydrostaticPressure;
}
}
frameCountProgress.incrementProgress();
}
return dstDataFrames;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -2328,6 +2404,11 @@ RigFemScalarResultFrames* RigFemPartResultsCollection::calculateDerivedResult( i
return calculateTimeLapseResult( partIndex, resVarAddr ); return calculateTimeLapseResult( partIndex, resVarAddr );
} }
if ( resVarAddr.normalizeByHydrostaticPressure() )
{
return calculateNormalizedResult( partIndex, resVarAddr );
}
if ( resVarAddr.resultPosType == RIG_ELEMENT_NODAL_FACE ) if ( resVarAddr.resultPosType == RIG_ELEMENT_NODAL_FACE )
{ {
if ( resVarAddr.componentName == "Pazi" || resVarAddr.componentName == "Pinc" ) if ( resVarAddr.componentName == "Pazi" || resVarAddr.componentName == "Pinc" )
@@ -2941,6 +3022,69 @@ std::vector<RigFemResultAddress>
return addresses; return addresses;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigFemResultAddress> RigFemPartResultsCollection::normalizedResults()
{
std::set<std::string> validFields = {"SE", "ST"};
std::set<std::string> validComponents = {"S11", "S22", "S33", "S12", "S13", "S23", "S1", "S2", "S3", "Q"};
std::set<RigFemResultAddress> results;
for ( auto field : validFields )
{
for ( auto component : validComponents )
{
results.insert( RigFemResultAddress( RIG_ELEMENT_NODAL,
field,
component,
RigFemResultAddress::allTimeLapsesValue(),
-1,
true ) );
}
}
results.insert(
RigFemResultAddress( RIG_ELEMENT_NODAL, "SE", "SEM", RigFemResultAddress::allTimeLapsesValue(), -1, true ) );
results.insert(
RigFemResultAddress( RIG_ELEMENT_NODAL, "ST", "STM", RigFemResultAddress::allTimeLapsesValue(), -1, true ) );
results.insert( RigFemResultAddress( RIG_NODAL, "POR-Bar", "", RigFemResultAddress::allTimeLapsesValue(), -1, true ) );
results.insert(
RigFemResultAddress( RIG_ELEMENT_NODAL, "POR-Bar", "", RigFemResultAddress::allTimeLapsesValue(), -1, true ) );
return results;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFemPartResultsCollection::isNormalizableResult( const RigFemResultAddress& result )
{
for ( auto normRes : normalizedResults() )
{
if ( normRes.resultPosType == result.resultPosType && normRes.fieldName == result.fieldName &&
normRes.componentName == result.componentName )
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::setNormalizationAirGap( double normalizationAirGap )
{
if ( std::abs( m_normalizationAirGap - normalizationAirGap ) > 1.0e-8 )
{
for ( auto result : normalizedResults() )
{
this->deleteResult( result );
}
}
m_normalizationAirGap = normalizationAirGap;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@@ -121,6 +121,10 @@ public:
static std::vector<RigFemResultAddress> tensorComponentAddresses( const RigFemResultAddress& resVarAddr ); static std::vector<RigFemResultAddress> tensorComponentAddresses( const RigFemResultAddress& resVarAddr );
static std::vector<RigFemResultAddress> tensorPrincipalComponentAdresses( const RigFemResultAddress& resVarAddr ); static std::vector<RigFemResultAddress> tensorPrincipalComponentAdresses( const RigFemResultAddress& resVarAddr );
static std::set<RigFemResultAddress> normalizedResults();
static bool isNormalizableResult( const RigFemResultAddress& result );
void setNormalizationAirGap( double normalizationAirGap );
private: private:
RigFemScalarResultFrames* findOrLoadScalarResult( int partIndex, const RigFemResultAddress& resVarAddr ); RigFemScalarResultFrames* findOrLoadScalarResult( int partIndex, const RigFemResultAddress& resVarAddr );
@@ -159,6 +163,7 @@ private:
RigFemScalarResultFrames* calculateFormationIndices( int partIndex, const RigFemResultAddress& resVarAddr ); RigFemScalarResultFrames* calculateFormationIndices( int partIndex, const RigFemResultAddress& resVarAddr );
RigFemScalarResultFrames* calculateStressGradients( int partIndex, const RigFemResultAddress& resVarAddr ); RigFemScalarResultFrames* calculateStressGradients( int partIndex, const RigFemResultAddress& resVarAddr );
RigFemScalarResultFrames* calculateNodalGradients( int partIndex, const RigFemResultAddress& resVarAddr ); RigFemScalarResultFrames* calculateNodalGradients( int partIndex, const RigFemResultAddress& resVarAddr );
RigFemScalarResultFrames* calculateNormalizedResult( int partIndex, const RigFemResultAddress& resVarAddr );
const RigFormationNames* activeFormationNames() const; const RigFormationNames* activeFormationNames() const;
@@ -171,6 +176,7 @@ private:
double m_cohesion; double m_cohesion;
double m_frictionAngleRad; double m_frictionAngleRad;
double m_normalizationAirGap;
RigStatisticsDataCache* statistics( const RigFemResultAddress& resVarAddr ); RigStatisticsDataCache* statistics( const RigFemResultAddress& resVarAddr );
std::vector<RigFemResultAddress> getResAddrToComponentsToRead( const RigFemResultAddress& resVarAddr ); std::vector<RigFemResultAddress> getResAddrToComponentsToRead( const RigFemResultAddress& resVarAddr );

View File

@@ -35,6 +35,7 @@ public:
, componentName( "" ) , componentName( "" )
, timeLapseBaseFrameIdx( NO_TIME_LAPSE ) , timeLapseBaseFrameIdx( NO_TIME_LAPSE )
, refKLayerIndex( NO_COMPACTION ) , refKLayerIndex( NO_COMPACTION )
, normalizedByHydrostaticPressure( false )
{ {
} }
@@ -42,12 +43,14 @@ public:
const std::string& aFieldName, const std::string& aFieldName,
const std::string& aComponentName, const std::string& aComponentName,
int timeLapseBaseFrameIdx = NO_TIME_LAPSE, int timeLapseBaseFrameIdx = NO_TIME_LAPSE,
int refKLayerIndex = NO_COMPACTION ) int refKLayerIndex = NO_COMPACTION,
bool normalizedByHydrostaticPressure = false )
: resultPosType( resPosType ) : resultPosType( resPosType )
, fieldName( aFieldName ) , fieldName( aFieldName )
, componentName( aComponentName ) , componentName( aComponentName )
, timeLapseBaseFrameIdx( timeLapseBaseFrameIdx ) , timeLapseBaseFrameIdx( timeLapseBaseFrameIdx )
, refKLayerIndex( refKLayerIndex ) , refKLayerIndex( refKLayerIndex )
, normalizedByHydrostaticPressure( normalizedByHydrostaticPressure )
{ {
} }
@@ -56,6 +59,7 @@ public:
std::string componentName; std::string componentName;
int timeLapseBaseFrameIdx; int timeLapseBaseFrameIdx;
int refKLayerIndex; int refKLayerIndex;
bool normalizedByHydrostaticPressure;
static constexpr int allTimeLapsesValue() static constexpr int allTimeLapsesValue()
{ {
@@ -78,6 +82,10 @@ public:
{ {
return timeLapseBaseFrameIdx == ALL_TIME_LAPSES; return timeLapseBaseFrameIdx == ALL_TIME_LAPSES;
} }
bool normalizeByHydrostaticPressure() const
{
return normalizedByHydrostaticPressure;
}
bool isValid() const bool isValid() const
{ {
@@ -92,6 +100,11 @@ public:
bool operator<( const RigFemResultAddress& other ) const bool operator<( const RigFemResultAddress& other ) const
{ {
if ( normalizedByHydrostaticPressure != other.normalizedByHydrostaticPressure )
{
return ( normalizedByHydrostaticPressure < other.normalizedByHydrostaticPressure );
}
if ( timeLapseBaseFrameIdx != other.timeLapseBaseFrameIdx ) if ( timeLapseBaseFrameIdx != other.timeLapseBaseFrameIdx )
{ {
return ( timeLapseBaseFrameIdx < other.timeLapseBaseFrameIdx ); return ( timeLapseBaseFrameIdx < other.timeLapseBaseFrameIdx );
@@ -118,7 +131,8 @@ public:
bool operator==( const RigFemResultAddress& other ) const bool operator==( const RigFemResultAddress& other ) const
{ {
if ( resultPosType != other.resultPosType || fieldName != other.fieldName || if ( resultPosType != other.resultPosType || fieldName != other.fieldName ||
componentName != other.componentName || timeLapseBaseFrameIdx != other.timeLapseBaseFrameIdx ) componentName != other.componentName || timeLapseBaseFrameIdx != other.timeLapseBaseFrameIdx ||
normalizedByHydrostaticPressure != other.normalizedByHydrostaticPressure )
{ {
return false; return false;
} }

View File

@@ -114,8 +114,8 @@ RimGeoMechResultDefinition::RimGeoMechResultDefinition( void )
"", "",
"", "",
"" ); "" );
CAF_PDM_InitField( &m_normalizationRkbDiff, "NormalizationRkbDiff", -1.0, "Air Gap", "", "", "" ); CAF_PDM_InitField( &m_normalizationAirGap, "NormalizationAirGap", -1.0, "Air Gap", "", "", "" );
m_normalizationRkbDiff.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() ); m_normalizationAirGap.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_compactionRefLayerUiField, CAF_PDM_InitField( &m_compactionRefLayerUiField,
"CompactionRefLayerUi", "CompactionRefLayerUi",
@@ -163,7 +163,7 @@ void RimGeoMechResultDefinition::defineUiOrdering( QString uiConfigName, caf::Pd
normalizationGroup->add( &m_normalizeByHydrostaticPressure ); normalizationGroup->add( &m_normalizeByHydrostaticPressure );
if ( m_normalizeByHydrostaticPressure ) if ( m_normalizeByHydrostaticPressure )
{ {
normalizationGroup->add( &m_normalizationRkbDiff ); normalizationGroup->add( &m_normalizationAirGap );
} }
} }
@@ -338,30 +338,35 @@ void RimGeoMechResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* ch
m_resultVariableUiField = ""; m_resultVariableUiField = "";
} }
} }
if ( &m_normalizeByHydrostaticPressure == changedField && m_normalizationRkbDiff < 0.0 ) if ( &m_normalizeByHydrostaticPressure == changedField && m_normalizationAirGap < 0.0 )
{ {
RiaMedianCalculator<double> rkbDiffCalc; RiaMedianCalculator<double> airGapCalc;
for ( auto wellPath : RiaApplication::instance()->project()->allWellPaths() ) for ( auto wellPath : RiaApplication::instance()->project()->allWellPaths() )
{ {
if ( wellPath->wellPathGeometry() ) if ( wellPath->wellPathGeometry() )
{ {
double rkbDiff = wellPath->wellPathGeometry()->rkbDiff(); double airGap = wellPath->wellPathGeometry()->rkbDiff();
if ( rkbDiff > 0.0 ) if ( airGap > 0.0 )
{ {
rkbDiffCalc.add( rkbDiff ); airGapCalc.add( airGap );
} }
} }
} }
if ( rkbDiffCalc.valid() ) if ( airGapCalc.valid() )
{ {
m_normalizationRkbDiff = rkbDiffCalc.median(); m_normalizationAirGap = airGapCalc.median();
} }
else else
{ {
m_normalizationRkbDiff = 0.0; m_normalizationAirGap = 0.0;
} }
} }
if ( m_normalizeByHydrostaticPressure && m_normalizationAirGap >= 0.0 )
{
m_geomCase->geoMechData()->femPartResults()->setNormalizationAirGap( m_normalizationAirGap );
}
// Get the possible property filter owner // Get the possible property filter owner
RimGeoMechPropertyFilter* propFilter = dynamic_cast<RimGeoMechPropertyFilter*>( this->parentField()->ownerObject() ); RimGeoMechPropertyFilter* propFilter = dynamic_cast<RimGeoMechPropertyFilter*>( this->parentField()->ownerObject() );
RimGridView* view = nullptr; RimGridView* view = nullptr;
@@ -372,7 +377,8 @@ void RimGeoMechResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* ch
this->firstAncestorOrThisOfType( rim3dWellLogCurve ); this->firstAncestorOrThisOfType( rim3dWellLogCurve );
if ( &m_resultVariableUiField == changedField || &m_compactionRefLayerUiField == changedField || if ( &m_resultVariableUiField == changedField || &m_compactionRefLayerUiField == changedField ||
&m_timeLapseBaseTimestep == changedField ) &m_timeLapseBaseTimestep == changedField || &m_normalizeByHydrostaticPressure == changedField ||
&m_normalizationAirGap == changedField )
{ {
QStringList fieldComponentNames = m_resultVariableUiField().split( QRegExp( "\\s+" ) ); QStringList fieldComponentNames = m_resultVariableUiField().split( QRegExp( "\\s+" ) );
if ( fieldComponentNames.size() > 0 ) if ( fieldComponentNames.size() > 0 )
@@ -535,7 +541,7 @@ void RimGeoMechResultDefinition::defineEditorAttribute( const caf::PdmFieldHandl
QString uiConfigName, QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) caf::PdmUiEditorAttribute* attribute )
{ {
if ( field == &m_normalizationRkbDiff ) if ( field == &m_normalizationAirGap )
{ {
auto attr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute ); auto attr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
if ( attr ) if ( attr )
@@ -604,7 +610,8 @@ RigFemResultAddress RimGeoMechResultDefinition::resultAddress() const
m_timeLapseBaseTimestep(), m_timeLapseBaseTimestep(),
resultFieldName().toStdString() == RigFemPartResultsCollection::FIELD_NAME_COMPACTION resultFieldName().toStdString() == RigFemPartResultsCollection::FIELD_NAME_COMPACTION
? m_compactionRefLayer() ? m_compactionRefLayer()
: RigFemResultAddress::noCompactionValue() ); : RigFemResultAddress::noCompactionValue(),
m_normalizeByHydrostaticPressure );
} }
} }
@@ -808,18 +815,7 @@ QString RimGeoMechResultDefinition::convertToUiResultFieldName( QString resultFi
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
bool RimGeoMechResultDefinition::normalizableResultSelected() const bool RimGeoMechResultDefinition::normalizableResultSelected() const
{ {
if ( m_resultPositionType == RIG_NODAL ) return RigFemPartResultsCollection::isNormalizableResult( this->resultAddress() );
{
return m_resultFieldName == "POR-Bar";
}
else if ( m_resultPositionType == RIG_ELEMENT_NODAL && ( m_resultFieldName == "ST" || m_resultFieldName == "SE" ) )
{
static const std::set<QString> validComponents =
{"S11", "S22", "S33", "S12", "S13", "S23", "S1", "S2", "S3", "Q", "STM", "SEM"};
return validComponents.count( m_resultComponentName );
}
return false;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -832,6 +828,7 @@ void RimGeoMechResultDefinition::setResultAddress( const RigFemResultAddress& re
m_resultComponentName = QString::fromStdString( resultAddress.componentName ); m_resultComponentName = QString::fromStdString( resultAddress.componentName );
m_timeLapseBaseTimestep = resultAddress.timeLapseBaseFrameIdx; m_timeLapseBaseTimestep = resultAddress.timeLapseBaseFrameIdx;
m_compactionRefLayer = resultAddress.refKLayerIndex; m_compactionRefLayer = resultAddress.refKLayerIndex;
m_normalizeByHydrostaticPressure = resultAddress.normalizedByHydrostaticPressure;
m_resultPositionTypeUiField = m_resultPositionType; m_resultPositionTypeUiField = m_resultPositionType;
m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() ); m_resultVariableUiField = composeFieldCompString( m_resultFieldName(), m_resultComponentName() );

View File

@@ -118,7 +118,7 @@ private:
caf::PdmField<int> m_timeLapseBaseTimestep; caf::PdmField<int> m_timeLapseBaseTimestep;
caf::PdmField<int> m_compactionRefLayer; caf::PdmField<int> m_compactionRefLayer;
caf::PdmField<bool> m_normalizeByHydrostaticPressure; caf::PdmField<bool> m_normalizeByHydrostaticPressure;
caf::PdmField<double> m_normalizationRkbDiff; caf::PdmField<double> m_normalizationAirGap;
// UI Fields only // UI Fields only
friend class RimGeoMechPropertyFilter; // Property filter needs the ui fields friend class RimGeoMechPropertyFilter; // Property filter needs the ui fields