diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp index 1a1351d695..5d7bfa9137 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp +++ b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.cpp @@ -260,6 +260,12 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompletions( const std::v } } + // make sure we use per-connection D-factors, must be done after combining completions + for ( auto& completion : completions ) + { + completion.setPerConnectionDfactor(); + } + const QString eclipseCaseName = exportSettings.caseToApply->caseUserDescription(); if ( exportSettings.fileSplit == RicExportCompletionDataSettingsUi::ExportSplit::UNIFIED_FILE ) @@ -413,8 +419,9 @@ RigCompletionData RicWellPathExportCompletionDataFeatureImpl::combineEclipseCell auto isValidTransmissibility = []( double transmissibility ) { return RiaStatisticsTools::isValidNumber( transmissibility ) && transmissibility >= 0.0; }; - auto startMD = completions[0].startMD(); - auto endMD = completions[0].endMD(); + auto startMD = completions[0].startMD(); + auto endMD = completions[0].endMD(); + auto completionNumber = completions[0].completionNumber(); for ( const RigCompletionData& completion : completions ) { @@ -442,6 +449,14 @@ RigCompletionData RicWellPathExportCompletionDataFeatureImpl::combineEclipseCell } } + if ( !completionNumber.has_value() ) + { + if ( completion.completionNumber().has_value() ) + { + completionNumber = completion.completionNumber(); + } + } + double transmissibility = completion.transmissibility(); if ( !isValidTransmissibility( transmissibility ) ) @@ -468,6 +483,7 @@ RigCompletionData RicWellPathExportCompletionDataFeatureImpl::combineEclipseCell { resultCompletion.setDepthRange( startMD.value(), endMD.value() ); } + if ( completionNumber.has_value() ) resultCompletion.setCompletionNumber( completionNumber.value() ); double combinedDiameter = diameterCalculator.weightedMean(); double combinedSkinFactor = skinFactorCalculator.weightedMean(); @@ -898,6 +914,15 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompdatAndWpimultTables( { exportWpimultTableUsingFormatter( formatter, gridName, completions ); } + + for ( auto& completion : completions ) + { + if ( completion.completionNumber().has_value() ) + { + exportComplumpTableUsingFormatter( formatter, gridName, completions ); + break; + } + } } RiaLogging::info( QString( "Successfully exported completion data to %1" ).arg( exportFile->fileName() ) ); @@ -1000,10 +1025,7 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompdatTableUsingFormatte formatter.addValueOrDefaultMarker( data.diameter(), RigCompletionData::defaultValue() ); formatter.addValueOrDefaultMarker( data.kh(), RigCompletionData::defaultValue() ); formatter.addValueOrDefaultMarker( data.skinFactor(), RigCompletionData::defaultValue() ); - if ( RigCompletionData::isDefaultValue( data.dFactor() ) ) - formatter.add( "1*" ); - else - formatter.add( -data.dFactor() ); + formatter.addValueOrDefaultMarker( data.dFactor(), RigCompletionData::defaultValue() ); switch ( data.direction() ) { @@ -1024,6 +1046,65 @@ void RicWellPathExportCompletionDataFeatureImpl::exportCompdatTableUsingFormatte formatter.tableCompleted(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicWellPathExportCompletionDataFeatureImpl::exportComplumpTableUsingFormatter( RifTextDataTableFormatter& formatter, + const QString& gridName, + const std::vector& completionData ) +{ + if ( gridName.isEmpty() ) + { + std::vector header = { RifTextDataTableColumn( "WELL", "NAME" ), + RifTextDataTableColumn( "", "I" ), + RifTextDataTableColumn( "", "J" ), + RifTextDataTableColumn( "", "K1" ), + RifTextDataTableColumn( "", "K2" ), + RifTextDataTableColumn( "COMP", "NUM" ) }; + + formatter.header( header ); + formatter.keyword( "COMPLUMP" ); + } + else + { + std::vector header = { RifTextDataTableColumn( "WELL", "NAME" ), + RifTextDataTableColumn( "LGR", "NAME" ), + RifTextDataTableColumn( "", "I" ), + RifTextDataTableColumn( "", "J" ), + RifTextDataTableColumn( "", "K1" ), + RifTextDataTableColumn( "", "K2" ), + RifTextDataTableColumn( "COMP", "NUM" ) }; + + formatter.header( header ); + formatter.keyword( "COMPLMPL" ); + } + + for ( const RigCompletionData& data : completionData ) + { + if ( !data.completionNumber().has_value() || data.transmissibility() == 0.0 || data.wpimult() == 0.0 ) + { + // Don't export completions without transmissibility or completion number set + continue; + } + + formatter.add( data.wellName() ); + + if ( !gridName.isEmpty() ) + { + formatter.add( gridName ); + } + + formatter.add( data.completionDataGridCell().localCellIndexI() + 1 ) + .add( data.completionDataGridCell().localCellIndexJ() + 1 ) + .add( data.completionDataGridCell().localCellIndexK() + 1 ) + .add( data.completionDataGridCell().localCellIndexK() + 1 ) + .add( data.completionNumber().value() ); + + formatter.rowCompleted(); + } + formatter.tableCompleted(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1172,6 +1253,7 @@ std::vector kh, direction ); completion.setDepthRange( cell.startMD, cell.endMD ); + if ( interval->completionNumber() > 0 ) completion.setCompletionNumber( interval->completionNumber() ); completion.addMetadata( "Perforation Completion", QString( "MD In: %1 - MD Out: %2" ).arg( cell.startMD ).arg( cell.endMD ) + @@ -1727,5 +1809,12 @@ std::vector RicWellPathExportCompletionDataFeatureImpl::compl std::sort( completions.begin(), completions.end() ); + // make sure we set per-connection D-factors, must be done after combining completions + for ( auto& completion : completions ) + { + completion.setPerConnectionDfactor(); // we calculate per connection D-factors, which are negative per definition (ref. OPM Flow + // manual) + } + return completions; } \ No newline at end of file diff --git a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h index f434db4ae2..0e71b76ca8 100644 --- a/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h +++ b/ApplicationLibCode/Commands/CompletionExportCommands/RicWellPathExportCompletionDataFeatureImpl.h @@ -179,6 +179,10 @@ private: const QString& gridName, const std::vector& completionData ); + static void exportComplumpTableUsingFormatter( RifTextDataTableFormatter& formatter, + const QString& gridName, + const std::vector& completionData ); + static void exportWpimultTableUsingFormatter( RifTextDataTableFormatter& formatter, const QString& gridName, const std::vector& completionData ); diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.cpp b/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.cpp index 4123f4a2de..279f4f67b8 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.cpp +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.cpp @@ -50,6 +50,7 @@ RimPerforationInterval::RimPerforationInterval() CAF_PDM_InitScriptableField( &m_endMD, "EndMeasuredDepth", 0.0, "End MD" ); CAF_PDM_InitScriptableField( &m_diameter, "Diameter", 0.216, "Diameter" ); CAF_PDM_InitScriptableField( &m_skinFactor, "SkinFactor", 0.0, "Skin Factor" ); + CAF_PDM_InitScriptableField( &m_completionNumber, "CompletionNumber", 0, "Completion Number" ); CAF_PDM_InitField( &m_startOfHistory_OBSOLETE, "StartOfHistory", true, "All Timesteps" ); m_startOfHistory_OBSOLETE.xmlCapability()->setIOWritable( false ); @@ -158,6 +159,22 @@ double RimPerforationInterval::skinFactor() const return m_skinFactor(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimPerforationInterval::setCompletionNumber( int number ) +{ + m_completionNumber = number; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimPerforationInterval::completionNumber() const +{ + return m_completionNumber(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -363,13 +380,15 @@ void RimPerforationInterval::defineUiOrdering( QString uiConfigName, caf::PdmUiO uiOrdering.add( &m_endMD ); uiOrdering.add( &m_diameter ); uiOrdering.add( &m_skinFactor ); + uiOrdering.add( &m_completionNumber ); - uiOrdering.add( &m_useCustomStartDate ); - uiOrdering.add( &m_startDate ); + auto dateGrp = uiOrdering.addNewGroup( "Date Settings" ); + dateGrp->setCollapsedByDefault(); + dateGrp->add( &m_useCustomStartDate ); + dateGrp->add( &m_startDate ); m_startDate.uiCapability()->setUiReadOnly( !m_useCustomStartDate ); - - uiOrdering.add( &m_useCustomEndDate ); - uiOrdering.add( &m_endDate ); + dateGrp->add( &m_useCustomEndDate ); + dateGrp->add( &m_endDate ); m_endDate.uiCapability()->setUiReadOnly( !m_useCustomEndDate ); uiOrdering.skipRemainingFields(); diff --git a/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.h b/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.h index a68aba7f0b..6edf912aa0 100644 --- a/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.h +++ b/ApplicationLibCode/ProjectDataModel/Completions/RimPerforationInterval.h @@ -53,8 +53,10 @@ public: void setDiameter( double diameter ); void setSkinFactor( double skinFactor ); + void setCompletionNumber( int number ); double diameter( RiaDefines::EclipseUnitSystem unitSystem ) const; double skinFactor() const; + int completionNumber() const; bool isActiveOnDate( const QDateTime& date ) const; @@ -88,6 +90,7 @@ private: caf::PdmField m_endMD; caf::PdmField m_diameter; caf::PdmField m_skinFactor; + caf::PdmField m_completionNumber; caf::PdmField m_useCustomStartDate; caf::PdmField m_startDate; diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp index b1c15297cd..c9eb3044fe 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp @@ -97,21 +97,17 @@ Opm::DeckKeyword welspecsKeyword( const std::string wellGrpName, RimEclipseCase* //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -Opm::DeckKeyword compdatKeyword( RimEclipseCase* eCase, RimWellPath* wellPath ) +Opm::DeckKeyword compdatKeyword( const std::vector& compdata, const std::string wellName ) { - if ( eCase == nullptr || wellPath == nullptr || wellPath->completionSettings() == nullptr || eCase->eclipseCaseData() == nullptr ) + if ( compdata.empty() ) { return Opm::DeckKeyword(); } - auto compdata = RicWellPathExportCompletionDataFeatureImpl::completionDataForWellPath( wellPath, eCase ); - using C = Opm::ParserKeywords::COMPDAT; Opm::DeckKeyword kw( ( Opm::ParserKeywords::COMPDAT() ) ); - auto wellName = wellPath->completionSettings()->wellNameForExport().toStdString(); - for ( auto& cd : compdata ) { std::vector items; @@ -153,6 +149,70 @@ Opm::DeckKeyword compdatKeyword( RimEclipseCase* eCase, RimWellPath* wellPath ) return kw; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword wpimultKeyword( const std::vector& compdata, const std::string wellName ) +{ + if ( compdata.empty() ) + { + return Opm::DeckKeyword(); + } + + using W = Opm::ParserKeywords::WPIMULT; + + Opm::DeckKeyword kw( ( Opm::ParserKeywords::WPIMULT() ) ); + + for ( auto& cd : compdata ) + { + if ( cd.wpimult() == RigCompletionData::defaultValue() ) + { + continue; + } + + std::vector items; + + items.push_back( RifOpmDeckTools::item( W::WELL::itemName, wellName ) ); + items.push_back( RifOpmDeckTools::item( W::WELLPI::itemName, cd.wpimult() ) ); + items.push_back( RifOpmDeckTools::item( W::I::itemName, cd.completionDataGridCell().localCellIndexI() + 1 ) ); + items.push_back( RifOpmDeckTools::item( W::J::itemName, cd.completionDataGridCell().localCellIndexJ() + 1 ) ); + items.push_back( RifOpmDeckTools::item( W::K::itemName, cd.completionDataGridCell().localCellIndexK() + 1 ) ); + + kw.addRecord( Opm::DeckRecord{ std::move( items ) } ); + } + + return kw; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword complumpKeyword( const std::vector& compdata, const std::string wellName ) +{ + if ( compdata.empty() ) + { + return Opm::DeckKeyword(); + } + using C = Opm::ParserKeywords::COMPLUMP; + Opm::DeckKeyword kw( ( Opm::ParserKeywords::COMPLUMP() ) ); + for ( auto& cd : compdata ) + { + if ( !cd.completionNumber().has_value() ) + { + continue; + } + std::vector items; + items.push_back( RifOpmDeckTools::item( C::WELL::itemName, wellName ) ); + items.push_back( RifOpmDeckTools::item( C::I::itemName, cd.completionDataGridCell().localCellIndexI() + 1 ) ); + items.push_back( RifOpmDeckTools::item( C::J::itemName, cd.completionDataGridCell().localCellIndexJ() + 1 ) ); + items.push_back( RifOpmDeckTools::item( C::K1::itemName, cd.completionDataGridCell().localCellIndexK() + 1 ) ); + items.push_back( RifOpmDeckTools::item( C::K2::itemName, cd.completionDataGridCell().localCellIndexK() + 1 ) ); + items.push_back( RifOpmDeckTools::item( C::N::itemName, cd.completionNumber().value() ) ); + kw.addRecord( Opm::DeckRecord{ std::move( items ) } ); + } + return kw; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h index 6a6439a4e7..73387b5beb 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h @@ -24,6 +24,7 @@ #include #include +class RigCompletionData; class RigMainGrid; class RigMswTableData; class RimEclipseCase; @@ -48,7 +49,9 @@ namespace RimKeywordFactory { Opm::DeckKeyword welspecsKeyword( const std::string wellGrpName, RimEclipseCase* eCase, RimWellPath* wellPath ); -Opm::DeckKeyword compdatKeyword( RimEclipseCase* eCase, RimWellPath* wellPath ); +Opm::DeckKeyword compdatKeyword( const std::vector& compdata, const std::string wellName ); +Opm::DeckKeyword wpimultKeyword( const std::vector& compdata, const std::string wellName ); +Opm::DeckKeyword complumpKeyword( const std::vector& compdata, const std::string wellName ); Opm::DeckKeyword welsegsKeyword( const RigMswTableData& mswData, int& maxSegments, int& maxBranches ); Opm::DeckKeyword compsegsKeyword( const RigMswTableData& mswData ); diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp index f2c9490ff2..2c12fbd9df 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp @@ -1030,9 +1030,21 @@ int RimOpmFlowJob::mergeBasicWellSettings() { const int failure = -1; + if ( m_eclipseCase() == nullptr || m_wellPath() == nullptr || m_wellPath()->completionSettings() == nullptr || + m_eclipseCase()->eclipseCaseData() == nullptr ) + { + RiaLogging::error( "Cannot create COMPDAT keyword - check case, wellpath and completion settings data." ); + return failure; + } + + auto compdata = RicWellPathExportCompletionDataFeatureImpl::completionDataForWellPath( m_wellPath(), m_eclipseCase() ); + auto wellName = m_wellPath()->completionSettings()->wellNameForExport().toStdString(); + int mergePosition = m_openWellDeckPosition(); - auto compdatKw = RimKeywordFactory::compdatKeyword( m_eclipseCase(), m_wellPath() ); + auto compdatKw = RimKeywordFactory::compdatKeyword( compdata, wellName ); + auto wpimultKw = RimKeywordFactory::wpimultKeyword( compdata, wellName ); + auto complumpKw = RimKeywordFactory::complumpKeyword( compdata, wellName ); auto welspecsKw = RimKeywordFactory::welspecsKeyword( m_wellGroupName().toStdString(), m_eclipseCase(), m_wellPath() ); if ( welspecsKw.empty() || compdatKw.empty() ) @@ -1044,6 +1056,14 @@ int RimOpmFlowJob::mergeBasicWellSettings() if ( m_wellOpenType == WellOpenType::OPEN_AT_DATE ) { // reverse order for correct insertion order + if ( !complumpKw.empty() ) + { + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), complumpKw ) ) return failure; + } + if ( !wpimultKw.empty() ) + { + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), wpimultKw ) ) return failure; + } if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), compdatKw ) ) return failure; if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), welspecsKw ) ) return failure; mergePosition = 0; @@ -1054,6 +1074,16 @@ int RimOpmFlowJob::mergeBasicWellSettings() if ( mergePosition < 0 ) return failure; mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, compdatKw ); if ( mergePosition < 0 ) return failure; + if ( !wpimultKw.empty() ) + { + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, wpimultKw ); + if ( mergePosition < 0 ) return failure; + } + if ( !complumpKw.empty() ) + { + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, complumpKw ); + if ( mergePosition < 0 ) return failure; + } } // increase wells and connections in welldims to make sure they are big enough diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.cpp b/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.cpp index 8886c4550a..ad14ae77fc 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.cpp @@ -24,6 +24,7 @@ #include +#include #include //================================================================================================== @@ -46,6 +47,7 @@ RigCompletionData::RigCompletionData( const QString& wellName, const RigCompleti , m_secondOrderingValue( std::numeric_limits::infinity() ) , m_startMD( std::nullopt ) , m_endMD( std::nullopt ) + , m_completionNumber( std::nullopt ) { } @@ -261,6 +263,17 @@ void RigCompletionData::setDFactor( double dFactor ) m_dFactor = dFactor; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCompletionData::setPerConnectionDfactor() +{ + if ( isDefaultValue( m_dFactor ) ) return; + + // We use per connection dfactors, they have negative values, ref OPM Flow manual - COMPDAT kw + m_dFactor = std::abs( m_dFactor ) * -1.0; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -381,6 +394,14 @@ std::optional RigCompletionData::endMD() const return m_endMD; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::optional RigCompletionData::completionNumber() const +{ + return m_completionNumber; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -517,6 +538,7 @@ void RigCompletionData::copy( RigCompletionData& target, const RigCompletionData target.m_firstOrderingValue = from.m_firstOrderingValue; target.m_secondOrderingValue = from.m_secondOrderingValue; target.m_sourcePdmObject = from.m_sourcePdmObject; + target.m_completionNumber = from.m_completionNumber; } //-------------------------------------------------------------------------------------------------- @@ -527,3 +549,11 @@ void RigCompletionData::setDepthRange( double startMD, double endMD ) m_startMD = startMD; m_endMD = endMD; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigCompletionData::setCompletionNumber( int completionNumber ) +{ + m_completionNumber = completionNumber; +} diff --git a/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.h b/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.h index 86c10573e0..57f0570a86 100644 --- a/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.h +++ b/ApplicationLibCode/ReservoirDataModel/Completions/RigCompletionData.h @@ -86,6 +86,7 @@ public: void setDiameter( double diameter ); void setTransmissibility( double transmissibility ); void setDepthRange( double startMD, double endMD ); + void setCompletionNumber( int completionNumber ); void setTransAndWPImultBackgroundDataFromFishbone( double transmissibility, double skinFactor, @@ -120,6 +121,7 @@ public: bool isNonDarcyFlow() const; void setDFactor( double dFactor ); void setKh( double kh ); + void setPerConnectionDfactor(); void addMetadata( const QString& name, const QString& comment ); @@ -140,6 +142,7 @@ public: bool isMainBore() const; std::optional startMD() const; std::optional endMD() const; + std::optional completionNumber() const; QString directionStringIJK() const; QString directionStringXYZ() const; QString metaDataString() const; @@ -166,6 +169,8 @@ private: std::optional m_startMD; // start MD in completion cell std::optional m_endMD; // end MD in completion cell + std::optional m_completionNumber; // for complump kword + bool m_isMainBore; // to use mainbore for Eclipse calculation double m_wpimult; diff --git a/GrpcInterface/GrpcProtos/SimulatorTables.proto b/GrpcInterface/GrpcProtos/SimulatorTables.proto index 11cc8874ee..73867270a0 100644 --- a/GrpcInterface/GrpcProtos/SimulatorTables.proto +++ b/GrpcInterface/GrpcProtos/SimulatorTables.proto @@ -39,6 +39,7 @@ message SimulatorCompdatEntry { optional double end_md = 15; optional string comment = 16; optional string grid_name = 17; + optional int32 completion_number = 18; } message SimulatorWelspecsEntry { diff --git a/GrpcInterface/Python/rips/PythonExamples/wells_and_fractures/completion_data.py b/GrpcInterface/Python/rips/PythonExamples/wells_and_fractures/completion_data.py index db5a8e2e65..860691ec8c 100644 --- a/GrpcInterface/Python/rips/PythonExamples/wells_and_fractures/completion_data.py +++ b/GrpcInterface/Python/rips/PythonExamples/wells_and_fractures/completion_data.py @@ -53,6 +53,7 @@ for well in wells: txt += fieldValueOrDefaultText(line, "pvt_num") + " " txt += fieldValueOrDefaultText(line, "hydrostatic_density_calc") + " " txt += fieldValueOrDefaultText(line, "fip_region") + " " + txt += "/" print(txt) @@ -60,14 +61,17 @@ for well in wells: compdat = completion_data.compdat + complump_entries = [] + print("COMPDAT") for line in compdat: txt = "" + complump = "" if line.HasField("start_md"): txt += "-- Perforation MD In " + str(line.start_md) - txt += ", MD Out " + str(line.end_md) + "\n" + txt += ", MD Out " + str(line.end_md) + "--\n" txt += " " txt += line.well_name + " " @@ -83,13 +87,36 @@ for well in wells: txt += fieldValueOrDefaultText(line, "skin_factor") + " " txt += fieldValueOrDefaultText(line, "d_factor") + " " txt += "'%s'" % line.direction + txt += " /" + + if (line.HasField("completion_number")) and (line.completion_number > 0): + complump += " " + complump += line.well_name + " " + complump += str(line.grid_i) + " " + complump += str(line.grid_j) + " " + complump += str(line.upper_k) + " " + complump += str(line.lower_k) + " " + complump += str(line.completion_number) + " " + complump += " /" + + complump_entries.append(complump) print(txt) + print("/\n") + + if len(complump_entries) > 0: + print("COMPLUMP") + for complump_entry in complump_entries: + print(complump_entry) + print("/\n") + else: + print("-- No COMPLUMP entries --\n") + print("WELSEGS") welsegs = completion_data.welsegs if (welsegs is None) or (len(welsegs) == 0): - print(" -- No WELSEGS data --") + print(" -- No WELSEGS data --\n") else: for welsegs_entry in welsegs: # Print WELSEGS header @@ -102,6 +129,7 @@ for well in wells: txt += header.info_type + " " txt += fieldValueOrDefaultText(header, "pressure_components") + " " txt += fieldValueOrDefaultText(header, "flow_model") + txt += " /" print(txt) # Print WELSEGS segment rows @@ -115,7 +143,7 @@ for well in wells: txt += str(row.depth) + " " txt += fieldValueOrDefaultText(row, "diameter") + " " txt += fieldValueOrDefaultText(row, "roughness") + " " - # txt += fieldValueOrDefaultText(row, "description") + txt += " /" print(txt) print("/") @@ -135,6 +163,7 @@ for well in wells: txt += str(compseg.distance_start) + " " txt += str(compseg.distance_end) + " " txt += fieldValueOrDefaultText(compseg, "grid_name") + txt += " /" print(txt) print("/\n") diff --git a/GrpcInterface/RiaWellPathDataToGrpcConverter.cpp b/GrpcInterface/RiaWellPathDataToGrpcConverter.cpp index 15eaf31775..32a69b4fd9 100644 --- a/GrpcInterface/RiaWellPathDataToGrpcConverter.cpp +++ b/GrpcInterface/RiaWellPathDataToGrpcConverter.cpp @@ -72,6 +72,10 @@ void RiaWellPathDataToGrpcConverter::copyCompdatToGrpc( const RigCompletionData& compDat->set_start_md( inputData.startMD().value() ); compDat->set_end_md( inputData.endMD().value() ); } + if ( inputData.completionNumber().has_value() ) + { + compDat->set_completion_number( inputData.completionNumber().value() ); + } // Set LGR grid name, empty string for main grid compDat->set_grid_name( inputData.completionDataGridCell().lgrName().toStdString() );