4.1 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.
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.
Fig. 7. Running an engine as a standalone application
The following steps are required in the conversion of the engine core:
- Change the engine core so that it can be compiled into a DLL.
- Add a function to the engine core that will run a full simulation: logical function RunSimulation()
- Create an engine application (EXE) that from its main program calls the RunSimulation function in your engine core DLL.
- 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 SDK 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)
l
ogical 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.