#14063 Well Event: Group records of same keyword across wells

The schedule generator previously concatenated full keyword blocks
(`KEYWORD ... /\n/\n`) — one per well — producing verbose output where
each WELSPECS / COMPDAT / WCONHIST / WELSEGS / COMPSEGS / etc. block
appeared once per contributing well. Eclipse keywords are designed to
hold multiple records under a single header; the per-well repetition is
syntactically valid but bloats the file and obscures intent.

Switch `RicScheduleDataGenerator` to accumulate
`std::map<QString, Opm::DeckKeyword>` instead of raw concatenated text.
Each per-well helper now returns an `Opm::DeckKeyword`, and a new
`mergeKeyword` primitive appends its records into the accumulator entry,
creating the entry from the helper's keyword on first encounter. At
emission time each accumulated keyword is serialised once.

To support this, `RifEventKeywordFormatter` is split: each `format*`
QString function now wraps a corresponding `build*` function that
returns `std::optional<Opm::DeckKeyword>`. `RimWellEventKeyword` and
`RimKeywordEvent` expose a parallel `generateDeckKeyword` accessor.
The text-scraping `extractKeywordName` helper becomes dead code and is
removed.
This commit is contained in:
Kristian Bendiksen committed 2026-05-28 08:21:17 +02:00
1 parent d2e7bed6b8
commit 6ef024cee9
9 files changed
+249 -177

No files matched your search

