Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
spline_functions.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file src/numeric/interpolation/spline_functions.cc
11 /// @brief Interpolation with cubic splines
12 /// @author Will Sheffler
13 
14 
16 
17 namespace numeric {
18 namespace interpolation {
19 namespace spline {
20 
21 
22 //Given arrays x[1..n] and y[1..n] containing a tabulated function,
23 //i.e., y i = f(xi),with x1 < x2 <...<xN , and given values yp1 and
24 //ypn for the first derivative of the interpolating function at
25 //points 1 and n, respectively, this routine returns an array y2[1..n]
26 //that contains the second derivatives of the interpolating function
27 //at the tabulated points xi.Ifyp1 and/or ypn are equal to 1 10 30
28 //or larger, the routine is signaled to set the corresponding
29 //boundary condition for a natural spline, with zero second
30 //derivative on that boundary.
33  utility::vector1<Real> const & x,
34  utility::vector1<Real> const & y,
35  Real yp1,
36  Real ypn
37 )
38 {
39 
40  Real qn,un;
41 
42  // using namespace std;
43  // cerr << "spline second derivative 1 yp1 " << yp1 << " ypn " << ypn<< endl;
44  // cerr << " x:" ;
45  // for(int ii=1; ii<=(int)x.size();ii++)
46  // cerr << ' ' << x[ii] ;
47  // cerr << endl;
48  // cerr << " y:" ;
49  // for(int ii=1; ii<=(int)y.size();ii++)
50  // cerr << ' ' << y[ii] ;
51  // cerr << endl;
52  // std::cerr << "starting spline_second_derivative" << std::endl;
53 
54  int n = x.size();
57 
58  // cout << "spline second derivative 2 "<< n << endl;
59  //The lower boundary condition is set either to be nat-ural y2[1]=u[1]=0.0;
60  if ( yp1 > 0.99e30 ) {
61  //or else to have a specified first derivative.
62  y2[1] = u[1]=0.0;
63  } else {
64  y2[1] = -0.5;
65  u[1]=(3.0/(x[2]-x[1]))*((y[2]-y[1])/(x[2]-x[1])-yp1);
66  }
67  // cout << "spline second derivative 3 " << u[1] << endl;
68  //This is the decomposition loop of the tridiagonal al-gorithm.
69  //y2 and u are used for tem-porary storage of the decomposed factors.
70 
71  for ( int i=2; i<=n-1; i++ ) {
72  Real sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]);
73  Real p=sig*y2[i-1]+2.0;
74  y2[i]=(sig-1.0)/p;
75  u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]);
76  u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p;
77  // cout << i << ' ' << y2[i] << ' ' << u[i] << endl;
78  }
79  // cout << "spline second derivative 4 "<< endl;
80  //The upper boundary condition is set either to be natural qn=un=0.0;
81  if ( ypn > 0.99e30 ) {
82  qn = un = 0.0;
83  } else { //or else to have a specified first derivative.
84  qn=0.5;
85  un=(3.0/(x[n]-x[n-1]))*(ypn-(y[n]-y[n-1])/(x[n]-x[n-1]));
86  }
87  // cout << "spline second derivative 5 "<< endl;
88  //This is the backsubstitution loop of the tridiagonal algorithm
89  y2[n]=(un-qn*u[n-1])/(qn*y2[n-1]+1.0);
90  // cout << "spline second derivative 6 "<< endl;
91  for ( int k=n-1; k>=1; k-- ) {
92  // cout << k << ' ' << y2[k] << ' ' << u[k] << endl;
93  y2[k]=y2[k]*y2[k+1]+u[k];
94  }
95  // cout << "spline second derivative 7 "<< endl;
96  return y2;
97 }
98 
99 // !!!!!!!!!! THIS COULD BE MADE MUCH FASTER IF XA ARE IN ORDER
100 // AND IT WAS MODIFIED NOT TO LOOK UP "BIN"
101 //Given the arrays xa[1..n] and ya[1..n], which tabulate a function
102 //(with the xai s in order), and given the array y2a[1..n], which
103 //is the output from spline above, and given a value of x, this
104 //routine returns a cubic-spline interpolated value y.
106  utility::vector1<Real> const & xa,
107  utility::vector1<Real> const & ya,
108  utility::vector1<Real> const & y2a,
109  Real x, Real & y, Real & dy
110 )
111 {
112  int klo,khi;
113  Real h,b,a;
114 
115  //We will find the right place in the table by means of bisection.
116  //This is optimal if sequential calls to this routine are at
117  //random values of x. If sequential calls are in order, and
118  //closely spaced, one would do better to store previous values
119  //of klo and khi and test if they remain appropriate on the next call.
120  int n = xa.size();
121  klo=1;
122  khi=n;
123  while ( khi-klo > 1 ) {
124  int k=(khi+klo) >> 1;
125  if ( xa[k] > x ) {
126  khi=k;
127  } else {
128  klo=k;
129  }
130  }
131  //klo and khi now bracket the input value of x.
132  h=xa[khi]-xa[klo];
133  // if (h == 0.0)
134  // cout << "spline interpolate: Bad xa input to routine splint" << endl;
135  //The xa s must be dis-tinct.
136  a=(xa[khi]-x)/h;
137  b=(x-xa[klo])/h;
138  //Cubic spline polynomial is now evaluated.
139  y = a*ya[klo]+b*ya[khi] + ( (a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi] ) *(h*h)/6.0;
140  dy = (ya[khi]-ya[klo])/h + ( (3*b*b-1)*y2a[khi] - (3*a*a-1)*y2a[klo] ) * h /6.0;
141 }
142 
143 } // end namespace spline
144 } // end namespace interpolation
145 } // end namespace numeric
def x
utility::vector1< Real > spline_second_derivative(utility::vector1< Real > const &x, utility::vector1< Real > const &y, Real yp1, Real ypn)
tuple p
Definition: docking.py:9
double Real
Definition: types.hh:39
void spline_interpolate(utility::vector1< Real > const &xa, utility::vector1< Real > const &ya, utility::vector1< Real > const &y2a, Real x, Real &y, Real &dy)
def y