You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Introduction

I have looked carefully at the current OpenMI development version 2 (the chained approach). I believe that it works, but somehow I also find it a bit too complicated. The whole idea of creating a chain of data operations may provide possibilities, but I have a hard time finding examples where this is really needed.

In my approach below I have tried to simplify things so there is only one data operation (I called this interface a bridge, just to confuse everyone). Maybe the bridge actually is a cover up for a link, honestly I do not know. Please forgive me if I am moving in circles (smile). Please take a look at the relevant interfaces in the figure below.

A linkable component has a list of input items (IInputExchangeItems) and output items (IOutputExchangeItems). Data can be accessed directly by GetValues() and SetValues(Object) through the output and input items, respectively. In this case it is the raw data, no conversions is done, so what you set or get is data at whatever time the component it at.

In order to make conversions a bridge is required. You can request the output item to create a bridge, which will take care of any temporal, spatial, unit, and other conversion that is needed in order to make the data fit with the target exchange item (the CreateBridge(IExchangeItem)). A bridge must be activated before the GetValues method on this bridge can be invoked. This is needed because the bridge may need to buffer time dependent data. If e.g. an output item has data represented on a polyline and the input item needs data on a polygon, a bridge that makes this conversion is created. You can still set additional options by changing arguments (e.g. inversDistance, search radius, temporal relaxation factor etc.).

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

 [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

[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

[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

[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();
        }

  • No labels