/* 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;
using System.Collections.Generic;
using OpenDA.DotNet.Interfaces;
using OpenMI.Standard2;
using OpenMI.Standard2.TimeSpace;
namespace OpenDA.DotNet.OpenMI.Bridge
{
public class ExchangeItem : IExchangeItem
{
private readonly ITimeSpaceInput _openMIInputItem;
private readonly ITimeSpaceOutput _openMIOutputItem;
private readonly ITimeSpaceExchangeItem _openMIItem;
private readonly bool _useBufferedValues;
private readonly List> _bufferedValues;
private readonly List _bufferedTimes;
private static double _lastOutputTime; // HACK, REMOVE
public ExchangeItem(IBaseExchangeItem openMIItem) : this(openMIItem, false)
{
}
public ExchangeItem(IBaseExchangeItem openMIItem, bool useBufferedValues)
{
if (openMIItem is ITimeSpaceOutput)
{
_openMIItem = _openMIOutputItem = (ITimeSpaceOutput) openMIItem;
}
else if (openMIItem is ITimeSpaceInput)
{
_openMIItem = _openMIInputItem = (ITimeSpaceInput) openMIItem;
}
else
{
throw new Exception("Unknown exchange item type: " + openMIItem.GetType());
}
if (_openMIItem.TimeSet != null && _openMIItem.TimeSet.HasDurations)
{
throw new Exception("\"" + Id + ": OpenDA Time Spans not covered by OpenDA Exchange items");
}
_useBufferedValues = useBufferedValues;
if (_useBufferedValues)
{
_bufferedValues = new List> {new List()};
_bufferedTimes = new List();
}
}
public string Id
{
get { return _openMIItem.Id; }
}
public string Description
{
get { return _openMIItem.Description; }
}
public Type ValueType
{
get { return typeof (IList); }
}
public Role Role
{
get
{
if (_openMIInputItem != null)
{
return Role.InOut; // Input Exchange Items can be asked for their current values
}
return Role.Output;
}
}
public object Values
{
get
{
if (_useBufferedValues)
{
return _bufferedValues;
}
ITimeSpaceValueSet openMIValueSet = _openMIOutputItem != null
? _openMIOutputItem.Values
: _openMIInputItem.Values;
// TODO: remove handling only one time step
// TODO: replace loop by openMIValueSet.GetValue(new[] { 0 })
List> values = new List> { new List() };
int index0CountValues0 = openMIValueSet.GetIndexCount(new[] { 0 });
for (int i = 0; i < index0CountValues0; i++)
{
values[0].Add((double) openMIValueSet.GetValue(new[] { 0, i }));
}
return values;
}
set
{
if (_openMIInputItem == null)
{
throw new Exception("\"" + Id + "SetValues: Values can not be set for output item");
}
if (!(value is double[]))
{
throw new Exception("\"" + Id + "SetValues: Unexpected object type for setting Values: " +
value.GetType());
}
double[] doubles = (double[]) value;
if (doubles.Length != 1)
{
throw new Exception("\"" + Id + "SetValues: Unexpected size for setting Values: " + value.GetType());
}
_openMIInputItem.Values = new ValueSet(_openMIItem, doubles[0]);
}
}
public double[] ValuesAsDoubles
{
get { return ((List>) Values)[0].ToArray(); }
set
{
if (_openMIInputItem == null)
{
throw new Exception("\"" + Id + "SetValues: Values can not be set for output item");
}
_openMIInputItem.Values = new ValueSet(_openMIItem, value);
}
}
public void AxpyOnValues(double alpha, double[] axpyValues)
{
if (_openMIInputItem == null)
{
throw new Exception("\"" + Id + "SetValues: Values can not be set for output item");
}
IList timeSeriesValuesForElement = _openMIInputItem.Values.GetElementValuesForTime(0);
for (int index = 0; index < axpyValues.Length; index++)
{
timeSeriesValuesForElement[index] = (double) timeSeriesValuesForElement[index] + alpha * axpyValues[index];
}
_openMIInputItem.Values.SetElementValuesForTime(0, timeSeriesValuesForElement);
}
public void MultiplyValues(double[] multiplicationFactors)
{
throw new NotImplementedException();
}
public double[] Times
{
get
{
if (_useBufferedValues)
{
return _bufferedTimes.ToArray();
}
IList openMITimes = _openMIItem.TimeSet.Times;
double[] openDATimes = new double[openMITimes.Count];
for (int i = 0; i < openMITimes.Count; i++)
{
openDATimes[i] = openMITimes[i].StampAsModifiedJulianDay;
}
return openDATimes;
}
set { throw new Exception("\"" + Id + "Set times not allowed for OpenMI exchange items"); }
}
public void AddNewOpenMIOutputValuesToBuffer()
{
ITimeSpaceValueSet timeSpaceValueSet = _openMIOutputItem.Values;
if (_openMIItem.TimeSet != null && _openMIItem.TimeSet.Times.Count > 0)
{
double currentOutputTimeAsMJD = _openMIItem.TimeSet.Times[0].StampAsModifiedJulianDay;
if (!_bufferedTimes.Contains(currentOutputTimeAsMJD))
{
_bufferedValues[0].Add((double)timeSpaceValueSet.Values2D[0][0]);
_bufferedTimes.Add(currentOutputTimeAsMJD);
_lastOutputTime = currentOutputTimeAsMJD; // HACK, REMOVE
}
}
else
{
_bufferedValues[0].Add((double)timeSpaceValueSet.Values2D[0][0]);
_bufferedTimes.Add(_lastOutputTime); // HACK, REMOVE
}
}
}
}