using System; using System.Collections; using System.Collections.Generic; using Oatc.OpenMI.Sdk.Backbone; using Oatc.OpenMI.Sdk.DevelopmentSupport; using Oatc.OpenMI.Sdk.Wrapper; using OpenMI.Standard; using TimeSpan=Oatc.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 = ""; int logLevel = 2; bool flush = false; // user supplied settings if (properties["modelId"] != null) { _modelId = (string)properties["modelId"]; } if (properties["modelDirectory"] != null) { modelDirectory = (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(); } // 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 GetTimeHorizon().Start; } 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); } } }