Merge pull request #506 from joakim-hove/schedule-events

Schedule events
This commit is contained in:
Joakim Hove
2015-07-24 14:21:20 +02:00
22 changed files with 569 additions and 131 deletions

View File

@@ -95,6 +95,7 @@ EclipseState/Schedule/ScheduleEnums.cpp
EclipseState/Schedule/GroupTreeNode.cpp
EclipseState/Schedule/GroupTree.cpp
EclipseState/Schedule/Tuning.cpp
EclipseState/Schedule/Events.cpp
#
EclipseState/Tables/SingleRecordTable.cpp
EclipseState/Tables/MultiRecordTable.cpp
@@ -181,6 +182,7 @@ EclipseState/Schedule/ScheduleEnums.hpp
EclipseState/Schedule/GroupTreeNode.hpp
EclipseState/Schedule/GroupTree.hpp
EclipseState/Schedule/Tuning.hpp
EclipseState/Schedule/Events.hpp
#
EclipseState/Util/ElasticVector.hpp
EclipseState/Util/OrderedMap.hpp

View File

@@ -143,7 +143,7 @@ namespace Opm {
m_restart_output_config->globalReset(rs);
}
else {
m_restart_output_config->add(timestep, rs);
m_restart_output_config->update(timestep, rs);
}
}
@@ -169,7 +169,7 @@ namespace Opm {
rs.timestep = timestep;
rs.basic = (restart == 0) ? 0 : 1;
m_restart_output_config->add(timestep, rs);
m_restart_output_config->update(timestep, rs);
}

View File

