using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using RTCTools.OpenMI.Sdk.Backbone;
using RTCTools.OpenMI.Sdk.DevelopmentSupport;
using RTCTools.OpenMI.Sdk.Wrapper;
using OpenMI.Standard;
using TimeSpan=RTCTools.OpenMI.Sdk.Backbone.TimeSpan;
using Deltares.RtcTools.Net;
namespace Deltares.RtcToolsWrapper
{
///
/// Wrapper for RtcTools that implements the Oatc's wrapping utility's IEngine interface
///
public class RtcToolsWrapper : IEngine
{
private const string indexSeparator = "@";
private readonly RtcToolsDll _cRtcTools = new RtcToolsDll();
private readonly List _outputExchangeItems = new List();
private readonly List _inputExchangeItems = new List();
private readonly List _quantities = new List();
private readonly List _units = new List();
private Dictionary _oMap = new Dictionary();
private Dictionary _iMap = new Dictionary();
private Dictionary _unitMap = new Dictionary();
private Dictionary _dimMap = new Dictionary();
private DateTime dtCurrentTime;
private double missingValue = -999.00; // this is the value Sobek uses. If Sobek gets this value, Sobek does nothing.
private int OpenMiTimeStepSkip = 1; // default value is 1.
// OpenMiTimeStepSkip = 1 would mean that data exchange takes place every time step RTC-Tools has.
// OpenMiTimeStepSkip = 2 would mean that every 2nd time step is made available in OpenMI
private string _schemaLocation = ".\\";
private string _modelId = "RtcTools_ModelId";
public void Initialize(Hashtable properties)
{
// defaults
string modelDirectory = Path.GetFullPath(".");
int logLevel = 2;
bool flush = false;
// user supplied settings
if (properties["modelId"] != null)
{
_modelId = (string)properties["modelId"];
}
if (properties["modelDirectory"] != null)
{
modelDirectory = Path.GetFullPath((string)properties["modelDirectory"]);
}
if (properties["MissingValue"]!= null)
{
missingValue = Convert.ToDouble(properties["MissingValue"].ToString());
}
if (properties["OpenMiTimeStepSkip"]!= null)
{
OpenMiTimeStepSkip = Convert.ToInt32(properties["OpenMiTimeStepSkip"].ToString());
}
if (properties["SchemaLocation"] != null)
{
_schemaLocation = properties["SchemaLocation"].ToString();
}
if (!Directory.Exists(modelDirectory))
{
throw new Exception(String.Format("Model directory {0} does not exist", modelDirectory));
}
// creates a class from type RtcToolsDllDotNetAcces.
_cRtcTools.Initialize(modelDirectory, _schemaLocation);
// initalizes units and dimensions
InitializeUnits();
// create exchange items, to be stored in adjacent ArrayLists
for (int i=0; i<_cRtcTools.GetInputExchangeItemCount(); i++)
{
// element
Element e = new Element();
e.ID = _cRtcTools.InputExchangeItemGetElementId(i);
// element set
ElementSet es = new ElementSet();
es.AddElement(e);
es.ElementType = ElementType.IDBased;
es.Description = es.ID = _cRtcTools.InputExchangeItemGetQuantityId(i)+indexSeparator+e.ID;
_iMap.Add(es.ID, i);
// quantity
Quantity q = new Quantity(_cRtcTools.InputExchangeItemGetQuantityId(i));
string u = _cRtcTools.InputExchangeItemGetUnit(i);
q.Unit = _unitMap[u];
q.Dimension = _dimMap[u];
// exchange item
InputExchangeItem iei = new InputExchangeItem();
iei.Quantity = q;
iei.ElementSet = es;
_inputExchangeItems.Add(iei);
}
for (int i=0; i<_cRtcTools.GetOutputExchangeItemCount(); i++)
{
// element
Element e = new Element();
e.ID = _cRtcTools.OutputExchangeItemGetElementId(i);
// element set
ElementSet es = new ElementSet();
es.AddElement(e);
es.ElementType = ElementType.IDBased;
es.Description = es.ID = _cRtcTools.OutputExchangeItemGetQuantityId(i)+indexSeparator+e.ID;
_oMap.Add(es.ID, i);
// quantity
Quantity q = new Quantity(_cRtcTools.OutputExchangeItemGetQuantityId(i));
string u = _cRtcTools.OutputExchangeItemGetUnit(i);
q.Unit = _unitMap[u];
q.Dimension = _dimMap[u];
// exchange item
OutputExchangeItem oei = new OutputExchangeItem();
oei.Quantity = q;
oei.ElementSet = es;
_outputExchangeItems.Add(oei);
}
}
public void Finish()
{
_cRtcTools.Finish();
}
public void Dispose()
{
_cRtcTools.Dispose();
}
public bool PerformTimeStep()
{
if (OpenMiTimeStepSkip != -1)
{
_cRtcTools.PerformTimeStep(OpenMiTimeStepSkip);
}
else
{
_cRtcTools.PerformTimeStep(1);
}
return true;
}
// time related ------------------------------------------------------------------
public ITime GetCurrentTime()
{
string datetime = _cRtcTools.GetCurrentTimeString();
dtCurrentTime = DateTime.Parse(datetime);
double dCurrentTime = CalendarConverter.Gregorian2ModifiedJulian(dtCurrentTime);
TimeStamp tsCurrentTime = new TimeStamp(dCurrentTime);
return tsCurrentTime;
}
public ITime GetInputTime(string quantityID, string elementSetID)
{
return GetCurrentTime();
}
public ITimeStamp GetEarliestNeededTime()
{
return GetCurrentTime() as TimeStamp;
}
public ITimeSpan GetTimeHorizon()
{
string datetime = _cRtcTools.GetStartTimeString();
var dtStartTime = DateTime.Parse(datetime);
double dStartTime = CalendarConverter.Gregorian2ModifiedJulian(dtStartTime);
ITimeStamp tsStart = new TimeStamp(dStartTime);
datetime = _cRtcTools.GetEndTimeString();
var dtEndTime = DateTime.Parse(datetime);
double dEndTime = CalendarConverter.Gregorian2ModifiedJulian(dtEndTime);
ITimeStamp tsEnd = new TimeStamp(dEndTime);
ITimeSpan timeHorizon = new TimeSpan(tsStart, tsEnd);
return timeHorizon;
}
public double GetMissingValueDefinition()
{
return missingValue;
}
public string GetComponentID() {
return "RtcTools_ComponentId";
}
public string GetComponentDescription() {
return "RtcTools_ComponentDescription";
}
public string GetModelID() {
return _modelId;
}
public string GetModelDescription() {
return "RtcTools_ModelDescription";
}
// get / set values ----------------------------------------------------------------
public IValueSet GetValues(string quantityID, string elementSetID)
{
ScalarSet scalarSet = new ScalarSet(new[] { GetMissingValueDefinition() });
try {
int index = _oMap[elementSetID];
double value = _cRtcTools.GetValue(index);
if (!double.IsNaN(value)) {
scalarSet = new ScalarSet(new[] { value });
}
}
catch (Exception) {
throw new Exception("RtcToolsWrapper.GetValues: Error in GetValue(elementSetID= " + elementSetID + ", quantityID= " + quantityID + ")");
}
/*if (scalarSet.GetScalar(0).Equals(GetMissingValueDefinition()))
{
Event eventA = new Event(0);
eventA.Description = "RtcToolsWrapper.GetValues: Got NaN value from RtcTools Core. Setting " + GetMissingValueDefinition() + " for " + elementSetID + "," + quantityID + ")";
eventA.Type = EventType.Informative;
// How do we send this event?
}*/
return scalarSet;
}
public void SetValues(string quantityID, string elementSetID, IValueSet values)
{
double value = ((ScalarSet)values).GetScalar(0);
if (value != GetMissingValueDefinition())
{
try
{
int index = _iMap[elementSetID];
if (OpenMiTimeStepSkip != -1)
{
_cRtcTools.SetValue(index, value, OpenMiTimeStepSkip);
}
else
{
_cRtcTools.SetValue(index, value);
}
}
catch (Exception)
{
throw new Exception("RtcToolsWrapper.SetValues: Error in SetValue(elementSetID= " + elementSetID +
", quantityID= " + quantityID + ")");
}
}
}
// exchange items --------------------------------------------------------------
public int GetInputExchangeItemCount() {
return _cRtcTools.GetInputExchangeItemCount();
}
public int GetOutputExchangeItemCount() {
return _cRtcTools.GetOutputExchangeItemCount();
}
public OutputExchangeItem GetOutputExchangeItem(int exchangeItemIndex) {
return (OutputExchangeItem)_outputExchangeItems[exchangeItemIndex];
}
public InputExchangeItem GetInputExchangeItem(int exchangeItemIndex) {
return (InputExchangeItem)_inputExchangeItems[exchangeItemIndex];
}
private void InitializeUnits()
{
// init supported units
Unit mUnit = new Unit();
mUnit.ID = "m";
mUnit.ConversionFactorToSI = 1;
mUnit.OffSetToSI = 0;
Dimension mDimension = new Dimension();
mDimension.SetPower(DimensionBase.Length, 1);
_unitMap.Add(mUnit.ID, mUnit);
_dimMap.Add(mUnit.ID, mDimension);
Unit m2Unit = new Unit();
m2Unit.ID = "m^2";
m2Unit.ConversionFactorToSI = 1;
m2Unit.OffSetToSI = 0;
Dimension m2Dimension = new Dimension();
m2Dimension.SetPower(DimensionBase.Length, 2);
_unitMap.Add(m2Unit.ID, m2Unit);
_dimMap.Add(m2Unit.ID, m2Dimension);
Unit m3Unit = new Unit();
m3Unit.ID = "m^3";
m3Unit.ConversionFactorToSI = 1;
m3Unit.OffSetToSI = 0;
Dimension m3Dimension = new Dimension();
m3Dimension.SetPower(DimensionBase.Length, 3);
_unitMap.Add(m3Unit.ID, m3Unit);
_dimMap.Add(m3Unit.ID, m3Dimension);
Unit m3sUnit = new Unit();
m3sUnit.ID = "m^3/s";
m3sUnit.ConversionFactorToSI = 1;
m3sUnit.OffSetToSI = 0;
Dimension m3sDimension = new Dimension();
m3sDimension.SetPower(DimensionBase.Length, 3);
m3sDimension.SetPower(DimensionBase.Time, -1);
_unitMap.Add(m3sUnit.ID, m3sUnit);
_dimMap.Add(m3sUnit.ID, m3sDimension);
Unit sUnit = new Unit();
sUnit.ID = "s";
sUnit.ConversionFactorToSI = 1;
sUnit.OffSetToSI = 0;
Dimension sDimension = new Dimension();
sDimension.SetPower(DimensionBase.Time, 1);
_unitMap.Add(sUnit.ID, sUnit);
_dimMap.Add(sUnit.ID, sDimension);
}
}
}