diff --git a/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.cpp b/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.cpp index ae49d5fcbc..d05cc934de 100644 --- a/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.cpp @@ -74,9 +74,9 @@ static std::optional locateKeywordAtTimeStep( std::unique_ if ( startIdx.has_value() ) { auto idx = startIdx.value(); - idx--; + idx++; // locate keyword for the selected step, break if another date is found - for ( auto it = idx; it != fileDeck->start(); it-- ) + for ( auto it = idx; it != fileDeck->stop(); it++ ) { auto& kw = fileDeck->operator[]( it ); if ( kw.name() == Opm::ParserKeywords::DATES::keywordName ) @@ -156,8 +156,6 @@ static Opm::ParseContext defaultParseContext() //-------------------------------------------------------------------------------------------------- static bool insertKeywordAtIndex( std::unique_ptr& fileDeck, Opm::DeckKeyword& keyword, Opm::FileDeck::Index insertIdx ) { - Opm::ErrorGuard errors{}; - try { fileDeck->insert( insertIdx, keyword ); @@ -351,7 +349,7 @@ int RifOpmFlowDeckFile::mergeKeywordAtPosition( int position, const Opm::DeckKey //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RifOpmFlowDeckFile::mergeKeywordAtTimeStep( int timeStep, const Opm::DeckKeyword& keyword ) +bool RifOpmFlowDeckFile::mergeKeywordAtTimeStep( int timeStep, const Opm::DeckKeyword& keyword, std::string insertAfterKeyword ) { if ( m_fileDeck.get() == nullptr ) return false; @@ -378,8 +376,23 @@ bool RifOpmFlowDeckFile::mergeKeywordAtTimeStep( int timeStep, const Opm::DeckKe } else { - // existing kw not found, insert a new one - m_fileDeck->insert( insertIdx, keyword ); + bool insertedOk = false; + if ( !insertAfterKeyword.empty() ) + { + auto insertAfterKw = internal::locateKeywordAtTimeStep( m_fileDeck, timeStep, insertAfterKeyword ); + if ( insertAfterKw.has_value() ) + { + auto afterIdx = insertAfterKw.value(); + afterIdx++; + m_fileDeck->insert( afterIdx, keyword ); + insertedOk = true; + } + } + if ( !insertedOk ) + { + // insert after keyword not found, insert at date position + m_fileDeck->insert( insertIdx, keyword ); + } } return true; } @@ -631,6 +644,55 @@ bool RifOpmFlowDeckFile::setWelldims( int maxWells, int maxConnections, int maxG return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RifOpmFlowDeckFile::wsegdims() +{ + using W = Opm::ParserKeywords::WSEGDIMS; + if ( m_fileDeck.get() == nullptr ) return {}; + auto idx = m_fileDeck->find( W::keywordName ); + if ( idx.has_value() ) + { + std::vector dims; + + auto& kw = m_fileDeck->operator[]( idx.value() ); + const auto& rec = kw.getRecord( 0 ); + dims.push_back( rec.getItem().get( 0 ) ); + dims.push_back( rec.getItem().get( 0 ) ); + dims.push_back( rec.getItem().get( 0 ) ); + + return dims; + } + return { 0, 0, 0 }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RifOpmFlowDeckFile::setWsegdims( int maxMSWells, int maxSegmentsPerWell, int maxBranchesPerWell ) +{ + using W = Opm::ParserKeywords::WSEGDIMS; + if ( m_fileDeck.get() == nullptr ) return false; + + auto idx = m_fileDeck->find( W::keywordName ); + if ( !idx.has_value() ) + { + idx = m_fileDeck->find( Opm::ParserKeywords::WELLDIMS::keywordName ); + if ( !idx.has_value() ) return false; + idx = idx.value() + 1; + } + + Opm::DeckKeyword newKw( ( Opm::ParserKeywords::WSEGDIMS() ) ); + newKw.addRecord( Opm::DeckRecord{ { RifOpmDeckTools::item( W::NSWLMX::itemName, maxMSWells ), + RifOpmDeckTools::item( W::NSEGMX::itemName, maxSegmentsPerWell ), + RifOpmDeckTools::item( W::NLBRMX::itemName, maxBranchesPerWell ) } } ); + + m_fileDeck->erase( idx.value() ); + m_fileDeck->insert( idx.value(), newKw ); + return true; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -777,97 +839,6 @@ bool RifOpmFlowDeckFile::replaceKeyword( const std::string& section, const Opm:: return true; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RifOpmFlowDeckFile::mergeMswData( std::vector& mswFileData ) -{ - Opm::ErrorGuard errors{}; - - int curTimeStep = 0; - int maxSteps = (int)mswFileData.size(); - std::string prevFileData; - - // locate dates keyword for the selected step - for ( auto it = m_fileDeck->start(); it != m_fileDeck->stop(); it++ ) - { - auto& kw = m_fileDeck->operator[]( it ); - if ( kw.name() != Opm::ParserKeywords::DATES::keywordName ) continue; - - Opm::FileDeck::Index insertIdx( it ); - - if ( mswFileData[curTimeStep] != prevFileData ) - { - auto deck = Opm::Parser{}.parseString( mswFileData[curTimeStep], internal::defaultParseContext(), errors ); - - for ( auto kwit = deck.begin(); kwit != deck.end(); kwit++ ) - { - Opm::DeckKeyword newKw( *kwit ); - - if ( ( newKw.name() == Opm::ParserKeywords::WELSPECS::keywordName ) && ( curTimeStep == 0 ) ) - { - const auto found = m_fileDeck->find( Opm::ParserKeywords::WELSPECS::keywordName ); - if ( !found.has_value() ) - { - m_fileDeck->insert( insertIdx, newKw ); - insertIdx++; - } - else - { - Opm::DeckRecord newRecToAdd( newKw.getRecord( 0 ) ); - - auto& existing_idx = found.value(); - auto& welspecs_kw = m_fileDeck->operator[]( existing_idx ); - - Opm::DeckKeyword newWelspecsKw( welspecs_kw ); - newWelspecsKw.addRecord( std::move( newRecToAdd ) ); - - m_fileDeck->erase( existing_idx ); - m_fileDeck->insert( existing_idx, newWelspecsKw ); - } - } - else if ( ( newKw.name() == Opm::ParserKeywords::COMPDAT::keywordName ) && ( curTimeStep == 0 ) ) - { - const auto found = m_fileDeck->find( Opm::ParserKeywords::COMPDAT::keywordName ); - if ( !found.has_value() ) - { - m_fileDeck->insert( insertIdx, newKw ); - insertIdx++; - } - else - { - auto& existing_idx = found.value(); - auto& compdat_kw = m_fileDeck->operator[]( existing_idx ); - - Opm::DeckKeyword newCompdatKw( compdat_kw ); - - for ( size_t i = 0; i < newKw.size(); i++ ) - { - Opm::DeckRecord newRecToAdd( newKw.getRecord( i ) ); - newCompdatKw.addRecord( std::move( newRecToAdd ) ); - } - - m_fileDeck->erase( existing_idx ); - m_fileDeck->insert( existing_idx, newCompdatKw ); - } - } - else - { - m_fileDeck->insert( insertIdx, newKw ); - insertIdx++; - } - } - - prevFileData = mswFileData[curTimeStep]; - } - - curTimeStep++; - if ( curTimeStep >= maxSteps ) break; - } - - return curTimeStep > 1; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.h b/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.h index bb63b4d271..69707d7dbd 100644 --- a/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.h +++ b/ApplicationLibCode/FileInterface/RifOpmFlowDeckFile.h @@ -48,9 +48,7 @@ public: bool saveDeck( std::string folder, std::string filename ); int mergeKeywordAtPosition( int deckPosition, const Opm::DeckKeyword& keyword ); - bool mergeKeywordAtTimeStep( int timeStep, const Opm::DeckKeyword& keyword ); - - bool mergeMswData( std::vector& mswFileData ); + bool mergeKeywordAtTimeStep( int timeStep, const Opm::DeckKeyword& keyword, std::string insertAfterKeyword = "" ); bool openWellAtTimeStep( int timeStep, Opm::DeckKeyword& openKeyword ); bool openWellAtDeckPosition( int deckPosition, Opm::DeckKeyword& openKeyword ); @@ -71,6 +69,9 @@ public: std::vector welldims(); bool setWelldims( int maxWells, int maxConnections, int maxGroups, int maxWellsInGroup ); + std::vector wsegdims(); + bool setWsegdims( int maxMSWells, int maxSegmentsPerWell, int maxBranchesPerWell ); + std::vector regdims(); bool setRegdims( int maxRegions, int maxRegionDefinitions, int maxRegionFlowConnections, int maxFIPRegions ); bool ensureRegdimsKeyword(); diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp index e7f694cecb..821fcb36c9 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.cpp @@ -35,16 +35,40 @@ #include "cvfStructGrid.h" +#include "opm/input/eclipse/Deck/Deck.hpp" #include "opm/input/eclipse/Deck/DeckItem.hpp" #include "opm/input/eclipse/Deck/DeckKeyword.hpp" #include "opm/input/eclipse/Deck/DeckRecord.hpp" -#include "opm/input/eclipse/Parser/ParserKeyword.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/B.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/C.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/F.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/O.hpp" #include "opm/input/eclipse/Parser/ParserKeywords/W.hpp" +#include "opm/input/eclipse/Parser/ErrorGuard.hpp" +#include "opm/input/eclipse/Parser/InputErrorAction.hpp" +#include "opm/input/eclipse/Parser/ParseContext.hpp" +#include "opm/input/eclipse/Parser/Parser.hpp" + +namespace internal +{ +//-------------------------------------------------------------------------------------------------- +/// Temporary methods for MSW data while waiting for MSW export rewrite +//-------------------------------------------------------------------------------------------------- +static Opm::ParseContext defaultParseContext() +{ + // Use the same default ParseContext as flow. + Opm::ParseContext pc( Opm::InputErrorAction::WARN ); + pc.update( Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputErrorAction::IGNORE ); + pc.update( Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputErrorAction::WARN ); + pc.update( Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputErrorAction::WARN ); + pc.update( Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputErrorAction::WARN ); + + return pc; +} + +} // namespace internal + //================================================================================================== /// /// @@ -158,6 +182,139 @@ Opm::DeckKeyword compdatKeyword( RimEclipseCase* eCase, RimWellPath* wellPath ) return kw; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword welsegsKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ) +{ + if ( eCase == nullptr || wellPath == nullptr || wellPath->completionSettings() == nullptr ) + { + return Opm::DeckKeyword(); + } + + Opm::ErrorGuard errors{}; + bool headerDone = false; + + Opm::DeckKeyword newKw( ( Opm::ParserKeywords::WELSEGS() ) ); + + auto deck = Opm::Parser{}.parseString( completionText, internal::defaultParseContext(), errors ); + for ( auto kwit = deck.begin(); kwit != deck.end(); kwit++ ) + { + auto& existingKw = *kwit; + + if ( existingKw.name() != Opm::ParserKeywords::WELSEGS::keywordName ) continue; + + for ( size_t i = 0; i < existingKw.size(); i++ ) + { + Opm::DeckRecord newRec( existingKw.getRecord( i ) ); + if ( newRec.getItem( 0 ).is_string() && headerDone ) continue; + + newKw.addRecord( std::move( newRec ) ); + headerDone = true; + } + } + + return newKw; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword compsegsKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ) +{ + if ( eCase == nullptr || wellPath == nullptr || wellPath->completionSettings() == nullptr ) + { + return Opm::DeckKeyword(); + } + + Opm::ErrorGuard errors{}; + bool headerDone = false; + + Opm::DeckKeyword newKw( ( Opm::ParserKeywords::COMPSEGS() ) ); + + auto deck = Opm::Parser{}.parseString( completionText, internal::defaultParseContext(), errors ); + for ( auto kwit = deck.begin(); kwit != deck.end(); kwit++ ) + { + auto& existingKw = *kwit; + + if ( existingKw.name() != Opm::ParserKeywords::COMPSEGS::keywordName ) continue; + + for ( size_t i = 0; i < existingKw.size(); i++ ) + { + Opm::DeckRecord newRec( existingKw.getRecord( i ) ); + + if ( newRec.size() == 1 && headerDone ) continue; + + newKw.addRecord( std::move( newRec ) ); + headerDone = true; + } + } + + return newKw; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword wsegvalvKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ) +{ + if ( eCase == nullptr || wellPath == nullptr || wellPath->completionSettings() == nullptr ) + { + return Opm::DeckKeyword(); + } + + Opm::ErrorGuard errors{}; + + Opm::DeckKeyword newKw( ( Opm::ParserKeywords::WSEGVALV() ) ); + + auto deck = Opm::Parser{}.parseString( completionText, internal::defaultParseContext(), errors ); + for ( auto kwit = deck.begin(); kwit != deck.end(); kwit++ ) + { + auto& existingKw = *kwit; + + if ( existingKw.name() != Opm::ParserKeywords::WSEGVALV::keywordName ) continue; + + for ( size_t i = 0; i < existingKw.size(); i++ ) + { + Opm::DeckRecord newRec( existingKw.getRecord( i ) ); + newKw.addRecord( std::move( newRec ) ); + } + } + + return newKw; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Opm::DeckKeyword wsegaicdKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ) +{ + if ( eCase == nullptr || wellPath == nullptr || wellPath->completionSettings() == nullptr ) + { + return Opm::DeckKeyword(); + } + + Opm::ErrorGuard errors{}; + + Opm::DeckKeyword newKw( ( Opm::ParserKeywords::WSEGAICD() ) ); + + auto deck = Opm::Parser{}.parseString( completionText, internal::defaultParseContext(), errors ); + for ( auto kwit = deck.begin(); kwit != deck.end(); kwit++ ) + { + auto& existingKw = *kwit; + + if ( existingKw.name() != Opm::ParserKeywords::WSEGAICD::keywordName ) continue; + + for ( size_t i = 0; i < existingKw.size(); i++ ) + { + Opm::DeckRecord newRec( existingKw.getRecord( i ) ); + newKw.addRecord( std::move( newRec ) ); + } + } + + return newKw; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h index 98967ceb58..ce5e7b227e 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimKeywordFactory.h @@ -48,6 +48,12 @@ namespace RimKeywordFactory Opm::DeckKeyword welspecsKeyword( const std::string wellGrpName, RimEclipseCase* eCase, RimWellPath* wellPath ); Opm::DeckKeyword compdatKeyword( RimEclipseCase* eCase, RimWellPath* wellPath ); + +Opm::DeckKeyword welsegsKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ); +Opm::DeckKeyword compsegsKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ); +Opm::DeckKeyword wsegvalvKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ); +Opm::DeckKeyword wsegaicdKeyword( RimEclipseCase* eCase, RimWellPath* wellPath, const std::string completionText ); + Opm::DeckKeyword faultsKeyword( const RigMainGrid* mainGrid, const cvf::Vec3st& min = cvf::Vec3st::ZERO, const cvf::Vec3st& max = cvf::Vec3st::UNDEFINED, diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp index 888cc2976b..8694f07611 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.cpp @@ -783,29 +783,19 @@ bool RimOpmFlowJob::onPrepare() } m_wellPath->completionSettings()->setGroupName( m_wellGroupName() ); - int mergePosition = m_openWellDeckPosition(); + int mergePosition = mergeBasicWellSettings(); + if ( mergePosition < 0 ) + { + RiaLogging::error( "Unable to merge new well data into DATA file. Please check file format." ); + return false; + } if ( ( m_includeMSWData ) && ( m_wellOpenType == WellOpenType::OPEN_AT_DATE ) ) { - std::vector mswData; - int nDates = (int)m_eclipseCase()->timeStepDates().size(); - for ( int timeStep = 0; timeStep < nDates; timeStep++ ) - { - mswData.push_back( exportMswWellSettings( timeStep ) ); - } - - if ( !m_deckFile->mergeMswData( mswData ) ) - { - RiaLogging::error( "Failed to merge MSW data into file deck." ); - return false; - } - } - else - { - mergePosition = mergeBasicWellSettings(); + mergePosition = mergeMswData( mergePosition ); if ( mergePosition < 0 ) { - RiaLogging::error( "Unable to merge new well data into DATA file. Please check file format." ); + RiaLogging::error( "Failed to merge MSW data into file deck." ); return false; } } @@ -1018,7 +1008,7 @@ int RimOpmFlowJob::mergeBasicWellSettings() // reverse order for correct insertion order if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), compdatKw ) ) return failure; if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), welspecsKw ) ) return failure; - return 0; + mergePosition = 0; } else { @@ -1031,8 +1021,10 @@ int RimOpmFlowJob::mergeBasicWellSettings() // increase wells and connections in welldims to make sure they are big enough auto additionalConnections = (int)compdatKw.size(); auto welldims = m_deckFile->welldims(); - if ( !m_deckFile->setWelldims( (int)welldims[0] + 1, (int)( welldims[1] + additionalConnections ), (int)welldims[2] + 1, (int)welldims[3] + 1 ) ) + if ( ( welldims.size() < 4 ) || + !m_deckFile->setWelldims( (int)welldims[0] + 1, (int)( welldims[1] + additionalConnections ), (int)welldims[2] + 1, (int)welldims[3] + 1 ) ) { + RiaLogging::error( "Failed to update WELLDIMS keyword in DATA file, is it missing?" ); return failure; } return mergePosition; @@ -1074,6 +1066,78 @@ std::string RimOpmFlowJob::exportMswWellSettings( int timeStep ) return fileContent.toStdString(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RimOpmFlowJob::mergeMswData( int mergePosition ) +{ + const int failure = -1; + + auto mswData = exportMswWellSettings( 0 ); + + auto welsegsKw = RimKeywordFactory::welsegsKeyword( m_eclipseCase(), m_wellPath(), mswData ); + auto compsegsKw = RimKeywordFactory::compsegsKeyword( m_eclipseCase(), m_wellPath(), mswData ); + auto wsegvalvKw = RimKeywordFactory::wsegvalvKeyword( m_eclipseCase(), m_wellPath(), mswData ); + auto wsegaicdKw = RimKeywordFactory::wsegaicdKeyword( m_eclipseCase(), m_wellPath(), mswData ); + + if ( welsegsKw.size() < 1 || compsegsKw.size() < 1 ) + { + RiaLogging::error( "Failed to create WELSEGS or COMPSEGS keyword from MSW data." ); + return failure; + } + + if ( m_wellOpenType == WellOpenType::OPEN_AT_DATE ) + { + // make sure we insert after COMPDAT kw + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), welsegsKw, "COMPDAT" ) ) return failure; + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), compsegsKw, welsegsKw.name() ) ) return failure; + if ( wsegvalvKw.size() >= 1 ) + { + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), wsegvalvKw, compsegsKw.name() ) ) return failure; + } + if ( wsegaicdKw.size() >= 1 ) + { + if ( !m_deckFile->mergeKeywordAtTimeStep( m_openTimeStep(), wsegaicdKw, compsegsKw.name() ) ) return failure; + } + + mergePosition = 0; + } + else + { + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, welsegsKw ); + if ( mergePosition < 0 ) return failure; + mergePosition++; + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, compsegsKw ); + if ( mergePosition < 0 ) return failure; + mergePosition++; + if ( wsegvalvKw.size() >= 1 ) + { + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, wsegvalvKw ); + if ( mergePosition < 0 ) return failure; + mergePosition++; + } + if ( wsegaicdKw.size() >= 1 ) + { + mergePosition = m_deckFile->mergeKeywordAtPosition( mergePosition, wsegaicdKw ); + if ( mergePosition < 0 ) return failure; + mergePosition++; + } + } + + int branches = (int)m_wellPath->allWellPathLaterals().size(); + + // increase wells and connections in welldims to make sure they are big enough + auto additionalSegments = (int)welsegsKw.size() - 1; + auto wsegdims = m_deckFile->wsegdims(); + auto maxBranches = std::max( branches, wsegdims[2] ); + if ( ( wsegdims.size() < 3 ) || !m_deckFile->setWsegdims( wsegdims[0] + 1, wsegdims[1] + additionalSegments, maxBranches + 1 ) ) + { + RiaLogging::error( "Failed to update WSEGDIMS keyword in DATA file." ); + return failure; + } + return mergePosition; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.h b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.h index b8b02b4f6e..a995a15b1c 100644 --- a/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.h +++ b/ApplicationLibCode/ProjectDataModel/Jobs/RimOpmFlowJob.h @@ -104,6 +104,7 @@ private: int mergeBasicWellSettings(); std::string exportMswWellSettings( int timeStep ); + int mergeMswData( int mergePosition ); void selectOpenWellPosition(); void resetEnsembleRunId();