2017-05-15 09:04:11 -05:00
/////////////////////////////////////////////////////////////////////////////////
//
2017-05-16 07:50:54 -05:00
// Copyright (C) 2017 Statoil ASA
2017-05-15 09:04:11 -05:00
//
// 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 "RicWellPathExportCompletionDataFeature.h"
# include "RiaApplication.h"
# include "RiaLogging.h"
2017-06-28 03:13:59 -05:00
# include "RicExportCompletionDataSettingsUi.h"
# include "RicExportFeatureImpl.h"
# include "RicFishbonesTransmissibilityCalculationFeatureImp.h"
2017-08-01 05:44:11 -05:00
# include "RicExportFractureCompletionsImpl.h"
2017-06-28 03:13:59 -05:00
# include "RigActiveCellInfo.h"
2017-09-13 03:39:20 -05:00
# include "RigCaseCellResultsData.h"
2017-06-28 03:13:59 -05:00
# include "RigEclipseCaseData.h"
# include "RigMainGrid.h"
# include "RigResultAccessorFactory.h"
2017-08-21 08:24:20 -05:00
2017-06-28 03:13:59 -05:00
# include "RigTransmissibilityEquations.h"
2017-08-21 08:24:20 -05:00
2017-06-28 03:13:59 -05:00
# include "RigWellLogExtractionTools.h"
# include "RigWellPath.h"
# include "RigWellPathIntersectionTools.h"
2017-05-30 02:26:45 -05:00
# include "RimFishboneWellPath.h"
# include "RimFishboneWellPathCollection.h"
2017-06-28 03:13:59 -05:00
# include "RimFishbonesCollection.h"
# include "RimFishbonesMultipleSubs.h"
2017-05-29 06:13:25 -05:00
# include "RimPerforationCollection.h"
2017-06-28 03:13:59 -05:00
# include "RimPerforationInterval.h"
# include "RimProject.h"
2017-06-12 05:03:42 -05:00
# include "RimEclipseWell.h"
# include "RimEclipseWellCollection.h"
2017-06-28 03:13:59 -05:00
# include "RimWellPath.h"
# include "RimWellPathCollection.h"
2017-06-14 06:43:56 -05:00
# include "RimWellPathCompletions.h"
2017-06-07 09:04:34 -05:00
2017-05-15 09:04:11 -05:00
# include "RiuMainWindow.h"
# include "cafPdmUiPropertyViewDialog.h"
2017-06-28 03:13:59 -05:00
# include "cafSelectionManager.h"
2017-05-15 09:04:11 -05:00
2017-05-19 04:28:02 -05:00
# include "cvfPlane.h"
2017-05-15 09:04:11 -05:00
# include <QAction>
2017-07-03 08:02:24 -05:00
# include <QDir>
2017-05-15 09:04:11 -05:00
# include <QFileDialog>
# include <QMessageBox>
2017-05-16 07:50:54 -05:00
CAF_CMD_SOURCE_INIT ( RicWellPathExportCompletionDataFeature , " RicWellPathExportCompletionDataFeature " ) ;
2017-05-15 09:04:11 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeature : : isCommandEnabled ( )
{
2017-06-12 05:03:42 -05:00
std : : vector < RimWellPath * > wellPaths = selectedWellPaths ( ) ;
std : : vector < RimEclipseWell * > simWells = selectedSimWells ( ) ;
if ( wellPaths . empty ( ) & & simWells . empty ( ) )
{
return false ;
}
if ( ! wellPaths . empty ( ) & & ! simWells . empty ( ) )
{
return false ;
}
std : : set < RimEclipseCase * > eclipseCases ;
for ( auto simWell : simWells )
{
RimEclipseCase * eclipseCase ;
simWell - > firstAncestorOrThisOfType ( eclipseCase ) ;
eclipseCases . insert ( eclipseCase ) ;
}
if ( eclipseCases . size ( ) > 1 )
{
return false ;
}
return true ;
2017-05-15 09:04:11 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature : : onActionTriggered ( bool isChecked )
{
2017-05-29 08:52:35 -05:00
std : : vector < RimWellPath * > wellPaths = selectedWellPaths ( ) ;
2017-06-12 05:03:42 -05:00
std : : vector < RimEclipseWell * > simWells = selectedSimWells ( ) ;
2017-05-15 09:04:11 -05:00
2017-06-12 05:03:42 -05:00
CVF_ASSERT ( wellPaths . size ( ) > 0 | | simWells . size ( ) > 0 ) ;
2017-05-15 09:04:11 -05:00
RiaApplication * app = RiaApplication : : instance ( ) ;
QString projectFolder = app - > currentProjectPath ( ) ;
QString defaultDir = RiaApplication : : instance ( ) - > lastUsedDialogDirectoryWithFallback ( " COMPLETIONS " , projectFolder ) ;
2017-06-23 06:21:47 -05:00
bool onlyWellPathCollectionSelected = noWellPathsSelectedDirectly ( ) ;
RicExportCompletionDataSettingsUi exportSettings ( onlyWellPathCollectionSelected ) ;
2017-06-12 05:03:42 -05:00
if ( wellPaths . empty ( ) )
{
exportSettings . showForSimWells ( ) ;
}
else
{
exportSettings . showForWellPath ( ) ;
}
2017-05-19 04:09:36 -05:00
std : : vector < RimCase * > cases ;
app - > project ( ) - > allCases ( cases ) ;
for ( auto c : cases )
{
RimEclipseCase * eclipseCase = dynamic_cast < RimEclipseCase * > ( c ) ;
if ( eclipseCase ! = nullptr )
{
exportSettings . caseToApply = eclipseCase ;
break ;
}
}
2017-05-15 09:04:11 -05:00
2017-06-15 04:21:37 -05:00
exportSettings . folder = defaultDir ;
2017-05-15 09:04:11 -05:00
caf : : PdmUiPropertyViewDialog propertyDialog ( RiuMainWindow : : instance ( ) , & exportSettings , " Export Completion Data " , " " ) ;
2017-06-28 03:13:59 -05:00
RicExportFeatureImpl : : configureForExport ( & propertyDialog ) ;
2017-05-15 09:04:11 -05:00
if ( propertyDialog . exec ( ) = = QDialog : : Accepted )
{
2017-06-22 06:39:30 -05:00
RiaApplication : : instance ( ) - > setLastUsedDialogDirectory ( " COMPLETIONS " , exportSettings . folder ) ;
2017-05-15 09:04:11 -05:00
2017-06-12 05:03:42 -05:00
exportCompletions ( wellPaths , simWells , exportSettings ) ;
2017-05-15 09:04:11 -05:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature : : setupActionLook ( QAction * actionToSetup )
{
actionToSetup - > setText ( " Export Completion Data " ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-05-29 08:52:35 -05:00
std : : vector < RimWellPath * > RicWellPathExportCompletionDataFeature : : selectedWellPaths ( )
{
std : : vector < RimWellPath * > wellPaths ;
caf : : SelectionManager : : instance ( ) - > objectsByType ( & wellPaths ) ;
2017-06-22 07:34:49 -05:00
if ( wellPaths . empty ( ) )
2017-05-29 08:52:35 -05:00
{
2017-06-22 07:34:49 -05:00
std : : vector < RimWellPathCollection * > wellPathCollections ;
caf : : SelectionManager : : instance ( ) - > objectsByType ( & wellPathCollections ) ;
for ( auto wellPathCollection : wellPathCollections )
2017-05-29 08:52:35 -05:00
{
2017-06-22 07:34:49 -05:00
for ( auto wellPath : wellPathCollection - > wellPaths ( ) )
{
wellPaths . push_back ( wellPath ) ;
}
2017-05-29 08:52:35 -05:00
}
}
std : : set < RimWellPath * > uniqueWellPaths ( wellPaths . begin ( ) , wellPaths . end ( ) ) ;
wellPaths . assign ( uniqueWellPaths . begin ( ) , uniqueWellPaths . end ( ) ) ;
return wellPaths ;
}
2017-06-22 06:39:30 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeature : : noWellPathsSelectedDirectly ( )
{
std : : vector < RimWellPath * > wellPaths ;
caf : : SelectionManager : : instance ( ) - > objectsByType ( & wellPaths ) ;
if ( wellPaths . empty ( ) ) return true ;
else return false ;
}
2017-05-29 08:52:35 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-12 05:03:42 -05:00
std : : vector < RimEclipseWell * > RicWellPathExportCompletionDataFeature : : selectedSimWells ( )
{
std : : vector < RimEclipseWell * > simWells ;
caf : : SelectionManager : : instance ( ) - > objectsByType ( & simWells ) ;
std : : vector < RimEclipseWellCollection * > simWellCollections ;
caf : : SelectionManager : : instance ( ) - > objectsByType ( & simWellCollections ) ;
for ( auto simWellCollection : simWellCollections )
{
for ( auto simWell : simWellCollection - > wells ( ) )
{
simWells . push_back ( simWell ) ;
}
}
std : : set < RimEclipseWell * > uniqueSimWells ( simWells . begin ( ) , simWells . end ( ) ) ;
simWells . assign ( uniqueSimWells . begin ( ) , uniqueSimWells . end ( ) ) ;
return simWells ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-20 06:26:52 -05:00
void RicWellPathExportCompletionDataFeature : : exportCompletions ( const std : : vector < RimWellPath * > & wellPaths ,
const std : : vector < RimEclipseWell * > & simWells ,
2017-06-20 01:26:53 -05:00
const RicExportCompletionDataSettingsUi & exportSettings )
2017-05-15 09:04:11 -05:00
{
2017-05-16 02:43:41 -05:00
2017-05-19 09:45:07 -05:00
if ( exportSettings . caseToApply ( ) = = nullptr )
2017-05-16 02:43:41 -05:00
{
RiaLogging : : error ( " Export Completions Data: Cannot export completions data without specified eclipse case " ) ;
return ;
}
2017-05-16 08:17:19 -05:00
2017-06-15 04:37:00 -05:00
std : : vector < RimWellPath * > usedWellPaths ;
2017-06-22 06:39:30 -05:00
if ( exportSettings . wellSelection = = RicExportCompletionDataSettingsUi : : ALL_WELLS
| | exportSettings . wellSelection = = RicExportCompletionDataSettingsUi : : SELECTED_WELLS )
2017-05-15 09:04:11 -05:00
{
2017-06-15 04:37:00 -05:00
usedWellPaths = wellPaths ;
2017-05-15 09:04:11 -05:00
}
2017-06-15 04:37:00 -05:00
else if ( exportSettings . wellSelection = = RicExportCompletionDataSettingsUi : : CHECKED_WELLS )
2017-06-08 05:59:12 -05:00
{
2017-06-15 04:37:00 -05:00
for ( auto wellPath : wellPaths )
2017-06-08 05:59:12 -05:00
{
2017-06-15 04:37:00 -05:00
if ( wellPath - > showWellPath )
2017-06-08 05:59:12 -05:00
{
2017-06-15 04:37:00 -05:00
usedWellPaths . push_back ( wellPath ) ;
2017-06-08 05:59:12 -05:00
}
2017-06-15 04:37:00 -05:00
}
}
2017-06-08 05:59:12 -05:00
{
bool unitSystemMismatch = false ;
2017-06-15 04:37:00 -05:00
for ( const RimWellPath * wellPath : usedWellPaths )
2017-06-08 05:59:12 -05:00
{
2017-06-20 03:40:39 -05:00
if ( wellPath - > unitSystem ( ) ! = exportSettings . caseToApply - > eclipseCaseData ( ) - > unitsType ( ) )
2017-06-08 05:59:12 -05:00
{
unitSystemMismatch = true ;
break ;
}
}
2017-06-12 05:03:42 -05:00
for ( const RimEclipseWell * simWell : simWells )
{
RimEclipseCase * eclipseCase ;
simWell - > firstAncestorOrThisOfType ( eclipseCase ) ;
if ( exportSettings . caseToApply - > eclipseCaseData ( ) - > unitsType ( ) ! = eclipseCase - > eclipseCaseData ( ) - > unitsType ( ) )
{
unitSystemMismatch = true ;
break ;
}
}
2017-06-08 05:59:12 -05:00
if ( unitSystemMismatch )
{
RiaLogging : : error ( " Well path unit systems must match unit system of chosen eclipse case. " ) ;
return ;
}
}
2017-06-20 01:26:53 -05:00
std : : map < IJKCellIndex , std : : vector < RigCompletionData > > completionsPerEclipseCell ;
2017-06-20 06:26:52 -05:00
// FractureTransmissibilityExportInformation
2017-06-08 05:59:12 -05:00
2017-06-20 06:26:52 -05:00
QString fractureTransmisibillityExportInformationPath = QDir ( exportSettings . folder ) . filePath ( " FractureTransmissibilityExportInformation " ) ;
QFile fractureTransmissibilityExportInformationFile ( fractureTransmisibillityExportInformationPath ) ;
if ( ! fractureTransmissibilityExportInformationFile . open ( QIODevice : : WriteOnly ) )
{
RiaLogging : : error ( QString ( " Export Completions Data: Could not open the file: %1 " ) . arg ( fractureTransmisibillityExportInformationPath ) ) ;
return ;
}
QTextStream fractureTransmissibilityExportInformationStream ( & fractureTransmissibilityExportInformationFile ) ;
2017-06-01 10:21:46 -05:00
2017-06-15 04:37:00 -05:00
for ( auto wellPath : usedWellPaths )
2017-05-29 06:13:25 -05:00
{
2017-05-29 08:52:35 -05:00
// Generate completion data
2017-05-19 09:45:07 -05:00
2017-05-29 08:52:35 -05:00
if ( exportSettings . includePerforations )
{
std : : vector < RigCompletionData > perforationCompletionData = generatePerforationsCompdatValues ( wellPath , exportSettings ) ;
2017-06-20 01:26:53 -05:00
appendCompletionData ( & completionsPerEclipseCell , perforationCompletionData ) ;
2017-05-29 08:52:35 -05:00
}
if ( exportSettings . includeFishbones )
{
2017-06-14 07:58:39 -05:00
std : : vector < RigCompletionData > fishbonesCompletionData = RicFishbonesTransmissibilityCalculationFeatureImp : : generateFishboneCompdatValuesUsingAdjustedCellVolume ( wellPath , exportSettings ) ;
2017-06-20 01:26:53 -05:00
appendCompletionData ( & completionsPerEclipseCell , fishbonesCompletionData ) ;
2017-05-29 08:52:35 -05:00
}
2017-05-19 09:45:07 -05:00
2017-08-21 08:24:20 -05:00
# ifdef USE_PROTOTYPE_FEATURE_FRACTURES
2017-06-01 09:34:30 -05:00
if ( exportSettings . includeFractures ( ) )
{
2017-06-20 06:26:52 -05:00
std : : vector < RigCompletionData > fractureCompletionData = RicExportFractureCompletionsImpl : : generateCompdatValuesForWellPath ( wellPath , exportSettings , & fractureTransmissibilityExportInformationStream ) ;
appendCompletionData ( & completionsPerEclipseCell , fractureCompletionData ) ;
2017-06-01 09:34:30 -05:00
}
2017-08-21 08:24:20 -05:00
# endif // USE_PROTOTYPE_FEATURE_FRACTURES
2017-06-01 09:34:30 -05:00
2017-06-01 10:21:46 -05:00
}
2017-05-29 08:52:35 -05:00
2017-08-21 08:24:20 -05:00
# ifdef USE_PROTOTYPE_FEATURE_FRACTURES
2017-06-12 05:03:42 -05:00
for ( auto simWell : simWells )
{
2017-07-31 08:10:07 -05:00
std : : vector < RigCompletionData > fractureCompletionData = RicExportFractureCompletionsImpl : : generateCompdatValuesForSimWell ( exportSettings . caseToApply ( ) ,
simWell ,
& fractureTransmissibilityExportInformationStream ) ;
2017-06-20 06:26:52 -05:00
appendCompletionData ( & completionsPerEclipseCell , fractureCompletionData ) ;
2017-06-12 05:03:42 -05:00
}
2017-08-21 08:24:20 -05:00
# endif // USE_PROTOTYPE_FEATURE_FRACTURES
2017-06-12 05:03:42 -05:00
2017-06-15 04:21:37 -05:00
const QString eclipseCaseName = exportSettings . caseToApply - > caseUserDescription ( ) ;
if ( exportSettings . fileSplit = = RicExportCompletionDataSettingsUi : : UNIFIED_FILE )
{
2017-08-08 06:56:07 -05:00
std : : vector < RigCompletionData > completions ;
for ( auto & data : completionsPerEclipseCell )
{
completions . push_back ( combineEclipseCellCompletions ( data . second , exportSettings ) ) ;
}
2017-06-15 04:21:37 -05:00
const QString fileName = QString ( " UnifiedCompletions_%1 " ) . arg ( eclipseCaseName ) ;
2017-06-21 03:58:02 -05:00
printCompletionsToFile ( exportSettings . folder , fileName , completions , exportSettings . compdatExport ) ;
2017-06-15 04:21:37 -05:00
}
else if ( exportSettings . fileSplit = = RicExportCompletionDataSettingsUi : : SPLIT_ON_WELL )
{
2017-06-15 04:37:00 -05:00
for ( auto wellPath : usedWellPaths )
2017-06-15 04:21:37 -05:00
{
2017-08-08 06:56:07 -05:00
std : : map < IJKCellIndex , std : : vector < RigCompletionData > > filteredWellCompletions = getCompletionsForWell ( completionsPerEclipseCell , wellPath - > completions ( ) - > wellNameForExport ( ) ) ;
std : : vector < RigCompletionData > completions ;
for ( auto & data : filteredWellCompletions )
{
completions . push_back ( combineEclipseCellCompletions ( data . second , exportSettings ) ) ;
}
2017-06-15 04:21:37 -05:00
std : : vector < RigCompletionData > wellCompletions ;
for ( auto completion : completions )
{
if ( completion . wellName ( ) = = wellPath - > completions ( ) - > wellNameForExport ( ) )
{
wellCompletions . push_back ( completion ) ;
}
}
2017-08-04 09:42:35 -05:00
if ( wellCompletions . empty ( ) ) continue ;
2017-06-15 04:21:37 -05:00
QString fileName = QString ( " %1_unifiedCompletions_%2 " ) . arg ( wellPath - > name ( ) ) . arg ( eclipseCaseName ) ;
2017-06-21 03:58:02 -05:00
printCompletionsToFile ( exportSettings . folder , fileName , wellCompletions , exportSettings . compdatExport ) ;
2017-06-15 04:21:37 -05:00
}
}
else if ( exportSettings . fileSplit = = RicExportCompletionDataSettingsUi : : SPLIT_ON_WELL_AND_COMPLETION_TYPE )
{
2017-06-15 04:37:00 -05:00
for ( auto wellPath : usedWellPaths )
2017-06-15 04:21:37 -05:00
{
2017-08-08 06:56:07 -05:00
std : : map < IJKCellIndex , std : : vector < RigCompletionData > > filteredWellCompletions = getCompletionsForWell ( completionsPerEclipseCell , wellPath - > completions ( ) - > wellNameForExport ( ) ) ;
std : : vector < RigCompletionData > completions ;
for ( auto & data : filteredWellCompletions )
{
completions . push_back ( combineEclipseCellCompletions ( data . second , exportSettings ) ) ;
}
2017-06-15 04:21:37 -05:00
{
std : : vector < RigCompletionData > fishbonesCompletions = getCompletionsForWellAndCompletionType ( completions , wellPath - > completions ( ) - > wellNameForExport ( ) , RigCompletionData : : FISHBONES ) ;
2017-08-04 09:42:35 -05:00
if ( ! fishbonesCompletions . empty ( ) )
{
QString fileName = QString ( " %1_Fishbones_%2 " ) . arg ( wellPath - > name ( ) ) . arg ( eclipseCaseName ) ;
printCompletionsToFile ( exportSettings . folder , fileName , fishbonesCompletions , exportSettings . compdatExport ) ;
}
2017-06-15 04:21:37 -05:00
}
{
std : : vector < RigCompletionData > perforationCompletions = getCompletionsForWellAndCompletionType ( completions , wellPath - > completions ( ) - > wellNameForExport ( ) , RigCompletionData : : PERFORATION ) ;
2017-08-04 09:42:35 -05:00
if ( ! perforationCompletions . empty ( ) )
{
QString fileName = QString ( " %1_Perforations_%2 " ) . arg ( wellPath - > name ( ) ) . arg ( eclipseCaseName ) ;
printCompletionsToFile ( exportSettings . folder , fileName , perforationCompletions , exportSettings . compdatExport ) ;
}
2017-06-15 04:21:37 -05:00
}
2017-08-01 06:09:42 -05:00
{
std : : vector < RigCompletionData > fractureCompletions = getCompletionsForWellAndCompletionType ( completions , wellPath - > completions ( ) - > wellNameForExport ( ) , RigCompletionData : : FRACTURE ) ;
2017-08-04 09:42:35 -05:00
if ( ! fractureCompletions . empty ( ) )
{
QString fileName = QString ( " %1_Fractures_%2 " ) . arg ( wellPath - > name ( ) ) . arg ( eclipseCaseName ) ;
printCompletionsToFile ( exportSettings . folder , fileName , fractureCompletions , exportSettings . compdatExport ) ;
}
2017-08-01 06:09:42 -05:00
}
2017-06-15 04:21:37 -05:00
}
}
}
2017-06-20 01:26:53 -05:00
//==================================================================================================
///
//==================================================================================================
RigCompletionData RicWellPathExportCompletionDataFeature : : combineEclipseCellCompletions ( const std : : vector < RigCompletionData > & completions ,
const RicExportCompletionDataSettingsUi & settings )
{
CVF_ASSERT ( ! completions . empty ( ) ) ;
QString wellName = completions [ 0 ] . wellName ( ) ;
IJKCellIndex cellIndexIJK = completions [ 0 ] . cellIndex ( ) ;
RigMainGrid * grid = settings . caseToApply - > eclipseCaseData ( ) - > mainGrid ( ) ;
size_t cellIndex = grid - > cellIndexFromIJK ( cellIndexIJK . i , cellIndexIJK . j , cellIndexIJK . k ) ;
RigCompletionData : : CompletionType completionType = completions [ 0 ] . completionType ( ) ;
//completion type, skin factor, well bore diameter and cell direction are taken from (first) main bore,
//if no main bore they are taken from first completion
double skinfactor = completions [ 0 ] . skinFactor ( ) ;
double wellBoreDiameter = completions [ 0 ] . diameter ( ) ;
CellDirection cellDirection = completions [ 0 ] . direction ( ) ;
for ( const RigCompletionData & completion : completions )
{
if ( completion . isMainBore ( ) )
{
skinfactor = completion . skinFactor ( ) ;
wellBoreDiameter = completion . diameter ( ) ;
cellDirection = completion . direction ( ) ;
break ;
}
}
RigCompletionData resultCompletion ( wellName , cellIndexIJK ) ;
double totalTrans = 0.0 ;
for ( const RigCompletionData & completion : completions )
{
2017-08-01 07:31:47 -05:00
resultCompletion . m_metadata . reserve ( resultCompletion . m_metadata . size ( ) + completion . m_metadata . size ( ) ) ;
resultCompletion . m_metadata . insert ( resultCompletion . m_metadata . end ( ) , completion . m_metadata . begin ( ) , completion . m_metadata . end ( ) ) ;
2017-06-20 01:26:53 -05:00
if ( completion . completionType ( ) ! = completions [ 0 ] . completionType ( ) )
{
2017-08-01 07:31:47 -05:00
QString errorMessage = QString ( " Cannot combine completions of different types in same cell [%1, %2, %3] " ) . arg ( cellIndexIJK . i + 1 ) . arg ( cellIndexIJK . j + 1 ) . arg ( cellIndexIJK . k + 1 ) ;
RiaLogging : : error ( errorMessage ) ;
resultCompletion . addMetadata ( " ERROR " , errorMessage ) ;
2017-06-20 01:26:53 -05:00
return resultCompletion ; //Returning empty completion, should not be exported
}
if ( completion . wellName ( ) ! = completions [ 0 ] . wellName ( ) )
{
2017-08-01 07:31:47 -05:00
QString errorMessage = QString ( " Cannot combine completions from different wells in same cell [%1, %2, %3] " ) . arg ( cellIndexIJK . i + 1 ) . arg ( cellIndexIJK . j + 1 ) . arg ( cellIndexIJK . k + 1 ) ;
RiaLogging : : error ( errorMessage ) ;
resultCompletion . addMetadata ( " ERROR " , errorMessage ) ;
2017-06-20 01:26:53 -05:00
return resultCompletion ; //Returning empty completion, should not be exported
}
if ( completion . transmissibility ( ) = = HUGE_VAL )
{
2017-08-01 07:31:47 -05:00
QString errorMessage = QString ( " Transmissibility calculation has failed for cell [%1, %2, %3] " ) . arg ( cellIndexIJK . i + 1 ) . arg ( cellIndexIJK . j + 1 ) . arg ( cellIndexIJK . k + 1 ) ;
RiaLogging : : error ( errorMessage ) ;
resultCompletion . addMetadata ( " ERROR " , errorMessage ) ;
2017-06-20 01:26:53 -05:00
return resultCompletion ; //Returning empty completion, should not be exported
}
2017-06-20 06:48:46 -05:00
2017-06-21 08:54:18 -05:00
if ( settings . excludeMainBoreForFishbones & & completionType = = RigCompletionData : : FISHBONES & & completion . isMainBore ( ) )
{
continue ;
}
2017-06-20 01:26:53 -05:00
totalTrans = totalTrans + completion . transmissibility ( ) ;
}
2017-08-01 07:31:47 -05:00
if ( settings . compdatExport = = RicExportCompletionDataSettingsUi : : TRANSMISSIBILITIES )
2017-06-20 01:26:53 -05:00
{
resultCompletion . setCombinedValuesExplicitTrans ( totalTrans , completionType ) ;
}
2017-06-23 08:45:22 -05:00
else if ( settings . compdatExport = = RicExportCompletionDataSettingsUi : : WPIMULT_AND_DEFAULT_CONNECTION_FACTORS )
2017-06-20 01:26:53 -05:00
{
//calculate trans for main bore - but as Eclipse will do it!
double transmissibilityEclipseCalculation = RicWellPathExportCompletionDataFeature : : calculateTransmissibilityAsEclipseDoes ( settings . caseToApply ( ) ,
skinfactor ,
wellBoreDiameter / 2 ,
cellIndex ,
cellDirection ) ;
double wpimult = totalTrans / transmissibilityEclipseCalculation ;
resultCompletion . setCombinedValuesImplicitTransWPImult ( wpimult , cellDirection , skinfactor , wellBoreDiameter , completionType ) ;
}
return resultCompletion ;
}
2017-06-15 04:21:37 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-08-04 09:42:35 -05:00
void RicWellPathExportCompletionDataFeature : : printCompletionsToFile ( const QString & folderName ,
const QString & fileName ,
std : : vector < RigCompletionData > & completions ,
RicExportCompletionDataSettingsUi : : CompdatExportType exportType )
2017-06-15 04:21:37 -05:00
{
2017-06-20 01:26:53 -05:00
//TODO: Check that completion is ready for export
2017-07-03 08:02:24 -05:00
QDir exportFolder = QDir ( folderName ) ;
if ( ! exportFolder . exists ( ) )
{
bool createdPath = exportFolder . mkpath ( folderName ) ;
if ( createdPath ) RiaLogging : : info ( " Created export folder " + folderName ) ;
else RiaLogging : : error ( " Selected output folder does not exist, and could not be created. " ) ;
}
QString filePath = exportFolder . filePath ( fileName ) ;
2017-06-15 04:21:37 -05:00
QFile exportFile ( filePath ) ;
2017-07-03 08:02:24 -05:00
if ( ! exportFile . open ( QIODevice : : WriteOnly ) )
2017-06-01 10:21:46 -05:00
{
2017-06-15 04:21:37 -05:00
RiaLogging : : error ( QString ( " Export Completions Data: Could not open the file: %1 " ) . arg ( filePath ) ) ;
return ;
2017-06-01 10:21:46 -05:00
}
2017-06-15 04:21:37 -05:00
QTextStream stream ( & exportFile ) ;
RifEclipseDataTableFormatter formatter ( stream ) ;
2017-06-01 10:21:46 -05:00
// Sort by well name / cell index
std : : sort ( completions . begin ( ) , completions . end ( ) ) ;
2017-06-15 04:21:37 -05:00
2017-06-01 10:21:46 -05:00
// Print completion data
generateCompdatTable ( formatter , completions ) ;
2017-06-20 01:26:53 -05:00
2017-06-21 03:58:02 -05:00
if ( exportType = = RicExportCompletionDataSettingsUi : : WPIMULT_AND_DEFAULT_CONNECTION_FACTORS )
2017-06-01 10:21:46 -05:00
{
generateWpimultTable ( formatter , completions ) ;
2017-05-16 08:17:19 -05:00
}
2017-06-08 04:56:06 -05:00
2017-06-15 04:21:37 -05:00
RiaLogging : : info ( QString ( " Successfully exported completion data to %1 " ) . arg ( filePath ) ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < RigCompletionData > RicWellPathExportCompletionDataFeature : : getCompletionsForWellAndCompletionType ( const std : : vector < RigCompletionData > & completions ,
const QString & wellName ,
RigCompletionData : : CompletionType completionType )
{
std : : vector < RigCompletionData > filteredCompletions ;
for ( auto completion : completions )
{
if ( completion . wellName ( ) = = wellName & & completion . completionType ( ) = = completionType )
{
filteredCompletions . push_back ( completion ) ;
}
}
return filteredCompletions ;
2017-05-19 09:45:07 -05:00
}
2017-05-15 09:04:11 -05:00
2017-08-08 06:56:07 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : map < IJKCellIndex , std : : vector < RigCompletionData > > RicWellPathExportCompletionDataFeature : : getCompletionsForWell ( const std : : map < IJKCellIndex , std : : vector < RigCompletionData > > & cellToCompletionMap , const QString & wellName )
{
std : : map < IJKCellIndex , std : : vector < RigCompletionData > > wellCompletions ;
for ( const auto & it : cellToCompletionMap )
{
for ( auto & completion : it . second )
{
if ( completion . wellName ( ) = = wellName )
{
wellCompletions [ it . first ] . push_back ( completion ) ;
}
}
}
return wellCompletions ;
}
2017-05-19 09:45:07 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-05-30 08:00:14 -05:00
void RicWellPathExportCompletionDataFeature : : generateCompdatTable ( RifEclipseDataTableFormatter & formatter , const std : : vector < RigCompletionData > & completionData )
2017-05-19 09:45:07 -05:00
{
std : : vector < RifEclipseOutputTableColumn > header = {
2017-05-29 06:13:25 -05:00
RifEclipseOutputTableColumn ( " Well " ) ,
RifEclipseOutputTableColumn ( " I " ) ,
RifEclipseOutputTableColumn ( " J " ) ,
RifEclipseOutputTableColumn ( " K1 " ) ,
RifEclipseOutputTableColumn ( " K2 " ) ,
RifEclipseOutputTableColumn ( " Status " ) ,
RifEclipseOutputTableColumn ( " SAT " ) ,
2017-08-10 08:07:56 -05:00
RifEclipseOutputTableColumn ( " TR " , RifEclipseOutputTableDoubleFormatting ( RifEclipseOutputTableDoubleFormat : : RIF_SCIENTIFIC ) ) ,
2017-05-29 06:13:25 -05:00
RifEclipseOutputTableColumn ( " DIAM " ) ,
RifEclipseOutputTableColumn ( " KH " ) ,
RifEclipseOutputTableColumn ( " S " ) ,
RifEclipseOutputTableColumn ( " Df " ) ,
RifEclipseOutputTableColumn ( " DIR " ) ,
RifEclipseOutputTableColumn ( " r0 " )
2017-05-19 09:45:07 -05:00
} ;
formatter . keyword ( " COMPDAT " ) ;
formatter . header ( header ) ;
2017-05-29 06:13:25 -05:00
for ( const RigCompletionData & data : completionData )
{
2017-06-21 08:54:18 -05:00
if ( data . transmissibility ( ) = = 0.0 | | data . wpimult ( ) = = 0.0 )
{
//Don't export completions without transmissibility
continue ;
}
2017-05-29 06:13:25 -05:00
for ( const RigCompletionMetaData & metadata : data . metadata ( ) )
{
formatter . comment ( QString ( " %1 : %2 " ) . arg ( metadata . name ) . arg ( metadata . comment ) ) ;
}
formatter . add ( data . wellName ( ) ) ;
formatter . addZeroBasedCellIndex ( data . cellIndex ( ) . i ) . addZeroBasedCellIndex ( data . cellIndex ( ) . j ) . addZeroBasedCellIndex ( data . cellIndex ( ) . k ) . addZeroBasedCellIndex ( data . cellIndex ( ) . k ) ;
switch ( data . connectionState ( ) )
{
case OPEN :
formatter . add ( " OPEN " ) ;
break ;
case SHUT :
formatter . add ( " SHUT " ) ;
break ;
case AUTO :
formatter . add ( " AUTO " ) ;
break ;
}
if ( RigCompletionData : : isDefaultValue ( data . saturation ( ) ) ) formatter . add ( " 1* " ) ; else formatter . add ( data . saturation ( ) ) ;
if ( RigCompletionData : : isDefaultValue ( data . transmissibility ( ) ) )
{
formatter . add ( " 1* " ) ; // Transmissibility
if ( RigCompletionData : : isDefaultValue ( data . diameter ( ) ) ) formatter . add ( " 1* " ) ; else formatter . add ( data . diameter ( ) ) ;
if ( RigCompletionData : : isDefaultValue ( data . kh ( ) ) ) formatter . add ( " 1* " ) ; else formatter . add ( data . kh ( ) ) ;
if ( RigCompletionData : : isDefaultValue ( data . skinFactor ( ) ) ) formatter . add ( " 1* " ) ; else formatter . add ( data . skinFactor ( ) ) ;
if ( RigCompletionData : : isDefaultValue ( data . dFactor ( ) ) ) formatter . add ( " 1* " ) ; else formatter . add ( data . dFactor ( ) ) ;
switch ( data . direction ( ) )
{
case DIR_I :
formatter . add ( " 'X' " ) ;
break ;
case DIR_J :
formatter . add ( " 'Y' " ) ;
break ;
case DIR_K :
formatter . add ( " 'Z' " ) ;
break ;
default :
formatter . add ( " 'Z' " ) ;
break ;
}
}
else
{
formatter . add ( data . transmissibility ( ) ) ;
}
formatter . rowCompleted ( ) ;
}
formatter . tableCompleted ( ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-05-30 08:00:14 -05:00
void RicWellPathExportCompletionDataFeature : : generateWpimultTable ( RifEclipseDataTableFormatter & formatter , const std : : vector < RigCompletionData > & completionData )
2017-05-29 06:13:25 -05:00
{
std : : vector < RifEclipseOutputTableColumn > header = {
RifEclipseOutputTableColumn ( " Well " ) ,
RifEclipseOutputTableColumn ( " Mult " ) ,
RifEclipseOutputTableColumn ( " I " ) ,
RifEclipseOutputTableColumn ( " J " ) ,
RifEclipseOutputTableColumn ( " K " ) ,
} ;
formatter . keyword ( " WPIMULT " ) ;
formatter . header ( header ) ;
for ( auto & completion : completionData )
{
2017-06-23 08:45:22 -05:00
if ( completion . wpimult ( ) = = 0.0 | | completion . isDefaultValue ( completion . wpimult ( ) ) )
2017-06-21 08:54:18 -05:00
{
continue ;
}
2017-05-29 06:13:25 -05:00
formatter . add ( completion . wellName ( ) ) ;
2017-06-21 08:54:18 -05:00
formatter . add ( completion . wpimult ( ) ) ;
2017-05-29 06:13:25 -05:00
formatter . addZeroBasedCellIndex ( completion . cellIndex ( ) . i ) . addZeroBasedCellIndex ( completion . cellIndex ( ) . j ) . addZeroBasedCellIndex ( completion . cellIndex ( ) . k ) ;
formatter . rowCompleted ( ) ;
}
formatter . tableCompleted ( ) ;
}
2017-05-19 09:45:07 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-05-30 07:37:51 -05:00
std : : vector < RigCompletionData > RicWellPathExportCompletionDataFeature : : generatePerforationsCompdatValues ( const RimWellPath * wellPath , const RicExportCompletionDataSettingsUi & settings )
2017-05-19 09:45:07 -05:00
{
2017-06-20 03:40:39 -05:00
RiaEclipseUnitTools : : UnitSystem unitSystem = settings . caseToApply - > eclipseCaseData ( ) - > unitsType ( ) ;
2017-05-29 06:13:25 -05:00
std : : vector < RigCompletionData > completionData ;
2017-08-11 07:05:59 -05:00
const RigActiveCellInfo * activeCellInfo = settings . caseToApply - > eclipseCaseData ( ) - > activeCellInfo ( RiaDefines : : MATRIX_MODEL ) ;
2017-06-20 03:18:20 -05:00
2017-05-19 09:45:07 -05:00
2017-05-29 06:13:25 -05:00
for ( const RimPerforationInterval * interval : wellPath - > perforationIntervalCollection ( ) - > perforations ( ) )
2017-05-19 09:45:07 -05:00
{
2017-05-30 08:42:05 -05:00
if ( ! interval - > isActiveOnDate ( settings . caseToApply - > timeStepDates ( ) [ settings . timeStep ] ) ) continue ;
2017-09-19 10:20:49 -05:00
using namespace std ;
pair < vector < cvf : : Vec3d > , vector < double > > perforationPointsAndMD = wellPath - > wellPathGeometry ( ) - > clippedPointSubset ( interval - > startMD ( ) , interval - > endMD ( ) ) ;
2017-09-19 08:22:14 -05:00
std : : vector < WellPathCellIntersectionInfo > intersectedCells = RigWellPathIntersectionTools : : findCellsIntersectedByPath ( settings . caseToApply - > eclipseCaseData ( ) ,
2017-09-19 10:20:49 -05:00
perforationPointsAndMD . first ,
perforationPointsAndMD . second ) ;
2017-05-29 06:13:25 -05:00
for ( auto & cell : intersectedCells )
{
2017-10-06 05:36:21 -05:00
bool cellIsActive = activeCellInfo - > isActive ( cell . globCellIndex ) ;
2017-06-20 03:18:20 -05:00
if ( ! cellIsActive ) continue ;
2017-05-29 06:13:25 -05:00
size_t i , j , k ;
2017-10-06 05:36:21 -05:00
settings . caseToApply - > eclipseCaseData ( ) - > mainGrid ( ) - > ijkFromCellIndex ( cell . globCellIndex , & i , & j , & k ) ;
2017-06-14 06:43:56 -05:00
RigCompletionData completion ( wellPath - > completions ( ) - > wellNameForExport ( ) , IJKCellIndex ( i , j , k ) ) ;
2017-10-06 05:36:21 -05:00
CellDirection direction = calculateDirectionInCell ( settings . caseToApply , cell . globCellIndex , cell . internalCellLengths ) ;
2017-06-20 03:18:20 -05:00
double transmissibility = RicWellPathExportCompletionDataFeature : : calculateTransmissibility ( settings . caseToApply ,
wellPath ,
cell . internalCellLengths ,
interval - > skinFactor ( ) ,
2017-06-20 03:40:39 -05:00
interval - > diameter ( unitSystem ) / 2 ,
2017-10-06 05:36:21 -05:00
cell . globCellIndex ,
2017-09-20 08:24:29 -05:00
settings . useLateralNTG ) ;
2017-06-20 03:18:20 -05:00
completion . setTransAndWPImultBackgroundDataFromPerforation ( transmissibility ,
interval - > skinFactor ( ) ,
2017-06-20 03:40:39 -05:00
interval - > diameter ( unitSystem ) ,
2017-06-20 03:18:20 -05:00
direction ) ;
2017-06-22 08:20:16 -05:00
completion . addMetadata ( " Perforation " , QString ( " StartMD: %1 - EndMD: %2 " ) . arg ( interval - > startMD ( ) ) . arg ( interval - > endMD ( ) ) + QString ( " : " ) + QString : : number ( transmissibility ) ) ;
2017-05-29 06:13:25 -05:00
completionData . push_back ( completion ) ;
}
2017-05-19 09:45:07 -05:00
}
2017-05-29 06:13:25 -05:00
return completionData ;
2017-05-19 09:45:07 -05:00
}
2017-05-15 09:04:11 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < size_t > RicWellPathExportCompletionDataFeature : : findIntersectingCells ( const RigEclipseCaseData * caseData , const std : : vector < cvf : : Vec3d > & coords )
{
2017-05-16 07:50:54 -05:00
std : : set < size_t > cells ;
2017-05-15 09:04:11 -05:00
2017-05-29 06:13:25 -05:00
std : : vector < HexIntersectionInfo > intersections = RigWellPathIntersectionTools : : getIntersectedCells ( caseData - > mainGrid ( ) , coords ) ;
2017-05-19 04:28:02 -05:00
for ( auto intersection : intersections )
{
cells . insert ( intersection . m_hexIndex ) ;
}
// Ensure only unique cells are included
std : : vector < size_t > cellsVector ;
cellsVector . assign ( cells . begin ( ) , cells . end ( ) ) ;
// Sort cells
std : : sort ( cellsVector . begin ( ) , cellsVector . end ( ) ) ;
return cellsVector ;
}
2017-05-15 09:04:11 -05:00
//--------------------------------------------------------------------------------------------------
2017-05-16 07:50:54 -05:00
///
2017-05-15 09:04:11 -05:00
//--------------------------------------------------------------------------------------------------
2017-05-19 09:45:07 -05:00
void RicWellPathExportCompletionDataFeature : : markWellPathCells ( const std : : vector < size_t > & wellPathCells , std : : vector < WellSegmentLocation > * locations )
2017-05-15 09:04:11 -05:00
{
2017-05-19 09:45:07 -05:00
std : : set < size_t > wellPathCellSet ( wellPathCells . begin ( ) , wellPathCells . end ( ) ) ;
for ( WellSegmentLocation & location : * locations )
2017-05-16 02:43:41 -05:00
{
2017-05-19 09:45:07 -05:00
for ( WellSegmentLateral & lateral : location . laterals )
2017-05-16 02:43:41 -05:00
{
2017-05-19 09:45:07 -05:00
for ( WellSegmentLateralIntersection & intersection : lateral . intersections )
{
if ( wellPathCellSet . find ( intersection . cellIndex ) ! = wellPathCellSet . end ( ) )
{
intersection . mainBoreCell = true ;
}
}
2017-05-16 02:43:41 -05:00
}
}
}
2017-05-19 04:28:02 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicWellPathExportCompletionDataFeature : : wellSegmentLocationOrdering ( const WellSegmentLocation & first , const WellSegmentLocation & second )
{
return first . measuredDepth < second . measuredDepth ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-14 03:32:24 -05:00
bool RicWellPathExportCompletionDataFeature : : isPointBetween ( const cvf : : Vec3d & startPoint , const cvf : : Vec3d & endPoint , const cvf : : Vec3d & pointToCheck )
2017-05-19 04:28:02 -05:00
{
cvf : : Plane plane ;
2017-06-14 03:32:24 -05:00
plane . setFromPointAndNormal ( pointToCheck , endPoint - startPoint ) ;
return plane . side ( startPoint ) ! = plane . side ( endPoint ) ;
2017-05-19 04:28:02 -05:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-05-29 06:13:25 -05:00
std : : vector < WellSegmentLocation > RicWellPathExportCompletionDataFeature : : findWellSegmentLocations ( const RimEclipseCase * caseToApply , const RimWellPath * wellPath )
2017-05-19 04:28:02 -05:00
{
2017-05-29 08:39:37 -05:00
std : : vector < RimFishbonesMultipleSubs * > fishbonesSubs ;
2017-05-19 08:44:32 -05:00
for ( RimFishbonesMultipleSubs * subs : wellPath - > fishbonesCollection ( ) - > fishbonesSubs ( ) )
2017-05-29 08:39:37 -05:00
{
fishbonesSubs . push_back ( subs ) ;
}
return findWellSegmentLocations ( caseToApply , wellPath , fishbonesSubs ) ;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std : : vector < WellSegmentLocation > RicWellPathExportCompletionDataFeature : : findWellSegmentLocations ( const RimEclipseCase * caseToApply , const RimWellPath * wellPath , const std : : vector < RimFishbonesMultipleSubs * > & fishbonesSubs )
{
std : : vector < WellSegmentLocation > wellSegmentLocations ;
for ( RimFishbonesMultipleSubs * subs : fishbonesSubs )
2017-05-19 04:28:02 -05:00
{
2017-06-02 03:16:16 -05:00
for ( auto & sub : subs - > installedLateralIndices ( ) )
2017-05-19 04:28:02 -05:00
{
2017-06-02 03:16:16 -05:00
double measuredDepth = subs - > measuredDepth ( sub . subIndex ) ;
2017-05-19 04:28:02 -05:00
cvf : : Vec3d position = wellPath - > wellPathGeometry ( ) - > interpolatedPointAlongWellPath ( measuredDepth ) ;
2017-06-02 03:16:16 -05:00
WellSegmentLocation location = WellSegmentLocation ( subs , measuredDepth , - position . z ( ) , sub . subIndex ) ;
for ( size_t lateralIndex : sub . lateralIndices )
2017-05-19 04:28:02 -05:00
{
location . laterals . push_back ( WellSegmentLateral ( lateralIndex ) ) ;
}
wellSegmentLocations . push_back ( location ) ;
}
}
std : : sort ( wellSegmentLocations . begin ( ) , wellSegmentLocations . end ( ) , wellSegmentLocationOrdering ) ;
2017-05-19 09:45:07 -05:00
assignBranchAndSegmentNumbers ( caseToApply , & wellSegmentLocations ) ;
2017-05-19 04:28:02 -05:00
return wellSegmentLocations ;
}
2017-05-19 09:45:07 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-09-19 08:22:14 -05:00
void RicWellPathExportCompletionDataFeature : : calculateLateralIntersections ( const RimEclipseCase * caseToApply ,
WellSegmentLocation * location ,
int * branchNum ,
int * segmentNum )
2017-05-19 09:45:07 -05:00
{
for ( WellSegmentLateral & lateral : location - > laterals )
{
lateral . branchNumber = + + ( * branchNum ) ;
2017-09-19 10:20:49 -05:00
std : : vector < std : : pair < cvf : : Vec3d , double > > lateralCoordMDPairs = location - > fishbonesSubs - > coordsAndMDForLateral ( location - > subIndex , lateral . lateralIndex ) ;
std : : vector < cvf : : Vec3d > lateralCoords ;
std : : vector < double > lateralMDs ;
lateralCoords . reserve ( lateralCoordMDPairs . size ( ) ) ;
lateralMDs . reserve ( lateralCoordMDPairs . size ( ) ) ;
for ( auto & coordMD : lateralCoordMDPairs )
{
lateralCoords . push_back ( coordMD . first ) ;
lateralMDs . push_back ( coordMD . second ) ;
}
2017-09-19 08:22:14 -05:00
std : : vector < WellPathCellIntersectionInfo > intersections = RigWellPathIntersectionTools : : findCellsIntersectedByPath ( caseToApply - > eclipseCaseData ( ) ,
2017-09-19 10:20:49 -05:00
lateralCoords ,
lateralMDs ) ;
2017-05-19 09:45:07 -05:00
2017-05-29 06:13:25 -05:00
auto intersection = intersections . cbegin ( ) ;
double length = 0 ;
double depth = 0 ;
2017-06-14 03:32:24 -05:00
cvf : : Vec3d startPoint = lateralCoords [ 0 ] ;
2017-06-02 05:50:16 -05:00
int attachedSegmentNumber = location - > icdSegmentNumber ;
2017-05-19 09:45:07 -05:00
2017-06-14 03:32:24 -05:00
for ( size_t i = 1 ; i < lateralCoords . size ( ) & & intersection ! = intersections . cend ( ) ; + + i )
2017-05-19 09:45:07 -05:00
{
2017-06-14 03:32:24 -05:00
if ( isPointBetween ( startPoint , lateralCoords [ i ] , intersection - > endPoint ) )
2017-05-19 09:45:07 -05:00
{
2017-05-29 06:13:25 -05:00
length + = ( intersection - > endPoint - startPoint ) . length ( ) ;
depth + = intersection - > endPoint . z ( ) - startPoint . z ( ) ;
2017-09-19 08:22:14 -05:00
WellSegmentLateralIntersection lateralIntersection ( + + ( * segmentNum ) ,
attachedSegmentNumber ,
2017-10-06 05:36:21 -05:00
intersection - > globCellIndex ,
2017-09-19 08:22:14 -05:00
length ,
depth ) ;
2017-06-07 09:04:34 -05:00
lateralIntersection . lengthsInCell = intersection - > internalCellLengths ;
2017-05-29 06:13:25 -05:00
lateral . intersections . push_back ( lateralIntersection ) ;
length = 0 ;
depth = 0 ;
2017-06-02 04:43:03 -05:00
startPoint = intersection - > endPoint ;
2017-05-29 06:13:25 -05:00
attachedSegmentNumber = * segmentNum ;
+ + intersection ;
}
else
{
2017-06-14 03:32:24 -05:00
length + = ( lateralCoords [ i ] - startPoint ) . length ( ) ;
depth + = lateralCoords [ i ] . z ( ) - startPoint . z ( ) ;
startPoint = lateralCoords [ i ] ;
2017-05-19 09:45:07 -05:00
}
2017-05-22 06:23:48 -05:00
}
2017-05-19 09:45:07 -05:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicWellPathExportCompletionDataFeature : : assignBranchAndSegmentNumbers ( const RimEclipseCase * caseToApply , std : : vector < WellSegmentLocation > * locations )
{
int segmentNumber = 1 ;
int branchNumber = 1 ;
// First loop over the locations so that each segment on the main stem is an incremental number
for ( WellSegmentLocation & location : * locations )
{
location . segmentNumber = + + segmentNumber ;
2017-06-02 05:50:16 -05:00
location . icdBranchNumber = + + branchNumber ;
location . icdSegmentNumber = + + segmentNumber ;
2017-05-19 09:45:07 -05:00
}
// Then assign branch and segment numbers to each lateral parts
for ( WellSegmentLocation & location : * locations )
{
calculateLateralIntersections ( caseToApply , & location , & branchNumber , & segmentNumber ) ;
}
}
2017-05-22 06:23:48 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-15 02:11:55 -05:00
void RicWellPathExportCompletionDataFeature : : appendCompletionData ( std : : map < IJKCellIndex , std : : vector < RigCompletionData > > * completionData , const std : : vector < RigCompletionData > & data )
2017-05-22 06:23:48 -05:00
{
2017-05-29 06:13:25 -05:00
for ( auto & completion : data )
2017-05-22 06:23:48 -05:00
{
2017-05-29 06:13:25 -05:00
auto it = completionData - > find ( completion . cellIndex ( ) ) ;
if ( it ! = completionData - > end ( ) )
2017-05-22 06:23:48 -05:00
{
2017-06-15 02:11:55 -05:00
it - > second . push_back ( completion ) ;
2017-05-22 06:23:48 -05:00
}
2017-05-29 06:13:25 -05:00
else
2017-05-22 06:23:48 -05:00
{
2017-06-15 02:11:55 -05:00
completionData - > insert ( std : : pair < IJKCellIndex , std : : vector < RigCompletionData > > ( completion . cellIndex ( ) , std : : vector < RigCompletionData > { completion } ) ) ;
2017-05-22 06:23:48 -05:00
}
}
}
2017-05-30 02:26:45 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-07 09:04:34 -05:00
CellDirection RicWellPathExportCompletionDataFeature : : calculateDirectionInCell ( RimEclipseCase * eclipseCase , size_t cellIndex , const cvf : : Vec3d & lengthsInCell )
2017-05-30 02:26:45 -05:00
{
2017-06-07 09:04:34 -05:00
RigEclipseCaseData * eclipseCaseData = eclipseCase - > eclipseCaseData ( ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DX " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dxAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DX " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DY " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dyAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DY " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DZ " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dzAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DZ " ) ;
2017-06-07 09:04:34 -05:00
double xLengthFraction = abs ( lengthsInCell . x ( ) / dxAccessObject - > cellScalarGlobIdx ( cellIndex ) ) ;
double yLengthFraction = abs ( lengthsInCell . y ( ) / dyAccessObject - > cellScalarGlobIdx ( cellIndex ) ) ;
double zLengthFraction = abs ( lengthsInCell . z ( ) / dzAccessObject - > cellScalarGlobIdx ( cellIndex ) ) ;
if ( xLengthFraction > yLengthFraction & & xLengthFraction > zLengthFraction )
2017-05-30 02:26:45 -05:00
{
2017-05-30 02:31:37 -05:00
return CellDirection : : DIR_I ;
2017-06-07 09:04:34 -05:00
}
else if ( yLengthFraction > xLengthFraction & & yLengthFraction > zLengthFraction )
{
2017-05-30 02:31:37 -05:00
return CellDirection : : DIR_J ;
2017-06-07 09:04:34 -05:00
}
else
{
2017-05-30 02:31:37 -05:00
return CellDirection : : DIR_K ;
2017-05-30 02:26:45 -05:00
}
}
2017-06-08 03:40:56 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2017-06-13 08:37:06 -05:00
double RicWellPathExportCompletionDataFeature : : calculateTransmissibility ( RimEclipseCase * eclipseCase ,
const RimWellPath * wellPath ,
const cvf : : Vec3d & internalCellLengths ,
double skinFactor ,
double wellRadius ,
size_t cellIndex ,
2017-09-20 08:24:29 -05:00
bool useLateralNTG ,
2017-06-13 08:37:06 -05:00
size_t volumeScaleConstant ,
2017-06-20 02:46:25 -05:00
CellDirection directionForVolumeScaling )
2017-06-08 03:40:56 -05:00
{
RigEclipseCaseData * eclipseCaseData = eclipseCase - > eclipseCaseData ( ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DX " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dxAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DX " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DY " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dyAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DY " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DZ " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dzAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DZ " ) ;
2017-06-08 03:40:56 -05:00
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMX " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permxAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMX " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMY " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permyAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMY " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMZ " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permzAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMZ " ) ;
2017-06-08 03:40:56 -05:00
2017-09-20 08:24:29 -05:00
double ntg = 1.0 ;
size_t ntgResIdx = eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " NTG " ) ;
if ( ntgResIdx ! = cvf : : UNDEFINED_SIZE_T )
{
cvf : : ref < RigResultAccessor > ntgAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " NTG " ) ;
ntg = ntgAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
}
double latNtg = useLateralNTG ? ntg : 1.0 ;
2017-06-08 03:40:56 -05:00
double dx = dxAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double dy = dyAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double dz = dzAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double permx = permxAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
2017-09-19 10:26:13 -05:00
double permy = permyAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double permz = permzAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
2017-06-08 03:40:56 -05:00
2017-06-13 08:22:12 -05:00
double darcy = RiaEclipseUnitTools : : darcysConstant ( wellPath - > unitSystem ( ) ) ;
2017-06-08 03:40:56 -05:00
2017-06-13 08:37:06 -05:00
if ( volumeScaleConstant ! = 1 )
{
2017-06-20 02:46:25 -05:00
if ( directionForVolumeScaling = = CellDirection : : DIR_I ) dx = dx / volumeScaleConstant ;
if ( directionForVolumeScaling = = CellDirection : : DIR_J ) dy = dy / volumeScaleConstant ;
if ( directionForVolumeScaling = = CellDirection : : DIR_K ) dz = dz / volumeScaleConstant ;
2017-06-13 08:37:06 -05:00
}
2017-09-20 08:24:29 -05:00
double transx = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( internalCellLengths . x ( ) * latNtg , permy , permz , dy , dz , wellRadius , skinFactor , darcy ) ;
double transy = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( internalCellLengths . y ( ) * latNtg , permx , permz , dx , dz , wellRadius , skinFactor , darcy ) ;
double transz = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( internalCellLengths . z ( ) * ntg , permy , permx , dy , dx , wellRadius , skinFactor , darcy ) ;
2017-06-08 03:40:56 -05:00
return RigTransmissibilityEquations : : totalConnectionFactor ( transx , transy , transz ) ;
}
2017-06-20 01:26:53 -05:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RicWellPathExportCompletionDataFeature : : calculateTransmissibilityAsEclipseDoes ( RimEclipseCase * eclipseCase ,
double skinFactor ,
double wellRadius ,
size_t cellIndex ,
CellDirection direction )
{
RigEclipseCaseData * eclipseCaseData = eclipseCase - > eclipseCaseData ( ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DX " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dxAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DX " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DY " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dyAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DY " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " DZ " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > dzAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " DZ " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMX " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permxAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMX " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMY " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permyAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMY " ) ;
2017-09-13 03:39:20 -05:00
eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " PERMZ " ) ;
2017-08-11 07:05:59 -05:00
cvf : : ref < RigResultAccessor > permzAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " PERMZ " ) ;
2017-06-20 01:26:53 -05:00
2017-09-20 08:24:29 -05:00
double ntg = 1.0 ;
size_t ntgResIdx = eclipseCase - > results ( RiaDefines : : MATRIX_MODEL ) - > findOrLoadScalarResult ( RiaDefines : : STATIC_NATIVE , " NTG " ) ;
if ( ntgResIdx ! = cvf : : UNDEFINED_SIZE_T )
{
cvf : : ref < RigResultAccessor > ntgAccessObject = RigResultAccessorFactory : : createFromUiResultName ( eclipseCaseData , 0 , RiaDefines : : MATRIX_MODEL , 0 , " NTG " ) ;
ntg = ntgAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
}
2017-06-20 01:26:53 -05:00
double dx = dxAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double dy = dyAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double dz = dzAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double permx = permxAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
2017-09-19 10:26:13 -05:00
double permy = permyAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
double permz = permzAccessObject - > cellScalarGlobIdx ( cellIndex ) ;
2017-06-20 01:26:53 -05:00
2017-06-20 03:40:39 -05:00
RiaEclipseUnitTools : : UnitSystem units = eclipseCaseData - > unitsType ( ) ;
2017-06-20 01:26:53 -05:00
double darcy = RiaEclipseUnitTools : : darcysConstant ( units ) ;
double trans = cvf : : UNDEFINED_DOUBLE ;
if ( direction = = CellDirection : : DIR_I )
{
trans = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( dx , permy , permz , dy , dz , wellRadius , skinFactor , darcy ) ;
}
else if ( direction = = CellDirection : : DIR_J )
{
trans = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( dy , permx , permz , dx , dz , wellRadius , skinFactor , darcy ) ;
}
else if ( direction = = CellDirection : : DIR_K )
{
2017-09-20 08:24:29 -05:00
trans = RigTransmissibilityEquations : : wellBoreTransmissibilityComponent ( dz * ntg , permy , permx , dy , dx , wellRadius , skinFactor , darcy ) ;
2017-06-20 01:26:53 -05:00
}
return trans ;
}