mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#9439 Fix unstable location of generated well target at sea level
NB! This fix will update the location of well target at sea level, and can potentially change the MD from sea level to first user defined well target. This will affect completions defined for the modelled well, as they are defined by MD. * #9439 Make MD more predictable when toggling sea level target. * #9439 Avoid updating well path tangents when toggling sea level target * Disable IO of well target at sea level Co-authored-by: Magne Sjaastad <magne.sjaastad@ceetronsolutions.com>
This commit is contained in:
parent
befab37588
commit
254c74be13
@ -99,6 +99,10 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
|
||||
m_autoTargetAtSeaLevel = new RimWellPathTarget;
|
||||
m_autoTargetAtSeaLevel->setEnabled( false );
|
||||
|
||||
// Disable IO was introduced to avoid errors related to unstable location of well target at sea level.
|
||||
// https://github.com/OPM/ResInsight/issues/9439
|
||||
m_autoTargetAtSeaLevel.xmlCapability()->disableIO();
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_isAttachedToParentWell, "AttachedToParentWell", false, "Attached to Parent Well" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_fixedWellPathPoints, "FixedWellPathPoints", "" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_fixedMeasuredDepths, "FixedMeasuredDepths", "" );
|
||||
@ -257,17 +261,28 @@ std::vector<RimWellPathTarget*> RimWellPathGeometryDef::createTargets( const std
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
|
||||
{
|
||||
cvf::ref<RigWellPath> wellPathGeometry = new RigWellPath;
|
||||
// User defined well targets can be updated from 3D view or from table. Always update location for well target at
|
||||
// sea level.
|
||||
updateTargetAtSeaLevel();
|
||||
|
||||
if ( m_useAutoGeneratedTargetAtSeaLevel )
|
||||
{
|
||||
updateTargetAtSeaLevel();
|
||||
}
|
||||
double offsetMd = m_useAutoGeneratedTargetAtSeaLevel ? 0.0 : m_mdAtFirstTarget;
|
||||
return createWellPathGeometry( m_useAutoGeneratedTargetAtSeaLevel, offsetMd, true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry( bool useAutoGeneratedTargetAtSeaLevel,
|
||||
double offsetMd,
|
||||
bool updateTargets ) const
|
||||
{
|
||||
cvf::ref<RigWellPath> wellPathGeometry = new RigWellPath;
|
||||
|
||||
std::vector<cvf::Vec3d> wellPathPoints = m_fixedWellPathPoints;
|
||||
std::vector<double> measuredDepths = m_fixedMeasuredDepths;
|
||||
|
||||
RiaLineArcWellPathCalculator wellPathCalculator = lineArcWellPathCalculator();
|
||||
RiaLineArcWellPathCalculator wellPathCalculator =
|
||||
lineArcWellPathCalculator( useAutoGeneratedTargetAtSeaLevel, updateTargets );
|
||||
|
||||
if ( wellPathCalculator.lineArcEndpoints().size() >= 2 )
|
||||
{
|
||||
@ -275,15 +290,11 @@ cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
|
||||
auto [sampledWellPathPoints, sampledMeasuredDepths] = arcLineSampler.sampledPointsAndMDs( 30, false );
|
||||
wellPathPoints.insert( wellPathPoints.end(), sampledWellPathPoints.begin(), sampledWellPathPoints.end() );
|
||||
|
||||
double startMD = 0.0;
|
||||
double startMD = offsetMd;
|
||||
if ( !measuredDepths.empty() )
|
||||
{
|
||||
startMD = measuredDepths.back();
|
||||
}
|
||||
else if ( !m_useAutoGeneratedTargetAtSeaLevel )
|
||||
{
|
||||
startMD = m_mdAtFirstTarget;
|
||||
}
|
||||
|
||||
for ( auto md : sampledMeasuredDepths )
|
||||
{
|
||||
@ -306,7 +317,8 @@ cvf::ref<RigWellPath> RimWellPathGeometryDef::createWellPathGeometry()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaWellPlanCalculator::WellPlanSegment> RimWellPathGeometryDef::wellPlan() const
|
||||
{
|
||||
RiaLineArcWellPathCalculator wellPathCalculator = lineArcWellPathCalculator();
|
||||
RiaLineArcWellPathCalculator wellPathCalculator =
|
||||
lineArcWellPathCalculator( m_useAutoGeneratedTargetAtSeaLevel, false );
|
||||
|
||||
RiaWellPlanCalculator wpCalc( wellPathCalculator.startTangent(), wellPathCalculator.lineArcEndpoints() );
|
||||
|
||||
@ -517,21 +529,28 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change
|
||||
RimWellPathGeometryDefTools::updateLinkedGeometryDefinitions( linkedDefs, delta );
|
||||
}
|
||||
}
|
||||
else if ( changedField == &m_useAutoGeneratedTargetAtSeaLevel && !m_useAutoGeneratedTargetAtSeaLevel )
|
||||
else if ( changedField == &m_useAutoGeneratedTargetAtSeaLevel )
|
||||
{
|
||||
auto firstTarget = firstActiveTarget();
|
||||
if ( firstTarget != nullptr )
|
||||
updateTargetAtSeaLevel();
|
||||
|
||||
if ( !m_useAutoGeneratedTargetAtSeaLevel() )
|
||||
{
|
||||
auto firstLocationXYZ = firstTarget->targetPointXYZ() + anchorPointXyz();
|
||||
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;
|
||||
// Temporarily enable target at sea level to be able to create a complete geometry to find MD of first
|
||||
// target of the complete geometry
|
||||
auto wellPathGeo = createWellPathGeometry( true, 0.0, false );
|
||||
|
||||
double mdAtFirstTarget = wellPathGeo->closestMeasuredDepth( firstLocationXYZ );
|
||||
m_mdAtFirstTarget = mdAtFirstTarget;
|
||||
double mdAtFirstTarget = wellPathGeo->closestMeasuredDepth( firstLocationXYZ );
|
||||
m_mdAtFirstTarget = mdAtFirstTarget;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mdAtFirstTarget = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,10 +603,18 @@ void RimWellPathGeometryDef::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTre
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellPathTarget*> RimWellPathGeometryDef::activeWellTargets() const
|
||||
{
|
||||
return activeWellTargets( m_useAutoGeneratedTargetAtSeaLevel );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellPathTarget*> RimWellPathGeometryDef::activeWellTargets( bool useAutoGeneratedTargetAtSeaLevel ) const
|
||||
{
|
||||
std::vector<RimWellPathTarget*> active;
|
||||
|
||||
if ( m_useAutoGeneratedTargetAtSeaLevel && !m_wellTargets.empty() && m_autoTargetAtSeaLevel )
|
||||
if ( useAutoGeneratedTargetAtSeaLevel && !m_wellTargets.empty() && m_autoTargetAtSeaLevel )
|
||||
{
|
||||
active.push_back( m_autoTargetAtSeaLevel );
|
||||
}
|
||||
@ -606,11 +633,12 @@ std::vector<RimWellPathTarget*> RimWellPathGeometryDef::activeWellTargets() cons
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaLineArcWellPathCalculator RimWellPathGeometryDef::lineArcWellPathCalculator() const
|
||||
RiaLineArcWellPathCalculator RimWellPathGeometryDef::lineArcWellPathCalculator( bool useAutoGeneratedTargetAtSeaLevel,
|
||||
bool updateTargets ) const
|
||||
{
|
||||
std::vector<RimWellPathTarget*> activeTargets;
|
||||
|
||||
auto candidates = activeWellTargets();
|
||||
auto candidates = activeWellTargets( useAutoGeneratedTargetAtSeaLevel );
|
||||
if ( !candidates.empty() )
|
||||
{
|
||||
activeTargets.push_back( candidates.front() );
|
||||
@ -637,18 +665,21 @@ RiaLineArcWellPathCalculator RimWellPathGeometryDef::lineArcWellPathCalculator()
|
||||
const std::vector<RiaLineArcWellPathCalculator::WellTargetStatus>& targetStatuses =
|
||||
wellPathCalculator.targetStatuses();
|
||||
|
||||
for ( size_t tIdx = 0; tIdx < activeTargets.size(); ++tIdx )
|
||||
if ( updateTargets )
|
||||
{
|
||||
activeTargets[tIdx]->setDerivedTangent( targetStatuses[tIdx].resultAzimuthRadians,
|
||||
targetStatuses[tIdx].resultInclinationRadians );
|
||||
for ( size_t tIdx = 0; tIdx < activeTargets.size(); ++tIdx )
|
||||
{
|
||||
activeTargets[tIdx]->setDerivedTangent( targetStatuses[tIdx].resultAzimuthRadians,
|
||||
targetStatuses[tIdx].resultInclinationRadians );
|
||||
|
||||
activeTargets[tIdx]->setRadius1Data( targetStatuses[tIdx].isRadius1Editable,
|
||||
targetStatuses[tIdx].hasOverriddenRadius1,
|
||||
targetStatuses[tIdx].resultRadius1 );
|
||||
activeTargets[tIdx]->setRadius1Data( targetStatuses[tIdx].isRadius1Editable,
|
||||
targetStatuses[tIdx].hasOverriddenRadius1,
|
||||
targetStatuses[tIdx].resultRadius1 );
|
||||
|
||||
activeTargets[tIdx]->setRadius2Data( targetStatuses[tIdx].isRadius2Editable,
|
||||
targetStatuses[tIdx].hasOverriddenRadius2,
|
||||
targetStatuses[tIdx].resultRadius2 );
|
||||
activeTargets[tIdx]->setRadius2Data( targetStatuses[tIdx].isRadius2Editable,
|
||||
targetStatuses[tIdx].hasOverriddenRadius2,
|
||||
targetStatuses[tIdx].resultRadius2 );
|
||||
}
|
||||
}
|
||||
|
||||
return wellPathCalculator;
|
||||
@ -661,6 +692,12 @@ void RimWellPathGeometryDef::updateTargetAtSeaLevel()
|
||||
{
|
||||
if ( m_useAutoGeneratedTargetAtSeaLevel && !m_wellTargets.empty() )
|
||||
{
|
||||
// Update tangents for existing well targets without the target at sea level.
|
||||
bool useAutoGeneratedTargetAtSeaLevel = false;
|
||||
double offsetMd = 0.0;
|
||||
bool updateTargets = true;
|
||||
createWellPathGeometry( useAutoGeneratedTargetAtSeaLevel, offsetMd, updateTargets );
|
||||
|
||||
cvf::Vec3d newPos = cvf::Vec3d::ZERO;
|
||||
|
||||
auto firstTarget = m_wellTargets[0];
|
||||
|
@ -95,6 +95,10 @@ public:
|
||||
bool showAbsoluteCoordinates() const;
|
||||
|
||||
protected:
|
||||
std::vector<RimWellPathTarget*> activeWellTargets( bool useAutoGeneratedTargetAtSeaLevel ) const;
|
||||
cvf::ref<RigWellPath>
|
||||
createWellPathGeometry( bool useAutoGeneratedTargetAtSeaLevel, double offsetMd, bool updateTargets ) const;
|
||||
|
||||
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
|
||||
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field,
|
||||
@ -113,7 +117,8 @@ private:
|
||||
void initAfterRead() override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
RiaLineArcWellPathCalculator lineArcWellPathCalculator() const;
|
||||
RiaLineArcWellPathCalculator lineArcWellPathCalculator( bool useAutoGeneratedTargetAtSeaLevel,
|
||||
bool updateTargets = true ) const;
|
||||
|
||||
void updateTargetAtSeaLevel();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user