Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • The MyEngineDLL class is the compiled core engine code (e.g. Fortran).
  • The MyEngineDLLAccess class is responsible for translating the Win32Api from MyEngineDLL to .NET (C#).
  • Calling conventions and exception handling are different for .NET and Fortran. The MyEngineDotNetAccess class ensures that these operations follow the .NET conventions.
  • The MyEngineWrapper class implements the IEngineAccess interface, which means that it can be accessed by the LinkableEngine class.
  • The MyLinkableEngine class is responsible for the creation of the MyEngineWrapper class and for assigning a reference to this class to a protected field variable in the LinkableEngine class, thus enabling this class to access the MyEngineWrapper class.
     
    More details of these classes are provided in the following sections.
    The OpenMI standard puts a lot of responsibilities on the LinkableComponents. The main idea is that when the GetValues method is invoked the providing component must be able to deliver the requested values so that these apply to the requested time and the requested location. To be able to do this the LinkableComponent may have to interpolate, extrapolate or aggregate both in time and space. These and other things are handled by the LinkableEngine.
     
    The LinkableEngine class includes the following features:
     
  • Buffering: When a model is running as an OpenMI component it may be queried for values that correspond to a time that is before the current time of the model. Most models will only keep values for the current timestep and the previous timestep in memory. It is therefore necessary to store data associated with the OpenMI links in a buffer. The LinkableEngine handles the buffering for you.
  • Temporal interpolation and extrapolation: Most models are only capable of delivering results at times that correspond to their internal timesteps. The LinkableEngine class handles all the temporal operations that are required for LinkableComponents.
  • Spatial operations: The LinkableEngine provides a range of spatial data operations.
  • Link book-keeping: The LinkableEngine handles book-keeping for links added to your component.
  • Event handling: The LinkableEngine sends events that enable an event-listener to monitor the progress of the linked system when running.
     
    More details about how the LinkableEngine works is given in  in OATC.OpenMI.SDK technical documentation.
Migration - step by step

The best strategy when migrating a model is to split the process into a number of steps; at the end of each step you can compile your code and run a small test.

The steps needed for migration are described in this chapter.

Step 1: Changing your engine core 

The aim of the migration is to develop a class that implements the IEngine interface. As shown in Figure 6, the class that implements the IEngine interface is supported by other classes and the engine DLL.
Image Added
Fig 6. Wrapping classes and engine core DLL
 
Model engines are typically compiled into an executable file (EXE). Such executable files are not accessible by other components and as such are not very suitable as a basis for OpenMI components. It is therefore necessary for your engine to be compiled into a dynamic link library file (DLL).
Ideally you should make modifications to your engines so that the same engine can be used both when running as an OpenMI component and when running as a standalone application. Having two versions of the same engine leads to unnecessary maintenance work. Therefore you could make a new application (EXE) that calls a function in the engine core DLL which, in turn, makes your engine perform a full simulation.
Figure 7 illustrates the software required to run an engine as a standalone application. The SimpleRiverApplication.EXE file is never used when running in an OpenMI setting.
 
Image Added
Fig. 7. Running an engine as a standalone application
 
The following steps are required in the conversion of the engine core:

  1. Change the engine core so that it can be compiled into a DLL.
  2. Add a function to the engine core that will run a full simulation: logical function RunSimulation()
  3. Create an engine application (EXE) that from its main program calls the RunSimulation function in your engine core DLL.
  4. Run your engine by deploying the engine application and check that the engine is still producing correct results.

When your engine is running in the OpenMI Software Development Kit it must be able to initialize, perform single timesteps, finalize and be disposed as separate operations. This means that your engine core may need to be reorganized. You can do this in any way you like but one logical approach is to create four functions:
 logical function Initialize()
(Open files and populate your engine with initial data)
logical function PerformTimeStep()
(Perform a single timestep)
logical function Finish()
(Close files)
logical function Dispose()
(De-allocate memory)
 
The RunSimulation function should now be changed so that it calls the Initialize function, then repeatedly calls the PerformTimeStep function until the simulation has completed, and finally
calls the Finish and Dispose functions.
At this point you should run your application again and check that the engine is still producing the correct results.
You have now completed the restructuring of the engine. The remaining changes that you need to make to the engine will be much smaller. The nature of the changes will be dependent on the particular engine. For now, you can move on to creating the wrapper code.
 

Step 2: Creating the .Net assemblies

The next step is to create the wrapper classes (Figure 8). For this stage, make sure that the OpenMI Software Development Kit is installed on your PC.
Image Added
Fig 8. C# wrapping classes