Upload
jan-gregersen
View
422
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Introduction to developing or migrating models to be compliant to the OpenMI Standard. OpenMI is an open standard which allows dynamic linking of numerical models, such as river models rainfall-runoff models and so on. See also:http://www.lictek.com
Citation preview
Jan Gregersen 1
Jan Gregersen
http://www.LicTek.com
OpenMI Developers Training
Jan Gregersen 2
Simple River
5 10
X (km)
Y (km)
5
10 Node:0
Node:1
Node:2
Node:3
Branch:0
Branch:1
Branch:2
Y (km) 5 10
X (km)
5
10
Runoff Model Simple River
OutputExchangeItem InputExchangeItem
Quantity ID : Runoff
DataOperaiton : Distributed
ElementSet : Polygons
Quantity ID : Inflow
ElementSet : Polyline
Jan Gregersen 3
How it works
Load components:
Query exchange items:
Add links:
Jan Gregersen 4
How it works
Prepare:
Run (GetValues):
Finish:
DHI - Water & Environment Jan Gregersen
The OpenMI standard
Jan Gregersen 6
DHI - Water & Environment Jan Gregersen
Migration of models
Jan Gregersen 8
Now What ???
Jan Gregersen 9
Org.OpenMI.Utilities
Org.OpenMI.Utilities.Spatial
Org.OpenMI.Utilities.Buffer
Org.OpenMI.Utilities.Wrapper
Buffers results from the engine core
Mapping of values associated to one array of times /timespans to values represented on another array of times/timespans
t t
Mapping of values associated to one ElementSet to be represented on another ElementSet
SmartBuffer
ElementMapper
SmartWrapper
Generic wrapper suited for time stepping model engines
Jan Gregersen 10
LinkableEngine features
• Provides a default implementation of the ILinkableComponent interface
• Links bookkeeping
• Event handling
• Buffering
• Temporal interpolations, aggregations,extrapolations
• Spatial interpolations, aggregations,extrapolations
Jan Gregersen 11
Wrapper design pattern
Jan Gregersen 12
IEngine Interface
// -- Execution control methods (Inherited from IRunEngine) --
void Initialize(Hashtable properties);
bool PerformTimeStep();
void Finish();
//-- Time methods (Inherited from IRunEngine) --
ITime GetCurrentTime();
ITime GetInputTime(string QuantityID, string ElementSetID);
ITimeStamp GetEarliestNeededTime();
//-- Data access methods (Inherited from IRunEngine) --
void SetValues(string QuantityID, string ElementSetID, IValueSet values);
IValueSet GetValues(string QuantityID, string ElementSetID);
//-- Component description methods (Inherited from IRunEngine) --
double GetMissingValueDefinition();
string GetComponentID();
string GetComponentDescription();
// -- Model description methods --
string GetModelID();
string GetModelDescription();
double GetTimeHorizon();
// -- Exchange items --
int GetInputExchangeItemCount();
int GetOutputExchangeItemCount();
org.OpenMI.Backbone GetInputExchangeItem(int exchangeItemIndex);
org.OpenMI.Backbone GetOutputExchangeItem(int exchangeItemIndex);
Jan Gregersen 13
Inside the LinkableEngine
SmartWrapper
SmartInputLinkSet SmartOutputLinkSet
SmartInputLink
UpdateBuffer()GetValues()
UpdateInput()
SmartOutputLink
UpdateInput() UpdateBuffer()GetValues()
Link
SmartBuffer ElementMapper
*
1
*
1
has has
hashas
has
has
Link
access
access
Jan Gregersen 14
GetValues()
Model B Model A
GetValues(time, LinkID)
1. Update with input from linked models
2. Perform time step and fill internal buffers
3. Map values in time and space
Return values
While (CurrentTime < time & State is “Not Busy”)
GetValues(time, LinkID)
Jan Gregersen 15
GetValues()
Model B Model A
GetValues(time, LinkID)
1. Update with input from linked models
2. Perform time step and fill internal buffers
3. Map values in time and space
Return values
While (CurrentTime < time & State is “Not Busy”)
GetValues(time, LinkID)
Jan Gregersen 16
GetValues()
Model B Model AEngine
AIPAccess
SmartOutputLInkSet
A SmartBuffer
AElementMapper
A SmartOutput
LInk
SmartInputLink
Set
GetValues(tl LinkID)
GetCurrentTime()
IsBusy = true
A SmartInputLink
UpdateInput(ct)
UpdateInput(ct)
GetValues(ct,LinkID)
SetValues(Quantity,LocationID,Values)
For each Input Link
Jan Gregersen 17
GetValues()
Model B Model A
GetValues(time, LinkID)
1. Update with input from linked models
2. Perform time step and fill internal buffers
3. Map values in time and space
Return values
While (CurrentTime < time & State is “Not Busy”)
GetValues(time, LinkID)
Jan Gregersen 18
GetValues()
Model B Model AEngine
AIPAccess
SmartOutputLInkSet
A SmartBuffer
AElementMapper
A SmartOutput
LInk
SmartInputLink
Set
PerformTimeStep()
A SmartInputLink
UpdateBuffers()
UpdateBuffer()
Getvalues(Quantity,LocationIDs)
Addvalues(time, valueSet)
For each output link
IsBusy = false
Jan Gregersen 19
GetValues()
Model B Model A
GetValues(time, LinkID)
1. Update with input from linked models
2. Perform time step and fill internal buffers
3. Map values in time and space
Return values
While (CurrentTime < time & State is “Not Busy”)
GetValues(time, LinkID)
Jan Gregersen 20
GetValues()
Model B Model AEngine
AIPAccess
SmartOutputLInkSet
A SmartBuffer
AElementMapper
A SmartOutput
LInk
SmartInputLink
Set
GetValues(time, LinkID)
A SmartInputLink
GetValues(time)
GetValues(time)
MapValues(inpuValues)
Jan Gregersen 21
IEngine Interface
// -- Execution control methods (Inherited from IRunEngine) --
void Initialize(Hashtable properties);
bool PerformTimeStep();
void Finish();
//-- Time methods (Inherited from IRunEngine) --
ITime GetCurrentTime();
ITime GetInputTime(string QuantityID, string ElementSetID);
ITimeStamp GetEarliestNeededTime();
//-- Data access methods (Inherited from IRunEngine) --
void SetValues(string QuantityID, string ElementSetID, IValueSet values);
IValueSet GetValues(string QuantityID, string ElementSetID);
//-- Component description methods (Inherited from IRunEngine) --
double GetMissingValueDefinition();
string GetComponentID();
string GetComponentDescription();
// -- Model description methods --
string GetModelID();
string GetModelDescription();
double GetTimeHorizon();
// -- Exchange items --
int GetInputExchangeItemCount();
int GetOutputExchangeItemCount();
org.OpenMI.Backbone GetInputExchangeItem(int exchangeItemIndex);
org.OpenMI.Backbone GetOutputExchangeItem(int exchangeItemIndex);
Jan Gregersen 22
Wrapper design pattern
Jan Gregersen 23
Migration steps
• Change your engine to a dll
• Implement Initialize, PerformTimeStep and Finish
• Create the EngineDllWrapper class
Jan Gregersen 24
Wrapper design pattern
Jan Gregersen 25
Migration steps
• Create your MyEnigneWrapper
• Implement Initialize and Finish
• Implement remaining Ienigne methods
Jan Gregersen 26
Jan Gregersen 27
The ElementMapper
Ground water
Model
River Model
GetValues(time, link)
CalculateReturn values
Link
ElementSetQuantity
“GW Recharge”
Has Has
Jan Gregersen 28
Spatial mapping
Jan Gregersen 29
ElementMapper
Org.OpenMI.Utilties.Spatial
ElementMapper
Initialise(string methodDescription, IElementSet fromElements, IElementSet toElements)IValueSet MapValues(IValueSet inputValues)
nmnmmm
n
n
n
m x
x
x
x
mmmm
mmmm
mmmm
mmmm
r
r
r
r
.
.
.....
.
.
.
.
3
2
1
321
3333231
2232221
1131211
3
2
1
Jan Gregersen 30
Element Mapping
GE1GE2
GE3GE4
RE1
RE1
RE3
2/100
000
2/13/20
03/11
A
ALI
Element
• ID Based
• Point
• Line
• Polyline
• Polygon
“Node127”
(x1,y1)
(x1,y1) (x2,y2)
(x1,y1) (x2,y2) (x3,y3) (x4,y4)
(x1,y1)
(x2,y2)
(x3,y3)
(x4,y4)
(x5,y5)
ElementSet example
H
H
HH
H
H
H
H
H
H
H
HQ
Q
Q
Q
Q
Q
Q
Q
Q
Q
Q
Quantity
• ID ( “Runoff” )
• Description ( “Rainfall runoff” )
• Dimension ( e.g. L3 T-1 )– GetPower ( <dimensionBase> )
• Unit:– ID ( “CFS” )
– Descr ( “Cubic feet per second “ )
– ConversionFactorToSI ( 0,0283168439 )
– OffsetToSI ( 0 )
ExchangeItem
• InputExchangeItem
– Quantity
– ElementSet
• OutputExchangeItem
– Quantity
– ElementSet
– [ DataOperations
• ID
• Arguments ]
Unidirectional link
{while RMtime < t1}
{while RRtime < RMtime + _dt}
«interface»
RRmodel :
ILinkableComponent
«interface»
RiverModel :
ILinkableComponentMainProgram
[1]
[2]
[3]
GetValues(time=t1, linkID=TriggerLink)
GetValues(time=RMtime + _dt, linkID=RRtoRiver)
PerformTimeStep
return ValueSet: Runoff
PerformTimeStep
return ValueSet: RiverFlow
Bidirectional links
MainProgram
«interface»
RiverModel :
ILinkableComponent
«interface»
GroundWaterModel :
ILinkableComponent
RiverModel uses time step t1, GroundwaterModel uses time step t2
[2]
[3]
[6]
[7]
[1]
[4]
[5]
GetValues(t2,TriggerLink)
GetValues(time=t1, linkID=QtoRiver)
GetValues(time=t2, linkID=HtoGW)
Extrapolate (t2)
return extrapolated ValueSet: HtoGW (t2)
PerformTimeStep (t2)
return interpolated ValueSet QtoRiver (t1)
PerformTimeStep (t1)
GetValues(time=t2, linkID=QtoRiver)
return ValueSet QtoRiver (t2)
PerformTimeStep (t2)
return ValueSet Hriver (t2)
{unti l l QtoGW is stabi l ized}
«interface»
GroundWaterModel :
ILinkableComponent
«interface»
RiverModel :
ILinkableComponent
IterationControl ler
:
ILinkableComponentMainProgram
[1]
[2]
[3]
[4]
[5]
[6]
[7]
GetValues(time=t2, l inkID=H_SW)
KeepCurrentState
RiverState_t_begin
KeepCurrentState
GWState_t_begin
InitialGuess(QtoGW)
RestoreState(RiverState_t_begin)
RestoreState(GWState_t_begin)
GetValues(time=t2, l inkID=H_GW)
GetValues(time=t2, l inkID=QtoGW)
QtoGW_guess
H_GW
GetValues(time=t2, l inkID=H_SW)
GetValues(time=t2, l inkID=QtoGW)
QtoGW_guess
H_SW
Evaluate
NewGuess(QtoGW)
result: H_SW
{until RRtime=t1}
User
MainProgram
:
IListener
«interface»
RR model :
ILinkableComponent
«interface»
RiverModel :
ILinkableComponent
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
Start
GetValues(time=t1,TriggerLinkID)
OnEvent(SourceAfterGetValuesCall)
return computation thread
GetValues(time=t1,linkID=QtoRiver)
OnEvent(SourceAfterGetValuesCall)
return computation thread
PerformTimeStep((_dt))
OnEvent(DataChanged)
return computation thread
OnEvent(SourceBeforeGetValuesReturn)Pause
Resume
return computation thread
return ValueSet(QtoRiver, t1)
OnEvent(TargetAfterGetValuesReturn)
return computation thread
PerformTimeStep(RM_dt)
OnEvent(DataChanged)
OnEvent(SourceBeforeGetValuesReturn)
return computation thead
return ValueSet(t1)
Persistency
• OMI File
– For identifying a linkable component
• Composition
– In org.OpenMI.Utilities.Configuration
– Holds administration of links and linkable components
– Can be run
– Can be written and read to / from xml
Exercise 9:Unit Conversion
Step 1
Open the DataCombinator
Step 2
Adjust the code of GetValues so that it delivers data in the right unit
Step 3
Adjust the test program to ask for a quantity which has a conversion factor not equal to one
Step 4
Identify a value as missing value (e.g. -999) and adjust the input. Make sure this value is processed correctly.
Step 5
Test the program using NUnit