/// <summary>Removes all elements from the <see cref="IGridPointCurve"/> object. /// </summary> /// <remarks>This method set the <see cref="IOperable.IsOperable"/> flag to <c>false</c>.</remarks> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public void Clear() { m_GridPointLabels.Clear(); m_GridPointArguments.Clear(); m_GridPointValues.Clear(); m_State = GridPointCurve.State.GridPointChanged; }
/// <summary>Removes a specific grid point. /// </summary> /// <param name="gridPointIndex">The null-based index of the grid point.</param> /// <remarks>This method set the <see cref="IOperable.IsOperable"/> flag to <c>false</c>.</remarks> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public void RemoveAt(int gridPointIndex) { m_GridPointArguments.RemoveAt(gridPointIndex); m_GridPointValues.RemoveAt(gridPointIndex); m_State = GridPointCurve.State.GridPointChanged; }
/// <summary>Changes a specific grid point argument. /// </summary> /// <param name="gridPointIndex">The null-based index of the grid point.</param> /// <param name="argument">The argument of the specified grid point, i.e. the <see cref="System.Double"/> representation of the label of the x-axis.</param> /// <remarks>This method set the <see cref="IOperable.IsOperable"/> flag to <c>false</c>.</remarks> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public void SetGridPointArgument(int gridPointIndex, double argument) { /* If a re-ordering of the grid points is necessary we first remove the grid point and re-insert the 'new' a the specific position: */ if (GridPointCount == 0) { throw new InvalidOperationException(); } if ((gridPointIndex < 0) || (gridPointIndex > GridPointCount - 1)) { throw new IndexOutOfRangeException(); } int previousGridPointIndex = Math.Max(0, gridPointIndex - 1); int nextGridPointIndex = Math.Min(gridPointIndex + 1, GridPointCount - 1); if ((m_GridPointArguments[previousGridPointIndex] <= argument) && (argument <= m_GridPointArguments[nextGridPointIndex])) { m_GridPointArguments[gridPointIndex] = argument; m_State |= GridPointCurve.State.GridPointArgumentChanged; } else { var label = m_GridPointLabels[gridPointIndex]; var value = m_GridPointValues[gridPointIndex]; RemoveAt(gridPointIndex); Add(label, argument, value); } }
/// <summary>Gets a value of the surface at a specified (x,y) coordinate. /// </summary> /// <param name="x">The x coordinate of the point.</param> /// <param name="y">The y coordinate of the point.</param> /// <returns>The value of the surface at (<paramref name="x"/>, <paramref name="y"/>).</returns> public override double GetValue(double x, double y) { int columnCount = m_HorizontalDoubleLabels.Length; /* compute values w.r.t. to the y-coordinate and each relevant column, i.e. store values to take into account for horizontal * interpolation. In the case of a non-local approach, one may improve performance by indicating that the labels will not be changed: */ int k = 0; for (int j = 0; j < columnCount; j++) { m_TempValuesForHorizontalEvaluation[k++] = m_CurvesAlongVerticalDirection[j].GetValue(y); } GridPointCurve.State horizontalCurveState = GridPointCurve.State.GridPointChanged; if ((m_HorizontalParametrization.IsOperable == true) && (m_HorizontalParametrization.GridPointCount == columnCount)) { horizontalCurveState = GridPointCurve.State.GridPointValueChanged; } m_HorizontalParametrization.Update(columnCount, m_HorizontalDoubleLabels, m_TempValuesForHorizontalEvaluation, horizontalCurveState); if ((x < m_HorizontalParametrization.LowerBound) || (x > m_HorizontalParametrization.UpperBound)) { throw new ArgumentOutOfRangeException(); } return(m_HorizontalParametrization.GetValue(x)); }
/// <summary>Updates the current instance. This method may change <see cref="IOperable.IsOperable"/>. /// </summary> /// <remarks>Call this method after grid points have been removed, modified or added and before trying to compute a value at a specified argument. /// <para>In general this method sets the <see cref="IOperable.IsOperable"/> flag to <c>true</c>.</para></remarks> public void Update() { m_CurveBuilder.Update(m_GridPointLabels.Count, m_GridPointArguments, m_GridPointValues, m_State); m_LeftExtrapolator.Update(); m_RightExtrapolator.Update(); m_State = GridPointCurve.State.NoChangeSinceLastUpdate; }
/// <summary>Changes the value component of a specific grid point. /// </summary> /// <param name="label">The label.</param> /// <param name="value">The value.</param> /// <returns>A value indicating whether the <paramref name="label"/> exists in the curve and the value component has been changed to <paramref name="value"/>.</returns> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public bool TrySetValue(double label, double value) { int labelIndex = m_GridPointArguments.FindIndex(match => match.Equals(label)); if (labelIndex >= 0) { m_GridPointValues[labelIndex] = value; m_State |= GridPointCurve.State.GridPointValueChanged; return true; } return false; }
/// <summary>Removes a specific grid point. /// </summary> /// <param name="label">The label of the grid point to remove.</param> /// <returns>A value indicating whether the grid point with respect to <paramref name="label"/> has been removed.</returns> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public bool TryRemove(double label) { int labelIndex = m_GridPointArguments.FindIndex(match => match.Equals(label)); if (labelIndex >= 0) { m_GridPointArguments.RemoveAt(labelIndex); m_GridPointValues.RemoveAt(labelIndex); m_State = GridPointCurve.State.GridPointChanged; return true; } return false; }
/// <summary>Changes the value component of a specific grid point. /// </summary> /// <param name="label">The label.</param> /// <param name="value">The value.</param> /// <returns>A value indicating whether the <paramref name="label"/> exists in the curve and the value component has been changed to <paramref name="value"/>.</returns> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public bool TrySetValue(TLabel label, double value) { int labelIndex = m_GridPointLabels.FindIndex(match => match.Equals(label)); if (labelIndex >= 0) { m_GridPointValues[labelIndex] = value; m_State |= GridPointCurve.State.GridPointValueChanged; return(true); } return(false); }
/// <summary>Adds a specific grid point. /// </summary> /// <param name="label">The label.</param> /// <param name="argument">The argument, i.e. the <see cref="System.Double"/> representation of <paramref name="label"/>.</param> /// <param name="value">The value.</param> /// <returns>The null-based index of the grid point in the curve, the grid points should be ordered with respect to the argument.</returns> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public int Add(double label, double argument, double value) { int index = m_GridPointArguments.BinarySearch(argument); if (index >= 0) { throw new ArgumentException(); } index = (~index); m_GridPointArguments.Insert(index, argument); m_GridPointValues.Insert(index, value); m_State = GridPointCurve.State.GridPointChanged; return index; }
/// <summary>Initializes a new instance of the <see cref="StandardGridPointCurveNoLabels"/> class. /// </summary> /// <param name="curveInterpolatorFactory">The curve interpolator factory.</param> /// <param name="curveInterpolator">The curve interpolator.</param> /// <param name="leftExtrapolatorFactory">The left extrapolator factory.</param> /// <param name="leftExtrapolator">The left extrapolator.</param> /// <param name="rightExtrapolatorFactory">The right extrapolator factory.</param> /// <param name="rightExtrapolator">The right extrapolator.</param> /// <param name="capacity">The number of elements that the new grid point curve can initially store.</param> internal StandardGridPointCurveNoLabels(GridPointCurve.Interpolator curveInterpolatorFactory, ICurveDataFitting curveInterpolator, GridPointCurve.Extrapolator leftExtrapolatorFactory, ICurveExtrapolator leftExtrapolator, GridPointCurve.Extrapolator rightExtrapolatorFactory, ICurveExtrapolator rightExtrapolator, int capacity = 20) { m_GridPointArguments = new List<double>(capacity); m_GridPointValues = new List<double>(capacity); m_CurveBuilder = curveInterpolator; m_LeftExtrapolator = leftExtrapolator; m_RightExtrapolator = rightExtrapolator; m_State = GridPointCurve.State.GridPointChanged; m_ReadOnlyGridPointValues = new ReadOnlyCollection<double>(m_GridPointValues); m_ReadOnlyGridPointArguments = new ReadOnlyCollection<double>(m_GridPointArguments); }
/// <summary>Gets a value at a specified point (<paramref name="columnIndex"/>, <paramref name="y"/>). /// </summary> /// <param name="columnIndex">The null-based column index of the point.</param> /// <param name="y">The y coordinate of the point.</param> /// <returns>The value of the surface at (<paramref name="columnIndex"/>, <paramref name="y"/>).</returns> public override double GetValue(int columnIndex, double y) { if (m_HorizontalExactFitToGridPoints == false) { if (m_VerticalLabelMapping == null) { return(GetValue(m_GridPointMatrix.HorizontalDoubleLabels[columnIndex], y)); } else { return(GetValue(m_GridPointMatrix.HorizontalDoubleLabels[m_VerticalLabelMapping[columnIndex]], y)); } } /* if the horizontal curve fitting meets the grid points, an evaluation of the horizontal curve fitting is not necessary. Here, we do not distinguish * between local and non-local interpolation approach and we take into account all values (!= NaN) along vertical direction: */ int numberOfRelevantRows = 0; for (int j = 0; j < m_GridPointMatrix.RowCount; j++) { double gridValue = m_GridPointMatrix[j, columnIndex]; if (Double.IsNaN(gridValue) == false) { m_TempValuesForVerticalEvaluation[numberOfRelevantRows] = gridValue; m_TempVerticalDoubleLabels[numberOfRelevantRows] = m_GridPointMatrix.VerticalDoubleLabels[j]; numberOfRelevantRows++; } } GridPointCurve.State verticalCurveState = GridPointCurve.State.GridPointChanged; if ((m_VerticalInterpolator.IsOperable == true) && (m_VerticalInterpolator.GridPointCount == m_GridPointMatrix.RowCount) && (numberOfRelevantRows == m_GridPointMatrix.RowCount)) { verticalCurveState = GridPointCurve.State.GridPointValueChanged; } m_VerticalInterpolator.Update(numberOfRelevantRows, m_TempVerticalDoubleLabels, m_TempValuesForVerticalEvaluation, verticalCurveState); if (y < m_VerticalInterpolator.LowerBound) { m_VerticalAboveExtrapolator.Update(); return(m_VerticalAboveExtrapolator.GetValue(y)); } else if (y > m_VerticalInterpolator.UpperBound) { m_VerticalBelowExtrapolator.Update(); return(m_VerticalBelowExtrapolator.GetValue(y)); } return(m_VerticalInterpolator.GetValue(y)); }
/// <summary>Initializes a new instance of the <see cref="StandardGridPointCurveNoLabels"/> class. /// </summary> /// <param name="curveParametrizationFactory">The curve parametrization factory.</param> /// <param name="curveParametrization">The curve parametrization.</param> /// <param name="capacity">The number of elements that the new grid point curve can initially store.</param> internal StandardGridPointCurveNoLabels(GridPointCurve.Parametrization curveParametrizationFactory, ICurveDataFitting curveParametrization, int capacity = 20) { m_GridPointArguments = new List<double>(capacity); m_GridPointValues = new List<double>(capacity); m_CurveBuilder = curveParametrization; // do not apply any truncation (extrapolation) approach: m_LeftExtrapolator = GridPointCurve.Extrapolator.None.First.Create(curveParametrization); m_RightExtrapolator = GridPointCurve.Extrapolator.None.Last.Create(curveParametrization); m_ReadOnlyGridPointValues = new ReadOnlyCollection<double>(m_GridPointValues); m_ReadOnlyGridPointArguments = new ReadOnlyCollection<double>(m_GridPointArguments); m_State = GridPointCurve.State.GridPointChanged; }
/// <summary>Gets a value at a specified point (<paramref name="columnIndex"/>, <paramref name="y"/>). /// </summary> /// <param name="columnIndex">The null-based column index of the point.</param> /// <param name="y">The y coordinate of the point.</param> /// <returns>The value of the surface at (<paramref name="columnIndex"/>, <paramref name="y"/>).</returns> public override double GetValue(int columnIndex, double y) { if (m_HorizontalExactFitToGridPoints == false) { if (m_VerticalLabelMapping == null) { return(GetValue(m_GridPointMatrix.HorizontalDoubleLabels[columnIndex], y)); } else { return(GetValue(m_GridPointMatrix.HorizontalDoubleLabels[m_VerticalLabelMapping[columnIndex]], y)); } } /* if the horizontal curve fitting meets the grid points, an evaluation of the horizontal curve fitting is not necessary. We take into account all values (!= NaN) along vertical direction: */ int numberOfRelevantRows = 0; for (int j = 0; j < m_GridPointMatrix.RowCount; j++) { double gridValue = m_GridPointMatrix[j, columnIndex]; if (Double.IsNaN(gridValue) == false) { m_TempValuesForVerticalEvaluation[numberOfRelevantRows] = gridValue; m_TempVerticalDoubleLabels[numberOfRelevantRows] = m_GridPointMatrix.VerticalDoubleLabels[j]; numberOfRelevantRows++; } } GridPointCurve.State verticalCurveState = GridPointCurve.State.GridPointChanged; if ((m_VerticalParametrization.IsOperable == true) && (m_VerticalParametrization.GridPointCount == m_GridPointMatrix.RowCount) && (numberOfRelevantRows == m_GridPointMatrix.RowCount)) { verticalCurveState = GridPointCurve.State.GridPointValueChanged; } m_VerticalParametrization.Update(numberOfRelevantRows, m_TempVerticalDoubleLabels, m_TempValuesForVerticalEvaluation, verticalCurveState); if ((y < m_VerticalParametrization.LowerBound) || (y > m_VerticalParametrization.UpperBound)) { throw new ArgumentOutOfRangeException(); } return(m_VerticalParametrization.GetValue(y)); }
/// <summary>Gets a value of the surface at a specified (x,y) coordinate. /// </summary> /// <param name="x">The x coordinate of the point.</param> /// <param name="y">The y coordinate of the point.</param> /// <returns>The value of the surface at (<paramref name="x"/>, <paramref name="y"/>).</returns> public override double GetValue(double x, double y) { int rowCount = m_VerticalDoubleLabels.Length; int k = 0; for (int j = 0; j < rowCount; j++) { m_TempValuesForVerticalEvaluation[k++] = m_CurvesAlongHorizontalDirection[j].GetValue(x); } GridPointCurve.State verticalCurveState = GridPointCurve.State.GridPointChanged; if ((m_VerticalParametrization.IsOperable == true) && (m_VerticalParametrization.GridPointCount == rowCount)) { verticalCurveState = GridPointCurve.State.GridPointValueChanged; } m_VerticalParametrization.Update(rowCount, m_VerticalDoubleLabels, m_TempValuesForVerticalEvaluation, verticalCurveState); if ((y < m_VerticalParametrization.LowerBound) || (y > m_VerticalParametrization.UpperBound)) { throw new ArgumentOutOfRangeException(); } return(m_VerticalParametrization.GetValue(y)); }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// <para>This method should always store all required data for later use, i.e. creates deep copies of the arguments.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { if (gridPointCount <= 0) { m_GridPointCount = 0; // current instance is not operable } else { m_GridPointCount = gridPointCount; int order = m_LeastSquaresRegressionFactory.Order; if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged)) { ArrayMemory.Reallocate(ref m_GridPointArguments, gridPointCount, Math.Max(10, gridPointCount / 5)); gridPointArguments.CopyTo(m_GridPointArguments, gridPointCount, gridPointArgumentStartIndex, sourceIncrement: gridPointArgumentIncrement); /* The optimal parameters (weights) are given by \beta = (A^t *A)^{-1} *A^t * y, where A is the design matrix and * y are the observations (=values of the grid points). For this, we compute the SVD of the design matrix 'A', i.e. * A = U*\Sigma*V^t, where U is a m-by-m, V is a n-by-n and \Sigma is a m-by-n matrix, where n = order +1 and m = number of grid points. It follows * \beta = (V * \Sigma^{-1} * U^t) * y. * */ DenseMatrix designMatrix = m_LeastSquaresRegressionFactory.BasisFunctions.GetDesignMatrix(m_GridPointArguments, gridPointCount, order); m_AdjustedReciprocalSingularValues = designMatrix.GetSingularValueDecomposition(out m_U, out m_Vt); // compute \Sigma^{-1} =\diag(s_1,...,s_n,0,....,0)^{-1}: double relThreshold = m_LeastSquaresRegressionFactory.RelativeSingularValueThreshold * m_AdjustedReciprocalSingularValues[0]; // the singular values are given in decresing order double absSingularValueThreshold = m_LeastSquaresRegressionFactory.AbsoluteSingularValueThreshold; for (int j = 0; j <= order; j++) { double singularValue = m_AdjustedReciprocalSingularValues[j]; if ((singularValue < absSingularValueThreshold) || (singularValue < relThreshold)) { m_AdjustedReciprocalSingularValues[j] = 0; } else { m_AdjustedReciprocalSingularValues[j] = 1.0 / singularValue; } } } if (state.HasFlag(GridPointCurve.State.GridPointValueChanged)) { ArrayMemory.Reallocate(ref m_GridPointValues, gridPointCount, Math.Max(10, gridPointCount / 5)); gridPointValues.CopyTo(m_GridPointValues, gridPointCount, gridPointValueStartIndex, sourceIncrement: gridPointValueIncrement); } /* one may compute b = U^t*b using BLAS, where 'b' are the grid point values, which gives a * vector of length #grid points. Afterwards, one divided the first (Order+1) elements with * the adjusted singular values and truncate the vector (only the first (Order+1) elements are needed) * for later use. * * Disadvantages: * * - b = U^t*b does no work with 'dgemv', but c = U^t*b + 0.0*c, where 'c' is some working * array of length #grid points. This is a #grid point x #grid point operation, * - the working array 'c' has #grid points elements, but we need the first (Order+1) elements only. * * example BLAS Code: * * m_WorkingArray = new double[values.Count]; * BLAS.Level2.dgemv(values.Count, values.Count, 1.0, m_U.m_Data, BLAS.MatrixTransposeState.Transpose, values, 0.0, m_WorkingArray); * for (int k = 0; k <= m_Order; k++){ * m_WorkingArray[k] *= m_AdjustedReciprocalSingularValues[k];} * */ for (int j = 0; j <= order; j++) // we do not use BLAS (see above), its a (order+1) * #grid point operation only { double value = 0.0; for (int k = 0; k < gridPointCount; k++) { value += m_U[k, j] * m_GridPointValues[k]; } m_WorkingArray[j] = value * m_AdjustedReciprocalSingularValues[j]; } // the multiplication of the (Order+1,Order+1)-matrix V and the 'working array' gives the coefficients: BLAS.Level2.dgemv(order + 1, order + 1, 1.0, m_Vt.Data, m_WorkingArray, 0.0, m_Coefficients, BLAS.MatrixTransposeState.Transpose); } }
/// <summary>Updates the current boundary condition. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double"/> representation.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments"/>.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/>, with respect to the previous function call.</param> /// <param name="gridPointArgumentsStartIndex">The null-based start index of <paramref name="gridPointArguments"/> to take into account.</param> /// <param name="gridPointValuesStartIndex">The null-based start index of <paramref name="gridPointValues"/> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments"/>.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues"/>.</param> /// <remarks>This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentsStartIndex = 0, int gridPointValuesStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { // nothing to do }
/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { double[] coefficientsB, coefficientsC, coefficientsD; m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out coefficientsB, out coefficientsC, out coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; // = t_{j+1} - t_j double nextDeltaT = m_SplineEvaluator.GridPointArguments[2] - m_SplineEvaluator.GridPointArguments[1]; // = t_{j+2} - t_{j+1} double b = ((m_SplineEvaluator.GridPointArguments[2] + m_SplineEvaluator.GridPointArguments[1] - 2 * m_SplineEvaluator.GridPointArguments[0]) * (m_SplineEvaluator.GridPointValues[1] - m_SplineEvaluator.GridPointValues[0]) / deltaT - deltaT * (m_SplineEvaluator.GridPointValues[2] - m_SplineEvaluator.GridPointValues[1]) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[2] - m_SplineEvaluator.GridPointArguments[0]); int k = 0; // k is the shortcut for j-1, i.e. k = j-1 double valueAtk = m_SplineEvaluator.GridPointValues[k]; for (int j = 1; j < gridPointCount - 1; j++) { double valueAtj = m_SplineEvaluator.GridPointValues[j]; nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; double nextB = (nextDeltaT * (valueAtj - valueAtk) / deltaT + deltaT * (m_SplineEvaluator.GridPointValues[j + 1] - valueAtj) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[k]); double m = (valueAtj - valueAtk) / deltaT; coefficientsB[k] = b; coefficientsC[k] = (3 * m - nextB - 2 * b) / deltaT; coefficientsD[k] = (nextB + b - 2 * m) / (deltaT * deltaT); b = nextB; deltaT = nextDeltaT; valueAtk = valueAtj; k++; } // Special case for the last coefficients: (k=n-1) int n = gridPointCount - 1; double b_n = -(nextDeltaT * (m_SplineEvaluator.GridPointValues[n - 1] - m_SplineEvaluator.GridPointValues[n - 2]) / deltaT - (2 * m_SplineEvaluator.GridPointArguments[n] - m_SplineEvaluator.GridPointArguments[n - 1] - m_SplineEvaluator.GridPointArguments[n - 2]) * (m_SplineEvaluator.GridPointValues[n] - m_SplineEvaluator.GridPointValues[n - 1]) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[n] - m_SplineEvaluator.GridPointArguments[n - 2]); double m_n = (m_SplineEvaluator.GridPointValues[n] - m_SplineEvaluator.GridPointValues[n - 1]) / nextDeltaT; coefficientsB[k] = b; coefficientsC[k] = (3 * m_n - b_n - 2 * b) / deltaT; coefficientsD[k] = (b_n + b - 2 * m_n) / (deltaT * deltaT); }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="gridPointArgumentHint">Describes the structure of the grid point arguments.</param> /// <param name="gridPointValueHint">Describes the structure of the grid point values.</param> /// <param name="gridPointValueTransformation">A transformation to apply to the grid point values, i.e. number of grid points and grid point values (mainly used for log-linear interpolation). /// Caution: The application of a transformation has an impact on <see cref="Interpolator.GridPointValues"/>.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// <para>This method should always store all required data for later use, i.e. creates deep copies of the arguments.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, MklGridPointCurve.xHintValue gridPointArgumentHint, MklGridPointCurve.yHintValue gridPointValueHint, Action <int, double[]> gridPointValueTransformation, GridPointCurve.State state = GridPointCurve.State.GridPointChanged, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { if (gridPointCount <= 0) { m_GridPointCount = 0; // i.e. current instance is not operable } else { m_GridPointCount = gridPointCount; bool isInitializedBefore = m_Task != IntPtr.Zero; if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointArguments, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointArguments = new ReadOnlyCollection <double>(m_GridPointArguments); if (isInitializedBefore == true) { CheckErrorCode(_dfdEditPtr(m_Task, PtrParameterChangeType.DF_X, m_GridPointArguments), "dfdEditPtr"); } } gridPointArguments.CopyTo(m_GridPointArguments, gridPointCount, gridPointArgumentStartIndex, sourceIncrement: gridPointArgumentIncrement); if ((ArrayMemory.Reallocate(ref m_SplineCoefficients, (int)m_MklDataFitting.m_SplineOrder * gridPointCount, Math.Max(10, gridPointCount / 5)) == true) && (isInitializedBefore == true)) { CheckErrorCode(_dfdEditPtr(m_Task, PtrParameterChangeType.DF_PP_SCOEFF, m_SplineCoefficients), "dfdEditPtr"); } if (isInitializedBefore == true) { CheckErrorCode(_dfiEditVal(m_Task, IntParameterChangeType.DF_XHINT, (int)gridPointArgumentHint), "dfiEditVal"); } } if (state.HasFlag(GridPointCurve.State.GridPointValueChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointValues, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointValues = new ReadOnlyCollection <double>(m_GridPointValues); if (isInitializedBefore == true) { CheckErrorCode(_dfdEditPtr(m_Task, PtrParameterChangeType.DF_Y, m_GridPointValues), "dfdEditPtr"); } } gridPointValues.CopyTo(m_GridPointValues, gridPointCount, gridPointValueStartIndex, sourceIncrement: gridPointValueIncrement); gridPointValueTransformation(gridPointCount, m_GridPointValues); // mainly used for log-linear transformation, i.e. apply logarithm to each grid point value. Caution: The public properties shows transformed values as well! if (isInitializedBefore == true) { CheckErrorCode(_dfiEditVal(m_Task, IntParameterChangeType.DF_NX, gridPointCount), "dfiEditVal"); CheckErrorCode(_dfiEditVal(m_Task, IntParameterChangeType.DF_YHINT, (int)gridPointValueHint), "dfiEditVal"); } else { CheckErrorCode(_dfdNewTask1D(out m_Task, gridPointCount, m_GridPointArguments, gridPointArgumentHint, 1, m_GridPointValues, gridPointValueHint), "dfdNewTask1D"); } } if (state != GridPointCurve.State.NoChangeSinceLastUpdate) { CheckErrorCode(_dfdEditPPSpline1D(m_Task, m_MklDataFitting.m_SplineOrder, m_MklDataFitting.m_SplineType, m_MklDataFitting.m_BoundaryConditionType, m_MklDataFitting.m_BoundaryCondition, m_MklDataFitting.m_InternalConditionTypes, m_MklDataFitting.m_InternalConditions, m_SplineCoefficients, m_MklDataFitting.m_SplineCoefficientHint), "dfdEditPPSpline1D"); if (m_MklDataFitting.m_SplineOrder != MklCurveInterpolationSpline.SplineOrder.DF_PP_STD) // for a 'real' spline interpolation, one has to calculate the spline coefficients { CheckErrorCode(_dfdConstruct1D(m_Task, MklCurveInterpolationSpline.SplineFormat.DF_PP_SPLINE, MklCurveInterpolationSpline.SplineConstructionMethod.DF_METHOD_STD), "dfdConstruct1D"); } } } }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="gridPointArgumentHint">Describes the structure of the grid point arguments.</param> /// <param name="gridPointValueHint">Describes the structure of the grid point values.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// <para>This method should always store all required data for later use, i.e. creates deep copies of the arguments.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, MklGridPointCurve.xHintValue gridPointArgumentHint, MklGridPointCurve.yHintValue gridPointValueHint, GridPointCurve.State state = GridPointCurve.State.GridPointChanged, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { Update(gridPointCount, gridPointArguments, gridPointValues, gridPointArgumentHint, gridPointValueHint, (n, v) => { }, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); }
/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { Update(gridPointCount, gridPointArguments, gridPointValues, MklGridPointCurve.xHintValue.DF_NO_HINT, MklGridPointCurve.yHintValue.DF_NO_HINT, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); }
/// <summary>Updates the current boundary condition. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged)) { m_FirstXDelta = gridPointArguments[gridPointArgumentStartIndex + 1] - gridPointArguments[gridPointArgumentStartIndex]; m_LastXDelta = gridPointArguments[gridPointArgumentStartIndex + gridPointArgumentIncrement * (gridPointCount - 1)] - gridPointArguments[gridPointArgumentStartIndex + gridPointArgumentIncrement * (gridPointCount - 2)]; } m_FirstYDelta = gridPointValues[gridPointValueStartIndex + 1] - gridPointValues[gridPointValueStartIndex]; m_LastYDelta = gridPointValues[gridPointValueStartIndex + gridPointValueIncrement * (gridPointCount - 1)] - gridPointValues[gridPointValueStartIndex + gridPointValueIncrement * (gridPointCount - 2)]; }
/// <summary>Updates the current boundary condition. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double"/> representation.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments"/>.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/>, with respect to the previous function call.</param> /// <param name="gridPointArgumentsStartIndex">The null-based start index of <paramref name="gridPointArguments"/> to take into account.</param> /// <param name="gridPointValuesStartIndex">The null-based start index of <paramref name="gridPointValues"/> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments"/>.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues"/>.</param> /// <remarks>This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentsStartIndex = 0, int gridPointValuesStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { if (gridPointCount < 2) { m_FirstBoundaryCoefficient = m_LastBoundaryCoefficient = Double.NaN; } else { double deltaT = gridPointArguments[gridPointArgumentsStartIndex + gridPointArgumentIncrement] - gridPointArguments[gridPointArgumentsStartIndex]; // = t_{j+1} - t_j double nextDeltaT = gridPointArguments[gridPointArgumentsStartIndex + 2 * gridPointArgumentIncrement] - gridPointArguments[gridPointArgumentsStartIndex + gridPointArgumentIncrement]; // = t_{j+2} - t_{j+1} double valueAt1 = gridPointValues[gridPointValuesStartIndex + gridPointValueIncrement]; double m = (valueAt1 - gridPointValues[gridPointValuesStartIndex]) / deltaT; m_FirstBoundaryCoefficient = ((deltaT + deltaT + nextDeltaT) * m - deltaT * (gridPointValues[gridPointValuesStartIndex + 2 * gridPointValueIncrement] - valueAt1) / nextDeltaT) / (deltaT + nextDeltaT); int lastGridPointArgumentIndex = gridPointArgumentsStartIndex + gridPointArgumentIncrement * (gridPointCount - 1); int lastGridPointValueIndex = gridPointValuesStartIndex + gridPointValueIncrement * (gridPointCount - 1); double lastButOneDeltaT = gridPointArguments[lastGridPointArgumentIndex - 2 * gridPointArgumentIncrement] - gridPointArguments[lastGridPointArgumentIndex - gridPointArgumentIncrement]; double lastButOne_m = (gridPointValues[lastGridPointValueIndex - 2 * gridPointValueIncrement] - gridPointValues[lastGridPointValueIndex - gridPointValueIncrement]) / lastButOneDeltaT; double lastDeltaT = gridPointArguments[lastGridPointArgumentIndex - gridPointArgumentIncrement] - gridPointArguments[lastGridPointArgumentIndex]; double last_m = (gridPointValues[lastGridPointValueIndex - gridPointValueIncrement] - gridPointValues[lastGridPointValueIndex]) / lastDeltaT; m_LastBoundaryCoefficient = ((2.0 * lastDeltaT + lastButOneDeltaT) * last_m - lastDeltaT * last_m) / (lastButOneDeltaT + lastDeltaT); } }
/// <summary>Changes the value component of a specific grid point. /// </summary> /// <param name="gridPointIndex">The null-based index of the grid point.</param> /// <param name="value">The value.</param> /// <remarks>This method set the <see cref="IOperable.IsOperable"/> flag to <c>false</c>.</remarks> /// <exception cref="InvalidOperationException">Thrown, if <see cref="IGridPointCurve.IsReadOnly"/> is <c>true</c>.</exception> public void SetValue(int gridPointIndex, double value) { m_GridPointValues[gridPointIndex] = value; m_State |= GridPointCurve.State.GridPointValueChanged; }
/// <summary>Gets a value of the surface at a specified (x,y) coordinate. /// </summary> /// <param name="x">The x coordinate of the point.</param> /// <param name="y">The y coordinate of the point.</param> /// <returns>The value of the surface at (<paramref name="x"/>, <paramref name="y"/>).</returns> public override double GetValue(double x, double y) { int rowCount = m_VerticalDoubleLabels.Length; int firstRowIndex = 0; int lastRowIndex = rowCount - 1; int relevantRowCount = rowCount; /* if the interpolation along vertical direction is a local approach a few function evaluations are needed only: */ if (m_VerticalInterpolatorFactory.IsLocalApproach == true) { if (y < m_VerticalDoubleLabels[0]) // above the grid points { lastRowIndex = Math.Min(rowCount - 1, m_VerticalAboveExtrapolatorFactory.GetLevelOfGridPointDependency(rowCount)); } else if (y > m_VerticalDoubleLabels[rowCount - 1]) // below the grid points { firstRowIndex = Math.Max(0, rowCount - m_VerticalBelowExtrapolatorFactory.GetLevelOfGridPointDependency(rowCount) - 1); } else // inside the grid points { int nonLastLeftGridPointIndex = GridPointCurve.Utilities.GetNonLastNearestIndex(y, m_VerticalDoubleLabels, m_VerticalDoubleLabels.Length); int upperLocalnessLevel = m_VerticalInterpolatorFactory.GetLeftLocalnessLevel(nonLastLeftGridPointIndex, rowCount); int lowerLocalnessLevel = m_VerticalInterpolatorFactory.GetRightLocalnessLevel(nonLastLeftGridPointIndex, rowCount); firstRowIndex = Math.Max(nonLastLeftGridPointIndex - upperLocalnessLevel, 0); lastRowIndex = Math.Min(nonLastLeftGridPointIndex + lowerLocalnessLevel, rowCount - 1); } relevantRowCount = lastRowIndex - firstRowIndex + 1; /* perhaps one may take into account less rows than required for the interpolation, i.e. one has to adjust the first/last row index: */ if (relevantRowCount < m_VerticalInterpolatorFactory.MinimalRequiredNumberOfGridPoints) { int numberOfAdditionalRequiredRows = m_VerticalInterpolatorFactory.MinimalRequiredNumberOfGridPoints - relevantRowCount; firstRowIndex = Math.Max(0, firstRowIndex - numberOfAdditionalRequiredRows); lastRowIndex = Math.Min(rowCount - 1, lastRowIndex + numberOfAdditionalRequiredRows); relevantRowCount = lastRowIndex - firstRowIndex + 1; } } /* compute values w.r.t. to the x-coordinate and each relevant row, i.e. store values to take into account for vertical * interpolation. In the case of a non-local approach, one may improve performance by indicating that the labels will not be changed: */ int k = 0; for (int j = firstRowIndex; j <= lastRowIndex; j++) { m_TempValuesForVerticalEvaluation[k++] = m_CurvesAlongHorizontalDirection[j].GetValue(x); } GridPointCurve.State verticalCurveState = GridPointCurve.State.GridPointChanged; if ((m_VerticalInterpolatorFactory.IsLocalApproach == false) && (m_VerticalInterpolator.IsOperable == true) && (m_VerticalInterpolator.GridPointCount == rowCount)) { verticalCurveState = GridPointCurve.State.GridPointValueChanged; } m_VerticalInterpolator.Update(relevantRowCount, m_VerticalDoubleLabels, m_TempValuesForVerticalEvaluation, verticalCurveState, gridPointArgumentStartIndex: firstRowIndex); if (y < m_VerticalInterpolator.LowerBound) { m_VerticalAboveExtrapolator.Update(); return(m_VerticalAboveExtrapolator.GetValue(y)); } else if (y > m_VerticalInterpolator.UpperBound) { m_VerticalBelowExtrapolator.Update(); return(m_VerticalBelowExtrapolator.GetValue(y)); } return(m_VerticalInterpolator.GetValue(y)); }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of gridPointArguments and gridPointValues to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double"/> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to gridPointArguments.</param> /// <param name="state">The state of the grid points, i.e. gridPointArguments and gridPointValues, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of gridPointArguments to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of gridPointValues to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments"/>.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues"/>.</param> /// <remarks>This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable"/> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state = GridPointCurve.State.GridPointChanged, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { int n = gridPointCount - 1; if (n >= 3) { m_BoundaryCondition.Update(gridPointCount, gridPointArguments, gridPointValues, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out double[] coefficientsB, out double[] coefficientsC, out double[] coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double b = m_BoundaryCondition.GetFirstBoundaryCoefficient(); int gridPointValueIndex = gridPointValueStartIndex; int gridPointArgumentIndex = gridPointArgumentStartIndex; double deltaT = m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex + gridPointArgumentIncrement] - m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex]; // = t_{j+1} - t_j double nextDeltaT; // = t_{j+2} - t_{j+1} double m = (m_SplineEvaluator.GridPointValues[gridPointValueIndex + gridPointValueIncrement] - m_SplineEvaluator.GridPointValues[gridPointValueIndex]) / deltaT; int k = 0; // k is just the shortcut for j-1, i.e. k = j-1 double next_m = 0.0; // assiment is needed for the compiler only. for (int j = 1; j < n; j++) { gridPointValueIndex += gridPointValueIncrement; gridPointArgumentIndex += gridPointArgumentIncrement; nextDeltaT = m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex + gridPointArgumentIncrement] - m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex]; next_m = (m_SplineEvaluator.GridPointValues[gridPointValueIndex + gridPointValueIncrement] - m_SplineEvaluator.GridPointValues[gridPointValueIndex]) / nextDeltaT; double nextB = 0.0; if (m * next_m > 0.0) // locally monotone { double max = Math.Max(m, next_m); double min = Math.Min(m, next_m); nextB = 3.0 * m * next_m / (max + min + min); if (min > 0.0) // locally increasing { nextB = Math.Min(Math.Max(0.0, nextB), 3.0 * min); } else if (max < 0.0) { nextB = Math.Max(Math.Min(0.0, nextB), 3.0 * max); } } coefficientsB[k] = b; coefficientsC[k] = (3.0 * m - nextB - b - b) / deltaT; coefficientsD[k] = (nextB + b - m - m) / (deltaT * deltaT); b = nextB; deltaT = nextDeltaT; m = next_m; k++; } // Special case for the last coefficients, i.e. 'b_n': b = m_BoundaryCondition.GetLastBoundaryCoefficient(); coefficientsB[k] = b; coefficientsC[k] = (3.0 * next_m - b - b) / deltaT; coefficientsD[k] = (b - next_m - next_m) / (deltaT * deltaT); } }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="gridPointArgumentHint">Describes the structure of the grid point arguments.</param> /// <param name="gridPointValueHint">Describes the structure of the grid point values.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// <para>This method should always store all required data for later use, i.e. creates deep copies of the arguments.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, MklGridPointCurve.xHintValue gridPointArgumentHint, MklGridPointCurve.yHintValue gridPointValueHint, GridPointCurve.State state = GridPointCurve.State.GridPointChanged, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { /* lets store a copy of the original grid point values: */ if (state.HasFlag(GridPointCurve.State.GridPointValueChanged)) { if (ArrayMemory.Reallocate(ref m_OriginalGridPointValues, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_OriginalGridPointValuesReadOnlyCollection = new ReadOnlyCollection <double>(m_OriginalGridPointValues); } gridPointValues.CopyTo(m_OriginalGridPointValues, gridPointCount, gridPointValueStartIndex, sourceIncrement: gridPointValueIncrement); } m_DataFitting.Update(gridPointCount, gridPointArguments, gridPointValues, gridPointArgumentHint, gridPointValueHint, (n, x) => { VectorUnit.Basics.Log(n, x); }, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); }
public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { throw new NotImplementedException(); }
/// <summary>Updates the current instance, i.e. stores the grid points and returns references to the coefficients of the splines. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double"/> representation.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments"/>.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments"/> and <paramref name="gridPointValues"/>, with respect to the previous function call.</param> /// <param name="coefficientsB">A reference to the coefficients 'b' with respect to f(t) = a[j] + b[j]*(t[j] - t) + c[j] * (t[j] - t)^2 + d[j] * (t[j] - t)^3. The caller of this method has to set valid coefficients (output).</param> /// <param name="coefficientsC">A reference to the coefficients 'c' with respect to f(t) = a[j] + b[j]*(t[j] - t) + c[j] * (t[j] - t)^2 + d[j] * (t[j] - t)^3. The caller of this method has to set valid coefficients (output).</param> /// <param name="coefficientsD">A reference to the coefficients 'd' with respect to f(t) = a[j] + b[j]*(t[j] - t) + c[j] * (t[j] - t)^2 + d[j] * (t[j] - t)^3. The caller of this method has to set valid coefficients (output).</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, out double[] coefficientsB, out double[] coefficientsC, out double[] coefficientsD, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { m_GridPointCount = gridPointCount; if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointArguments, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointArguments = new ReadOnlyCollection <double>(m_GridPointArguments); } gridPointArguments.CopyTo(m_GridPointArguments, gridPointCount, gridPointArgumentStartIndex, sourceIncrement: gridPointArgumentIncrement); } if (state.HasFlag(GridPointCurve.State.GridPointValueChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointValues, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointValues = new ReadOnlyCollection <double>(m_GridPointValues); } gridPointValues.CopyTo(m_GridPointValues, gridPointCount, gridPointValueStartIndex, sourceIncrement: gridPointValueIncrement); } /* allocate memory for spline coefficients if necessary and add a small buffer to avoid reallocation of memory: */ ArrayMemory.Reallocate(ref m_CoefficientsB, gridPointCount - 1, Math.Max(10, gridPointCount / 5)); coefficientsB = m_CoefficientsB; ArrayMemory.Reallocate(ref m_CoefficientsC, gridPointCount - 1, Math.Max(10, gridPointCount / 5)); coefficientsC = m_CoefficientsC; ArrayMemory.Reallocate(ref m_CoefficientsD, gridPointCount - 1, Math.Max(10, gridPointCount / 5)); coefficientsD = m_CoefficientsD; IntegralCacheUpdateRequested = true; }
/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { if (gridPointCount <= 0) { m_GridPointCount = 0; // current instance is not operable } else { m_GridPointCount = gridPointCount; if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointArguments, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointArguments = new ReadOnlyCollection <double>(m_GridPointArguments); } gridPointArguments.CopyTo(m_GridPointArguments, gridPointCount, gridPointArgumentStartIndex, sourceIncrement: gridPointArgumentIncrement); } if (state.HasFlag(GridPointCurve.State.GridPointValueChanged)) { if (ArrayMemory.Reallocate(ref m_GridPointValues, gridPointCount, Math.Max(10, gridPointCount / 5)) == true) { m_ReadOnlyGridPointValues = new ReadOnlyCollection <double>(m_GridPointValues); } gridPointValues.CopyTo(m_GridPointValues, gridPointCount, gridPointValueStartIndex, sourceIncrement: gridPointValueIncrement); } } m_IntegralCache.EarmarkUpdateRequest(); }
/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { m_BoundaryCondition.Update(gridPointCount, gridPointArguments, gridPointValues, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double[] coefficientsB, coefficientsC, coefficientsD; m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out coefficientsB, out coefficientsC, out coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); int n = gridPointCount; int nMinusOne = n - 1; double deltaT; // LU decomposition is necessary if and only if the labels have been changed, too: if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged) == true) { ArrayMemory.Reallocate(ref m_DiagonalElements, n, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SubDiagonalElements, nMinusOne, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SuperDiagonalElements, nMinusOne, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SecondSuperDiagonalElements, nMinusOne - 1, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_PivotIndices, n, Math.Max(10, n / 5)); deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; for (int j = 1; j < nMinusOne; j++) { double nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; m_SubDiagonalElements[j - 1] = deltaT; m_DiagonalElements[j] = 2.0 * (deltaT + nextDeltaT); m_SuperDiagonalElements[j] = nextDeltaT; deltaT = nextDeltaT; } m_BoundaryCondition.GetRemainingMatrixElements(out m_DiagonalElements[0], out m_SuperDiagonalElements[0], out m_SubDiagonalElements[n - 2], out m_DiagonalElements[nMinusOne]); LAPACK.LinearEquations.MatrixFactorization.dgttrf(n, m_SubDiagonalElements, m_DiagonalElements, m_SuperDiagonalElements, m_SecondSuperDiagonalElements, m_PivotIndices); } /* Compute the right hand side of Ax=b, where A is the tri-diagonal matrix already calculated and * b depends on the second derivatives and the boundary condition only. We store the value of b in *coefficientsC*: */ deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; for (int j = 1; j < nMinusOne; j++) { double nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; coefficientsC[j] = 3.0 * ((m_SplineEvaluator.GridPointValues[j + 1] - m_SplineEvaluator.GridPointValues[j]) / nextDeltaT - (m_SplineEvaluator.GridPointValues[j] - m_SplineEvaluator.GridPointValues[j - 1]) / deltaT); deltaT = nextDeltaT; } m_BoundaryCondition.GetRemainingRightHandSideElements(out coefficientsC[0], out coefficientsC[nMinusOne]); /* Calculate the solution x of Ax=b. The solution is the coefficient 'c' and 'dttrs' stores the result in 'coefficientsC': */ LAPACK.LinearEquations.Solver.dgttrs(n, m_SubDiagonalElements, m_DiagonalElements, m_SuperDiagonalElements, m_SecondSuperDiagonalElements, m_PivotIndices, coefficientsC, 1); /* Calculate the coefficients b_j and d_j: */ for (int k = 0; k < nMinusOne; k++) { deltaT = m_SplineEvaluator.GridPointArguments[k + 1] - m_SplineEvaluator.GridPointArguments[k]; coefficientsD[k] = (coefficientsC[k + 1] - coefficientsC[k]) / (3.0 * deltaT); coefficientsB[k] = (m_SplineEvaluator.GridPointValues[k + 1] - m_SplineEvaluator.GridPointValues[k]) / deltaT - deltaT * (2 * coefficientsC[k] + coefficientsC[k + 1]) / 3.0; } }