mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-30 17:10:19 -05:00
#13425 Add time-dependent well events and schedule data generation
Implement timeline-based event system for managing temporal changes in well completions, perforations, valves, and production controls. Features: - Event timeline container with date-based querying - Six event types: PERF, VALVE, TUBING, WSTATE, WTYPE, WCONTROL - Schedule keyword generation (DATES, COMPDAT, WELSEGS, WCONPROD, WCONINJE) - Multi-well schedule generation support - Python GRPC API for event management - YAML configuration file support - Comprehensive test suite Implementation: - New directory: ApplicationLibCode/ProjectDataModel/WellEvents/ - Event classes inherit from RimWellEvent base class - RimWellEventTimeline integrated into RimWellPath - RicScheduleDataGenerator for multi-well schedule export - Python API: event_timeline(), add_perf_event(), add_valve_event(), etc. - Tests verify all event types and YAML config parsing #13425 Add date tracking to valves and diameter/roughness intervals Add creation date fields to RimWellPathValve and RimDiameterRoughnessInterval to support filtering objects by date during completion data export. - Add m_useCustomStartDate and m_startDate fields - Add enableCustomStartDate(), setCustomStartDate(), isActiveOnDate() methods - Set creation dates when applying valve and tubing events in RimWellEventTimeline #13425 Add date-based filtering for schedule data export Add optional export date parameter to MSW data collection functions to filter valves and perforations based on their creation dates during schedule export. - Add exportDate parameter to collectWsegvalvData, collectWsegAicdData, collectWsegSicdData, and collectCompsegData functions - Filter valves by checking isActiveOnDate() on the associated RimWellPathValve - Add RimPerforationInterval reference to RicMswPerforation for date filtering - Pass export date from RicScheduleDataGenerator through the extraction chain This ensures segment numbers reflect the full model while only including objects active on the export date in output keywords. Add test to prove compsegs changes over time. #13425 Fix mypy type checking errors in well_events.py - Add type annotations to all function parameters - Fix generic type hints (dict -> Dict[str, Any]) - Import Any type for proper type safety - Add type: ignore for method reassignment - All 31 tests pass #13425 Add schedule-level keyword events for non-well-specific keywords Add a new event type called "Keyword Event" for schedule-level Eclipse keywords (RPTRST, GRUPTREE, RPTSCHED, etc.) that are NOT tied to a specific well path. This complements the existing RimWellEventKeyword which operates at the well level. - Add RimKeywordEvent class inheriting from RimWellEvent with null wellPath - Add SCHEDULE_KEYWORD enum value to EventType - Add addKeywordEvent() method to RimWellEventTimeline - Add AddKeywordEvent Python API method to RimcWellEventTimeline - Update RicScheduleDataGenerator to output global keywords after well sections - Add Python wrapper add_keyword_event() with type inference - Add tests and examples for RPTRST, GRUPTREE keywords
This commit is contained in:
1 parent
96eabcfd96
commit
a4dad97024
59 files changed
+7466
-77
No files matched your search
@@ -0,0 +1,30 @@
|
||||
set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEvent.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventPerf.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventValve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventTubing.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventState.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventType.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventControl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventKeyword.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventKeywordItem.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimKeywordEvent.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventTimeline.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEvent.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventPerf.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventValve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventTubing.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventState.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventType.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventControl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventKeyword.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventKeywordItem.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimKeywordEvent.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimWellEventTimeline.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
|
||||
@@ -0,0 +1,140 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimKeywordEvent.h"
|
||||
|
||||
#include "RimWellEventKeywordItem.h"
|
||||
|
||||
#include "FileInterface/RifEventKeywordFormatter.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiOrdering.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimKeywordEvent, "KeywordEvent" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimKeywordEvent::RimKeywordEvent()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Keyword Event", "", "", "KeywordEvent" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_keywordName, "KeywordName", QString(), "Keyword Name" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_items, "Items", "Items" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimKeywordEvent::~RimKeywordEvent()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimKeywordEvent::keywordName() const
|
||||
{
|
||||
return m_keywordName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::setKeywordName( const QString& keyword )
|
||||
{
|
||||
m_keywordName = keyword;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::addStringItem( const QString& name, const QString& value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setStringValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::addIntItem( const QString& name, int value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setIntValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::addDoubleItem( const QString& name, double value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setDoubleValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEventKeywordItem*> RimKeywordEvent::items() const
|
||||
{
|
||||
std::vector<RimWellEventKeywordItem*> result;
|
||||
for ( const auto& item : m_items )
|
||||
{
|
||||
if ( item.notNull() )
|
||||
{
|
||||
result.push_back( item.p() );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimKeywordEvent::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
return RifEventKeywordFormatter::formatKeyword( m_keywordName(), items() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_keywordName );
|
||||
uiOrdering.add( &m_items );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimKeywordEvent::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
uiTreeOrdering.add( &m_items );
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Schedule-level keyword event - represents a schedule keyword with arbitrary keyword items
|
||||
/// that is NOT tied to a specific well path (e.g., RPTRST, GRUPTREE, RPTSCHED)
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimKeywordEvent : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimKeywordEvent();
|
||||
~RimKeywordEvent() override;
|
||||
|
||||
// Keyword management
|
||||
QString keywordName() const;
|
||||
void setKeywordName( const QString& keyword );
|
||||
|
||||
// Item management
|
||||
void addStringItem( const QString& name, const QString& value );
|
||||
void addIntItem( const QString& name, int value );
|
||||
void addDoubleItem( const QString& name, double value );
|
||||
|
||||
std::vector<class RimWellEventKeywordItem*> items() const;
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override { return EventType::SCHEDULE_KEYWORD; }
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_keywordName;
|
||||
caf::PdmChildArrayField<class RimWellEventKeywordItem*> m_items;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiDateEditor.h"
|
||||
|
||||
CAF_PDM_ABSTRACT_SOURCE_INIT( RimWellEvent, "WellEvent" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::RimWellEvent()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well Event", "", "", "WellEvent" );
|
||||
|
||||
CAF_PDM_InitField( &m_eventDate, "EventDate", QDateTime(), "Event Date" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_wellPath, "WellPath", "Well Path" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::~RimWellEvent()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QDateTime RimWellEvent::eventDate() const
|
||||
{
|
||||
return m_eventDate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEvent::setEventDate( const QDateTime& date )
|
||||
{
|
||||
m_eventDate = date;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellPath* RimWellEvent::wellPath() const
|
||||
{
|
||||
return m_wellPath();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEvent::setWellPath( RimWellPath* wellPath )
|
||||
{
|
||||
m_wellPath = wellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEvent::wellName() const
|
||||
{
|
||||
if ( m_wellPath() )
|
||||
{
|
||||
return m_wellPath()->name();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEvent::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_wellPath );
|
||||
uiOrdering.add( &m_eventDate );
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
|
||||
class RimWellPath;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Base class for well events in a timeline-based event system
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEvent : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class EventType
|
||||
{
|
||||
PERF,
|
||||
VALVE,
|
||||
TUBING,
|
||||
WSTATE,
|
||||
WTYPE,
|
||||
WCONTROL,
|
||||
KEYWORD,
|
||||
SCHEDULE_KEYWORD
|
||||
};
|
||||
|
||||
RimWellEvent();
|
||||
~RimWellEvent() override;
|
||||
|
||||
QDateTime eventDate() const;
|
||||
void setEventDate( const QDateTime& date );
|
||||
|
||||
RimWellPath* wellPath() const;
|
||||
void setWellPath( RimWellPath* wellPath );
|
||||
QString wellName() const; // Convenience method to get well name
|
||||
|
||||
virtual EventType eventType() const = 0;
|
||||
virtual QString generateScheduleKeyword( const QString& wellName ) const = 0;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
protected:
|
||||
caf::PdmField<QDateTime> m_eventDate;
|
||||
caf::PdmPtrField<RimWellPath*> m_wellPath;
|
||||
};
|
||||
@@ -0,0 +1,382 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventControl.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventControl::ControlMode>::setUp()
|
||||
{
|
||||
addItem( RimWellEventControl::ControlMode::ORAT, "ORAT", "Oil Rate" );
|
||||
addItem( RimWellEventControl::ControlMode::WRAT, "WRAT", "Water Rate" );
|
||||
addItem( RimWellEventControl::ControlMode::GRAT, "GRAT", "Gas Rate" );
|
||||
addItem( RimWellEventControl::ControlMode::LRAT, "LRAT", "Liquid Rate" );
|
||||
addItem( RimWellEventControl::ControlMode::RESV, "RESV", "Reservoir Volume" );
|
||||
addItem( RimWellEventControl::ControlMode::BHP, "BHP", "BHP" );
|
||||
addItem( RimWellEventControl::ControlMode::THP, "THP", "THP" );
|
||||
setDefault( RimWellEventControl::ControlMode::ORAT );
|
||||
}
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventControl::WellStatus>::setUp()
|
||||
{
|
||||
addItem( RimWellEventControl::WellStatus::OPEN, "OPEN", "Open" );
|
||||
addItem( RimWellEventControl::WellStatus::SHUT, "SHUT", "Shut" );
|
||||
addItem( RimWellEventControl::WellStatus::STOP, "STOP", "Stop" );
|
||||
setDefault( RimWellEventControl::WellStatus::OPEN );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventControl, "WellEventControl" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventControl::RimWellEventControl()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well Control Event", "", "", "WellEventControl" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_controlMode, "ControlMode", caf::AppEnum<ControlMode>( ControlMode::ORAT ), "Control Mode" );
|
||||
CAF_PDM_InitScriptableField( &m_wellStatus, "WellStatus", caf::AppEnum<WellStatus>( WellStatus::OPEN ), "Well Status" );
|
||||
CAF_PDM_InitScriptableField( &m_controlValue, "ControlValue", 0.0, "Control Value" );
|
||||
CAF_PDM_InitScriptableField( &m_bhpLimit, "BhpLimit", 0.0, "BHP Limit [bar]" );
|
||||
CAF_PDM_InitScriptableField( &m_thpLimit, "ThpLimit", 0.0, "THP Limit [bar]" );
|
||||
CAF_PDM_InitScriptableField( &m_oilRate, "OilRate", 0.0, "Oil Rate [Sm3/day]" );
|
||||
CAF_PDM_InitScriptableField( &m_waterRate, "WaterRate", 0.0, "Water Rate [Sm3/day]" );
|
||||
CAF_PDM_InitScriptableField( &m_gasRate, "GasRate", 0.0, "Gas Rate [Sm3/day]" );
|
||||
CAF_PDM_InitScriptableField( &m_liquidRate, "LiquidRate", 0.0, "Liquid Rate [Sm3/day]" );
|
||||
CAF_PDM_InitScriptableField( &m_isProducer, "IsProducer", true, "Is Producer" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventControl::~RimWellEventControl()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventControl::ControlMode RimWellEventControl::controlMode() const
|
||||
{
|
||||
return m_controlMode();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventControl::WellStatus RimWellEventControl::wellStatus() const
|
||||
{
|
||||
return m_wellStatus();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::controlValue() const
|
||||
{
|
||||
return m_controlValue();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::bhpLimit() const
|
||||
{
|
||||
return m_bhpLimit();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::thpLimit() const
|
||||
{
|
||||
return m_thpLimit();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::oilRate() const
|
||||
{
|
||||
return m_oilRate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::waterRate() const
|
||||
{
|
||||
return m_waterRate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::gasRate() const
|
||||
{
|
||||
return m_gasRate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventControl::liquidRate() const
|
||||
{
|
||||
return m_liquidRate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventControl::isProducer() const
|
||||
{
|
||||
return m_isProducer();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setControlMode( ControlMode mode )
|
||||
{
|
||||
m_controlMode = mode;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setWellStatus( WellStatus status )
|
||||
{
|
||||
m_wellStatus = status;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setControlValue( double value )
|
||||
{
|
||||
m_controlValue = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setBhpLimit( double limit )
|
||||
{
|
||||
m_bhpLimit = limit;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setThpLimit( double limit )
|
||||
{
|
||||
m_thpLimit = limit;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setOilRate( double rate )
|
||||
{
|
||||
m_oilRate = rate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setWaterRate( double rate )
|
||||
{
|
||||
m_waterRate = rate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setGasRate( double rate )
|
||||
{
|
||||
m_gasRate = rate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setLiquidRate( double rate )
|
||||
{
|
||||
m_liquidRate = rate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::setIsProducer( bool isProducer )
|
||||
{
|
||||
m_isProducer = isProducer;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventControl::eventType() const
|
||||
{
|
||||
return EventType::WCONTROL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventControl::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
if ( m_isProducer() )
|
||||
{
|
||||
return generateWCONPROD( wellName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine injector type based on control mode or use water as default
|
||||
QString injectorType = "WATER";
|
||||
if ( m_controlMode() == ControlMode::GRAT )
|
||||
{
|
||||
injectorType = "GAS";
|
||||
}
|
||||
return generateWCONINJE( wellName, injectorType );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventControl::generateWCONPROD( const QString& wellName ) const
|
||||
{
|
||||
// WCONPROD format:
|
||||
// Well Status Ctrl OilRate WatRate GasRate LiqRate ResV BHP THP
|
||||
auto formatValue = []( double val ) -> QString
|
||||
{
|
||||
if ( val == 0.0 ) return "1*";
|
||||
return QString::number( val, 'f', 1 );
|
||||
};
|
||||
|
||||
QString line = QString( "WCONPROD\n" );
|
||||
line += QString( "-- Well Status Ctrl OilRate WatRate GasRate LiqRate ResV BHP THP\n" );
|
||||
line += QString( " %1 %2 %3 %4 %5 %6 %7 1* %8 %9 /\n" )
|
||||
.arg( wellName, -8 )
|
||||
.arg( m_wellStatus().text(), -4 )
|
||||
.arg( m_controlMode().text(), -4 )
|
||||
.arg( formatValue( m_oilRate() ), 8 )
|
||||
.arg( formatValue( m_waterRate() ), 8 )
|
||||
.arg( formatValue( m_gasRate() ), 8 )
|
||||
.arg( formatValue( m_liquidRate() ), 8 )
|
||||
.arg( formatValue( m_bhpLimit() ), 6 )
|
||||
.arg( formatValue( m_thpLimit() ), 6 );
|
||||
line += "/\n\n";
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventControl::generateWCONINJE( const QString& wellName, const QString& injectorType ) const
|
||||
{
|
||||
// WCONINJE format:
|
||||
// Well Type Status Ctrl Rate BHP
|
||||
QString ctrlStr;
|
||||
switch ( m_controlMode() )
|
||||
{
|
||||
case ControlMode::WRAT:
|
||||
ctrlStr = "RATE";
|
||||
break;
|
||||
case ControlMode::GRAT:
|
||||
ctrlStr = "RATE";
|
||||
break;
|
||||
case ControlMode::BHP:
|
||||
ctrlStr = "BHP";
|
||||
break;
|
||||
case ControlMode::THP:
|
||||
ctrlStr = "THP";
|
||||
break;
|
||||
default:
|
||||
ctrlStr = "RATE";
|
||||
break;
|
||||
}
|
||||
|
||||
auto formatValue = []( double val ) -> QString
|
||||
{
|
||||
if ( val == 0.0 ) return "1*";
|
||||
return QString::number( val, 'f', 1 );
|
||||
};
|
||||
|
||||
double rate = ( injectorType == "WATER" ) ? m_waterRate() : m_gasRate();
|
||||
|
||||
QString line = QString( "WCONINJE\n" );
|
||||
line += QString( "-- Well Type Status Ctrl Rate BHP\n" );
|
||||
line += QString( " %1 %2 %3 %4 %5 %6 /\n" )
|
||||
.arg( wellName, -8 )
|
||||
.arg( injectorType, -5 )
|
||||
.arg( m_wellStatus().text(), -4 )
|
||||
.arg( ctrlStr, -4 )
|
||||
.arg( formatValue( rate ), 10 )
|
||||
.arg( formatValue( m_bhpLimit() ), 8 );
|
||||
line += "/\n\n";
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_isProducer );
|
||||
uiOrdering.add( &m_wellStatus );
|
||||
uiOrdering.add( &m_controlMode );
|
||||
uiOrdering.add( &m_controlValue );
|
||||
|
||||
caf::PdmUiGroup* ratesGroup = uiOrdering.addNewGroup( "Rate Limits" );
|
||||
ratesGroup->add( &m_oilRate );
|
||||
ratesGroup->add( &m_waterRate );
|
||||
ratesGroup->add( &m_gasRate );
|
||||
ratesGroup->add( &m_liquidRate );
|
||||
|
||||
caf::PdmUiGroup* pressureGroup = uiOrdering.addNewGroup( "Pressure Limits" );
|
||||
pressureGroup->add( &m_bhpLimit );
|
||||
pressureGroup->add( &m_thpLimit );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventControl::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
QString typeStr = m_isProducer() ? "PROD" : "INJ";
|
||||
QString ctrlStr = m_controlMode().uiText();
|
||||
QString valueStr = QString::number( m_controlValue(), 'f', 0 );
|
||||
|
||||
setUiName( QString( "WCTRL %1: %2 %3 %4" ).arg( m_eventDate().toString( "yyyy-MM-dd" ) ).arg( typeStr ).arg( ctrlStr ).arg( valueStr ) );
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Well control event - defines production/injection control changes (WCONPROD/WCONINJE)
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventControl : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class ControlMode
|
||||
{
|
||||
ORAT, // Oil rate control
|
||||
WRAT, // Water rate control
|
||||
GRAT, // Gas rate control
|
||||
LRAT, // Liquid rate control
|
||||
RESV, // Reservoir volume rate control
|
||||
BHP, // Bottom hole pressure control
|
||||
THP // Tubing head pressure control
|
||||
};
|
||||
|
||||
enum class WellStatus
|
||||
{
|
||||
OPEN,
|
||||
SHUT,
|
||||
STOP
|
||||
};
|
||||
|
||||
RimWellEventControl();
|
||||
~RimWellEventControl() override;
|
||||
|
||||
// Getters
|
||||
ControlMode controlMode() const;
|
||||
WellStatus wellStatus() const;
|
||||
double controlValue() const;
|
||||
double bhpLimit() const;
|
||||
double thpLimit() const;
|
||||
double oilRate() const;
|
||||
double waterRate() const;
|
||||
double gasRate() const;
|
||||
double liquidRate() const;
|
||||
bool isProducer() const;
|
||||
|
||||
// Setters
|
||||
void setControlMode( ControlMode mode );
|
||||
void setWellStatus( WellStatus status );
|
||||
void setControlValue( double value );
|
||||
void setBhpLimit( double limit );
|
||||
void setThpLimit( double limit );
|
||||
void setOilRate( double rate );
|
||||
void setWaterRate( double rate );
|
||||
void setGasRate( double rate );
|
||||
void setLiquidRate( double rate );
|
||||
void setIsProducer( bool isProducer );
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
// Generate specific keywords
|
||||
QString generateWCONPROD( const QString& wellName ) const;
|
||||
QString generateWCONINJE( const QString& wellName, const QString& injectorType ) const;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::AppEnum<ControlMode>> m_controlMode;
|
||||
caf::PdmField<caf::AppEnum<WellStatus>> m_wellStatus;
|
||||
caf::PdmField<double> m_controlValue;
|
||||
caf::PdmField<double> m_bhpLimit;
|
||||
caf::PdmField<double> m_thpLimit;
|
||||
caf::PdmField<double> m_oilRate;
|
||||
caf::PdmField<double> m_waterRate;
|
||||
caf::PdmField<double> m_gasRate;
|
||||
caf::PdmField<double> m_liquidRate;
|
||||
caf::PdmField<bool> m_isProducer;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventControl::ControlMode>::setUp();
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventControl::WellStatus>::setUp();
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,140 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventKeyword.h"
|
||||
|
||||
#include "RimWellEventKeywordItem.h"
|
||||
|
||||
#include "FileInterface/RifEventKeywordFormatter.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiOrdering.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventKeyword, "WellEventKeyword" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeyword::RimWellEventKeyword()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well Keyword Event", "", "", "WellEventKeyword" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_keywordName, "KeywordName", QString(), "Keyword Name" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_items, "Items", "Items" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeyword::~RimWellEventKeyword()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventKeyword::keywordName() const
|
||||
{
|
||||
return m_keywordName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::setKeywordName( const QString& keyword )
|
||||
{
|
||||
m_keywordName = keyword;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::addStringItem( const QString& name, const QString& value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setStringValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::addIntItem( const QString& name, int value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setIntValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::addDoubleItem( const QString& name, double value )
|
||||
{
|
||||
auto* item = new RimWellEventKeywordItem();
|
||||
item->setItemName( name );
|
||||
item->setDoubleValue( value );
|
||||
m_items.push_back( item );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEventKeywordItem*> RimWellEventKeyword::items() const
|
||||
{
|
||||
std::vector<RimWellEventKeywordItem*> result;
|
||||
for ( const auto& item : m_items )
|
||||
{
|
||||
if ( item.notNull() )
|
||||
{
|
||||
result.push_back( item.p() );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventKeyword::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
return RifEventKeywordFormatter::formatKeyword( m_keywordName(), items() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_keywordName );
|
||||
uiOrdering.add( &m_items );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeyword::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
uiTreeOrdering.add( &m_items );
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Well keyword event - represents a schedule keyword with arbitrary keyword items
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventKeyword : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimWellEventKeyword();
|
||||
~RimWellEventKeyword() override;
|
||||
|
||||
// Keyword management
|
||||
QString keywordName() const;
|
||||
void setKeywordName( const QString& keyword );
|
||||
|
||||
// Item management
|
||||
void addStringItem( const QString& name, const QString& value );
|
||||
void addIntItem( const QString& name, int value );
|
||||
void addDoubleItem( const QString& name, double value );
|
||||
|
||||
std::vector<class RimWellEventKeywordItem*> items() const;
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override { return EventType::KEYWORD; }
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_keywordName;
|
||||
caf::PdmChildArrayField<class RimWellEventKeywordItem*> m_items;
|
||||
};
|
||||
@@ -0,0 +1,129 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventKeywordItem.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventKeywordItem, "RimWellEventKeywordItem" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeywordItem::RimWellEventKeywordItem()
|
||||
{
|
||||
CAF_PDM_InitObject( "Keyword Item", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_itemName, "ItemName", "Item Name" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_itemType, "ItemType", "Type" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_stringValue, "StringValue", "String Value" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_intValue, "IntValue", "Integer Value" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_doubleValue, "DoubleValue", "Double Value" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeywordItem::~RimWellEventKeywordItem()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventKeywordItem::itemName() const
|
||||
{
|
||||
return m_itemName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeywordItem::ItemType RimWellEventKeywordItem::itemType() const
|
||||
{
|
||||
return m_itemType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventKeywordItem::stringValue() const
|
||||
{
|
||||
return m_stringValue();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimWellEventKeywordItem::intValue() const
|
||||
{
|
||||
return m_intValue();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventKeywordItem::doubleValue() const
|
||||
{
|
||||
return m_doubleValue();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeywordItem::setItemName( const QString& name )
|
||||
{
|
||||
m_itemName = name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeywordItem::setStringValue( const QString& value )
|
||||
{
|
||||
m_itemType = ItemType::STRING;
|
||||
m_stringValue = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeywordItem::setIntValue( int value )
|
||||
{
|
||||
m_itemType = ItemType::INTEGER;
|
||||
m_intValue = value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventKeywordItem::setDoubleValue( double value )
|
||||
{
|
||||
m_itemType = ItemType::DOUBLE;
|
||||
m_doubleValue = value;
|
||||
}
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void AppEnum<RimWellEventKeywordItem::ItemType>::setUp()
|
||||
{
|
||||
addItem( RimWellEventKeywordItem::ItemType::STRING, "STRING", "String" );
|
||||
addItem( RimWellEventKeywordItem::ItemType::INTEGER, "INTEGER", "Integer" );
|
||||
addItem( RimWellEventKeywordItem::ItemType::DOUBLE, "DOUBLE", "Double" );
|
||||
setDefault( RimWellEventKeywordItem::ItemType::STRING );
|
||||
}
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,72 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
// A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Represents a single keyword item (field) with a name, type, and value
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventKeywordItem : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class ItemType
|
||||
{
|
||||
STRING,
|
||||
INTEGER,
|
||||
DOUBLE
|
||||
};
|
||||
|
||||
RimWellEventKeywordItem();
|
||||
~RimWellEventKeywordItem() override;
|
||||
|
||||
// Getters
|
||||
QString itemName() const;
|
||||
ItemType itemType() const;
|
||||
QString stringValue() const;
|
||||
int intValue() const;
|
||||
double doubleValue() const;
|
||||
|
||||
// Setters
|
||||
void setItemName( const QString& name );
|
||||
void setStringValue( const QString& value );
|
||||
void setIntValue( int value );
|
||||
void setDoubleValue( double value );
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_itemName;
|
||||
caf::PdmField<caf::AppEnum<ItemType>> m_itemType;
|
||||
caf::PdmField<QString> m_stringValue;
|
||||
caf::PdmField<int> m_intValue;
|
||||
caf::PdmField<double> m_doubleValue;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventKeywordItem::ItemType>::setUp();
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,199 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventPerf.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiDoubleSliderEditor.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventPerf::State>::setUp()
|
||||
{
|
||||
addItem( RimWellEventPerf::State::OPEN, "OPEN", "Open" );
|
||||
addItem( RimWellEventPerf::State::SHUT, "SHUT", "Shut" );
|
||||
setDefault( RimWellEventPerf::State::OPEN );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventPerf, "WellEventPerf" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventPerf::RimWellEventPerf()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Perforation Event", ":/PerforationInterval16x16.png", "", "WellEventPerf" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_startMD, "StartMd", 0.0, "Start MD" );
|
||||
CAF_PDM_InitScriptableField( &m_endMD, "EndMd", 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_state, "State", caf::AppEnum<State>( State::OPEN ), "State" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventPerf::~RimWellEventPerf()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventPerf::startMD() const
|
||||
{
|
||||
return m_startMD();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventPerf::endMD() const
|
||||
{
|
||||
return m_endMD();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventPerf::diameter() const
|
||||
{
|
||||
return m_diameter();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventPerf::skinFactor() const
|
||||
{
|
||||
return m_skinFactor();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventPerf::State RimWellEventPerf::state() const
|
||||
{
|
||||
return m_state();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::setStartMD( double md )
|
||||
{
|
||||
m_startMD = md;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::setEndMD( double md )
|
||||
{
|
||||
m_endMD = md;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::setDiameter( double diameter )
|
||||
{
|
||||
m_diameter = diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::setSkinFactor( double skinFactor )
|
||||
{
|
||||
m_skinFactor = skinFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::setState( State state )
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventPerf::eventType() const
|
||||
{
|
||||
return EventType::PERF;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventPerf::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
// Generate COMPDAT keyword line
|
||||
// COMPDAT format: Well I J K1 K2 Status SAT Trans Diam Kh Skin Dir
|
||||
// Note: Grid indices (I, J, K1, K2) require grid intersection calculation
|
||||
// This method generates a template that needs grid data to be complete
|
||||
|
||||
QString status = ( m_state() == State::OPEN ) ? "OPEN" : "SHUT";
|
||||
|
||||
QString line = QString( "-- %1 MD: %2 - %3, Diam: %4, Skin: %5, %6\n" )
|
||||
.arg( wellName )
|
||||
.arg( m_startMD(), 0, 'f', 2 )
|
||||
.arg( m_endMD(), 0, 'f', 2 )
|
||||
.arg( m_diameter(), 0, 'f', 4 )
|
||||
.arg( m_skinFactor(), 0, 'f', 2 )
|
||||
.arg( status );
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_startMD );
|
||||
uiOrdering.add( &m_endMD );
|
||||
uiOrdering.add( &m_diameter );
|
||||
uiOrdering.add( &m_skinFactor );
|
||||
uiOrdering.add( &m_state );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventPerf::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
QString stateStr = ( m_state() == State::OPEN ) ? "OPEN" : "SHUT";
|
||||
setUiName( QString( "PERF %1: %2 - %3 [%4]" )
|
||||
.arg( m_eventDate().toString( "yyyy-MM-dd" ) )
|
||||
.arg( m_startMD(), 0, 'f', 1 )
|
||||
.arg( m_endMD(), 0, 'f', 1 )
|
||||
.arg( stateStr ) );
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Perforation event - defines when a perforation interval opens or closes
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventPerf : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class State
|
||||
{
|
||||
OPEN,
|
||||
SHUT
|
||||
};
|
||||
|
||||
RimWellEventPerf();
|
||||
~RimWellEventPerf() override;
|
||||
|
||||
// Getters
|
||||
double startMD() const;
|
||||
double endMD() const;
|
||||
double diameter() const;
|
||||
double skinFactor() const;
|
||||
State state() const;
|
||||
|
||||
// Setters
|
||||
void setStartMD( double md );
|
||||
void setEndMD( double md );
|
||||
void setDiameter( double diameter );
|
||||
void setSkinFactor( double skinFactor );
|
||||
void setState( State state );
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_startMD;
|
||||
caf::PdmField<double> m_endMD;
|
||||
caf::PdmField<double> m_diameter;
|
||||
caf::PdmField<double> m_skinFactor;
|
||||
caf::PdmField<caf::AppEnum<State>> m_state;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventPerf::State>::setUp();
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,110 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventState.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventState::WellState>::setUp()
|
||||
{
|
||||
addItem( RimWellEventState::WellState::OPEN, "OPEN", "Open" );
|
||||
addItem( RimWellEventState::WellState::SHUT, "SHUT", "Shut" );
|
||||
addItem( RimWellEventState::WellState::STOP, "STOP", "Stop" );
|
||||
setDefault( RimWellEventState::WellState::OPEN );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventState, "WellEventState" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventState::RimWellEventState()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well State Event", "", "", "WellEventState" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_wellState, "WellState", caf::AppEnum<WellState>( WellState::OPEN ), "Well State" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventState::~RimWellEventState()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventState::WellState RimWellEventState::wellState() const
|
||||
{
|
||||
return m_wellState();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventState::setWellState( WellState state )
|
||||
{
|
||||
m_wellState = state;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventState::eventType() const
|
||||
{
|
||||
return EventType::WSTATE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventState::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
// Generate WELOPEN keyword
|
||||
QString line = QString( "WELOPEN\n %1 %2 /\n/\n\n" ).arg( wellName, -8 ).arg( m_wellState().text() );
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventState::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_wellState );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventState::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
setUiName( QString( "WSTATE %1: %2" ).arg( m_eventDate().toString( "yyyy-MM-dd" ) ).arg( m_wellState().text() ) );
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Well state event - defines when a well changes state (OPEN/SHUT/STOP)
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventState : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class WellState
|
||||
{
|
||||
OPEN,
|
||||
SHUT,
|
||||
STOP
|
||||
};
|
||||
|
||||
RimWellEventState();
|
||||
~RimWellEventState() override;
|
||||
|
||||
// Getters
|
||||
WellState wellState() const;
|
||||
|
||||
// Setters
|
||||
void setWellState( WellState state );
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::AppEnum<WellState>> m_wellState;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventState::WellState>::setUp();
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,593 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventTimeline.h"
|
||||
|
||||
#include "RimKeywordEvent.h"
|
||||
#include "RimWellEvent.h"
|
||||
#include "RimWellEventControl.h"
|
||||
#include "RimWellEventKeyword.h"
|
||||
#include "RimWellEventPerf.h"
|
||||
#include "RimWellEventState.h"
|
||||
#include "RimWellEventTubing.h"
|
||||
#include "RimWellEventType.h"
|
||||
#include "RimWellEventValve.h"
|
||||
|
||||
#include "RimDiameterRoughnessInterval.h"
|
||||
#include "RimDiameterRoughnessIntervalCollection.h"
|
||||
#include "RimMswCompletionParameters.h"
|
||||
#include "RimPerforationCollection.h"
|
||||
#include "RimPerforationInterval.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimTools.h"
|
||||
#include "RimValveTemplate.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
#include "RimWellPathValve.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventTimeline, "WellEventTimeline" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventTimeline::RimWellEventTimeline()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well Event Timeline", "", "", "WellEventTimeline" );
|
||||
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_events, "Events", "Events" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventTimeline::~RimWellEventTimeline()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEvent*> RimWellEventTimeline::events() const
|
||||
{
|
||||
return m_events.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QDateTime> RimWellEventTimeline::getAllEventDates() const
|
||||
{
|
||||
std::set<QDateTime> uniqueDates;
|
||||
|
||||
for ( const auto& event : m_events )
|
||||
{
|
||||
if ( event && event->eventDate().isValid() )
|
||||
{
|
||||
uniqueDates.insert( event->eventDate() );
|
||||
}
|
||||
}
|
||||
|
||||
return std::vector<QDateTime>( uniqueDates.begin(), uniqueDates.end() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEvent*> RimWellEventTimeline::getEventsAtDate( const QDateTime& date ) const
|
||||
{
|
||||
std::vector<RimWellEvent*> result;
|
||||
|
||||
for ( auto& event : m_events )
|
||||
{
|
||||
if ( event && event->eventDate() == date )
|
||||
{
|
||||
result.push_back( event );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEvent*> RimWellEventTimeline::getEventsByType( RimWellEvent::EventType type ) const
|
||||
{
|
||||
std::vector<RimWellEvent*> result;
|
||||
|
||||
for ( auto& event : m_events )
|
||||
{
|
||||
if ( event && event->eventType() == type )
|
||||
{
|
||||
result.push_back( event );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellEvent*> RimWellEventTimeline::getEventsUpToDate( const QDateTime& date ) const
|
||||
{
|
||||
std::vector<RimWellEvent*> result;
|
||||
|
||||
for ( auto& event : m_events )
|
||||
{
|
||||
if ( event && event->eventDate().isValid() && event->eventDate() <= date )
|
||||
{
|
||||
result.push_back( event );
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by date
|
||||
std::sort( result.begin(), result.end(), []( const RimWellEvent* a, const RimWellEvent* b ) { return a->eventDate() < b->eventDate(); } );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellPath*> RimWellEventTimeline::getWellPathsWithEvents() const
|
||||
{
|
||||
std::set<RimWellPath*> uniqueWellPaths;
|
||||
|
||||
for ( auto& event : m_events )
|
||||
{
|
||||
if ( event && event->wellPath() )
|
||||
{
|
||||
uniqueWellPaths.insert( event->wellPath() );
|
||||
}
|
||||
}
|
||||
|
||||
return std::vector<RimWellPath*>( uniqueWellPaths.begin(), uniqueWellPaths.end() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimWellPath*> RimWellEventTimeline::getWellPathsWithEventsUpToDate( const QDateTime& date ) const
|
||||
{
|
||||
std::set<RimWellPath*> uniqueWellPaths;
|
||||
|
||||
for ( auto& event : m_events )
|
||||
{
|
||||
if ( event && event->wellPath() && event->eventDate().isValid() && event->eventDate() <= date )
|
||||
{
|
||||
uniqueWellPaths.insert( event->wellPath() );
|
||||
}
|
||||
}
|
||||
|
||||
return std::vector<RimWellPath*>( uniqueWellPaths.begin(), uniqueWellPaths.end() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QDateTime RimWellEventTimeline::lastAppliedTimestamp() const
|
||||
{
|
||||
return m_lastAppliedTimestamp;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventPerf* RimWellEventTimeline::addPerforationEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventPerf();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventValve* RimWellEventTimeline::addValveEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventValve();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventTubing* RimWellEventTimeline::addTubingEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventTubing();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventState* RimWellEventTimeline::addStateEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventState();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventType* RimWellEventTimeline::addTypeEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventType();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventControl* RimWellEventTimeline::addControlEvent( RimWellPath* wellPath, const QDateTime& date )
|
||||
{
|
||||
auto* event = new RimWellEventControl();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventKeyword* RimWellEventTimeline::addWellKeywordEvent( RimWellPath* wellPath, const QDateTime& date, const QString& keywordName )
|
||||
{
|
||||
auto* event = new RimWellEventKeyword();
|
||||
event->setWellPath( wellPath );
|
||||
event->setEventDate( date );
|
||||
event->setKeywordName( keywordName );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimKeywordEvent* RimWellEventTimeline::addKeywordEvent( const QDateTime& date, const QString& keywordName )
|
||||
{
|
||||
auto* event = new RimKeywordEvent();
|
||||
// Note: wellPath is NOT set for schedule-level keyword events
|
||||
event->setEventDate( date );
|
||||
event->setKeywordName( keywordName );
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
return event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTimeline::addEvent( RimWellEvent* event )
|
||||
{
|
||||
if ( event )
|
||||
{
|
||||
m_events.push_back( event );
|
||||
updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTimeline::removeEvent( RimWellEvent* event )
|
||||
{
|
||||
m_events.removeChild( event );
|
||||
delete event;
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTimeline::clearAllEvents()
|
||||
{
|
||||
m_events.deleteChildren();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimWellEventTimeline::eventCount() const
|
||||
{
|
||||
return m_events.size();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventTimeline::applyEventsUpToDate( const QDateTime& date )
|
||||
{
|
||||
// Store the timestamp for later use in schedule generation
|
||||
m_lastAppliedTimestamp = date;
|
||||
|
||||
// Get events up to the specified date (already sorted by date)
|
||||
std::vector<RimWellEvent*> eventsToApply = getEventsUpToDate( date );
|
||||
|
||||
if ( eventsToApply.empty() )
|
||||
{
|
||||
return true; // Nothing to apply is not an error
|
||||
}
|
||||
|
||||
// Get the well path collection from the parent hierarchy
|
||||
auto* wellPathCollection = firstAncestorOrThisOfType<RimWellPathCollection>();
|
||||
if ( !wellPathCollection )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool anyEventApplied = false;
|
||||
|
||||
// Apply each event based on its type
|
||||
for ( RimWellEvent* event : eventsToApply )
|
||||
{
|
||||
bool success = applyEvent( wellPathCollection, event );
|
||||
if ( success )
|
||||
{
|
||||
anyEventApplied = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update views if any events were applied
|
||||
if ( anyEventApplied )
|
||||
{
|
||||
RimProject::current()->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
}
|
||||
|
||||
return anyEventApplied;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventTimeline::applyEvent( RimWellPathCollection* wellPathCollection, RimWellEvent* event )
|
||||
{
|
||||
// Find the well path by name
|
||||
if ( RimWellPath* wellPath = wellPathCollection->wellPathByName( event->wellName() ) )
|
||||
{
|
||||
switch ( event->eventType() )
|
||||
{
|
||||
case RimWellEvent::EventType::PERF:
|
||||
{
|
||||
if ( auto* perfEvent = dynamic_cast<RimWellEventPerf*>( event ) )
|
||||
{
|
||||
return applyPerfEvent( *perfEvent, *wellPath );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RimWellEvent::EventType::TUBING:
|
||||
{
|
||||
if ( auto* tubingEvent = dynamic_cast<RimWellEventTubing*>( event ) )
|
||||
{
|
||||
return applyTubingEvent( *tubingEvent, *wellPath );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RimWellEvent::EventType::VALVE:
|
||||
{
|
||||
if ( auto* valveEvent = dynamic_cast<RimWellEventValve*>( event ) )
|
||||
{
|
||||
return applyValveEvent( *valveEvent, *wellPath );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RimWellEvent::EventType::WSTATE:
|
||||
case RimWellEvent::EventType::WCONTROL:
|
||||
case RimWellEvent::EventType::WTYPE:
|
||||
// Skip WSTATE and WCONTROL events per requirements
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventTimeline::applyTubingEvent( const RimWellEventTubing& event, RimWellPath& wellPath )
|
||||
{
|
||||
auto* mswParams = wellPath.mswCompletionParameters();
|
||||
if ( !mswParams )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* intervalCollection = mswParams->diameterRoughnessIntervals();
|
||||
if ( !intervalCollection )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the diameter roughness mode to intervals
|
||||
mswParams->setDiameterRoughnessMode( RimMswCompletionParameters::DiameterRoughnessMode::INTERVALS );
|
||||
|
||||
// Create a new interval
|
||||
auto* interval = intervalCollection->createInterval( event.startMD(), event.endMD(), event.innerDiameter(), event.roughness() );
|
||||
|
||||
if ( interval )
|
||||
{
|
||||
// Set the custom start date based on the event date
|
||||
interval->enableCustomStartDate( true );
|
||||
interval->setCustomStartDate( event.eventDate().date() );
|
||||
|
||||
mswParams->updateConnectedEditors();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventTimeline::applyPerfEvent( const RimWellEventPerf& event, RimWellPath& wellPath )
|
||||
{
|
||||
auto* perfCollection = wellPath.perforationIntervalCollection();
|
||||
if ( !perfCollection )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new perforation interval
|
||||
auto* perfInterval = new RimPerforationInterval;
|
||||
perfInterval->setStartAndEndMD( event.startMD(), event.endMD() );
|
||||
perfInterval->setDiameter( event.diameter() );
|
||||
perfInterval->setSkinFactor( event.skinFactor() );
|
||||
perfInterval->setUnitSystemSpecificDefaults();
|
||||
|
||||
// Set the custom start date based on the event date
|
||||
perfInterval->enableCustomStartDate( true );
|
||||
perfInterval->setCustomStartDate( event.eventDate().date() );
|
||||
|
||||
perfCollection->appendPerforation( perfInterval );
|
||||
perfCollection->updateConnectedEditors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventTimeline::applyValveEvent( const RimWellEventValve& event, RimWellPath& wellPath )
|
||||
{
|
||||
auto* perfCollection = wellPath.perforationIntervalCollection();
|
||||
if ( !perfCollection )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto findByMeasuredDepth = []( const std::vector<RimPerforationInterval*>& perfs, double valveMD ) -> RimPerforationInterval*
|
||||
{
|
||||
for ( auto* perf : perfs )
|
||||
{
|
||||
if ( valveMD >= perf->startMD() && valveMD <= perf->endMD() ) return perf;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
// Find a perforation interval that contains this valve's measured depth
|
||||
std::vector<RimPerforationInterval*> perfs = perfCollection->perforationsNoConst();
|
||||
double valveMD = event.measuredDepth();
|
||||
RimPerforationInterval* targetPerf = findByMeasuredDepth( perfs, valveMD );
|
||||
|
||||
if ( !targetPerf )
|
||||
{
|
||||
// No matching perforation found - valve cannot be placed
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new valve
|
||||
auto* valve = new RimWellPathValve;
|
||||
|
||||
targetPerf->addValve( valve );
|
||||
|
||||
valve->setMeasuredDepthAndCount( valveMD, 0, 1 );
|
||||
|
||||
// Set the custom start date based on the event date
|
||||
valve->enableCustomStartDate( true );
|
||||
valve->setCustomStartDate( event.eventDate().date() );
|
||||
|
||||
auto convertToValveType = []( RimWellEventValve::ValveType valveType )
|
||||
{
|
||||
switch ( valveType )
|
||||
{
|
||||
case RimWellEventValve::ValveType::ICD:
|
||||
return RiaDefines::WellPathComponentType::ICD;
|
||||
case RimWellEventValve::ValveType::AICD:
|
||||
return RiaDefines::WellPathComponentType::AICD;
|
||||
case RimWellEventValve::ValveType::ICV:
|
||||
default:
|
||||
return RiaDefines::WellPathComponentType::ICV;
|
||||
}
|
||||
};
|
||||
|
||||
// Map the event valve type to the RiaDefines type and find a matching template
|
||||
RiaDefines::WellPathComponentType valveComponentType = convertToValveType( event.valveType() );
|
||||
|
||||
// Try to find a matching valve template
|
||||
if ( RimProject* project = RimProject::current() )
|
||||
{
|
||||
for ( auto* tmpl : project->allValveTemplates() )
|
||||
{
|
||||
if ( tmpl->type() == valveComponentType )
|
||||
{
|
||||
valve->setValveTemplate( tmpl );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetPerf->updateConnectedEditors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTimeline::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
setUiName( QString( "Event Timeline (%1 events)" ).arg( m_events.size() ) );
|
||||
|
||||
// Sort events by date for display
|
||||
std::vector<RimWellEvent*> sortedEvents = events();
|
||||
std::sort( sortedEvents.begin(),
|
||||
sortedEvents.end(),
|
||||
[]( const RimWellEvent* a, const RimWellEvent* b ) { return a->eventDate() < b->eventDate(); } );
|
||||
|
||||
for ( auto* event : sortedEvents )
|
||||
{
|
||||
uiTreeOrdering.add( event );
|
||||
}
|
||||
|
||||
uiTreeOrdering.skipRemainingChildren();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <vector>
|
||||
|
||||
class RimWellEventPerf;
|
||||
class RimWellEventValve;
|
||||
class RimWellEventTubing;
|
||||
class RimWellEventState;
|
||||
class RimWellEventType;
|
||||
class RimWellEventControl;
|
||||
class RimWellEventKeyword;
|
||||
class RimKeywordEvent;
|
||||
class RimWellPath;
|
||||
class RimWellPathCollection;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Timeline container for well events
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventTimeline : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimWellEventTimeline();
|
||||
~RimWellEventTimeline() override;
|
||||
|
||||
// Access all events
|
||||
std::vector<RimWellEvent*> events() const;
|
||||
|
||||
// Query methods
|
||||
std::vector<QDateTime> getAllEventDates() const;
|
||||
std::vector<RimWellEvent*> getEventsAtDate( const QDateTime& date ) const;
|
||||
std::vector<RimWellEvent*> getEventsByType( RimWellEvent::EventType type ) const;
|
||||
std::vector<RimWellEvent*> getEventsUpToDate( const QDateTime& date ) const;
|
||||
std::vector<RimWellPath*> getWellPathsWithEvents() const;
|
||||
std::vector<RimWellPath*> getWellPathsWithEventsUpToDate( const QDateTime& date ) const;
|
||||
|
||||
// Add event methods (return the created event for further configuration)
|
||||
RimWellEventPerf* addPerforationEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventValve* addValveEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventTubing* addTubingEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventState* addStateEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventType* addTypeEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventControl* addControlEvent( RimWellPath* wellPath, const QDateTime& date );
|
||||
RimWellEventKeyword* addWellKeywordEvent( RimWellPath* wellPath, const QDateTime& date, const QString& keywordName );
|
||||
RimKeywordEvent* addKeywordEvent( const QDateTime& date, const QString& keywordName );
|
||||
|
||||
// Generic add event method
|
||||
void addEvent( RimWellEvent* event );
|
||||
|
||||
// Remove event
|
||||
void removeEvent( RimWellEvent* event );
|
||||
|
||||
// Clear all events
|
||||
void clearAllEvents();
|
||||
|
||||
// Get count
|
||||
size_t eventCount() const;
|
||||
|
||||
// Apply events up to a given date (creates actual completions from event data)
|
||||
bool applyEventsUpToDate( const QDateTime& date );
|
||||
|
||||
// Get the last applied timestamp (returns invalid QDateTime if no timestamp was set)
|
||||
QDateTime lastAppliedTimestamp() const;
|
||||
|
||||
protected:
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
bool applyEvent( RimWellPathCollection* wellPathCollection, RimWellEvent* event );
|
||||
|
||||
bool applyTubingEvent( const RimWellEventTubing& event, RimWellPath& wellPath );
|
||||
bool applyPerfEvent( const RimWellEventPerf& event, RimWellPath& wellPath );
|
||||
bool applyValveEvent( const RimWellEventValve& event, RimWellPath& wellPath );
|
||||
|
||||
caf::PdmChildArrayField<RimWellEvent*> m_events;
|
||||
QDateTime m_lastAppliedTimestamp;
|
||||
};
|
||||
@@ -0,0 +1,162 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventTubing.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventTubing, "WellEventTubing" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventTubing::RimWellEventTubing()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Tubing Event", "", "", "WellEventTubing" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_startMD, "StartMd", 0.0, "Start MD" );
|
||||
CAF_PDM_InitScriptableField( &m_endMD, "EndMd", 0.0, "End MD" );
|
||||
CAF_PDM_InitScriptableField( &m_innerDiameter, "InnerDiameter", 0.15, "Inner Diameter [m]" );
|
||||
CAF_PDM_InitScriptableField( &m_roughness, "Roughness", 1.0e-5, "Roughness [m]" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventTubing::~RimWellEventTubing()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventTubing::startMD() const
|
||||
{
|
||||
return m_startMD();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventTubing::endMD() const
|
||||
{
|
||||
return m_endMD();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventTubing::innerDiameter() const
|
||||
{
|
||||
return m_innerDiameter();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventTubing::roughness() const
|
||||
{
|
||||
return m_roughness();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::setStartMD( double md )
|
||||
{
|
||||
m_startMD = md;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::setEndMD( double md )
|
||||
{
|
||||
m_endMD = md;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::setInnerDiameter( double diameter )
|
||||
{
|
||||
m_innerDiameter = diameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::setRoughness( double roughness )
|
||||
{
|
||||
m_roughness = roughness;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventTubing::eventType() const
|
||||
{
|
||||
return EventType::TUBING;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventTubing::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
// Generate a comment line describing the tubing change
|
||||
// Actual WELSEGS segment data requires grid calculations
|
||||
QString line = QString( "-- %1 TUBING: MD %2 - %3, Diam: %4 m, Rough: %5 m\n" )
|
||||
.arg( wellName )
|
||||
.arg( m_startMD(), 0, 'f', 2 )
|
||||
.arg( m_endMD(), 0, 'f', 2 )
|
||||
.arg( m_innerDiameter(), 0, 'f', 4 )
|
||||
.arg( m_roughness(), 0, 'e', 3 );
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_startMD );
|
||||
uiOrdering.add( &m_endMD );
|
||||
uiOrdering.add( &m_innerDiameter );
|
||||
uiOrdering.add( &m_roughness );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventTubing::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
setUiName( QString( "TUBING %1: %2 - %3 (D: %4 m)" )
|
||||
.arg( m_eventDate().toString( "yyyy-MM-dd" ) )
|
||||
.arg( m_startMD(), 0, 'f', 1 )
|
||||
.arg( m_endMD(), 0, 'f', 1 )
|
||||
.arg( m_innerDiameter(), 0, 'f', 3 ) );
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Tubing event - defines changes to tubing/liner diameter and roughness
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventTubing : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimWellEventTubing();
|
||||
~RimWellEventTubing() override;
|
||||
|
||||
// Getters
|
||||
double startMD() const;
|
||||
double endMD() const;
|
||||
double innerDiameter() const;
|
||||
double roughness() const;
|
||||
|
||||
// Setters
|
||||
void setStartMD( double md );
|
||||
void setEndMD( double md );
|
||||
void setInnerDiameter( double diameter );
|
||||
void setRoughness( double roughness );
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_startMD;
|
||||
caf::PdmField<double> m_endMD;
|
||||
caf::PdmField<double> m_innerDiameter;
|
||||
caf::PdmField<double> m_roughness;
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventType.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventType::WellType>::setUp()
|
||||
{
|
||||
addItem( RimWellEventType::WellType::OIL_PRODUCER, "OIL_PRODUCER", "Oil Producer" );
|
||||
addItem( RimWellEventType::WellType::GAS_PRODUCER, "GAS_PRODUCER", "Gas Producer" );
|
||||
addItem( RimWellEventType::WellType::WATER_PRODUCER, "WATER_PRODUCER", "Water Producer" );
|
||||
addItem( RimWellEventType::WellType::WATER_INJECTOR, "WATER_INJECTOR", "Water Injector" );
|
||||
addItem( RimWellEventType::WellType::GAS_INJECTOR, "GAS_INJECTOR", "Gas Injector" );
|
||||
setDefault( RimWellEventType::WellType::OIL_PRODUCER );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventType, "WellEventType" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventType::RimWellEventType()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Well Type Event", "", "", "WellEventType" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_wellType, "WellType", caf::AppEnum<WellType>( WellType::OIL_PRODUCER ), "Well Type" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventType::~RimWellEventType()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventType::WellType RimWellEventType::wellType() const
|
||||
{
|
||||
return m_wellType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventType::setWellType( WellType type )
|
||||
{
|
||||
m_wellType = type;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventType::isProducer() const
|
||||
{
|
||||
return m_wellType() == WellType::OIL_PRODUCER || m_wellType() == WellType::GAS_PRODUCER || m_wellType() == WellType::WATER_PRODUCER;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellEventType::isInjector() const
|
||||
{
|
||||
return m_wellType() == WellType::WATER_INJECTOR || m_wellType() == WellType::GAS_INJECTOR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventType::eventType() const
|
||||
{
|
||||
return EventType::WTYPE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventType::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
// Generate a comment about well type - actual well type specification
|
||||
// typically appears in WELSPECS which is defined once at simulation start
|
||||
QString typeStr;
|
||||
switch ( m_wellType() )
|
||||
{
|
||||
case WellType::OIL_PRODUCER:
|
||||
typeStr = "OIL PRODUCER";
|
||||
break;
|
||||
case WellType::GAS_PRODUCER:
|
||||
typeStr = "GAS PRODUCER";
|
||||
break;
|
||||
case WellType::WATER_PRODUCER:
|
||||
typeStr = "WATER PRODUCER";
|
||||
break;
|
||||
case WellType::WATER_INJECTOR:
|
||||
typeStr = "WATER INJECTOR";
|
||||
break;
|
||||
case WellType::GAS_INJECTOR:
|
||||
typeStr = "GAS INJECTOR";
|
||||
break;
|
||||
}
|
||||
|
||||
QString line = QString( "-- %1 WELL TYPE: %2\n" ).arg( wellName ).arg( typeStr );
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventType::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_wellType );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventType::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
QString typeStr;
|
||||
switch ( m_wellType() )
|
||||
{
|
||||
case WellType::OIL_PRODUCER:
|
||||
typeStr = "OIL PROD";
|
||||
break;
|
||||
case WellType::GAS_PRODUCER:
|
||||
typeStr = "GAS PROD";
|
||||
break;
|
||||
case WellType::WATER_PRODUCER:
|
||||
typeStr = "WAT PROD";
|
||||
break;
|
||||
case WellType::WATER_INJECTOR:
|
||||
typeStr = "WAT INJ";
|
||||
break;
|
||||
case WellType::GAS_INJECTOR:
|
||||
typeStr = "GAS INJ";
|
||||
break;
|
||||
}
|
||||
|
||||
setUiName( QString( "WTYPE %1: %2" ).arg( m_eventDate().toString( "yyyy-MM-dd" ) ).arg( typeStr ) );
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Well type event - defines when a well changes type (producer/injector)
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventType : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class WellType
|
||||
{
|
||||
OIL_PRODUCER,
|
||||
GAS_PRODUCER,
|
||||
WATER_PRODUCER,
|
||||
WATER_INJECTOR,
|
||||
GAS_INJECTOR
|
||||
};
|
||||
|
||||
RimWellEventType();
|
||||
~RimWellEventType() override;
|
||||
|
||||
// Getters
|
||||
WellType wellType() const;
|
||||
|
||||
// Setters
|
||||
void setWellType( WellType type );
|
||||
|
||||
// Helper methods
|
||||
bool isProducer() const;
|
||||
bool isInjector() const;
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<caf::AppEnum<WellType>> m_wellType;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventType::WellType>::setUp();
|
||||
} // namespace caf
|
||||
@@ -0,0 +1,273 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimWellEventValve.h"
|
||||
|
||||
#include "RimProject.h"
|
||||
#include "RimValveTemplate.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafPdmObjectScriptingCapability.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventValve::State>::setUp()
|
||||
{
|
||||
addItem( RimWellEventValve::State::OPEN, "OPEN", "Open" );
|
||||
addItem( RimWellEventValve::State::SHUT, "SHUT", "Shut" );
|
||||
setDefault( RimWellEventValve::State::OPEN );
|
||||
}
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventValve::ValveType>::setUp()
|
||||
{
|
||||
addItem( RimWellEventValve::ValveType::ICV, "ICV", "ICV" );
|
||||
addItem( RimWellEventValve::ValveType::ICD, "ICD", "ICD" );
|
||||
addItem( RimWellEventValve::ValveType::AICD, "AICD", "AICD" );
|
||||
setDefault( RimWellEventValve::ValveType::ICV );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimWellEventValve, "WellEventValve" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventValve::RimWellEventValve()
|
||||
{
|
||||
CAF_PDM_InitScriptableObject( "Valve Event", ":/ICVValve16x16.png", "", "WellEventValve" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_measuredDepth, "MeasuredDepth", 0.0, "Measured Depth" );
|
||||
CAF_PDM_InitScriptableField( &m_valveType, "ValveType", caf::AppEnum<ValveType>( ValveType::ICV ), "Valve Type" );
|
||||
CAF_PDM_InitScriptableField( &m_state, "State", caf::AppEnum<State>( State::OPEN ), "State" );
|
||||
CAF_PDM_InitScriptableField( &m_flowCoefficient, "FlowCoefficient", 0.7, "Flow Coefficient" );
|
||||
CAF_PDM_InitScriptableField( &m_area, "Area", 0.0001, "Area [m2]" );
|
||||
CAF_PDM_InitScriptableFieldNoDefault( &m_valveTemplate, "ValveTemplate", "Valve Template" );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventValve::~RimWellEventValve()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventValve::measuredDepth() const
|
||||
{
|
||||
return m_measuredDepth();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventValve::ValveType RimWellEventValve::valveType() const
|
||||
{
|
||||
return m_valveType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEventValve::State RimWellEventValve::state() const
|
||||
{
|
||||
return m_state();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventValve::flowCoefficient() const
|
||||
{
|
||||
if ( m_valveTemplate() )
|
||||
{
|
||||
return m_valveTemplate()->flowCoefficient();
|
||||
}
|
||||
return m_flowCoefficient();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RimWellEventValve::area() const
|
||||
{
|
||||
return m_area();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimValveTemplate* RimWellEventValve::valveTemplate() const
|
||||
{
|
||||
return m_valveTemplate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setMeasuredDepth( double md )
|
||||
{
|
||||
m_measuredDepth = md;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setValveType( ValveType type )
|
||||
{
|
||||
m_valveType = type;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setState( State state )
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setFlowCoefficient( double coefficient )
|
||||
{
|
||||
m_flowCoefficient = coefficient;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setArea( double area )
|
||||
{
|
||||
m_area = area;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::setValveTemplate( RimValveTemplate* valveTemplate )
|
||||
{
|
||||
m_valveTemplate = valveTemplate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellEvent::EventType RimWellEventValve::eventType() const
|
||||
{
|
||||
return EventType::VALVE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellEventValve::generateScheduleKeyword( const QString& wellName ) const
|
||||
{
|
||||
// Generate WSEGVALV keyword line for valve events
|
||||
// WSEGVALV format: Well Seg CV Ac
|
||||
QString line = QString( "-- %1 %2 at MD: %3, CV: %4, Area: %5, %6\n" )
|
||||
.arg( wellName )
|
||||
.arg( m_valveType().text() )
|
||||
.arg( m_measuredDepth(), 0, 'f', 2 )
|
||||
.arg( flowCoefficient(), 0, 'f', 3 )
|
||||
.arg( m_area(), 0, 'e', 3 )
|
||||
.arg( m_state().text() );
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimWellEvent::defineUiOrdering( uiConfigName, uiOrdering );
|
||||
|
||||
uiOrdering.add( &m_valveType );
|
||||
uiOrdering.add( &m_measuredDepth );
|
||||
uiOrdering.add( &m_state );
|
||||
uiOrdering.add( &m_valveTemplate );
|
||||
|
||||
bool hasTemplate = m_valveTemplate() != nullptr;
|
||||
m_flowCoefficient.uiCapability()->setUiReadOnly( hasTemplate );
|
||||
|
||||
uiOrdering.add( &m_flowCoefficient );
|
||||
uiOrdering.add( &m_area );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellEventValve::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName )
|
||||
{
|
||||
QString stateStr = ( m_state() == State::OPEN ) ? "OPEN" : "SHUT";
|
||||
QString valveTypeStr;
|
||||
switch ( m_valveType() )
|
||||
{
|
||||
case ValveType::ICV:
|
||||
valveTypeStr = "ICV";
|
||||
setUiIconFromResourceString( ":/ICVValve16x16.png" );
|
||||
break;
|
||||
case ValveType::ICD:
|
||||
valveTypeStr = "ICD";
|
||||
setUiIconFromResourceString( ":/ICDValve16x16.png" );
|
||||
break;
|
||||
case ValveType::AICD:
|
||||
valveTypeStr = "AICD";
|
||||
setUiIconFromResourceString( ":/AICDValve16x16.png" );
|
||||
break;
|
||||
}
|
||||
|
||||
setUiName( QString( "%1 %2: MD %3 [%4]" )
|
||||
.arg( valveTypeStr )
|
||||
.arg( m_eventDate().toString( "yyyy-MM-dd" ) )
|
||||
.arg( m_measuredDepth(), 0, 'f', 1 )
|
||||
.arg( stateStr ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimWellEventValve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_valveTemplate )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
|
||||
RimProject* project = RimProject::current();
|
||||
if ( project )
|
||||
{
|
||||
std::vector<RimValveTemplate*> allTemplates = project->allValveTemplates();
|
||||
for ( RimValveTemplate* valveTemplate : allTemplates )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( valveTemplate->name(), valveTemplate ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RimWellEvent.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimValveTemplate;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Valve event - defines when a valve opens or closes
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimWellEventValve : public RimWellEvent
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class State
|
||||
{
|
||||
OPEN,
|
||||
SHUT
|
||||
};
|
||||
|
||||
enum class ValveType
|
||||
{
|
||||
ICV,
|
||||
ICD,
|
||||
AICD
|
||||
};
|
||||
|
||||
RimWellEventValve();
|
||||
~RimWellEventValve() override;
|
||||
|
||||
// Getters
|
||||
double measuredDepth() const;
|
||||
ValveType valveType() const;
|
||||
State state() const;
|
||||
double flowCoefficient() const;
|
||||
double area() const;
|
||||
RimValveTemplate* valveTemplate() const;
|
||||
|
||||
// Setters
|
||||
void setMeasuredDepth( double md );
|
||||
void setValveType( ValveType type );
|
||||
void setState( State state );
|
||||
void setFlowCoefficient( double coefficient );
|
||||
void setArea( double area );
|
||||
void setValveTemplate( RimValveTemplate* valveTemplate );
|
||||
|
||||
// Override from RimWellEvent
|
||||
EventType eventType() const override;
|
||||
QString generateScheduleKeyword( const QString& wellName ) const override;
|
||||
|
||||
protected:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<double> m_measuredDepth;
|
||||
caf::PdmField<caf::AppEnum<ValveType>> m_valveType;
|
||||
caf::PdmField<caf::AppEnum<State>> m_state;
|
||||
caf::PdmField<double> m_flowCoefficient;
|
||||
caf::PdmField<double> m_area;
|
||||
caf::PdmPtrField<RimValveTemplate*> m_valveTemplate;
|
||||
};
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventValve::State>::setUp();
|
||||
|
||||
template <>
|
||||
void caf::AppEnum<RimWellEventValve::ValveType>::setUp();
|
||||
} // namespace caf
|
||||
Reference in new issue
Block a user