V3FIT
All Classes Namespaces Files Functions Variables Enumerations Macros Pages
mkbicubw.f
1  subroutine mkbicubw(x,nx,y,ny,f,nf2,
2  > ibcxmin,bcxmin,ibcxmax,bcxmax,
3  > ibcymin,bcymin,ibcymax,bcymax,
4  > wk,nwk,
5  > ilinx,iliny,ier)
6 C
7 C setup a bicubic spline; store coefficients in compact form
8 C (as per suggestion of L. Zakharov, PPPL, Feb. 1999)
9 C 4 coeffs per grid point: f,fxx,fyy,fxxyy
10 C
11 C
12 C input:
13  integer nx ! length of x vector
14  integer ny ! length of y vector
15  real x(nx) ! x vector, strict ascending
16  real y(ny) ! y vector, strict ascending
17 C
18  integer nf2 ! 2nd dimension of f, nf2.ge.nx
19 C input/output:
20 C
21  real f(4,nf2,ny) ! data & spline coefficients
22 C
23 C on input: f(1,i,j) = f(x(i),y(j))
24 C on output: f(1,i,j) unchanged
25 C f(2,i,j) = d2f/dx2(x(i),y(j))
26 C f(3,i,j) = d2f/dy2(x(i),y(j))
27 C f(4,i,j) = d4f/dx2dy2(x(i),y(j))
28 C
29 C and the interpolation formula for (x,y) in (x(i),x(i+1))^(y(j),y(j+1))
30 C is:
31 C hx = x(i+1)-x(i) hy = y(j+1)-y(j)
32 C dxp= (x-x(i))/hx dxm= 1-dxp dxp,dxm in (0,1)
33 C dyp= (x-x(i))/hx dym= 1-dyp dyp,dym in (0,1)
34 C dx3p = dxp**3-dxp dx3m = dxm**3-dxm dxp3,dxm3 in (0,1)
35 C
36 C finterp = dxm*(dym*f(1,i,j)+dyp*f(1,i,j+1))
37 C +dxp*(dym*f(1,i+1,j)+dyp*f(1,i+1,j+1))
38 C +1/6*hx**2*
39 C dx3m*(dym*f(2,i,j)+dyp*f(2,i,j+1))
40 C +dx3p*(dym*f(2,i+1,j)+dyp*f(2,i+1,j+1))
41 C +1/6*hy**2*
42 C dxm*(dy3m*f(3,i,j)+dy3p*f(3,i,j+1))
43 C +dxp*(dy3m*f(3,i+1,j)+dy3p*f(3,i+1,j+1))
44 C +1/36*hx**2*hy**2*
45 C dx3m*(dym*f(4,i,j)+dyp*f(4,i,j+1))
46 C +dx3p*(dym*f(4,i+1,j)+dyp*f(4,i+1,j+1))
47 C
48 C where the f(2:4,*,*) are cleverly evaluated to assure
49 C (a) finterp is continuous and twice differentiable across all
50 C grid cell boundaries, and
51 C (b) all boundary conditions are satisfied.
52 C
53 C the boundary conditions specification options are:
54 C inputs:
55 C
56  integer ibcxmin ! bc flag for x=xmin
57  real bcxmin(ny) ! bc data vs. y at x=xmin
58  integer ibcxmax ! bc flag for x=xmax
59  real bcxmax(ny) ! bc data vs. y at x=xmax
60 C
61  integer ibcymin ! bc flag for y=ymin
62  real bcymin(nx) ! bc data vs. x at y=ymin
63  integer ibcymax ! bc flag for y=ymax
64  real bcymax(nx) ! bc data vs. x at y=ymax
65 C
66 C with interpretation:
67 c ibcxmin -- indicator for boundary condition at x(1):
68 c bcxmin(...) -- boundary condition data
69 c =-1 -- periodic boundary condition
70 c =0 -- use "not a knot"
71 c =1 -- match slope, specified at x(1),th(ith) by bcxmin(ith)
72 c =2 -- match 2nd derivative, specified at x(1),th(ith) by bcxmin(ith)
73 c =3 -- boundary condition is slope=0 (df/dx=0) at x(1), all th(j)
74 c =4 -- boundary condition is d2f/dx2=0 at x(1), all th(j)
75 c =5 -- match 1st derivative to 1st divided difference
76 c =6 -- match 2nd derivative to 2nd divided difference
77 c =7 -- match 3rd derivative to 3rd divided difference
78 c (for more detailed definition of BCs 5-7, see the
79 c comments of subroutine mkspline)
80 c NOTE bcxmin(...) referenced ONLY if ibcxmin=1 or ibcxmin=2
81 c
82 c ibcxmax -- indicator for boundary condition at x(nx):
83 c bcxmax(...) -- boundary condition data
84 c (interpretation as with ibcxmin, bcxmin)
85 c NOTE: if ibcxmin=-1, ibcxmax is ignored! ...and the BC is periodic.
86 c
87 C and analogous interpretation for ibcymin,bcymin,ibcymax,bcymax
88 C (df/dy or d2f/dy2 boundary conditions at y=ymin and y=ymax).
89 C
90 C *** workspace ***
91 C This FORTRAN-77 routine requires a workspace of
92 C nwk = (AT LEAST) 21*nx*ny
93 C *** for dynamic allocation of this workspace use subroutine mkbicub
94 C which has the same arguments as mkbicubw, except that the workspace
95 C does not have to be provided -- mkbicub is FORTRAN-90.
96 C
97 C input:
98  integer nwk ! size of workspace
99 C modified on output:
100  real wk(nwk) ! workspace
101 C
102 C and output arguments
103 C
104  integer ilinx ! =1: x grid is "nearly" equally spaced
105  integer iliny ! =1: y grid is "nearly" equally spaced
106 C
107 C ilinx and iliny are set to zero if corresponding grids are not equally
108 C spaced
109 C
110 C and completion code
111 C
112  integer ier ! =0 on exit if there is no error.
113 C
114 C if there is an error, ier is set and a message is output on unit 6.
115 C these are considered programming errors in the calling routine.
116 C
117 C possible errors:
118 C x(...) not strict ascending
119 C y(...) not strict ascending
120 C nx .lt. 4
121 C ny .lt. 4
122 C invalid boundary condition flag
123 C workspace too small
124 C
125 C-----------------------------------------------------
126 C local arrays
127 C
128  integer iselect(10)
129  integer zvalues(10)
130 C
131  data iselect/-1,0,0,0,0,0,0,0,0,0/
132 C
133 C-----------------------------------------------------
134 C
135  itest=21*nx*ny
136  if(nwk.lt.itest) then
137  write(6,9901) nwk,itest
138  9901 format(' ?mkbicubw: workspace too small:'/
139  > ' user supplied: nwk=',i7,'; need at least: ',i7/
140  > ' nwk = at least 21*nx*ny is required.')
141  ier=1
142  return
143  endif
144 C
145  iadfp=1
146  isiz1=16*nx*ny
147  iadfw=iadfp+isiz1
148  inwk = nwk-isiz1
149 C
150  call mkbicop(f,nf2,wk(iadfp),nx,ny)
151 C
152 C evaluate 4x4 continuous bicubic spline
153 C
154  call bcspline(x,nx,y,ny,wk(iadfp),nx,
155  > ibcxmin,bcxmin,ibcxmax,bcxmax,
156  > ibcymin,bcymin,ibcymax,bcymax,
157  > wk(iadfw),inwk,
158  > ilinx,iliny,ier)
159 C
160  if(ier.ne.0) return
161 C
162 C convert to 4-coefficient (2nd/4th partials form)
163 C
164  hxlast=x(nx)-x(nx-1)
165  hylast=y(ny)-y(ny-1)
166  call mkbicon(f,nf2,wk(iadfp),nx,ny,hxlast,hylast)
167 C
168  return
169  end
170 C
171 C----------------------------------------------------------------
172 C mkbicop -- copy spline function input data
173 C
174  subroutine mkbicop(fin,nf2,fwk,nx,ny)
175 C
176  real fin(4,nf2,ny)
177  real fwk(4,4,nx,ny)
178 C
179  do iy=1,ny
180  do ix=1,nx
181  fwk(1,1,ix,iy)=fin(1,ix,iy)
182  enddo
183  enddo
184 C
185  return
186  end
187 C----------------------------------------------------------------
188 C mkbicon -- create compact spline representation from 4x4
189 C (bcspline) representation
190 C
191  subroutine mkbicon(fin,nf2,fwk,nx,ny,hxlast,hylast)
192 C
193  real fin(4,nf2,ny)
194  real fwk(4,4,nx,ny)
195 C
196 C-----------------------------------------------------
197 C local arrays
198 C
199  integer iselect(10)
200  real zvalues(10)
201 C
202  data iselect/-1,0,0,0,0,0,0,0,0,0/
203 C
204 C-----------------------------------------------------
205 C
206  do iy=1,ny
207  do ix=1,nx
208 C
209 C copy derivatives from result. Special treatment needed for end zones
210 C
211  iflag=0
212  dxuse=0.0
213  dyuse=0.0
214  ixuse=ix
215  iyuse=iy
216  if(ix.eq.nx) then
217  iflag=1
218  dxuse=hxlast
219  ixuse=ix-1
220  endif
221  if(iy.eq.ny) then
222  iflag=1
223  dyuse=hylast
224  iyuse=iy-1
225  endif
226 C
227  if(iflag.eq.1) then
228  call bcspevfn(iselect,1,1,zvalues,
229  > ixuse,iyuse,dxuse,dyuse,
230  > fwk,nx,ny)
231  do j=2,4
232  fin(j,ix,iy)=zvalues(j)
233  enddo
234  else
235  fin(2,ix,iy)=2.0*fwk(3,1,ix,iy)
236  fin(3,ix,iy)=2.0*fwk(1,3,ix,iy)
237  fin(4,ix,iy)=4.0*fwk(3,3,ix,iy)
238  endif
239 C
240  enddo
241  enddo
242 C
243  return
244  end