@@ -29,6 +29,29 @@
namespace Opm {
/**
The DynamicState<T> class is designed to hold information about
properties with the following semantics:
1. The property can be updated repeatedly at different
timesteps; observe that the class does not support
operator[] - only updates with weakly increasing timesteps
are supported.
2. At any point in the time the previous last set value
applies.
The class is very much tailored to support the Schedule file of
Eclipse where a control applied at time T will apply
indefinitely, or until explicitly set to a different value.
The update() method returns true if the updated value is
different from the current value, this implies that the
class<T> must support operator!=
*/
template <class T>
class DynamicState {
public:
@@ -88,27 +111,34 @@ namespace Opm {
}
void add(size_t index , T value) {
/**
If the current value has been changed the method will
return true, otherwise it will return false.
*/
bool update(size_t index , T value) {
bool change = (value != m_currentValue);
if (index >= (m_timeMap->size()))
throw std::range_error("Index value is out range.");
if (m_data.size() > 0) {
if (m_data.size() > 0) {
if (index < (m_data.size() - 1))
throw std::invalid_argument("Elements must be added in weakly increasing order");
}
{
size_t currentSize = m_data.size();
if (currentSize <= index) {
for (size_t i = currentSize; i <= index; i++)
m_data.push_back( m_currentValue );
}
}
{
size_t currentSize = m_data.size();
if (currentSize <= index) {
for (size_t i = currentSize; i <= index; i++)
m_data.push_back( m_currentValue );
}
}
m_data[index] = value;
m_currentValue = value;
if (m_initialRange == 0)
m_initialRange = index;
m_data[index] = value;
m_currentValue = value;
if (m_initialRange == 0)
m_initialRange = index;
return change;
}

View File

@@ -0,0 +1,49 @@
/*
Copyright 2015 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM 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.
OPM 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 for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstddef>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
namespace Opm {
Events::Events() {
}
bool Events::hasEvent(ScheduleEvents::Events event, size_t reportStep) const {
if (reportStep < m_events.size()) {
uint64_t eventSum = m_events[reportStep];
if (eventSum & event)
return true;
else
return false;
} else
return false;
}
void Events::addEvent(ScheduleEvents::Events event, size_t reportStep) {
if (m_events.size() <= reportStep)
m_events.resize( 2 * reportStep + 1 );
m_events[reportStep] |= event;
}
}

View File

@@ -0,0 +1,95 @@
/*
Copyright 2015 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM 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.
OPM 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 for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCHEDULE_EVENTS_HPP
#define SCHEDULE_EVENTS_HPP
#include <cstdint>
#include <vector>
namespace Opm
{
namespace ScheduleEvents {
// These values are used as bitmask - 2^n structure is essential.
enum Events {
/* The NEW_WELL event is triggered by the WELSPECS
keyword. */
NEW_WELL = 1,
/*
The NEW_GROUP event is triggered by the WELSPECS and
GRUPTREE keywords.
*/
NEW_GROUP = 2,
/*
The PRODUCTION_UPDATE event is triggered by the
WCONPROD and WCONHIST keywords. The event will be
triggered if *any* of the elements in one of keywords
is changed. Quite simlar for INJECTION_UPDATE and
POLYMER_UPDATE.
*/
PRODUCTION_UPDATE = 4,
INJECTION_UPDATE = 8,
POLYMER_UPDATES = 16,
/*
This event is triggered if the well status is changed
between {OPEN,SHUT,STOP,AUTO}. There are many keywords
which can trigger a well status change.
*/
WELL_STATUS_CHANGE = 32,
/*
COMPDAT and WELOPEN
*/
COMPLETION_CHANGE = 64,
/*
The well group topolyg has changed.
*/
GROUP_CHANGE = 128
};
}
/*
This class implements a simple system for recording when various
events happen in the Schedule file. The purpose of the class is
that downstream code can query this system whether a certain a
event has taken place, and then perform potentially expensive
calculations conditionally:
auto events = schedule->getEvents();
if (events.hasEvent(SchedulEvents::NEW_WELL , reportStep))
// Perform expensive calculation which must be performed
// when a new well is introduced.
...
*/
class Events {
public:
Events();
void addEvent(ScheduleEvents::Events event, size_t reportStep);
bool hasEvent(ScheduleEvents::Events event, size_t reportStep) const;
private:
std::vector<uint64_t> m_events;
};
}
#endif

View File

@@ -115,7 +115,7 @@ namespace Opm {
}
void Group::setProductionGroup(size_t timeStep, bool isProductionGroup_) {
m_isProductionGroup->add(timeStep, isProductionGroup_);
m_isProductionGroup->update(timeStep, isProductionGroup_);
}
@@ -146,7 +146,7 @@ namespace Opm {
if (phase != currentPhase)
throw std::invalid_argument("Sorry - we currently do not support injecting multiple phases at the same time.");
}
m_injection->phase->add( time_step , phase );
m_injection->phase->update( time_step , phase );
}
Phase::PhaseEnum Group::getInjectionPhase( size_t time_step ) const {
@@ -154,7 +154,7 @@ namespace Opm {
}
void Group::setInjectionRate( size_t time_step , double rate) {
return m_injection->rate->add( time_step , rate);
m_injection->rate->update( time_step , rate);
}
double Group::getInjectionRate( size_t time_step ) const {
@@ -162,7 +162,7 @@ namespace Opm {
}
void Group::setInjectionControlMode(size_t time_step , GroupInjection::ControlEnum controlMode) {
m_injection->controlMode->add( time_step , controlMode );
m_injection->controlMode->update( time_step , controlMode );
}
GroupInjection::ControlEnum Group::getInjectionControlMode( size_t time_step) const {
@@ -170,7 +170,7 @@ namespace Opm {
}
void Group::setSurfaceMaxRate( size_t time_step , double rate) {
return m_injection->surfaceFlowMaxRate->add( time_step , rate);
m_injection->surfaceFlowMaxRate->update( time_step , rate);
}
double Group::getSurfaceMaxRate( size_t time_step ) const {
@@ -178,7 +178,7 @@ namespace Opm {
}
void Group::setReservoirMaxRate( size_t time_step , double rate) {
return m_injection->reservoirFlowMaxRate->add( time_step , rate);
m_injection->reservoirFlowMaxRate->update( time_step , rate);
}
double Group::getReservoirMaxRate( size_t time_step ) const {
@@ -186,7 +186,7 @@ namespace Opm {
}
void Group::setTargetReinjectFraction( size_t time_step , double rate) {
return m_injection->targetReinjectFraction->add( time_step , rate);
m_injection->targetReinjectFraction->update( time_step , rate);
}
double Group::getTargetReinjectFraction( size_t time_step ) const {
@@ -194,7 +194,7 @@ namespace Opm {
}
void Group::setTargetVoidReplacementFraction( size_t time_step , double rate) {
return m_injection->targetVoidReplacementFraction->add( time_step , rate);
m_injection->targetVoidReplacementFraction->update( time_step , rate);
}
double Group::getTargetVoidReplacementFraction( size_t time_step ) const {
@@ -204,7 +204,7 @@ namespace Opm {
/*****************************************************************/
void Group::setProductionControlMode( size_t time_step , GroupProduction::ControlEnum controlMode) {
m_production->controlMode->add(time_step , controlMode );
m_production->controlMode->update(time_step , controlMode );
}
GroupProduction::ControlEnum Group::getProductionControlMode( size_t time_step ) const {
@@ -218,12 +218,12 @@ namespace Opm {
void Group::setProductionExceedLimitAction( size_t time_step , GroupProductionExceedLimit::ActionEnum action) {
m_production->exceedAction->add(time_step , action);
m_production->exceedAction->update(time_step , action);
}
void Group::setOilTargetRate(size_t time_step , double oilTargetRate) {
m_production->oilTarget->add(time_step , oilTargetRate);
m_production->oilTarget->update(time_step , oilTargetRate);
}
@@ -233,7 +233,7 @@ namespace Opm {
void Group::setGasTargetRate(size_t time_step , double gasTargetRate) {
m_production->gasTarget->add(time_step , gasTargetRate);
m_production->gasTarget->update(time_step , gasTargetRate);
}
@@ -243,7 +243,7 @@ namespace Opm {
void Group::setWaterTargetRate(size_t time_step , double waterTargetRate) {
m_production->waterTarget->add(time_step , waterTargetRate);
m_production->waterTarget->update(time_step , waterTargetRate);
}
@@ -253,7 +253,7 @@ namespace Opm {
void Group::setLiquidTargetRate(size_t time_step , double liquidTargetRate) {
m_production->liquidTarget->add(time_step , liquidTargetRate);
m_production->liquidTarget->update(time_step , liquidTargetRate);
}
@@ -291,7 +291,7 @@ namespace Opm {
WellSetPtr newWellSet = WellSetPtr( wellSet->shallowCopy() );
newWellSet->addWell(well);
m_wells->add(time_step , newWellSet);
m_wells->update(time_step , newWellSet);
}
@@ -300,7 +300,7 @@ namespace Opm {
WellSetPtr newWellSet = WellSetPtr( wellSet->shallowCopy() );
newWellSet->delWell(wellName);
m_wells->add(time_step , newWellSet);
m_wells->update(time_step , newWellSet);
}
}

View File

@@ -192,27 +192,28 @@ namespace Opm {
const std::string& wellName = record->getItem("WELL")->getTrimmedString(0);
const std::string& groupName = record->getItem("GROUP")->getTrimmedString(0);
if (!hasGroup(groupName)) {
if (!hasGroup(groupName))
addGroup(groupName , currentStep);
}
if (!hasWell(wellName)) {
if (!hasWell(wellName))
addWell(wellName, record, currentStep);
}
WellConstPtr currentWell = getWell(wellName);
checkWELSPECSConsistency(currentWell, keyword, recordNr);
addWellToGroup( getGroup(groupName) , getWell(wellName) , currentStep);
bool treeChanged = handleGroupFromWELSPECS(groupName, newTree);
needNewTree = needNewTree || treeChanged;
if (handleGroupFromWELSPECS(groupName, newTree))
needNewTree = true;
}
if (needNewTree) {
m_rootGroupTree->add(currentStep, newTree);
m_rootGroupTree->update(currentStep, newTree);
m_events.addEvent( ScheduleEvents::GROUP_CHANGE , currentStep);
}
}
void Schedule::checkWELSPECSConsistency(WellConstPtr well, DeckKeywordConstPtr keyword, size_t recordIdx) const {
DeckRecordConstPtr record = keyword->getRecord(recordIdx);
if (well->getHeadI() != record->getItem("HEAD_I")->getInt(0) - 1) {
@@ -274,13 +275,19 @@ namespace Opm {
throw std::invalid_argument(msg);
}
}
well->setStatus( currentStep , status );
well->setProductionProperties(currentStep, properties);
updateWellStatus( well , currentStep , status );
if (well->setProductionProperties(currentStep, properties))
m_events.addEvent( ScheduleEvents::PRODUCTION_UPDATE , currentStep);
}
}
}
void Schedule::updateWellStatus(std::shared_ptr<Well> well, size_t reportStep , WellCommon::StatusEnum status) {
if (well->setStatus( reportStep , status ))
m_events.addEvent( ScheduleEvents::WELL_STATUS_CHANGE , reportStep );
}
void Schedule::handleWCONHIST(DeckKeywordConstPtr keyword, size_t currentStep) {
handleWCONProducer(keyword, currentStep, false);
}
@@ -381,7 +388,7 @@ namespace Opm {
WellInjector::TypeEnum injectorType = WellInjector::TypeFromString( record->getItem("TYPE")->getTrimmedString(0) );
WellCommon::StatusEnum status = WellCommon::StatusFromString( record->getItem("STATUS")->getTrimmedString(0));
well->setStatus( currentStep , status );
updateWellStatus( well , currentStep , status );
WellInjectionProperties properties(well->getInjectionPropertiesCopy(currentStep));
properties.injectorType = injectorType;
@@ -433,7 +440,8 @@ namespace Opm {
throw std::invalid_argument("Tried to set invalid control: " + cmodeString + " for well: " + wellNamePattern);
}
}
well->setInjectionProperties(currentStep, properties);
if (well->setInjectionProperties(currentStep, properties))
m_events.addEvent( ScheduleEvents::INJECTION_UPDATE , currentStep );
}
}
}
@@ -481,7 +489,7 @@ namespace Opm {
WellCommon::StatusEnum status = WellCommon::StatusFromString( record->getItem("STATUS")->getTrimmedString(0));
well->setStatus( currentStep , status );
updateWellStatus(well , currentStep , status );
WellInjectionProperties properties(well->getInjectionPropertiesCopy(currentStep));
properties.injectorType = injectorType;
@@ -495,7 +503,8 @@ namespace Opm {
}
properties.predictionMode = false;
well->setInjectionProperties(currentStep, properties);
if (well->setInjectionProperties(currentStep, properties))
m_events.addEvent( ScheduleEvents::INJECTION_UPDATE , currentStep );
}
}
@@ -507,7 +516,8 @@ namespace Opm {
bool haveCompletionData = false;
for (size_t i=2; i<7; i++) {
if (record->getItem(i)->hasValue(0)) {
auto item = record->getItem(i);
if (!item->defaultApplied(0)) {
haveCompletionData = true;
break;
}
@@ -576,15 +586,16 @@ namespace Opm {
CompletionPtr newCompletion = std::make_shared<Completion>(currentCompletion, completionStatus);
newCompletionSet->add(newCompletion);
}
well->addCompletionSet(currentStep, newCompletionSet);
if (newCompletionSet->allCompletionsShut()) {
well->setStatus(currentStep, WellCommon::StatusEnum::SHUT);
}
well->addCompletionSet(currentStep, newCompletionSet);
m_events.addEvent(ScheduleEvents::COMPLETION_CHANGE, currentStep);
if (newCompletionSet->allCompletionsShut())
updateWellStatus( well , currentStep , WellCommon::StatusEnum::SHUT);
}
else if(!haveCompletionData) {
WellCommon::StatusEnum status = WellCommon::StatusFromString( record->getItem("STATUS")->getTrimmedString(0));
well->setStatus(currentStep, status);
updateWellStatus( well , currentStep , status );
}
}
}
@@ -924,6 +935,7 @@ namespace Opm {
WellPtr well = getWell(wellName);
well->addCompletions(currentStep, iter->second);
}
m_events.addEvent(ScheduleEvents::COMPLETION_CHANGE, currentStep);
}
void Schedule::handleWGRUPCON(DeckKeywordConstPtr keyword, size_t currentStep) {
@@ -962,7 +974,7 @@ namespace Opm {
if (!hasGroup(childName))
addGroup( childName , currentStep );
}
m_rootGroupTree->add(currentStep, newTree);
m_rootGroupTree->update(currentStep, newTree);
}
void Schedule::handleWRFT(DeckKeywordConstPtr keyword, size_t currentStep) {
@@ -1065,6 +1077,7 @@ namespace Opm {
well = std::make_shared<Well>(wellName, m_grid , headI, headJ, refDepth, preferredPhase, m_timeMap , timeStep);
m_wells.insert( wellName , well);
m_events.addEvent( ScheduleEvents::NEW_WELL , timeStep );
}
size_t Schedule::numWells() const {
@@ -1144,6 +1157,7 @@ namespace Opm {
}
GroupPtr group(new Group(groupName, m_timeMap , timeStep));
m_groups[ groupName ] = group;
m_events.addEvent( ScheduleEvents::NEW_GROUP , timeStep );
}
size_t Schedule::numGroups() const {
@@ -1252,4 +1266,9 @@ namespace Opm {
TuningPtr Schedule::getTuning() const {
return m_tuning;
}
const Events& Schedule::getEvents() const {
return m_events;
}
}

View File

@@ -19,6 +19,7 @@
#ifndef SCHEDULE_HPP
#define SCHEDULE_HPP
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/GroupTree.hpp>
@@ -64,7 +65,7 @@ namespace Opm
TuningPtr getTuning() const;
bool initOnly() const;
const Events& getEvents() const;
private:
TimeMapPtr m_timeMap;
@@ -72,10 +73,11 @@ namespace Opm
std::shared_ptr<const EclipseGrid> m_grid;
std::map<std::string , GroupPtr> m_groups;
std::shared_ptr<DynamicState<GroupTreePtr> > m_rootGroupTree;
Events m_events;
TuningPtr m_tuning;
bool nosim;
void updateWellStatus(std::shared_ptr<Well> well, size_t reportStep , WellCommon::StatusEnum status);
void addWellToGroup( GroupPtr newGroup , WellPtr well , size_t timeStep);
void initFromDeck(DeckConstPtr deck, IOConfigPtr ioConfig);
void initializeNOSIM(DeckConstPtr deck);

View File

@@ -243,39 +243,39 @@ namespace Opm {
}
/*The following "set" method declarations diverges from coding standard to improve readability*/
void Tuning::setTSINIT(size_t timestep, double TSINIT) { m_TSINIT->add(timestep, TSINIT); }
void Tuning::setTSMAXZ(size_t timestep, double TSMAXZ) { m_TSMAXZ->add(timestep, TSMAXZ); }
void Tuning::setTSMINZ(size_t timestep, double TSMINZ) { m_TSMINZ->add(timestep, TSMINZ); }
void Tuning::setTSMCHP(size_t timestep, double TSMCHP) { m_TSMCHP->add(timestep, TSMCHP); }
void Tuning::setTSFMAX(size_t timestep, double TSFMAX) { m_TSFMAX->add(timestep, TSFMAX); }
void Tuning::setTSFMIN(size_t timestep, double TSFMIN) { m_TSFMIN->add(timestep, TSFMIN); }
void Tuning::setTSFCNV(size_t timestep, double TSFCNV) { m_TSFCNV->add(timestep, TSFCNV); }
void Tuning::setTFDIFF(size_t timestep, double TFDIFF) { m_TFDIFF->add(timestep, TFDIFF); }
void Tuning::setTHRUPT(size_t timestep, double THRUPT) { m_THRUPT->add(timestep, THRUPT); }
void Tuning::setTMAXWC(size_t timestep, double TMAXWC) { m_TMAXWC->add(timestep, TMAXWC); m_TMAXWC_has_value->add(timestep, true); }
void Tuning::setTRGTTE(size_t timestep, double TRGTTE) { m_TRGTTE->add(timestep, TRGTTE); }
void Tuning::setTRGCNV(size_t timestep, double TRGCNV) { m_TRGCNV->add(timestep, TRGCNV); }
void Tuning::setTRGMBE(size_t timestep, double TRGMBE) { m_TRGMBE->add(timestep, TRGMBE); }
void Tuning::setTRGLCV(size_t timestep, double TRGLCV) { m_TRGLCV->add(timestep, TRGLCV); }
void Tuning::setXXXTTE(size_t timestep, double XXXTTE) { m_XXXTTE->add(timestep, XXXTTE); }
void Tuning::setXXXCNV(size_t timestep, double XXXCNV) { m_XXXCNV->add(timestep, XXXCNV); }
void Tuning::setXXXMBE(size_t timestep, double XXXMBE) { m_XXXMBE->add(timestep, XXXMBE); }
void Tuning::setXXXLCV(size_t timestep, double XXXLCV) { m_XXXLCV->add(timestep, XXXLCV); }
void Tuning::setXXXWFL(size_t timestep, double XXXWFL) { m_XXXWFL->add(timestep, XXXWFL); }
void Tuning::setTRGFIP(size_t timestep, double TRGFIP) { m_TRGFIP->add(timestep, TRGFIP); }
void Tuning::setTRGSFT(size_t timestep, double TRGSFT) { m_TRGSFT->add(timestep, TRGSFT); m_TRGSFT_has_value->add(timestep, true); }
void Tuning::setTHIONX(size_t timestep, double THIONX) { m_THIONX->add(timestep, THIONX); }
void Tuning::setTRWGHT(size_t timestep, int TRWGHT) { m_TRWGHT->add(timestep, TRWGHT); }
void Tuning::setNEWTMX(size_t timestep, int NEWTMX) { m_NEWTMX->add(timestep, NEWTMX); }
void Tuning::setNEWTMN(size_t timestep, int NEWTMN) { m_NEWTMN->add(timestep, NEWTMN); }
void Tuning::setLITMAX(size_t timestep, int LITMAX) { m_LITMAX->add(timestep, LITMAX); }
void Tuning::setLITMIN(size_t timestep, int LITMIN) { m_LITMIN->add(timestep, LITMIN); }
void Tuning::setMXWSIT(size_t timestep, int MXWSIT) { m_MXWSIT->add(timestep, MXWSIT); }
void Tuning::setMXWPIT(size_t timestep, int MXWPIT) { m_MXWPIT->add(timestep, MXWPIT); }
void Tuning::setDDPLIM(size_t timestep, double DDPLIM) { m_DDPLIM->add(timestep, DDPLIM); }
void Tuning::setDDSLIM(size_t timestep, double DDSLIM) { m_DDSLIM->add(timestep, DDSLIM); }
void Tuning::setTRGDPR(size_t timestep, double TRGDPR) { m_TRGDPR->add(timestep, TRGDPR); }
void Tuning::setXXXDPR(size_t timestep, double XXXDPR) { m_XXXDPR->add(timestep, XXXDPR); m_XXXDPR_has_value->add(timestep, true); }
void Tuning::setTSINIT(size_t timestep, double TSINIT) { m_TSINIT->update(timestep, TSINIT); }
void Tuning::setTSMAXZ(size_t timestep, double TSMAXZ) { m_TSMAXZ->update(timestep, TSMAXZ); }
void Tuning::setTSMINZ(size_t timestep, double TSMINZ) { m_TSMINZ->update(timestep, TSMINZ); }
void Tuning::setTSMCHP(size_t timestep, double TSMCHP) { m_TSMCHP->update(timestep, TSMCHP); }
void Tuning::setTSFMAX(size_t timestep, double TSFMAX) { m_TSFMAX->update(timestep, TSFMAX); }
void Tuning::setTSFMIN(size_t timestep, double TSFMIN) { m_TSFMIN->update(timestep, TSFMIN); }
void Tuning::setTSFCNV(size_t timestep, double TSFCNV) { m_TSFCNV->update(timestep, TSFCNV); }
void Tuning::setTFDIFF(size_t timestep, double TFDIFF) { m_TFDIFF->update(timestep, TFDIFF); }
void Tuning::setTHRUPT(size_t timestep, double THRUPT) { m_THRUPT->update(timestep, THRUPT); }
void Tuning::setTMAXWC(size_t timestep, double TMAXWC) { m_TMAXWC->update(timestep, TMAXWC); m_TMAXWC_has_value->update(timestep, true); }
void Tuning::setTRGTTE(size_t timestep, double TRGTTE) { m_TRGTTE->update(timestep, TRGTTE); }
void Tuning::setTRGCNV(size_t timestep, double TRGCNV) { m_TRGCNV->update(timestep, TRGCNV); }
void Tuning::setTRGMBE(size_t timestep, double TRGMBE) { m_TRGMBE->update(timestep, TRGMBE); }
void Tuning::setTRGLCV(size_t timestep, double TRGLCV) { m_TRGLCV->update(timestep, TRGLCV); }
void Tuning::setXXXTTE(size_t timestep, double XXXTTE) { m_XXXTTE->update(timestep, XXXTTE); }
void Tuning::setXXXCNV(size_t timestep, double XXXCNV) { m_XXXCNV->update(timestep, XXXCNV); }
void Tuning::setXXXMBE(size_t timestep, double XXXMBE) { m_XXXMBE->update(timestep, XXXMBE); }
void Tuning::setXXXLCV(size_t timestep, double XXXLCV) { m_XXXLCV->update(timestep, XXXLCV); }
void Tuning::setXXXWFL(size_t timestep, double XXXWFL) { m_XXXWFL->update(timestep, XXXWFL); }
void Tuning::setTRGFIP(size_t timestep, double TRGFIP) { m_TRGFIP->update(timestep, TRGFIP); }
void Tuning::setTRGSFT(size_t timestep, double TRGSFT) { m_TRGSFT->update(timestep, TRGSFT); m_TRGSFT_has_value->update(timestep, true); }
void Tuning::setTHIONX(size_t timestep, double THIONX) { m_THIONX->update(timestep, THIONX); }
void Tuning::setTRWGHT(size_t timestep, int TRWGHT) { m_TRWGHT->update(timestep, TRWGHT); }
void Tuning::setNEWTMX(size_t timestep, int NEWTMX) { m_NEWTMX->update(timestep, NEWTMX); }
void Tuning::setNEWTMN(size_t timestep, int NEWTMN) { m_NEWTMN->update(timestep, NEWTMN); }
void Tuning::setLITMAX(size_t timestep, int LITMAX) { m_LITMAX->update(timestep, LITMAX); }
void Tuning::setLITMIN(size_t timestep, int LITMIN) { m_LITMIN->update(timestep, LITMIN); }
void Tuning::setMXWSIT(size_t timestep, int MXWSIT) { m_MXWSIT->update(timestep, MXWSIT); }
void Tuning::setMXWPIT(size_t timestep, int MXWPIT) { m_MXWPIT->update(timestep, MXWPIT); }
void Tuning::setDDPLIM(size_t timestep, double DDPLIM) { m_DDPLIM->update(timestep, DDPLIM); }
void Tuning::setDDSLIM(size_t timestep, double DDSLIM) { m_DDSLIM->update(timestep, DDSLIM); }
void Tuning::setTRGDPR(size_t timestep, double TRGDPR) { m_TRGDPR->update(timestep, TRGDPR); }
void Tuning::setXXXDPR(size_t timestep, double XXXDPR) { m_XXXDPR->update(timestep, XXXDPR); m_XXXDPR_has_value->update(timestep, true); }
} //namespace Opm

View File

@@ -63,9 +63,9 @@ namespace Opm {
}
void Well::setProductionProperties(size_t timeStep , const WellProductionProperties newProperties) {
m_isProducer->add(timeStep , true);
m_productionProperties->add(timeStep, newProperties);
bool Well::setProductionProperties(size_t timeStep , const WellProductionProperties newProperties) {
m_isProducer->update(timeStep , true);
return m_productionProperties->update(timeStep, newProperties);
}
WellProductionProperties Well::getProductionPropertiesCopy(size_t timeStep) const {
@@ -76,9 +76,9 @@ namespace Opm {
return m_productionProperties->at(timeStep);
}
void Well::setInjectionProperties(size_t timeStep , const WellInjectionProperties newProperties) {
m_isProducer->add(timeStep , false);
m_injectionProperties->add(timeStep, newProperties);
bool Well::setInjectionProperties(size_t timeStep , const WellInjectionProperties newProperties) {
m_isProducer->update(timeStep , false);
return m_injectionProperties->update(timeStep, newProperties);
}
WellInjectionProperties Well::getInjectionPropertiesCopy(size_t timeStep) const {
@@ -89,9 +89,9 @@ namespace Opm {
return m_injectionProperties->at(timeStep);
}
void Well::setPolymerProperties(size_t timeStep , const WellPolymerProperties newProperties) {
m_isProducer->add(timeStep , false);
m_polymerProperties->add(timeStep, newProperties);
bool Well::setPolymerProperties(size_t timeStep , const WellPolymerProperties newProperties) {
m_isProducer->update(timeStep , false);
return m_polymerProperties->update(timeStep, newProperties);
}
WellPolymerProperties Well::getPolymerPropertiesCopy(size_t timeStep) const {
@@ -113,13 +113,12 @@ namespace Opm {
return m_status->get( timeStep );
}
void Well::setStatus(size_t timeStep, WellCommon::StatusEnum status) {
bool Well::setStatus(size_t timeStep, WellCommon::StatusEnum status) {
if ((WellCommon::StatusEnum::OPEN == status) && getCompletions(timeStep)->allCompletionsShut()) {
std::cerr << "ERROR when handling keyword for well "<< name() << ": Cannot open a well where all completions are shut" << std::endl;
return false;
} else
{
m_status->add( timeStep , status );
}
return m_status->update( timeStep , status );
}
bool Well::isProducer(size_t timeStep) const {
@@ -135,7 +134,7 @@ namespace Opm {
}
void Well::setAvailableForGroupControl(size_t timeStep, bool isAvailableForGroupControl_) {
m_isAvailableForGroupControl->add(timeStep, isAvailableForGroupControl_);
m_isAvailableForGroupControl->update(timeStep, isAvailableForGroupControl_);
}
double Well::getGuideRate(size_t timeStep) const {
@@ -143,7 +142,7 @@ namespace Opm {
}
void Well::setGuideRate(size_t timeStep, double guideRate) {
m_guideRate->add(timeStep, guideRate);
m_guideRate->update(timeStep, guideRate);
}
GuideRate::GuideRatePhaseEnum Well::getGuideRatePhase(size_t timeStep) const {
@@ -151,7 +150,7 @@ namespace Opm {
}
void Well::setGuideRatePhase(size_t timeStep, GuideRate::GuideRatePhaseEnum phase) {
m_guideRatePhase->add(timeStep, phase);
m_guideRatePhase->update(timeStep, phase);
}
double Well::getGuideRateScalingFactor(size_t timeStep) const {
@@ -159,7 +158,7 @@ namespace Opm {
}
void Well::setGuideRateScalingFactor(size_t timeStep, double scalingFactor) {
m_guideRateScalingFactor->add(timeStep, scalingFactor);
m_guideRateScalingFactor->update(timeStep, scalingFactor);
}
/*****************************************************************/
@@ -224,7 +223,7 @@ namespace Opm {
void Well::addCompletionSet(size_t time_step, const CompletionSetConstPtr newCompletionSet){
CompletionSetPtr mutable_copy(newCompletionSet->shallowCopy());
mutable_copy->orderCompletions(m_headI, m_headJ, m_grid);
m_completions->add(time_step, mutable_copy);
m_completions->update(time_step, mutable_copy);
}
const std::string Well::getGroupName(size_t time_step) const {
@@ -233,13 +232,13 @@ namespace Opm {
void Well::setGroupName(size_t time_step, const std::string& groupName ) {
m_groupName->add(time_step , groupName);
m_groupName->update(time_step , groupName);
}
void Well::setRFTActive(size_t time_step, bool value){
m_rft->add(time_step, value);
m_rft->update(time_step, value);
}
bool Well::getRFTActive(size_t time_step) const{
@@ -250,7 +249,7 @@ namespace Opm {
return m_plt->get(time_step);
}
void Well::setPLTActive(size_t time_step, bool value){
m_plt->add(time_step, value);
m_plt->update(time_step, value);
}
int Well::findWellFirstOpen(int startTimeStep) const{

View File

@@ -51,7 +51,7 @@ namespace Opm {
void setGroupName(size_t timeStep , const std::string& groupName);
WellCommon::StatusEnum getStatus(size_t timeStep) const;
void setStatus(size_t timeStep, WellCommon::StatusEnum Status);
bool setStatus(size_t timeStep, WellCommon::StatusEnum Status);
int getHeadI() const;
int getHeadJ() const;
@@ -74,15 +74,15 @@ namespace Opm {
void addCompletionSet(size_t time_step, const CompletionSetConstPtr newCompletionSet);
CompletionSetConstPtr getCompletions(size_t timeStep) const;
void setProductionProperties(size_t timeStep , const WellProductionProperties properties);
bool setProductionProperties(size_t timeStep , const WellProductionProperties properties);
WellProductionProperties getProductionPropertiesCopy(size_t timeStep) const;
const WellProductionProperties& getProductionProperties(size_t timeStep) const;
void setInjectionProperties(size_t timeStep , const WellInjectionProperties properties);
bool setInjectionProperties(size_t timeStep , const WellInjectionProperties properties);
WellInjectionProperties getInjectionPropertiesCopy(size_t timeStep) const;
const WellInjectionProperties& getInjectionProperties(size_t timeStep) const;
void setPolymerProperties(size_t timeStep , const WellPolymerProperties properties);
bool setPolymerProperties(size_t timeStep , const WellPolymerProperties properties);
WellPolymerProperties getPolymerPropertiesCopy(size_t timeStep) const;
const WellPolymerProperties& getPolymerProperties(size_t timeStep) const;

View File

@@ -16,4 +16,22 @@ namespace Opm {
controlMode = WellInjector::CMODE_UNDEFINED;
}
bool WellInjectionProperties::operator==(const WellInjectionProperties& other) const {
if ((surfaceInjectionRate == other.surfaceInjectionRate) &&
(reservoirInjectionRate == other.reservoirInjectionRate) &&
(BHPLimit == other.BHPLimit) &&
(THPLimit == other.THPLimit) &&
(predictionMode == other.predictionMode) &&
(injectionControls == other.injectionControls) &&
(injectorType == other.injectorType) &&
(controlMode == other.controlMode))
return true;
else
return false;
}
bool WellInjectionProperties::operator!=(const WellInjectionProperties& other) const {
return !(*this == other);
}
}

View File

@@ -34,8 +34,10 @@ namespace Opm {
WellInjector::TypeEnum injectorType;
WellInjector::ControlModeEnum controlMode;
WellInjectionProperties();
bool operator==(const WellInjectionProperties& other) const;
bool operator!=(const WellInjectionProperties& other) const;
WellInjectionProperties();
bool hasInjectionControl(WellInjector::ControlModeEnum controlModeArg) const {
if (injectionControls & controlModeArg)
return true;

View File

@@ -9,4 +9,17 @@ namespace Opm {
m_polymerConcentration = 0.0;
m_saltConcentration = 0.0;
}
bool WellPolymerProperties::operator==(const WellPolymerProperties& other) const {
if ((m_polymerConcentration == other.m_polymerConcentration) &&
(m_saltConcentration == other.m_saltConcentration))
return true;
else
return false;
}
bool WellPolymerProperties::operator!=(const WellPolymerProperties& other) const {
return !(*this == other);
}
}

View File

@@ -27,6 +27,8 @@ namespace Opm {
double m_polymerConcentration;
double m_saltConcentration;
bool operator==(const WellPolymerProperties& other) const;
bool operator!=(const WellPolymerProperties& other) const;
WellPolymerProperties();
};
}

View File

@@ -129,4 +129,27 @@ namespace Opm {
m_productionControls = 0;
}
bool WellProductionProperties::operator==(const WellProductionProperties& other) const {
if ((OilRate == other.OilRate) &&
(WaterRate == other.WaterRate) &&
(GasRate == other.GasRate) &&
(LiquidRate == other.LiquidRate) &&
(ResVRate == other.ResVRate) &&
(BHPLimit == other.BHPLimit) &&
(THPLimit == other.THPLimit) &&
(VFPTableNumber == other.VFPTableNumber) &&
(controlMode == other.controlMode) &&
(m_productionControls == other.m_productionControls))
return true;
else
return false;
}
bool WellProductionProperties::operator!=(const WellProductionProperties& other) const {
return !(*this == other);
}
} // namespace Opm

View File

@@ -24,7 +24,8 @@
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
namespace Opm {
struct WellProductionProperties {
class WellProductionProperties {
public:
double OilRate;
double WaterRate;
double GasRate;
@@ -38,6 +39,8 @@ namespace Opm {
WellProducer::ControlModeEnum controlMode;
bool operator==(const WellProductionProperties& other) const;
bool operator!=(const WellProductionProperties& other) const;
WellProductionProperties();
static WellProductionProperties history(DeckRecordConstPtr record);

View File

@@ -3,7 +3,7 @@ foreach(tapp TimeMapTest ScheduleTests WellTests
GroupTests ScheduleEnumTests
CompletionTests CompletionSetTests
DynamicStateTests GroupTreeNodeTests
GroupTreeTests TuningTests)
GroupTreeTests TuningTests EventTests)
opm_add_test(run${tapp} SOURCES ${tapp}.cpp
LIBRARIES opmparser ${Boost_LIBRARIES})
endforeach()

View File

@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(DynamicStateSetOutOfRangeThrows) {
for (size_t i = 0; i < 2; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
BOOST_CHECK_THROW( state.add(3 , 100) , std::range_error);
BOOST_CHECK_THROW( state.update(3 , 100) , std::range_error);
}
@@ -74,19 +74,19 @@ BOOST_AUTO_TEST_CASE(DynamicStateSetOK) {
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add(2 , 23 );
state.update(2 , 23 );
BOOST_CHECK_EQUAL( 137 , state.get(0));
BOOST_CHECK_EQUAL( 137 , state.get(1));
BOOST_CHECK_EQUAL( 23 , state.get(2));
BOOST_CHECK_EQUAL( 23 , state.get(5));
state.add(2 , 17);
state.update(2 , 17);
BOOST_CHECK_EQUAL( 137 , state.get(0));
BOOST_CHECK_EQUAL( 137 , state.get(1));
BOOST_CHECK_EQUAL( 17 , state.get(2));
BOOST_CHECK_EQUAL( 17 , state.get(5));
state.add(6 , 60);
state.update(6 , 60);
BOOST_CHECK_EQUAL( 17 , state.get(2));
BOOST_CHECK_EQUAL( 17 , state.get(5));
BOOST_CHECK_EQUAL( 60 , state.get(6));
@@ -103,8 +103,8 @@ BOOST_AUTO_TEST_CASE(DynamicStateAddIndexAlreadySetThrows) {
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add( 5 , 60);
BOOST_CHECK_THROW( state.add(3 , 78) , std::invalid_argument);
state.update( 5 , 60);
BOOST_CHECK_THROW( state.update(3 , 78) , std::invalid_argument);
}
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(DynamicStateAddAt) {
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add( 10 , 77 );
state.update( 10 , 77 );
{
const int& v1 = state.at(10);
int v2 = state.get(10);
@@ -135,15 +135,15 @@ BOOST_AUTO_TEST_CASE(DynamicStateCheckSize) {
BOOST_CHECK_EQUAL( 0U , state.size() );
state.add( 0 , 10 );
state.update( 0 , 10 );
BOOST_CHECK_EQUAL( 1U , state.size() );
state.add( 2 , 10 );
state.update( 2 , 10 );
BOOST_CHECK_EQUAL( 3U , state.size() );
state.add( 2 , 10 );
state.update( 2 , 10 );
BOOST_CHECK_EQUAL( 3U , state.size() );
state.add( 6 , 10 );
state.update( 6 , 10 );
BOOST_CHECK_EQUAL( 7U , state.size() );
}
@@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(DynamicStateOperatorSubscript) {
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add( 10 , 200 );
state.update( 10 , 200 );
BOOST_CHECK_EQUAL( state[9] , 137 );
BOOST_CHECK_EQUAL( state[0] , 137 );
@@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE(DynamicStateInitial) {
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add( 10 , 200 );
state.update( 10 , 200 );
BOOST_CHECK_EQUAL( state[9] , 137 );
BOOST_CHECK_EQUAL( state[0] , 137 );
BOOST_CHECK_EQUAL( state[10] , 200 );
@@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(DynamicStateInitial) {
BOOST_CHECK_EQUAL( state[10] , 200 );
state2.add( 10 , 200 );
state2.update( 10 , 200 );
BOOST_CHECK_EQUAL( state2[9] , 137 );
BOOST_CHECK_EQUAL( state2[0] , 137 );
BOOST_CHECK_EQUAL( state2[10] , 200 );
@@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE( ResetGlobal ) {
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
state.add(5 , 100);
state.update(5 , 100);
BOOST_CHECK_EQUAL( state[0] , 137 );
BOOST_CHECK_EQUAL( state[4] , 137 );
BOOST_CHECK_EQUAL( state[5] , 100 );
@@ -222,3 +222,16 @@ BOOST_AUTO_TEST_CASE( ResetGlobal ) {
BOOST_CHECK_EQUAL( state[5] , 88 );
BOOST_CHECK_EQUAL( state[9] , 88 );
}
BOOST_AUTO_TEST_CASE( CheckReturn ) {
boost::gregorian::date startDate( 2010 , boost::gregorian::Jan , 1);
Opm::TimeMapPtr timeMap(new Opm::TimeMap(boost::posix_time::ptime(startDate)));
Opm::DynamicState<int> state(timeMap , 137);
for (size_t i = 0; i < 10; i++)
timeMap->addTStep( boost::posix_time::hours( (i+1) * 24 ));
BOOST_CHECK_EQUAL( false , state.update( 0 , 137 ));
BOOST_CHECK_EQUAL( false , state.update( 3 , 137 ));
BOOST_CHECK_EQUAL( true , state.update( 5 , 200 ));
}

View File

@@ -0,0 +1,55 @@
/*
Copyright 2013 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM 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.
OPM 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 for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#define BOOST_TEST_MODULE CompletionSetTests
#include <boost/test/unit_test.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
BOOST_AUTO_TEST_CASE(CreateEmpty) {
Opm::Events events;
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 10));
events.addEvent( Opm::ScheduleEvents::NEW_WELL , 0 );
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 0));
events.addEvent( Opm::ScheduleEvents::NEW_WELL , 10 );
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 9));
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 10));
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 11));
events.addEvent( Opm::ScheduleEvents::NEW_WELL , 10 );
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 9));
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 10));
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 11));
events.addEvent( Opm::ScheduleEvents::WELL_STATUS_CHANGE , 9 );
events.addEvent( Opm::ScheduleEvents::WELL_STATUS_CHANGE , 10 );
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 9));
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 10));
BOOST_CHECK_EQUAL( false , events.hasEvent(Opm::ScheduleEvents::NEW_WELL , 11));
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::WELL_STATUS_CHANGE , 9));
BOOST_CHECK_EQUAL( true , events.hasEvent(Opm::ScheduleEvents::WELL_STATUS_CHANGE , 10));
}

View File

@@ -29,6 +29,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/CompletionSet.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
#include <opm/parser/eclipse/Units/ConversionFactors.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/GroupTreeNode.hpp>
@@ -751,3 +752,37 @@ BOOST_AUTO_TEST_CASE(WellTestWPOLYMER) {
BOOST_CHECK_CLOSE(0.3*Metric::PolymerDensity, props_well32.m_polymerConcentration, 0.0001);
}
}
BOOST_AUTO_TEST_CASE(TestEvents) {
ParserPtr parser(new Parser());
boost::filesystem::path scheduleFile("testdata/integration_tests/SCHEDULE/SCHEDULE_EVENTS");
DeckPtr deck = parser->parseFile(scheduleFile.string());
std::shared_ptr<const EclipseGrid> grid = std::make_shared<const EclipseGrid>(40,40,30);
IOConfigPtr ioConfig;
ScheduleConstPtr sched(new Schedule(grid , deck, ioConfig));
const Events& events = sched->getEvents();
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::NEW_WELL , 0 ) );
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::NEW_WELL , 1 ) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::NEW_WELL , 2 ) );
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::NEW_WELL , 3 ) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::COMPLETION_CHANGE , 0 ) );
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::COMPLETION_CHANGE , 1) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::COMPLETION_CHANGE , 5 ) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE , 1 ));
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE , 2 ));
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE , 3 ));
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::COMPLETION_CHANGE , 5) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::GROUP_CHANGE , 0 ));
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::GROUP_CHANGE , 1 ));
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::GROUP_CHANGE , 3 ) );
BOOST_CHECK_EQUAL( false , events.hasEvent(ScheduleEvents::NEW_GROUP , 2 ) );
BOOST_CHECK_EQUAL( true , events.hasEvent(ScheduleEvents::NEW_GROUP , 3 ) );
}