VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
spline_cubic.f
Go to the documentation of this file.
1
2 subroutine spline_cubic(x,y,xx,yy,n,iflag)
3 USE stel_kinds
4 implicit none
5!----------------------------------------------------------------------
6! iflag = 0 normal return
7! iflag =-1 x-request outside of bounds
8! iflag =-2 xx arrays with two equal entries or not in correct order
9!----------------------------------------------------------------------
10!-----------------------------------------------
11! D u m m y A r g u m e n t s
12!-----------------------------------------------
13 integer, intent(in) :: n
14 integer, intent(inout) :: iflag
15 real(rprec), intent(in) :: x
16 real(rprec), dimension(n), intent(in) :: xx,yy
17!-----------------------------------------------
18! L o c a l V a r i a b l e s
19!-----------------------------------------------
20 real(rprec), intent(out) :: y
21 real(rprec), dimension(n) :: y2, dxx
22 real(rprec) :: yp1, ypn
23 real(rprec) :: c
24!-----------------------------------------------
25
26 iflag = 0 !initialization
27 if(x < xx(1) .or. x > xx(n)) then
28 iflag = -1
29 y=0.d+0
30 return
31 endif
32 dxx(1:n-1)=xx(2:n)-xx(1:n-1)
33 if(minval(dxx(1:n-1)) <= 0.d+0) then
34 iflag=-2
35 return
36 endif
37
38! fix boundary derivatives by quadratic fit
39! left part
40 c=((yy(3)-yy(1))/(xx(3)-xx(1))-(yy(2)-yy(1))/(xx(2)-xx(1)))
41 > /(xx(3)-xx(2))
42 yp1=(yy(2)-yy(1))/(xx(2)-xx(1))-c*(xx(2)-xx(1))
43! right part
44 c=((yy(n-2)-yy(n))/(xx(n-2)-xx(n))
45 > -(yy(n-1)-yy(n))/(xx(n-1)-xx(n)))
46 > /(xx(n-2)-xx(n-1))
47 ypn=(yy(n-1)-yy(n))/(xx(n-1)-xx(n))-c*(xx(n-1)-xx(n))
48
49 call spline_nr(xx,yy,n,yp1,ypn,y2)
50 call splint_nr(xx,yy,y2,n,x,y)
51
52 return
53
54 contains
55
56 subroutine spline_nr(x,y,n,yp1,ypn,y2)
57! taken from numerical recipes f77 and recoded.
58! Given the arrays x(1:n) and y(1:n) containing the tabulated function
59! with x(1) < x(2) <...< x(n) and given values yp1 and ypn for the first
60! derivative of the interpolating function at points q and n, respectively,
61! this routine returns an array y2(1:n) of length n which contains the
62! second derivatives of the interpolating function at the tabulated points x(i).
63! If yp1 and/or ypn are equatl to 1ed+30 or larger, the routine is signaled
64! to set the correspoinding boundary condition for a natural spline with zero
65! derivative on that boundary.
66! nmax is the largest anticipated value of n.
67 integer, intent(in) :: n
68 integer, parameter :: nmax=500
69 real(rprec), intent(in) :: yp1, ypn
70 real(rprec), dimension(n), intent(in) :: x, y
71 real(rprec), dimension(n), intent(out) :: y2
72 integer :: i,k
73 real(rprec) :: p, qn, sig, un
74 real(rprec), dimension(n) :: u
75
76 if(yp1 > .99d+30) then
77 y2(1)=0.d+0
78 u(1) =0.d+0
79 else
80 y2(1)=-0.5d+0
81 u(1)=(3.d+0/(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1)
82 endif
83
84 do i=2,n-1
85 sig=(x(i)-x(i-1))/(x(i+1)-x(i-1))
86 p=sig*y2(i-1)+2.d+0
87 y2(i)=(sig-1.d+0)/p
88 u(i)=(6.d+0*((y(i+1)-y(i))/(x(i+1)-x(i))-(y(i)-y(i-1))
89 > /(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig*u(i-1))/p
90 enddo
91 if (ypn > .99d+30)then
92 qn=0.d+0
93 un=0.d+0
94 else
95 qn=0.5d+0
96 un=(3.d+0/(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1)))
97 endif
98 y2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.d+0)
99 do k=n-1,1,-1
100 y2(k)=y2(k)*y2(k+1)+u(k)
101 enddo
102 return
103 end subroutine spline_nr
104
105 subroutine splint_nr(xa,ya,y2a,n,x,y)
106! Given the arrays xa(1:n) and ya(1:n) of length n, which tabulate a function
107! with the xa(i)'s in order), and given the array y2a(1:n), which is the
108! output from spline above, and given a value of x, this routine returns
109! a cubic-spline interpolated value y.
110 implicit none
111 integer, intent(in) :: n
112 real(rprec), intent(in) :: x
113 real(rprec), intent(out) :: y
114 real(rprec), dimension(n), intent(in) :: xa, ya, y2a
115!- local -------------------
116 real(rprec) :: a, b, h
117 integer :: k, khi, klo
118
119 klo=1
120 khi=n
121 do
122 if (khi-klo <= 1) exit !inverted num.rec. condition for endless do-loop exit
123 k=(khi+klo)/2
124 if(xa(k) > x) then
125 khi=k
126 else
127 klo=k
128 endif
129 enddo
130
131 h=xa(khi)-xa(klo)
132 if(h ==0.d+0)
133 > stop "spline_cubic: bad xa input! xa(i) have to be distinct!"
134 a=(xa(khi)-x)/h
135 b=(x-xa(klo))/h
136 y=a*ya(klo)+b*ya(khi) +
137 > ((a**3-a)*y2a(klo)+(b**3-b)*y2a(khi))*(h**2)/6.d+0
138 return
139 end subroutine splint_nr
140
141 end subroutine spline_cubic
142
subroutine spline_cubic(x, y, xx, yy, n, iflag)
Definition spline_cubic.f:3
subroutine spline_nr(x, y, n, yp1, ypn, y2)