Академический Документы
Профессиональный Документы
Культура Документы
Any enquiries relating to this report should be referred to the authors at the following
address:
WRc Swindon, Frankland Road, Blagrove, Swindon, Wiltshire, SN5 8YF.
Telephone: + 44 (0) 1793 865000
Fax: + 44 (0) 1793 865001
The contents of this document are subject to copyright and all rights are reserved. No part of
this document may be reproduced, stored in a retrieval system or transmitted, in any form or
by any means electronic, mechanical, photocopying, recording or otherwise, without the prior
written consent of the copyright owner.
This document has been produced by WRc plc.
CONTENTS
1
INTRODUCTION
2.1
2.2
2.3
2.4
Migration team
Harmon-It Use Case
Defining the exchange items
Defining the links
3
3
6
8
WRAPPING
3.1
3.2
3.3
3.4
3.5
Linkable engine
Migration
Migration of your model
The OMI XML file
Support for BOD
9
9
17
22
23
25
27
5.1
5.2
5.3
5.4
5.5
5.6
Linking
Running
Results
Sewer to sewage works (CS to STOAT)
Sewage works to river (STOAT to RS)
Experience
27
29
30
31
35
38
39
6.1
39
43
APPENDIX 1
45
A1.1
A1.2
Engine
Main wrapper
APPENDIX 2
A2.1
C# WRAPPER CODE
45
45
51
Support types
51
APPENDIX 3
OMI CREATOR
58
APPENDIX 4
MAIN CODE
65
APPENDIX 5
81
APPENDIX 6
APPENDIX 7
PAPER SUBMITTED TO MODSIM05 CONFERENCE ON
MODEL USAGE AND INTEGRATION
LIST OF TABLES
Table 2.1
Migration Team
Table 2.2
Parameter exchange between programs
Table 2.3
Available parameters in STOAT
83
87
3
5
6
LIST OF FIGURES
Figure 2.1
Figure 2.2
Figure 5.1
Figure 5.2
Figure 5.3
Figure 5.4
Figure 5.5
Figure 5.6
Figure 5.7
Figure 5.8
Figure 5.9
Figure 5.10
Figure 5.11
Figure 5.12
Figure 5.13
Figure 5.14
Figure 5.15
Figure 5.16
Figure 5.17
Figure 5.18
Schematic connection
Data interpretation
InfoWorks CS city layout
STOAT sewage works model
InfoWorks RS river model
OpenMI Configuration Editor layout
Flow: CS outlet to STOAT
Flow: CS inlet to STOAT
Suspended solids: CS outlet to STOAT
Suspended solids: CS inlet to STOAT
Suspended solids: CS outlet to STOAT, ignoring peak value
Suspended solids: CS inlet to STOAT, ignoring peak value
Ammonia: CS outlet to STOAT
Ammonia: CS inlet to STOAT
Flow: STOAT outlet to RS
Flow: STOAT inlet to RS
Suspended solids: STOAT outlet to RS
Suspended solids: STOAT inlet to RS
Ammonia: STOAT outlet to RS
Ammonia: STOAT inlet to RS
ii
3
6
27
28
28
29
31
31
32
32
33
33
34
34
35
35
36
36
37
37
1 INTRODUCTION
The HarmonIT project has developed a modelling interface (OMI, the Open Modelling
Interface) for data exchange between programs. The aim of the OMI is to provide a uniform
exchange mechanism for any software that may be applied within the water cycle, and
specifically to facilitate the use of such programs for providing solutions within the Water
Framework Directive.
The core OMI developers have provided the definition of the interface and have demonstrated
that they can successfully apply the OMI to their own programs. Another part of the HarmonIT
consortium comprises the Work Package 8 (WP8) group, software developers and users who
have not participated in the development of the OMI. The WP8 members task is to
demonstrate that the OMI can be understood and applied by people who have not been
intimately involved with its development. WP8 is thus proving that the OMI can successfully
be applied based primarily on the available printed documentation.
WRc is a WP8 member, and has chosen to migrate STOAT. STOAT is a dynamic wastewater
modelling program, and has previously provided data exchange interfaces to river and sewer
models. The data exchange methods have been file based (with Wallingford Softwares
InfoWorks) and both file and direct program access with DHIs MOUSE and MIKE software.
These existing data exchange systems have been used to speed up the addition of the OMI
interface to STOAT.
This report covers the following:
Section 2 describes a use case for STOAT. This is an example of the use of STOAT with the
OMI, the expected results, the data to be exchanged, and a full listing of what data
parameters may be exchanged.
Section 3 is the main part of the report, describing the addition of support for the OMI. All the
code is given in the appendices, with Section 3 using excerpts to discuss the implementation
of the OMI.
Section 4 describes the tests carried out on the OMI-enabled STOAT
Section 5 describes the application of the use-case.
Finally, Section 6 provides conclusions, a discussion of difficulties encountered in
implementing the OMI, and the resolutions adopted.
2.1
Migration team
Table 2.1
Migration Team
Name
Jeremy Dudley
2.2
Role
Lead developer
One example of a use case is presented, for the case where STOAT will be run with a sewer
model providing input to STOAT, and a river model receiving the output from STOAT.
2.2.1
Layout
InfoWorks CS
Figure 2.1
2.2.2
STOAT
InfoWorks RS
Schematic connection
Description
Primary actor
Model integrator, using the prepared component models, and then linking them
together to provide the larger-scale system;
2.2.4
Preconditions
Usage
Parameter exchange
Table 2.2 lists the parameters that are expected to be exchanged between the sewer model
and STOAT, and again between STOAT and the river model. The parameters fall into the
areas of flow, suspended solids, COD, ammonia, temperature and temperature. Details are
given in the table as to what is expected by STOAT.
Table 2.2
Determinand
Flow
Suspended solids
InfoWorks CS1
m3/s
kg/m3
COD
kg/m3
Ammonia
Temperature
Alkalinity
kg/m3
0
C
Mol
2.2.7
STOAT2
3
m /h
kg/m3, divided into volatile and nonvolatile. If INFOWORKS CS
represents only suspended solids
then assume ratio 75:25 VSS:NVSS
kg/m3, divided into soluble
degradable COD (SS), soluble
nondegradable COD (SI),
particulate degradable COD (X S)
and particulate nondegradable COD
(XI). If INFOWORKS CS represents
COD only as COD (or as dissolved
and attached) then a suitable
partition will be defined in STOAT.
Should be a one-to-one mapping
0
C
Mol; will need to define a different
data source or assumed (constant)
value if not supported in
INFOWORKS CS
InfoWorks RS3
m3/s
kg/m3
kg/m3
kg/m3
0
C
mol
Assessment of success
Time
Figure 2.2
2.3
2.3.1
Data interpretation
Table 2.3
Process
Influent
Parameter
Flow
COD
Volatile fatty acids
Soluble degradable COD
Soluble nondegradable COD
Particulate degradable COD
Particulate nondegradable COD
Suspended solids
Volatile suspended solids
Nonvolatile suspended solids
Ammonia
Nitrate
Soluble organic degradable N
Soluble organic nondegradable
Symbol
Q
COD
SA
SS
SI
XS
XI
TSS
VSS
NVSS
SNH
SNO
SNS
SNI
Input/Output
I
I
I
I
I
I
I
I
I
I
I
I
I
I
Process
Sub-process
Stream
Parameter
N
Particulate organic degradable
N
Particulate organic
nondegradable N
Phosphate
Soluble organic degradable P
Soluble organic nondegradable
P
Particulate organic degradable
P
Particulate organic
nondegradable P
Dissolved oxygen
Alkalinity
Temperature
pH
Flow
COD
Volatile fatty acids
Soluble degradable COD
Soluble nondegradable COD
Particulate degradable COD
Particulate nondegradable COD
Suspended solids
Volatile suspended solids
Nonvolatile suspended solids
Ammonia
Nitrate
Soluble organic degradable N
Soluble organic nondegradable
N
Particulate organic degradable
N
Particulate organic
nondegradable N
Phosphate
Soluble organic degradable P
Soluble organic nondegradable
P
Particulate organic degradable
P
Particulate organic
nondegradable P
Dissolved oxygen
Alkalinity
Temperature
pH
Symbol
Input/Output
XNS
XNI
SPO4
SPS
SPI
I
I
I
XPS
XPI
SO2
SALK
T
pH
Q
COD
SA
SS
SI
XS
XI
TSS
VSS
NVSS
SNH
SNO
SNS
SNI
I
I
I
I
O
O
O
O
O
O
O
O
O
O
O
O
O
O
XNS
XNI
SPO4
SPS
SPI
O
O
O
XPS
XPI
SO2
SALK
T
pH
O
O
O
O
Process
Activated
sludge
Sub-process
ASM 1
ASM 2
ASM 3
Settling tank
2.4
Parameter
Soluble degradable COD
Symbol
SS
Input/Output
O
SI
XS
XI
SNH
SNO
SO2
XH
XA
SA
SS
SI
XS
XI
TSS
SNH
SNO
SPO4
SO2
SALK
T
SS
SI
XS
XI
SNH
SNO
SO2
XH
XA
SALK
TSS
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
O
3 WRAPPING
The standard OMI specification is written around Microsofts .NET architecture, with all
provided components written using C#, and all examples provided also using C#. Older
applications, such as STOAT, are not yet ready to be fully migrated to a .NET environment.
Because of this, the OMI system provides for wrappers small pieces of code that make use
of OMI components to handle much of the OMI processing, and are completely hidden from
the developer. All that the developer has to do is to implement the OMI Interfaces to the OMI
environment; additional interfaces to the original application, mapping between .NET and the
main program; and specify any custom behaviour required by the wrapping exercise. This
incurs an additional processing overhead, so that simulations will be slower but how
significant the communication overhead is will be reported upon during the testing phase. The
other implication is that the footprint of the applications is larger. For example, STOAT will
require installing its current run-time support files, for Visual Basic and Visual Fortran, and in
addition the .NET runtime support. However, many of these files are now provided as a
standard part of Microsofts operating systems, as they are shared by any application using
.NET or Visual Basic.
There are two main wrapper components. The first is a relatively trivial piece of code that
creates an object that will implement the main code. The second component, then, is the main
part of the wrapper, and this implements the needed OMI Interfaces.
3.1
Linkable engine
The linkable engine provides a level of indirection to the main code. All that is needed is that a
class member, _engineApiAccess, is set to an instance of the main code in this case,
STOATEngine. The code is listed below, excluding various directives to import namespaces.
namespace WRc.OMI
// All WRc OMI objects will be in this namespace.
{public class STOAT : LinkableEngine
// LinkableEngine hides much of the OMI work
{protected override void SetEngineApiAccess()
// Just this to implement
{_engineApiAccess = new STOATEngine();}
// Create a reference to the
// main work engine
}
}
3.2
Migration
The implicit mental model behind the OMI wrapping system was that the original program
provided a clean separation between the user interface, which would generate any required
data files, and the computational engine. The user interface would be run, which would create
data files. Then an additional data file would be created, which would contain information
about the OMI usage (this data file is discussed further in Section 3.4). The computational
engine would be rewritten as a DLL, and this DLL would be called directly by the wrapper.
STOAT is written with close coupling between the user interface and the computational
engine, where the user interface generates all data needed at each timestep, calls the
computational parts, and the processes the results. There is no provision for file handling
within the computational core. Because of this difference between the expected model and
STOAT the STOAT OMI implementation runs the main program. At present the STOAT user
interface is also displayed during OMI-based simulations, so that results can be displayed as
they are being calculated.
The wrapper core expects that the following should be implemented:
namespace WRc.OMI
// Must be same namespace as used for ILinkableEngine
{public class STOATEngine: IEngine
// This will be the main work engine
{// Long description of simulation
string IEngine.GetModelDescription()
// Short description of simulation
string IEngine.GetModelID()
// Number of items that can be provided to STOAT
int IEngine.GetInputExchangeItemCount()
// Description of data items that STOAT can use
InputExchangeItem IEngine.GetInputExchangeItem(int exchangeItemIndex)
// Repeat for items that STOAT can provide to other applications
int IEngine.GetOutputExchangeItemCount()
OutputExchangeItem IEngine.GetOutputExchangeItem(int exchangeItemIndex)
// Period for next simulation timestep
ITimeSpan IEngine.GetTimeHorizon()
// Close STOAT completely
void IRunEngine.Dispose()
// Close the current simulation
void IRunEngine.Finish()
// Long description of STOAT
string IRunEngine.GetComponentDescription()
// Short description of STOAT
string IRunEngine.GetComponentID()
// Time at which STOAT will provide next set of data items
ITime IRunEngine.GetCurrentTime()
// If STOAT is likely to interpolate using earlier values that the current,
// this is used to define how much history must be retained. IRunEngine maintains
// a data buffer, and uses the value of GetEarliestNeededTime to prevent the
// buffer from storing all simulation value since the start of the simulation.
ITimeStamp IRunEngine.GetEarliestNeededTime()
// Time at which STOAT will expect next set of data items
ITime IRunEngine.GetInputTime(string QuantityID, string ElementSetID)
// If data is not available, this is the numeric value that will be used
// to signal this. IrunEngine will then make an appropriate interpolation
// or extrapolation for other programs.
double IRunEngine.GetMissingValueDefinition()
// Get values from STOAT for use by other programs
IValueSet IRunEngine.GetValues(string QuantityID, string ElementSetID)
// Provide values to STOAT
void IRunEngine.SetValues(string QuantityID, string ElementSetID,
IValueSet values)
// Initialise STOAT
void IRunEngine.Initialize(System.Collections.Hashtable properties)
// Carry out a single timestep
bool IRunEngine.PerformTimeStep()
}
}
10
No changes were made to the engine core, in the sense of splitting the computational engine
from the user interface. New methods were added to the user interface to support the OMI
interface.
Because STOAT will be controlled directly by another program it must be compiled as a COM
component, in this case as an ActiveX executable. On being instantiated it must detect and
take appropriate action. The main subroutine (the starting point for a Visual Basic application)
contains the following check
If App.StartMode = vbSModeAutomation Then // Controlled by another program
giTVPClass = TVP_L3
// Set a flag that this is the case.
The STOAT Visual Basic OMI interface was written to duplicate, as closely as possible, the
OMI C# methods. To this end various support classes were written, to provide a match on
methods. These methods are:
CEnums: provides enumerated constants for dimensions and elements (only the
IDBased element is used by STOAT at present).
CDimension: class to hold dimensions of unit, e.g. m3/s.
CUnit: Linear conversion to SI units SI equivalent = a + b x value.
CQuantity: amalgamates units (conversion information to SI) and dimensions.
InputExchangeItem: Amalgamates elements and quantities, to provide a basic class
used for exchanging data.
OutputExchangeItem: Amalgamates elements and quantities, to provide a basic class
used for exchanging data.
ITimeSpan: a time period, delimited by a start and end.
IValueSet: An array of double precision values, used to hold the numerical values
being exchanged and described by InputExchangeItem (or OutputExchangeItem).
CElement: not used, but implemented for completeness of the definition of input and
output exchange items.
CSpatialRef: not used, but implemented for completeness of the definition of input and
output exchange items.
Each wrapper method then has a corresponding Visual Basic implementation. These are
described in parallel in the following sections.
11
3.2.2
The C# code was written, using the wrapper, with the details given below. As well as providing
references to the main OMI components, an additional reference was required to STOAT.
Aside from STOAT, the following components had to be referenced:
org.OpenMI.Backbone
org.OpenMI.DevelopmentSupport
org.OpenMI.Standard
org.OpenMI.Utilities.Buffer
org.OpenMI.Utilities.Spatial
org.OpenMI.Utilities.Wrapper
System
System.Data
System.XML
3.2.3
The functions in STOAT were chosen to map directly onto the functions exposed by the
wrapper. Therefore the STOAT functions are described in parallel with the wrapper functions.
3.2.4
Implementing MyEngineDotNetAccess
Implementing MyModelOpenMIComponent
Four global objects were defined for the class, to map onto the STOAT classes.
STOAT4.HarmonIT
STOAT4.InputExchangeItem
STOAT4.OutputExchangeItem
STOAT4.IValueSet
LSTOAT;
STOAT_In;
STOAT_Out;
STOAT_Val;
12
The wrapper code in large part calls the STOAT Visual Basic equivalents. There may be a
need to explicitly assign from STOAT return values to wrapper values, where
structures/classes are used to hold the return values. In the following, the wrapper (using C#)
is written in black while the main STOAT program, written in Visual Basic, is written in red.
string IEngine.GetModelDescription()
{return LSTOAT.GetModelDescription();}
// Pass-through to VB
// Pass-through to VB
// As GetModelDescription, but
// replacing spaces with underscores
Dim s As String
s = "Works " & gCurrentWorks.iID & ": Run " & gCurrentRun.iID
s = Replace(s, " ", "_")
GetModelID = s
End Function
int IEngine.GetInputExchangeItemCount()
{return LSTOAT.GetInputExchangeItemCount();
// Pass-through to VB}
LSTOAT.GetInputExchangeItem(exchangeItemIndex);
STOAT_In.Element.get_Description();
// VB copy to C#
STOAT_In.Element.get_ID();
new ElementSet(sDescription, sID, ElementType.IDBased,
new SpatialReference());
// Assemble C# struct
// Repeat for units details not shown
// repeat for quantity details not show
return item;
}
=
=
=
=
13
14
{return LSTOAT.GetOutputExchangeItemCount();
// Pass-through to VB}
GetOutputExchangeItemCount = iCount
ReDim Outputs(0 To iCount)
NumberOfOutputItems = iCount
End Function
// A repeat of InputExhange, substituting Output for Input
OutputExchangeItem IEngine.GetOutputExchangeItem(int exchangeItemIndex)
Public Function GetOutputExchangeItem(ByVal ItemIndex As Long) As OutputExchangeItem
iModel = 0
// First, map the exchange item index onto a process or stream, and an exchange item for
// that process or stream.
For i = 1 To giNumberOfProcesses
If Not WorksProcess(i).bDeleted Then
iStages = WorksProcess(i).iNumberOfStages
Select Case WorksProcess(i).iType
Case STW_ASAL
Select Case WorksProcess(i).iModelID
Case MDL_IAWQ1, MDL_IAWQ1_BENCH, MDL_ASM1A, MDL_ASM1B
// Have we reached the relevant process?
If iCount + NUMBER_OF_ASM1_EXCHANGE_VALUES * iStages > ItemIndex Then
iModel = 1
// If yes, record the process type
iType = ItemIndex iCount // Record the process exchange item
iStages = 1
// Map it onto the required stage
Do While iType >= NUMBER_OF_ASM1_EXCHANGE_VALUES
iType = iType - NUMBER_OF_ASM1_EXCHANGE_VALUES
15
iStages = iStages + 1
Loop
sName = WorksProcess(i).sName & ": Stage " & Trim$(iStages)
Exit For
// And quit
End If
// If this is not the relevant process, increment the number of exchange items for which
// we have searched, and proceed to the next process
iCount = iCount + NUMBER_OF_ASM1_EXCHANGE_VALUES * iStages
Case MDL_IAWQ2D, MDL_IAWQ2W, MDL_ASM2D, MDL_ASM2W
// Similar code for other processes deleted for clarity
End Select
End If
Next i
// If no match found when searching for processes, continue searching for streams
If iModel = 0 Then
For i = 1 To giNumberOfLinks
If Not WorksLink(i).bDeleted Then
If iCount + NUMBER_OF_STREAM_EXCHANGE_VALUES > ItemIndex Then
iModel = -1
iType = ItemIndex - iCount
sName = WorksLink(i).sName
Exit For
End If
iCount = iCount + NUMBER_OF_STREAM_EXCHANGE_VALUES
End If
Next i
End If
// Assign dimensions
fOffset = 0: fMultiplier = 1
Set tDim = New CDimension
tDim.SetAll -3, 1
' Will over ride where needed
sUnit = "kg/m"
Select Case iModel
Case -1
Select Case iType
Case 0: sComp = "Q":
sDescription = "Flow": tDim.SetAll 3, 0, -1: sUnit = "m/s"
Case 1: sComp = "COD":
sDescription = "Total COD"
// Similar code deleted for clarity
End Select
' Record results for local use
With Outputs(ItemIndex)
.iStage = iStages
If iModel > 0 Then
.iType = PROCESS
Else
.iType = STREAM
End If
.iUnit = i
.sParameter = sComp
.sLabel = sName
.fSIMult = fMultiplier
.fSIOffset = fOffset
End With
Set tResult = New OutputExchangeItem
With tResult
With .Element
.ID = sName
.Description = sName
End With
With .Quantity
.SetDimension tDim
.ID = sComp
.Description = sDescription
16
With .Unit
.ID = sUnit
.Description = sUnit
.ConversionFactorToSI = fMultiplier
.OffsetToSI = fOffset
End With
End With
End With
Set GetOutputExchangeItem = tResult
End Function
ITimeSpan IEngine.GetTimeHorizon()
{ STOAT4.ITimeSpan T = LSTOAT.GetTimeHorizon();
// Pass-through to VB
TimeStamp start = new TimeStamp(T.Start);
// Transfer to C# equivalents
TimeStamp finish = new TimeStamp(T.Finish);
return new org.OpenMI.Backbone.TimeSpan(start,finish);
}
Public Function GetTimeHorizon() As ITimeSpan
Dim cReturn As New ITimeSpan
cReturn.Start = ToModifiedJulian(CDbl(gCurrentRun.varStartTime))
cReturn.Finish = ToModifiedJulian(CDbl(gCurrentRun.varEndTime))
Set GetTimeHorizon = cReturn
End Function
3.2.8
// Simulation start
// Simulation end
3.3.1
// COD -> SA
=
=
=
=
new
new
new
new
STOAT4.HarmonITClass();
STOAT4.InputExchangeItemClass();
STOAT4.OutputExchangeItemClass();
STOAT4.IValueSetClass();
// Initialise STOAT
bReturn = LSTOAT.Initialize(sDatabase, iWorksID, iRunID, iOldRunID,
iStartCondition, bReuseExistingRun, sRunName);
LSTOAT.SetConstants(ss, si, xs, xi, sa, sol_ss, sol_si, sol_sns, sol_sni,
sol_sps, sol_spi, sol_xs, sol_xi, sol_xns, sol_xni,
sol_xps, sol_xpi);
}
' iWorksID -- the works ID that shall be used. This will be stored within the OMI file
' iRunID -- the run ID that shall be used. This may be modified - see below
' iOldRunID -- if a run is to be created based on a previous run
17
'
A value of -1 means do not use this
' iStartCondition - 0:: Start from beginning
'
1:: Start from end
'
2:: Start from end, preserve operational settings
' bReuse -- TRUE -- if the run ID has been used, overwrite it
'
FALSE append as the next available run slot
'
Public Function Initialize(ByVal sDatabase As String, _
ByVal iWorksID As Integer, ByVal iRunID As Integer, _
ByVal iOldRunID As Integer, ByVal iStartCondition As Integer,
_
ByVal bReuse As Boolean, ByVal sRunName As String) As Boolean
// Change the database to the one to be used for this simulation
If gdbUser Is Nothing Then
QuietChangeDatabase sDatabase
ElseIf gdbUser.Name <> sDatabase Then
QuietChangeDatabase sDatabase
End If
// Open the works
gOpenBatchWorks iWorksID
// Open the reun
gbCreateOMIWarmStartRun iRunID, iOldRunID, iStartCondition, bReuse, sRunName
// Set various internal parameters to a state that indicates that a simulation may proceed
SetRunMode True
Initialize = True
gbStandardRun = False ' Disable end of run message
NumberOfInputItems = -1
NumberOfOutputItems = -1
frmIconMenu.Hide
End Function
3.3.2
18
// Assign to the
// relevant influent
End Select
End Sub
Public Sub gSetOMIStreamData(iStream As Integer, sComp As String, fVal As Single)
Dim i
As Integer
Dim j
As Integer
Static bCalled
As Boolean
' Defaults to FALSE
Static dLastTime As Double
// The first time this is used in a simulation the LastTime is set to 1
// There is not always a one-to-one mapping between input exchange items and the STOAT
// usage, so that the start of each timestep needs to be recorded, and then as data is
// exchanged the relevant transformations are carried out.
If Not bCalled Then
bCalled = True
dLastTime = -1
End If
19
// existing value
.fComponent(PART_BOD) = .fComponent(PART_BOD) _
+ fVal * (1 - omi_sol_ss)
End If
mInfluentRun(j).Reset(1) = False
// Similar code removed for clarity
End Select
End With
Next i
End Sub
3.3.3
20
3.3.4
21
3.4
The OMI XML file is written through the Visual Basic interface.
The user can access the following screen:
22
3.5
Following the development of a larger use case for a paper, there was a need to link STOAT
with Wallingford Softwares SULIS program. SULIS works with BOD, requiring provision of
dissolved and attached BOD. The Wallingford Software river model, InfoWorks RS, could
provide COD as dissolved and attached fractions.
STOAT was modified to provide support for these fractions, both on input and output for
streams. The approach is indicated in the following figures.
23
BOD
F1
1 - F1
Dissolved BOD
Attached BOD
F2S
F2P
Dissolved
degradable COD
Attached
degradable COD
1 F3P
1 F3S
F3S
F3P
Dissolved
nondegradable
COD
Attached
nondegradable
COD
1 F4S
1 F4S
Soluble
degradable COD
Soluble
nondegradable
COD
Particulate
degradable COD
F4S
F4S
24
Particulate
nondegradable
COD
STOAT Testing did not use the unit-testing approach, because the bulk of the STOAT code
was in a Visual Basic environment for which a suitable unit-based testing framework was not
available. Testing instead proceeded using primarily the insertion of print statements (in a
Windows environment, MessageBox calls), along with the DataMonitor component in the
OpenMI configuration editor.
The STOAT code was implemented easily, following the guidelines given in the OpenMI
Guidelines publication and also the example framework provided during the December 2004
OpenMI training course. The main bug found was associated with the limited error checking
carried out by the OpenMI configuration editor, when one (large) STOAT flowsheet was
replaced by another (smaller) flowsheet, without updating the composition data file created by
the configuration editor. The substitution of a small flowsheet for a larger one was required
because of the implementation of the configuration editor, which requeried for configuration
data following each mouse click with the large flowsheet this resulted in each mouse click
being followed by a delay of around 15 minutes while the (unchanged) data was being
requeried.
An updated configuration editor was provided, as this problem had been recognised by the
OpenMI development team, but this failed to parse the XML OMI configuration files correctly.
Testing therefore continued using the original configuration editor, pending a release of the
next OpenMI update.
The DataMonitor was used to ensure that the output from STOAT, through the OpenMI
GetValues routine, matched the values being generated in STOAT. At that stage testing was
halted, until the OpenMI update was available.
Further testing of STOAT was done as part of preparation for a paper, submitted to the
ModSim05 conference, discussing experience of using the OpenMI to link different programs
together. This testing made use of the updated configuration editor, where usability for
creating OpenMI compositions had greatly improved.
The testing revealed three main bugs in the STOAT implementation:
1. The OMI file was not properly formed, and the argument parameters Key and Value were
case-sensitive when they had been specified as key and value they had not been
correctly parsed. An earlier version of the configuration editor had not had been case
sensitive, not had it complained about ill-formed XML.
2. The routine GetInputExchangeItemCount is called many times. Each time it is called the
STOAT implementation created local storage space for the exchange items, and cleared
the storage. The local storage values are then assigned during the calls to
GetInputExchangeItem. However, after GetInputExchangeItem had been called there
were additional calls to GetInputExchangeItemCount, and these destroyed the values
assigned to the local copy of the InputExchangeItems. When data was being exchanged
through calls to SetValue STOAT was not able to locate the exchanged data items. The
solution adopted to this problem was to check if GetInputExchangeItemCount had been
previously called, and if so to return the previous count, rather than destroy the local
storage space.
25
3. Elapsed times are stored as double precision numbers. The OpenMI configuration editor
appears to expect that the smallest unit of time is the second. As long as GetCurrentTime
and similar time routines returned times that could be expressed as an integer number of
seconds the configuration editor would run OpenMI compositions. However, if a rounding
error (as found when using a timestep of 0.01 hours, because 0.01 is not an exact binary
fraction) led to times that had a fractional second, then the configuration editor would halt
a simulation with a failure message. The solution here was to calculate the time and to
ensure that it was always rounded to an integral number of seconds; in Visual Basic this
was implemented as CLng(3600 x Elapsed time in hours). The CLng function in Visual
Basic rounds to the nearest integer, with rounding to even for the special case where the
fractional part is exactly 0.5.
26
5.1
Linking
STOAT was first linked with STOAT, running the output from one STOAT into a second. It
was then run with the test case, InfoWorks CS feeding STOAT, which in turn fed InfoWorks
RS. Finally, two instances of STOAT were used as part of a large configuration, described in
Appendix 7.
This section describes the output of the case where InfoWorks CS provided the input to
STOAT, and STOAT the input to InfoWorks RS.
There were no problems with linking the models. The layouts of the three models are given in
Figure 5.1 (InfoWorks CS), Figure 5.2 (STOAT) and Figure 5.3 (InfoWorks RS). The linking of
these three models was done using the OpenMI configuration editor, and is shown in Figure
5.4.
Figure 5.1
27
Figure 5.2
Figure 5.3
28
CS, RS and
STOAT models
described in this
section
Figure 5.4
When loading saved configurations STOAT produces OMI files that by default create a new
instance of a run for each simulation. Because it was new run, with a new ID number, the
configuration editor was unable to recreate the configuration. STOAT also has the option with
the OMI files to use an existing run, so that the run ID will be the same for each usage. With
this option the configuration editor proceeded with no problems. STOAT has been modified to
make this the default behaviour when creating an OMI file.
5.2
Running
There were no problems running STOAT, once the two problems described in Section 4 had
been resolved. These problems were failure of SetValues to locate the passed input items,
29
and the rounding errors in time calculations resulting in simulations being stopped early with a
failure message because the time was not an integer number of seconds.
5.3
Results
The results were passed correctly between the different programs. There was a need to
ensure that the timesteps used by all three programs were the same, as otherwise peaks in
flow and quality could be missed (if they did not occur on a communication timestep) or
sustained for too long (because interpolation within the programs was on the communicated
values.)
InfoWorks CS programs uses units of m3/s and kg/m3, STOAT m3/h and mg/l (g/m3), and
InfoWorks RS m3/s and mg/l. Therefore the scaling of a factor of 1000 between STOAT and
the InfoWorks results should be used when viewing the following figures. These results show
that while linking is feasible the philosophy behind the OpenMI, the modelling of large
catchments linking different modelling programs, will in future need to provide better means
for aggregating results from the disparate programs for easier comprehension.
Results are shown below for flow, suspended solids and ammonia transmitted between the
three programs, demonstrating that the values are being passed correctly in time and
magnitude. The STOAT implementation of the OpenMI is compatible with that used by
Wallingford Software in InfoWorks RS and InfoWorks CS.
30
5.4
5.4.1
Figure 5.5
Figure 5.6
Peak 3.9 m3/s (14,040 m3/h) correct. Baseline 2.2 m3/s (7,920 m3/h) correct.
31
5.4.2
Suspended solids
Figure 5.7
Figure 5.8
Peak 0.027 g/l; missed. STOAT peak of 20 mg/l. Most likely reason is one of timestep
communication. The peak from CS is clearly seen in STOAT, so data transmission is taking
place, but a smaller timestep may be needed to fully capture the peak. The timestep used was
60 seconds.
32
Figure 5.9
Figure 5.10
Diurnal peaks around 0.0006, 0.0008 and 0.001 g/l. These are captured by STOAT.
33
5.4.3
Ammonia
Figure 5.11
Figure 5.12
Peak of 0.0007 g/l; second peak 0.00036; third and fourth peaks 0.0004 g/l. STOAT peaks are
0.7 mg/l (OK), 0.36 (OK), and 0.4 (OK).
34
5.5
5.5.1
Figure 5.13
Figure 5.14
35
5.5.2
Suspended solids
Figure 5.15
Figure 5.16
Two peaks around 11 mg/l, picked up by RS, and a baseline around 8 mg/l, again picked up
by RS.
36
Figure 5.17
Figure 5.18
Ammonia trough around 0.075 mg/l, and rising to 0.11 mg/l. RS values the same.
37
5.6
Experience
Once the components had been tested and signed off working with OpenMI configurations
proved remarkably straight-forward. Initially there was a view that the compositions were
fragile, because of the poor error handling in the configuration editor. However, as the
programs were modified to correct these errors the system became remarkably robust.
The main operational problem then became, with large compositions, that of ensuring that the
component models were correctly connected. The current configuration editor displays all
components as equal-sized shapes of the same colour, so that the visual representation of
the composition does not make it easy to identify the models and ensure that they are indeed
connected correctly. This, however, is because of the prototypical nature of the configuration
editor, and future editors should better address the need for visual feedback during
composition.
The compute speed when STOAT was run with the second model also as STOAT appeared
to be little reduced against a stand-alone STOAT simulation. However, when adding the RS
component the compute speed slowed down considerably, because of the much greater data
exchange taking place between the hydraulics and water quality components of RS. This
indicates that there is a large overhead in the data exchange mechanism used by OpenMI but
that this overhead is only noticeable when large quantities of data are exchanged frequently.
When the data is exchanged between a small number of points, for a small number of
quantities, then the compute speed of the original programs still dominates the overall
execution speed.
With the STOAT to STOAT test the first STOAT sewage works model was designed to
accommodate a flow of 300 m3/h, while the second model was designed to accommodate a
flow of 8,000 m3/h. Running with a communication timestep of 1 hour produced instability in
the second model, caused by the mismatch in the expected flows. When the communication
timestep was reduced to 0.1 h the instability was avoided, as adequate interpolation of the
influent was achieved. Therefore, when carrying out OpenMI simulations, there may be some
initial settling down of the combined model where appropriate communication intervals are
investigated.
The criteria for acceptance of the use case were all successfully met.
38
6.1
The OpenMI has proved remarkably easy to implement in STOAT. There are two
reasons for this.
1. STOAT having a similar architecture to the model data exchange
interface developed from previous work with datasharing between
STOAT and DHIs MOUSE and MIKE products; and
2. The December 2004 training course on the implementation of OMI,
which converted a large, difficult to follow and navigate set of
documents into a short series of easy-to-follow slides. Anyone
planning to implement the OMI would be strongly recommended to
include time and funding to attend a similar conversion course.
6.1.1
Time
Conversion time was not a problem. A total of 11 days was required for the
conversion, with documentation for this report taking another 3 and testing an
additional 2 days, including bug fixes.
6.1.2
The main problem was the immaturity of the existing user interface provided for
testing OMI components. Problems encountered included:
Having imported a component into the project it was sometimes necessary to
close the project and reopen before it was fully enabled; on some cases it
seemed that a reboot was also needed. This has since been fixed.
Every GUI action interrogated the list of available input and output items.
When that list is several thousand then the delay after each GUI action can
run into tens of minutes using a 1 GHz Pentium IV. This has since been
fixed.
There was no detection for inconsistencies in imported projects having
manually edited a project, the interface did not detect that it was no longer
consistent with the models, and crashed elsewhere with internal problems.
The documentation, while comprehensive, is difficult to navigate and difficult
to understand. Most the documentation for the migration support was taken
from the c. 8 pages of code listing provided during the migration training
course. The rewrite of the guidelines document has removed many of the
problems associated with that document.
39
ACKNOWLEDGMENTS
The solution to the time calculation problem, where the OpenMI configuration editor
required that the time should be an integral number of seconds, was developed by
Wiktoria Daniels of Wallingford Software and made available to WRc during the final
round of debugging.
The simulation linking InfoWorks CS, STOAT and InfoWorks RS was also carried out
by Wiktoria Daniels, and the graphs presented in this report were generated by her.
41
43
44
Appendix 1
A1.1
C# Wrapper Code
Engine
using System;
using
using
using
using
org.OpenMI.Standard;
org.OpenMI.Backbone;
org.OpenMI.Utilities.Spatial;
org.OpenMI.Utilities.Wrapper;
namespace WRc.OMI
{
public class STOAT : LinkableEngine
{
protected override void SetEngineApiAccess()
{
_engineApiAccess = new STOATEngine();
}
}
}
A1.2
Main wrapper
org.OpenMI.Standard;
org.OpenMI.Backbone;
org.OpenMI.Utilities.Spatial;
org.OpenMI.Utilities.Wrapper;
namespace WRc.OMI
{
public class STOATEngine : IEngine
{
STOAT4.HarmonIT
LSTOAT;
STOAT4.InputExchangeItem STOAT_In;
STOAT4.OutputExchangeItem STOAT_Out;
STOAT4.IValueSet
STOAT_Val;
45
=
=
=
=
=
STOAT_In.Quantity.Unit.get_ID();
STOAT_In.Quantity.Unit.get_Description();
STOAT_In.Quantity.Unit.ConversionFactorToSI;
STOAT_In.Quantity.Unit.OffsetToSI;
new Unit(sID, fFactor, fOffset, sDescription);
dim.SetPower(DimensionBase.AmountOfSubstance, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eAmountOfSubstance));
dim.SetPower(DimensionBase.Length, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eLength));
dim.SetPower(DimensionBase.Mass, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eMass));
dim.SetPower(DimensionBase.Time, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eTime));
dim.SetPower(DimensionBase.ElectricCurrent, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eElectricCurrent));
dim.SetPower(DimensionBase.Temperature, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eTemperature));
dim.SetPower(DimensionBase.LuminousIntensity, STOAT_In.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eLuminousIntensity));
sDescription = STOAT_In.Quantity.Description;
sID
= STOAT_In.Quantity.ID;
item.Quantity = new Quantity(unit, sDescription, sID,
org.OpenMI.Standard.ValueType.Scalar,
dim);
return item;
}
int IEngine.GetInputExchangeItemCount()
{int iValue;
iValue = LSTOAT.GetInputExchangeItemCount();
return iValue;
}
string IEngine.GetModelDescription()
{return LSTOAT.GetModelDescription();}
string IEngine.GetModelID()
{return LSTOAT.GetModelID();}
46
=
=
=
=
=
STOAT_Out.Quantity.Unit.get_ID();
STOAT_Out.Quantity.Unit.get_Description();
STOAT_Out.Quantity.Unit.ConversionFactorToSI;
STOAT_Out.Quantity.Unit.OffsetToSI;
new Unit(sID, fFactor, fOffset, sDescription);
dim.SetPower(DimensionBase.AmountOfSubstance, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eAmountOfSubstance));
dim.SetPower(DimensionBase.Length, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eLength));
dim.SetPower(DimensionBase.Mass, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eMass));
dim.SetPower(DimensionBase.Time, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eTime));
dim.SetPower(DimensionBase.ElectricCurrent, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eElectricCurrent));
dim.SetPower(DimensionBase.Temperature, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eTemperature));
dim.SetPower(DimensionBase.LuminousIntensity, STOAT_Out.Quantity.Dimension.get_Power(STOAT4.EDimensionType.eLuminousIntensity));
sDescription = STOAT_Out.Quantity.Description;
sID
= STOAT_Out.Quantity.ID;
item.Quantity = new Quantity(unit, sDescription, sID,
org.OpenMI.Standard.ValueType.Scalar,
dim);
return item;
}
int IEngine.GetOutputExchangeItemCount()
{int iValue;
iValue = LSTOAT.GetOutputExchangeItemCount();
return iValue;
}
ITimeSpan IEngine.GetTimeHorizon()
{ STOAT4.ITimeSpan T = LSTOAT.GetTimeHorizon();
TimeStamp start = new TimeStamp(T.Start);
TimeStamp finish = new TimeStamp(T.Finish);
return new org.OpenMI.Backbone.TimeSpan(start,finish);
}
#endregion
47
48
double
double
double
double
double
sDatabase
iWorksID
iRunID
iOldRunID
iStartCondition
bReuseExistingRun
sRunName
sa
ss
si
xs
xi
=
=
=
=
=
=
=
=
=
=
=
=
(string)
short.Parse((string)
short.Parse((string)
short.Parse((string)
short.Parse((string)
bool.Parse( (string)
(string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
properties["Database"];
properties["WorksID"]);
properties["RunID"]);
properties["OldRunID"]);
properties["StartCondition"]);
properties["ReuseExistingRun"]);
properties["RunName"];
properties["SA"]);
properties["SS"]);
properties["SI"]);
properties["XS"]);
properties["XI"]);
// COD -> SA
=
=
=
=
new
new
new
new
=
=
=
=
=
=
double.Parse((string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
double.Parse((string)
properties["sol_BOD"]);
properties["deg_COD"]);
properties["sol_deg_COD"]);
properties["par_deg_COD"]);
properties["sBOD_sCOD"]);
properties["pBOD_pCOD"]);
STOAT4.HarmonITClass();
STOAT4.InputExchangeItemClass();
STOAT4.OutputExchangeItemClass();
STOAT4.IValueSetClass();
49
LSTOAT.SetConstants(ss, si, xs, xi, sa, sol_ss, sol_si, sol_sns, sol_sni, sol_sps, sol_spi,
sol_xs, sol_xi, sol_xns, sol_xni, sol_xps, sol_xpi,
sol_bod, deg_cod, deg_sol, deg_part, sol_cod_to_bod, part_cod_to_bod);
}
bool IRunEngine.PerformTimeStep()
{bool bOK = LSTOAT.PerformTimeStep();
return bOK;}
void IRunEngine.SetValues(string QuantityID, string ElementSetID, IValueSet values)
{double f = ((IScalarSet) values).GetScalar(0);
STOAT_Val.set_Values(0, f);
LSTOAT.SetValues(QuantityID,ElementSetID,STOAT_Val);
}
#endregion
}
}
50
Appendix 2
A2.1
Support types
A2.1.1 CDimension
Option Explicit
Dim mPowers(0 To EDimensionType.NUM_BASE_DIMENSIONS)
Public Property Get Power(Quantity As EDimensionType) As Long
Power = mPowers(Quantity)
End Property
Public Property Let Power(Quantity As EDimensionType, iValue As Long)
mPowers(Quantity) = iValue
End Property
Public Sub SetAll(Optional iLength As Long = 0, Optional iMass As Long = 0, _
Optional iTime As Long = 0, Optional iCurrent As Long = 0, _
Optional iTemperature As Long = 0, Optional iMolarity As Long = 0, _
Optional iLuminosity As Long = 0, Optional iCurrency As Long = 0)
mPowers(eAmountOfSubstance) = iMolarity
mPowers(eCurrency) = iCurrency
mPowers(eElectricCurrent) = iCurrent
mPowers(eLength) = iLength
mPowers(eLuminousIntensity) = iLuminosity
mPowers(eMass) = iMass
mPowers(eTemperature) = iTemperature
mPowers(eTime) = iTime
End Sub
A2.1.2 CElement
Dim sDescription
Dim sID
Dim mSpatialRef
As String
As String
As New CSpatialRef
51
Description = sDescription
End Property
Public Property Let Description(s As String)
sDescription = s
End Property
Public Property Get ID() As String
ID = sID
End Property
Public Property Let ID(s As String)
sID = s
End Property
Public Property Get SpatialRef() As CSpatialRef
SpatialRef = mSpatialRef
End Property
Public Property Let SpatialRef(x As CSpatialRef)
mSpatialRef = x
End Property
52
A2.1.3 CEnums
Enum EElementType
IDBased
XYLine
XYPoint
XYPolygon
XYPolyLine
XYZLine
XYZPoint
XYZPolygon
XYZPolyhedron
XYZPolyLine
End Enum
Enum EDimensionType
eLength
eMass
eTime
eElectricCurrent
eTemperature
eAmountOfSubstance
eLuminousIntensity
eCurrency
NUM_BASE_DIMENSIONS
End Enum
A2.1.4 CQuantity
Public Unit
Public Dimension
Private sID
Private sDescription
As
As
As
As
New CUnit
New CDimension
String
String
53
End Sub
Public Property Get Description() As String
Description = sDescription
End Property
Public Property Let Description(ByVal vNewValue As String)
sDescription = vNewValue
End Property
Public Property Get ID() As String
ID = sID
End Property
Public Property Let ID(ByVal vNewValue As String)
sID = vNewValue
End Property
A2.1.5 CSpatialRef
Dim mX
Dim mY
Dim mZ
As Double
As Double
As Double
54
mX = vx
End Property
Public Property Let y(vy As Double)
mY = vy
End Property
Public Property Let z(vz As Double)
mZ = vz
End Property
Private Sub Class_Initialize()
mX = 0: mY = 0: mZ = 0
End Sub
Public Sub SpatialRef(x As Double, y As Double, z As Double)
mX = x: mY = y: mZ = z
End Sub
A2.1.6 CUnit
Dim
Dim
Dim
Dim
msID
mfConversionFactor
mfOffset
msDescription
As
As
As
As
String
Double
Double
String
55
ID = msID
End Property
Public Property Let Description(s As String)
msDescription = s
End Property
Public Property Get Description() As String
Description = msDescription
End Property
Public Sub Unit(sID As String, fConversionFactor As Double, fOffset As Double, sDescription As String)
msID = sID
mfConversionFactor = fConversionFactor
mfOffset = fOffset
msDescription = sDescription
End Sub
Private Sub Class_Initialize()
msID = ""
mfConversionFactor = 1#
mfOffset = 0
msDescription = ""
End Sub
A2.1.7 InputExchangeItem
Public Element
Public Quantity
As New CElement
As New Cquantity
A2.1.8 ITimeSpan
Public Start
As Double
Public Finish As Double
Private Sub Class_Initialize()
Start = 0
Finish = 0
End Sub
A2.1.9 IValueSet
Option Explicit
56
Dim iCount
As Long
Dim fValues() As Double
Public Property Get Count() As Long
Count = iCount
End Property
Public Property Get Values(ByVal i As Long) As Double
Values = fValues(i)
End Property
Public Property Let Values(ByVal i As Long, ByVal a As Double)
If i > iCount Then
iCount = i
ReDim Preserve fValues(0 To iCount)
End If
fValues(i) = a
End Property
Private Sub Class_Initialize()
ReDim fValues(0 To 0)
iCount = -1
End Sub
A2.1.10
OutputExchangeItem
Public Element
Public Quantity
As New CElement
As New Cquantity
57
Appendix 3
Option Explicit
Dim sCompletedRuns
Dim sStartedRuns
Public bCancel
OMI Creator
As String
As String
As Boolean
58
End If
End Sub
Private Sub cmbButtons_Click(Index As Integer)
Dim i As Long
Select Case Index
Case 0: bCancel = False
' Basic validation checks
' 1. Any cell red? Or does not contain a valid number?
For i = 0 To 4
If txtCOD(i).BackColor = vbRed Then
MsgBox "All COD fractions must be in the range 0 .. 1. Please correct the entries marked in red."
Exit Sub
ElseIf Not IsNumeric(txtCOD(i).Text) Then
txtCOD(i).Text = 0
End If
Next i
For i = 0 To 5
If txtParticulate(i).BackColor = vbRed Then
MsgBox "All 'Apparent soluble' fractions must be in the range 0 .. 1. Please correct the entries marked in red."
Exit Sub
ElseIf Not IsNumeric(txtParticulate(i).Text) Then
txtParticulate(i).Text = 0
End If
Next i
For i = 0 To 5
If txtSoluble(i).BackColor = vbRed Then
MsgBox "All 'true soluble' fractions must be in the range 0 .. 1. Please correct the entries marked in red."
Exit Sub
ElseIf Not IsNumeric(txtSoluble(i).Text) Then
txtSoluble(i).Text = 0
End If
Next i
For i = 0 To 5
If txtBOD(i).BackColor = vbRed Then
MsgBox "BOD cannot exceed COD, nor can the fractions exceed 1."
Exit Sub
End If
Next i
' 2. Check sums
If CDbl(txtCOD(0).Text)
+ CDbl(txtCOD(2).Text)
+ CDbl(txtCOD(4).Text)
MsgBox "COD fractions
Exit Sub
End If
+ CDbl(txtCOD(1).Text) _
+ CDbl(txtCOD(3).Text) _
<> 1 Then
must sum to 1.0"
59
60
61
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
iFile,
iFile,
iFile,
iFile,
iFile,
iFile,
iFile,
"Database", gdbUser.Name
"WorksID", CStr(gCurrentWorks.iID)
"RunID", CStr(iRunID)
"OldRunID", CStr(iOldRunID)
"StartCondition", CStr(iChosenOption)
"ReuseExistingRun", CStr(CBool(Me.chkUseExisting.Value <> 0))
"RunName", Me.txtRunName.Text
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
iFile,
iFile,
iFile,
iFile,
iFile,
"SS",
"SI",
"XS",
"XI",
"SA",
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
iFile,
iFile,
iFile,
iFile,
iFile,
iFile,
"Sol_SS", Me.txtSoluble(0).Text
"Sol_SI", Me.txtSoluble(1).Text
"Sol_SNS", Me.txtSoluble(2).Text
"Sol_SNI", Me.txtSoluble(3).Text
"Sol_SPS", Me.txtSoluble(4).Text
"Sol_SPI", Me.txtSoluble(5).Text
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
iFile,
iFile,
iFile,
iFile,
iFile,
iFile,
"Sol_XS", Me.txtParticulate(0).Text
"Sol_XI", Me.txtParticulate(1).Text
"Sol_XNS", Me.txtParticulate(2).Text
"Sol_XNI", Me.txtParticulate(3).Text
"Sol_XPS", Me.txtParticulate(4).Text
"Sol_XPI", Me.txtParticulate(5).Text
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
PrintArg
iFile,
iFile,
iFile,
iFile,
iFile,
iFile,
"sBOD_sCOD", Me.txtBOD(0).Text
"pBOD_pCOD", Me.txtBOD(1).Text
"deg_COD", Me.txtBOD(2).Text
"sol_BOD", Me.txtBOD(3).Text
"sol_deg_COD", Me.txtBOD(4).Text
"par_deg_COD", Me.txtBOD(5).Text
Print
Print
Print
Close
End If
End Sub
Me.txtCOD(0).Text
Me.txtCOD(1).Text
Me.txtCOD(2).Text
Me.txtCOD(3).Text
Me.txtCOD(4).Text
62
63
64
Appendix 4
Main code
'
' COM interface for OpenMI system
'
' Defined input values
Const NUMBER_OF_INFLUENT_EXCHANGE_VALUES = 29
' Defined output values
Const NUMBER_OF_STREAM_EXCHANGE_VALUES = 29
Const NUMBER_OF_ASM1_EXCHANGE_VALUES = 9
Const NUMBER_OF_ASM2_EXCHANGE_VALUES = 13
Const NUMBER_OF_ASM3_EXCHANGE_VALUES = 11
Const NUMBER_OF_FST_EXCHANGE_VALUES = 1
Dim Inputs() As RecordData
Dim Outputs() As RecordData
Dim NumberofInputItems As Long
Dim NumberOfOutputItems As Long
Const PROCESS = 1
Const STREAM = 2
65
' -------------- Start of items defined under IEngine ----------------------Public Function GetTimeHorizon() As ITimeSpan
Dim cReturn As New ITimeSpan
cReturn.Start = ToModifiedJulian(CDbl(gCurrentRun.varStartTime))
cReturn.Finish = ToModifiedJulian(CDbl(gCurrentRun.varEndTime))
Set GetTimeHorizon = cReturn
End Function
Public Function GetInputExchangeItemCount() As Long
Dim i
As Long
Dim iCount As Long
If NumberofInputItems <> -1 Then
GetInputExchangeItemCount = NumberofInputItems
Exit Function
End If
iReturn = 0
For i = 1 To giNumberOfProcesses
If Not WorksProcess(i).bDeleted Then
Select Case WorksProcess(i).iType
Case STW_INFL, STW_IND, STW_LAND
iCount = iCount + NUMBER_OF_INFLUENT_EXCHANGE_VALUES
End Select
End If
Next i
GetInputExchangeItemCount = iCount
ReDim Preserve Inputs(0 To iCount)
NumberofInputItems = iCount
End Function
Public Function GetInputExchangeItem(ByVal ItemIndex As Long) As InputExchangeItem
Dim i
As Long
Dim iCount
As Long
Dim iWanted
As Long
Dim iItem
As Long
Dim sComp
As String
Dim sDescription As String
Dim fMultiplier
As Double
Dim fOffset
As Double
Dim tResult
As InputExchangeItem
Dim tDim
As CDimension
Dim sUnit
As String
iWanted = Int(ItemIndex / NUMBER_OF_INFLUENT_EXCHANGE_VALUES) + 1
iItem = ItemIndex Mod NUMBER_OF_INFLUENT_EXCHANGE_VALUES
For i = 1 To giNumberOfProcesses
If Not WorksProcess(i).bDeleted Then
66
67
.iType = PROCESS
.iUnit = i
.sParameter = sComp
.fSIMult = fMultiplier
.fSIOffset = fOffset
.sLabel = WorksProcess(i).sName
End With
68
69
70
If iModel = 0 Then
For i = 1 To giNumberOfLinks
If Not WorksLink(i).bDeleted Then
If iCount + NUMBER_OF_STREAM_EXCHANGE_VALUES > ItemIndex Then
iModel = -1
iType = ItemIndex - iCount
sName = WorksLink(i).sName
Exit For
End If
iCount = iCount + NUMBER_OF_STREAM_EXCHANGE_VALUES
End If
Next i
End If
fOffset = 0: fMultiplier = 1
Set tDim = New CDimension
tDim.SetAll -3, 1
' Will over ride where needed
sUnit = "kg/m"
Select Case iModel
Case -1
Select Case iType
Case 0: sComp = "Q":
sDescription = "Flow": tDim.SetAll 3, 0, -1: sUnit = "m/s"
Case 1: sComp = "COD":
sDescription = "Total COD"
Case 2: sComp = "SA":
sDescription = "Volatile fatty acid as COD"
Case 3: sComp = "SS":
sDescription = "Soluble degradable COD"
Case 4: sComp = "SI":
sDescription = "Soluble nondegradable COD"
Case 5: sComp = "XS":
sDescription = "Particulate degradable COD"
Case 6: sComp = "XI":
sDescription = "Particulate nondegradable COD"
Case 7: sComp = "sCOD":
sDescription = "Soluble COD"
Case 8: sComp = "pCOD":
sDescription = "Particulate COD"
Case 9: sComp = "BOD":
sDescription = "BOD5"
Case 10: sComp = "sBOD": sDescription = "Soluble BOD"
Case 11: sComp = "pBOD": sDescription = "Particulate BOD"
Case 12: sComp = "TSS":
sDescription = "Suspended solids"
Case 13: sComp = "VSS":
sDescription = "Volatile suspended solids"
Case 14: sComp = "NVSS": sDescription = "Nonvolatile suspended solids"
Case 15: sComp = "SNH":
sDescription = "Ammonia"
Case 16: sComp = "SNO":
sDescription = "Nitrate"
Case 17: sComp = "SNS":
sDescription = "Soluble degradable organic N"
Case 18: sComp = "SNI":
sDescription = "Soluble nondegradable organic N"
Case 19: sComp = "XNS":
sDescription = "Particulate degradable organic N"
Case 20: sComp = "XNI":
sDescription = "Particulate nondegradable organic N"
Case 21: sComp = "SPO4": sDescription = "Phosphate"
Case 22: sComp = "SPS":
sDescription = "Soluble degradable organic P"
Case 23: sComp = "SPI":
sDescription = "Soluble nondegradable organic P"
Case 24: sComp = "XPS":
sDescription = "Particulate degradable organic P"
Case 25: sComp = "XPI":
sDescription = "Particulate nondegradable organic P"
Case 26: sComp = "SO2":
sDescription = "Dissolved oxygen"
Case 27: sComp = "SALK": sDescription = "Alkalinity": tDim.SetAll -3, 0, 0, 0, 0, 1: sUnit = "M/m"
71
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
=
=
=
=
=
=
=
=
=
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
=
=
=
=
=
=
=
=
=
=
=
=
=
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
sDescription
=
=
=
=
=
=
=
=
=
=
=
72
'
' Record results for local use
'
With Outputs(ItemIndex)
.iStage = iStages
If iModel > 0 Then
.iType = PROCESS
Else
.iType = STREAM
End If
.iUnit = i
.sParameter = sComp
.sLabel = sName
.fSIMult = fMultiplier
.fSIOffset = fOffset
End With
Set tResult = New OutputExchangeItem
With tResult
With .Element
.ID = sName
.Description = sName
End With
With .Quantity
.SetDimension tDim
.ID = sComp
.Description = sDescription
With .Unit
.ID = sUnit
.Description = sUnit
.ConversionFactorToSI = fMultiplier
.OffsetToSI = fOffset
End With
End With
End With
Set GetOutputExchangeItem = tResult
End Function
Public Function GetModelID() As String
Dim s As String
s = "Works " & gCurrentWorks.iID & ": Run " & gCurrentRun.iID
s = Replace(s, " ", "_")
GetModelID = s
End Function
73
74
75
gbStandardRun = False
SetRunMode True
Initialize = True
gbStandardRun = False ' Disable end of run message
frmIconMenu.Hide
NumberofInputItems = -1
NumberOfOutputItems = -1
End Function
Public Sub SetConstants(ByVal ss As Double, ByVal si As Double, _
ByVal xs As Double, ByVal xi As Double, _
ByVal sa As Double, _
ByVal sol_ss As Double, ByVal sol_si As Double, _
ByVal sol_sns As Double, ByVal sol_sni As Double, _
ByVal sol_sps As Double, ByVal sol_spi As Double, _
ByVal sol_xs As Double, ByVal sol_xi As Double, _
ByVal sol_xns As Double, ByVal sol_xni As Double, _
ByVal sol_xps As Double, ByVal sol_xpi As Double, _
ByVal SOL_BOD As Double, ByVal deg_cod As Double, _
ByVal deg_sol As Double, ByVal deg_part As Double, _
ByVal sol_cod_to_bod As Double, ByVal part_cod_to_bod As Double)
omi_ss = ss: omi_si = si: omi_xs = xs: omi_xi = xi: omi_sa = sa
omi_sol_ss = sol_ss: omi_sol_si = sol_si: omi_sol_xs = sol_xs: omi_sol_xi = sol_xi
omi_sol_sns = sol_sns: omi_sol_sni = sol_sni: omi_sol_xns = sol_xns: omi_sol_xni = sol_xni
omi_sol_sps = sol_sps: omi_sol_spi = sol_spi: omi_sol_xps = sol_xps: omi_sol_xpi = sol_xpi
omi_sol_bod = SOL_BOD
omi_deg_cod = deg_cod
omi_deg_sol = deg_sol
omi_deg_part = deg_part
omi_sol_cod_to_bod = sol_cod_to_bod
omi_part_cod_to_bod = part_cod_to_bod
End Sub
'
'
'
'
'
'
76
77
Case "BOD":
Case "sBOD":
Case "pBOD":
Case "TSS":
Case "VSS":
Case "NVSS":
Case "SNH":
Case "SNO":
Case "SNS":
Case "SNI":
Case "XNS":
Case "XNI":
Case "SPO4":
Case "SPS":
Case "SPI":
Case "XPS":
Case "XPI":
Case "SO2":
Case "SALK":
Case "T":
Case "pH":
End Select
End With
f = .fComponent(SOL_BOD) * sol_cod_to_bod _
+ .fComponent(PART_BOD) * part_cod_to_bod
f = .fComponent(SOL_BOD) * sol_cod_to_bod _
+ .fComponent(PART_BOD) * part_cod_to_bod * omi_sol_cod
f = .fComponent(PART_BOD) * part_cod_to_bod * (1 - omi_sol_cod)
f = .fComponent(VOL_S) + .fComponent(NONVOL_S)
f = .fComponent(VOL_S)
f = .fComponent(NONVOL_S)
f = .fComponent(SOL_NH3)
f = .fComponent(SOL_NO3)
f = .fComponent(SOL_ORGN) + omi_sol_xns * .fComponent(PART_ORGN)
f = .fComponent(sndon) + omi_sol_xni * .fComponent(xndon)
f = .fComponent(PART_ORGN) * (1# - omi_sol_xns)
f = .fComponent(xndon) * (1# - omi_sol_xni)
f = .fComponent(SOL_PO4)
f = .fComponent(sorgpo4) + omi_sol_xps * .fComponent(xpo4)
f = .fComponent(sorgndpo4) + omi_sol_xpi * .fComponent(xndpo4)
f = .fComponent(xpo4) * (1# - omi_sol_xps)
f = .fComponent(xndpo4) * (1# - omi_sol_xpi)
f = .fComponent(SOL_O2)
f = .fComponent(Alk)
f = .fTemperature
f = .fpH
78
79
80
Appendix 5
Option Explicit
Public
Public
Public
Public
Public
omi_sa
omi_ss
omi_si
omi_xs
omi_xi
As
As
As
As
As
Public
Public
Public
Public
Public
Public
omi_sol_ss
omi_sol_si
omi_sol_sns
omi_sol_sni
omi_sol_sps
omi_sol_spi
As
As
As
As
As
As
Double
Double
Double
Double
Double
Double
Public
Public
Public
Public
Public
Public
omi_sol_xs
omi_sol_xi
omi_sol_xns
omi_sol_xni
omi_sol_xps
omi_sol_xpi
As
As
As
As
As
As
Double
Double
Double
Double
Double
Double
Public
Public
Public
Public
Public
Public
omi_sol_bod
omi_deg_cod
omi_deg_sol
omi_deg_part
omi_sol_cod_to_bod
omi_part_cod_to_bod
Double
Double
Double
Double
Double
As
As
As
As
As
As
Double
Double
Double
Double
Double
Double
'
'
'
'
'
'
81
82
Appendix 6
83
Case "SA":
Case "SS":
Case "SI":
Case "XS":
If mInfluentRun(j).Reset(1) Then
.fComponent(PART_BOD) = fVal
Else
.fComponent(PART_BOD) = .fComponent(PART_BOD) + fVal
End If
mInfluentRun(j).Reset(1) = False
Case "XI":
Case "sCOD":
Case "pCOD":
Case "BOD":
Case "sBOD":
Case "pBOD":
Case "TSS":
Case
Case
Case
Case
Case
"VSS":
"NVSS":
"SNH":
"SNO":
"SNS":
If mInfluentRun(j).Reset(2) Then
.fComponent(PART_INERT_COD) = fVal
Else
.fComponent(PART_INERT_COD) = .fComponent(PART_INERT_COD) + fVal
End If
mInfluentRun(j).Reset(2) = False
gSetOMIStreamData iStream, "SS", fVal * omi_deg_sol
gSetOMIStreamData iStream, "SI", fVal * (1 - omi_deg_sol)
gSetOMIStreamData iStream, "XS", fVal * omi_deg_part
gSetOMIStreamData iStream, "XI", fVal * (1 - omi_deg_part)
gSetOMIStreamData iStream, "sBOD", fVal * omi_sol_bod
gSetOMIStreamData iStream, "pBOD", fVal * (1 - omi_sol_bod)
fVal = fVal / omi_deg_cod / omi_sol_cod_to_bod
gSetOMIStreamData iStream, "sCOD", fVal
fVal = fVal / omi_deg_cod / omi_part_cod_to_bod
gSetOMIStreamData iStream, "pCOD", fVal
.fComponent(VOL_S) = fVal * FRACT_VSS
.fComponent(NONVOL_S) = fVal * (1 - FRACT_VSS)
.fComponent(VOL_S) = fVal
.fComponent(NONVOL_S) = fVal
.fComponent(SOL_NH3) = fVal
.fComponent(SOL_NO3) = fVal
.fComponent(SOL_ORGN) = fVal
If mInfluentRun(j).Reset(3) Then
.fComponent(PART_ORGN) = fVal * (1 - omi_sol_sns)
Else
84
Case "SNI":
Case "XNS":
If mInfluentRun(j).Reset(3) Then
.fComponent(PART_ORGN) = fVal
Else
.fComponent(PART_ORGN) = .fComponent(PART_ORGN) + fVal
End If
mInfluentRun(j).Reset(3) = False
Case "XNI":
Case "SPO4":
Case "SPS":
Case "SPI":
If mInfluentRun(j).Reset(4) Then
.fComponent(xndon) = fVal
Else
.fComponent(xndon) = .fComponent(xndon) + fVal
End If
mInfluentRun(j).Reset(4) = False
.fComponent(SOL_PO4) = fVal
.fComponent(sorgpo4) = fVal
If mInfluentRun(j).Reset(5) Then
.fComponent(xpo4) = fVal * (1 - omi_sol_sps)
Else
.fComponent(xpo4) = .fComponent(xpo4) + fVal * (1 - omi_sol_sps)
End If
mInfluentRun(j).Reset(5) = False
.fComponent(sorgndpo4) = fVal
If mInfluentRun(j).Reset(6) Then
.fComponent(xndpo4) = fVal * (1 - omi_sol_spi)
Else
.fComponent(xndpo4) = .fComponent(xndpo4) + fVal * (1 - omi_sol_spi)
End If
mInfluentRun(j).Reset(6) = False
Case "XPS":
If mInfluentRun(j).Reset(5) Then
.fComponent(xpo4) = fVal
Else
.fComponent(xpo4) = .fComponent(xpo4) + fVal
End If
mInfluentRun(j).Reset(5) = False
Case "XPI":
If mInfluentRun(j).Reset(6) Then
.fComponent(xndpo4) = fVal
Else
85
Case "SO2":
Case "SALK":
Case "T":
Case "pH":
End Select
End With
Next i
End Sub
86
Appendix 7
Paper submitted to ModSim05
Conference on model usage and integration
Applying the Open Modelling Interface (OpenMI)
Dudley, J1, W Daniels2, PJA Gijsbers3, D Fortune2, S Westen2, and JB Gregersen4
1
WRc plc, UK
87
Extended abstract
Catchment-level modelling has been regarded,
since at least the middle 1980s, as a necessary part
of providing integrated solutions for improving
water quality in receiving waters. However, the
tools that have been available to support this level
of modelling have not made such modelling
convenient. Typically there has been no support
for data exchange between different vendors, and
different classes of model (e.g., rivers, sewers and
sewage works) have used different water quality
parameters in their assessment. The purpose of the
OpenMI has been to provide a first level of greater
ease of data exchange between different programs,
by removing the barrier of exchanging data
between different programs. The OpenMI has also
provided mechanisms to simplify exchanging
quantities between different programs for
example, should one program expect flow in US
units, and another in cumecs, simple
transformations can be defined to ensure that each
program can convert the data from the other to the
required units. A relatively large-scale application
of the OpenMI in a model catchment is described
here, to better illustrate some of the benefits and
modelling issues that are introduced by use of the
OpenMI.
It is concluded that the OpenMI has facilitated
linking many disparate water-cycle programs. The
focus of OpenMI (i.e. data exchange at the engine
/component level) and the current state of adoption
by the software community require the usage of a
straightforward editor to define the linkage outside
the user interface environments of the various
systems. This focus has kept the conceptual
overhead low, as each program in the catchment
model is manipulated individually, so that the
domain experts do not need to learn a new
interface. In a similar way, the results of the
intergrated computation needs to be inspected
through the individual user interfaces of the
various models incorporated.
In addition it is concluded that the OpenMI
provides a feasible for solution for the ITcommunication problem. However, it does not
solve all problems. As each program is required to
exchange data with a program from a different
model developer there has been the need to
communicate to ensure that the semantics are
clear, that the connection points are correct, and
that the data being transferred is mapped correctly
e.g., agreeing on transformation protocols
between COD from the sewage models to BOD in
the lake model. This communication has been a
WRc Ref: UC6920/13124-1
September 2005
88
INTRODUCTION
This paper illustrates two points:
Table 4
Link
From
To
A
B
C
D
E
F
G
H
I
J
K
L
89
WQ
OMI Hills
HYMOS Database
Rainfall
C
OMI Valley
SOBEK-RR
Rainfall / Runoff
A
Wallingford
SOBEK-SF
Sewer Flow
B
OMI River
SOBEK-CF
Channel Flow
D
OMI River
Infoworks RS
Channel Flow
F
Delft
Infoworks CS
Sewer Flow
STOAT
Wastewater
treatment works
overflow
I
STOAT
Wastewater treatment
works
Delft Polder
SOBEK-RR
Rainfall / Runoff
Lake Harmoni
SULIS
L
Infoworks RS
Channel Flow
Figure 6.1
90
Swindon
Infoworks CS
Sewer Flow
Previous attempts at creating large integrated models, such as the previous DHI/WRc collaborative project TVP
(Taylor et al., 1999), have created GIS-based interfaces that have attempted to simplify visual representation, but
not the mechanics of connecting the programs and running them. OpenMI focuses on the linkage issue rather than
such software areas as user interfaces. On the contrary, OpenMI does not mandate a user interface and allows
users and their suppliers to develop user interfaces for OpenMI or to embed OpenMI functionality in their own
products. However, to enable working with OpenMI there is a simple linkage editor provided as part of the C#
.Net implementation. This implementation also provides utilities for model wrapping. It is available as open
source on sourceforge.net/projects/openmi/ or through the OpenMI website (www.openmi.org). An example of
the linkage editor is shown in Figure 2. After the programs have been connected the quantities being exchanged
are then defined, as illustrated in Figure 3. In the previous TVP programme a GIS-based user interface was
available, but this made it more difficult to distinguish between the spatial layout of the models and the
boundaries of the programs. The simple approach currently used in the OpenMI demonstrator has been found to
enhance understanding of the inter-relationships between the different programs and the quantities being
exchanged between these programs A GIS-enabled interface that allows switching between the spatial and
software views may help in ensuring that connections are made at the right points, rather than relying upon
descriptions (e.g., Swindon overflow from the sewer model should connect to CSO spill point on the river
model.) However, OpenMI also supports mapping of spatial coordinates, so that future iterations of the program
may automatically identify the connections through their geographical coordinates, and detect if the connections
are not correctly spatially aligned.
Figure 6.2
91
Figure 6.3
3.
Table 2 provides an overview of the way OpenMI allows model connections to be defined to address the problems
described above. The default wrapper implementation for OpenMI accommodates the specification of data
operations as presented. The bottom pane of Figure 3 shows the feedback available in the current interface to
guide users in ensuring that they are transferring data at the correct location, and mapping quantities correctly.
While OpenMI supports transformations, so that quantities can be manipulated at the OpenMI level, this is not as
readily available where the mapping is not a simple one-to-one relationship (as, for example, different units for
flow), but rather a many-to-one relationship (for example, suspended solids in the target program being the sum of
several solids fractions in the source.) This requires that the programs provide support for such mappings, and can
be done either at the OpenMI level, or, at a further level within the target program.
92
Table 5 Overview of modelled variables and data operations to match output and
input
Link
Output Quantity
Input Quanity
Data operation
A
B
C
D
Runoff (m3/s)
Runoff (m3/s)
Rainfall (mm/s)
Discharge (m3/s)
Water level (m above OL)
Flow
COD
Suspended solids
.Ammoniacal nitrogen
Flow
COD
Suspended solids
Ammoniacal nitrogen
Temperature
Stage (m above HL)
Flow
COD
Suspended solids
Ammoniacal nitrogen
Temperature
Stage (m above HL)
Flow
COD
Suspended solids
Ammoniacal nitrogen
Temperature
Flow
COD Suspended solids
Ammoniacal nitrogen
Unit conversion
datum offset: -0.03 m
-
K
L
Flow
COD
Suspended solids
Ammoniacal nitrogen
Temperature
Runoff (m3/s)
Stage (m above HL)
Flow
BOD
Suspended solids
Ammoniacal nitrogen
Temperature
93
4.
The OpenMI has facilitated linking many disparate water-cycle programs. Avoiding regarding the purpose of the
OpenMI as providing an integrated software suite has kept the conceptual overhead low, as each program in the
catchment model is manipulated individually, so that the domain experts do not need to learn a new interface. (Of
course, the chosen implementation may include such a new over-arching interface linking the different models
but this is not a requirement of OpenMI, and is instead a policy decision to be made by users or vendors.)
The integration of the different programs into the larger catchment model has required each contributor to
describe where the data file containing the submodel connection data is stored on the computer system, and what
input and output connections and quantities are involved. As each program is required to exchange data with a
program from a different domain expert there has been the need to communicate to ensure that the connection
points are correct, and that the data being transferred is mapped correctly e.g., agreeing on transformation
protocols between COD from the sewage models to BOD in the lake model. This communication has been a
source of difficulty with previous efforts at integrated catchment modelling, and while OpenMI can simplify the
technical aspects it does not address these human issues.
After the catchment model has been run the results from each program need to be analysed in the originating
program. The currently available OpenMI implementation provides mechanism for examining exchanged data,
but this is not as convenient as the facilities provided in each originating program. Consequently, again, analysing
the results in deciding the overall catchment impact has required further communication between the domain
experts. The OpenMI allows larger problems to be tackled, but does not remove the constraints of ensuring
communication between the different technical work areas in understanding the total output. As well as needing
the traditional local areas of expertise for example, river, sewerage and sewage treatment works modellers
there has also been the greater need for a new area of expertise, providing the catchment-level understanding of
the whole problem. This has normally been addressed at a more political level than has been the case for the
technical problems, with each technical team attempting to provide its solution to the ultimate decision makers
with no interaction, or understanding, of the effects that their solution has on other parts of the complete problem.
The OpenMI, by providing a framework for these different areas to better integrate the modelling work, has
concomitantly provided a social framework to encourage the individual teams to work together to provide better
modelling data for the decision makers.
5.
REFERENCES
Taylor, S, B Tomicic, W Williams and K Murray, 1999, TVP ICS and RTC in Oldham, WaPUG
Autumn Meeting, http://www.wapug.org.uk/past_papers/autumn_1999/paper08.pdf
Gijsbers, P.J.A. and Gregersen, J.B., 2005 OpenMI: A glue for integrated modelling, this conference
6.
ACKNOWLEDGMENTS
The authors would like to thank their respective organisations for permission to publish this paper. We would also
like to thank the EU for funding the project that led to the development of the OpenMI, and the members of the
HarmonIT team for providing tools and support used for this project. The views expressed in this paper are those
of the authors, and are not necessarily the views of WRc, Wallingford Software, WL/Delft Hydraulics, DHI Water
& Environment , the EU Commission or the HarmonIT partners and consortium.
94