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

@@ -34,6 +34,7 @@
#include "RimWellPathTarget.h"
#include "RimWellPathTieIn.h"
#include "RigWellPathGeometryTools.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiTreeOrdering.h"
@@ -87,7 +88,7 @@ void RimModeledWellPath::createWellPathGeometry()
//--------------------------------------------------------------------------------------------------
void RimModeledWellPath::updateWellPathVisualization()
{
this->setWellPathGeometry( m_geometryDefinition->createWellPathGeometry().p() );
createWellPathGeometry();
std::vector<RimPlotCurve*> refferingCurves;
this->objectsWithReferringPtrFieldsOfType( refferingCurves );
@@ -288,7 +289,10 @@ void RimModeledWellPath::updateTieInLocationFromParentWell()
cvf::Vec3d relativePointXYZ = lastPointXYZ - referencePointXYZ;
auto firstTarget = targets.front();
firstTarget->setPointXYZ( relativePointXYZ );
const auto [azimuth, inclination] =
RigWellPathGeometryTools::calculateAzimuthAndInclinationAtMd( tieIn->tieInMeasuredDepth(),
parentWellPath->wellPathGeometry() );
firstTarget->setAsPointXYZAndTangentTarget( relativePointXYZ, azimuth, inclination );
updateGeometry( true );
}

View File

