Fix automatic part id detection for Fault Reactivation Result, and resampling bug in RigWellLogCurveData

* Fix resampling bug and refactor code
- Fix bug for resampling, prevent index increment.
- Refactor functions into static functions.
- Fix issue in interpolateSegment not using correct indices for depthType != resamplingDepthType
- Add unit tests

* Change WellAllocationPlot to use step left
Remove dummy point and utilize step left for WellAllocationPont

* Fix bug in creating resampled values and depths for RigWellLogCurveData

* Fix automatic part detection for Fault Reactivation Result
- Fix incorrect automatic part detection
- Set default distance to intersection to 1.0 [m]
This commit is contained in:
Jørgen Herje 2023-06-20 10:08:10 +02:00 committed by GitHub
parent 22e9e7aeb0
commit 0685078ab3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 395 additions and 75 deletions

View File

@ -124,6 +124,37 @@ const int* RigFemPart::connectivities( size_t elementIdx ) const
return &m_allElementConnectivities[m_elementConnectivityStartIndices[elementIdx]]; return &m_allElementConnectivities[m_elementConnectivityStartIndices[elementIdx]];
} }
//--------------------------------------------------------------------------------------------------
/// Returns state of success for fill element coordinates
//--------------------------------------------------------------------------------------------------
bool RigFemPart::fillElementCoordinates( size_t elementIdx, std::array<cvf::Vec3d, 8>& coordinates ) const
{
const auto elemType = elementType( elementIdx );
const int* elemConnectivity = connectivities( elementIdx );
const auto nodeCount = RigFemTypes::elementNodeCount( elemType );
// Only handle element of hex for now - false success
if ( nodeCount != 8 ) return false;
// Retrieve the node indices
std::vector<int> nodeIndices;
for ( int i = 0; i < nodeCount; ++i )
{
const int nodeIdx = elemConnectivity[i];
nodeIndices.push_back( nodeIdx );
}
// Fill coordinates for each node
const auto& partNodes = nodes();
for ( int i = 0; i < nodeIndices.size(); ++i )
{
coordinates[i].set( partNodes.coordinates[nodeIndices[i]] );
}
// Return true success
return true;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -27,6 +27,7 @@
#include "cvfBoundingBox.h" #include "cvfBoundingBox.h"
#include "cvfObject.h" #include "cvfObject.h"
#include "cvfVector3.h" #include "cvfVector3.h"
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
@ -64,6 +65,8 @@ public:
bool isHexahedron( size_t elementIdx ) const; bool isHexahedron( size_t elementIdx ) const;
const int* connectivities( size_t elementIdx ) const; const int* connectivities( size_t elementIdx ) const;
bool fillElementCoordinates( size_t elementIdx, std::array<cvf::Vec3d, 8>& coordinates ) const;
size_t elementNodeResultIdx( int elementIdx, int elmLocalNodeIdx ) const; size_t elementNodeResultIdx( int elementIdx, int elmLocalNodeIdx ) const;
size_t elementNodeResultCount() const; size_t elementNodeResultCount() const;
int nodeIdxFromElementNodeResultIdx( size_t elmNodeResultIdx ) const; int nodeIdxFromElementNodeResultIdx( size_t elmNodeResultIdx ) const;

View File

@ -337,10 +337,6 @@ void RimWellAllocationPlot::updateFromWell()
accFlow = ( m_flowType == ACCUMULATED ? wfCalculator->accumulatedTracerFlowPrConnection( tracerName, brIdx ) accFlow = ( m_flowType == ACCUMULATED ? wfCalculator->accumulatedTracerFlowPrConnection( tracerName, brIdx )
: wfCalculator->tracerFlowPrConnection( tracerName, brIdx ) ); : wfCalculator->tracerFlowPrConnection( tracerName, brIdx ) );
// Insert the first depth position again, to add a <maxdepth, 0.0> value pair
curveDepthValues.insert( curveDepthValues.begin(), curveDepthValues[0] );
accFlow.insert( accFlow.begin(), 0.0 );
if ( m_flowType == ACCUMULATED && brIdx == 0 && !accFlow.empty() ) // Add fictitious point to -1 if ( m_flowType == ACCUMULATED && brIdx == 0 && !accFlow.empty() ) // Add fictitious point to -1
// for first branch // for first branch
{ {
@ -474,6 +470,8 @@ void RimWellAllocationPlot::addStackedCurve( const QString& tracerNa
curve->setColor( getTracerColor( tracerName ) ); curve->setColor( getTracerColor( tracerName ) );
} }
curve->setInterpolation( RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_STEP_LEFT );
plotTrack->addCurve( curve ); plotTrack->addCurve( curve );
curve->loadDataAndUpdate( true ); curve->loadDataAndUpdate( true );

View File

@ -27,6 +27,7 @@
#include "RigFemPartCollection.h" #include "RigFemPartCollection.h"
#include "RigGeoMechCaseData.h" #include "RigGeoMechCaseData.h"
#include "RigHexIntersectionTools.h"
#include "RigReservoirGridTools.h" #include "RigReservoirGridTools.h"
#include "RimGeoMechCase.h" #include "RimGeoMechCase.h"
@ -52,6 +53,8 @@
#include "cvfBoundingBox.h" #include "cvfBoundingBox.h"
#include <array>
CAF_PDM_SOURCE_INIT( RimGeoMechFaultReactivationResult, "RimGeoMechFaultReactivationResult" ); CAF_PDM_SOURCE_INIT( RimGeoMechFaultReactivationResult, "RimGeoMechFaultReactivationResult" );
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -64,7 +67,10 @@ RimGeoMechFaultReactivationResult::RimGeoMechFaultReactivationResult()
CAF_PDM_InitFieldNoDefault( &m_intersection, "Intersection", "Intersection" ); CAF_PDM_InitFieldNoDefault( &m_intersection, "Intersection", "Intersection" );
CAF_PDM_InitField( &m_distanceFromIntersection, "FaceDistanceFromIntersection", 0.0, "Face Distance From Intersection" ); CAF_PDM_InitField( &m_distanceFromIntersection,
"FaceDistanceFromIntersection",
m_defaultDistanceFromIntersection,
"Face Distance From Intersection" );
CAF_PDM_InitField( &m_widthOutsideIntersection, "FaceWidthOutsideIntersection", 0.0, "Face Width Outside Intersection" ); CAF_PDM_InitField( &m_widthOutsideIntersection, "FaceWidthOutsideIntersection", 0.0, "Face Width Outside Intersection" );
CAF_PDM_InitFieldNoDefault( &m_createFaultReactivationResult, "CreateReactivationResult", "" ); CAF_PDM_InitFieldNoDefault( &m_createFaultReactivationResult, "CreateReactivationResult", "" );
@ -156,7 +162,8 @@ void RimGeoMechFaultReactivationResult::fieldChangedByUi( const caf::PdmFieldHan
} }
if ( changedField == &m_createFaultReactivationResult && m_intersection() ) if ( changedField == &m_createFaultReactivationResult && m_intersection() )
{ {
onLoadDataAndUpdate(); createWellGeometry();
createWellLogCurves();
} }
} }
@ -172,7 +179,7 @@ void RimGeoMechFaultReactivationResult::defineEditorAttribute( const caf::PdmFie
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute ); caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
if ( attrib ) if ( attrib )
{ {
attrib->m_buttonText = "Create"; attrib->m_buttonText = "Create Plot";
} }
} }
} }
@ -332,19 +339,31 @@ void RimGeoMechFaultReactivationResult::createWellLogCurves()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
int RimGeoMechFaultReactivationResult::getPartIndexFromPoint( const RigFemPartCollection* const partCollection, const cvf::Vec3d& point ) const int RimGeoMechFaultReactivationResult::getPartIndexFromPoint( const RigFemPartCollection* const partCollection, const cvf::Vec3d& point ) const
{ {
int idx = 0; const int idx = 0;
if ( !partCollection ) return idx; if ( !partCollection ) return idx;
// Find candidates for intersected global elements
const cvf::BoundingBox intersectingBb( point, point ); const cvf::BoundingBox intersectingBb( point, point );
std::vector<size_t> intersectedGlobalElementIndices; std::vector<size_t> intersectedGlobalElementIndexCandidates;
partCollection->findIntersectingGlobalElementIndices( intersectingBb, &intersectedGlobalElementIndices ); partCollection->findIntersectingGlobalElementIndices( intersectingBb, &intersectedGlobalElementIndexCandidates );
if ( intersectedGlobalElementIndices.empty() ) return idx; if ( intersectedGlobalElementIndexCandidates.empty() ) return idx;
// Utilize first intersected element to detect part for point // Iterate through global element candidates and check if point is in hexCorners
const auto [partId, elementIndex] = partCollection->partIdAndElementIndex( intersectedGlobalElementIndices.front() ); for ( const auto& globalElementIndex : intersectedGlobalElementIndexCandidates )
idx = partId; {
const auto [part, elementIndex] = partCollection->partAndElementIndex( globalElementIndex );
// Find nodes from element
std::array<cvf::Vec3d, 8> coordinates;
const bool isSuccess = part->fillElementCoordinates( elementIndex, coordinates );
if ( !isSuccess ) continue;
const bool isPointInCell = RigHexIntersectionTools::isPointInCell( point, coordinates.data() );
if ( isPointInCell ) return part->elementPartId();
}
// Utilize first part to have an id
return idx; return idx;
} }

