Versions Compared

Key

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

...

Please see examples of how the linkable components can be used for different purposes in the unit test examples below:
The full source code is located at source forge in the branch called "OpenMI-2.0.0-Gregersen02", use the SimpleComponent solution under MyOpenMISource/LicTek/OpenMIVersion2Tests/SimpleComponent.

Simple Getvalues

Code Block
 [Test]
        public void GetValues()
        {
            ILinkableComponent myLinkableComponent = new MyLinkableComponent();
            myLinkableComponent.Initialize(new Argument[0]);
            double x = (double)myLinkableComponent.OutputItems[0].GetValues();
            Assert.AreEqual(7.3, x);
        }

Simple SetValues

Code Block
[Test]
        public void SetValues()
        {
            ILinkableComponent myLinkableComponent = new MyLinkableComponent();
            myLinkableComponent.Initialize(new Argument[0]);

            double x = 6.4;
            myLinkableComponent.InputItems[0].SetValues(x);
                        
            Assert.AreEqual(x, ((MyLinkableComponent) myLinkableComponent).WaterLevel);
        }

Configuration test

Code Block
[Test]
        public void ConfigurationTest()
        {
            ILinkableComponent upperRiver = new MyLinkableComponent();
            ILinkableComponent lowerRiver = new MyLinkableComponent();
            upperRiver.Initialize(new Argument[0]);
            lowerRiver.Initialize(new Argument[0]);

            // Connect the two models
            // The bridge object will take care of temporal, spatial, and unit conversion.
            IBridge bridge = upperRiver.OutputItems[0].CreateBridge(lowerRiver.InputItems[0]);
            lowerRiver.InputItems[0].AddBridge(bridge);
            bridge.IsActivated = true;

            // prepare, but this may not be needed since the IsActivated is swithed on

            //Run
            lowerRiver.Update(new TimeStamp(100));

            //close down
            upperRiver.Finish();
            upperRiver.Dispose();
            lowerRiver.Finish();
            lowerRiver.Dispose();

        }

Calibration test

Code Block
[Test]
        public void CalibrationTest()
        {
            ILinkableComponent upperRiver = new MyLinkableComponent();
            upperRiver.Initialize(new Argument[0]);

            double observedWaterLevel = 2.3;
            double roughness = 0.03;
            double simulatedWaterLevel = 0;

            
            Object state = ((IManageState)upperRiver).KeepCurrentState();

            do
            {
                upperRiver.InputItems[17].SetValues(roughness);
                upperRiver.Update(new TimeStamp(232));
                simulatedWaterLevel = (double) upperRiver.OutputItems[5].GetValues();

                roughness = VeryAdvancedCalibrationAlgorithm(roughness, observedWaterLevel, simulatedWaterLevel);
                ((IManageState)upperRiver).RestoreState(state);
            } 
            while (Math.Abs(observedWaterLevel - simulatedWaterLevel) < 0.01);

            upperRiver.Finish();
            upperRiver.Dispose();
        }

Suggestions for how to handle time

The way time is represented in the 1.4 standard has for a long time been bothering me. If you want to make a very simple component that does not care about time, you still have to implement TimeHorizon, GetEarliestInputTime, and the GetValues method will have a time argument. Examples of such components could be a GIS geo-references soil conductivity or soil type (when we get the quality data type included). It could also be a very simple component that provides a single value e.g. if you want to make a component for setting the roughness coefficient from outside via OpenMI.

I have changed the interfaces as shown on the figure below:

  1. I made a new interface called IIdentifier. This has nothing to do with the time issues and I should probably not have made this change since it can confuse the issue. Anyway the IIdentifier is simply used to group the caption, ID and description that we have in some of our interfaces.
  1. A new interface called ITemporal (could not at the moment come up with at better name (sad)). The idea is that if time is relevant for an exchange item (input or output) then such exchange items may implement this interface in addition to IInputExchangeItem or IOutputExchangeItem. The TimeHorizon property is moved from the ILinkableComponet to the ITemporal interface, so a time horizon relates to at specific exchange item rather than the whole linkable component.
    The property exchangeTime should be regarded exactly as IElementSet. So, the elemetSet defines the locations for where data can be provided or accepted and likewise does the exchangeTime define when data is available or expected. This also means that the GetValues method in the IBridge interface does not need at time argumet. The bridge will convert data from being represented on the output elementset and the output exchange time to be presented on the input elementset at the input exchange time. The AlwaysForwardInTime property is used to tell the other component that the exchange time will never be moved backwards thus allowing the delivering component to clear it's buffer.

Image Added