Major rewrite of MSW export model

This commit is contained in:
Magne Sjaastad 2021-04-13 07:22:56 +02:00
parent 9ecfefe094
commit 63690d5196
65 changed files with 2766 additions and 2225 deletions

View File

@ -10,7 +10,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewValveFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewValveTemplateFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewValveAtMeasuredDepthFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicDeleteValveTemplateFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathImportCompletionsFileFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathImportPerforationIntervalsFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewStimPlanModelPlotFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFractureStatisticsFeature.h
@ -27,7 +26,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewValveFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewValveTemplateFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewValveAtMeasuredDepthFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicDeleteValveTemplateFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathImportCompletionsFileFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathImportPerforationIntervalsFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewStimPlanModelPlotFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFractureStatisticsFeature.cpp

View File

@ -27,7 +27,6 @@
#include "Rim3dView.h"
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimProject.h"
#include "RimWellPathCollection.h"
#include "RimWellPathCompletions.h"

View File

@ -1,128 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil 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 "RicWellPathImportCompletionsFileFeature.h"
#include "RiaApplication.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimProject.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathCompletions.h"
#include "Riu3DMainWindowTools.h"
#include "RiuFileDialogTools.h"
#include "cafSelectionManager.h"
#include <QAction>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT( RicWellPathImportCompletionsFileFeature, "RicWellPathImportCompletionsFileFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathImportCompletionsFileFeature::isCommandEnabled()
{
if ( RicWellPathImportCompletionsFileFeature::selectedWellPathCollection() != nullptr )
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathImportCompletionsFileFeature::onActionTriggered( bool isChecked )
{
RimImportedFishboneLateralsCollection* fishbonesWellPathCollection =
RicWellPathImportCompletionsFileFeature::selectedWellPathCollection();
CVF_ASSERT( fishbonesWellPathCollection );
// Open dialog box to select well path files
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( "WELLPATH_DIR" );
QStringList wellPathFilePaths = RiuFileDialogTools::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(),
"Import Fishbone Laterals",
defaultDir,
"Well Path Laterals (*.json *.asc *.asci "
"*.ascii *.dev);;All Files (*.*)" );
if ( wellPathFilePaths.size() < 1 ) return;
// Remember the path to next time
app->setLastUsedDialogDirectory( "WELLPATH_DIR", QFileInfo( wellPathFilePaths.last() ).absolutePath() );
fishbonesWellPathCollection->importCompletionsFromFile( wellPathFilePaths );
RimWellPathCollection* wellPathCollection;
fishbonesWellPathCollection->firstAncestorOrThisOfType( wellPathCollection );
if ( wellPathCollection )
{
wellPathCollection->updateConnectedEditors();
}
if ( app->project() )
{
app->project()->scheduleCreateDisplayModelAndRedrawAllViews();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathImportCompletionsFileFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Import Fishbone Laterals" );
actionToSetup->setIcon( QIcon( ":/FishBoneGroupFromFile16x16.png" ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimImportedFishboneLateralsCollection* RicWellPathImportCompletionsFileFeature::selectedWellPathCollection()
{
RimFishbonesCollection* objToFind = nullptr;
caf::PdmUiItem* pdmUiItem = caf::SelectionManager::instance()->selectedItem();
caf::PdmObjectHandle* objHandle = dynamic_cast<caf::PdmObjectHandle*>( pdmUiItem );
if ( objHandle )
{
objHandle->firstAncestorOrThisOfType( objToFind );
}
if ( objToFind == nullptr )
{
std::vector<RimWellPath*> wellPaths;
caf::SelectionManager::instance()->objectsByType( &wellPaths );
if ( !wellPaths.empty() )
{
return wellPaths[0]->fishbonesCollection()->wellPathCollection();
}
}
else
{
return objToFind->wellPathCollection();
}
return nullptr;
}

View File

@ -1,40 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 Statoil 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
class RimImportedFishboneLateralsCollection;
//==================================================================================================
///
//==================================================================================================
class RicWellPathImportCompletionsFileFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
// Overrides
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
static RimImportedFishboneLateralsCollection* selectedWellPathCollection();
};

View File

@ -21,6 +21,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicMswValveAccumulators.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureTextReportFeatureImpl.h
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureReportItem.h
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForTemporaryLgrsFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicMswTableFormatterTools.h
)
@ -46,6 +47,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicMswValveAccumulators.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureTextReportFeatureImpl.cpp
${CMAKE_CURRENT_LIST_DIR}/RicWellPathFractureReportItem.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportCompletionsForTemporaryLgrsFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicMswTableFormatterTools.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES

View File

@ -83,7 +83,7 @@ RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi()
CAF_PDM_InitField( &timeStep, "TimeStepIndex", 0, " Time Step", "", "", "" );
CAF_PDM_InitField( &includeMsw, "IncludeMSW", true, "Include Multi Segment Well Model", "", "", "" );
CAF_PDM_InitField( &includeMsw, "IncludeMSW", true, "Multi Segment Well Model", "", "", "" );
CAF_PDM_InitField( &useLateralNTG, "UseLateralNTG", false, "Use NTG Horizontally", "", "", "" );
@ -112,16 +112,17 @@ RicExportCompletionDataSettingsUi::RicExportCompletionDataSettingsUi()
"",
"" );
CAF_PDM_InitField( &m_exportDataSourceAsComment,
"ExportDataSourceAsComment",
true,
"Export Data Source In Comment",
CAF_PDM_InitField( &m_exportDataSourceAsComment, "ExportDataSourceAsComment", true, "Comment", "", "", "" );
CAF_PDM_InitField( &m_exportWelspec, "ExportWelspec", true, "WELSPEC keyword", "", "", "" );
CAF_PDM_InitField( &m_completionWelspecAfterMainBore,
"CompletionWelspecAfterMainBore",
false,
"WELSEGS per Completion Type",
"",
"",
"" );
CAF_PDM_InitField( &m_exportWelspec, "ExportWelspec", true, "Export WELSPEC keyword", "", "", "" );
m_displayForSimWell = true;
m_fracturesEnabled = true;
@ -217,6 +218,14 @@ bool RicExportCompletionDataSettingsUi::exportWelspec() const
return m_exportWelspec;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicExportCompletionDataSettingsUi::exportCompletionWelspecAfterMainBore() const
{
return m_completionWelspecAfterMainBore();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -329,9 +338,10 @@ void RicExportCompletionDataSettingsUi::defineUiOrdering( QString uiConfigName,
group->add( &compdatExport );
group->add( &caseToApply );
group->add( &useLateralNTG );
group->add( &includeMsw );
group->add( &m_exportDataSourceAsComment );
group->add( &m_exportWelspec );
group->add( &includeMsw );
group->add( &m_completionWelspecAfterMainBore );
}
{

View File

@ -98,6 +98,7 @@ public:
bool reportCompletionsTypesIndividually() const;
bool exportDataSourceAsComment() const;
bool exportWelspec() const;
bool exportCompletionWelspecAfterMainBore() const;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
@ -112,6 +113,7 @@ private:
caf::PdmField<CombinationModeType> m_reportCompletionTypesSeparately;
caf::PdmField<bool> m_exportDataSourceAsComment;
caf::PdmField<bool> m_exportWelspec;
caf::PdmField<bool> m_completionWelspecAfterMainBore;
bool m_displayForSimWell;
bool m_fracturesEnabled;

View File

@ -32,7 +32,6 @@
#include "RimEclipseCase.h"
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimPerforationCollection.h"
#include "RimProject.h"
#include "RimWellPath.h"

View File

@ -30,14 +30,12 @@
#include "RigCompletionData.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigWellLogExtractor.h"
#include "RigWellPath.h"
#include "RigWellPathIntersectionTools.h"
#include "RigWellLogExtractor.h"
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLaterals.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimWellPath.h"
#include "RimWellPathCompletions.h"
@ -98,7 +96,6 @@ std::vector<RigCompletionData>
std::map<size_t, std::vector<WellBorePartForTransCalc>> wellBorePartsInCells; // wellBore = main bore or fishbone
// lateral
findFishboneLateralsWellBoreParts( wellBorePartsInCells, wellPath, settings );
findFishboneImportedLateralsWellBoreParts( wellBorePartsInCells, wellPath, settings );
const RigActiveCellInfo* activeCellInfo =
settings.caseToApply->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL );
@ -221,40 +218,44 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWell
exportInfo.setLinerDiameter( mswParameters->linerDiameter( unitSystem ) );
exportInfo.setRoughnessFactor( mswParameters->roughnessFactor( unitSystem ) );
RicWellPathExportMswCompletionsImpl::generateFishbonesMswExportInfo( settings.caseToApply(),
wellPath,
0.0,
{},
false,
&exportInfo,
exportInfo.mainBoreBranch() );
RicWellPathExportMswCompletionsImpl::generateFishbonesMswExportInfoForWell( settings.caseToApply(),
wellPath,
&exportInfo,
exportInfo.mainBoreBranch() );
bool isMainBore = false;
for ( auto segment : exportInfo.mainBoreBranch()->segments() )
for ( auto mainBoreSegment : exportInfo.mainBoreBranch()->segments() )
{
for ( auto completion : segment->completions() )
for ( auto mainBoreCompletion : mainBoreSegment->completions() )
{
for ( auto completionSegment : completion->segments() )
for ( auto completionSegment : mainBoreCompletion->segments() )
{
for ( std::shared_ptr<RicMswSegmentCellIntersection> intersection : completionSegment->intersections() )
for ( auto completion : completionSegment->completions() )
{
double diameter = segment->holeDiameter();
QString completionMetaData =
( segment->label() +
QString( ": Sub: %1 Lateral: %2" ).arg( segment->subIndex() ).arg( completion->index() ) );
for ( auto segment : completion->segments() )
{
for ( auto intersection : segment->intersections() )
{
double diameter = segment->holeDiameter();
QString completionMetaData = ( segment->label() + QString( ": Sub: %1 Lateral: %2" )
.arg( segment->subIndex() + 1 )
.arg( completion->index() + 1 ) );
WellBorePartForTransCalc wellBorePart = WellBorePartForTransCalc( intersection->lengthsInCell(),
diameter / 2.0,
segment->skinFactor(),
isMainBore,
completionMetaData );
WellBorePartForTransCalc wellBorePart =
WellBorePartForTransCalc( intersection->lengthsInCell(),
diameter / 2.0,
segment->skinFactor(),
isMainBore,
completionMetaData );
wellBorePart.intersectionWithWellMeasuredDepth = segment->endMD();
wellBorePart.lateralIndex = completion->index();
wellBorePart.setSourcePdmObject( segment->sourcePdmObject() );
wellBorePart.intersectionWithWellMeasuredDepth = segment->endMD();
wellBorePart.lateralIndex = completion->index();
wellBorePart.setSourcePdmObject( segment->sourcePdmObject() );
wellBorePartsInCells[intersection->globalCellIndex()].push_back( wellBorePart );
wellBorePartsInCells[intersection->globalCellIndex()].push_back( wellBorePart );
}
}
}
}
}
@ -262,8 +263,8 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWell
{
// Note that it is not supported to export main bore perforation intervals for Imported Laterals, only for
// fishbones defined by ResInsight. It is not trivial to define the open section of the main bore for imported
// laterals.
// fishbones defined by ResInsight. It is not trivial to define the open section of the main bore for
// imported laterals.
if ( wellPath->fishbonesCollection()->isChecked() )
{
@ -295,56 +296,6 @@ void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneLateralsWell
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicFishbonesTransmissibilityCalculationFeatureImp::findFishboneImportedLateralsWellBoreParts(
std::map<size_t, std::vector<WellBorePartForTransCalc>>& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings )
{
RiaDefines::EclipseUnitSystem unitSystem = settings.caseToApply->eclipseCaseData()->unitsType();
if ( !wellPath ) return;
if ( !wellPath->wellPathGeometry() ) return;
bool isMainBore = false;
double holeRadius = wellPath->fishbonesCollection()->wellPathCollection()->holeDiameter( unitSystem ) / 2.0;
double skinFactor = wellPath->fishbonesCollection()->wellPathCollection()->skinFactor();
for ( const RimImportedFishboneLaterals* fishbonesPath :
wellPath->fishbonesCollection()->wellPathCollection()->wellPaths() )
{
if ( !fishbonesPath->isChecked() )
{
continue;
}
std::vector<WellPathCellIntersectionInfo> intersectedCells =
RigWellPathIntersectionTools::findCellIntersectionInfosAlongPath( settings.caseToApply->eclipseCaseData(),
wellPath->name(),
fishbonesPath->coordinates(),
fishbonesPath->measuredDepths() );
for ( const auto& cellIntersectionInfo : intersectedCells )
{
QString completionMetaData = fishbonesPath->name();
WellBorePartForTransCalc wellBorePart =
WellBorePartForTransCalc( cellIntersectionInfo.intersectionLengthsInCellCS,
holeRadius,
skinFactor,
isMainBore,
completionMetaData );
wellBorePart.intersectionWithWellMeasuredDepth = cellIntersectionInfo.startMD;
wellBorePartsInCells[cellIntersectionInfo.globCellIndex].push_back( wellBorePart );
}
}
// Note that it is not supported to export main bore perforation intervals for Imported Laterals, only for fishbones
// defined by ResInsight
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -48,11 +48,6 @@ private:
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings );
static void
findFishboneImportedLateralsWellBoreParts( std::map<size_t, std::vector<WellBorePartForTransCalc>>& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings );
static void appendMainWellBoreParts( std::map<size_t, std::vector<WellBorePartForTransCalc>>& wellBorePartsInCells,
const RimWellPath* wellPath,
const RicExportCompletionDataSettingsUi& settings,

View File

@ -1,3 +1,21 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RicMswBranch.h"
#include "RicMswCompletions.h"
@ -139,6 +157,39 @@ std::vector<RicMswSegment*> RicMswBranch::segments()
return allSegments;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicMswSegment* RicMswBranch::findClosestSegmentByMidpoint( double measuredDepthLocation )
{
if ( measuredDepthLocation < startMD() )
{
return segmentCount() > 0 ? segments().front() : nullptr;
}
if ( measuredDepthLocation > endMD() )
{
return segmentCount() > 0 ? segments().back() : nullptr;
}
RicMswSegment* closestSegment = nullptr;
double smallestDistance = std::numeric_limits<double>::infinity();
for ( auto seg : segments() )
{
double midpointMD = 0.5 * ( seg->startMD() + seg->endMD() );
double candidateDistance = std::abs( midpointMD - measuredDepthLocation );
if ( candidateDistance < smallestDistance )
{
closestSegment = seg;
smallestDistance = candidateDistance;
}
}
return closestSegment;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -53,6 +53,8 @@ public:
std::vector<const RicMswSegment*> segments() const;
std::vector<RicMswSegment*> segments();
RicMswSegment* findClosestSegmentByMidpoint( double measuredDepth );
size_t segmentCount() const;
std::vector<const RicMswBranch*> branches() const;

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Equinor ASA
// Copyright (C) 2021- 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
@ -18,9 +18,11 @@
#include "RicMswCompletions.h"
#include "RiaLogging.h"
#include "RicMswSegmentCellIntersection.h"
#include "RimWellPath.h"
#include "RimWellPathValve.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -123,30 +125,22 @@ void RicMswValve::setIsValid( bool valid )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::unique_ptr<RicMswValve> RicMswValve::createExportValve( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve )
std::unique_ptr<RicMswValve> RicMswValve::createTieInValve( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve )
{
std::unique_ptr<RicMswValve> outletValve;
if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICD )
if ( wellPathValve->componentType() != RiaDefines::WellPathComponentType::ICV )
{
outletValve = std::make_unique<RicMswPerforationICD>( label, wellPath, startMD, startTVD, wellPathValve );
RiaLogging::error( "MSW export: The outlet valve must be of type ICV" );
return nullptr;
}
else if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::ICV )
{
outletValve = std::make_unique<RicMswPerforationICV>( label, wellPath, startMD, startTVD, wellPathValve );
}
else if ( wellPathValve->componentType() == RiaDefines::WellPathComponentType::AICD )
{
outletValve = std::make_unique<RicMswPerforationAICD>( label, wellPath, startMD, startTVD, wellPathValve );
}
else
{
CAF_ASSERT( false && "Valve needs to be either an ICD, ICVF or AICD" );
}
return outletValve;
std::unique_ptr<RicMswTieInICV> tieInValve =
std::make_unique<RicMswTieInICV>( label, wellPath, startMD, startTVD, wellPathValve );
return tieInValve;
}
//--------------------------------------------------------------------------------------------------
@ -247,6 +241,10 @@ RicMswPerforationICV::RicMswPerforationICV( const QString& label,
: RicMswWsegValve( label, wellPath, startMD, startTVD, wellPathValve )
{
setIsValid( true );
setFlowCoefficient( wellPathValve->flowCoefficient() );
double orificeRadius = wellPathValve->orificeDiameter( wellPath->unitSystem() ) / 2;
setArea( orificeRadius * orificeRadius * cvf::PI_D );
}
//-------------------------------------------------------------------
@ -270,6 +268,7 @@ RicMswPerforationAICD::RicMswPerforationAICD( const QString& label,
, m_length( 0.0 )
, m_flowScalingFactor( 0.0 )
{
m_parameters.fill( std::numeric_limits<double>::infinity() );
}
//--------------------------------------------------------------------------------------------------
@ -343,3 +342,28 @@ std::array<double, AICD_NUM_PARAMS>& RicMswPerforationAICD::values()
{
return m_parameters;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicMswTieInICV::RicMswTieInICV( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve )
: RicMswWsegValve( label, wellPath, startMD, startTVD, wellPathValve )
{
setIsValid( true );
setFlowCoefficient( wellPathValve->flowCoefficient() );
double orificeRadius = wellPathValve->orificeDiameter( wellPath->unitSystem() ) / 2;
setArea( orificeRadius * orificeRadius * cvf::PI_D );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigCompletionData::CompletionType RicMswTieInICV::completionType() const
{
return RigCompletionData::PERFORATION_ICV;
}

View File

@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Equinor ASA
// Copyright (C) 2021- 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
@ -15,6 +15,7 @@
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RicMswBranch.h"
@ -26,6 +27,7 @@
#include "cvfMath.h"
#include <QString>
#include <memory>
class RimWellPathValve;
@ -49,6 +51,9 @@ private:
size_t m_index;
};
//==================================================================================================
///
//==================================================================================================
class RicMswFishbones : public RicMswCompletion
{
public:
@ -111,11 +116,11 @@ public:
bool isValid() const;
void setIsValid( bool valid );
static std::unique_ptr<RicMswValve> createExportValve( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve );
static std::unique_ptr<RicMswValve> createTieInValve( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve );
private:
bool m_valid;
@ -186,6 +191,22 @@ public:
RigCompletionData::CompletionType completionType() const override;
};
//==================================================================================================
// This object is representing the optional tie-in valve used to limit the inflow from a branch
// into the parent branch
// ICV valve is the only supported valve for this MSW item
//==================================================================================================
class RicMswTieInICV : public RicMswWsegValve
{
public:
RicMswTieInICV( const QString& label,
const RimWellPath* wellPath,
double startMD,
double startTVD,
const RimWellPathValve* wellPathValve );
RigCompletionData::CompletionType completionType() const override;
};
//==================================================================================================
///
//==================================================================================================

View File

@ -1,3 +1,21 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RicMswItem.h"
//--------------------------------------------------------------------------------------------------

View File

@ -40,7 +40,7 @@ RicMswSegment::RicMswSegment( const QString& label,
, m_endTVD( endTVD )
, m_outputMD( 0.0 )
, m_outputTVD( 0.0 )
, m_effectiveDiameter( 0.15 )
, m_equivalentDiameter( 0.15 )
, m_holeDiameter( RicMswExportInfo::defaultDoubleValue() )
, m_openHoleRoughnessFactor( 5.0e-5 )
, m_skinFactor( RicMswExportInfo::defaultDoubleValue() )
@ -116,9 +116,9 @@ double RicMswSegment::outputTVD() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMswSegment::effectiveDiameter() const
double RicMswSegment::equivalentDiameter() const
{
return m_effectiveDiameter;
return m_equivalentDiameter;
}
//--------------------------------------------------------------------------------------------------
@ -198,9 +198,9 @@ void RicMswSegment::setLabel( const QString& label )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswSegment::setEffectiveDiameter( double effectiveDiameter )
void RicMswSegment::setEquivalentDiameter( double effectiveDiameter )
{
m_effectiveDiameter = effectiveDiameter;
m_equivalentDiameter = effectiveDiameter;
}
//--------------------------------------------------------------------------------------------------

View File

@ -53,7 +53,7 @@ public:
void setOutputTVD( double outputTVD );
double outputTVD() const;
double effectiveDiameter() const;
double equivalentDiameter() const;
double holeDiameter() const;
double openHoleRoughnessFactor() const;
double skinFactor() const;
@ -65,7 +65,7 @@ public:
std::vector<RicMswCompletion*> completions();
void setLabel( const QString& label );
void setEffectiveDiameter( double effectiveDiameter );
void setEquivalentDiameter( double diameter );
void setHoleDiameter( double holeDiameter );
void setOpenHoleRoughnessFactor( double roughnessFactor );
void setSkinFactor( double skinFactor );
@ -88,10 +88,10 @@ private:
double m_startTVD;
double m_endTVD;
double m_outputMD;
double m_outputTVD;
double m_outputMD;
double m_outputTVD;
double m_effectiveDiameter;
double m_equivalentDiameter;
double m_holeDiameter;
double m_openHoleRoughnessFactor;
double m_skinFactor;

View File

@ -0,0 +1,998 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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 "RicMswTableFormatterTools.h"
#include "RiaLogging.h"
#include "RicMswCompletions.h"
#include "RicMswExportInfo.h"
#include "RifTextDataTableFormatter.h"
#include "RigWellPath.h"
#include "RimWellPath.h" // TODO: Consider adding wellnameforexport to RicMswExportInfo to avoid these includes
#include "RimWellPathCompletionSettings.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateWelsegsTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
bool exportCompletionSegmentsAfterMainBore )
{
formatter.keyword( "WELSEGS" );
double startMD = exportInfo.mainBoreBranch()->startMD();
double startTVD = exportInfo.mainBoreBranch()->startTVD();
{
std::vector<RifTextDataTableColumn> header = {
RifTextDataTableColumn( "Name" ),
RifTextDataTableColumn( "Dep 1" ),
RifTextDataTableColumn( "Tlen 1" ),
RifTextDataTableColumn( "Vol 1" ),
RifTextDataTableColumn( "Len&Dep" ),
RifTextDataTableColumn( "PresDrop" ),
};
formatter.header( header );
formatter.add( exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport() );
formatter.add( startTVD );
formatter.add( startMD );
formatter.addValueOrDefaultMarker( exportInfo.topWellBoreVolume(), RicMswExportInfo::defaultDoubleValue() );
formatter.add( exportInfo.lengthAndDepthText() );
formatter.add( QString( "'%1'" ).arg( exportInfo.pressureDropText() ) );
formatter.rowCompleted();
}
{
std::vector<RifTextDataTableColumn> header =
{ RifTextDataTableColumn( "First Seg" ),
RifTextDataTableColumn( "Last Seg" ),
RifTextDataTableColumn( "Branch Num" ),
RifTextDataTableColumn( "Outlet Seg" ),
RifTextDataTableColumn( "Length" ),
RifTextDataTableColumn( "Depth Change" ),
RifTextDataTableColumn( "Diam" ),
RifTextDataTableColumn( "Rough", RifTextDataTableDoubleFormatting( RIF_FLOAT, 7 ) ) };
formatter.header( header );
}
int segmentNumber = 2; // There's an implicit segment number 1.
RicMswSegment* parentSegment = nullptr;
writeWelsegsSegmentsRecursively( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
&segmentNumber,
maxSegmentLength,
exportCompletionSegmentsAfterMainBore,
parentSegment );
formatter.tableCompleted();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeWelsegsSegmentsRecursively( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<RicMswBranch*> branch,
gsl::not_null<int*> segmentNumber,
double maxSegmentLength,
bool exportCompletionSegmentsAfterMainBore,
RicMswSegment* connectedToSegment )
{
auto outletSegment = connectedToSegment;
RicMswValve* outletValve = nullptr;
auto branchSegments = branch->segments();
auto it = branchSegments.begin();
if ( outletValve = dynamic_cast<RicMswTieInICV*>( branch.get() ); outletValve != nullptr )
{
writeValveWelsegsSegment( outletSegment, outletValve, formatter, exportInfo, maxSegmentLength, segmentNumber );
auto valveSegments = outletValve->segments();
outletSegment = valveSegments.front();
*segmentNumber = outletSegment->segmentNumber() + 1;
++it; // skip segment below
}
formatter.addOptionalComment( QString( "Segments on branch %1" ).arg( branch->label() ) );
auto branchStartSegmentIterator = it;
for ( ; it != branchSegments.end(); ++it )
{
auto segment = *it;
segment->setSegmentNumber( *segmentNumber );
if ( segment->subIndex() != cvf::UNDEFINED_SIZE_T )
{
QString comment = segment->label() + QString( ", sub %1" ).arg( segment->subIndex() + 1 );
formatter.addOptionalComment( comment );
}
writeWelsegsSegment( segment, outletSegment, formatter, exportInfo, maxSegmentLength, branch, segmentNumber );
outletSegment = segment;
if ( !exportCompletionSegmentsAfterMainBore )
{
writeCompletionsForSegment( outletSegment, segment, &outletValve, formatter, exportInfo, maxSegmentLength, segmentNumber );
}
}
if ( exportCompletionSegmentsAfterMainBore )
{
it = branchStartSegmentIterator;
for ( ; it != branchSegments.end(); ++it )
{
auto segment = *it;
writeCompletionsForSegment( outletSegment, segment, &outletValve, formatter, exportInfo, maxSegmentLength, segmentNumber );
}
}
for ( auto childBranch : branch->branches() )
{
RicMswSegment* outletSegmentForChildBranch = outletSegment;
RicMswSegment* tieInSegmentOnParentBranch = branch->findClosestSegmentByMidpoint( childBranch->startMD() );
if ( tieInSegmentOnParentBranch ) outletSegmentForChildBranch = tieInSegmentOnParentBranch;
writeWelsegsSegmentsRecursively( formatter,
exportInfo,
childBranch,
segmentNumber,
maxSegmentLength,
exportCompletionSegmentsAfterMainBore,
outletSegmentForChildBranch );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeWelsegsCompletionCommentHeader( RifTextDataTableFormatter& formatter,
RigCompletionData::CompletionType completionType )
{
QString optionalCommentText;
switch ( completionType )
{
case RigCompletionData::FISHBONES:
break;
case RigCompletionData::FRACTURE:
optionalCommentText = "Fracture Segments";
break;
case RigCompletionData::PERFORATION:
optionalCommentText = "Perforation Segments";
break;
case RigCompletionData::FISHBONES_ICD:
optionalCommentText = "Fishbones Segments - ICD";
break;
case RigCompletionData::PERFORATION_ICD:
optionalCommentText = "Perforation Segments - ICD";
break;
case RigCompletionData::PERFORATION_AICD:
optionalCommentText = "Perforation Segments - AICD";
break;
case RigCompletionData::PERFORATION_ICV:
optionalCommentText = "Perforation Segments - ICV";
break;
case RigCompletionData::CT_UNDEFINED:
optionalCommentText = "Main Stem";
break;
default:
break;
}
if ( !optionalCommentText.isEmpty() )
{
formatter.addOptionalComment( optionalCommentText );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateCompsegTables( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo )
{
/*
* TODO: Creating the regular perforation COMPSEGS table should come in here, before the others
* should take precedence by appearing later in the output. See #3230.
*/
std::set<size_t> intersectedCells;
{
std::set<RigCompletionData::CompletionType> perforationTypes = { RigCompletionData::PERFORATION,
RigCompletionData::PERFORATION_ICD,
RigCompletionData::PERFORATION_ICV,
RigCompletionData::PERFORATION_AICD };
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
false,
perforationTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
if ( exportInfo.hasSubGridIntersections() )
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
true,
perforationTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
}
{
std::set<RigCompletionData::CompletionType> fishbonesTypes = { RigCompletionData::FISHBONES_ICD,
RigCompletionData::FISHBONES };
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
false,
fishbonesTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
if ( exportInfo.hasSubGridIntersections() )
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
true,
fishbonesTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
}
{
std::set<RigCompletionData::CompletionType> fractureTypes = { RigCompletionData::FRACTURE };
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
false,
fractureTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
if ( exportInfo.hasSubGridIntersections() )
{
bool headerGenerated = false;
generateCompsegTable( formatter,
exportInfo,
exportInfo.mainBoreBranch(),
true,
fractureTypes,
&headerGenerated,
&intersectedCells );
if ( headerGenerated ) formatter.tableCompleted();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateCompsegTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<const RicMswBranch*> branch,
bool exportSubGridIntersections,
const std::set<RigCompletionData::CompletionType>& exportCompletionTypes,
gsl::not_null<bool*> headerGenerated,
gsl::not_null<std::set<size_t>*> intersectedCells )
{
for ( auto segment : branch->segments() )
{
auto completion = dynamic_cast<const RicMswCompletion*>( branch.get() );
for ( auto intersection : segment->intersections() )
{
bool isSubGridIntersection = !intersection->gridName().isEmpty();
if ( isSubGridIntersection != exportSubGridIntersections ) continue;
double startLength = segment->startMD();
double endLength = segment->endMD();
if ( completion )
{
bool isPerforationValve = completion->completionType() == RigCompletionData::PERFORATION_ICD ||
completion->completionType() == RigCompletionData::PERFORATION_AICD ||
completion->completionType() == RigCompletionData::PERFORATION_ICV;
if ( isPerforationValve )
{
startLength = segment->startMD();
endLength = segment->endMD();
}
}
size_t globalCellIndex = intersection->globalCellIndex();
// Here we check if the cell is already reported. Make sure we report intersections before other completions
// on the segment to be able to connect the branch with most flow
if ( !intersectedCells->count( globalCellIndex ) )
{
if ( exportSubGridIntersections )
{
formatter.add( intersection->gridName() );
}
cvf::Vec3st ijk = intersection->gridLocalCellIJK();
formatter.addOneBasedCellIndex( ijk.x() ).addOneBasedCellIndex( ijk.y() ).addOneBasedCellIndex( ijk.z() );
int branchNumber = -1;
if ( completion ) branchNumber = completion->branchNumber();
formatter.add( branchNumber );
formatter.add( startLength );
formatter.add( endLength );
formatter.rowCompleted();
intersectedCells->insert( globalCellIndex );
}
}
// Report connected completions after the intersection on current segment has been reported
for ( auto completion : segment->completions() )
{
if ( completion->segments().empty() || !exportCompletionTypes.count( completion->completionType() ) )
continue;
if ( !*headerGenerated )
{
generateCompsegHeader( formatter, exportInfo, completion->completionType(), exportSubGridIntersections );
*headerGenerated = true;
}
generateCompsegTable( formatter,
exportInfo,
completion,
exportSubGridIntersections,
exportCompletionTypes,
headerGenerated,
intersectedCells );
}
}
for ( auto childBranch : branch->branches() )
{
generateCompsegTable( formatter,
exportInfo,
childBranch,
exportSubGridIntersections,
exportCompletionTypes,
headerGenerated,
intersectedCells );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateCompsegHeader( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
RigCompletionData::CompletionType completionType,
bool exportSubGridIntersections )
{
if ( exportSubGridIntersections )
{
formatter.keyword( "COMPSEGL" );
}
else
{
formatter.keyword( "COMPSEGS" );
}
if ( completionType == RigCompletionData::FISHBONES_ICD )
{
formatter.comment( "Fishbones" );
}
else if ( completionType == RigCompletionData::FRACTURE )
{
formatter.comment( "Fractures" );
}
{
std::vector<RifTextDataTableColumn> header = { RifTextDataTableColumn( "Name" ) };
formatter.header( header );
formatter.add( exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport() );
formatter.rowCompleted();
}
{
std::vector<RifTextDataTableColumn> allHeaders;
if ( exportSubGridIntersections )
{
allHeaders.push_back( RifTextDataTableColumn( "Grid" ) );
}
std::vector<RifTextDataTableColumn> commonHeaders = { RifTextDataTableColumn( "I" ),
RifTextDataTableColumn( "J" ),
RifTextDataTableColumn( "K" ),
RifTextDataTableColumn( "Branch no" ),
RifTextDataTableColumn( "Start Length" ),
RifTextDataTableColumn( "End Length" ),
RifTextDataTableColumn( "Dir Pen" ),
RifTextDataTableColumn( "End Range" ),
RifTextDataTableColumn( "Connection Depth" ) };
allHeaders.insert( allHeaders.end(), commonHeaders.begin(), commonHeaders.end() );
formatter.header( allHeaders );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateWsegvalvTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo )
{
bool foundValve = false;
generateWsegvalvTableRecursively( formatter,
exportInfo.mainBoreBranch(),
foundValve,
exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport() );
if ( foundValve )
{
formatter.tableCompleted();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateWsegvalvTableRecursively( RifTextDataTableFormatter& formatter,
gsl::not_null<RicMswBranch*> branch,
bool& isHeaderWritten,
const QString& wellNameForExport )
{
{
auto tieInValve = dynamic_cast<RicMswTieInICV*>( branch.get() );
if ( tieInValve && !tieInValve->segments().empty() )
{
if ( !isHeaderWritten )
{
writeWsegvalHeader( formatter );
isHeaderWritten = true;
}
auto firstSubSegment = tieInValve->segments().front();
CAF_ASSERT( tieInValve->completionType() == RigCompletionData::PERFORATION_ICV );
{
formatter.addOptionalComment( tieInValve->label() );
}
formatter.add( wellNameForExport );
formatter.add( firstSubSegment->segmentNumber() );
formatter.add( tieInValve->flowCoefficient() );
formatter.add( QString( "%1" ).arg( tieInValve->area(), 8, 'g', 4 ) );
formatter.rowCompleted();
}
}
for ( auto segment : branch->segments() )
{
for ( auto completion : segment->completions() )
{
if ( RigCompletionData::isWsegValveTypes( completion->completionType() ) )
{
if ( !isHeaderWritten )
{
writeWsegvalHeader( formatter );
isHeaderWritten = true;
}
auto wsegValve = static_cast<RicMswWsegValve*>( completion );
if ( !wsegValve->segments().empty() )
{
CVF_ASSERT( wsegValve->segments().size() == 1u );
auto firstSubSegment = wsegValve->segments().front();
// TODO: The following line was blocking export of valves for fishbones
// Unclear why this line was included. Remove when MSW export has ben verified correctly
// if ( !firstSubSegment->intersections().empty() )
{
if ( wsegValve->completionType() == RigCompletionData::PERFORATION_ICD ||
wsegValve->completionType() == RigCompletionData::PERFORATION_ICV )
{
formatter.addOptionalComment( wsegValve->label() );
}
formatter.add( wellNameForExport );
formatter.add( firstSubSegment->segmentNumber() );
formatter.add( wsegValve->flowCoefficient() );
formatter.add( QString( "%1" ).arg( wsegValve->area(), 8, 'g', 4 ) );
formatter.rowCompleted();
}
}
}
}
}
for ( auto childBranch : branch->branches() )
{
generateWsegvalvTableRecursively( formatter, childBranch, isHeaderWritten, wellNameForExport );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::generateWsegAicdTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo )
{
RifTextDataTableFormatter tighterFormatter( formatter );
tighterFormatter.setColumnSpacing( 1 );
tighterFormatter.setTableRowPrependText( " " );
bool foundValve = false;
for ( auto segment : exportInfo.mainBoreBranch()->segments() )
{
for ( auto completion : segment->completions() )
{
if ( completion->completionType() == RigCompletionData::PERFORATION_AICD )
{
auto aicd = static_cast<RicMswPerforationAICD*>( completion );
if ( aicd->isValid() )
{
if ( !foundValve )
{
std::vector<QString> columnDescriptions =
{ "Well Name",
"Segment Number",
"Segment Number",
"Strength of AICD",
"Flow Scaling Factor for AICD",
"Density of Calibration Fluid",
"Viscosity of Calibration Fluid",
"Critical water in liquid fraction for emulsions viscosity model",
"Emulsion viscosity transition region",
"Max ratio of emulsion viscosity to continuous phase viscosity",
"Flow scaling factor method",
"Maximum flow rate for AICD device",
"Volume flow rate exponent, x",
"Viscosity function exponent, y",
"Device OPEN/SHUT",
"Exponent of the oil flowing fraction in the density mixture calculation",
"Exponent of the water flowing fraction in the density mixture calculation",
"Exponent of the gas flowing fraction in the density mixture calculation",
"Exponent of the oil flowing fraction in the density viscosity calculation",
"Exponent of the water flowing fraction in the density viscosity calculation",
"Exponent of the gas flowing fraction in the density viscosity calculation" };
tighterFormatter.keyword( "WSEGAICD" );
tighterFormatter.comment( "Column Overview:" );
for ( size_t i = 0; i < columnDescriptions.size(); ++i )
{
tighterFormatter.comment(
QString( "%1: %2" ).arg( i + 1, 2, 10, QChar( '0' ) ).arg( columnDescriptions[i] ) );
}
std::vector<RifTextDataTableColumn> header;
for ( size_t i = 1; i <= 21; ++i )
{
QString cName = QString( "%1" ).arg( i, 2, 10, QChar( '0' ) );
RifTextDataTableColumn col( cName,
RifTextDataTableDoubleFormatting(
RifTextDataTableDoubleFormat::RIF_CONSISE ),
RIGHT );
header.push_back( col );
}
tighterFormatter.header( header );
foundValve = true;
}
if ( !aicd->segments().empty() )
{
CVF_ASSERT( aicd->segments().size() == 1u );
tighterFormatter.comment( aicd->label() );
tighterFormatter.add(
exportInfo.mainBoreBranch()->wellPath()->completionSettings()->wellNameForExport() ); // #1
tighterFormatter.add( aicd->segments().front()->segmentNumber() );
tighterFormatter.add( aicd->segments().front()->segmentNumber() );
std::array<double, AICD_NUM_PARAMS> values = aicd->values();
tighterFormatter.add( values[AICD_STRENGTH] );
tighterFormatter.add( aicd->flowScalingFactor() ); // #5 Flow scaling factor used when item
// #11 is set to '1'
tighterFormatter.add( values[AICD_DENSITY_CALIB_FLUID] );
tighterFormatter.add( values[AICD_VISCOSITY_CALIB_FLUID] );
tighterFormatter.addValueOrDefaultMarker( values[AICD_CRITICAL_WATER_IN_LIQUID_FRAC],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EMULSION_VISC_TRANS_REGION],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_RATIO_EMULSION_VISC],
RicMswExportInfo::defaultDoubleValue() ); // #10
tighterFormatter.add( 1 ); // #11 : Always use method "b. Scale factor". The value of the
// scale factor is given in item #5
tighterFormatter.addValueOrDefaultMarker( values[AICD_MAX_FLOW_RATE],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.add( values[AICD_VOL_FLOW_EXP] );
tighterFormatter.add( values[AICD_VISOSITY_FUNC_EXP] );
tighterFormatter.add( aicd->isOpen() ? "OPEN" : "SHUT" ); // #15
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_DENSITY],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_DENSITY],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_GAS_FRAC_DENSITY],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_OIL_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_WATER_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() ); // #20
tighterFormatter.addValueOrDefaultMarker( values[AICD_EXP_GAS_FRAC_VISCOSITY],
RicMswExportInfo::defaultDoubleValue() );
tighterFormatter.rowCompleted();
}
}
else
{
RiaLogging::error( QString( "Export AICD Valve (%1): Valve is invalid. At least one required "
"template parameter is not set." )
.arg( aicd->label() ) );
}
}
}
}
if ( foundValve )
{
tighterFormatter.tableCompleted();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeWelsegsSegment( RicMswSegment* segment,
const RicMswSegment* previousSegment,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
gsl::not_null<RicMswBranch*> branch,
int* segmentNumber )
{
CVF_ASSERT( segment && segmentNumber );
double startMD = segment->startMD();
double endMD = segment->endMD();
std::vector<std::pair<double, double>> segments = createSubSegmentMDPairs( startMD, endMD, maxSegmentLength );
CVF_ASSERT( branch->wellPath() );
auto wellPathGeometry = branch->wellPath()->wellPathGeometry();
CVF_ASSERT( wellPathGeometry );
double prevOutMD = branch->startMD();
double prevOutTVD = branch->startTVD();
if ( previousSegment )
{
prevOutMD = previousSegment->outputMD();
prevOutTVD = previousSegment->outputTVD();
}
auto outletSegment = previousSegment;
for ( const auto& [subStartMD, subEndMD] : segments )
{
double depth = 0;
double length = 0;
double midPointMD = 0.5 * ( subStartMD + subEndMD );
double midPointTVD = tvdFromMeasuredDepth( branch->wellPath(), midPointMD );
if ( exportInfo.lengthAndDepthText() == QString( "INC" ) )
{
depth = midPointTVD - prevOutTVD;
length = midPointMD - prevOutMD;
}
else
{
depth = midPointTVD;
length = midPointMD;
}
segment->setOutputMD( midPointMD );
segment->setOutputTVD( midPointTVD );
segment->setSegmentNumber( *segmentNumber );
formatter.add( *segmentNumber ).add( *segmentNumber );
formatter.add( branch->branchNumber() );
if ( outletSegment )
formatter.add( outletSegment->segmentNumber() );
else
formatter.add( 1 );
formatter.add( length );
formatter.add( depth );
formatter.add( exportInfo.linerDiameter() );
formatter.add( exportInfo.roughnessFactor() );
formatter.rowCompleted();
( *segmentNumber )++;
outletSegment = segment;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeValveWelsegsSegment( const RicMswSegment* outletSegment,
RicMswValve* valve,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber )
{
CVF_ASSERT( valve );
if ( !valve->isValid() ) return;
CVF_ASSERT( !valve->label().isEmpty() );
CVF_ASSERT( valve->wellPath() );
formatter.addOptionalComment( valve->label() );
auto segments = valve->segments();
auto subSegment = segments.front();
subSegment->setSegmentNumber( *segmentNumber );
double startMD = subSegment->startMD();
double endMD = subSegment->endMD();
double midPointMD = 0.5 * ( startMD + endMD );
double midPointTVD = tvdFromMeasuredDepth( valve->wellPath(), midPointMD );
subSegment->setOutputMD( midPointMD );
subSegment->setOutputTVD( midPointTVD );
std::vector<std::pair<double, double>> splitSegments = createSubSegmentMDPairs( startMD, endMD, maxSegmentLength );
auto wellPathGeometry = valve->wellPath()->wellPathGeometry();
CVF_ASSERT( wellPathGeometry );
for ( const auto& [subStartMD, subEndMD] : splitSegments )
{
int subSegmentNumber = ( *segmentNumber )++;
double subStartTVD = tvdFromMeasuredDepth( valve->wellPath(), subStartMD );
double subEndTVD = tvdFromMeasuredDepth( valve->wellPath(), subEndMD );
double depth = 0;
double length = 0;
if ( exportInfo.lengthAndDepthText() == QString( "INC" ) )
{
depth = subEndTVD - subStartTVD;
length = subEndMD - subStartMD;
}
else
{
depth = subEndTVD;
length = subEndMD;
}
formatter.add( subSegmentNumber );
formatter.add( subSegmentNumber );
formatter.add( valve->branchNumber() );
formatter.add( outletSegment->segmentNumber() );
formatter.add( length );
formatter.add( depth );
formatter.add( exportInfo.linerDiameter() );
formatter.add( exportInfo.roughnessFactor() );
formatter.rowCompleted();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeCompletionWelsegsSegments( gsl::not_null<const RicMswSegment*> outletSegment,
gsl::not_null<const RicMswCompletion*> completion,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber )
{
writeWelsegsCompletionCommentHeader( formatter, completion->completionType() );
if ( completion->completionType() == RigCompletionData::FISHBONES )
{
formatter.addOptionalComment(
QString( "Sub index %1 - %2" ).arg( outletSegment->subIndex() + 1 ).arg( completion->label() ) );
}
else if ( completion->completionType() == RigCompletionData::FRACTURE )
{
formatter.addOptionalComment(
QString( "%1 connected to segment %2" ).arg( completion->label() ).arg( outletSegment->segmentNumber() ) );
}
CVF_ASSERT( completion->wellPath() );
int outletSegmentNumber = outletSegment->segmentNumber();
for ( auto segment : completion->segments() )
{
double startMD = segment->startMD();
double endMD = segment->endMD();
std::vector<std::pair<double, double>> splitSegments = createSubSegmentMDPairs( startMD, endMD, maxSegmentLength );
for ( const auto& [subStartMD, subEndMD] : splitSegments )
{
int subSegmentNumber = ( *segmentNumber )++;
double subStartTVD = tvdFromMeasuredDepth( completion->wellPath(), subStartMD );
double subEndTVD = tvdFromMeasuredDepth( completion->wellPath(), subEndMD );
double depth = 0;
double length = 0;
if ( exportInfo.lengthAndDepthText() == QString( "INC" ) )
{
depth = subEndTVD - subStartTVD;
length = subEndMD - subStartMD;
}
else
{
depth = subEndTVD;
length = subEndMD;
}
formatter.add( subSegmentNumber );
formatter.add( subSegmentNumber );
formatter.add( completion->branchNumber() );
formatter.add( outletSegmentNumber );
formatter.add( length );
formatter.add( depth );
formatter.add( segment->equivalentDiameter() );
formatter.add( segment->openHoleRoughnessFactor() );
formatter.rowCompleted();
outletSegmentNumber = subSegmentNumber;
}
for ( auto completionSegment : completion->segments() )
{
auto noConst = const_cast<RicMswSegment*>( completionSegment );
noConst->setSegmentNumber( outletSegmentNumber );
for ( auto comp : completionSegment->completions() )
{
writeCompletionWelsegsSegments( completionSegment, comp, formatter, exportInfo, maxSegmentLength, segmentNumber );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeCompletionsForSegment( gsl::not_null<const RicMswSegment*> outletSegment,
gsl::not_null<RicMswSegment*> segment,
RicMswValve** outletValve,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber )
{
for ( auto& completion : segment->completions() )
{
// For a well with perforation intervals, the WELSEGS segments are reported twice if if we include the
// RicMswPerforation completions. Investigate when this class is intended to be exported to file
auto performationMsw = dynamic_cast<RicMswPerforation*>( completion );
if ( performationMsw ) continue;
auto segmentValve = dynamic_cast<RicMswValve*>( completion );
auto fishboneIcd = dynamic_cast<RicMswFishbonesICD*>( completion );
if ( !fishboneIcd && segmentValve != nullptr )
{
writeValveWelsegsSegment( segment, segmentValve, formatter, exportInfo, maxSegmentLength, segmentNumber );
*outletValve = segmentValve;
}
else
{
// If we have a valve, the outlet segment is the valve's segment
RicMswSegment* outletSegment = *outletValve && ( *outletValve )->segmentCount() > 0
? ( *outletValve )->segments().front()
: segment.get();
writeCompletionWelsegsSegments( outletSegment, completion, formatter, exportInfo, maxSegmentLength, segmentNumber );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<double, double>>
RicMswTableFormatterTools::createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength )
{
int subSegmentCount = (int)( std::trunc( ( endMD - startMD ) / maxSegmentLength ) + 1 );
double subSegmentLength = ( endMD - startMD ) / subSegmentCount;
std::vector<std::pair<double, double>> subSegmentMDPairs;
double subStartMD = startMD;
double subEndMD = startMD + subSegmentLength;
for ( int i = 0; i < subSegmentCount; ++i )
{
subSegmentMDPairs.push_back( std::make_pair( subStartMD, subEndMD ) );
subStartMD += subSegmentLength;
subEndMD += std::min( subSegmentLength, endMD );
}
return subSegmentMDPairs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicMswTableFormatterTools::tvdFromMeasuredDepth( gsl::not_null<const RimWellPath*> wellPath, double measuredDepth )
{
auto wellPathGeometry = wellPath->wellPathGeometry();
CVF_ASSERT( wellPathGeometry );
double tvdValue = -wellPathGeometry->interpolatedPointAlongWellPath( measuredDepth ).z();
return tvdValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicMswTableFormatterTools::writeWsegvalHeader( RifTextDataTableFormatter& formatter )
{
formatter.keyword( "WSEGVALV" );
std::vector<RifTextDataTableColumn> header = {
RifTextDataTableColumn( "Well Name" ),
RifTextDataTableColumn( "Seg No" ),
RifTextDataTableColumn( "Cv" ),
RifTextDataTableColumn( "Ac" ),
};
formatter.header( header );
}

View File

@ -0,0 +1,130 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RigCompletionData.h"
#include "cvfVector3.h"
#include <gsl/gsl>
class RicMswExportInfo;
class RifTextDataTableFormatter;
class RicMswBranch;
class RicMswSegment;
class RicMswValve;
class RicMswCompletion;
class RimWellPath;
namespace RicMswTableFormatterTools
{
class CvfVec3stComparator
{
public:
bool operator()( const cvf::Vec3st& lhs, const cvf::Vec3st& rhs ) const
{
if ( lhs.z() == rhs.z() )
{
if ( lhs.y() == rhs.y() )
{
return lhs.x() < rhs.x();
}
return lhs.y() < rhs.y();
}
return lhs.z() < rhs.z();
}
};
void generateWelsegsTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
bool exportCompletionSegmentsAfterMainBore );
void writeWelsegsSegmentsRecursively( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<RicMswBranch*> branch,
gsl::not_null<int*> segmentNumber,
double maxSegmentLength,
bool exportCompletionSegmentsAfterMainBore,
RicMswSegment* connectedToSegment );
void writeWelsegsSegment( RicMswSegment* segment,
const RicMswSegment* previousSegment,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
gsl::not_null<RicMswBranch*> branch,
int* segmentNumber );
void writeValveWelsegsSegment( const RicMswSegment* outletSegment,
RicMswValve* valve,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber );
void writeCompletionWelsegsSegments( gsl::not_null<const RicMswSegment*> outletSegment,
gsl::not_null<const RicMswCompletion*> completion,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber );
void writeCompletionsForSegment( gsl::not_null<const RicMswSegment*> outletSegment,
gsl::not_null<RicMswSegment*> segment,
RicMswValve** outletValve,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber );
void writeWelsegsCompletionCommentHeader( RifTextDataTableFormatter& formatter,
RigCompletionData::CompletionType completionType );
void generateCompsegTables( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
void generateCompsegTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<const RicMswBranch*> branch,
bool exportSubGridIntersections,
const std::set<RigCompletionData::CompletionType>& exportCompletionTypes,
gsl::not_null<bool*> headerGenerated,
gsl::not_null<std::set<size_t>*> intersectedCells );
void generateCompsegHeader( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
RigCompletionData::CompletionType completionType,
bool exportSubGridIntersections );
void generateWsegvalvTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
void generateWsegvalvTableRecursively( RifTextDataTableFormatter& formatter,
gsl::not_null<RicMswBranch*> branch,
bool& isHeaderWritten,
const QString& wellNameForExport );
void generateWsegAicdTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
std::vector<std::pair<double, double>> createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength );
double tvdFromMeasuredDepth( gsl::not_null<const RimWellPath*> wellPath, double measuredDepth );
void writeWsegvalHeader( RifTextDataTableFormatter& formatter );
} // namespace RicMswTableFormatterTools

View File

@ -99,7 +99,33 @@ void RicWellPathExportCompletionDataFeature::prepareExportSettingsAndExportCompl
s->descendantsIncludingThisOfType( simWellFractures );
}
for ( auto w : wellPaths )
std::vector<RimWellPath*> topLevelWells;
{
std::set<RimWellPath*> myWells;
for ( auto w : wellPaths )
{
myWells.insert( w->topLevelWellPath() );
}
topLevelWells.assign( myWells.begin(), myWells.end() );
}
std::vector<RimWellPath*> allLaterals;
{
std::set<RimWellPath*> laterals;
for ( auto t : topLevelWells )
{
auto laterals = t->wellPathLateralsRecursively();
for ( auto l : laterals )
{
allLaterals.push_back( l );
}
}
}
for ( auto w : allLaterals )
{
w->descendantsIncludingThisOfType( wellPathFractures );
w->descendantsIncludingThisOfType( wellPathFishbones );
@ -162,7 +188,7 @@ void RicWellPathExportCompletionDataFeature::prepareExportSettingsAndExportCompl
RiaApplication::instance()->setLastUsedDialogDirectory( "COMPLETIONS", exportSettings->folder );
RicWellPathExportCompletionDataFeatureImpl::exportCompletions( wellPaths, simWells, *exportSettings );
RicWellPathExportCompletionDataFeatureImpl::exportCompletions( topLevelWells, simWells, *exportSettings );
}
}
@ -220,25 +246,5 @@ std::vector<RimWellPath*> RicWellPathExportCompletionDataFeature::selectedWellPa
std::vector<RimWellPath*> wellPaths;
caf::SelectionManager::instance()->objectsByType( &wellPaths );
std::set<RimWellPath*> uniqueWellPaths( wellPaths.begin(), wellPaths.end() );
wellPaths.assign( uniqueWellPaths.begin(), uniqueWellPaths.end() );
if ( wellPaths.empty() )
{
RimWellPathCompletions* completions =
caf::SelectionManager::instance()->selectedItemAncestorOfType<RimWellPathCompletions>();
if ( completions )
{
RimWellPath* wellPath = nullptr;
completions->firstAncestorOrThisOfTypeAsserted( wellPath );
wellPaths.push_back( wellPath );
}
}
wellPaths.erase( std::remove_if( wellPaths.begin(),
wellPaths.end(),
[]( auto wellPath ) { return !wellPath->isTopLevelWellPath(); } ),
wellPaths.end() );
return wellPaths;
}

View File

@ -85,7 +85,7 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::vector<RimWellPath*>& wellPaths,
void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::vector<RimWellPath*>& topLevelWellPaths,
const std::vector<RimSimWellInView*>& simWells,
const RicExportCompletionDataSettingsUi& exportSettings )
{
@ -111,12 +111,16 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
if ( exportSettings.compdatExport == RicExportCompletionDataSettingsUi::TRANSMISSIBILITIES ||
exportSettings.compdatExport == RicExportCompletionDataSettingsUi::WPIMULT_AND_DEFAULT_CONNECTION_FACTORS )
{
std::vector<RimWellPath*> usedWellPaths;
for ( RimWellPath* wellPath : wellPaths )
std::vector<RimWellPath*> allWellPathLaterals;
for ( RimWellPath* wellPath : topLevelWellPaths )
{
if ( wellPath->unitSystem() == exportSettings.caseToApply->eclipseCaseData()->unitsType() )
{
usedWellPaths.push_back( wellPath );
auto tieInWells = wellPath->wellPathLateralsRecursively();
for ( auto w : tieInWells )
{
allWellPathLaterals.push_back( w );
}
}
else
{
@ -162,11 +166,11 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
}
size_t maxProgress =
usedWellPaths.size() * 3 + simWells.size() +
allWellPathLaterals.size() * 3 + simWells.size() +
( exportSettings.fileSplit == RicExportCompletionDataSettingsUi::SPLIT_ON_WELL
? usedWellPaths.size()
? allWellPathLaterals.size()
: exportSettings.fileSplit == RicExportCompletionDataSettingsUi::SPLIT_ON_WELL_AND_COMPLETION_TYPE
? usedWellPaths.size() * 3
? allWellPathLaterals.size() * 3
: 1 ) +
simWells.size();
@ -176,7 +180,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
std::vector<RigCompletionData> completions;
for ( auto wellPath : usedWellPaths )
for ( auto wellPath : allWellPathLaterals )
{
std::map<size_t, std::vector<RigCompletionData>> completionsPerEclipseCellAllCompletionTypes;
std::map<size_t, std::vector<RigCompletionData>> completionsPerEclipseCellFishbones;
@ -297,12 +301,12 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
}
else if ( exportSettings.fileSplit == RicExportCompletionDataSettingsUi::SPLIT_ON_WELL )
{
for ( auto wellPath : usedWellPaths )
for ( auto wellPath : topLevelWellPaths )
{
std::vector<RigCompletionData> completionsForWell;
for ( const auto& completion : completions )
{
if ( RicWellPathExportCompletionDataFeatureImpl::isCompletionWellPathEqual( completion, wellPath ) )
if ( wellPath == topLevelWellPath( completion ) )
{
completionsForWell.push_back( completion );
}
@ -340,15 +344,14 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
for ( const auto& completionType : completionTypes )
{
for ( auto wellPath : usedWellPaths )
for ( auto wellPath : topLevelWellPaths )
{
std::vector<RigCompletionData> completionsForWell;
for ( const auto& completion : completions )
{
if ( completionType == completion.completionType() )
{
if ( RicWellPathExportCompletionDataFeatureImpl::isCompletionWellPathEqual( completion,
wellPath ) )
if ( wellPath == topLevelWellPath( completion ) )
{
completionsForWell.push_back( completion );
}
@ -439,7 +442,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v
if ( exportSettings.includeMsw )
{
RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions( exportSettings, wellPaths );
RicWellPathExportMswCompletionsImpl::exportWellSegmentsForAllCompletions( exportSettings, topLevelWellPaths );
}
}
@ -1746,18 +1749,20 @@ std::pair<double, cvf::Vec2i> RicWellPathExportCompletionDataFeatureImpl::wellPa
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeatureImpl::isCompletionWellPathEqual( const RigCompletionData& completion,
const RimWellPath* wellPath )
RimWellPath* RicWellPathExportCompletionDataFeatureImpl::topLevelWellPath( const RigCompletionData& completion )
{
if ( !wellPath ) return false;
RimWellPath* parentWellPath = nullptr;
if ( completion.sourcePdmObject() )
{
completion.sourcePdmObject()->firstAncestorOrThisOfType( parentWellPath );
}
return ( parentWellPath == wellPath );
if ( parentWellPath )
{
return parentWellPath->topLevelWellPath();
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------

View File

@ -194,5 +194,5 @@ private:
static void exportCarfinForTemporaryLgrs( const RimEclipseCase* sourceCase, const QString& folder );
static bool isCompletionWellPathEqual( const RigCompletionData& completion, const RimWellPath* wellPath );
static RimWellPath* topLevelWellPath( const RigCompletionData& completion );
};

View File

@ -21,24 +21,21 @@
#include "RicMswCompletions.h"
#include "RicMswExportInfo.h"
#include "RicMswSegment.h"
#include "RigCompletionData.h"
#include <gsl/gsl>
#include <set>
class RicExportCompletionDataSettingsUi;
class RifTextDataTableFormatter;
class RigActiveCellInfo;
class RimEclipseCase;
class RimFishbones;
class RimPerforationInterval;
class RimWellPath;
class RimWellPathValve;
class RimWellPathFracture;
class RimMswCompletionParameters;
class SubSegmentIntersectionInfo;
class RigWellPath;
class RimModeledWellPath;
struct WellPathCellIntersectionInfo;
@ -47,23 +44,6 @@ class QFile;
class RicWellPathExportMswCompletionsImpl
{
private:
class CvfVec3stComparator
{
public:
bool operator()( const cvf::Vec3st& lhs, const cvf::Vec3st& rhs ) const
{
if ( lhs.z() == rhs.z() )
{
if ( lhs.y() == rhs.y() )
{
return lhs.x() < rhs.x();
}
return lhs.y() < rhs.y();
}
return lhs.z() < rhs.z();
}
};
public:
static void exportWellSegmentsForAllCompletions( const RicExportCompletionDataSettingsUi& exportSettings,
const std::vector<RimWellPath*>& wellPaths );
@ -71,20 +51,29 @@ public:
static void exportWellSegmentsForFractures( RimEclipseCase* eclipseCase,
std::shared_ptr<QFile> exportFile,
const RimWellPath* wellPath,
bool exportDataSourceAsComment );
bool exportDataSourceAsComment,
bool completionSegmentsAfterMainBore );
static void exportWellSegmentsForFishbones( RimEclipseCase* eclipseCase,
std::shared_ptr<QFile> exportFile,
const RimWellPath* wellPath,
bool exportDataSourceAsComment );
bool exportDataSourceAsComment,
bool completionSegmentsAfterMainBore );
static void exportWellSegmentsForPerforations( RimEclipseCase* eclipseCase,
std::shared_ptr<QFile> exportFile,
const RimWellPath* wellPath,
int timeStep,
bool exportDataSourceAsComment );
bool exportDataSourceAsComment,
bool completionSegmentsAfterMainBore );
static void generateFishbonesMswExportInfo( const RimEclipseCase* caseToApply,
static void generateFishbonesMswExportInfoForWell( const RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
gsl::not_null<RicMswExportInfo*> exportInfo,
gsl::not_null<RicMswBranch*> branch );
private:
static void generateFishbonesMswExportInfo( const RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
double initialMD,
const std::vector<WellPathCellIntersectionInfo>& cellIntersections,
@ -92,8 +81,7 @@ public:
gsl::not_null<RicMswExportInfo*> exportInfo,
gsl::not_null<RicMswBranch*> branch );
private:
static void generateFishbonesMswExportInfo( const RimEclipseCase* caseToApply,
static void generateFishbonesMswExportInfo( const RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
double initialMD,
const std::vector<WellPathCellIntersectionInfo>& cellIntersections,
@ -102,11 +90,12 @@ private:
gsl::not_null<RicMswExportInfo*> exportInfo,
gsl::not_null<RicMswBranch*> branch );
static RicMswExportInfo generateFracturesMswExportInfo( RimEclipseCase* caseToApply, const RimWellPath* wellPath );
static RicMswExportInfo generateFracturesMswExportInfo( RimEclipseCase* caseToApply,
const RimWellPath* wellPath,
const std::vector<RimWellPathFracture*>& fractures );
static bool generateFracturesMswExportInfo( RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
double initialMD,
const std::vector<WellPathCellIntersectionInfo>& cellIntersections,
gsl::not_null<RicMswExportInfo*> exportInfo,
gsl::not_null<RicMswBranch*> branch );
static bool generatePerforationsMswExportInfo( RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
@ -127,64 +116,12 @@ private:
gsl::not_null<const RigWellPath*> wellPathGeometry,
gsl::not_null<const RimEclipseCase*> eclipseCase );
static void generateWelsegsTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength );
static void writeWelsegsSegmentsRecursively( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<RicMswBranch*> branch,
gsl::not_null<int*> segmentNumber,
double maxSegmentLength,
RicMswSegment* connectedToSegment = nullptr );
static void writeWelsegsSegment( RicMswSegment* segment,
const RicMswSegment* previousSegment,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
gsl::not_null<RicMswBranch*> branch,
int* segmentNumber );
static void writeValveWelsegsSegment( const RicMswSegment* outletSegment,
RicMswValve* valve,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber );
static void writeCompletionWelsegsSegments( gsl::not_null<const RicMswSegment*> outletSegment,
gsl::not_null<const RicMswCompletion*> completion,
RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
double maxSegmentLength,
int* segmentNumber );
static void writeWelsegsCompletionCommentHeader( RifTextDataTableFormatter& formatter,
RigCompletionData::CompletionType completionType );
static void generateCompsegTables( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
static void generateCompsegTable( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
gsl::not_null<const RicMswBranch*> branch,
bool exportSubGridIntersections,
const std::set<RigCompletionData::CompletionType>& exportCompletionTypes,
gsl::not_null<bool*> headerGenerated,
gsl::not_null<std::set<cvf::Vec3st, CvfVec3stComparator>*> intersectedCells );
static void generateCompsegHeader( RifTextDataTableFormatter& formatter,
RicMswExportInfo& exportInfo,
RigCompletionData::CompletionType completionType,
bool exportSubGridIntersections );
static void generateWsegvalvTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
static void generateWsegAicdTable( RifTextDataTableFormatter& formatter, RicMswExportInfo& exportInfo );
static std::pair<double, double>
calculateOverlapWithActiveCells( double startMD,
double endMD,
const std::vector<WellPathCellIntersectionInfo>& wellPathIntersections,
const RigActiveCellInfo* activeCellInfo );
private:
static std::vector<std::pair<double, double>>
createSubSegmentMDPairs( double startMD, double endMD, double maxSegmentLength );
static void createWellPathSegments( gsl::not_null<RicMswBranch*> branch,
const std::vector<WellPathCellIntersectionInfo>& cellSegmentIntersections,
const std::vector<const RimPerforationInterval*>& perforationIntervals,
@ -211,14 +148,15 @@ private:
static void moveIntersectionsToSuperICDsOrAICDs( gsl::not_null<RicMswBranch*> branch );
static void assignFishbonesLateralIntersections( const RimEclipseCase* caseToApply,
static void assignFishbonesLateralIntersections( const RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
const RimFishbones* fishbonesSubs,
gsl::not_null<RicMswSegment*> segment,
bool* foundSubGridIntersections,
double maxSegmentLength );
double maxSegmentLength,
RiaDefines::EclipseUnitSystem unitSystem );
static void assignFractureCompletionsToCellSegment( const RimEclipseCase* caseToApply,
static void assignFractureCompletionsToCellSegment( const RimEclipseCase* eclipseCase,
const RimWellPath* wellPath,
const RimWellPathFracture* fracture,
const std::vector<RigCompletionData>& completionData,
@ -238,17 +176,19 @@ private:
double overlapEnd,
bool* foundSubGridIntersections );
static void assignBranchNumbersToPerforations( const RimEclipseCase* caseToApply,
static void assignBranchNumbersToPerforations( const RimEclipseCase* eclipseCase,
gsl::not_null<RicMswSegment*> segment,
gsl::not_null<int*> branchNumber );
static void assignBranchNumbersToOtherCompletions( const RimEclipseCase* caseToApply,
static void assignBranchNumbersToOtherCompletions( const RimEclipseCase* eclipseCase,
gsl::not_null<RicMswSegment*> segment,
gsl::not_null<int*> branchNumber );
static void assignBranchNumbersToBranch( const RimEclipseCase* caseToApply,
static void assignBranchNumbersToBranch( const RimEclipseCase* eclipseCase,
RicMswExportInfo* exportInfo,
gsl::not_null<RicMswBranch*> branch,
gsl::not_null<int*> branchNumber );
static double tvdFromMeasuredDepth( gsl::not_null<const RimWellPath*> wellPath, double measuredDepth );
static std::unique_ptr<RicMswBranch> createChildMswBranch( const RimModeledWellPath* childWellPath );
static std::vector<RimModeledWellPath*> wellPathsWithTieIn( const RimWellPath* wellPath );
};

View File

@ -143,7 +143,8 @@ void RicEclipseCellResultToFileImpl::writeDataToTextFile( QFile*
textstream << "\n";
textstream << "-- Exported from ResInsight"
<< "\n";
textstream << eclipseKeyword << "\n" << right << qSetFieldWidth( 16 );
textstream << eclipseKeyword << "\n" << qSetFieldWidth( 16 );
textstream.setFieldAlignment( QTextStream::AlignRight );
caf::ProgressInfo pi( resultData.size(), QString( "Writing data to file %1" ).arg( file->fileName() ) );
size_t progressSteps = resultData.size() / 20;

View File

@ -15,6 +15,7 @@
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicNewWellPathLateralAtDepthFeature.h"
#include "WellPathCommands/RicWellPathsUnitSystemSettingsImpl.h"
@ -23,12 +24,11 @@
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimModeledWellPath.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimTools.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimWellPathGeometryDef.h"
#include "RimWellPathGroup.h"
#include "RimWellPathTarget.h"
#include "Riu3DMainWindowTools.h"
@ -38,6 +38,7 @@
#include <QAction>
#include "RiaTextStringTools.h"
#include <cmath>
CAF_CMD_SOURCE_INIT( RicNewWellPathLateralAtDepthFeature, "RicNewWellPathLateralAtDepthFeature" );
@ -63,56 +64,44 @@ void RicNewWellPathLateralAtDepthFeature::onActionTriggered( bool isChecked )
RiuWellPathSelectionItem* wellPathSelItem = wellPathSelectionItem();
CVF_ASSERT( wellPathSelItem );
RimWellPath* wellPath = wellPathSelItem->m_wellpath;
CVF_ASSERT( wellPath );
RimWellPathGroup* wellPathGroup = nullptr;
wellPath->firstAncestorOrThisOfType( wellPathGroup );
RimWellPath* parentWellPath = wellPathSelItem->m_wellpath;
CVF_ASSERT( parentWellPath );
RimProject* project = RimProject::current();
if ( project && RimProject::current()->activeOilField() )
RimProject* project = RimProject::current();
RimWellPathCollection* wellPathColl = RimTools::wellPathCollection();
if ( project && wellPathColl )
{
RimWellPathCollection* wellPathCollection = RimProject::current()->activeOilField()->wellPathCollection();
double parentWellMD = wellPathSelItem->m_measuredDepth;
if ( wellPathCollection )
{
auto newModeledWellPath = new RimModeledWellPath();
auto newModeledWellPath = new RimModeledWellPath();
auto [pointVector, measuredDepths] =
wellPath->wellPathGeometry()->clippedPointSubset( wellPath->wellPathGeometry()->measuredDepths().front(),
wellPathSelItem->m_measuredDepth );
if ( pointVector.size() < 2u ) return;
newModeledWellPath->geometryDefinition()->setMdAtFirstTarget( measuredDepths.back() );
newModeledWellPath->geometryDefinition()->setUseAutoGeneratedTargetAtSeaLevel( false );
newModeledWellPath->geometryDefinition()->setFixedWellPathPoints( pointVector );
newModeledWellPath->geometryDefinition()->setFixedMeasuredDepths( measuredDepths );
newModeledWellPath->setName( wellPath->name() + QString( " md=%1" ).arg( wellPathSelItem->m_measuredDepth ) );
auto [pointVector, measuredDepths] =
parentWellPath->wellPathGeometry()
->clippedPointSubset( parentWellPath->wellPathGeometry()->measuredDepths().front(), parentWellMD );
if ( pointVector.size() < 2u ) return;
{
RimWellPathTarget* newTarget = newModeledWellPath->geometryDefinition()->appendTarget();
auto lastPoint = pointVector.back();
auto tangent = lastPoint - pointVector[pointVector.size() - 2];
newTarget->setAsPointXYZAndTangentTarget( { lastPoint[0], lastPoint[1], lastPoint[2] }, tangent );
}
newModeledWellPath->geometryDefinition()->setIsAttachedToParentWell( true );
newModeledWellPath->geometryDefinition()->setMdAtFirstTarget( measuredDepths.back() );
newModeledWellPath->geometryDefinition()->setUseAutoGeneratedTargetAtSeaLevel( false );
newModeledWellPath->geometryDefinition()->setFixedWellPathPoints( pointVector );
newModeledWellPath->geometryDefinition()->setFixedMeasuredDepths( measuredDepths );
newModeledWellPath->geometryDefinition()->enableTargetPointPicking( true );
auto nameOfNewWell = updateNameOfParentAndFindNameOfSideStep( parentWellPath );
newModeledWellPath->setName( nameOfNewWell );
newModeledWellPath->connectWellPaths( parentWellPath, parentWellMD );
newModeledWellPath->createWellPathGeometry();
if ( wellPathGroup )
{
wellPathGroup->addChildWellPath( newModeledWellPath );
}
else
{
bool importedWellPath = false;
wellPathCollection->addWellPath( newModeledWellPath, importedWellPath );
wellPathCollection->groupWellPaths( { wellPath, newModeledWellPath } );
}
newModeledWellPath->firstAncestorOrThisOfTypeAsserted( wellPathGroup );
wellPathGroup->updateAllRequiredEditors();
project->scheduleCreateDisplayModelAndRedrawAllViews();
newModeledWellPath->geometryDefinition()->enableTargetPointPicking( true );
newModeledWellPath->setUnitSystem( parentWellPath->unitSystem() );
Riu3DMainWindowTools::selectAsCurrentItem( newModeledWellPath->geometryDefinition() );
}
newModeledWellPath->createWellPathGeometry();
bool importGrouped = false;
wellPathColl->addWellPath( newModeledWellPath, importGrouped );
wellPathColl->updateAllRequiredEditors();
project->scheduleCreateDisplayModelAndRedrawAllViews();
Riu3DMainWindowTools::selectAsCurrentItem( newModeledWellPath->geometryDefinition() );
}
}
@ -137,3 +126,76 @@ RiuWellPathSelectionItem* RicNewWellPathLateralAtDepthFeature::wellPathSelection
return wellPathItem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicNewWellPathLateralAtDepthFeature::updateNameOfParentAndFindNameOfSideStep( RimWellPath* parentwWellPath )
{
if ( !parentwWellPath ) return "";
QString nameOfNewWell;
auto topLevelWell = parentwWellPath->topLevelWellPath();
QStringList allNames;
{
RimProject* proj = RimProject::current();
const std::vector<RimWellPath*>& wellPaths = proj->allWellPaths();
for ( auto wellPath : wellPaths )
{
if ( wellPath )
{
auto currentTopLevelWell = wellPath->topLevelWellPath();
if ( topLevelWell == currentTopLevelWell )
{
allNames.push_back( wellPath->name() );
}
}
}
}
if ( allNames.size() == 1 )
{
QString name = parentwWellPath->name();
if ( name.contains( "Y1" ) )
{
nameOfNewWell = name.replace( "Y1", "Y2" );
}
else
{
parentwWellPath->setNameNoUpdateOfExportName( name + " Y1" );
nameOfNewWell = name + " Y2";
}
return nameOfNewWell;
}
{
QString commonRoot = RiaTextStringTools::commonRoot( allNames );
QString trimmedCommonRoot = RiaTextStringTools::trimNonAlphaNumericCharacters( commonRoot );
// Remove side step prefix
trimmedCommonRoot.replace( " Y", "" );
int maxYValue = 0;
for ( auto n : allNames )
{
auto suffix = n.replace( trimmedCommonRoot, "" );
int candidate = suffix.toInt();
maxYValue = std::max( maxYValue, candidate );
}
if ( !trimmedCommonRoot.isEmpty() && trimmedCommonRoot.endsWith( "Y" ) )
{
trimmedCommonRoot = trimmedCommonRoot.left( trimmedCommonRoot.size() - 1 ).trimmed();
}
nameOfNewWell = QString( "%1 Y%2" ).arg( trimmedCommonRoot ).arg( maxYValue + 1 );
}
return nameOfNewWell;
}

View File

@ -21,6 +21,7 @@
#include "cafCmdFeature.h"
class RiuWellPathSelectionItem;
class RimWellPath;
//==================================================================================================
///
@ -37,4 +38,5 @@ protected:
private:
static RiuWellPathSelectionItem* wellPathSelectionItem();
QString updateNameOfParentAndFindNameOfSideStep( RimWellPath* parentwWellPath );
};

View File

@ -562,12 +562,12 @@ void RifEclipseInputFileTools::saveFault( QString
}
QTextStream stream( &exportFile );
stream << "FAULTS" << endl;
stream << "FAULTS" << '\n';
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << endl;
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << '\n';
saveFault( stream, mainGrid, faultFaces, faultName, min, maxIn, refinement );
stream << "/" << endl;
stream << "/" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -744,9 +744,9 @@ void RifEclipseInputFileTools::saveFaults( QTextStream& stream,
const cvf::Vec3st& max /*= cvf::Vec3st::UNDEFINED*/,
const cvf::Vec3st& refinement /*= cvf::Vec3st(1, 1, 1)*/ )
{
stream << "FAULTS" << endl;
stream << "FAULTS" << '\n';
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << endl;
stream << "-- Name I1 I2 J1 J2 K1 K2 Face ( I/J/K )" << '\n';
const cvf::Collection<RigFault>& faults = mainGrid->faults();
for ( const auto& fault : faults )
@ -757,7 +757,7 @@ void RifEclipseInputFileTools::saveFaults( QTextStream& stream,
saveFault( stream, mainGrid, fault->faultFaces(), fault->name(), min, max, refinement );
}
}
stream << "/" << endl;
stream << "/" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -1319,7 +1319,7 @@ void RifEclipseInputFileTools::writeFaultLine( QTextStream&
stream << "'" << faultName << "'"
<< " " << i << " " << i << " " << j << " " << j << " " << startK << " " << endK << " "
<< faultFaceText( faceType ) << " / ";
stream << endl;
stream << '\n';
}
//--------------------------------------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ bool RifStimPlanModelAsymmetricFrkExporter::writeToFile( RimStimPlanModel* stimP
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelAsymmetricFrkExporter::appendHeaderToStream( QTextStream& stream )
{
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl << "<asymmetric>" << endl;
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << '\n' << "<asymmetric>" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -75,21 +75,21 @@ void RifStimPlanModelAsymmetricFrkExporter::appendBarrierDataToStream( QTextStre
double barrierDipDeg,
int wellPenetrationLayer )
{
stream << "<BedDipDeg>" << endl
<< bedDipDeg << endl
<< "</BedDipDeg>" << endl
<< "<Barrier>" << endl
<< static_cast<int>( hasBarrier ) << endl
<< "</Barrier>" << endl
<< "<BarrierDipDeg>" << endl
<< barrierDipDeg << endl
<< "</BarrierDipDeg>" << endl
<< "<DistanceToBarrier>" << endl
<< distanceToBarrier << endl
<< "</DistanceToBarrier>" << endl
<< "<WellPenetrationLayer>" << endl
<< wellPenetrationLayer << endl
<< "</WellPenetrationLayer>" << endl;
stream << "<BedDipDeg>" << '\n'
<< bedDipDeg << '\n'
<< "</BedDipDeg>" << '\n'
<< "<Barrier>" << '\n'
<< static_cast<int>( hasBarrier ) << '\n'
<< "</Barrier>" << '\n'
<< "<BarrierDipDeg>" << '\n'
<< barrierDipDeg << '\n'
<< "</BarrierDipDeg>" << '\n'
<< "<DistanceToBarrier>" << '\n'
<< distanceToBarrier << '\n'
<< "</DistanceToBarrier>" << '\n'
<< "<WellPenetrationLayer>" << '\n'
<< wellPenetrationLayer << '\n'
<< "</WellPenetrationLayer>" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -97,5 +97,5 @@ void RifStimPlanModelAsymmetricFrkExporter::appendBarrierDataToStream( QTextStre
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelAsymmetricFrkExporter::appendFooterToStream( QTextStream& stream )
{
stream << "</asymmetric>" << endl;
stream << "</asymmetric>" << '\n';
}

View File

@ -75,7 +75,7 @@ bool RifStimPlanModelDeviationFrkExporter::writeToFile( RimStimPlanModel* stimPl
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelDeviationFrkExporter::appendHeaderToStream( QTextStream& stream )
{
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl << "<deviation>" << endl;
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << '\n' << "<deviation>" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -86,23 +86,23 @@ void RifStimPlanModelDeviationFrkExporter::appendToStream( QTextStream&
const std::vector<double>& values )
{
stream.setRealNumberPrecision( 20 );
stream << "<cNamedSet>" << endl
<< "<name>" << endl
<< label << endl
<< "</name>" << endl
<< "<dimCount>" << endl
<< 1 << endl
<< "</dimCount>" << endl
<< "<sizes>" << endl
<< values.size() << endl
<< "</sizes>" << endl
<< "<data>" << endl;
stream << "<cNamedSet>" << '\n'
<< "<name>" << '\n'
<< label << '\n'
<< "</name>" << '\n'
<< "<dimCount>" << '\n'
<< 1 << '\n'
<< "</dimCount>" << '\n'
<< "<sizes>" << '\n'
<< values.size() << '\n'
<< "</sizes>" << '\n'
<< "<data>" << '\n';
for ( auto val : values )
{
stream << val << endl;
stream << val << '\n';
}
stream << "</data>" << endl << "</cNamedSet>" << endl;
stream << "</data>" << '\n' << "</cNamedSet>" << '\n';
}
//--------------------------------------------------------------------------------------------------
@ -110,7 +110,7 @@ void RifStimPlanModelDeviationFrkExporter::appendToStream( QTextStream&
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelDeviationFrkExporter::appendFooterToStream( QTextStream& stream )
{
stream << "</deviation>" << endl;
stream << "</deviation>" << '\n';
}
//--------------------------------------------------------------------------------------------------

View File

@ -234,7 +234,7 @@ bool RifStimPlanModelGeologicalFrkExporter::writeToCsvFile( const QString&
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelGeologicalFrkExporter::appendHeaderToStream( QTextStream& stream )
{
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl << "<geologic>" << endl;
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << '\n' << "<geologic>" << endl;
}
//--------------------------------------------------------------------------------------------------
@ -260,7 +260,7 @@ void RifStimPlanModelGeologicalFrkExporter::appendToStream( QTextStream&
stream << val << endl;
}
stream << "</data>" << endl << "</cNamedSet>" << endl;
stream << "</data>" << '\n' << "</cNamedSet>" << endl;
}
//--------------------------------------------------------------------------------------------------

View File

@ -80,7 +80,7 @@ bool RifStimPlanModelPerfsFrkExporter::writeToFile( RimStimPlanModel* stimPlanMo
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelPerfsFrkExporter::appendHeaderToStream( QTextStream& stream )
{
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl << "<perfs>" << endl;
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << '\n' << "<perfs>" << endl;
}
//--------------------------------------------------------------------------------------------------
@ -88,7 +88,7 @@ void RifStimPlanModelPerfsFrkExporter::appendHeaderToStream( QTextStream& stream
//--------------------------------------------------------------------------------------------------
void RifStimPlanModelPerfsFrkExporter::appendFractureOrientationToStream( QTextStream& stream, bool isTransverse )
{
stream << "<transverse>" << endl << static_cast<int>( isTransverse ) << endl << "</transverse>" << endl;
stream << "<transverse>" << '\n' << static_cast<int>( isTransverse ) << '\n' << "</transverse>" << endl;
}
//--------------------------------------------------------------------------------------------------

View File

@ -32,8 +32,7 @@
#include "RimEclipseView.h"
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLaterals.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimModeledWellPath.h"
#include "RimPerforationCollection.h"
#include "RimPerforationInterval.h"
#include "RimRegularLegendConfig.h"
@ -49,6 +48,8 @@
#include "RimWellPathCollection.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPathGeometryDef.h"
#include "RimWellPathTarget.h"
#include "RimWellPathValve.h"
#include "Riv3dWellLogPlanePartMgr.h"
@ -67,12 +68,18 @@
#include "cafDisplayCoordTransform.h"
#include "cafEffectGenerator.h"
#include "cvfDrawableGeo.h"
#include "cvfDrawableText.h"
#include "cvfDrawableVectors.h"
#include "cvfFont.h"
#include "cvfGeometryBuilderTriangles.h"
#include "cvfGeometryUtils.h"
#include "cvfModelBasicList.h"
#include "cvfOpenGLResourceManager.h"
#include "cvfPart.h"
#include "cvfScalarMapperContinuousLinear.h"
#include "cvfShaderProgram.h"
#include "cvfTransform.h"
#include "cvfqtUtils.h"
@ -362,40 +369,6 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList*
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivWellPathPartMgr::appendImportedFishbonesToModel( cvf::ModelBasicList* model,
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize )
{
if ( !m_rimWellPath || !m_rimWellPath->fishbonesCollection()->wellPathCollection()->isChecked() ) return;
RivPipeGeometryGenerator geoGenerator;
std::vector<RimImportedFishboneLaterals*> fishbonesWellPaths;
m_rimWellPath->descendantsIncludingThisOfType( fishbonesWellPaths );
for ( RimImportedFishboneLaterals* fbWellPath : fishbonesWellPaths )
{
if ( !fbWellPath->isChecked() ) continue;
std::vector<cvf::Vec3d> displayCoords =
displayCoordTransform->transformToDisplayCoords( fbWellPath->coordinates() );
cvf::ref<RivObjectSourceInfo> objectSourceInfo = new RivObjectSourceInfo( fbWellPath );
cvf::Collection<cvf::Part> parts;
geoGenerator.cylinderWithCenterLineParts( &parts,
displayCoords,
m_rimWellPath->wellPathColor(),
m_rimWellPath->combinedScaleFactor() * characteristicCellSize * 0.5 );
for ( auto part : parts )
{
part->setSourceInfo( objectSourceInfo.p() );
model->addPart( part.p() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -783,6 +756,73 @@ void RivWellPathPartMgr::buildWellPathParts( const caf::DisplayCoordTransform* d
m_wellLabelPart = part;
}
auto modeledWellPath = dynamic_cast<RimModeledWellPath*>( m_rimWellPath.p() );
if ( modeledWellPath )
{
bool showWellTargetSpheres = modeledWellPath->geometryDefinition()->showSpheres();
if ( showWellTargetSpheres )
{
auto geoDef = modeledWellPath->geometryDefinition();
auto sphereColor = geoDef->sphereColor();
double sphereRadiusFactor = geoDef->sphereRadiusFactor();
cvf::ref<cvf::Vec3fArray> vertices = new cvf::Vec3fArray;
cvf::ref<cvf::Vec3fArray> vecRes = new cvf::Vec3fArray;
cvf::ref<cvf::Color3fArray> colors = new cvf::Color3fArray;
auto wellTargets = geoDef->activeWellTargets();
size_t pointCount = wellTargets.size();
vertices->reserve( pointCount );
vecRes->reserve( pointCount );
colors->reserve( pointCount );
for ( const auto target : wellTargets )
{
auto domainCoord = target->targetPointXYZ() + modeledWellPath->geometryDefinition()->anchorPointXyz();
auto displayCoord = displayCoordTransform->transformToDisplayCoord( domainCoord );
vertices->add( cvf::Vec3f( displayCoord ) );
vecRes->add( cvf::Vec3f::X_AXIS );
colors->add( sphereColor );
}
cvf::ref<cvf::DrawableVectors> vectorDrawable;
if ( RiaGuiApplication::instance()->useShaders() )
{
vectorDrawable = new cvf::DrawableVectors( "u_transformationMatrix", "u_color" );
}
else
{
vectorDrawable = new cvf::DrawableVectors();
}
vectorDrawable->setVectors( vertices.p(), vecRes.p() );
vectorDrawable->setColors( colors.p() );
double cellRadius = 15.0;
auto eclipseView = dynamic_cast<RimEclipseView*>( m_rimView.p() );
if ( eclipseView )
{
double characteristicCellSize = eclipseView->mainGrid()->characteristicIJCellSize();
cellRadius = sphereRadiusFactor * characteristicCellSize;
}
cvf::GeometryBuilderTriangles builder;
cvf::GeometryUtils::createSphere( cellRadius, 15, 15, &builder );
vectorDrawable->setGlyph( builder.trianglesUShort().p(), builder.vertices().p() );
cvf::ref<cvf::Part> part = new cvf::Part;
part->setName( "RivWellPathPartMgr_WellTargetSpheres" );
part->setDrawable( vectorDrawable.p() );
part->setEffect( new cvf::Effect() );
m_spherePart = part;
}
}
}
//--------------------------------------------------------------------------------------------------
@ -813,8 +853,12 @@ void RivWellPathPartMgr::appendStaticGeometryPartsToModel( cvf::ModelBasicList*
model->addPart( m_wellLabelPart.p() );
}
if ( m_spherePart.notNull() )
{
model->addPart( m_spherePart.p() );
}
appendFishboneSubsPartsToModel( model, displayCoordTransform, characteristicCellSize );
appendImportedFishbonesToModel( model, displayCoordTransform, characteristicCellSize );
appendWellPathAttributesToModel( model, displayCoordTransform, characteristicCellSize );
RimGridView* gridView = dynamic_cast<RimGridView*>( m_rimView.p() );
@ -852,6 +896,11 @@ void RivWellPathPartMgr::appendFlattenedStaticGeometryPartsToModel( cvf::ModelBa
{
model->addPart( m_wellLabelPart.p() );
}
if ( m_spherePart.notNull() )
{
model->addPart( m_spherePart.p() );
}
}
//--------------------------------------------------------------------------------------------------
@ -923,6 +972,7 @@ void RivWellPathPartMgr::clearAllBranchData()
m_centerLinePart = nullptr;
m_centerLineDrawable = nullptr;
m_wellLabelPart = nullptr;
m_spherePart = nullptr;
}
//--------------------------------------------------------------------------------------------------

View File

@ -98,9 +98,6 @@ private:
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize );
void appendImportedFishbonesToModel( cvf::ModelBasicList* model,
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize );
void appendPerforationsToModel( cvf::ModelBasicList* model,
size_t timeStepIndex,
@ -147,6 +144,7 @@ private:
cvf::ref<cvf::Part> m_centerLinePart;
cvf::ref<cvf::DrawableGeo> m_centerLineDrawable;
cvf::ref<cvf::Part> m_wellLabelPart;
cvf::ref<cvf::Part> m_spherePart;
cvf::ref<Riv3dWellLogPlanePartMgr> m_3dWellLogPlanePartMgr;
cvf::ref<RivWellConnectionFactorPartMgr> m_wellConnectionFactorPartMgr;

View File

@ -152,6 +152,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimCustomObjectiveFunctionWeight.h
${CMAKE_CURRENT_LIST_DIR}/RimEquilibriumAxisAnnotation.h
${CMAKE_CURRENT_LIST_DIR}/RimTimeAxisAnnotation.h
${CMAKE_CURRENT_LIST_DIR}/RimPolylinesDataInterface.h
${CMAKE_CURRENT_LIST_DIR}/RimWellPathTieIn.h
)
@ -304,6 +305,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimCustomObjectiveFunction.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCustomObjectiveFunctionWeight.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEquilibriumAxisAnnotation.cpp
${CMAKE_CURRENT_LIST_DIR}/RimTimeAxisAnnotation.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPathTieIn.cpp
)
if(Qt5Charts_FOUND)

View File

@ -42,8 +42,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RimCompletionCellIntersectionCalc.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFishbonesCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFishbones.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFishbonesPipeProperties.cpp
${CMAKE_CURRENT_LIST_DIR}/RimImportedFishboneLaterals.cpp
${CMAKE_CURRENT_LIST_DIR}/RimImportedFishboneLateralsCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPerforationCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimPerforationInterval.cpp
${CMAKE_CURRENT_LIST_DIR}/RimWellPathCompletions.cpp

View File

@ -24,6 +24,7 @@
#include "RigFishbonesGeometry.h"
#include "RigWellPath.h"
#include "RimFishbonesCollection.h"
#include "RimFishbonesPipeProperties.h"
#include "RimMultipleValveLocations.h"
#include "RimProject.h"
#include "RimWellPath.h"
@ -185,7 +186,7 @@ QString RimFishbones::generatedName() const
dynamic_cast<caf::PdmChildArrayField<RimFishbones*>*>( this->parentField() );
CVF_ASSERT( container );
size_t index = container->index( this );
size_t index = container->index( this ) + 1;
return QString( "Fishbone %1" ).arg( index );
}
@ -278,7 +279,17 @@ double RimFishbones::tubingDiameter( RiaDefines::EclipseUnitSystem unitSystem )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFishbones::effectiveDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
double RimFishbones::holeDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
{
return m_pipeProperties()->holeDiameter( unitSystem );
}
//--------------------------------------------------------------------------------------------------
/// Compute the equivalent diameter based on the area between two cylinders
//
// http://www.fekete.com/san/webhelp/feketeharmony/harmony_webhelp/content/html_files/reference_material/calculations_and_correlations/annular_diameters.htm
//--------------------------------------------------------------------------------------------------
double RimFishbones::equivalentDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
{
double innerRadius = tubingDiameter( unitSystem ) / 2;
double outerRadius = holeDiameter( unitSystem ) / 2;
@ -286,12 +297,20 @@ double RimFishbones::effectiveDiameter( RiaDefines::EclipseUnitSystem unitSystem
double innerArea = cvf::PI_D * innerRadius * innerRadius;
double outerArea = cvf::PI_D * outerRadius * outerRadius;
double effectiveArea = outerArea - innerArea;
double equivalentArea = outerArea - innerArea;
double effectiveRadius = cvf::Math::sqrt( effectiveArea / cvf::PI_D );
double effectiveRadius = cvf::Math::sqrt( equivalentArea / cvf::PI_D );
return effectiveRadius * 2;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimFishbones::skinFactor() const
{
return m_pipeProperties()->skinFactor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -382,6 +401,14 @@ void RimFishbones::geometryUpdated()
proj->reloadCompletionTypeResultsInAllViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RimFishbones::SubAndLateralIndex>& RimFishbones::installedLateralIndices() const
{
return m_subLateralIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -613,13 +640,13 @@ void RimFishbones::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& u
}
{
caf::PdmUiGroup* wellGroup = uiOrdering.addNewGroup( "Well Properties" );
caf::PdmUiGroup* wellGroup = uiOrdering.addNewGroup( "Lateral Properties" );
m_pipeProperties->uiOrdering( uiConfigName, *wellGroup );
}
{
caf::PdmUiGroup* mswGroup = uiOrdering.addNewGroup( "Multi Segment Wells" );
caf::PdmUiGroup* mswGroup = uiOrdering.addNewGroup( "Lateral Multi Segment Wells" );
mswGroup->setCollapsedByDefault( true );
mswGroup->add( &m_lateralTubingDiameter );
mswGroup->add( &m_lateralOpenHoleRoghnessFactor );

View File

@ -22,7 +22,6 @@
#include "Rim3dPropertiesInterface.h"
#include "RimCheckableNamedObject.h"
#include "RimFishbonesPipeProperties.h"
#include "RimWellPathComponentInterface.h"
#include "cvfColor3.h"
@ -37,6 +36,7 @@
#include <memory>
class RigFisbonesGeometry;
class RimFishbonesPipeProperties;
class RimMultipleValveLocations;
//==================================================================================================
@ -79,13 +79,10 @@ public:
double exitAngle() const;
double buildAngle() const;
double tubingDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double holeDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
{
return m_pipeProperties()->holeDiameter( unitSystem );
}
double effectiveDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double skinFactor() const { return m_pipeProperties()->skinFactor(); }
double tubingDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double holeDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double equivalentDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double skinFactor() const;
double openHoleRoughnessFactor( RiaDefines::EclipseUnitSystem unitSystem ) const;
double icdOrificeDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const;
double icdFlowCoefficient() const;
@ -94,7 +91,7 @@ public:
void geometryUpdated();
const std::vector<SubAndLateralIndex>& installedLateralIndices() const { return m_subLateralIndices; };
const std::vector<SubAndLateralIndex>& installedLateralIndices() const;
std::vector<cvf::Vec3d> coordsForLateral( size_t subIndex, size_t lateralIndex ) const;
std::vector<std::pair<cvf::Vec3d, double>> coordsAndMDForLateral( size_t subIndex, size_t lateralIndex ) const;
void recomputeLateralLocations();

View File

@ -25,7 +25,6 @@
#include "RigWellPath.h"
#include "RimFishbones.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimProject.h"
#include "RimWellPath.h"
@ -50,10 +49,6 @@ RimFishbonesCollection::RimFishbonesCollection()
m_fishbones.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_wellPathCollection, "WellPathCollection", "Imported Laterals", "", "", "" );
m_wellPathCollection = new RimImportedFishboneLateralsCollection;
m_wellPathCollection.uiCapability()->setUiHidden( true );
CAF_PDM_InitField( &m_startMD, "StartMD", HUGE_VAL, "Start MD", "", "", "" );
CAF_PDM_InitField( &m_mainBoreDiameter, "MainBoreDiameter", 0.216, "Main Bore Diameter", "", "", "" );
CAF_PDM_InitField( &m_skinFactor, "MainBoreSkinFactor", 0., "Main Bore Skin Factor [0..1]", "", "", "" );
@ -74,16 +69,6 @@ RimFishbonesCollection::RimFishbonesCollection()
m_lengthAndDepth_OBSOLETE.xmlCapability()->setIOWritable( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimImportedFishboneLateralsCollection* RimFishbonesCollection::wellPathCollection() const
{
CVF_ASSERT( m_wellPathCollection );
return m_wellPathCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -268,14 +253,6 @@ void RimFishbonesCollection::recalculateStartMD()
}
}
for ( const RimImportedFishboneLaterals* wellPath : m_wellPathCollection->wellPaths() )
{
if ( wellPath->measuredDepths().size() > 0 )
{
minStartMD = std::min( minStartMD, wellPath->measuredDepths()[0] - 13.0 );
}
}
if ( !manuallyModifiedStartMD || minStartMD < m_startMD() )
{
m_startMD = minStartMD;
@ -342,7 +319,5 @@ void RimFishbonesCollection::setUnitSystemSpecificDefaults()
{
m_mainBoreDiameter = 0.708;
}
m_wellPathCollection->setUnitSystemSpecificDefaults();
}
}

View File

@ -30,7 +30,6 @@
#include "cvfColor3.h"
class RimFishbones;
class RimImportedFishboneLateralsCollection;
//==================================================================================================
//
@ -44,9 +43,8 @@ class RimFishbonesCollection : public RimCheckableNamedObject
public:
RimFishbonesCollection();
RimImportedFishboneLateralsCollection* wellPathCollection() const;
void appendFishbonesSubs( RimFishbones* subs );
const RimMswCompletionParameters* mswParameters() const;
void appendFishbonesSubs( RimFishbones* subs );
const RimMswCompletionParameters* mswParameters() const;
bool hasFishbones() const;
std::vector<RimFishbones*> activeFishbonesSubs() const;
@ -68,9 +66,8 @@ private:
cvf::Color3f nextFishbonesColor() const;
private:
caf::PdmChildArrayField<RimFishbones*> m_fishbones;
caf::PdmChildField<RimImportedFishboneLateralsCollection*> m_wellPathCollection;
caf::PdmChildField<RimMswCompletionParameters*> m_mswParameters;
caf::PdmChildArrayField<RimFishbones*> m_fishbones;
caf::PdmChildField<RimMswCompletionParameters*> m_mswParameters;
caf::PdmField<double> m_startMD;
caf::PdmField<double> m_skinFactor;

View File

@ -1,117 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
//
// 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 "RimImportedFishboneLaterals.h"
#include "RimProject.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiTextEditor.h"
CAF_PDM_SOURCE_INIT( RimImportedFishboneLaterals, "WellPathCompletion" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimImportedFishboneLaterals::RimImportedFishboneLaterals()
{
CAF_PDM_InitObject( "WellPathCompletion", ":/FishBoneLateralFromFile16x16.png", "", "" );
CAF_PDM_InitFieldNoDefault( &m_coordinates, "Coordinates", "Coordinates", "", "", "" );
m_coordinates.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_measuredDepths, "MeasuredDepth", "MeasuredDepth", "", "", "" );
m_measuredDepths.uiCapability()->setUiHidden( true );
userDescriptionField()->uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_displayCoordinates, "DisplayCoordinates", "Coordinates", "", "", "" );
m_displayCoordinates.registerGetMethod( this, &RimImportedFishboneLaterals::displayCoordinates );
m_displayCoordinates.uiCapability()->setUiReadOnly( true );
m_displayCoordinates.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
m_displayCoordinates.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosType::TOP );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimImportedFishboneLaterals::~RimImportedFishboneLaterals()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLaterals::setCoordinates( std::vector<cvf::Vec3d> coordinates )
{
m_coordinates = coordinates;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLaterals::setMeasuredDepths( std::vector<double> measuredDepths )
{
m_measuredDepths = measuredDepths;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLaterals::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimProject* proj;
this->firstAncestorOrThisOfType( proj );
if ( proj ) proj->scheduleCreateDisplayModelAndRedrawAllViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLaterals::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_displayCoordinates );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimImportedFishboneLaterals::displayCoordinates() const
{
CVF_ASSERT( m_coordinates().size() == m_measuredDepths().size() );
QStringList displayValues;
displayValues.push_back( QString( "X\tY\tZ\tMD" ) );
for ( size_t i = 0; i < m_coordinates().size(); i++ )
{
const cvf::Vec3d& coords = m_coordinates()[i];
const double& measuredDepth = m_measuredDepths()[i];
displayValues.push_back( QString( "%1\t%2\t%3\t%4" )
.arg( coords.x(), 0, 'f', 2 )
.arg( coords.y(), 0, 'f', 2 )
.arg( coords.z(), 0, 'f', 2 )
.arg( measuredDepth, 0, 'f', 2 ) );
}
return displayValues.join( "\n" );
}

View File

@ -1,66 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimCheckableNamedObject.h"
#include "cafAppEnum.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
// Include to make Pdm work for cvf::Color
#include "cafPdmChildArrayField.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfVec3d.h"
#include "cafPdmProxyValueField.h"
#include "cvfObject.h"
#include "cvfVector3.h"
//==================================================================================================
///
///
//==================================================================================================
class RimImportedFishboneLaterals : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
RimImportedFishboneLaterals();
~RimImportedFishboneLaterals() override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void setCoordinates( std::vector<cvf::Vec3d> coordinates );
void setMeasuredDepths( std::vector<double> measuredDepths );
std::vector<cvf::Vec3d> coordinates() const { return m_coordinates(); }
std::vector<double> measuredDepths() const { return m_measuredDepths(); }
private:
QString displayCoordinates() const;
caf::PdmField<std::vector<cvf::Vec3d>> m_coordinates;
caf::PdmField<std::vector<double>> m_measuredDepths;
caf::PdmProxyValueField<QString> m_displayCoordinates;
};

View File

@ -1,149 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// 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 "RimImportedFishboneLateralsCollection.h"
#include "Rim3dView.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLaterals.h"
#include "RimProject.h"
#include "RigWellPath.h"
#include "RifWellPathImporter.h"
#include "Riu3DMainWindowTools.h"
// The more general term WellPathCompletionCollection was unfortunately used in this more specific case of fishbones
// In order to preserve compatibility, the old keyword is kept as an alias, but could be removed in the future.
CAF_PDM_SOURCE_INIT( RimImportedFishboneLateralsCollection, "FishboneWellPathCollection", "WellPathCompletionCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimImportedFishboneLateralsCollection::RimImportedFishboneLateralsCollection()
{
CAF_PDM_InitObject( "WellPathCompletions", ":/FishBoneGroupFromFile16x16.png", "", "" );
nameField()->uiCapability()->setUiHidden( true );
this->setName( "Imported Laterals" );
CAF_PDM_InitFieldNoDefault( &m_wellPaths, "WellPaths", "Imported Laterals", "", "", "" );
m_wellPaths.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_pipeProperties, "PipeProperties", "Pipe Properties", "", "", "" );
m_pipeProperties.uiCapability()->setUiHidden( true );
m_pipeProperties.uiCapability()->setUiTreeHidden( true );
m_pipeProperties.uiCapability()->setUiTreeChildrenHidden( true );
m_pipeProperties = new RimFishbonesPipeProperties;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLateralsCollection::importCompletionsFromFile( const QStringList& filePaths )
{
RifWellPathImporter wellPathImporter;
for ( const QString& filePath : filePaths )
{
size_t wellDataCount = wellPathImporter.wellDataCount( filePath );
for ( size_t i = 0; i < wellDataCount; ++i )
{
RifWellPathImporter::WellData wellData = wellPathImporter.readWellData( filePath, i );
RimImportedFishboneLaterals* wellCompletion = new RimImportedFishboneLaterals();
wellCompletion->setName( wellData.m_name );
wellCompletion->setCoordinates( wellData.m_wellPathGeometry->uniqueWellPathPoints() );
wellCompletion->setMeasuredDepths( wellData.m_wellPathGeometry->uniqueMeasuredDepths() );
appendCompletion( wellCompletion );
}
}
RimFishbonesCollection* fishbonesCollection;
firstAncestorOrThisOfType( fishbonesCollection );
if ( fishbonesCollection != nullptr )
{
fishbonesCollection->recalculateStartMD();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLateralsCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimProject* proj;
this->firstAncestorOrThisOfTypeAsserted( proj );
proj->scheduleCreateDisplayModelAndRedrawAllViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<const RimImportedFishboneLaterals*> RimImportedFishboneLateralsCollection::wellPaths() const
{
std::vector<const RimImportedFishboneLaterals*> paths;
for ( const RimImportedFishboneLaterals* path : m_wellPaths )
{
paths.push_back( path );
}
return paths;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLateralsCollection::setUnitSystemSpecificDefaults()
{
m_pipeProperties->setUnitSystemSpecificDefaults();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLateralsCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* wellPropertiesGroup = uiOrdering.addNewGroup( "Well Properties" );
m_pipeProperties->uiOrdering( uiConfigName, *wellPropertiesGroup );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimImportedFishboneLateralsCollection::appendCompletion( RimImportedFishboneLaterals* completion )
{
m_wellPaths.push_back( completion );
updateConnectedEditors();
Riu3DMainWindowTools::selectAsCurrentItem( completion );
uiCapability()->setUiHidden( !m_wellPaths.empty() );
RimProject* project = nullptr;
firstAncestorOrThisOfTypeAsserted( project );
if ( project )
{
project->reloadCompletionTypeResultsInAllViews();
}
}

View File

@ -1,67 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimCheckableNamedObject.h"
#include "RimFishbonesPipeProperties.h"
#include "RimImportedFishboneLaterals.h"
#include "RiaDefines.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
//==================================================================================================
//
//
//
//==================================================================================================
class RimImportedFishboneLateralsCollection : public RimCheckableNamedObject
{
CAF_PDM_HEADER_INIT;
public:
RimImportedFishboneLateralsCollection();
void importCompletionsFromFile( const QStringList& filePaths );
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
std::vector<const RimImportedFishboneLaterals*> wellPaths() const;
double holeDiameter( RiaDefines::EclipseUnitSystem unitSystem ) const
{
return m_pipeProperties->holeDiameter( unitSystem );
}
double skinFactor() const { return m_pipeProperties->skinFactor(); }
void setUnitSystemSpecificDefaults();
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
private:
void appendCompletion( RimImportedFishboneLaterals* completion );
private:
caf::PdmChildArrayField<RimImportedFishboneLaterals*> m_wellPaths;
caf::PdmChildField<RimFishbonesPipeProperties*> m_pipeProperties;
};

View File

@ -49,7 +49,7 @@ void RimMswCompletionParameters::LengthAndDepthEnum::setUp()
{
addItem( RimMswCompletionParameters::INC, "INC", "Incremental" );
addItem( RimMswCompletionParameters::ABS, "ABS", "Absolute" );
setDefault( RimMswCompletionParameters::INC );
setDefault( RimMswCompletionParameters::ABS );
}
} // namespace caf

View File

@ -309,13 +309,7 @@ void RimWellPathCompletionSettings::defineEditorAttribute( const caf::PdmFieldHa
caf::PdmUiEditorAttribute* attribute )
{
caf::PdmUiLineEditorAttribute* lineEditorAttr = dynamic_cast<caf::PdmUiLineEditorAttribute*>( attribute );
if ( field == &m_wellNameForExport && lineEditorAttr )
{
QRegExpValidator* validator = new QRegExpValidator( nullptr );
validator->setRegExp( wellNameForExportRegExp() );
lineEditorAttr->validator = validator;
}
else if ( field == &m_drainageRadiusForPI && lineEditorAttr )
if ( field == &m_drainageRadiusForPI && lineEditorAttr )
{
caf::PdmDoubleStringValidator* validator = new caf::PdmDoubleStringValidator( "1*" );
lineEditorAttr->validator = validator;

View File

@ -22,7 +22,6 @@
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimPerforationCollection.h"
#include "RimPerforationInterval.h"
#include "RimProject.h"
@ -211,9 +210,7 @@ bool RimWellPathCompletions::hasCompletions() const
return true;
}
return !m_fishbonesCollection->allFishbonesSubs().empty() ||
!m_fishbonesCollection->wellPathCollection()->wellPaths().empty() ||
!m_perforationCollection->perforations().empty();
return !m_fishbonesCollection->allFishbonesSubs().empty() || !m_perforationCollection->perforations().empty();
}
//--------------------------------------------------------------------------------------------------
@ -244,8 +241,7 @@ void RimWellPathCompletions::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTre
uiTreeOrdering.add( &m_perforationCollection );
}
if ( !m_fishbonesCollection->allFishbonesSubs().empty() ||
!m_fishbonesCollection->wellPathCollection()->wellPaths().empty() )
if ( !m_fishbonesCollection->allFishbonesSubs().empty() )
{
uiTreeOrdering.add( &m_fishbonesCollection );
}

View File

@ -304,6 +304,14 @@ std::vector<std::pair<double, double>> RimWellPathValve::valveSegments() const
return segments;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathValve::setComponentTypeFilter( const std::set<RiaDefines::WellPathComponentType>& filter )
{
m_componentTypeFilter = filter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -456,6 +464,11 @@ QList<caf::PdmOptionItemInfo> RimWellPathValve::calculateValueOptions( const caf
std::vector<RimValveTemplate*> allTemplates = project->allValveTemplates();
for ( RimValveTemplate* valveTemplate : allTemplates )
{
if ( !m_componentTypeFilter.empty() )
{
if ( m_componentTypeFilter.count( valveTemplate->type() ) == 0 ) continue;
}
options.push_back( caf::PdmOptionItemInfo( valveTemplate->name(), valveTemplate ) );
}

View File

@ -65,6 +65,8 @@ public:
std::vector<std::pair<double, double>> valveSegments() const;
void setComponentTypeFilter( const std::set<RiaDefines::WellPathComponentType>& filter );
// Overrides from RimWellPathCompletionInterface
bool isEnabled() const override;
RiaDefines::WellPathComponentType componentType() const override;
@ -92,4 +94,6 @@ private:
caf::PdmChildField<RimMultipleValveLocations*> m_multipleValveLocations;
caf::PdmField<bool> m_editValveTemplate;
caf::PdmField<bool> m_createValveTemplate;
std::set<RiaDefines::WellPathComponentType> m_componentTypeFilter;
};

View File

@ -88,7 +88,6 @@
#include "RimGridCrossPlotCollection.h"
#include "RimGridCrossPlotDataSet.h"
#include "RimIdenticalGridCaseGroup.h"
#include "RimImportedFishboneLateralsCollection.h"
#include "RimIntersectionCollection.h"
#include "RimIntersectionResultDefinition.h"
#include "RimIntersectionResultsDefinitionCollection.h"
@ -336,7 +335,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicReloadWellPathFormationNamesFeature";
menuBuilder.addSeparator();
menuBuilder << "RicWellPathImportPerforationIntervalsFeature";
menuBuilder << "RicWellPathImportCompletionsFileFeature";
menuBuilder << "RicImportWellMeasurementsFeature";
menuBuilder.subMenuEnd();
menuBuilder.addSeparator();
@ -392,10 +390,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicShowWellPlanFeature";
}
}
else if ( dynamic_cast<RimImportedFishboneLateralsCollection*>( firstUiItem ) )
{
appendImportMenu( menuBuilder );
}
else if ( dynamic_cast<RimWellPathCompletions*>( firstUiItem ) )
{
menuBuilder.subMenuStart( "Create Completions", QIcon( ":/CompletionsSymbol16x16.png" ) );
@ -418,8 +412,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder.addSeparator();
appendExportCompletions( menuBuilder );
}
else if ( dynamic_cast<RimFishbonesCollection*>( firstUiItem ) || dynamic_cast<RimFishbones*>( firstUiItem ) ||
dynamic_cast<RimImportedFishboneLateralsCollection*>( firstUiItem ) )
else if ( dynamic_cast<RimFishbonesCollection*>( firstUiItem ) || dynamic_cast<RimFishbones*>( firstUiItem ) )
{
menuBuilder << "RicNewFishbonesSubsFeature";
appendExportCompletions( menuBuilder );
@ -1335,8 +1328,6 @@ int RimContextCommandBuilder::appendImportMenu( caf::CmdFeatureMenuBuilder& menu
candidates << "RicWellPathFormationsImportFileFeature";
candidates << "RicWellLogsImportFileFeature";
candidates << "RicReloadWellPathFormationNamesFeature";
candidates << "Separator";
candidates << "RicWellPathImportCompletionsFileFeature";
return appendSubMenuWithCommands( menuBuilder, candidates, "Import", QIcon(), addSeparatorBeforeMenu );
}

View File

@ -18,21 +18,24 @@
#include "RimModeledWellPath.h"
#include "RiaCompletionTypeCalculationScheduler.h"
#include "RicfCommandObject.h"
#include "RimProject.h"
#include "RimWellPathGeometryDef.h"
#include "RifTextDataTableFormatter.h"
#include "RigWellPath.h"
#include "RiaCompletionTypeCalculationScheduler.h"
#include "RifTextDataTableFormatter.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimPlotCurve.h"
#include "RimProject.h"
#include "RimTools.h"
#include "RimWellPath.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPathGeometryDef.h"
#include "RimWellPathTarget.h"
#include "RimWellPathTieIn.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiTreeOrdering.h"
CAF_PDM_SOURCE_INIT( RimModeledWellPath, "ModeledWellPath" );
@ -191,6 +194,7 @@ void RimModeledWellPath::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrd
void RimModeledWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_name );
RimWellPath::defineUiOrdering( uiConfigName, uiOrdering );
}
@ -198,10 +202,95 @@ void RimModeledWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
///
//--------------------------------------------------------------------------------------------------
void RimModeledWellPath::onGeometryDefinitionChanged( const caf::SignalEmitter* emitter, bool fullUpdate )
{
updateGeometry( fullUpdate );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimModeledWellPath::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
// TODO remove if nothing happens here
RimWellPath::fieldChangedByUi( changedField, oldValue, newValue );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimModeledWellPath::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimModeledWellPath::updateGeometry( bool fullUpdate )
{
updateWellPathVisualization();
std::vector<RimWellPathTieIn*> tieInObjects;
objectsWithReferringPtrFieldsOfType( tieInObjects );
for ( auto tieIn : tieInObjects )
{
if ( tieIn->parentWell() == this )
{
tieIn->updateChildWellGeometry();
}
}
if ( fullUpdate )
{
scheduleUpdateOfDependentVisualization();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimModeledWellPath::updateTieInLocationFromParentWell()
{
RimWellPath* parentWellPath = nullptr;
RimWellPathTieIn* tieIn = wellPathTieIn();
if ( tieIn )
{
parentWellPath = tieIn->parentWell();
auto targets = m_geometryDefinition->activeWellTargets();
if ( parentWellPath && !targets.empty() )
{
auto [pointVector, measuredDepths] =
parentWellPath->wellPathGeometry()
->clippedPointSubset( parentWellPath->wellPathGeometry()->measuredDepths().front(),
tieIn->tieInMeasuredDepth() );
if ( pointVector.size() > 2u )
{
auto firstTarget = targets.front();
firstTarget->setPointXYZ( pointVector.back() );
m_geometryDefinition->setIsAttachedToParentWell( true );
m_geometryDefinition->setMdAtFirstTarget( measuredDepths.back() );
m_geometryDefinition->setFixedWellPathPoints( pointVector );
m_geometryDefinition->setFixedMeasuredDepths( measuredDepths );
updateGeometry( true );
}
}
}
if ( !parentWellPath )
{
m_geometryDefinition->setIsAttachedToParentWell( false );
m_geometryDefinition->setFixedWellPathPoints( {} );
m_geometryDefinition->setFixedMeasuredDepths( {} );
}
}

View File

@ -20,6 +20,7 @@
#include "RimWellPath.h"
#include "cafPdmChildField.h"
#include "cafPdmPtrField.h"
class RimWellPathTarget;
class RimWellPath;
@ -38,11 +39,20 @@ public:
void scheduleUpdateOfDependentVisualization();
RimWellPathGeometryDef* geometryDefinition() const;
QString wellPlanText();
void updateTieInLocationFromParentWell();
private:
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void onGeometryDefinitionChanged( const caf::SignalEmitter* emitter, bool fullUpdate );
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void updateGeometry( bool fullUpdate );
private:
caf::PdmChildField<RimWellPathGeometryDef*> m_geometryDefinition;
};

View File

@ -234,19 +234,43 @@ QString RimTools::relocateFile( const QString& originalFileName,
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTools::wellPathOptionItems( QList<caf::PdmOptionItemInfo>* options )
void RimTools::wellPathOptionItemsSubset( const std::vector<RimWellPath*>& wellPathsToExclude,
QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
auto wellPathColl = RimTools::wellPathCollection();
if ( wellPathColl )
{
caf::IconProvider wellIcon( ":/Well.svg" );
for ( auto wellPath : wellPathColl->allWellPaths() )
std::vector<RimWellPath*> wellPathsToInclude;
auto all = wellPathColl->allWellPaths();
for ( auto w : all )
{
options->push_back( caf::PdmOptionItemInfo( wellPath->name(), wellPath, false, wellIcon ) );
bool include = true;
for ( auto exclude : wellPathsToExclude )
{
if ( w == exclude ) include = false;
}
if ( include ) wellPathsToInclude.push_back( w );
}
optionItemsForSpecifiedWellPaths( wellPathsToInclude, options );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTools::wellPathOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
if ( !options ) return;
auto wellPathColl = RimTools::wellPathCollection();
if ( wellPathColl )
{
optionItemsForSpecifiedWellPaths( wellPathColl->allWellPaths(), options );
}
}
@ -255,17 +279,12 @@ void RimTools::wellPathOptionItems( QList<caf::PdmOptionItemInfo>* options )
//--------------------------------------------------------------------------------------------------
void RimTools::wellPathWithFormationsOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
std::vector<RimWellPath*> wellPaths;
RimTools::wellPathWithFormations( &wellPaths );
caf::IconProvider wellIcon( ":/Well.svg" );
for ( auto wellPath : wellPaths )
{
options->push_back( caf::PdmOptionItemInfo( wellPath->name(), wellPath, false, wellIcon ) );
}
optionItemsForSpecifiedWellPaths( wellPaths, options );
}
//--------------------------------------------------------------------------------------------------
@ -291,7 +310,6 @@ void RimTools::wellPathWithFormations( std::vector<RimWellPath*>* wellPaths )
//--------------------------------------------------------------------------------------------------
void RimTools::caseOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
RimProject* proj = RimProject::current();
@ -312,7 +330,6 @@ void RimTools::caseOptionItems( QList<caf::PdmOptionItemInfo>* options )
//--------------------------------------------------------------------------------------------------
void RimTools::eclipseCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
RimProject* proj = RimProject::current();
@ -337,7 +354,6 @@ void RimTools::eclipseCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
//--------------------------------------------------------------------------------------------------
void RimTools::geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
RimProject* proj = RimProject::current();
@ -362,7 +378,6 @@ void RimTools::geoMechCaseOptionItems( QList<caf::PdmOptionItemInfo>* options )
//--------------------------------------------------------------------------------------------------
void RimTools::colorLegendOptionItems( QList<caf::PdmOptionItemInfo>* options )
{
CVF_ASSERT( options );
if ( !options ) return;
RimProject* project = RimProject::current();
@ -407,3 +422,18 @@ void RimTools::timeStepsForCase( RimCase* gridCase, QList<caf::PdmOptionItemInfo
options->push_back( caf::PdmOptionItemInfo( timeStepNames[i], i ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimTools::optionItemsForSpecifiedWellPaths( const std::vector<RimWellPath*>& wellPaths,
QList<caf::PdmOptionItemInfo>* options )
{
if ( !options ) return;
caf::IconProvider wellIcon( ":/Well.svg" );
for ( auto wellPath : wellPaths )
{
options->push_back( caf::PdmOptionItemInfo( wellPath->name(), wellPath, false, wellIcon ) );
}
}

View File

@ -51,6 +51,8 @@ public:
bool* foundFile,
std::vector<QString>* searchedPaths );
static void wellPathOptionItemsSubset( const std::vector<RimWellPath*>& wellPathsToExclude,
QList<caf::PdmOptionItemInfo>* options );
static void wellPathOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void wellPathWithFormationsOptionItems( QList<caf::PdmOptionItemInfo>* options );
static void wellPathWithFormations( std::vector<RimWellPath*>* wellPaths );
@ -61,4 +63,8 @@ public:
static RimWellPathCollection* wellPathCollection();
static void timeStepsForCase( RimCase* gridCase, QList<caf::PdmOptionItemInfo>* options );
private:
static void optionItemsForSpecifiedWellPaths( const std::vector<RimWellPath*>& wellPaths,
QList<caf::PdmOptionItemInfo>* options );
};

View File

@ -50,6 +50,7 @@
#include "RimWellPathCompletions.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPathTieIn.h"
#include "RiuMainWindow.h"
@ -131,6 +132,8 @@ RimWellPath::RimWellPath()
m_wellPathAttributes = new RimWellPathAttributeCollection;
m_wellPathAttributes->uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_wellPathTieIn, "WellPathTieIn", "well Path Tie-In", "", "", "" );
this->setDeletable( true );
}
@ -285,7 +288,9 @@ const RimWellPathCompletions* RimWellPath::completions() const
//--------------------------------------------------------------------------------------------------
const RimWellPathCompletionSettings* RimWellPath::completionSettings() const
{
return m_completionSettings();
if ( isTopLevelWellPath() ) return m_completionSettings();
return topLevelWellPath()->completionSettings();
}
//--------------------------------------------------------------------------------------------------
@ -293,7 +298,9 @@ const RimWellPathCompletionSettings* RimWellPath::completionSettings() const
//--------------------------------------------------------------------------------------------------
RimWellPathCompletionSettings* RimWellPath::completionSettings()
{
return m_completionSettings();
if ( isTopLevelWellPath() ) return m_completionSettings();
return topLevelWellPath()->completionSettings();
}
//--------------------------------------------------------------------------------------------------
@ -612,6 +619,11 @@ void RimWellPath::setWellPathGeometry( RigWellPath* wellPathModel )
//--------------------------------------------------------------------------------------------------
void RimWellPath::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
if ( m_wellPathTieIn() )
{
m_wellPathTieIn->uiOrdering( uiConfigName, uiOrdering );
}
if ( m_simWellName().isEmpty() )
{
// Try to set default simulation well name
@ -961,12 +973,18 @@ std::vector<const RimWellPathComponentInterface*> RimWellPath::allCompletionsRec
{
std::vector<const RimWellPathComponentInterface*> allCompletions;
std::vector<const RimWellPathCompletions*> completionCollections;
this->descendantsOfType( completionCollections );
for ( auto collection : completionCollections )
auto tieInWells = wellPathLateralsRecursively();
tieInWells.push_back( const_cast<RimWellPath*>( this ) );
for ( auto w : tieInWells )
{
std::vector<const RimWellPathComponentInterface*> completions = collection->allCompletions();
allCompletions.insert( allCompletions.end(), completions.begin(), completions.end() );
std::vector<const RimWellPathCompletions*> completionCollections;
w->descendantsOfType( completionCollections );
for ( auto collection : completionCollections )
{
std::vector<const RimWellPathComponentInterface*> completions = collection->allCompletions();
allCompletions.insert( allCompletions.end(), completions.begin(), completions.end() );
}
}
return allCompletions;
@ -1048,12 +1066,27 @@ bool RimWellPath::isMultiLateralWellPath() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellPath::topLevelWellPath() const
RimWellPath* RimWellPath::topLevelWellPath()
{
std::vector<RimWellPath*> wellPathHierarchy;
this->allAncestorsOrThisOfType( wellPathHierarchy );
RimWellPath* wellPath = wellPathHierarchy.back();
return wellPath;
if ( m_wellPathTieIn() && m_wellPathTieIn->parentWell() )
{
return m_wellPathTieIn()->parentWell()->topLevelWellPath();
}
return this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimWellPath* RimWellPath::topLevelWellPath() const
{
if ( m_wellPathTieIn() && m_wellPathTieIn->parentWell() )
{
return m_wellPathTieIn()->parentWell()->topLevelWellPath();
}
return this;
}
//--------------------------------------------------------------------------------------------------
@ -1062,3 +1095,46 @@ RimWellPath* RimWellPath::topLevelWellPath() const
void RimWellPath::updateAfterAddingToWellPathGroup()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellPath*> RimWellPath::wellPathLateralsRecursively() const
{
std::vector<RimWellPath*> tieInWells;
auto wellPathColl = RimTools::wellPathCollection();
if ( wellPathColl )
{
wellPathColl->allWellPaths();
for ( auto w : wellPathColl->allWellPaths() )
{
if ( w->topLevelWellPath() == this )
{
tieInWells.push_back( w );
}
}
}
return tieInWells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathTieIn* RimWellPath::wellPathTieIn() const
{
return m_wellPathTieIn();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPath::connectWellPaths( RimWellPath* parentWell, double parentTieInMeasuredDepth )
{
if ( !m_wellPathTieIn() ) m_wellPathTieIn = new RimWellPathTieIn;
m_wellPathTieIn->connectWellPaths( parentWell, this, parentTieInMeasuredDepth );
m_wellPathTieIn->updateFirstTargetFromParentWell();
}

View File

@ -54,10 +54,10 @@ class RimPerforationCollection;
class RimWellPathAttributeCollection;
class RimWellPathCompletions;
class RimWellPathCompletionSettings;
class RimWellPathFractureCollection;
class Rim3dWellLogCurve;
class Rim3dWellLogCurveCollection;
class RimWellPathTieIn;
//==================================================================================================
///
@ -154,10 +154,15 @@ public:
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
bool isTopLevelWellPath() const;
bool isMultiLateralWellPath() const;
RimWellPath* topLevelWellPath() const;
void updateAfterAddingToWellPathGroup();
bool isTopLevelWellPath() const;
bool isMultiLateralWellPath() const;
RimWellPath* topLevelWellPath();
const RimWellPath* topLevelWellPath() const;
void updateAfterAddingToWellPathGroup();
std::vector<RimWellPath*> wellPathLateralsRecursively() const;
RimWellPathTieIn* wellPathTieIn() const;
void connectWellPaths( RimWellPath* childWell, double tieInMeasuredDepth );
protected:
// Override PdmObject
@ -201,6 +206,8 @@ private:
caf::PdmChildField<RimWellPathCompletions*> m_completions;
caf::PdmChildField<RimWellPathAttributeCollection*> m_wellPathAttributes;
caf::PdmChildField<RimWellPathTieIn*> m_wellPathTieIn;
private:
static size_t simulationWellBranchCount( const QString& simWellName );

View File

@ -74,7 +74,10 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
CAF_PDM_InitScriptableField( &m_airGap, "AirGap", 0.0, "Air Gap", "", "", "" );
m_airGap.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitScriptableField( &m_mdAtFirstTarget, "MdAtFirstTarget", 0.0, "MD at First Target", "", "", "" );
m_mdAtFirstTarget.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitScriptableFieldNoDefault( &m_wellTargets, "WellPathTargets", "Well Targets", "", "", "" );
m_wellTargets.uiCapability()->setUiEditorTypeName( caf::PdmUiTableViewEditor::uiEditorTypeName() );
m_wellTargets.uiCapability()->setUiTreeChildrenHidden( true );
@ -93,11 +96,16 @@ RimWellPathGeometryDef::RimWellPathGeometryDef()
m_autoTargetAtSeaLevel = new RimWellPathTarget;
m_autoTargetAtSeaLevel->setEnabled( false );
CAF_PDM_InitScriptableField( &m_isAttachedToParentWell, "AttachedToParentWell", false, "Attached to Parent Well", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_fixedWellPathPoints, "FixedWellPathPoints", "", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_fixedMeasuredDepths, "FixedMeasuredDepths", "", "", "", "" );
CAF_PDM_InitField( &m_pickPointsEnabled, "m_pickPointsEnabled", false, "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_pickPointsEnabled );
CAF_PDM_InitScriptableField( &m_showSpheres, "ShowSpheres", false, "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", "", "", "" );
}
//--------------------------------------------------------------------------------------------------
@ -159,6 +167,14 @@ void RimWellPathGeometryDef::setMdAtFirstTarget( double md )
m_mdAtFirstTarget = md;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathGeometryDef::setIsAttachedToParentWell( bool isAttached )
{
m_isAttachedToParentWell = isAttached;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -244,6 +260,30 @@ std::vector<RiaWellPlanCalculator::WellPlanSegment> RimWellPathGeometryDef::well
return wpCalc.wellPlan();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellPathGeometryDef::showSpheres() const
{
return m_showSpheres();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimWellPathGeometryDef::sphereColor() const
{
return m_sphereColor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellPathGeometryDef::sphereRadiusFactor() const
{
return m_sphereRadiusFactor();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -406,10 +446,19 @@ void RimWellPathGeometryDef::fieldChangedByUi( const caf::PdmFieldHandle* change
//--------------------------------------------------------------------------------------------------
void RimWellPathGeometryDef::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_referencePointUtmXyd );
uiOrdering.add( &m_airGap );
uiOrdering.add( &m_mdAtFirstTarget );
uiOrdering.add( &m_useAutoGeneratedTargetAtSeaLevel );
if ( !m_isAttachedToParentWell )
{
uiOrdering.add( &m_referencePointUtmXyd );
uiOrdering.add( &m_airGap );
uiOrdering.add( &m_mdAtFirstTarget );
uiOrdering.add( &m_useAutoGeneratedTargetAtSeaLevel );
}
auto group = uiOrdering.addNewGroup( "Well Target Appearance" );
group->add( &m_showSpheres );
group->add( &m_sphereColor );
group->add( &m_sphereRadiusFactor );
uiOrdering.add( &m_wellTargets );
uiOrdering.add( &m_pickPointsEnabled );

View File

@ -28,6 +28,7 @@
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
#include "cvfColor3.h"
#include "cvfObject.h"
class RimWellPath;
@ -55,6 +56,7 @@ public:
double mdAtFirstTarget() const;
void setMdAtFirstTarget( double mdrkb );
void setIsAttachedToParentWell( bool isAttached );
void setFixedWellPathPoints( const std::vector<cvf::Vec3d>& points );
void setFixedMeasuredDepths( const std::vector<double>& mds );
@ -80,6 +82,11 @@ public:
std::vector<RiaWellPlanCalculator::WellPlanSegment> wellPlan() const;
// Well target appearance
bool showSpheres() const;
cvf::Color3f sphereColor() const;
double sphereRadiusFactor() const;
protected:
void defineCustomContextMenu( const caf::PdmFieldHandle* fieldNeedingMenu, QMenu* menu, QWidget* fieldEditorWidget ) override;
@ -116,5 +123,11 @@ private:
caf::PdmField<std::vector<cvf::Vec3d>> m_fixedWellPathPoints;
caf::PdmField<std::vector<double>> m_fixedMeasuredDepths;
caf::PdmField<bool> m_isAttachedToParentWell;
caf::PdmField<bool> m_showSpheres;
caf::PdmField<cvf::Color3f> m_sphereColor;
caf::PdmField<double> m_sphereRadiusFactor;
std::shared_ptr<RicCreateWellTargetsPickEventHandler> m_pickTargetsEventHandler;
};

View File

@ -96,6 +96,14 @@ bool RimWellPathTarget::isEnabled() const
return m_isEnabled;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTarget::setPointXYZ( const cvf::Vec3d& point )
{
m_targetPoint = { point.x(), point.y(), -point.z() };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -42,8 +42,9 @@ public:
void setEnabled( bool enable );
bool isEnabled() const;
void setPointXYZ( const cvf::Vec3d& point );
void setAsPointTargetXYD( const cvf::Vec3d& point );
void setAsPointTargetXYZ( const cvf::Vec3d& point);
void setAsPointTargetXYZ( const cvf::Vec3d& point );
void setAsPointXYZAndTangentTarget( const cvf::Vec3d& point, const cvf::Vec3d& tangent );
void setAsPointXYZAndTangentTarget( const cvf::Vec3d& point, double azimuth, double inclination );
void setDerivedTangent( double azimuth, double inclination );

View File

@ -0,0 +1,205 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- 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 "RimWellPathTieIn.h"
#include "RigWellPath.h"
#include "RimModeledWellPath.h"
#include "RimTools.h"
#include "RimWellPathCollection.h"
#include "RimWellPathGeometryDef.h"
#include "RimWellPathTarget.h"
#include "RimWellPathValve.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleValueEditor.h"
CAF_PDM_SOURCE_INIT( RimWellPathTieIn, "RimWellPathTieIn" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathTieIn::RimWellPathTieIn()
{
CAF_PDM_InitObject( "Well Path Tie In", ":/NotDefined.png", "", "Well Path Tie In description" );
CAF_PDM_InitFieldNoDefault( &m_parentWell, "ParentWellPath", "ParentWellPath", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_childWell, "ChildWellPath", "ChildWellPath", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_tieInMeasuredDepth, "TieInMeasuredDepth", "TieInMeasuredDepth", "", "", "" );
m_tieInMeasuredDepth.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitScriptableField( &m_addValveAtConnection,
"AddValveAtConnection",
false,
"Add Outlet Valve for Branches",
"",
"",
"" );
CAF_PDM_InitScriptableFieldNoDefault( &m_valve, "Valve", "Branch Outlet Valve", "", "", "" );
m_valve = new RimWellPathValve;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::connectWellPaths( RimWellPath* parentWell, RimWellPath* childWell, double tieInMeasuredDepth )
{
m_parentWell = parentWell;
m_childWell = childWell;
m_tieInMeasuredDepth = tieInMeasuredDepth;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellPathTieIn::parentWell() const
{
return m_parentWell();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellPathTieIn::tieInMeasuredDepth() const
{
return m_tieInMeasuredDepth();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellPathTieIn::childWell() const
{
return m_childWell();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::updateChildWellGeometry()
{
auto modeledWellPath = dynamic_cast<RimModeledWellPath*>( m_childWell() );
if ( modeledWellPath )
{
modeledWellPath->updateTieInLocationFromParentWell();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::updateFirstTargetFromParentWell()
{
auto parentWellPath = m_parentWell();
if ( !parentWellPath ) return;
auto modeledWellPath = dynamic_cast<RimModeledWellPath*>( m_childWell() );
if ( modeledWellPath && modeledWellPath->geometryDefinition() )
{
auto [pointVector, measuredDepths] =
parentWellPath->wellPathGeometry()
->clippedPointSubset( parentWellPath->wellPathGeometry()->measuredDepths().front(), m_tieInMeasuredDepth );
if ( pointVector.size() < 2u ) return;
RimWellPathTarget* newTarget = nullptr;
if ( modeledWellPath->geometryDefinition()->activeWellTargets().empty() )
{
newTarget = modeledWellPath->geometryDefinition()->appendTarget();
}
else
{
newTarget = modeledWellPath->geometryDefinition()->activeWellTargets().front();
}
auto lastPoint = pointVector.back();
auto tangent = lastPoint - pointVector[pointVector.size() - 2];
newTarget->setAsPointXYZAndTangentTarget( { lastPoint[0], lastPoint[1], lastPoint[2] }, tangent );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimWellPathValve* RimWellPathTieIn::outletValve() const
{
return m_addValveAtConnection() && m_valve() && m_valve->valveTemplate() ? m_valve() : nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
auto tieInGroup = uiOrdering.addNewGroup( "Tie In Settings" );
tieInGroup->add( &m_parentWell );
tieInGroup->add( &m_tieInMeasuredDepth );
tieInGroup->add( &m_addValveAtConnection );
// Display only ICV valves
m_valve->setComponentTypeFilter( { RiaDefines::WellPathComponentType::ICV } );
if ( m_addValveAtConnection )
{
m_valve->uiOrdering( "TemplateOnly", *tieInGroup );
}
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTieIn::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_parentWell )
{
updateFirstTargetFromParentWell();
}
updateChildWellGeometry();
// Update all well paths to make sure the visibility of completion settings is updated
// Completions settings is only visible for top-level wells, not for tie-in wells
RimTools::wellPathCollection()->updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellPathTieIn::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_parentWell )
{
std::vector<RimWellPath*> wellPathsToExclude = { m_childWell() };
RimTools::wellPathOptionItemsSubset( wellPathsToExclude, &options );
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
return options;
}

View File

@ -0,0 +1,62 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018- 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPtrField.h"
class RimWellPath;
class RimWellPathValve;
class RimWellPathTieIn : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathTieIn();
void connectWellPaths( RimWellPath* parentWell, RimWellPath* childWell, double tieInMeasuredDepth );
RimWellPath* parentWell() const;
double tieInMeasuredDepth() const;
RimWellPath* childWell() const;
void updateChildWellGeometry();
void updateFirstTargetFromParentWell();
const RimWellPathValve* outletValve() const;
private:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
private:
caf::PdmPtrField<RimWellPath*> m_parentWell;
caf::PdmPtrField<RimWellPath*> m_childWell;
caf::PdmField<double> m_tieInMeasuredDepth;
caf::PdmField<bool> m_addValveAtConnection;
caf::PdmChildField<RimWellPathValve*> m_valve;
};

View File

@ -159,6 +159,8 @@ std::vector<WellPathCellIntersectionInfo> RigWellPathIntersectionTools::buildCon
{
std::vector<WellPathCellIntersectionInfo> intersectionsNoGap;
if ( originalIntersections.empty() ) return intersectionsNoGap;
for ( size_t i = 0; i < originalIntersections.size() - 1; i++ )
{
const WellPathCellIntersectionInfo& current = originalIntersections[i];

View File

@ -531,7 +531,6 @@ void RiuViewerCommands::displayContextMenu( QMouseEvent* event )
menuBuilder << "RicNewWellPathStimPlanModelAtPosFeature";
menuBuilder.addSeparator();
menuBuilder << "RicNewWellPathAttributeFeature";
menuBuilder << "RicWellPathImportCompletionsFileFeature";
menuBuilder.subMenuEnd();

View File

@ -10,7 +10,7 @@ set(RESINSIGHT_VERSION_TEXT "-dev")
# Must be unique and increasing within one combination of major/minor/patch version
# The uniqueness of this text is independent of RESINSIGHT_VERSION_TEXT
# Format of text must be ".xx"
set(RESINSIGHT_DEV_VERSION ".02")
set(RESINSIGHT_DEV_VERSION ".11")
# https://github.com/CRAVA/crava/tree/master/libs/nrlib
set(NRLIB_GITHUB_SHA "ba35d4359882f1c6f5e9dc30eb95fe52af50fd6f")