View File

@ -77,4 +77,6 @@ private:
caf::PdmField<int> m_faceAWellPathPartIndex; caf::PdmField<int> m_faceAWellPathPartIndex;
caf::PdmField<int> m_faceBWellPathPartIndex; caf::PdmField<int> m_faceBWellPathPartIndex;
const double m_defaultDistanceFromIntersection = 1.0; // [m] Default value from intersection and into each part
}; };

View File

@ -345,41 +345,57 @@ cvf::ref<RigWellLogCurveData> RigWellLogCurveData::calculateResampledCurveData(
return reSampledData; return reSampledData;
} }
void RigWellLogCurveData::interpolateSegment( RiaDefines::DepthTypeEnum resamplingDepthType, //--------------------------------------------------------------------------------------------------
double depthValue, /// The function creates and adds interpolated values for property and depths. The interpolated
size_t firstIndex, /// values are added to the end of the resampledValues. Target depth is added to the end of the
std::vector<double>& xValues, /// resampledDepths vector for the resampling type. The depth values for remaining depth types
std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& resampledDepths, /// are created by linear interpolation between first and second depth value of the resampling type.
const double eps ) const //--------------------------------------------------------------------------------------------------
void RigWellLogCurveData::createAndAddInterpolatedSegmentValueAndDepths(
std::vector<double>& resampledValues,
std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& resampledDepths,
RiaDefines::DepthTypeEnum resamplingDepthType,
double targetDepthValue,
size_t firstIndex,
size_t secondIndex,
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& originalDepths,
const std::vector<double>& propertyValues,
double eps )
{ {
auto depthIt = m_depths.find( resamplingDepthType ); if ( !originalDepths.contains( resamplingDepthType ) ) return;
size_t secondIndex = firstIndex + 1; const auto& depthValues = originalDepths.find( resamplingDepthType )->second;
if ( firstIndex >= depthValues.size() || secondIndex >= depthValues.size() ) return;
double depth0 = depthIt->second[firstIndex]; double depth0 = depthValues[firstIndex];
double depth1 = depthIt->second[secondIndex]; double depth1 = depthValues[secondIndex];
double x0 = m_propertyValues[firstIndex]; double x0 = propertyValues[firstIndex];
double x1 = m_propertyValues[secondIndex]; double x1 = propertyValues[secondIndex];
double slope = 0.0; double slope = 0.0;
if ( std::fabs( depth1 - depth0 ) > eps ) if ( std::fabs( depth1 - depth0 ) > eps )
{ {
slope = ( x1 - x0 ) / ( depth1 - depth0 ); slope = ( x1 - x0 ) / ( depth1 - depth0 );
} }
double xValue = slope * ( depthValue - depth0 ) + x0; double resampledValue = slope * ( targetDepthValue - depth0 ) + x0;
xValues.push_back( xValue ); resampledValues.push_back( resampledValue );
resampledDepths[resamplingDepthType].push_back( targetDepthValue );
for ( auto depthTypeValuesPair : m_depths ) // Add depth values for remaining depth types
for ( const auto& [depthType, depthTypeValues] : originalDepths )
{ {
if ( depthTypeValuesPair.first != resamplingDepthType ) if ( depthType == resamplingDepthType ) continue;
{ if ( firstIndex >= depthTypeValues.size() || secondIndex >= depthTypeValues.size() ) continue;
double otherDepth0 = depthTypeValuesPair.second[0];
double otherDepth1 = depthTypeValuesPair.second[1]; double otherDepth0 = depthTypeValues[firstIndex];
double otherSlope = ( otherDepth1 - otherDepth0 ) / ( depth1 - depth0 ); double otherDepth1 = depthTypeValues[secondIndex];
resampledDepths[depthTypeValuesPair.first].push_back( otherSlope * ( depthValue - depth0 ) + otherDepth0 ); double otherSlope = ( otherDepth1 - otherDepth0 ) / ( depth1 - depth0 );
} resampledDepths[depthType].push_back( otherSlope * ( targetDepthValue - depth0 ) + otherDepth0 );
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool isLeftOf( double x1, double x2, bool reverseOrder, double eps ) bool isLeftOf( double x1, double x2, bool reverseOrder, double eps )
{ {
if ( reverseOrder ) if ( reverseOrder )
@ -389,6 +405,9 @@ bool isLeftOf( double x1, double x2, bool reverseOrder, double eps )
return x2 - x1 > eps; return x2 - x1 > eps;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool isRightOf( double x1, double x2, bool reverseOrder, double eps ) bool isRightOf( double x1, double x2, bool reverseOrder, double eps )
{ {
return isLeftOf( x2, x1, reverseOrder, eps ); return isLeftOf( x2, x1, reverseOrder, eps );
@ -397,53 +416,59 @@ bool isRightOf( double x1, double x2, bool reverseOrder, double eps )
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
cvf::ref<RigWellLogCurveData> RigWellLogCurveData::calculateResampledCurveData( RiaDefines::DepthTypeEnum resamplingDepthType, std::pair<std::vector<double>, std::map<RiaDefines::DepthTypeEnum, std::vector<double>>>
const std::vector<double>& depths ) const RigWellLogCurveData::createResampledValuesAndDepths( RiaDefines::DepthTypeEnum resamplingDepthType,
const std::vector<double>& targetDepths,
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& originalDepths,
const std::vector<double>& propertyValues )
{ {
const double eps = 1.0e-8; const double eps = 1.0e-8;
std::vector<double> xValues; auto depthIt = originalDepths.find( resamplingDepthType );
if ( depthIt == originalDepths.end() || depthIt->second.empty() ) return {};
std::map<RiaDefines::DepthTypeEnum, std::vector<double>> resampledDepths; const auto& depthValues = depthIt->second;
resampledDepths.insert( std::make_pair( resamplingDepthType, depths ) );
auto depthIt = m_depths.find( resamplingDepthType );
cvf::ref<RigWellLogCurveData> reSampledData = new RigWellLogCurveData;
if ( depthIt == m_depths.end() || depthIt->second.empty() ) return reSampledData;
bool reverseOrder = resamplingDepthType == RiaDefines::DepthTypeEnum::CONNECTION_NUMBER; bool reverseOrder = resamplingDepthType == RiaDefines::DepthTypeEnum::CONNECTION_NUMBER;
std::vector<double> resampledValues;
std::map<RiaDefines::DepthTypeEnum, std::vector<double>> resampledDepths;
size_t segmentSearchStartIdx = 0; size_t segmentSearchStartIdx = 0;
for ( auto depth : depths ) for ( const auto& targetDepth : targetDepths )
{ {
bool foundPoint = false; bool foundPoint = false;
for ( size_t segmentStartIdx = segmentSearchStartIdx; segmentStartIdx < depthIt->second.size(); ++segmentStartIdx ) for ( size_t segmentStartIdx = segmentSearchStartIdx; segmentStartIdx < depthValues.size(); ++segmentStartIdx )
{ {
if ( std::fabs( depthIt->second[segmentStartIdx] - depth ) < eps ) // already have this depth point, if ( std::fabs( depthValues[segmentStartIdx] - targetDepth ) < eps ) // already have this depth point, reuse it
// reuse it
{ {
xValues.push_back( m_propertyValues[segmentStartIdx] ); // Copy all depth data for this segment
// Copy all depth types for this segment resampledValues.push_back( propertyValues[segmentStartIdx] );
for ( auto depthTypeValuesPair : m_depths ) for ( const auto& [depthType, depthValues] : originalDepths )
{ {
if ( depthTypeValuesPair.first != resamplingDepthType ) resampledDepths[depthType].push_back( depthValues[segmentStartIdx] );
{
resampledDepths[depthTypeValuesPair.first].push_back( depthTypeValuesPair.second[segmentStartIdx] );
}
} }
segmentSearchStartIdx = segmentStartIdx + 1; segmentSearchStartIdx = segmentStartIdx + 1;
foundPoint = true; foundPoint = true;
break; break;
} }
else if ( segmentStartIdx < depthIt->second.size() - 1 ) else if ( segmentStartIdx > 0 && segmentStartIdx < depthValues.size() )
{ {
double minDepthSegment = std::min( depthIt->second[segmentStartIdx], depthIt->second[segmentStartIdx + 1] ); // Interpolate between current and previous depth point
double maxDepthSegment = std::max( depthIt->second[segmentStartIdx], depthIt->second[segmentStartIdx + 1] ); const size_t firstIndex = segmentStartIdx - 1;
if ( cvf::Math::valueInRange( depth, minDepthSegment, maxDepthSegment ) ) const size_t secondIndex = segmentStartIdx;
double minDepthSegment = std::min( depthValues[firstIndex], depthValues[secondIndex] );
double maxDepthSegment = std::max( depthValues[firstIndex], depthValues[secondIndex] );
if ( cvf::Math::valueInRange( targetDepth, minDepthSegment, maxDepthSegment ) )
{ {
interpolateSegment( resamplingDepthType, depth, segmentStartIdx, xValues, resampledDepths, eps ); createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
targetDepth,
firstIndex,
secondIndex,
originalDepths,
propertyValues,
eps );
segmentSearchStartIdx = segmentStartIdx; segmentSearchStartIdx = segmentStartIdx;
foundPoint = true; foundPoint = true;
break; break;
@ -452,17 +477,36 @@ cvf::ref<RigWellLogCurveData> RigWellLogCurveData::calculateResampledCurveData(
} }
if ( !foundPoint ) if ( !foundPoint )
{ {
if ( isLeftOf( depth, depthIt->second.front(), reverseOrder, eps ) ) if ( isLeftOf( targetDepth, depthValues.front(), reverseOrder, eps ) )
{ {
// Extrapolate from front two // Extrapolate from front two
interpolateSegment( resamplingDepthType, depth, 0, xValues, resampledDepths, eps ); const size_t firstIndex = 0;
const size_t secondIndex = 1;
createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
targetDepth,
firstIndex,
secondIndex,
originalDepths,
propertyValues,
eps );
foundPoint = true; foundPoint = true;
} }
else if ( isRightOf( depth, depthIt->second.back(), reverseOrder, eps ) ) else if ( isRightOf( targetDepth, depthValues.back(), reverseOrder, eps ) )
{ {
// Extrapolate from end two // Extrapolate from end two
const size_t N = depthIt->second.size() - 1; const size_t N = depthValues.size() - 1;
interpolateSegment( resamplingDepthType, depth, N - 1, xValues, resampledDepths, eps ); const size_t N_1 = N - 1;
createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
targetDepth,
N_1,
N,
originalDepths,
propertyValues,
eps );
foundPoint = true; foundPoint = true;
} }
} }
@ -470,6 +514,18 @@ cvf::ref<RigWellLogCurveData> RigWellLogCurveData::calculateResampledCurveData(
CAF_ASSERT( foundPoint ); CAF_ASSERT( foundPoint );
} }
return std::make_pair( resampledValues, resampledDepths );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigWellLogCurveData> RigWellLogCurveData::calculateResampledCurveData( RiaDefines::DepthTypeEnum resamplingDepthType,
const std::vector<double>& depths ) const
{
const auto [xValues, resampledDepths] = createResampledValuesAndDepths( resamplingDepthType, depths, m_depths, m_propertyValues );
cvf::ref<RigWellLogCurveData> reSampledData = new RigWellLogCurveData;
reSampledData->setValuesAndDepths( xValues, resampledDepths, m_rkbDiff, m_depthUnit, true, m_useLogarithmicScale ); reSampledData->setValuesAndDepths( xValues, resampledDepths, m_rkbDiff, m_depthUnit, true, m_useLogarithmicScale );
return reSampledData; return reSampledData;
} }

View File

@ -82,12 +82,24 @@ public:
cvf::ref<RigWellLogCurveData> calculateResampledCurveData( double newMeasuredDepthStepSize ) const; cvf::ref<RigWellLogCurveData> calculateResampledCurveData( double newMeasuredDepthStepSize ) const;
cvf::ref<RigWellLogCurveData> calculateResampledCurveData( RiaDefines::DepthTypeEnum resamplingDepthType, cvf::ref<RigWellLogCurveData> calculateResampledCurveData( RiaDefines::DepthTypeEnum resamplingDepthType,
const std::vector<double>& depths ) const; const std::vector<double>& depths ) const;
void interpolateSegment( RiaDefines::DepthTypeEnum resamplingDepthType,
double depthValue, // Made static due to unit testing
size_t firstIndex, static void createAndAddInterpolatedSegmentValueAndDepths( std::vector<double>& resampledValues,
std::vector<double>& xValues, std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& resampledDepths,
std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& resampledDepths, RiaDefines::DepthTypeEnum resamplingDepthType,
const double eps ) const; double targetDepthValue,
size_t firstIndex,
size_t secondIndex,
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& originalDepths,
const std::vector<double>& propertyValues,
double eps );
// Made static due to unit testing
static std::pair<std::vector<double>, std::map<RiaDefines::DepthTypeEnum, std::vector<double>>>
createResampledValuesAndDepths( RiaDefines::DepthTypeEnum resamplingDepthType,
const std::vector<double>& targetDepths,
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& originalDepths,
const std::vector<double>& propertyValues );
private: private:
void calculateIntervalsOfContinousValidValues(); void calculateIntervalsOfContinousValidValues();

View File

@ -93,6 +93,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RigDeclineCurveCalculator-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RigDeclineCurveCalculator-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderFmuRft-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifReaderFmuRft-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellLogCalculatedCurve-Test.cpp
${CMAKE_CURRENT_LIST_DIR}/RigWellLogCurveData-Test.cpp
) )
if(RESINSIGHT_ENABLE_GRPC) if(RESINSIGHT_ENABLE_GRPC)

View File

@ -0,0 +1,197 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "gtest/gtest.h"
#include "RiaDefines.h"
#include "RigWellLogCurveData.h"
#include "cvfVector3.h"
#include <vector>
#include <iostream>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigWellLogCurveData, createAndAddInterpolatedSegmentValueAndDepths_first )
{
// Input data
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>> originalDepths =
{ { RiaDefines::DepthTypeEnum::MEASURED_DEPTH, { 0.0, 20.0, 40.0 } },
{ RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH, { 0.0, 30.0, 60.0 } },
{ RiaDefines::DepthTypeEnum::PSEUDO_LENGTH, { 0.0, 40.0, 80.0 } } };
const std::vector<double> propertyValues = { 0.0, 100.0, 150.0 };
const double eps = 1e-6;
// Output data
const auto resamplingDepthType = RiaDefines::DepthTypeEnum::MEASURED_DEPTH;
std::vector<double> resampledValues;
std::map<RiaDefines::DepthTypeEnum, std::vector<double>> resampledDepths;
// Target data (resampling with MEASURED_DEPTH)
const double targetDepthValue = 10.0; // Halfway between index 0 and 1 for MEASURED_DEPTH in originalDepths
const size_t firstIndex = 0;
const size_t secondIndex = firstIndex + 1;
// Call the function under test
RigWellLogCurveData::createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
targetDepthValue,
firstIndex,
secondIndex,
originalDepths,
propertyValues,
eps );
// Check the results
ASSERT_EQ( resampledValues.size(), size_t( 1 ) );
ASSERT_DOUBLE_EQ( resampledValues[0], 50.0 );
ASSERT_EQ( resampledDepths.size(), size_t( 3 ) );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH].size(), size_t( 1 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][0], 10.0 );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH].size(), size_t( 1 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][0], 15.0 );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH].size(), size_t( 1 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][0], 20.0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigWellLogCurveData, createAndAddInterpolatedSegmentValueAndDepths_second )
{
// Input data
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>> originalDepths =
{ { RiaDefines::DepthTypeEnum::MEASURED_DEPTH, { 0.0, 20.0, 40.0 } },
{ RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH, { 0.0, 30.0, 60.0 } },
{ RiaDefines::DepthTypeEnum::PSEUDO_LENGTH, { 0.0, 40.0, 80.0 } } };
const std::vector<double> propertyValues = { 0.0, 100.0, 150.0 };
const double eps = 1e-6;
// Output data
const auto resamplingDepthType = RiaDefines::DepthTypeEnum::MEASURED_DEPTH;
std::vector<double> resampledValues;
std::map<RiaDefines::DepthTypeEnum, std::vector<double>> resampledDepths;
// Target data (resampling with MEASURED_DEPTH)
const double firstTargetDepthValue = 10.0; // Halfway between first and second index for MEASURED_DEPTH in originalDepths
const double secondTargetDepthValue = 30.0; // Halfway between second and third index for MEASURED_DEPTH in originalDepths
const size_t firstIndex = 0;
const size_t secondIndex = 1;
const size_t thirdIndex = 2;
// Call the function under test with interpolating between first and second index
RigWellLogCurveData::createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
firstTargetDepthValue,
firstIndex,
secondIndex,
originalDepths,
propertyValues,
eps );
// Call the function under test with interpolating between second and third index
RigWellLogCurveData::createAndAddInterpolatedSegmentValueAndDepths( resampledValues,
resampledDepths,
resamplingDepthType,
secondTargetDepthValue,
secondIndex,
thirdIndex,
originalDepths,
propertyValues,
eps );
// Check the results
ASSERT_EQ( resampledValues.size(), size_t( 2 ) );
ASSERT_DOUBLE_EQ( resampledValues[0], 50.0 );
ASSERT_DOUBLE_EQ( resampledValues[1], 125.0 );
ASSERT_EQ( resampledDepths.size(), size_t( 3 ) );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH].size(), size_t( 2 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][0], 10.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][1], 30.0 );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH].size(), size_t( 2 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][0], 15.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][1], 45.0 );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH].size(), size_t( 2 ) );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][0], 20.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][1], 60.0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RigWellLogCurveData, CreateResampledValuesAndDepthsTest )
{
// Input data
RiaDefines::DepthTypeEnum resamplingDepthType = RiaDefines::DepthTypeEnum::MEASURED_DEPTH;
const std::vector<double> targetDepths = { 0.0, 5.0, 10.0, 15.0 };
const std::map<RiaDefines::DepthTypeEnum, std::vector<double>> originalDepths =
{ { RiaDefines::DepthTypeEnum::MEASURED_DEPTH, { 0.0, 10.0, 20.0 } },
{ RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH, { 0.0, 20.0, 40.0 } },
{ RiaDefines::DepthTypeEnum::PSEUDO_LENGTH, { 0.0, 30.0, 60.0 } } };
const std::vector<double> propertyValues = { 0.0, 100.0, 200.0 };
// Call the function under test
auto result = RigWellLogCurveData::createResampledValuesAndDepths( resamplingDepthType, targetDepths, originalDepths, propertyValues );
// Check the results
std::vector<double>& resampledPropertyValues = result.first;
std::map<RiaDefines::DepthTypeEnum, std::vector<double>>& resampledDepths = result.second;
const auto expectedSize = targetDepths.size();
ASSERT_EQ( resampledDepths.size(), originalDepths.size() );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH].size(), expectedSize );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH].size(), expectedSize );
ASSERT_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH].size(), expectedSize );
ASSERT_EQ( resampledPropertyValues.size(), expectedSize );
// Example assertions for the specific values
ASSERT_DOUBLE_EQ( resampledPropertyValues[0], 0.0 );
ASSERT_DOUBLE_EQ( resampledPropertyValues[1], 50.0 );
ASSERT_DOUBLE_EQ( resampledPropertyValues[2], 100.0 );
ASSERT_DOUBLE_EQ( resampledPropertyValues[3], 150.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][0], 0.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][1], 5.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][2], 10.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::MEASURED_DEPTH][3], 15.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][0], 0.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][1], 10.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][2], 20.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH][3], 30.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][0], 0.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][1], 15.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][2], 30.0 );
ASSERT_DOUBLE_EQ( resampledDepths[RiaDefines::DepthTypeEnum::PSEUDO_LENGTH][3], 45.0 );
}