#region Copyright /* * Copyright (c) 2005,2006,2007, OpenMI Association * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenMI Association nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY "OpenMI Association" ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL "OpenMI Association" BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #endregion using System; using System.Collections; using OpenMI.Standard; using RTCTools.OpenMI.Sdk.Backbone; namespace RTCTools.OpenMI.Sdk.Buffer { /// /// The SmartBuffer class provides bufferig functionality that will store values needed for a /// particular link in memory and functionality that will interpolate, extrapolate and aggregate /// values from these values. /// [Serializable] public class SmartBuffer { ArrayList _times; ArrayList _values; double _relaxationFactor; //Used for the extrapolation algorithm see also RelaxationFactor property bool _doExtendedDataVerification; /// /// Short description of the SmartBuffer /// /// ///The content of the SmartBuffer is lists of corresponding times and ValueSets, ///where times can be TimeStamps or TimeSpans and the ValueSets can be ScalarSets or VectorSets. ///Or in other words the content of the SmartBuffer is corresponding ScalarSets and TimeStamps, or ScalarSets and TimeSpans, or VectorSets and TimeStamps, or VectorSets and TimeSpans. /// ///SmartBuffer objects may not contain mixtures of TimeSpans and TimeStamps and may not contain mixtures of ScalarSets and VectorSets. ///The number of Times (TimeSpans or TimeStamps) must equal the number of ValueSets ( ScalarSets or VectorSets) in the SmartBuffer. /// public SmartBuffer() { Create(); } /// /// Create a new SmartBuffer with values and times copied from another SmartBuffer /// /// The SmartBuffer to copy public SmartBuffer(SmartBuffer smartBuffer) { Create(); if (smartBuffer.TimesCount > 0) { if (smartBuffer.GetTimeAt(0) is ITimeStamp && smartBuffer.GetValuesAt(0) is IScalarSet) { for (int i = 0; i < smartBuffer.TimesCount; i++) { AddValues(new TimeStamp((ITimeStamp) smartBuffer.GetTimeAt(i)),new ScalarSet((IScalarSet) smartBuffer.GetValuesAt(i))); } } if (smartBuffer.GetTimeAt(0) is ITimeStamp && smartBuffer.GetValuesAt(0) is IVectorSet) { for (int i = 0; i < smartBuffer.TimesCount; i++) { AddValues(new TimeStamp((ITimeStamp)smartBuffer.GetTimeAt(i)),new VectorSet((IVectorSet)smartBuffer.GetValuesAt(i))); } } if (smartBuffer.GetTimeAt(0) is ITimeSpan && smartBuffer.GetValuesAt(0) is IScalarSet) { for (int i = 0; i < smartBuffer.TimesCount; i++) { AddValues(new Backbone.TimeSpan((ITimeSpan)smartBuffer.GetTimeAt(i)),new ScalarSet((IScalarSet)smartBuffer.GetValuesAt(i))); } } if (smartBuffer.GetTimeAt(0) is ITimeSpan && smartBuffer.GetValuesAt(0) is IVectorSet) { for (int i = 0; i < smartBuffer.TimesCount; i++) { AddValues(new Backbone.TimeSpan((ITimeSpan)smartBuffer.GetTimeAt(i)),new VectorSet((IVectorSet)smartBuffer.GetValuesAt(i))); } } } } private void Create() { _times = new ArrayList(); _values = new ArrayList(); _doExtendedDataVerification = true; _relaxationFactor = 1.0; } /// /// Add corresponding values for time and values to the SmartBuffer. /// /// Description of the time parameter /// Description of the values parameter /// /// The AddValues method will internally make a copy of the added times and values. The reason for /// doing this is that the times and values arguments are references, and the correspondign values /// could be changed by the owner of the classes /// public void AddValues(ITime time, IValueSet valueSet) { if (time is ITimeStamp) { _times.Add(new TimeStamp( ((ITimeStamp) time).ModifiedJulianDay )); } else if(time is ITimeSpan) { TimeStamp newStartTime = new TimeStamp(((ITimeSpan) time).Start.ModifiedJulianDay); TimeStamp newEndTime = new TimeStamp(((ITimeSpan) time).End.ModifiedJulianDay); Backbone.TimeSpan newTimeSpan = new Backbone.TimeSpan(newStartTime, newEndTime); _times.Add(newTimeSpan); } else { throw new Exception("Invalid datatype used for time argument in method AddValues"); } if (valueSet is IScalarSet) { double[] x = new double[(valueSet).Count]; for (int i = 0; i < x.Length; i++) { x[i] = ((IScalarSet) valueSet).GetScalar(i); } ScalarSet newScalarSet = new ScalarSet(x); if (valueSet is ScalarSet) { newScalarSet.MissingValueDefinition = ((ScalarSet)valueSet).MissingValueDefinition; newScalarSet.CompareDoublesEpsilon = ((ScalarSet)valueSet).CompareDoublesEpsilon; } _values.Add(newScalarSet); } else if (valueSet is IVectorSet) { Vector[] vectors = new Vector[valueSet.Count]; for (int i = 0; i < vectors.Length; i++) { vectors[i] = new Vector(((IVectorSet) valueSet).GetVector(i).XComponent, ((IVectorSet) valueSet).GetVector(i).YComponent, ((IVectorSet) valueSet).GetVector(i).ZComponent); } VectorSet newVectorSet = new VectorSet(vectors); _values.Add(newVectorSet); } else { throw new Exception("Invalid datatype used for values argument in method AddValues"); } if (_doExtendedDataVerification) { CheckBuffer(); } } /// /// RelaxationFactor. The relaxation factor must be in the interval [0; 1]. The relaxation /// parameter is used when doing extrapolation. A value of 1 results in nearest extrapolation /// whereas a value 0 results in linear extrapolation. /// public double RelaxationFactor { get { return _relaxationFactor; } set { _relaxationFactor = value; if (_relaxationFactor < 0 || _relaxationFactor > 1) { throw new Exception("ReleaxationFactor is out of range"); } } } /// /// Returns the timeStepīth ITime. /// /// time step index /// The timeStepīth ITime public ITime GetTimeAt(int timeStep) { if (_doExtendedDataVerification) { CheckBuffer(); } return (ITime) _times[timeStep]; } //=============================================================================================== // GetValuesAt(int timeStep) : IValueSet //=============================================================================================== /// /// Returns the timeStepīth IValueSet /// /// time step index /// The timeStepīth IValueSet public IValueSet GetValuesAt(int timeStep) { if (_doExtendedDataVerification) { CheckBuffer(); } return (IValueSet) _values[timeStep]; } /// /// Returns the ValueSet that corresponds to requestTime. The ValueSet may be found by /// interpolation, extrapolation and/or aggregation. /// /// time for which the value is requested /// valueSet that corresponds to requestTime public IValueSet GetValues(ITime requestedTime) { if (_doExtendedDataVerification) { CheckTime(requestedTime); CheckBuffer(); } IValueSet returnValueSet; if (_values.Count == 0) { returnValueSet = new ScalarSet(); } else if (_values.Count == 1) { returnValueSet = MakeCopyOfValues(); } else if (requestedTime is ITimeStamp && _times[0] is ITimeStamp) { returnValueSet = MapFromTimeStampsToTimeStamp((ITimeStamp) requestedTime); } else if (requestedTime is ITimeSpan && _times[0] is ITimeSpan) { returnValueSet = MapFromTimeSpansToTimeSpan((ITimeSpan) requestedTime); } else if (requestedTime is ITimeSpan && _times[0] is ITimeStamp) { returnValueSet = MapFromTimeStampsToTimeSpan((ITimeSpan) requestedTime); } else if (requestedTime is ITimeStamp && _times[0] is ITimeSpan) { returnValueSet = MapFromTimeSpansToTimeStamp((ITimeStamp) requestedTime); } else { throw new Exception("Requested TimeMapping not available in SmartWrapper Class"); } return returnValueSet; } /// /// A ValueSet corresponding to a TimeSpan is calculated using interpolation or /// extrapolation in corresponding lists of ValueSets and TimeSpans. /// /// Time for which the ValueSet is requested /// ValueSet that corresponds to requestedTime private IValueSet MapFromTimeSpansToTimeSpan(ITimeSpan requestedTime) { try { int m = ((IValueSet)_values[0]).Count; double[][] xr = new double[m][]; // Values to return double trb = requestedTime.Start.ModifiedJulianDay; // Begin time in requester time interval double tre = requestedTime.End.ModifiedJulianDay; // End time in requester time interval int nk; // number of components (scalars has only 1 and vectors has 3 (3 axis)) if (_values[0] is IVectorSet) { nk = 3; } else { nk = 1; } for (int i = 0; i < m; i++) { xr[i] = new double[nk]; } for (int i = 0; i < m; i++) { for (int k = 0; k < nk; k++) { xr[i][k] = 0; } } for (int n = 0; n < _times.Count; n++) { double tbbn = ((ITimeSpan) _times[n]).Start.ModifiedJulianDay; double tben = ((ITimeSpan) _times[n]).End.ModifiedJulianDay; //--------------------------------------------------------------------------- // B: <--------------------------> // R: <-------------------------------------> // -------------------------------------------------------------------------- if (trb <= tbbn && tre >= tben ) //Buffered TimeSpan fully included in requested TimeSpan { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); xr[i][k-1] += sbin * (tben - tbbn)/(tre - trb); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (tbbn <= trb && tre <= tben) //cover all { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { xr[i][k-1] += Support.GetVal((IValueSet)_values[n], i, k); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (tbbn < trb && trb < tben && tre > tben) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); xr[i][k-1] += sbin * (tben - trb)/(tre - trb); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (trb < tbbn && tre > tbbn && tre < tben) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); xr[i][k-1] += sbin * (tre - tbbn)/(tre - trb); } } } } //-------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //--------------------------------------------------------------------------- double tbb0 = ((ITimeSpan) _times[0]).Start.ModifiedJulianDay; double tbe0 = ((ITimeSpan) _times[0]).End.ModifiedJulianDay; //double tbb1 = ((ITimeSpan) _times[1]).Start.ModifiedJulianDay; double tbe1 = ((ITimeSpan) _times[1]).End.ModifiedJulianDay; if (trb < tbb0 && tre > tbb0) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] += ((tbb0 - trb)/(tre - trb)) * (sbi0 - (1 - _relaxationFactor) * ((tbb0 - trb)*(sbi1 - sbi0)/(tbe1 - tbe0))); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- double tbeN_1 = ((ITimeSpan) _times[_times.Count-1]).End.ModifiedJulianDay; double tbbN_2 = ((ITimeSpan) _times[_times.Count-2]).Start.ModifiedJulianDay; if (tre > tbeN_1 && trb < tbeN_1) { //double tbeN_2 = ((ITimeSpan) _times[_times.Count-2]).End.ModifiedJulianDay; double tbbN_1 = ((ITimeSpan) _times[_times.Count-1]).Start.ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i,k); xr[i][k-1] += ((tre - tbeN_1)/(tre - trb)) * (sbiN_1 + (1 - _relaxationFactor) * ((tre - tbbN_1)*(sbiN_1 - sbiN_2)/(tbeN_1 - tbbN_2))); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- if (trb >= tbeN_1) { double tbeN_2 = ((ITimeSpan) _times[_times.Count-2]).End.ModifiedJulianDay; //double tbbN_1 = ((ITimeSpan) _times[_times.Count-1]).Start.ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i, k); xr[i][k-1] = sbiN_1 + (1 - _relaxationFactor) * ((sbiN_1 - sbiN_2)/(tbeN_1 - tbbN_2)) * (trb + tre - tbeN_1 - tbeN_2); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- if (tre <= tbb0) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] = sbi0 - (1 - _relaxationFactor) * ((sbi1 - sbi0)/(tbe1- tbb0))*(tbe0 + tbb0 - tre - trb); } } } //------------------------------------------------------------------------------------- if (_values[0] is IVectorSet) { Vector [] vectors = new Vector[m]; for (int i = 0; i < m; i++) { vectors[i] = new Vector(xr[i][0],xr[i][1],xr[i][2]); } VectorSet vectorSet = new VectorSet(vectors); return vectorSet; } else { double[] xx = new double[m]; for (int i = 0; i < m; i++) { xx[i] = xr[i][0]; } ScalarSet scalarSet = new ScalarSet(xx); return scalarSet; } } catch (Exception e) { throw new Exception("MapFromTimeSpansToTimeSpan Failed",e); } } /// /// A ValueSet corresponding to a TimeSpan is calculated using interpolation or /// extrapolation in corresponding lists of ValueSets and TimeStamps. /// /// Time for which the ValueSet is requested /// ValueSet that corresponds to requestedTime private IValueSet MapFromTimeStampsToTimeSpan(ITimeSpan requestedTime) { try { int m = ((IValueSet)_values[0]).Count; //int N = _times.Count; // Number of time steps in buffer double[][] xr = new double[m][]; // Values to return double trb = requestedTime.Start.ModifiedJulianDay; // Begin time in requester time interval double tre = requestedTime.End.ModifiedJulianDay; // End time in requester time interval int nk; // number of components (scalars has only 1 and vectors has 3 (3 axis)) if (_values[0] is IVectorSet) { nk = 3; } else { nk = 1; } for (int i = 0; i < m; i++) { xr[i] = new double[nk]; } for (int i = 0; i < m; i++) { for (int k = 0; k < nk; k++) { xr[i][k] = 0; } } for (int n = 0; n < _times.Count-1; n++) { double tbn = ((ITimeStamp) _times[n]).ModifiedJulianDay; double tbnp1 = ((ITimeStamp) _times[n+1]).ModifiedJulianDay; //--------------------------------------------------------------------------- // B: <--------------------------> // R: <-------------------------------------> // -------------------------------------------------------------------------- if (trb <= tbn && tre >= tbnp1 ) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); double sbinp1 = Support.GetVal((IValueSet)_values[n+1], i, k); xr[i][k-1] += 0.5 * (sbin + sbinp1) * (tbnp1 - tbn)/(tre - trb); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (tbn <= trb && tre <= tbnp1) //cover all { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); double sbinp1 = Support.GetVal((IValueSet)_values[n+1], i, k); xr[i][k-1] += sbin + ((sbinp1 - sbin)/(tbnp1 - tbn))*((tre + trb)/2 - tbn); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (tbn < trb && trb < tbnp1 && tre > tbnp1) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); double sbinp1 = Support.GetVal((IValueSet)_values[n+1], i, k); xr[i][k-1] += (sbinp1 - (sbinp1 - sbin)/(tbnp1 - tbn)*((tbnp1 - trb)/2))* (tbnp1 - trb)/(tre - trb); } } } //--------------------------------------------------------------------------- // Times[i] Interval: t1|-----------------|t2 // Requested Interval: rt1|--------------|rt2 // -------------------------------------------------------------------------- else if (trb < tbn && tre > tbn && tre < tbnp1) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) // for all values coorsponding to the same time interval { double sbin = Support.GetVal((IValueSet)_values[n], i, k); double sbinp1 = Support.GetVal((IValueSet)_values[n+1], i, k); xr[i][k-1] += (sbin + (sbinp1 - sbin)/(tbnp1 - tbn)*((tre - tbn)/2)) * (tre - tbn)/(tre - trb); } } } } //-------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //--------------------------------------------------------------------------- double tb0 = ((ITimeStamp) _times[0]).ModifiedJulianDay; //double tb1 = ((ITimeStamp) _times[0]).ModifiedJulianDay; double tb1 = ((ITimeStamp) _times[1]).ModifiedJulianDay; // line above was corrected to this Gregersen Sep 15 2004 double tbN_1 = ((ITimeStamp) _times[_times.Count-1]).ModifiedJulianDay; double tbN_2 = ((ITimeStamp) _times[_times.Count-2]).ModifiedJulianDay; if (trb < tb0 && tre > tb0) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] += ((tb0 - trb)/(tre - trb)) * (sbi0 - (1 - _relaxationFactor) * 0.5 * ((tb0 - trb)*(sbi1 - sbi0)/(tb1 - tb0))); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- if (tre > tbN_1 && trb < tbN_1) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i, k); xr[i][k-1] += ((tre - tbN_1)/(tre - trb)) * (sbiN_1 + (1 - _relaxationFactor) * 0.5 * ((tre - tbN_1)*(sbiN_1 - sbiN_2)/(tbN_1 - tbN_2))); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- if (trb >= tbN_1) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i, k); xr[i][k-1] = sbiN_1 + (1 - _relaxationFactor) * ((sbiN_1 - sbiN_2)/(tbN_1 - tbN_2)) * ( 0.5 * (trb + tre) - tbN_1); } } } //------------------------------------------------------------------------------------- // |--------|---------|--------| B // |----------------| R //------------------------------------------------------------------------------------- if (tre <= tb0) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] = sbi0 - (1 - _relaxationFactor) * ((sbi1 - sbi0)/(tb1- tb0))*(tb0 - 0.5 * (trb + tre)); } } } //------------------------------------------------------------------------------------- if (_values[0] is IVectorSet) { Vector [] vectors = new Vector[m]; for (int i = 0; i < m; i++) { vectors[i] = new Vector(xr[i][0],xr[i][1],xr[i][2]); } VectorSet vectorSet = new VectorSet(vectors); return vectorSet; } else { double[] xx = new double[m]; for (int i = 0; i < m; i++) { xx[i] = xr[i][0]; } ScalarSet scalarSet = new ScalarSet(xx); return scalarSet; } } catch (Exception e) { throw new Exception("MapFromTimeStampsToTimeSpan Failed",e); } } /// /// Makes a copy of the first ValueSet in the list of valueSets /// /// private IValueSet MakeCopyOfValues() { if (_values[0] is IScalarSet) { int NumberOfScalarsInEachScalarSet = ((IScalarSet) _values[0]).Count; double[] x = new Double[NumberOfScalarsInEachScalarSet]; for (int i = 0; i < NumberOfScalarsInEachScalarSet; i++) { x[i] = ((IScalarSet) _values[0]).GetScalar(i); } ScalarSet scalarSet = new ScalarSet(x); return scalarSet; } else // _values[0] is VectorSet { int NumberOfVectorsInEachVectorSet = ((IVectorSet) _values[0]).Count; Vector[] vectors = new Vector[NumberOfVectorsInEachVectorSet]; for (int i = 0; i < NumberOfVectorsInEachVectorSet; i++) { Vector vector; double x = ((IVectorSet)_values[0]).GetVector(i).XComponent; double y = ((IVectorSet) _values[0]).GetVector(i).YComponent; double z = ((IVectorSet) _values[0]).GetVector(i).ZComponent; vector = new Vector(x, y, z); vectors[i] = vector; } VectorSet vectorSet = new VectorSet(vectors); return vectorSet; } } /// /// A ValueSet corresponding to a TimeStamp is calculated using interpolation or /// extrapolation in corresponding lists of ValueSets and TimeStamps. /// /// TimeStamp for which the values are requested /// ValueSet that corresponds to the requested time stamp private IValueSet MapFromTimeStampsToTimeStamp(ITimeStamp requestedTimeStamp) { try { int m = ((IValueSet)_values[0]).Count; double[][] xr = new double[m][]; // Values to return double tr = requestedTimeStamp.ModifiedJulianDay; // Requested TimeStamp int nk; // number of components (scalars has only 1 and vectors has 3 (3 axis)) if (_values[0] is IVectorSet) { nk = 3; } else { nk = 1; } for (int i = 0; i < m; i++) { xr[i] = new double[nk]; } //--------------------------------------------------------------------------- // Buffered TimesStamps: | >tb0< >tb1< >tb2< >tbN< // Requested TimeStamp: | >tr< // -----------------------------------------> t // -------------------------------------------------------------------------- if (tr <= ((ITimeStamp)_times[0]).ModifiedJulianDay ) { double tb0 = ((ITimeStamp) _times[0]).ModifiedJulianDay; double tb1 = ((ITimeStamp) _times[1]).ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m ; i++) //For each Vector in buffered VectorSet [0] { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] = ((sbi0 - sbi1)/(tb0 - tb1))*(tr - tb0) * (1 - _relaxationFactor) + sbi0; } } } //--------------------------------------------------------------------------- // Buffered TimesStamps: | >tb0< >tb1< >tb2< >tbN_2< >tbN_1< // Requested TimeStamp: | >tr< // ---------------------------------------------------> t // -------------------------------------------------------------------------- else if (tr > ((ITimeStamp) _times[_times.Count - 1]).ModifiedJulianDay) { double tbN_2 = ((ITimeStamp) _times[_times.Count - 2]).ModifiedJulianDay; double tbN_1 = ((ITimeStamp) _times[_times.Count - 1]).ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) //For each Vector in buffered VectorSet [N-1] { double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i, k); double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); xr[i][k-1] = ((sbiN_1 - sbiN_2)/(tbN_1 - tbN_2))*(tr - tbN_1)*(1 - _relaxationFactor) + sbiN_1; } } } //--------------------------------------------------------------------------- // Availeble TimesStamps: | >tb0< >tb1< >tbna< >tnb< >tbN_1< >tbN_2< // Requested TimeStamp: | >tr< // -------------------------------------------------> t // -------------------------------------------------------------------------- else { for (int n = _times.Count - 2; n >= 0 ; n--) { double tbn1 = ((ITimeStamp) _times[n]).ModifiedJulianDay; double tbn2 = ((ITimeStamp) _times[n+1]).ModifiedJulianDay; if ( tbn1 <= tr && tr <= tbn2) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) //For each Vector in buffered VectorSet [n] { IValueSet valueSet_n = (IValueSet)_values[n]; double sbin1 = Support.GetVal(valueSet_n, i, k); IValueSet valueSet_nPlus1 = (IValueSet)_values[n+1]; double sbin2 = Support.GetVal(valueSet_nPlus1, i, k);; if ( valueSet_n.IsValid(i) && valueSet_nPlus1.IsValid(i)) { xr[i][k-1] = ((sbin2 - sbin1)/(tbn2 - tbn1)) * (tr - tbn1) + sbin1; } else if ( valueSet_n.IsValid(i) ) { xr[i][k-1] = sbin1; } else if ( valueSet_nPlus1.IsValid(i) ) { xr[i][k-1] = sbin2; } else { // both invalid, set to one of the (==invalid) values xr[i][k-1] = sbin1; } } } break; } } } //---------------------------------------------------------------------------------------------- if (_values[0] is IVectorSet) { Vector [] vectors = new Vector[m]; for (int i = 0; i < m; i++) { vectors[i] = new Vector(xr[i][0],xr[i][1],xr[i][2]); } VectorSet vectorSet = new VectorSet(vectors); return vectorSet; } else { double[] xx = new double[m]; for (int i = 0; i < m; i++) { xx[i] = xr[i][0]; } ScalarSet scalarSet = new ScalarSet(xx); return scalarSet; } } catch (Exception e) { throw new Exception("MapFromTimeStampsToTimeStamp Failed",e); } } /// /// A ValueSet corresponding to a TimeSpan is calculated using interpolation or /// extrapolation in corresponding lists of ValueSets and TimeSpans. /// /// Time for which the ValueSet is requested /// ValueSet that corresponds to requestedTime private IValueSet MapFromTimeSpansToTimeStamp(ITimeStamp requestedTimeStamp) { try { int m = ((IValueSet)_values[0]).Count; double[][] xr = new double[m][]; // Values to return double tr = requestedTimeStamp.ModifiedJulianDay; // Requested TimeStamp int nk; // number of components (scalars has only 1 and vectors has 3 (3 axis)) if (_values[0] is IVectorSet) { nk = 3; } else { nk = 1; } for (int i = 0; i < m; i++) { xr[i] = new double[nk]; } //--------------------------------------------------------------------------- // Buffered TimesSpans: | >tbb0< .......... >tbbN< // Requested TimeStamp: | >tr< // -----------------------------------------> t // -------------------------------------------------------------------------- if (tr <= ((ITimeSpan)_times[0]).Start.ModifiedJulianDay ) { double tbb0 = ((ITimeSpan) _times[0]).Start.ModifiedJulianDay; double tbb1 = ((ITimeSpan) _times[1]).Start.ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m ; i++) //For each Vector in buffered VectorSet [0] { double sbi0 = Support.GetVal((IValueSet)_values[0], i, k); double sbi1 = Support.GetVal((IValueSet)_values[1], i, k); xr[i][k-1] = ((sbi0 - sbi1)/(tbb0 - tbb1))*(tr - tbb0) * (1 - _relaxationFactor) + sbi0; } } } //--------------------------------------------------------------------------- // Buffered TimesSpans: | >tbb0< ................. >tbbN_1< // Requested TimeStamp: | >tr< // ---------------------------------------------------> t // -------------------------------------------------------------------------- else if (tr >= ((ITimeSpan) _times[_times.Count - 1]).End.ModifiedJulianDay) { double tbeN_2 = ((ITimeSpan) _times[_times.Count - 2]).End.ModifiedJulianDay; double tbeN_1 = ((ITimeSpan) _times[_times.Count - 1]).End.ModifiedJulianDay; for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) //For each Vector in buffered VectorSet [N-1] { double sbiN_2 = Support.GetVal((IValueSet)_values[_times.Count-2], i, k); double sbiN_1 = Support.GetVal((IValueSet)_values[_times.Count-1], i, k); xr[i][k-1] = ((sbiN_1 - sbiN_2)/(tbeN_1 - tbeN_2))*(tr - tbeN_1)*(1 - _relaxationFactor) + sbiN_1; } } } //--------------------------------------------------------------------------- // Availeble TimesSpans: | >tbb0< ...................... >tbbN_1< // Requested TimeStamp: | >tr< // -------------------------------------------------> t // -------------------------------------------------------------------------- else { for (int n = _times.Count - 1; n >= 0 ; n--) { double tbbn = ((ITimeSpan) _times[n]).Start.ModifiedJulianDay; double tben = ((ITimeSpan) _times[n]).End.ModifiedJulianDay; if ( tbbn <= tr && tr < tben) { for (int k = 1; k <= nk; k++) { for (int i = 0; i < m; i++) //For each Vector in buffered VectorSet [n] { xr[i][k-1] = Support.GetVal((IValueSet)_values[n], i, k); } } break; } } } //---------------------------------------------------------------------------------------------- if (_values[0] is IVectorSet) { Vector [] vectors = new Vector[m]; for (int i = 0; i < m; i++) { vectors[i] = new Vector(xr[i][0],xr[i][1],xr[i][2]); } VectorSet vectorSet = new VectorSet(vectors); return vectorSet; } else { double[] xx = new double[m]; for (int i = 0; i < m; i++) { xx[i] = xr[i][0]; } ScalarSet scalarSet = new ScalarSet(xx); return scalarSet; } } catch (Exception e) { throw new Exception("MapFromTimeSpansToTimeStamp Failed",e); } } /// /// Number of time streps in the buffer. /// public int TimesCount { get { return _times.Count; } } /// /// Read only property for the number of values in each of the valuesets contained in the buffer. /// public int ValuesCount { get { return ((IValueSet) _values[0]).Count; } } /// /// Checks weather the contents of the buffer is valid. /// public void CheckBuffer() { if(_times.Count != _values.Count) { throw new Exception("Different numbers of values and times in buffer"); } if(_times.Count == 0) { throw new Exception("Buffer is empty"); } for (int i = 0; i < _times.Count; i++) { if (!(_times[i] is ITimeSpan || _times[i] is ITimeStamp)) { throw new Exception("Illegal data type for time in buffer"); } } for (int i = 0; i < _values.Count; i++) { if (!(_values[i] is IScalarSet || _values[i] is IVectorSet)) { throw new Exception("Illegal data type for values in buffer"); } } if (_times[0] is ITimeSpan) { foreach ( ITimeSpan t in _times) { if (t.Start.ModifiedJulianDay >= t.End.ModifiedJulianDay) { throw new Exception("BeginTime is larger than or equal to EndTime in TimeSpan"); } } for (int i = 1; i < _times.Count; i++) { if (1.0e-8 < Math.Abs(((ITimeSpan)_times[i]).Start.ModifiedJulianDay - ((ITimeSpan)_times[i-1]).End.ModifiedJulianDay)) { throw new Exception("EndTime is not equal to StartTime for the following time step"); } } } if (_times[0] is ITimeStamp) { for (int i = 1; i < _times.Count; i++) { if (((ITimeStamp)_times[i]).ModifiedJulianDay <= ((ITimeStamp) _times[i-1]).ModifiedJulianDay) throw new Exception("TimeStamps are not increasing in buffer"); } } } /// /// Validates a given time. The check made is for TimeSpan the starting time must be smaller /// than the end time. Throws exception if the time is not valid. /// private static void CheckTime(ITime time) { if (time is ITimeSpan) { if(((ITimeSpan) time).Start.ModifiedJulianDay >= ((ITimeSpan) time).End.ModifiedJulianDay) { throw new Exception("Start Time is larger than or equal to End Time in TimeSpan"); } } } /// /// Read/Write property flag that indicates wheather or not to perform extended data /// checking. /// public bool DoExtendedDataVerification { get { return _doExtendedDataVerification; } set { _doExtendedDataVerification = value; } } /// /// Clear all times and values in the buffer at or later than the specified time /// If the specified time is type ITimeSpan the Start time is used. /// /// public void ClearAfter(ITime time) { //TODO: this method can be simplyfied (see implementation of method: ClearBefore TimeStamp timeStamp = new TimeStamp(); if (time is ITimeStamp) { timeStamp.ModifiedJulianDay = ((ITimeStamp) time).ModifiedJulianDay; } else if(time is ITimeSpan) { timeStamp.ModifiedJulianDay = ((ITimeSpan) time).Start.ModifiedJulianDay; } else { throw new Exception("Wrong argument type for call to RTCTools.OpenMI.Sdk.Buffer.SmartBuffer.ClearAfter()"); } if (_times.Count > 0) { bool recordWasRemoved; if(_times[0] is ITimeStamp) { do { recordWasRemoved = false; if (((ITimeStamp)_times[_times.Count - 1]).ModifiedJulianDay >= timeStamp.ModifiedJulianDay) { _values.RemoveAt(_times.Count - 1); _times.RemoveAt(_times.Count - 1); recordWasRemoved = true; } } while (recordWasRemoved && _times.Count > 0); } else if (_times[0] is ITimeSpan) { do { recordWasRemoved = false; if (((ITimeSpan)_times[_times.Count - 1]).Start.ModifiedJulianDay >= timeStamp.ModifiedJulianDay) { _values.RemoveAt(_times.Count - 1); _times.RemoveAt(_times.Count - 1); recordWasRemoved = true; } } while (recordWasRemoved && _times.Count > 0); } } } /// /// Clear all records in the buffer assocaited to time that is earlier that the /// time specified in the argument list. However, one record associated to time /// before the time in the argument list is left in the buffer. /// The criteria when comparing TimeSpans is that they may not overlap in order /// to be regarded as before each other. /// (see also RTCTools.OpenMI.Sdk.Buffer.Support.IsBefore(ITime ta, ITime tb) /// /// time before which the records are removed public void ClearBefore(ITimeStamp time) { int numberOfRecordsToRemove = 0; foreach (ITime t in _times) { if (Support.IsBefore(t, time)) { numberOfRecordsToRemove ++; } } numberOfRecordsToRemove--; // decrease index to ensure that one record before time is left back if (numberOfRecordsToRemove > 0) { _times.RemoveRange(0,numberOfRecordsToRemove); _values.RemoveRange(0,numberOfRecordsToRemove); } } /// /// Clears the buffer between start- and end- time of the time (TimeSpan). /// public void Clear(ITimeSpan time) //TODO: This method may not be used anywhere. Check if this is true and then remove this method { if (_times.Count > 0) { if(_times[0] is ITimeStamp) { for (int i = 0; i < _times.Count; i++) { if (((ITimeStamp)_times[i]).ModifiedJulianDay > time.Start.ModifiedJulianDay && ((ITimeStamp)_times[i]).ModifiedJulianDay < time.End.ModifiedJulianDay) { _times.RemoveAt(i); _values.RemoveAt(i); } } } else if (_times[0] is ITimeSpan) { for (int i = 0; i < _times.Count; i++) { if (((ITimeSpan)_times[i]).Start.ModifiedJulianDay > time.Start.ModifiedJulianDay && ((ITimeSpan)_times[i]).End.ModifiedJulianDay < time.End.ModifiedJulianDay) { _times.RemoveAt(i); _values.RemoveAt(i); } } } } } } }