Merge pull request #6274 from OPM/mud-weight-window-6213

Mud weight window 6213
This commit is contained in:
Kristian Bendiksen 2020-08-07 16:21:44 +02:00 committed by GitHub
commit 985ad52806
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1347 additions and 11 deletions

View File

@ -96,6 +96,8 @@ add_library( ${PROJECT_NAME}
RigFemPartResultCalculatorPoreCompressibility.cpp
RigFemPartResultCalculatorPorosityPermeability.h
RigFemPartResultCalculatorPorosityPermeability.cpp
RigFemPartResultCalculatorMudWeightWindow.h
RigFemPartResultCalculatorMudWeightWindow.cpp
RimGeoMechGeometrySelectionItem.h
RimGeoMechGeometrySelectionItem.cpp
)

View File

@ -0,0 +1,437 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigFemPartResultCalculatorMudWeightWindow.h"
#include "RigFemPart.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
#include "RigFemPartResultsCollection.h"
#include "RigFemResultAddress.h"
#include "RigFemScalarResultFrames.h"
#include "RigGeoMechBoreHoleStressCalculator.h"
#include "RigGeoMechWellLogExtractor.h"
#include "RiaOffshoreSphericalCoords.h"
#include "cafProgressInfo.h"
#include "cvfBoundingBox.h"
#include <QString>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFemPartResultCalculatorMudWeightWindow::RigFemPartResultCalculatorMudWeightWindow( RigFemPartResultsCollection& collection )
: RigFemPartResultCalculator( collection )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFemPartResultCalculatorMudWeightWindow::~RigFemPartResultCalculatorMudWeightWindow()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigFemPartResultCalculatorMudWeightWindow::isMatching( const RigFemResultAddress& resVarAddr ) const
{
return ( resVarAddr.fieldName == "MUD-WEIGHT" &&
( resVarAddr.componentName == "MWW" || resVarAddr.componentName == "MWM" ||
resVarAddr.componentName == "UMWL" || resVarAddr.componentName == "LMWL" ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigFemScalarResultFrames* RigFemPartResultCalculatorMudWeightWindow::calculate( int partIndex,
const RigFemResultAddress& resVarAddr )
{
CVF_ASSERT( isMatching( resVarAddr ) );
const std::vector<RimMudWeightWindowParameters::ParameterType> parameterTypes =
{RimMudWeightWindowParameters::ParameterType::WELL_DEVIATION,
RimMudWeightWindowParameters::ParameterType::WELL_AZIMUTH,
RimMudWeightWindowParameters::ParameterType::UCS,
RimMudWeightWindowParameters::ParameterType::POISSONS_RATIO,
RimMudWeightWindowParameters::ParameterType::K0_FG};
caf::ProgressInfo frameCountProgress( m_resultCollection->frameCount() * ( 4 + parameterTypes.size() ), "" );
frameCountProgress.setProgressDescription( "Calculating Mud Weight Window" );
std::map<RimMudWeightWindowParameters::ParameterType, RigFemScalarResultFrames*> parameterFrames;
std::map<RimMudWeightWindowParameters::ParameterType, float> parameterValues;
for ( auto parameterType : parameterTypes )
{
frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() );
loadParameterFramesOrValue( parameterType, partIndex, parameterFrames, parameterValues );
frameCountProgress.incrementProgress();
}
double airGap = m_resultCollection->airGapMudWeightWindow();
RimMudWeightWindowParameters::UpperLimitType upperLimitParameter =
m_resultCollection->upperLimitParameterMudWeightWindow();
RimMudWeightWindowParameters::LowerLimitType lowerLimitParameter =
m_resultCollection->lowerLimitParameterMudWeightWindow();
// Pore pressure
frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() );
RigFemScalarResultFrames* porePressureDataFrames =
m_resultCollection->findOrLoadScalarResult( partIndex, RigFemResultAddress( RIG_NODAL, "POR-Bar", "" ) );
frameCountProgress.incrementProgress();
// Stress (ST.S3)
frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() );
RigFemScalarResultFrames* stressDataFrames =
m_resultCollection->findOrLoadScalarResult( partIndex, RigFemResultAddress( resVarAddr.resultPosType, "ST", "S3" ) );
frameCountProgress.incrementProgress();
frameCountProgress.setNextProgressIncrement( m_resultCollection->frameCount() );
RigFemScalarResultFrames* mudWeightWindowFrames =
m_resultCollection->createScalarResult( partIndex,
RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "MWW" ) );
RigFemScalarResultFrames* mudWeightMiddleFrames =
m_resultCollection->createScalarResult( partIndex,
RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "MWM" ) );
RigFemScalarResultFrames* upperMudWeightLimitFrames =
m_resultCollection->createScalarResult( partIndex,
RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "UMWL" ) );
RigFemScalarResultFrames* lowerMudWeightLimitFrames =
m_resultCollection->createScalarResult( partIndex,
RigFemResultAddress( resVarAddr.resultPosType, resVarAddr.fieldName, "LMWL" ) );
frameCountProgress.incrementProgress();
const RigFemPart* femPart = m_resultCollection->parts()->part( partIndex );
const RigFemPartGrid* femPartGrid = femPart->getOrCreateStructGrid();
float inf = std::numeric_limits<float>::infinity();
frameCountProgress.setNextProgressIncrement( 1u );
int frameCount = stressDataFrames->frameCount();
for ( int fIdx = 0; fIdx < frameCount; ++fIdx )
{
const std::vector<float>& porFrameData = porePressureDataFrames->frameData( fIdx );
const std::vector<float>& stressFrameData = stressDataFrames->frameData( fIdx );
std::vector<float>& mudWeightWindowFrameData = mudWeightWindowFrames->frameData( fIdx );
std::vector<float>& mudWeightMiddleFrameData = mudWeightMiddleFrames->frameData( fIdx );
std::vector<float>& upperMudWeightLimitFrameData = upperMudWeightLimitFrames->frameData( fIdx );
std::vector<float>& lowerMudWeightLimitFrameData = lowerMudWeightLimitFrames->frameData( fIdx );
size_t valCount = stressFrameData.size();
mudWeightWindowFrameData.resize( valCount );
mudWeightMiddleFrameData.resize( valCount );
upperMudWeightLimitFrameData.resize( valCount );
lowerMudWeightLimitFrameData.resize( valCount );
int elementCount = femPart->elementCount();
std::map<RimMudWeightWindowParameters::ParameterType, std::vector<float>> parameterFrameData;
for ( auto parameterType : parameterTypes )
{
parameterFrameData[parameterType] = loadDataForFrame( parameterType, parameterFrames, fIdx );
}
// Load stress
RigFemResultAddress stressResAddr( RIG_ELEMENT_NODAL, "ST", "" );
std::vector<caf::Ten3f> vertexStressesFloat = m_resultCollection->tensors( stressResAddr, partIndex, fIdx );
std::vector<caf::Ten3d> vertexStresses;
vertexStresses.reserve( vertexStressesFloat.size() );
for ( const caf::Ten3f& floatTensor : vertexStressesFloat )
{
vertexStresses.push_back( caf::Ten3d( floatTensor ) );
}
#pragma omp parallel for
for ( int elmIdx = 0; elmIdx < elementCount; ++elmIdx )
{
RigElementType elmType = femPart->elementType( elmIdx );
double wellPathDeviation = getValueForElement( RimMudWeightWindowParameters::ParameterType::WELL_DEVIATION,
parameterFrameData,
parameterValues,
elmIdx );
double wellPathAzimuth = getValueForElement( RimMudWeightWindowParameters::ParameterType::WELL_AZIMUTH,
parameterFrameData,
parameterValues,
elmIdx );
double ucsBar = getValueForElement( RimMudWeightWindowParameters::ParameterType::UCS,
parameterFrameData,
parameterValues,
elmIdx );
double poissonsRatio = getValueForElement( RimMudWeightWindowParameters::ParameterType::POISSONS_RATIO,
parameterFrameData,
parameterValues,
elmIdx );
double K0_FG = getValueForElement( RimMudWeightWindowParameters::ParameterType::K0_FG,
parameterFrameData,
parameterValues,
elmIdx );
int elmNodeCount = RigFemTypes::elementNodeCount( femPart->elementType( elmIdx ) );
if ( elmType == HEX8P )
{
for ( int elmNodIdx = 0; elmNodIdx < elmNodeCount; ++elmNodIdx )
{
// Use hydrostatic pressure from cell centroid.
// Use centroid to avoid intra-element differences
cvf::Vec3d cellCentroid = femPartGrid->cellCentroid( elmIdx );
double cellCentroidTvdRKB = std::abs( cellCentroid.z() ) + airGap;
double cellCenterHydroStaticPressure =
RiaWellLogUnitTools<double>::hydrostaticPorePressureBar( cellCentroidTvdRKB );
size_t elmNodResIdx = femPart->elementNodeResultIdx( elmIdx, elmNodIdx );
if ( elmNodResIdx < stressFrameData.size() )
{
int nodeIdx = femPart->nodeIdxFromElementNodeResultIdx( elmNodResIdx );
// Pore pressure (unit: Bar)
double porePressureBar = porFrameData[nodeIdx];
// FG is for sands, SFG for shale. Sands has valid PP, shale does not.
bool isSand = ( porePressureBar != inf );
caf::Ten3d segmentStress = caf::Ten3d( vertexStressesFloat[nodeIdx] );
cvf::Vec3d wellPathTangent = calculateWellPathTangent( wellPathAzimuth, wellPathDeviation );
caf::Ten3d wellPathStressFloat =
RigGeoMechWellLogExtractor::transformTensorToWellPathOrientation( wellPathTangent,
segmentStress );
caf::Ten3d wellPathStressDouble( wellPathStressFloat );
RigGeoMechBoreHoleStressCalculator sigmaCalculator( wellPathStressDouble,
porePressureBar,
poissonsRatio,
ucsBar,
32 );
// Calculate upper limit
float upperLimit = inf;
if ( upperLimitParameter == RimMudWeightWindowParameters::UpperLimitType::FG )
{
upperLimit = sigmaCalculator.solveFractureGradient();
}
else if ( upperLimitParameter == RimMudWeightWindowParameters::UpperLimitType::SH_MIN )
{
upperLimit = stressFrameData[elmNodResIdx];
}
// Calculate lower limit
float lowerLimit = inf;
if ( lowerLimitParameter == RimMudWeightWindowParameters::LowerLimitType::PORE_PRESSURE )
{
lowerLimit = porePressureBar;
}
else if ( lowerLimitParameter ==
RimMudWeightWindowParameters::LowerLimitType::MAX_OF_PORE_PRESSURE_AND_SFG )
{
if ( isSand )
{
lowerLimit = porePressureBar;
}
else
{
double SFG = sigmaCalculator.solveStassiDalia();
lowerLimit = std::max( porePressureBar, SFG );
}
}
// Normalize by hydrostatic pore pressure
upperMudWeightLimitFrameData[elmNodResIdx] = upperLimit / cellCenterHydroStaticPressure;
lowerMudWeightLimitFrameData[elmNodResIdx] = lowerLimit / cellCenterHydroStaticPressure;
}
}
}
else
{
for ( int elmNodIdx = 0; elmNodIdx < elmNodeCount; ++elmNodIdx )
{
size_t elmNodResIdx = femPart->elementNodeResultIdx( elmIdx, elmNodIdx );
if ( elmNodResIdx < stressFrameData.size() )
{
mudWeightWindowFrameData[elmNodResIdx] = inf;
mudWeightMiddleFrameData[elmNodResIdx] = inf;
upperMudWeightLimitFrameData[elmNodResIdx] = inf;
lowerMudWeightLimitFrameData[elmNodResIdx] = inf;
}
}
}
}
size_t kRefLayer = m_resultCollection->referenceLayerMudWeightWindow();
#pragma omp parallel for
for ( int elmIdx = 0; elmIdx < elementCount; ++elmIdx )
{
RigElementType elmType = femPart->elementType( elmIdx );
int elmNodeCount = RigFemTypes::elementNodeCount( femPart->elementType( elmIdx ) );
size_t i, j, k;
bool validIndex = femPartGrid->ijkFromCellIndex( elmIdx, &i, &j, &k );
size_t kMin = std::min( k, kRefLayer );
size_t kMax = std::max( k, kRefLayer );
if ( elmType == HEX8P && validIndex )
{
for ( int elmNodIdx = 0; elmNodIdx < elmNodeCount; ++elmNodIdx )
{
size_t elmNodResIdx = femPart->elementNodeResultIdx( elmIdx, elmNodIdx );
float maxLowerMudWeightLimit = lowerMudWeightLimitFrameData[elmNodResIdx];
float minUpperMudWeightLimit = upperMudWeightLimitFrameData[elmNodResIdx];
for ( size_t currentK = kMin; currentK < kMax; currentK++ )
{
size_t kElmIdx = femPartGrid->cellIndexFromIJK( i, j, currentK );
if ( kElmIdx != cvf::UNDEFINED_SIZE_T && femPart->elementType( kElmIdx ) == HEX8P )
{
size_t kElmNodResIdx = femPart->elementNodeResultIdx( kElmIdx, elmNodIdx );
float currentLowerMudWeightLimit = lowerMudWeightLimitFrameData[kElmNodResIdx];
if ( currentLowerMudWeightLimit > maxLowerMudWeightLimit )
{
maxLowerMudWeightLimit = currentLowerMudWeightLimit;
}
float currentUpperMudWeightLimit = upperMudWeightLimitFrameData[kElmNodResIdx];
if ( currentUpperMudWeightLimit < minUpperMudWeightLimit )
{
minUpperMudWeightLimit = currentUpperMudWeightLimit;
}
}
}
float mudWeightWindow = minUpperMudWeightLimit - maxLowerMudWeightLimit;
mudWeightWindowFrameData[elmNodResIdx] = mudWeightWindow;
float mudWeightMiddle = inf;
if ( mudWeightWindow > 0.0 )
{
mudWeightMiddle = maxLowerMudWeightLimit + mudWeightWindow / 2.0;
}
mudWeightMiddleFrameData[elmNodResIdx] = mudWeightMiddle;
}
}
}
frameCountProgress.incrementProgress();
}
RigFemScalarResultFrames* requestedResultFrames = m_resultCollection->findOrLoadScalarResult( partIndex, resVarAddr );
return requestedResultFrames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Vec3d RigFemPartResultCalculatorMudWeightWindow::calculateWellPathTangent( double azimuth, double inclination )
{
double aziRad = cvf::Math::toRadians( azimuth );
double incRad = cvf::Math::toRadians( inclination );
return RiaOffshoreSphericalCoords::unitVectorFromAziInc( aziRad, incRad );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultCalculatorMudWeightWindow::loadParameterFramesOrValue(
RimMudWeightWindowParameters::ParameterType parameterType,
size_t partIndex,
std::map<RimMudWeightWindowParameters::ParameterType, RigFemScalarResultFrames*>& parameterFrames,
std::map<RimMudWeightWindowParameters::ParameterType, float>& parameterValues )
{
RigFemScalarResultFrames* resultFrames = nullptr;
QString resultAddress = m_resultCollection->getCalculationParameterAddress( parameterType );
if ( !resultAddress.isEmpty() )
{
resultFrames =
m_resultCollection->findOrLoadScalarResult( partIndex,
RigFemResultAddress( RIG_ELEMENT, resultAddress.toStdString(), "" ) );
parameterFrames[parameterType] = resultFrames;
}
parameterValues[parameterType] = m_resultCollection->getCalculationParameterValue( parameterType );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<float> RigFemPartResultCalculatorMudWeightWindow::loadDataForFrame(
RimMudWeightWindowParameters::ParameterType parameterType,
std::map<RimMudWeightWindowParameters::ParameterType, RigFemScalarResultFrames*>& parameterFrames,
int frameIndex )
{
auto it = parameterFrames.find( parameterType );
if ( it != parameterFrames.end() )
{
RigFemScalarResultFrames* frame = it->second;
std::vector<float> dataForFrame = frame->frameData( frameIndex );
return dataForFrame;
}
else
{
return std::vector<float>();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
float RigFemPartResultCalculatorMudWeightWindow::getValueForElement(
RimMudWeightWindowParameters::ParameterType parameterType,
const std::map<RimMudWeightWindowParameters::ParameterType, std::vector<float>>& parameterFrameData,
const std::map<RimMudWeightWindowParameters::ParameterType, float> parameterValues,
int elmIdx )
{
// Use data per element if available
auto it = parameterFrameData.find( parameterType );
if ( it != parameterFrameData.end() )
{
if ( !it->second.empty() && static_cast<size_t>( elmIdx ) < it->second.size() )
{
return it->second[elmIdx];
}
}
// Use fixed value
auto value = parameterValues.find( parameterType );
if ( value != parameterValues.end() )
{
return value->second;
}
else
{
// No value found (should not happen)
return std::numeric_limits<float>::infinity();
}
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RigFemPartResultCalculator.h"
#include "RimMudWeightWindowParameters.h"
#include "cvfVector3.h"
#include <map>
class RigFemPartResultsCollection;
class RigFemScalarResultFrames;
class RigFemResultAddress;
//==================================================================================================
///
//==================================================================================================
class RigFemPartResultCalculatorMudWeightWindow : public RigFemPartResultCalculator
{
public:
explicit RigFemPartResultCalculatorMudWeightWindow( RigFemPartResultsCollection& collection );
virtual ~RigFemPartResultCalculatorMudWeightWindow();
bool isMatching( const RigFemResultAddress& resVarAddr ) const override;
RigFemScalarResultFrames* calculate( int partIndex, const RigFemResultAddress& resVarAddr ) override;
cvf::Vec3d calculateWellPathTangent( double azimuth, double inclination );
private:
void loadParameterFramesOrValue( RimMudWeightWindowParameters::ParameterType parameterType,
size_t partIndex,
std::map<RimMudWeightWindowParameters::ParameterType, RigFemScalarResultFrames*>& parameterFrames,
std::map<RimMudWeightWindowParameters::ParameterType, float>& parameterValues );
static std::vector<float>
loadDataForFrame( RimMudWeightWindowParameters::ParameterType parameterType,
std::map<RimMudWeightWindowParameters::ParameterType, RigFemScalarResultFrames*>& parameterFrames,
int frameIndex );
static float
getValueForElement( RimMudWeightWindowParameters::ParameterType parameterType,
const std::map<RimMudWeightWindowParameters::ParameterType, std::vector<float>>& parameterFrameData,
const std::map<RimMudWeightWindowParameters::ParameterType, float> parameterValues,
int elmIdx );
};

View File

@ -39,6 +39,7 @@
#include "RigFemPartResultCalculatorFOS.h"
#include "RigFemPartResultCalculatorFormationIndices.h"
#include "RigFemPartResultCalculatorGamma.h"
#include "RigFemPartResultCalculatorMudWeightWindow.h"
#include "RigFemPartResultCalculatorNE.h"
#include "RigFemPartResultCalculatorNodalGradients.h"
#include "RigFemPartResultCalculatorNormalSE.h"
@ -118,6 +119,9 @@ RigFemPartResultsCollection::RigFemPartResultsCollection( RifGeoMechReaderInterf
m_initialPermeabilityResultAddress = "";
m_permeabilityExponent = 1.0;
m_airGapMudWeightWindow = 0.0;
m_referenceLayerMudWeightWindow = 0;
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorTimeLapse( *this ) ) );
m_resultCalculators.push_back(
@ -173,6 +177,8 @@ RigFemPartResultsCollection::RigFemPartResultsCollection( RifGeoMechReaderInterf
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorPoreCompressibility( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorPorosityPermeability( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorMudWeightWindow( *this ) ) );
m_resultCalculators.push_back(
std::unique_ptr<RigFemPartResultCalculator>( new RigFemPartResultCalculatorFormationIndices( *this ) ) );
}
@ -707,6 +713,11 @@ std::map<std::string, std::vector<std::string>>
fieldCompNames["PORO-PERM"].push_back( "PHI" );
fieldCompNames["PORO-PERM"].push_back( "DPHI" );
fieldCompNames["PORO-PERM"].push_back( "PERM" );
fieldCompNames["MUD-WEIGHT"].push_back( "MWW" );
fieldCompNames["MUD-WEIGHT"].push_back( "MWM" );
fieldCompNames["MUD-WEIGHT"].push_back( "UMWL" );
fieldCompNames["MUD-WEIGHT"].push_back( "LMWL" );
}
else if ( resPos == RIG_INTEGRATION_POINT )
{
@ -790,6 +801,11 @@ std::map<std::string, std::vector<std::string>>
fieldCompNames["PORO-PERM"].push_back( "PHI" );
fieldCompNames["PORO-PERM"].push_back( "DPHI" );
fieldCompNames["PORO-PERM"].push_back( "PERM" );
fieldCompNames["MUD-WEIGHT"].push_back( "MWW" );
fieldCompNames["MUD-WEIGHT"].push_back( "MWM" );
fieldCompNames["MUD-WEIGHT"].push_back( "UMWL" );
fieldCompNames["MUD-WEIGHT"].push_back( "LMWL" );
}
else if ( resPos == RIG_ELEMENT_NODAL_FACE )
{
@ -1325,6 +1341,23 @@ std::set<RigFemResultAddress> RigFemPartResultsCollection::referenceCaseDependen
return results;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RigFemResultAddress> RigFemPartResultsCollection::mudWeightWindowResults()
{
std::set<RigFemResultAddress> results;
for ( auto elmType : {RIG_ELEMENT_NODAL, RIG_INTEGRATION_POINT} )
{
results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "MWW", RigFemResultAddress::allTimeLapsesValue() ) );
results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "MWM", RigFemResultAddress::allTimeLapsesValue() ) );
results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "UMWL", RigFemResultAddress::allTimeLapsesValue() ) );
results.insert( RigFemResultAddress( elmType, "MUD-WEIGHT", "LMWL", RigFemResultAddress::allTimeLapsesValue() ) );
}
return results;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1606,3 +1639,102 @@ bool RigFemPartResultsCollection::isValidBiotData( const std::vector<float>& bio
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::setCalculationParameters( RimMudWeightWindowParameters::ParameterType parameterType,
const QString& address,
double value )
{
parameterAddresses[parameterType] = address;
parameterValues[parameterType] = value;
// Invalidate dependent results
for ( auto result : mudWeightWindowResults() )
{
this->deleteResult( result );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFemPartResultsCollection::getCalculationParameterValue( RimMudWeightWindowParameters::ParameterType parameterType ) const
{
auto it = parameterValues.find( parameterType );
if ( it != parameterValues.end() )
return it->second;
else
{
// TODO: log error maybe?
return 1.0;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RigFemPartResultsCollection::getCalculationParameterAddress( RimMudWeightWindowParameters::ParameterType parameterType ) const
{
auto it = parameterAddresses.find( parameterType );
if ( it != parameterAddresses.end() )
return it->second;
else
{
// TODO: log error maybe?
return QString();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigFemPartResultsCollection::airGapMudWeightWindow() const
{
return m_airGapMudWeightWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::UpperLimitType RigFemPartResultsCollection::upperLimitParameterMudWeightWindow() const
{
return m_upperLimitParameterMudWeightWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::LowerLimitType RigFemPartResultsCollection::lowerLimitParameterMudWeightWindow() const
{
return m_lowerLimitParameterMudWeightWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RigFemPartResultsCollection::referenceLayerMudWeightWindow() const
{
return m_referenceLayerMudWeightWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigFemPartResultsCollection::setMudWeightWindowParameters( double airGap,
RimMudWeightWindowParameters::UpperLimitType upperLimit,
RimMudWeightWindowParameters::LowerLimitType lowerLimit,
int referenceLayer )
{
m_airGapMudWeightWindow = airGap;
m_upperLimitParameterMudWeightWindow = upperLimit;
m_lowerLimitParameterMudWeightWindow = lowerLimit;
m_referenceLayerMudWeightWindow = referenceLayer;
// Invalidate dependent results
for ( auto result : mudWeightWindowResults() )
{
this->deleteResult( result );
}
}

View File

@ -21,6 +21,8 @@
#include "RigFemResultAddress.h"
#include "RimMudWeightWindowParameters.h"
#include "cafTensor3.h"
#include "cvfCollection.h"
@ -80,6 +82,21 @@ public:
QString initialPermeabilityAddress() const;
double permeabilityExponent() const;
void setCalculationParameters( RimMudWeightWindowParameters::ParameterType parameterType,
const QString& address,
double value );
double getCalculationParameterValue( RimMudWeightWindowParameters::ParameterType ) const;
QString getCalculationParameterAddress( RimMudWeightWindowParameters::ParameterType ) const;
void setMudWeightWindowParameters( double airGap,
RimMudWeightWindowParameters::UpperLimitType upperLimit,
RimMudWeightWindowParameters::LowerLimitType lowerLimit,
int referenceLayer );
double airGapMudWeightWindow() const;
RimMudWeightWindowParameters::UpperLimitType upperLimitParameterMudWeightWindow() const;
RimMudWeightWindowParameters::LowerLimitType lowerLimitParameterMudWeightWindow() const;
size_t referenceLayerMudWeightWindow() const;
std::map<std::string, std::vector<std::string>> scalarFieldAndComponentNames( RigFemResultPosEnum resPos );
std::vector<std::string> filteredStepNames() const;
bool assertResultsLoaded( const RigFemResultAddress& resVarAddr );
@ -144,6 +161,7 @@ public:
static bool isReferenceCaseDependentResult( const RigFemResultAddress& result );
static std::set<RigFemResultAddress> initialPermeabilityDependentResults();
static std::set<RigFemResultAddress> mudWeightWindowResults();
RigFemScalarResultFrames* findOrLoadScalarResult( int partIndex, const RigFemResultAddress& resVarAddr );
RigFemScalarResultFrames* createScalarResult( int partIndex, const RigFemResultAddress& resVarAddr );
@ -178,6 +196,14 @@ private:
int m_referenceTimeStep;
double m_airGapMudWeightWindow;
int m_referenceLayerMudWeightWindow;
RimMudWeightWindowParameters::UpperLimitType m_upperLimitParameterMudWeightWindow;
RimMudWeightWindowParameters::LowerLimitType m_lowerLimitParameterMudWeightWindow;
std::map<RimMudWeightWindowParameters::ParameterType, QString> parameterAddresses;
std::map<RimMudWeightWindowParameters::ParameterType, double> parameterValues;
std::vector<std::unique_ptr<RigFemPartResultCalculator>> m_resultCalculators;
RigStatisticsDataCache* statistics( const RigFemResultAddress& resVarAddr );

View File

@ -138,6 +138,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEclipseContourMapViewCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechContourMapProjection.h
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechContourMapView.h
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechContourMapViewCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimMudWeightWindowParameters.h
${CMAKE_CURRENT_LIST_DIR}/RimViewNameConfig.h
${CMAKE_CURRENT_LIST_DIR}/RimReloadCaseTools.h
${CMAKE_CURRENT_LIST_DIR}/RimPlotAxisPropertiesInterface.h
@ -231,6 +232,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimGeoMechPropertyFilter.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechPropertyFilterCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechResultDefinition.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGeoMechCellColors.cpp
${CMAKE_CURRENT_LIST_DIR}/RimMudWeightWindowParameters.cpp
${CMAKE_CURRENT_LIST_DIR}/RimViewWindow.cpp
${CMAKE_CURRENT_LIST_DIR}/Rim3dView.cpp
${CMAKE_CURRENT_LIST_DIR}/RimGridView.cpp

View File

@ -44,6 +44,7 @@
#include "RimGeoMechView.h"
#include "RimIntersectionCollection.h"
#include "RimMainPlotCollection.h"
#include "RimMudWeightWindowParameters.h"
#include "RimProject.h"
#include "RimTimeStepFilter.h"
#include "RimTools.h"
@ -179,6 +180,15 @@ RimGeoMechCase::RimGeoMechCase( void )
CAF_PDM_InitFieldNoDefault( &m_contourMapCollection, "ContourMaps", "2d Contour Maps", "", "", "" );
m_contourMapCollection = new RimGeoMechContourMapViewCollection;
m_contourMapCollection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_mudWeightWindowParameters,
"MudWeightWindowParameters",
"Mud Weight Window Parameters",
"",
"",
"" );
m_mudWeightWindowParameters = new RimMudWeightWindowParameters;
m_mudWeightWindowParameters.uiCapability()->setUiTreeHidden( true );
}
//--------------------------------------------------------------------------------------------------
@ -406,6 +416,8 @@ std::vector<Rim3dView*> RimGeoMechCase::allSpecialViews() const
//--------------------------------------------------------------------------------------------------
void RimGeoMechCase::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ )
{
uiTreeOrdering.add( &m_mudWeightWindowParameters );
std::vector<PdmObjectHandle*> children;
geoMechViews.childObjects( &children );
@ -1250,3 +1262,11 @@ std::vector<std::string> RimGeoMechCase::possibleElementPropertyFieldNames()
}
return fieldNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::FilePath> RimGeoMechCase::elementPropertyFileNames() const
{
return m_elementPropertyFileNames();
}

View File

@ -36,6 +36,7 @@ class RigGeoMechCaseData;
class RifGeoMechReaderInterface;
class RimGeoMechContourMapView;
class RimGeoMechContourMapViewCollection;
class RimMudWeightWindowParameters;
//==================================================================================================
///
@ -111,6 +112,14 @@ public:
QString initialPermeabilityAddress() const;
double permeabilityExponent() const;
std::vector<std::string> possibleElementPropertyFieldNames();
std::vector<caf::FilePath> elementPropertyFileNames() const;
QString findFileNameForElementProperty( const std::string& elementProperty,
const std::map<std::string, QString> addressesInFiles ) const;
void updateConnectedViews();
private:
cvf::Vec3d displayModelOffset() const override;
static std::vector<QDateTime> vectorOfValidDateTimesFromTimeStepStrings( const QStringList& timeStepStrings );
@ -125,20 +134,15 @@ private:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
QString findFileNameForElementProperty( const std::string& elementProperty,
const std::map<std::string, QString> addressesInFiles ) const;
void updateFormationNamesData() override;
void initAfterRead() override;
static QString subStringOfDigits( const QString& timeStepString, int numberOfDigitsToFind );
void importElementPropertyFile();
void closeSelectedElementPropertyFiles();
void reloadSelectedElementPropertyFiles();
std::vector<Rim3dView*> allSpecialViews() const override;
void updateConnectedViews();
std::vector<std::string> possibleElementPropertyFieldNames();
void importElementPropertyFile();
void closeSelectedElementPropertyFiles();
void reloadSelectedElementPropertyFiles();
std::vector<Rim3dView*> allSpecialViews() const override;
private:
cvf::ref<RigGeoMechCaseData> m_geoMechCaseData;
@ -160,6 +164,7 @@ private:
caf::PdmField<double> m_permeabilityExponent;
caf::PdmChildField<RimGeoMechContourMapViewCollection*> m_contourMapCollection;
caf::PdmChildField<RimMudWeightWindowParameters*> m_mudWeightWindowParameters;
bool m_applyTimeFilter;
};

View File

@ -0,0 +1,513 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimMudWeightWindowParameters.h"
#include "RiaLogging.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
#include "RigFemPartResultsCollection.h"
#include "RigGeoMechCaseData.h"
#include "RimGeoMechCase.h"
#include "cafPdmFieldIOScriptability.h"
#include "cafPdmObjectScriptability.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafPdmUiTreeOrdering.h"
CAF_PDM_SOURCE_INIT( RimMudWeightWindowParameters, "RimMudWeightWindowParameters" );
namespace caf
{
template <>
void caf::AppEnum<RimMudWeightWindowParameters::SourceType>::setUp()
{
addItem( RimMudWeightWindowParameters::SourceType::FIXED, "FIXED", "Fixed" );
addItem( RimMudWeightWindowParameters::SourceType::PER_ELEMENT, "PER_ELEMENT", "From element properties" );
setDefault( RimMudWeightWindowParameters::SourceType::FIXED );
}
template <>
void caf::AppEnum<RimMudWeightWindowParameters::ParameterType>::setUp()
{
addItem( RimMudWeightWindowParameters::ParameterType::WELL_DEVIATION, "WELL_DEVIATION", "Well Deviation" );
addItem( RimMudWeightWindowParameters::ParameterType::WELL_AZIMUTH, "WELL_AZIMUTH", "Well Azimuth" );
addItem( RimMudWeightWindowParameters::ParameterType::UCS, "UCS", "UCS" );
addItem( RimMudWeightWindowParameters::ParameterType::POISSONS_RATIO, "POISSONS_RARIO", "Poisson's Ratio" );
addItem( RimMudWeightWindowParameters::ParameterType::K0_FG, "K0_FG", "K0 FG" );
setDefault( RimMudWeightWindowParameters::ParameterType::WELL_DEVIATION );
}
template <>
void caf::AppEnum<RimMudWeightWindowParameters::UpperLimitType>::setUp()
{
addItem( RimMudWeightWindowParameters::UpperLimitType::FG, "FG", "Fracture Gradient" );
addItem( RimMudWeightWindowParameters::UpperLimitType::SH_MIN, "SH_MIN", "Minimum Horizontal Stress" );
setDefault( RimMudWeightWindowParameters::UpperLimitType::FG );
}
template <>
void caf::AppEnum<RimMudWeightWindowParameters::LowerLimitType>::setUp()
{
addItem( RimMudWeightWindowParameters::LowerLimitType::PORE_PRESSURE, "PORE_PRESSURE", "Pore Pressure" );
addItem( RimMudWeightWindowParameters::LowerLimitType::MAX_OF_PORE_PRESSURE_AND_SFG,
"MAX_OF_PORE_PRESSURE_AND_SFG",
"Maximum of Pore Pressure and SFG" );
setDefault( RimMudWeightWindowParameters::LowerLimitType::PORE_PRESSURE );
}
} // End namespace caf
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::RimMudWeightWindowParameters( void )
{
CAF_PDM_InitScriptableObjectWithNameAndComment( "Mud Weight Window Parameters",
"",
"",
"The Mud Weight Window Calculation Parameters",
"MudWeightWindowParameters",
"" );
caf::AppEnum<SourceType> defaultSourceType = RimMudWeightWindowParameters::SourceType::FIXED;
CAF_PDM_InitField( &m_wellDeviationType, "WellDeviationSourceType", defaultSourceType, "Well Deviation", "", "", "" );
CAF_PDM_InitField( &m_wellDeviationFixed, "WellDeviationFixed", 0.0, "Fixed Well Deviation", "", "", "" );
m_wellDeviationFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_wellDeviationAddress, "WellDeviationAddress", QString( "" ), "Value", "", "", "" );
m_wellDeviationAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_wellAzimuthType, "WellAzimuthSourceType", defaultSourceType, "Well Azimuth", "", "", "" );
CAF_PDM_InitField( &m_wellAzimuthFixed, "WellAzimuthFixed", 0.0, "Fixed Well Azimuth", "", "", "" );
m_wellAzimuthFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_wellAzimuthAddress, "WellAzimuthAddress", QString( "" ), "Value", "", "", "" );
m_wellAzimuthAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_UCSType, "UCSSourceType", defaultSourceType, "UCS [Bar]", "", "", "" );
CAF_PDM_InitField( &m_UCSFixed, "UCSFixed", 100.0, "Fixed UCS [Bar]", "", "", "" );
m_UCSFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_UCSAddress, "UCSAddress", QString( "" ), "Value", "", "", "" );
m_UCSAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_poissonsRatioType, "PoissonsRatioSourceType", defaultSourceType, "Poisson's Ratio", "", "", "" );
CAF_PDM_InitField( &m_poissonsRatioFixed, "PoissonsRatioFixed", 0.35, "Fixed Possion's Ratio", "", "", "" );
m_poissonsRatioFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_poissonsRatioAddress, "PoissonsRatioAddress", QString( "" ), "Value", "", "", "" );
m_poissonsRatioAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_K0_FGType, "K0_FGSourceType", defaultSourceType, "K0 FG", "", "", "" );
CAF_PDM_InitField( &m_K0_FGFixed, "K0_FGFixed", 0.75, "Fixed K0_FG", "", "", "" );
m_K0_FGFixed.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_K0_FGAddress, "K0_FGAddress", QString( "" ), "Value", "", "", "" );
m_K0_FGAddress.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_airGap, "AirGap", 0.0, "Air Gap", "", "", "" );
caf::AppEnum<UpperLimitType> defaultUpperLimitType = RimMudWeightWindowParameters::UpperLimitType::FG;
CAF_PDM_InitField( &m_upperLimitType, "UpperLimitType", defaultUpperLimitType, "Upper Limit Type", "", "", "" );
caf::AppEnum<LowerLimitType> defaultLowerLimitType =
RimMudWeightWindowParameters::LowerLimitType::MAX_OF_PORE_PRESSURE_AND_SFG;
CAF_PDM_InitField( &m_lowerLimitType, "LowerLimitType", defaultLowerLimitType, "Lower Limit Type", "", "", "" );
CAF_PDM_InitField( &m_referenceLayer, "ReferenceLayer", -1, "Reference Layer", "", "", "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::SourceType RimMudWeightWindowParameters::wellDeviationType() const
{
return m_wellDeviationType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::wellDeviation() const
{
return m_wellDeviationFixed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimMudWeightWindowParameters::wellDeviationAddress() const
{
return m_wellDeviationAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::SourceType RimMudWeightWindowParameters::wellAzimuthType() const
{
return m_wellAzimuthType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::wellAzimuth() const
{
return m_wellAzimuthFixed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimMudWeightWindowParameters::wellAzimuthAddress() const
{
return m_wellAzimuthAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::SourceType RimMudWeightWindowParameters::ucsType() const
{
return m_UCSType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::ucs() const
{
return m_UCSFixed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimMudWeightWindowParameters::ucsAddress() const
{
return m_UCSAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::SourceType RimMudWeightWindowParameters::poissonsRatioType() const
{
return m_poissonsRatioType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::poissonsRatio() const
{
return m_poissonsRatioFixed();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimMudWeightWindowParameters::poissonsRatioAddress() const
{
return m_poissonsRatioAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimMudWeightWindowParameters::SourceType RimMudWeightWindowParameters::K0_FG_Type() const
{
return m_K0_FGType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::K0_FG() const
{
return m_K0_FGFixed;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimMudWeightWindowParameters::K0_FGAddress() const
{
return m_K0_FGAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimMudWeightWindowParameters::airGap() const
{
return m_airGap;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMudWeightWindowParameters::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimGeoMechCase* geoMechCase = nullptr;
firstAncestorOrThisOfType( geoMechCase );
if ( !geoMechCase )
{
return;
}
if ( changedField == &m_wellDeviationFixed || changedField == &m_wellDeviationType ||
changedField == &m_wellDeviationAddress )
{
handleFieldChanged( geoMechCase,
ParameterType::WELL_DEVIATION,
&m_wellDeviationType,
&m_wellDeviationFixed,
&m_wellDeviationAddress,
changedField == &m_wellDeviationType );
}
else if ( changedField == &m_wellAzimuthFixed || changedField == &m_wellAzimuthType ||
changedField == &m_wellAzimuthAddress )
{
handleFieldChanged( geoMechCase,
ParameterType::WELL_AZIMUTH,
&m_wellAzimuthType,
&m_wellAzimuthFixed,
&m_wellAzimuthAddress,
changedField == &m_wellAzimuthType );
}
else if ( changedField == &m_UCSFixed || changedField == &m_UCSType || changedField == &m_UCSAddress )
{
handleFieldChanged( geoMechCase, ParameterType::UCS, &m_UCSType, &m_UCSFixed, &m_UCSAddress, changedField == &m_UCSType );
}
else if ( changedField == &m_poissonsRatioFixed || changedField == &m_poissonsRatioType ||
changedField == &m_poissonsRatioAddress )
{
handleFieldChanged( geoMechCase,
ParameterType::POISSONS_RATIO,
&m_poissonsRatioType,
&m_poissonsRatioFixed,
&m_poissonsRatioAddress,
changedField == &m_poissonsRatioType );
}
else if ( changedField == &m_K0_FGFixed || changedField == &m_K0_FGType || changedField == &m_K0_FGAddress )
{
handleFieldChanged( geoMechCase,
ParameterType::K0_FG,
&m_K0_FGType,
&m_K0_FGFixed,
&m_K0_FGAddress,
changedField == &m_K0_FGType );
}
else if ( changedField == &m_airGap || changedField == &m_upperLimitType || changedField == &m_lowerLimitType ||
changedField == &m_referenceLayer )
{
RigGeoMechCaseData* rigCaseData = geoMechCase->geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() )
{
rigCaseData->femPartResults()->setMudWeightWindowParameters( m_airGap,
m_upperLimitType.value(),
m_lowerLimitType.value(),
m_referenceLayer );
geoMechCase->updateConnectedViews();
}
}
}
void RimMudWeightWindowParameters::handleFieldChanged( RimGeoMechCase* geoMechCase,
ParameterType parameterType,
caf::PdmField<caf::AppEnum<SourceType>>* typeField,
caf::PdmField<double>* fixedField,
caf::PdmField<QString>* addressField,
bool typeFieldChanged )
{
RigGeoMechCaseData* rigCaseData = geoMechCase->geoMechData();
if ( rigCaseData && rigCaseData->femPartResults() )
{
if ( typeField->value() == RimMudWeightWindowParameters::SourceType::FIXED )
{
rigCaseData->femPartResults()->setCalculationParameters( parameterType, "", fixedField->value() );
}
else if ( typeField->value() == RimMudWeightWindowParameters::SourceType::PER_ELEMENT )
{
if ( typeFieldChanged )
{
// Show info message to user when selecting "from file" option before
// an element property has been imported
std::vector<std::string> elementProperties = geoMechCase->possibleElementPropertyFieldNames();
if ( elementProperties.empty() )
{
QString title = caf::AppEnum<ParameterType>::uiText( parameterType );
QString importMessage =
QString( "Please import '%1' from file by "
"selecting 'Import Element Property Table' on the Geomechanical Model." )
.arg( title );
RiaLogging::info( importMessage );
// Set back to default value
*typeField = RimMudWeightWindowParameters::SourceType::FIXED;
return;
}
}
if ( addressField->value().isEmpty() )
{
// Automatically select the first available property element if empty
std::vector<std::string> elementProperties = geoMechCase->possibleElementPropertyFieldNames();
if ( !elementProperties.empty() )
{
*addressField = QString::fromStdString( elementProperties[0] );
}
}
rigCaseData->femPartResults()->setCalculationParameters( parameterType,
addressField->value(),
fixedField->value() );
}
}
geoMechCase->updateConnectedViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMudWeightWindowParameters::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
defineGroup( uiOrdering, "Well Deviation", &m_wellDeviationType, &m_wellDeviationFixed, &m_wellDeviationAddress );
defineGroup( uiOrdering, "Well Azimuth", &m_wellAzimuthType, &m_wellAzimuthFixed, &m_wellAzimuthAddress );
defineGroup( uiOrdering, "UCS", &m_UCSType, &m_UCSFixed, &m_UCSAddress );
defineGroup( uiOrdering, "Poisson's Ratio", &m_poissonsRatioType, &m_poissonsRatioFixed, &m_poissonsRatioAddress );
defineGroup( uiOrdering, "K0 for Fracture Gradient Factor for Shale", &m_K0_FGType, &m_K0_FGFixed, &m_K0_FGAddress );
RimGeoMechCase* geoMechCase = nullptr;
firstAncestorOrThisOfType( geoMechCase );
if ( !geoMechCase )
{
return;
}
RigGeoMechCaseData* rigCaseData = geoMechCase->geoMechData();
if ( rigCaseData && m_referenceLayer == -1 )
{
m_referenceLayer =
(int)rigCaseData->femParts()->part( 0 )->getOrCreateStructGrid()->reservoirIJKBoundingBox().first.z();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMudWeightWindowParameters::defineGroup( caf::PdmUiOrdering& uiOrdering,
const QString& title,
caf::PdmField<caf::AppEnum<SourceType>>* typeField,
caf::PdmField<double>* fixedField,
caf::PdmField<QString>* addressField )
{
uiOrdering.add( typeField );
uiOrdering.add( fixedField );
uiOrdering.add( addressField );
fixedField->uiCapability()->setUiHidden( *typeField != RimMudWeightWindowParameters::SourceType::FIXED );
addressField->uiCapability()->setUiHidden( *typeField != RimMudWeightWindowParameters::SourceType::PER_ELEMENT );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimMudWeightWindowParameters::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_wellDeviationFixed || field == &m_wellAzimuthFixed )
{
auto uiDoubleValueEditorAttr = dynamic_cast<caf::PdmUiDoubleValueEditorAttribute*>( attribute );
if ( uiDoubleValueEditorAttr )
{
uiDoubleValueEditorAttr->m_validator = new QDoubleValidator( 0.0, 360.0, 3 );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimMudWeightWindowParameters::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
RimGeoMechCase* geoMechCase = nullptr;
firstAncestorOrThisOfType( geoMechCase );
if ( geoMechCase != nullptr )
{
if ( fieldNeedingOptions == &m_wellDeviationAddress || fieldNeedingOptions == &m_wellAzimuthAddress ||
fieldNeedingOptions == &m_UCSAddress || fieldNeedingOptions == &m_poissonsRatioAddress ||
fieldNeedingOptions == &m_K0_FGAddress )
{
std::vector<std::string> elementProperties = geoMechCase->possibleElementPropertyFieldNames();
std::vector<caf::FilePath> elementPropertyFileNames = geoMechCase->elementPropertyFileNames();
std::vector<QString> paths;
for ( auto path : elementPropertyFileNames )
{
paths.push_back( path.path() );
}
std::map<std::string, QString> addressesInFile =
geoMechCase->geoMechData()->femPartResults()->addressesInElementPropertyFiles( paths );
for ( const std::string elementProperty : elementProperties )
{
QString result = QString::fromStdString( elementProperty );
QString filename = geoMechCase->findFileNameForElementProperty( elementProperty, addressesInFile );
options.push_back( caf::PdmOptionItemInfo( result + " (" + filename + ")", result ) );
}
}
else if ( fieldNeedingOptions == &m_referenceLayer )
{
if ( geoMechCase->geoMechData() )
{
size_t kCount =
geoMechCase->geoMechData()->femParts()->part( 0 )->getOrCreateStructGrid()->gridPointCountK() - 1;
for ( size_t layerIdx = 0; layerIdx < kCount; ++layerIdx )
{
options.push_back( caf::PdmOptionItemInfo( QString::number( layerIdx + 1 ), (int)layerIdx ) );
}
}
}
}
return options;
}

View File

@ -0,0 +1,136 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "cafPdmField.h"
#include "cafPdmObject.h"
class RimGeoMechCase;
//==================================================================================================
///
///
//==================================================================================================
class RimMudWeightWindowParameters : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
enum class SourceType
{
FIXED = 0,
PER_ELEMENT
};
enum class ParameterType
{
WELL_DEVIATION,
WELL_AZIMUTH,
UCS,
POISSONS_RATIO,
K0_FG
};
enum class UpperLimitType
{
FG,
SH_MIN
};
enum class LowerLimitType
{
PORE_PRESSURE,
MAX_OF_PORE_PRESSURE_AND_SFG
};
RimMudWeightWindowParameters( void );
SourceType wellDeviationType() const;
double wellDeviation() const;
QString wellDeviationAddress() const;
SourceType wellAzimuthType() const;
double wellAzimuth() const;
QString wellAzimuthAddress() const;
SourceType ucsType() const;
double ucs() const;
QString ucsAddress() const;
SourceType poissonsRatioType() const;
double poissonsRatio() const;
QString poissonsRatioAddress() const;
SourceType K0_FG_Type() const;
double K0_FG() const;
QString K0_FGAddress() const;
double airGap() const;
private:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void defineGroup( caf::PdmUiOrdering& uiOrdering,
const QString& title,
caf::PdmField<caf::AppEnum<SourceType>>* typeField,
caf::PdmField<double>* fixedField,
caf::PdmField<QString>* addressField );
void handleFieldChanged( RimGeoMechCase* geoMechCase,
ParameterType parameterType,
caf::PdmField<caf::AppEnum<SourceType>>* typeField,
caf::PdmField<double>* fixedField,
caf::PdmField<QString>* addressField,
bool typeFieldChanged );
private:
caf::PdmField<caf::AppEnum<SourceType>> m_wellDeviationType;
caf::PdmField<double> m_wellDeviationFixed;
caf::PdmField<QString> m_wellDeviationAddress;
caf::PdmField<caf::AppEnum<SourceType>> m_wellAzimuthType;
caf::PdmField<double> m_wellAzimuthFixed;
caf::PdmField<QString> m_wellAzimuthAddress;
caf::PdmField<caf::AppEnum<SourceType>> m_UCSType;
caf::PdmField<double> m_UCSFixed;
caf::PdmField<QString> m_UCSAddress;
caf::PdmField<caf::AppEnum<SourceType>> m_poissonsRatioType;
caf::PdmField<double> m_poissonsRatioFixed;
caf::PdmField<QString> m_poissonsRatioAddress;
caf::PdmField<caf::AppEnum<SourceType>> m_K0_FGType;
caf::PdmField<double> m_K0_FGFixed;
caf::PdmField<QString> m_K0_FGAddress;
caf::PdmField<double> m_airGap;
caf::PdmField<caf::AppEnum<UpperLimitType>> m_upperLimitType;
caf::PdmField<caf::AppEnum<LowerLimitType>> m_lowerLimitType;
caf::PdmField<int> m_referenceLayer;
};

View File

@ -81,6 +81,9 @@ public:
std::vector<double> poissonSourceRegions( int frameIndex );
std::vector<double> ucsSourceRegions( int frameIndex );
static caf::Ten3d transformTensorToWellPathOrientation( const cvf::Vec3d& wellPathTangent,
const caf::Ten3d& wellPathTensor );
private:
enum WellPathTangentCalculation
{
@ -122,8 +125,6 @@ private:
cvf::Vec3d
calculateLengthInCell( size_t cellIndex, const cvf::Vec3d& startPoint, const cvf::Vec3d& endPoint ) const override;
cvf::Vec3d calculateWellPathTangent( int64_t intersectionIdx, WellPathTangentCalculation calculationType ) const;
static caf::Ten3d transformTensorToWellPathOrientation( const cvf::Vec3d& wellPathTangent,
const caf::Ten3d& wellPathTensor );
cvf::Vec3f cellCentroid( size_t intersectionIdx ) const;
double getWellLogIntersectionValue( size_t intersectionIdx,