Improve well path modeling

* Improve handling of MD at first target
* When sea level well target is disabled, update MD of first target
* Show well target spheres by default, allow toggling of spheres
* Activate well target modifiers when clicking on well targets
* Remove selection update causing an unstable 3D view
* Improve display and handling of multiple locations
* Add special 3D target for tie in well target
* Add slider to tie in MD input field
* Show MD in well path target table
* Delete all well path laterals when deleting a well path

* Python : Add lateral to parent well
* Python : Add perforation interval
This commit is contained in:
Magne Sjaastad
2021-08-13 16:48:33 +02:00
committed by GitHub
parent 40bd4c285a
commit 8dbb1d5ccd
50 changed files with 1377 additions and 310 deletions

View File

@@ -315,41 +315,15 @@ cvf::Vec3d RigWellPath::tangentAlongWellPath( double measuredDepth ) const
//--------------------------------------------------------------------------------------------------
double RigWellPath::wellPathAzimuthAngle( const cvf::Vec3d& position ) const
{
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
double closestDistance = cvf::UNDEFINED_DOUBLE;
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
{
cvf::Vec3d p1 = m_wellPathPoints[i - 1];
cvf::Vec3d p2 = m_wellPathPoints[i - 0];
double candidateDistance = cvf::GeometryTools::linePointSquareDist( p1, p2, position );
if ( candidateDistance < closestDistance )
{
closestDistance = candidateDistance;
closestIndex = i;
}
}
// For vertical well (x-component of direction = 0) returned angle will be 90.
double azimuthAngleDegrees = 90.0;
if ( closestIndex != cvf::UNDEFINED_DOUBLE )
cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED;
cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED;
twoClosestPoints( position, &p1, &p2 );
if ( !p1.isUndefined() )
{
cvf::Vec3d p1;
cvf::Vec3d p2;
if ( closestIndex > 0 )
{
p1 = m_wellPathPoints[closestIndex - 1];
p2 = m_wellPathPoints[closestIndex - 0];
}
else
{
p1 = m_wellPathPoints[closestIndex + 1];
p2 = m_wellPathPoints[closestIndex + 0];
}
cvf::Vec3d direction = p2 - p1;
if ( fabs( direction.y() ) > 1e-5 )
@@ -370,34 +344,11 @@ void RigWellPath::twoClosestPoints( const cvf::Vec3d& position, cvf::Vec3d* p1,
{
CVF_ASSERT( p1 && p2 );
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
double closestDistance = cvf::UNDEFINED_DOUBLE;
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
auto closeIndices = closestIndices( position );
if ( closeIndices.first != cvf::UNDEFINED_SIZE_T )
{
cvf::Vec3d point1 = m_wellPathPoints[i - 1];
cvf::Vec3d point2 = m_wellPathPoints[i - 0];
double candidateDistance = cvf::GeometryTools::linePointSquareDist( point1, point2, position );
if ( candidateDistance < closestDistance )
{
closestDistance = candidateDistance;
closestIndex = i;
}
}
if ( closestIndex != cvf::UNDEFINED_SIZE_T )
{
if ( closestIndex > 0 )
{
*p1 = m_wellPathPoints[closestIndex - 1];
*p2 = m_wellPathPoints[closestIndex - 0];
}
else
{
*p1 = m_wellPathPoints[closestIndex + 1];
*p2 = m_wellPathPoints[closestIndex + 0];
}
*p1 = m_wellPathPoints[closeIndices.first];
*p2 = m_wellPathPoints[closeIndices.second];
}
}
@@ -429,6 +380,32 @@ double RigWellPath::identicalTubeLength( const RigWellPath& other ) const
return identicalLength;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigWellPath::closestMeasuredDepth( const cvf::Vec3d& position ) const
{
auto [firstIndex, secondIndex] = closestIndices( position );
if ( firstIndex != cvf::UNDEFINED_SIZE_T )
{
cvf::Vec3d p1 = m_wellPathPoints[firstIndex];
cvf::Vec3d p2 = m_wellPathPoints[secondIndex];
double diffP1 = ( p1 - position ).lengthSquared();
double diffP2 = ( p2 - position ).lengthSquared();
double weigth1 = diffP2 / ( diffP1 + diffP2 );
double measureDepth1 = m_measuredDepths[firstIndex];
double measureDepth2 = m_measuredDepths[secondIndex];
double interpolatedValue = measureDepth1 * weigth1 + measureDepth2 * ( 1.0 - weigth1 );
return interpolatedValue;
}
return -1.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -681,3 +658,40 @@ std::vector<cvf::Vec3d> RigWellPath::clipPolylineStartAboveZ( const std::vector<
return clippedPolyLine;
}
//--------------------------------------------------------------------------------------------------
// Returns the closes indices with smallest index first
// If not found, cvf::UNDEFINED_SIZE_T is returned for both
//--------------------------------------------------------------------------------------------------
std::pair<size_t, size_t> RigWellPath::closestIndices( const cvf::Vec3d& position ) const
{
size_t closestIndex = cvf::UNDEFINED_SIZE_T;
double closestDistance = cvf::UNDEFINED_DOUBLE;
for ( size_t i = 1; i < m_wellPathPoints.size(); i++ )
{
cvf::Vec3d point1 = m_wellPathPoints[i - 1];
cvf::Vec3d point2 = m_wellPathPoints[i - 0];
double candidateDistance = cvf::GeometryTools::linePointSquareDist( point1, point2, position );
if ( candidateDistance < closestDistance )
{
closestDistance = candidateDistance;
closestIndex = i;
}
}
if ( closestIndex != cvf::UNDEFINED_SIZE_T )
{
if ( closestIndex > 0 )
{
return { closestIndex - 1, closestIndex };
}
else
{
return { closestIndex, closestIndex + 1 };
}
}
return { cvf::UNDEFINED_SIZE_T, cvf::UNDEFINED_SIZE_T };
}

View File

@@ -70,6 +70,7 @@ public:
double wellPathAzimuthAngle( const cvf::Vec3d& position ) const;
void twoClosestPoints( const cvf::Vec3d& position, cvf::Vec3d* p1, cvf::Vec3d* p2 ) const;
double identicalTubeLength( const RigWellPath& otherWellPathGeometry ) const;
double closestMeasuredDepth( const cvf::Vec3d& position ) const;
static cvf::ref<RigWellPath> commonGeometry( const std::vector<const RigWellPath*>& allGeometries );
void setUniqueStartAndEndIndex( size_t uniqueStartIndex, size_t uniqueEndIndex );
@@ -90,6 +91,9 @@ public:
double* horizontalLengthAlongWellToClipPoint,
size_t* indexToFirstVisibleSegment );
private:
std::pair<size_t, size_t> closestIndices( const cvf::Vec3d& position ) const;
private:
std::vector<cvf::Vec3d> m_wellPathPoints;
std::vector<double> m_measuredDepths;

View File

@@ -53,10 +53,6 @@ void RigWellPathGeometryExporter::exportWellPathGeometry( gsl::not_null<const Ri
{
rkbOffset = modeledWellPath->geometryDefinition()->airGap();
}
else
{
rkbOffset = modeledWellPath->geometryDefinition()->mdAtFirstTarget();
}
}
}
exportWellPathGeometry( *wellPathGeom, mdStepSize, rkbOffset, xValues, yValues, tvdValues, mdValues );

View File

@@ -23,6 +23,7 @@
#include "cvfMath.h"
#include "cvfMatrix3.h"
#include "RiaOffshoreSphericalCoords.h"
#include <algorithm>
#include <cmath>
@@ -133,6 +134,61 @@ std::vector<double> RigWellPathGeometryTools::interpolateMdFromTvd( const std::v
return interpolatedMdValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double>
RigWellPathGeometryTools::calculateAzimuthAndInclinationAtMd( double measuredDepth,
gsl::not_null<const RigWellPath*> wellPathGeometry )
{
int mdIndex = -1;
auto mdList = wellPathGeometry->measuredDepths();
for ( int i = 0; i < (int)mdList.size(); i++ )
{
if ( mdList[i] > measuredDepth )
{
mdIndex = i - 1;
break;
}
}
auto ptList = wellPathGeometry->wellPathPoints();
if ( mdIndex >= 0 && mdIndex < (int)ptList.size() - 1 )
{
const auto& v2 = cvf::Vec3d( ptList[mdIndex] );
const auto& v3 = cvf::Vec3d( ptList[mdIndex + 1] );
auto v32 = ( v3 - v2 ).getNormalized();
auto v13mean = v32;
if ( mdIndex > 0 )
{
const auto& v1 = cvf::Vec3d( ptList[mdIndex - 1] );
auto v21 = ( v2 - v1 ).getNormalized();
v13mean = ( v21 + v32 ) / 2;
}
auto v24mean = v32;
if ( mdIndex < (int)ptList.size() - 2 )
{
const auto& v4 = cvf::Vec3d( ptList[mdIndex + 2] );
auto v43 = ( v4 - v3 ).getNormalized();
v24mean = ( v32 + v43 ) / 2;
}
double weight = ( measuredDepth - mdList[mdIndex] ) / ( mdList[mdIndex + 1] - mdList[mdIndex] );
auto vTan = v13mean * ( 1.0 - weight ) + v24mean * ( weight );
RiaOffshoreSphericalCoords coords( vTan );
return { coords.azi(), coords.inc() };
}
return { 0.0, 0.0 };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -25,6 +25,8 @@
#include <vector>
#include <gsl/gsl>
class RigWellPath;
//==================================================================================================
@@ -45,6 +47,9 @@ public:
const std::vector<double>& originalTvdValues,
const std::vector<double>& tvdValuesToInterpolateFrom );
static std::pair<double, double>
calculateAzimuthAndInclinationAtMd( double measuredDepth, gsl::not_null<const RigWellPath*> wellPathGeometry );
private:
static std::vector<cvf::Vec3d> interpolateUndefinedNormals( const cvf::Vec3d& planeNormal,
const std::vector<cvf::Vec3d>& normals,