@@ -137,8 +137,6 @@ RimWellPath::RimWellPath()
CAF_PDM_InitFieldNoDefault( &m_wellPathTieIn, "WellPathTieIn", "well Path Tie-In", "", "", "" );
m_wellPathTieIn = new RimWellPathTieIn;
m_wellPathTieIn->connectWellPaths( nullptr, this, 0.0 );
this->setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
@@ -1170,6 +1168,31 @@ std::vector<RimWellPath*> RimWellPath::allWellPathLaterals() const
return laterals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellPath*> RimWellPath::wellPathLaterals() const
{
std::vector<RimWellPath*> laterals;
std::vector<caf::PdmObjectHandle*> referringObjects;
this->objectsWithReferringPtrFields( referringObjects );
for ( auto obj : referringObjects )
{
if ( auto tieIn = dynamic_cast<RimWellPathTieIn*>( obj ) )
{
auto tieInWellPath = tieIn->childWell();
if ( tieInWellPath == this ) continue;
if ( tieInWellPath )
{
laterals.push_back( tieInWellPath );
}
}
}
return laterals;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -163,6 +163,7 @@ public:
RimWellPath* topLevelWellPath();
const RimWellPath* topLevelWellPath() const;
std::vector<RimWellPath*> allWellPathLaterals() const;
std::vector<RimWellPath*> wellPathLaterals() const;
RimWellPathTieIn* wellPathTieIn() const;
void connectWellPaths( RimWellPath* childWell, double tieInMeasuredDepth );

View File

@@ -583,6 +583,15 @@ void RimWellPathCollection::deleteAllWellPaths()
updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection::deleteWell( RimWellPath* wellPath )
{
m_wellPaths.removeChildObject( wellPath );
delete wellPath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -98,6 +98,7 @@ public:
void removeWellPath( gsl::not_null<RimWellPath*> wellPath );
void deleteAllWellPaths();
void deleteWell( RimWellPath* wellPath );
void groupWellPaths( const std::vector<RimWellPath*>& wellPaths );
void rebuildWellPathNodes();

View File

@@ -105,7 +105,7 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
CAF_PDM_InitScriptableField( &m_linkReferencePointUpdates,
"LinkReferencePointUpdates",
false,
"Link Reference Point Updates",
"Link Reference Point",
"",
"",
"" );
@@ -121,7 +121,7 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
CAF_PDM_InitField( &m_pickPointsEnabled, "m_pickPointsEnabled", false, "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_pickPointsEnabled );
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", false, "Spheres", "", "", "" );
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", true, "Spheres", "", "", "" );
CAF_PDM_InitField( &m_sphereColor, "SphereColor", cvf::Color3f( cvf::Color3f::CEETRON ), "Sphere Color", "", "", "" );
CAF_PDM_InitField( &m_sphereRadiusFactor, "SphereRadiusFactor", 0.15, "Sphere Radius Factor", "", "", "" );
}
@@ -289,7 +289,17 @@ cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
RiaPolyArcLineSampler arcLineSampler( wellPathCalculator.startTangent(), wellPathCalculator.lineArcEndpoints() );
auto [sampledWellPathPoints, sampledMeasuredDepths] = arcLineSampler.sampledPointsAndMDs( 30, false );
wellPathPoints.insert( wellPathPoints.end(), sampledWellPathPoints.begin(), sampledWellPathPoints.end() );
double startMD = measuredDepths.empty() ? 0.0 : measuredDepths.back();
double startMD = 0.0;
if ( !measuredDepths.empty() )
{
startMD = measuredDepths.back();
}
else if ( !m_useAutoGeneratedTargetAtSeaLevel )
{
startMD = m_mdAtFirstTarget;
}
for ( auto md : sampledMeasuredDepths )
{
measuredDepths.push_back( md + startMD );
@@ -523,6 +533,23 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change
RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( linkedDefs, delta );
}
}
else if ( changedField == &m_useAutoGeneratedTargetAtSeaLevel && !m_useAutoGeneratedTargetAtSeaLevel )
{
auto firstTarget = firstActiveTarget();
if ( firstTarget != nullptr )
{
auto firstLocationXYZ = firstTarget->targetPointXYZ() + anchorPointXyz();
// Temporarily enable target at sea level to be able to create a complete geometry to find MD of first
// target of the complete geometry
m_useAutoGeneratedTargetAtSeaLevel = true;
auto wellPathGeo = createWellPathGeometry();
m_useAutoGeneratedTargetAtSeaLevel = false;
double mdAtFirstTarget = wellPathGeo->closestMeasuredDepth( firstLocationXYZ );
m_mdAtFirstTarget = mdAtFirstTarget;
}
}
changed.send( false );
}
@@ -759,6 +786,14 @@ void RimWellPathGeometryDef::defineObjectEditorAttribute( QString uiConfigName,
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimWellPathGeometryDef::objectToggleField()
{
return &m_showSpheres;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -102,6 +102,7 @@ protected:
caf::PdmUiEditorAttribute* attribute ) override;
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
caf::PdmFieldHandle* objectToggleField() override;
void onTargetMoved( const caf::SignalEmitter* emitter, bool fullUpdate );

View File

@@ -43,7 +43,7 @@ void caf::AppEnum<RimWellPathTarget::TargetTypeEnum>::setUp()
{
addItem( RimWellPathTarget::TargetTypeEnum::POINT_AND_TANGENT, "POINT_AND_TANGENT", "Point and Tangent" );
addItem( RimWellPathTarget::TargetTypeEnum::POINT, "POINT", "Point" );
setDefault( RimWellPathTarget::TargetTypeEnum::POINT_AND_TANGENT );
setDefault( RimWellPathTarget::TargetTypeEnum::POINT );
}
} // namespace caf
//--------------------------------------------------------------------------------------------------
@@ -51,7 +51,7 @@ void caf::AppEnum<RimWellPathTarget::TargetTypeEnum>::setUp()
//--------------------------------------------------------------------------------------------------
RimWellPathTarget::RimWellPathTarget()
: moved( this )
, m_targetType( TargetTypeEnum::POINT_AND_TANGENT )
, m_targetType( TargetTypeEnum::POINT )
, m_targetPointXYD( cvf::Vec3d::ZERO )
, m_azimuth( 0.0 )
, m_inclination( 0.0 )
@@ -69,10 +69,13 @@ RimWellPathTarget::RimWellPathTarget()
m_isLocked.uiCapability()->setUiHidden( true );
CAF_PDM_InitScriptableFieldNoDefault( &m_targetPointXYD, "TargetPoint", "Relative Coord", "", "", "" );
CAF_PDM_InitScriptableFieldNoDefault( &m_targetPointForDisplay, "TargetPointForDisplay", "UTM Coord", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_targetPointForDisplay, "TargetPointForDisplay", "UTM Coord", "", "", "" );
m_targetPointForDisplay.registerGetMethod( this, &RimWellPathTarget::targetPointForDisplayXYD );
m_targetPointForDisplay.registerSetMethod( this, &RimWellPathTarget::setTargetPointFromDisplayCoord );
CAF_PDM_InitScriptableFieldNoDefault( &m_targetMeasuredDepth, "TargetMeasuredDepth", "MD", "", "", "" );
m_targetMeasuredDepth.registerGetMethod( this, &RimWellPathTarget::measuredDepth );
CAF_PDM_InitScriptableField( &m_dogleg1, "Dogleg1", 3.0, "DL in", "", "[deg/30m]", "" );
CAF_PDM_InitScriptableField( &m_dogleg2, "Dogleg2", 3.0, "DL out", "", "[deg/30m]", "" );
@@ -224,10 +227,8 @@ double RimWellPathTarget::azimuth() const
{
return cvf::Math::toRadians( m_azimuth );
}
else
{
return std::numeric_limits<double>::infinity();
}
return std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
@@ -239,10 +240,8 @@ double RimWellPathTarget::inclination() const
{
return cvf::Math::toRadians( m_inclination );
}
else
{
return std::numeric_limits<double>::infinity();
}
return std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
@@ -441,6 +440,28 @@ void RimWellPathTarget::setTargetPointFromDisplayCoord( const cvf::Vec3d& coordI
m_targetPointXYD = newCoordInXYD;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellPathTarget::measuredDepth() const
{
RimWellPath* wellPath = nullptr;
this->firstAncestorOfType( wellPath );
auto geoDef = geometryDefinition();
if ( geoDef && wellPath && wellPath->wellPathGeometry() )
{
auto offsetXYZ = geoDef->anchorPointXyz();
auto coordXYZ = targetPointXYZ() + offsetXYZ;
auto wellPathGeo = wellPath->wellPathGeometry();
return wellPathGeo->closestMeasuredDepth( coordXYZ );
}
return 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -85,6 +85,7 @@ private:
cvf::Vec3d targetPointForDisplayXYD() const;
void setTargetPointFromDisplayCoord( const cvf::Vec3d& coordInXYZ );
double measuredDepth() const;
RimWellPathGeometryDef* geometryDefinition() const;
@@ -96,9 +97,11 @@ private:
caf::PdmField<caf::AppEnum<TargetTypeEnum>> m_targetType;
caf::PdmField<cvf::Vec3d> m_targetPointXYD;
caf::PdmProxyValueField<cvf::Vec3d> m_targetPointForDisplay;
caf::PdmField<double> m_azimuth;
caf::PdmField<double> m_inclination;
caf::PdmField<double> m_dogleg1;
caf::PdmField<double> m_dogleg2;
caf::PdmField<bool> m_hasTangentConstraintUiField;
caf::PdmProxyValueField<double> m_targetMeasuredDepth;
caf::PdmField<double> m_azimuth;
caf::PdmField<double> m_inclination;
caf::PdmField<double> m_dogleg1;
caf::PdmField<double> m_dogleg2;
caf::PdmField<bool> m_hasTangentConstraintUiField;
};

View File

@@ -30,7 +30,8 @@
#include "RiuMainWindow.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "RigWellPathGeometryTools.h"
#include "cafPdmUiDoubleSliderEditor.h"
CAF_PDM_SOURCE_INIT( RimWellPathTieIn, "RimWellPathTieIn" );
@@ -44,7 +45,7 @@ RimWellPathTieIn::RimWellPathTieIn()
CAF_PDM_InitFieldNoDefault( &m_parentWell, "ParentWellPath", "Parent Well Path", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_childWell, "ChildWellPath", "ChildWellPath", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_tieInMeasuredDepth, "TieInMeasuredDepth", "Tie In Measured Depth", "", "", "" );
m_tieInMeasuredDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
m_tieInMeasuredDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_addValveAtConnection, "AddValveAtConnection", false, "Add Outlet Valve for Branches", "", "", "" );
@@ -227,3 +228,32 @@ QList<caf::PdmOptionItemInfo> RimWellPathTieIn::calculateValueOptions( const caf
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_tieInMeasuredDepth )
{
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>( attribute );
if ( myAttr && parentWell() )
{
double minimumValue = 0.0, maximumValue = 0.0;
auto wellPathGeo = parentWell()->wellPathGeometry();
if ( wellPathGeo )
{
minimumValue = wellPathGeo->measuredDepths().front();
maximumValue = wellPathGeo->measuredDepths().back();
myAttr->m_minimum = minimumValue;
myAttr->m_maximum = maximumValue;
}
}
}
}

View File

@@ -53,6 +53,10 @@ private:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
private:
caf::PdmPtrField<RimWellPath*> m_parentWell;
caf::PdmPtrField<RimWellPath*> m_childWell;