/* MOD_V2.0 * Copyright (c) 2012 OpenDA Association * All rights reserved. * * This file is part of OpenDA. * * OpenDA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * OpenDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with OpenDA. If not, see . */ using System; using System.Collections.Generic; using OpenDA.DotNet.Interfaces; using OpenMI.Standard2; using OpenMI.Standard2.TimeSpace; using ITime=OpenDA.DotNet.Interfaces.ITime; namespace OpenDA.DotNet.OpenMI.Bridge { public class ModelInstance : IModelInstance { private readonly ModelFactory _openDaModelFactory; private readonly ITimeSpaceComponent _openMIComponent; private readonly IDictionary _inputs = new Dictionary(); private readonly IDictionary _outputs = new Dictionary(); public ModelInstance(ModelFactory myModelFactory, ITimeSpaceComponent openMIComponent) { _openDaModelFactory = myModelFactory; _openMIComponent = openMIComponent; GetExchangeItemsFromOpenMIComponent(); } public IInstance GetParent() { return _openDaModelFactory; } public ITimeSpaceComponent OpenMIComponent { get { return _openMIComponent; } } public ITime TimeHorizon { get { global::OpenMI.Standard2.TimeSpace.ITime timeHorizon = _openMIComponent.TimeExtent.TimeHorizon; double beginTime = timeHorizon.StampAsModifiedJulianDay; double endTime = beginTime + timeHorizon.DurationInDays; DotNet.Bridge.Time openDATimeHorizon = new DotNet.Bridge.Time(beginTime, endTime); return openDATimeHorizon; } } public ITime CurrentTime { get { return DetermineCurrentTime(TimeHorizon.BeginTime); } } public void Compute(ITime targetTime) { ITime lastTime = DetermineCurrentTime(null); if (lastTime == null) { throw new Exception("Could not find time/space output item to check model's current time"); } while (lastTime.EndTime.MJD < targetTime.MJD && _openMIComponent.Status != LinkableComponentStatus.Failed && _openMIComponent.Status != LinkableComponentStatus.Done) { try { _openMIComponent.Update(); } catch (Exception e) { ModelFactory.AppendLogMessage("Exception in Update()" + e); throw e; } foreach (KeyValuePair output in _outputs) { output.Value.AddNewOpenMIOutputValuesToBuffer(); } lastTime = DetermineCurrentTime(null); } } public string[] ExchangeItemIDs { get { string[] exchangeItemIDs = new string[_inputs.Count + _outputs.Count]; _inputs.Keys.CopyTo(exchangeItemIDs, 0); _outputs.Keys.CopyTo(exchangeItemIDs, _inputs.Count); return exchangeItemIDs; } } public string[] GetExchangeItemIDs(int roleAsInt) { Role role = DotNet.Bridge.Utils.RoleMapJ2N(roleAsInt); string[] exchangeItemIDs; switch (role) { case Role.Input: exchangeItemIDs = new string[_inputs.Count]; _inputs.Keys.CopyTo(exchangeItemIDs, 0); break; case Role.Output: exchangeItemIDs = new string[_inputs.Count]; _outputs.Keys.CopyTo(exchangeItemIDs, 0); break; case Role.InOut: exchangeItemIDs = ExchangeItemIDs; break; default: throw new Exception("Invalid Role value: " + role); } return exchangeItemIDs; } public IExchangeItem GetExchangeItem(string exchangeItemID) { if (_inputs.ContainsKey(exchangeItemID)) { return _inputs[exchangeItemID]; } if (!_outputs.ContainsKey(exchangeItemID)) { string availableItems = ""; foreach (var exchangeItem in _inputs) { availableItems += "In: " + exchangeItem.Key + "\n"; } foreach (var exchangeItem in _outputs) { availableItems += "Out: " + exchangeItem.Key + "\n"; } throw new Exception("Could not find exchange item \"" + exchangeItemID + "\". Available exchange items:\n" + availableItems); } return _outputs[exchangeItemID]; } public IModelState SaveInternalState() { throw new NotImplementedException(); } public void RestoreInternalState(IModelState savedInternalState) { throw new NotImplementedException(); } public void ReleaseInternalState(IModelState savedInternalState) { throw new NotImplementedException(); } public IModelState LoadPersistentState(string algorithmStateFilePath) { throw new NotImplementedException(); } public IVector[] GetObservedLocalization(IObservationDescriptions observationDescriptions, double distance) { return null; } public IVector GetObservedValues(IObservationDescriptions observationDescriptions) { return null; } public IVector[] GetObservedLocalization(String exchageItemID, IObservationDescriptions observationDescriptions, double distance) { return null; } public string ModelRunDirPath { get { return null; } // model instance's run dir is not known } public void Finish() { if (_openMIComponent != null) { _openMIComponent.Finish(); } } public override string ToString() { if (_openMIComponent != null) { return _openMIComponent.Caption; } return GetType().Name; } private ITime DetermineCurrentTime(ITime currentTime) { foreach (KeyValuePair output in _outputs) { if (output.Value.Times != null && output.Value.Times.Length > 0) { double timeAsMJD = output.Value.Times[output.Value.Times.Length - 1]; currentTime = new DotNet.Bridge.Time(timeAsMJD); break; } } if (currentTime == null) { currentTime = TimeHorizon.BeginTime; } return currentTime; } private void GetExchangeItemsFromOpenMIComponent() { string message = ""; foreach (IBaseInput baseInput in _openMIComponent.Inputs) { ITimeSpaceInput timeSpaceInput = baseInput as ITimeSpaceInput; if (timeSpaceInput != null) { if (_inputs.ContainsKey(timeSpaceInput.Id)) { string mess = "Input item " + timeSpaceInput.Id + " defined more then once"; ModelFactory.AppendLogMessage(mess); message += "\n" + mess; } else { _inputs.Add(timeSpaceInput.Id, new ExchangeItem(timeSpaceInput)); } } } foreach (IBaseOutput baseOutput in _openMIComponent.Outputs) { ITimeSpaceOutput timeSpaceOutput = baseOutput as ITimeSpaceOutput; if (timeSpaceOutput != null) { if (_outputs.ContainsKey(timeSpaceOutput.Id)) { string mess = "Output item " + timeSpaceOutput.Id + " defined more then once"; ModelFactory.AppendLogMessage(mess); message += "\n" + mess; } else { _outputs.Add(timeSpaceOutput.Id, new ExchangeItem(timeSpaceOutput, true)); } } } if (message.Length > 0) throw new Exception("Multiple Input and/or Output items:" + message); } } }