mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Add reference well depth adjustment to geomech case (#9547)
- Fix bug in retrieving bottom TVD value from ref well - Add result calculator for K-indices in geomech case - Improve depth adjustment algorithm
This commit is contained in:
@@ -552,12 +552,6 @@ RimWellLogExtractionCurve::WellLogExtractionCurveData
|
||||
// Reference well adjustment does not support simulated wells
|
||||
if ( m_trajectoryType == WELL_PATH && wellExtractor.notNull() && refWellExtractor.notNull() )
|
||||
{
|
||||
// ************************************************
|
||||
//
|
||||
// Adjust measured dept values according to refWell
|
||||
//
|
||||
// ************************************************
|
||||
|
||||
RigEclipseResultAddress indexKResAdr( RiaDefines::ResultCatType::STATIC_NATIVE,
|
||||
RiaResultNames::indexKResultName() );
|
||||
eclipseCase->eclipseCaseData()->results( RiaDefines::PorosityModelType::MATRIX_MODEL )->ensureKnownResultLoaded( indexKResAdr );
|
||||
@@ -601,8 +595,6 @@ RimWellLogExtractionCurve::WellLogExtractionCurveData
|
||||
bool performDataSmoothing,
|
||||
double smoothingThreshold )
|
||||
{
|
||||
// TODO: Add depth adjustements for reference well
|
||||
|
||||
WellLogExtractionCurveData curveData;
|
||||
RimWellLogPlotCollection* wellLogCollection = RimMainPlotCollection::current()->wellLogPlotCollection();
|
||||
cvf::ref<RigGeoMechWellLogExtractor> wellExtractor = wellLogCollection->findOrCreateExtractor( m_wellPath, geomCase );
|
||||
@@ -641,23 +633,51 @@ RimWellLogExtractionCurve::WellLogExtractionCurveData
|
||||
}
|
||||
}
|
||||
|
||||
const std::string fieldName = m_geomResultDefinition->resultAddress().fieldName;
|
||||
if ( fieldName == RiaResultNames::wbsAzimuthResult().toStdString() ||
|
||||
fieldName == RiaResultNames::wbsInclinationResult().toStdString() )
|
||||
{
|
||||
// Do not adjust depth values of Azimuth and Inclination as they are
|
||||
// dependent of the well geometry
|
||||
return curveData;
|
||||
}
|
||||
|
||||
if ( wellExtractor.notNull() && refWellExtractor.notNull() )
|
||||
{
|
||||
// Add reference well depth adjustments
|
||||
// NOTE: Perform performCurveDataSmoothing() for refWell, as done for well?
|
||||
|
||||
// ************************************************
|
||||
//
|
||||
// Adjust measured dept values according to refWell
|
||||
//
|
||||
// ************************************************
|
||||
RigFemResultAddress indexKResAdr( RigFemResultPosEnum::RIG_ELEMENT_NODAL, "INDEX", "INDEX_K" );
|
||||
|
||||
const size_t frameIdx = 0;
|
||||
std::vector<double> refWellMeasuredDepthValues = refWellExtractor->cellIntersectionMDs();
|
||||
std::vector<double> refWellTvDepthValues = refWellExtractor->cellIntersectionTVDs();
|
||||
std::vector<double> wellIndexKValues;
|
||||
std::vector<double> refWellIndexKValues;
|
||||
if ( indexKResAdr.isValid() )
|
||||
{
|
||||
wellExtractor->curveData( indexKResAdr, frameIdx, &wellIndexKValues );
|
||||
refWellExtractor->curveData( indexKResAdr, frameIdx, &refWellIndexKValues );
|
||||
}
|
||||
if ( !wellIndexKValues.empty() && !refWellIndexKValues.empty() )
|
||||
{
|
||||
adjustWellDepthValuesToReferenceWell( curveData.measuredDepthValues,
|
||||
curveData.tvDepthValues,
|
||||
wellIndexKValues,
|
||||
refWellMeasuredDepthValues,
|
||||
refWellTvDepthValues,
|
||||
refWellIndexKValues );
|
||||
}
|
||||
}
|
||||
|
||||
return curveData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Utility function to adjust well depth values according to reference well - match k-index
|
||||
// enter/exit values and linearize between enter/exit of k-index
|
||||
/// Utility function to adjust well depth values according to reference well - match
|
||||
/// enter and exit values for k-layer and linearize for depth values between enter/exit of k-layer.
|
||||
///
|
||||
/// Performs depth adjustment from first common k-layer to last common k-layer - i.e common min and
|
||||
/// max index-k, as long as the k-layers are asymptotically increasing.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogExtractionCurve::adjustWellDepthValuesToReferenceWell( std::vector<double>& rMeasuredDepthValues,
|
||||
std::vector<double>& rTvDepthValues,
|
||||
@@ -666,12 +686,6 @@ void RimWellLogExtractionCurve::adjustWellDepthValuesToReferenceWell( std::vecto
|
||||
const std::vector<double>& refWellTvDepthValues,
|
||||
const std::vector<double>& refWellIndexKValues )
|
||||
{
|
||||
// Description:
|
||||
// - Adjust values up to largest common k-index value
|
||||
// Assumptions:
|
||||
// - Both wells have min k-index equal to 1.
|
||||
// - k-index values are continously increasing values between top and bottom of well
|
||||
|
||||
CAF_ASSERT( rMeasuredDepthValues.size() == rTvDepthValues.size() &&
|
||||
"Number of depth values must be equal for well!" );
|
||||
CAF_ASSERT( rMeasuredDepthValues.size() == indexKValues.size() &&
|
||||
@@ -682,13 +696,15 @@ void RimWellLogExtractionCurve::adjustWellDepthValuesToReferenceWell( std::vecto
|
||||
"Number of index K values must be number of depth values for reference well!" );
|
||||
CAF_ASSERT( *std::min( indexKValues.cbegin(), indexKValues.cend() ) ==
|
||||
*std::min( refWellIndexKValues.cbegin(), refWellIndexKValues.cend() ) &&
|
||||
"Both index-K value vectors must have same start index-K layer" );
|
||||
"Both index-K value vectors must containt common min index-K layer" );
|
||||
|
||||
// Find common min and max k-index value for range depth values adjustment
|
||||
const double minLayerK = std::max( *std::min_element( refWellIndexKValues.cbegin(), refWellIndexKValues.cend() ),
|
||||
*std::min_element( indexKValues.cbegin(), indexKValues.cend() ) );
|
||||
const double maxLayerK = std::min( *std::max_element( refWellIndexKValues.cbegin(), refWellIndexKValues.cend() ),
|
||||
*std::max_element( indexKValues.cbegin(), indexKValues.cend() ) );
|
||||
// Find common min and max k-index value for range of depth values to adjust
|
||||
const auto minLayerK =
|
||||
static_cast<int>( std::max( *std::min_element( refWellIndexKValues.cbegin(), refWellIndexKValues.cend() ),
|
||||
*std::min_element( indexKValues.cbegin(), indexKValues.cend() ) ) );
|
||||
const auto maxLayerK =
|
||||
static_cast<int>( std::min( *std::max_element( refWellIndexKValues.cbegin(), refWellIndexKValues.cend() ),
|
||||
*std::max_element( indexKValues.cbegin(), indexKValues.cend() ) ) );
|
||||
if ( minLayerK > maxLayerK )
|
||||
{
|
||||
RiaLogging::error(
|
||||
@@ -696,32 +712,39 @@ void RimWellLogExtractionCurve::adjustWellDepthValuesToReferenceWell( std::vecto
|
||||
return;
|
||||
}
|
||||
|
||||
RigWellLogIndexDepthOffset refWellLogIndexDepthOffset;
|
||||
for ( int kLayer = static_cast<int>( minLayerK ); kLayer <= static_cast<int>( maxLayerK ); kLayer++ )
|
||||
// Only allow asymptotically increasing k-layers - break at first decreasing k-layer value
|
||||
auto createKLayerAndIndexMap = []( const std::vector<double>& indexKValues, int minLayerK, int maxLayerK ) {
|
||||
int prevKLayer = -1;
|
||||
std::map<int, std::vector<size_t>> kLayerAndIndexesMap = {};
|
||||
for ( size_t i = 0; i < indexKValues.size(); ++i )
|
||||
{
|
||||
const auto kLayer = static_cast<int>( indexKValues[i] );
|
||||
if ( kLayer < minLayerK ) continue;
|
||||
if ( kLayer < prevKLayer || kLayer > maxLayerK ) break;
|
||||
|
||||
kLayerAndIndexesMap[kLayer].push_back( i );
|
||||
prevKLayer = kLayer;
|
||||
}
|
||||
return kLayerAndIndexesMap;
|
||||
};
|
||||
|
||||
RigWellLogIndexDepthOffset refWellLogIndexDepthOffset;
|
||||
std::map<int, std::vector<size_t>> refWellKLayerAndIndexesMap =
|
||||
createKLayerAndIndexMap( refWellIndexKValues, minLayerK, maxLayerK );
|
||||
for ( const auto& [kLayer, indexes] : refWellKLayerAndIndexesMap )
|
||||
{
|
||||
const auto kLayerTopIter =
|
||||
std::find( refWellIndexKValues.cbegin(), refWellIndexKValues.cend(), static_cast<double>( kLayer ) );
|
||||
const auto kLayerBottomRIter =
|
||||
std::find( refWellIndexKValues.crbegin(), refWellIndexKValues.crend(), static_cast<double>( kLayer ) );
|
||||
const auto indexTop = std::distance( refWellIndexKValues.cbegin(), kLayerTopIter );
|
||||
const auto indexBottom = refWellIndexKValues.size() - 1 -
|
||||
std::distance( refWellIndexKValues.crbegin(), kLayerBottomRIter );
|
||||
|
||||
const auto topMd = refWellMeasuredDepthValues[indexTop];
|
||||
const auto bottomMd = refWellMeasuredDepthValues[indexBottom];
|
||||
const auto topTvd = refWellTvDepthValues[indexTop];
|
||||
const auto bottomTvd = refWellTvDepthValues[indexBottom];
|
||||
|
||||
refWellLogIndexDepthOffset.setIndexOffsetDepth( kLayer, topMd, bottomMd, topTvd, bottomTvd );
|
||||
}
|
||||
|
||||
std::map<int, std::vector<size_t>> wellKLayerAndIndexesMap = {};
|
||||
for ( size_t i = 0; i < indexKValues.size(); i++ )
|
||||
{
|
||||
const int kLayer = static_cast<int>( indexKValues[i] );
|
||||
wellKLayerAndIndexesMap[kLayer].push_back( i );
|
||||
if ( indexes.empty() ) continue;
|
||||
const auto indexTop = indexes.front();
|
||||
const auto indexBottom = indexes.back();
|
||||
refWellLogIndexDepthOffset.setIndexOffsetDepth( kLayer,
|
||||
refWellMeasuredDepthValues[indexTop],
|
||||
refWellMeasuredDepthValues[indexBottom],
|
||||
refWellTvDepthValues[indexTop],
|
||||
refWellTvDepthValues[indexBottom] );
|
||||
}
|
||||
|
||||
std::map<int, std::vector<size_t>> wellKLayerAndIndexesMap =
|
||||
createKLayerAndIndexMap( indexKValues, minLayerK, maxLayerK );
|
||||
for ( const auto& [kLayer, indexes] : wellKLayerAndIndexesMap )
|
||||
{
|
||||
const auto firstIdx = indexes.front();
|
||||
@@ -731,7 +754,7 @@ void RimWellLogExtractionCurve::adjustWellDepthValuesToReferenceWell( std::vecto
|
||||
rMeasuredDepthValues[firstIdx] = refWellLogIndexDepthOffset.getTopMd( kLayer );
|
||||
rMeasuredDepthValues[lastIdx] = refWellLogIndexDepthOffset.getBottomMd( kLayer );
|
||||
rTvDepthValues[firstIdx] = refWellLogIndexDepthOffset.getTopTvd( kLayer );
|
||||
rTvDepthValues[lastIdx] = refWellLogIndexDepthOffset.getBottomMd( kLayer );
|
||||
rTvDepthValues[lastIdx] = refWellLogIndexDepthOffset.getBottomTvd( kLayer );
|
||||
}
|
||||
else if ( indexes.size() > 2 && refWellLogIndexDepthOffset.hasIndex( kLayer ) )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user