Ejemplo n.º 1
0
bool CubicSpline::SetSpline( VectorView& X, VectorView& Y, bool logX, bool logY )
{
    int i,k;
    double p,sig;

    // determine element count
    N_ = X.size();

    // test that X and Y same size
    if( N_ < 2 || N_ > 100 ||  N_ != Y.size() )
        goto initFailed;

    // dimension structures for N elements
    X_.resize( N_ );
    Y_.resize( N_ );
    Y2_.resize( N_ );

    // put values into local X_ and Y_ vectors

    if( X[N_-1] < X[0] )
    {
        // Case 1: X_ values descending
        X_ = X.reverse();
        Y_ = Y.reverse();
    }
    else
    {
        // Caes 2: X_ values ascending
        X_ = X;
        Y_ = Y;
    }

    // convert X axis to its log if required
    
    if( logX )
    {
        logX_ = true;
        if( !X_.setLog() )
            goto initFailed;
    }

    // convert Y axis to its log if required

    if( logY )
    {
        logY_ = true;
        if( !Y_.setLog() )
            goto initFailed;
    }

    // use natural spline at boundaries

    Y2_[0]    = u[0]    = 0;
    Y2_[N_-1] = u[N_-1] = 0;

    // decomposition loop - tri-diagonal algorithm

    for( i=1; i<(N_-1); i++ )
    {
        sig    = ( X_[i] - X_[i-1] ) / ( X_[i+1] - X_[i-1] );

        p      = sig * Y2_[i-1] + 2.0;

        Y2_[i] = ( sig - 1.0 ) / p;

        u[i]   = ( Y_[i+1] - Y_[i] ) / ( X_[i+1] - X_[i] )
               - ( Y_[i] - Y_[i-1] ) / ( X_[i] - X_[i-1] );

        u[i]   = ( ( 6.0 * u[i] ) / ( X_[i+1] - X_[i-1] ) - sig * u[i-1] ) / p;
    }

    // backsubstitition loop - tri-diagonal algorithm

    for( k = N_-2; k >= 0; k -- )
    {
        Y2_[k] = Y2_[k] * Y2_[k+1] + u[k];
    }

    // SetSpline succeeded
    return true;

initFailed:

    // Set empty state
    SetEmpty( );

    // SetSpline failed
    return false;
}
Ejemplo n.º 2
0
double RioTintoTS::SPNV3
(
    int         N,
    VectorView  X,
    VectorView  Y,
    VectorView& S,
    double      XX
)
{
	double XIXI1 = 0.0;
	double DX    = 0.0;
	double XXI   = 0.0;
	double YY    = 0.0;
	double T     = 0.0;

    // Reverse vectors if X descending order

    if( X[N-1] < X[0] )
    {
        X.reset( X.reverse() );
        Y.reset( Y.reverse() );
    }

	// Find interval containing XX

	if( XX < X[0] )
	{
		// before X[0]

		XIXI1 = X[0] - X[1];
		DX    = (Y[0]-Y[1])/(XIXI1+1e-30) + XIXI1*(S[1]+2*S[0])/6.0;
		XXI   = XX - X[0];

		YY = Y[0] + XXI * ( DX + XXI*S[0] );
	}
	else if( XX > X[N-1] )
	{
		// after X[N-1]

		XIXI1 = X[N-1] - X[N-2];
		DX    = (Y[N-1]-Y[N-2])/(XIXI1+1e-30) + XIXI1*(2*S[N-1]+S[N-2])/6.0;
		XXI	 = XX - X[N-1];

		YY = Y[N-1] + XXI * ( DX + XXI*S[N-1] );
	}
	else
	{
		int i     = 0;
		int left  = 0;
		int right = N-1;
		int mid   = 0;

		while( XX>=X[left] && XX<=X[right] )
		{
			mid = left + (right-left)/2;

			if( mid==left )
			{
				i = left;
				break;
			}
			else if( XX < X[mid] )
			{
				right = mid;
			}
			else
			{
				left = mid;
			}
		}

		// between X[i] and X[i+1]

        double x1 = X[i];
        double x2 = X[i+1];
        double y1 = Y[i];
        double y2 = Y[i+1];


		XXI   = XX   - X[i];
		XIXI1 = X[i] - X[i+1];
		T     = 2.0*S[i] + XXI*(S[i]-S[i+1])/(XIXI1+1e-30) + S[i+1];

		YY = Y[i] + XXI*(Y[i]-Y[i+1])/(XIXI1+1e-30) + (XX-X[i+1])*T/6.0;
	}

	return YY;
}
Ejemplo n.º 3
0
void RioTintoTS::SPN3( int N, VectorView X, VectorView Y, VectorView& S )
{
	double DI;
	double AI;
	double AI1;
	double CI;
	double PI;
	double PI1;
	double Z;

	int	   i;
	int    j;
	int    NM1;

	static double C[100];

	if( N>2 && N<100 )
	{
        // Reverse vectors if X descending order
        if( X[N-1] < X[0] )
        {
            X.reset( X.reverse() );
            Y.reset( Y.reverse() );
        }

		// End points

		NM1    = N-1;
		S[0]   = 0;
		S[NM1] = 0;

		// Initial values

		DI = 0.0;
		AI = X[1] - X[0];
		CI = -AI * S[0];
		PI = ( Y[1] - Y[0] ) / ( AI + 1e-30 );

		// Form equations and reduce to triangular form

		for( i=1; i<NM1; i++ )
		{
			// Segment width
			AI1 = X[i+1] - X[i];
			
			// Diagonal elements
			Z = 2.0 * (AI1+AI) - DI;

			// Constant term
			PI1  = ( Y[i+1] - Y[i] ) / ( AI1 + 1e-30 );
			C[i] = ( 6.0*(PI1-PI) - CI ) / ( Z + 1e-30 );
			CI   = C[i] * AI1;

			// Upper daigonal
			S[i] = AI1 / ( Z + 1e-30 );
			DI   = S[i] * AI1;
			AI   = AI1;
		}

		// Back substitute

		for( j=(NM1-1); j>0; j-- )
		{
			S[j] = C[j] - S[j]*S[j+1];
		}
	}
}