Versions Compared

Key

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

...

Step 6: Implementing the MyModelLinkablComponent

The sixth step is to implement the MyModeLinkableComponent class (Figure 12).

Image Added

The MyModelLinkableComponent is the OpenMI-compliant linkable component that is going to be accessed by other models. Implementation of this class is very simple. The example code shown below is the complete implementation for the Simple River model.

Code Block

using System;
namespace MyOrganisation.OpenMI.MyModel
{
   public class MyModelOpenMIComponent :
   org.OpenMI.Utilities.Wrapper.LinkableEngine
   {
      protected override void SetEngineApiAccess()
      {
         _engineApiAccess = new MyEngineWrapper();
      }
   }
}

This class inherits from the LinkableEngine class. The class creates the EngineWrapper and assigns it to the protected field variable _engineApiAccess.

Step 7: Implementation of the remaining IEngine methods

The basic structure of your engine and wrapper code is now in place. The task is now to go through the MyEngineWrapper class and complete the implementation of the methods that are currently auto-generated stub code. Some of these methods can be completed only by changing the code in the MyEngineWrapper; for others, changes also need to be made to the other classes and the engine core (MyEngineDLL). After completion of each method you should update the test classes and run the unit test.


For each method you must decide if the bulk of implementation should be located in the MyEngineWrapper class or in the engine core. There is no general answer to this question. Placing the bulk of implementation in the engine core could be advantageous from the perspective of maintenance because you have most things located in one place. On the other hand, you may want to keep the engine core as free as possible of OpenMI-related code and therefore put the bulk of the implementation into the MyEngineWrapper class. Finally, there may also be considerations about the preferred programming language; the engine core may be programmed in Fortran, C or Pascal, whereas the MyEngineWrapper class is programmed in C#.


Implementation of the IEngine interface depends on the engine core, so it is not possible to give a general explanation of how each individual method should be implemented. However, the next chapter gives a description of how the IEngine interface has been implemented for the Simple River model.


The IEngine interface is shown below

Code Block

//== The org.OpenMI.Utilities.Wrapper.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);