Beispiel #1
0
            /// <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;
                }
            }
            /// <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);
            }
Beispiel #3
0
            /// <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);
                }
            }