@@ -33,6 +33,7 @@
#include "RimWellPathCompletionSettings.h"
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
#include "opm/input/eclipse/Deck/DeckRecord.hpp"
#include <map>
#include <set>
@@ -88,6 +89,26 @@ std::vector<QDateTime> RicScheduleDataGenerator::collectAllDates( const RimWellE
return std::vector<QDateTime>( uniqueDates.begin(), uniqueDates.end() );
}
//--------------------------------------------------------------------------------------------------
/// Append the records of `kw` into the entry for `name`, creating that entry from a copy of `kw`
/// on first encounter so the accumulated DeckKeyword is bound to the right ParserKeyword.
//--------------------------------------------------------------------------------------------------
void RicScheduleDataGenerator::mergeKeyword( std::map<QString, Opm::DeckKeyword>& acc, const QString& name, Opm::DeckKeyword kw )
{
if ( kw.size() == 0 && !kw.isDataKeyword() ) return;
auto it = acc.find( name );
if ( it == acc.end() )
{
acc.emplace( name, std::move( kw ) );
return;
}
for ( const auto& rec : kw )
{
it->second.addRecord( Opm::DeckRecord( rec ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -120,66 +141,64 @@ QString RicScheduleDataGenerator::generateDateSection( const RimWellEventTimelin
// Generate DATES keyword
result += RimKeywordFactory::deckKeywordToString( RimKeywordFactory::datesKeyword( date ) ) + "\n";
// Collect all keyword output into a map keyed by keyword name
std::map<QString, QString> keywordBlocks;
// Records for each keyword name are accumulated across wells, then serialised once below.
std::map<QString, Opm::DeckKeyword> keywordBlocks;
for ( auto* well : wellPaths )
{
if ( !well ) continue;
QString welspecsKw = generateWelspecsForWell( timeline, eclipseCase, *well, date );
if ( !welspecsKw.isEmpty() )
if ( auto welspecs = generateWelspecsForWell( timeline, eclipseCase, *well, date ) )
{
keywordBlocks["WELSPECS"] += welspecsKw;
mergeKeyword( keywordBlocks, "WELSPECS", std::move( *welspecs ) );
}
QString wellCompdat = generateCompdatForWell( timeline, eclipseCase, *well, date );
if ( !wellCompdat.isEmpty() )
if ( auto compdat = generateCompdatForWell( timeline, eclipseCase, *well, date ) )
{
keywordBlocks["COMPDAT"] += wellCompdat;
mergeKeyword( keywordBlocks, "COMPDAT", std::move( *compdat ) );
}
generateMswForWell( timeline, eclipseCase, *well, date, keywordBlocks );
generateWellControlForWell( timeline, *well, date, keywordBlocks );
}
// Process schedule-level keyword events (not tied to a specific well)
// Schedule-level keyword events (not tied to a specific well)
auto events = timeline.getEventsAtDate( date );
for ( auto* event : events )
{
if ( event->eventType() == RimWellEvent::EventType::SCHEDULE_KEYWORD )
if ( event->eventType() != RimWellEvent::EventType::SCHEDULE_KEYWORD ) continue;
auto* keywordEvent = dynamic_cast<RimKeywordEvent*>( event );
if ( !keywordEvent ) continue;
if ( auto kw = keywordEvent->generateDeckKeyword( "" ) )
{
auto* keywordEvent = dynamic_cast<RimKeywordEvent*>( event );
if ( keywordEvent )
{
QString keywordStr = keywordEvent->generateScheduleKeyword( "" );
if ( !keywordStr.isEmpty() )
{
keywordBlocks[keywordEvent->keywordName().toUpper()] += keywordStr + "\n";
}
}
mergeKeyword( keywordBlocks, keywordEvent->keywordName().toUpper(), std::move( *kw ) );
}
}
auto appendKeywordText = [&]( const Opm::DeckKeyword& kw )
{
if ( kw.size() == 0 && !kw.isDataKeyword() ) return;
result += RimKeywordFactory::deckKeywordToString( kw );
result += "\n";
};
// Output keywords in priority order
std::set<QString> emitted;
for ( const auto& kw : keywordOrder )
{
auto it = keywordBlocks.find( kw );
if ( it != keywordBlocks.end() && !it->second.isEmpty() )
if ( it != keywordBlocks.end() )
{
result += it->second;
appendKeywordText( it->second );
emitted.insert( kw );
}
}
// Output remaining keywords not in priority list
for ( const auto& [kw, data] : keywordBlocks )
// Output remaining keywords not in the priority list
for ( const auto& [kw, deckKw] : keywordBlocks )
{
if ( emitted.find( kw ) == emitted.end() && !data.isEmpty() )
{
result += data;
}
if ( emitted.contains( kw ) ) continue;
appendKeywordText( deckKw );
}
return result;
@@ -188,12 +207,11 @@ QString RicScheduleDataGenerator::generateDateSection( const RimWellEventTimelin
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicScheduleDataGenerator::generateWelspecsForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date )
std::optional<Opm::DeckKeyword> RicScheduleDataGenerator::generateWelspecsForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date )
{
// Get perforation events at this exact date for this well
auto events = timeline.getEventsAtDate( date );
bool hasEvents = false;
@@ -208,27 +226,22 @@ QString RicScheduleDataGenerator::generateWelspecsForWell( const RimWellEventTim
}
}
if ( !hasEvents ) return QString();
if ( !hasEvents ) return std::nullopt;
std::string wellGroupName = well.completionSettings()->groupNameForExport().toStdString();
auto welspecsKw = RimKeywordFactory::welspecsKeyword( wellGroupName, &eclipseCase, &well );
QString result;
result += RimKeywordFactory::deckKeywordToString( welspecsKw );
result += "\n";
return result;
if ( welspecsKw.name().empty() ) return std::nullopt;
return welspecsKw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicScheduleDataGenerator::generateCompdatForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date )
std::optional<Opm::DeckKeyword> RicScheduleDataGenerator::generateCompdatForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date )
{
// Get perforation events at this exact date for this well
auto events = timeline.getEventsAtDate( date );
bool hasPerfEvents = false;
@@ -241,38 +254,32 @@ QString RicScheduleDataGenerator::generateCompdatForWell( const RimWellEventTime
}
}
if ( !hasPerfEvents ) return QString();
if ( !hasPerfEvents ) return std::nullopt;
auto compdata = RicWellPathExportCompletionDataFeatureImpl::completionDataForWellPath( &well, &eclipseCase, date );
auto wellName = well.completionSettings()->wellNameForExport().toStdString();
auto compdatKw = RimKeywordFactory::compdatKeyword( compdata, wellName );
QString result;
result += RimKeywordFactory::deckKeywordToString( compdatKw );
result += "\n";
return result;
auto compdatKw = RimKeywordFactory::compdatKeyword( compdata, wellName );
if ( compdatKw.name().empty() ) return std::nullopt;
return compdatKw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicScheduleDataGenerator::generateMswForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& wellPath,
const QDateTime& date,
std::map<QString, QString>& keywordBlocks )
void RicScheduleDataGenerator::generateMswForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& wellPath,
const QDateTime& date,
std::map<QString, Opm::DeckKeyword>& keywordBlocks )
{
// Check if the well has MSW configured (from any previous tubing events applied via set_timestamp)
// If MSW is enabled, we should generate WELSEGS/COMPSEGS instead of COMPDAT
auto* mswParams = wellPath.mswCompletionParameters();
if ( !mswParams )
{
return;
}
// Also check if there are valve or tubing events at this specific date for this well
// (these trigger updates to the MSW configuration)
// MSW is generated only when there are valve/tubing/perforation events at this exact date.
auto events = timeline.getEventsAtDate( date );
bool hasMswEvents = false;
bool hasPerfEvents = false;
@@ -290,15 +297,11 @@ void RicScheduleDataGenerator::generateMswForWell( const RimWellEventTimeline& t
}
}
// Only generate MSW output if there are events at this specific date for this well
// This ensures wells only appear in schedule sections at their event dates
if ( !hasMswEvents && !hasPerfEvents )
{
return;
}
// Extract MSW data using the existing infrastructure
// Pass the export date to filter valve/perforation output based on their creation dates
bool exportAfterMainBore = true;
auto mswDataResult = RicWellPathExportMswTableData::extractSingleWellMswData( &eclipseCase,
&wellPath,
@@ -310,77 +313,40 @@ void RicScheduleDataGenerator::generateMswForWell( const RimWellEventTimeline& t
const auto& mswData = mswDataResult.value();
// Generate WELSEGS keyword
int maxSegments = 0;
int maxBranches = 0;
Opm::DeckKeyword welsegsKw = RimKeywordFactory::welsegsKeyword( mswData, maxSegments, maxBranches );
if ( welsegsKw.isDataKeyword() || welsegsKw.size() > 0 )
{
keywordBlocks["WELSEGS"] += RimKeywordFactory::deckKeywordToString( welsegsKw ) + "\n";
}
int maxSegments = 0;
int maxBranches = 0;
auto welsegsKw = RimKeywordFactory::welsegsKeyword( mswData, maxSegments, maxBranches );
mergeKeyword( keywordBlocks, "WELSEGS", std::move( welsegsKw ) );
// Generate COMPSEGS keyword
Opm::DeckKeyword compsegsKw = RimKeywordFactory::compsegsKeyword( mswData );
if ( compsegsKw.isDataKeyword() || compsegsKw.size() > 0 )
{
keywordBlocks["COMPSEGS"] += RimKeywordFactory::deckKeywordToString( compsegsKw ) + "\n";
}
auto compsegsKw = RimKeywordFactory::compsegsKeyword( mswData );
mergeKeyword( keywordBlocks, "COMPSEGS", std::move( compsegsKw ) );
// Generate WSEGVALV keyword (for valve events)
Opm::DeckKeyword wsegvalvKw = RimKeywordFactory::wsegvalvKeyword( mswData );
if ( wsegvalvKw.isDataKeyword() || wsegvalvKw.size() > 0 )
{
keywordBlocks["WSEGVALV"] += RimKeywordFactory::deckKeywordToString( wsegvalvKw ) + "\n";
}
auto wsegvalvKw = RimKeywordFactory::wsegvalvKeyword( mswData );
mergeKeyword( keywordBlocks, "WSEGVALV", std::move( wsegvalvKw ) );
// Generate WSEGAICD keyword (if AICD data present)
Opm::DeckKeyword wsegaicdKw = RimKeywordFactory::wsegaicdKeyword( mswData );
if ( wsegaicdKw.isDataKeyword() || wsegaicdKw.size() > 0 )
{
keywordBlocks["WSEGAICD"] += RimKeywordFactory::deckKeywordToString( wsegaicdKw ) + "\n";
}
auto wsegaicdKw = RimKeywordFactory::wsegaicdKeyword( mswData );
mergeKeyword( keywordBlocks, "WSEGAICD", std::move( wsegaicdKw ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicScheduleDataGenerator::generateWellControlForWell( const RimWellEventTimeline& timeline,
const RimWellPath& well,
const QDateTime& date,
std::map<QString, QString>& keywordBlocks )
void RicScheduleDataGenerator::generateWellControlForWell( const RimWellEventTimeline& timeline,
const RimWellPath& well,
const QDateTime& date,
std::map<QString, Opm::DeckKeyword>& keywordBlocks )
{
// Get state and control events at this exact date for this well
auto events = timeline.getEventsAtDate( date );
for ( auto* event : events )
{
if ( event->wellName() != well.name() ) continue;
QString keywordStr = RifEventKeywordFormatter::formatWellEvent( event, well.name() );
if ( !keywordStr.isEmpty() )
{
QString kwName = extractKeywordName( keywordStr );
if ( !kwName.isEmpty() )
{
keywordBlocks[kwName] += keywordStr + "\n";
}
}
}
}
auto kw = RifEventKeywordFormatter::buildWellEvent( event, well.name() );
if ( !kw ) continue;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicScheduleDataGenerator::extractKeywordName( const QString& block )
{
const auto lines = block.split( '\n' );
for ( const auto& line : lines )
{
QString trimmed = line.trimmed();
if ( !trimmed.isEmpty() && !trimmed.startsWith( "--" ) )
{
return trimmed;
}
const QString name = QString::fromStdString( kw->name() );
if ( name.isEmpty() ) continue;
mergeKeyword( keywordBlocks, name, std::move( *kw ) );
}
return {};
}
@@ -22,6 +22,7 @@
#include <QString>
#include <map>
#include <optional>
#include <vector>
class RimEclipseCase;
@@ -29,6 +30,11 @@ class RimWellPath;
class RimWellEvent;
class RimWellEventTimeline;
namespace Opm
{
class DeckKeyword;
} // namespace Opm
//==================================================================================================
///
/// Generator for Eclipse schedule data based on well events
@@ -53,26 +59,26 @@ private:
const std::vector<RimWellPath*>& wellPaths,
const QDateTime& date );
static QString
static std::optional<Opm::DeckKeyword>
generateWelspecsForWell( const RimWellEventTimeline& timeline, RimEclipseCase& eclipseCase, RimWellPath& well, const QDateTime& date );
// Generate COMPDAT for a well at a specific date based on events
static QString
static std::optional<Opm::DeckKeyword>
generateCompdatForWell( const RimWellEventTimeline& timeline, RimEclipseCase& eclipseCase, RimWellPath& well, const QDateTime& date );
// Generate WELSEGS and COMPSEGS for a well at a specific date, populating keyword blocks map
static void generateMswForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date,
std::map<QString, QString>& keywordBlocks );
// Generate WELSEGS / COMPSEGS / WSEGVALV / WSEGAICD for a well at a specific date, merging into the accumulator
static void generateMswForWell( const RimWellEventTimeline& timeline,
RimEclipseCase& eclipseCase,
RimWellPath& well,
const QDateTime& date,
std::map<QString, Opm::DeckKeyword>& keywordBlocks );
// Generate well control keywords (WCONPROD, WCONINJE, WELOPEN) for a well at a specific date, populating keyword blocks map
static void generateWellControlForWell( const RimWellEventTimeline& timeline,
const RimWellPath& well,
const QDateTime& date,
std::map<QString, QString>& keywordBlocks );
// Generate well control / well keyword event keywords for a well at a specific date, merging into the accumulator
static void generateWellControlForWell( const RimWellEventTimeline& timeline,
const RimWellPath& well,
const QDateTime& date,
std::map<QString, Opm::DeckKeyword>& keywordBlocks );
// Extract keyword name from the first non-comment line of a keyword block
static QString extractKeywordName( const QString& block );
// Append records of `kw` into the entry for `name`, creating it from `kw` if absent
static void mergeKeyword( std::map<QString, Opm::DeckKeyword>& acc, const QString& name, Opm::DeckKeyword kw );
};
@@ -43,10 +43,23 @@
#include <unordered_map>
#include <unordered_set>
namespace
{
QString keywordToString( const Opm::DeckKeyword& kw )
{
if ( kw.name().empty() ) return {};
std::ostringstream oss;
Opm::DeckOutput out( oss, 10 );
kw.write( out );
return QString::fromStdString( oss.str() );
}
} // namespace
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEventKeywordFormatter::formatKeyword( const QString& keywordName, const std::vector<RimWellEventKeywordItem*>& items )
std::optional<Opm::DeckKeyword> RifEventKeywordFormatter::buildKeyword( const QString& keywordName,
const std::vector<RimWellEventKeywordItem*>& items )
{
QString keyword = keywordName.toUpper();
std::string kwName = keyword.toStdString();
@@ -185,29 +198,20 @@ QString RifEventKeywordFormatter::formatKeyword( const QString& keywordName, con
}
}
// Return empty string if keyword creation failed
if ( kw.name().empty() )
{
return "";
}
// Format with OPM DeckOutput
std::ostringstream oss;
Opm::DeckOutput out( oss, 10 );
kw.write( out );
return QString::fromStdString( oss.str() );
if ( kw.name().empty() ) return std::nullopt;
return kw;
}
catch ( const std::exception& e )
{
RiaLogging::error( std::format( "Failed to create keyword '{}': {}", keyword, e.what() ) );
return "";
return std::nullopt;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEventKeywordFormatter::formatWconprod( const RimWellEventControl* controlEvent, const QString& wellName )
std::optional<Opm::DeckKeyword> RifEventKeywordFormatter::buildWconprod( const RimWellEventControl* controlEvent, const QString& wellName )
{
using W = Opm::ParserKeywords::WCONPROD;
@@ -243,17 +247,13 @@ QString RifEventKeywordFormatter::formatWconprod( const RimWellEventControl* con
Opm::DeckKeyword kw{ W() };
kw.addRecord( Opm::DeckRecord{ std::move( items ) } );
std::ostringstream oss;
Opm::DeckOutput out( oss, 10 );
kw.write( out );
return QString::fromStdString( oss.str() );
return kw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEventKeywordFormatter::formatWconinje( const RimWellEventControl* controlEvent, const QString& wellName )
std::optional<Opm::DeckKeyword> RifEventKeywordFormatter::buildWconinje( const RimWellEventControl* controlEvent, const QString& wellName )
{
using W = Opm::ParserKeywords::WCONINJE;
@@ -281,41 +281,57 @@ QString RifEventKeywordFormatter::formatWconinje( const RimWellEventControl* con
Opm::DeckKeyword kw{ W() };
kw.addRecord( Opm::DeckRecord{ std::move( items ) } );
std::ostringstream oss;
Opm::DeckOutput out( oss, 10 );
kw.write( out );
return QString::fromStdString( oss.str() );
return kw;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RifEventKeywordFormatter::formatWellEvent( const RimWellEvent* event, const QString& wellName )
std::optional<Opm::DeckKeyword> RifEventKeywordFormatter::buildWellEvent( const RimWellEvent* event, const QString& wellName )
{
if ( event->eventType() == RimWellEvent::EventType::WCONTROL )
{
auto* controlEvent = dynamic_cast<const RimWellEventControl*>( event );
const auto* controlEvent = dynamic_cast<const RimWellEventControl*>( event );
if ( controlEvent )
{
if ( controlEvent->isProducer() )
{
return formatWconprod( controlEvent, wellName );
}
else
{
return formatWconinje( controlEvent, wellName );
}
return controlEvent->isProducer() ? buildWconprod( controlEvent, wellName ) : buildWconinje( controlEvent, wellName );
}
}
else if ( event->eventType() == RimWellEvent::EventType::KEYWORD )
{
auto* keywordEvent = dynamic_cast<const RimWellEventKeyword*>( event );
const auto* keywordEvent = dynamic_cast<const RimWellEventKeyword*>( event );
if ( keywordEvent )
{
return formatKeyword( keywordEvent->keywordName(), keywordEvent->items() );
return buildKeyword( keywordEvent->keywordName(), keywordEvent->items() );
}
}
return {};
return std::nullopt;
}
//--------------------------------------------------------------------------------------------------
/// QString-returning wrappers: build the keyword and serialize once.
//--------------------------------------------------------------------------------------------------
QString RifEventKeywordFormatter::formatKeyword( const QString& keywordName, const std::vector<RimWellEventKeywordItem*>& items )
{
auto kw = buildKeyword( keywordName, items );
return kw ? keywordToString( *kw ) : QString();
}
QString RifEventKeywordFormatter::formatWconprod( const RimWellEventControl* controlEvent, const QString& wellName )
{
auto kw = buildWconprod( controlEvent, wellName );
return kw ? keywordToString( *kw ) : QString();
}
QString RifEventKeywordFormatter::formatWconinje( const RimWellEventControl* controlEvent, const QString& wellName )
{
auto kw = buildWconinje( controlEvent, wellName );
return kw ? keywordToString( *kw ) : QString();
}
QString RifEventKeywordFormatter::formatWellEvent( const RimWellEvent* event, const QString& wellName )
{
auto kw = buildWellEvent( event, wellName );
return kw ? keywordToString( *kw ) : QString();
}
@@ -19,14 +19,27 @@
#pragma once
#include <QString>
#include <optional>
#include <vector>
namespace Opm
{
class DeckKeyword;
} // namespace Opm
class RimWellEventControl;
class RimWellEvent;
class RimWellEventKeywordItem;
namespace RifEventKeywordFormatter
{
// build*: produce a structured Opm::DeckKeyword (used by callers that merge records across wells).
std::optional<Opm::DeckKeyword> buildKeyword( const QString& keywordName, const std::vector<RimWellEventKeywordItem*>& items );
std::optional<Opm::DeckKeyword> buildWconprod( const RimWellEventControl* controlEvent, const QString& wellName );
std::optional<Opm::DeckKeyword> buildWconinje( const RimWellEventControl* controlEvent, const QString& wellName );
std::optional<Opm::DeckKeyword> buildWellEvent( const RimWellEvent* event, const QString& wellName );
// format*: serialize the build* result to text. Convenience for single-keyword stringification.
QString formatKeyword( const QString& keywordName, const std::vector<RimWellEventKeywordItem*>& items );
QString formatWconprod( const RimWellEventControl* controlEvent, const QString& wellName );
QString formatWconinje( const RimWellEventControl* controlEvent, const QString& wellName );
@@ -22,6 +22,8 @@
#include "FileInterface/RifEventKeywordFormatter.h"
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiOrdering.h"
@@ -133,6 +135,14 @@ QString RimKeywordEvent::generateScheduleKeyword( const QString& wellName ) cons
return RifEventKeywordFormatter::formatKeyword( m_keywordName(), items() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<Opm::DeckKeyword> RimKeywordEvent::generateDeckKeyword( const QString& wellName ) const
{
return RifEventKeywordFormatter::buildKeyword( m_keywordName(), items() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -22,8 +22,14 @@
#include "cafPdmField.h"
#include <optional>
#include <vector>
namespace Opm
{
class DeckKeyword;
} // namespace Opm
//==================================================================================================
///
/// Schedule-level keyword event - represents a schedule keyword with arbitrary keyword items
@@ -51,8 +57,9 @@ public:
std::vector<class RimWellEventKeywordItem*> items() const;
// Override from RimWellEvent
EventType eventType() const override { return EventType::SCHEDULE_KEYWORD; }
QString generateScheduleKeyword( const QString& wellName ) const override;
EventType eventType() const override { return EventType::SCHEDULE_KEYWORD; }
QString generateScheduleKeyword( const QString& wellName ) const override;
std::optional<Opm::DeckKeyword> generateDeckKeyword( const QString& wellName ) const;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
@@ -22,6 +22,8 @@
#include "FileInterface/RifEventKeywordFormatter.h"
#include "opm/input/eclipse/Deck/DeckKeyword.hpp"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiOrdering.h"
@@ -133,6 +135,14 @@ QString RimWellEventKeyword::generateScheduleKeyword( const QString& wellName )
return RifEventKeywordFormatter::formatKeyword( m_keywordName(), items() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::optional<Opm::DeckKeyword> RimWellEventKeyword::generateDeckKeyword( const QString& wellName ) const
{
return RifEventKeywordFormatter::buildKeyword( m_keywordName(), items() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -22,8 +22,14 @@
#include "cafPdmField.h"
#include <optional>
#include <vector>
namespace Opm
{
class DeckKeyword;
} // namespace Opm
//==================================================================================================
///
/// Well keyword event - represents a schedule keyword with arbitrary keyword items
@@ -50,8 +56,9 @@ public:
std::vector<class RimWellEventKeywordItem*> items() const;
// Override from RimWellEvent
EventType eventType() const override { return EventType::KEYWORD; }
QString generateScheduleKeyword( const QString& wellName ) const override;
EventType eventType() const override { return EventType::KEYWORD; }
QString generateScheduleKeyword( const QString& wellName ) const override;
std::optional<Opm::DeckKeyword> generateDeckKeyword( const QString& wellName ) const;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;