program main
implicit none
integer::i,j,Nx,Ny,Mx,My
double precision::x,y,f,df,df2
double precision,allocatable::xdata(:),ydata(:),fdata(:,:),xa(:),ya(:),fa(:,:)
Nx=10
Ny=20
Mx=50
My=100
allocate(xdata(0:Nx),ydata(0:Ny),fdata(0:Nx,0:Ny))
allocate(xa(0:Mx),ya(0:My),fa(0:Mx,0:My))
xdata=0d0
ydata=0d0
fdata=0d0
xa=0d0
ya=0d0
fa=0d0
! original data
open(10,file='original_data.d')
write(10,'(A)')"# x y f(x,y)"
do i=0,Nx
do j=0,Ny
xdata(i)=dble(i)*0.5d0
ydata(j)=dble(j)*0.2d0
fdata(i,j)=sin(2d0*xdata(i))*exp(-0.5d0*ydata(j)**2)
write(10,*)xdata(i),ydata(j),fdata(i,j)
enddo
write(10,*)
enddo
close(10)
! Cubic-spline interpolation given position as point
open(10,file='interpolate_data1.d')
write(10,'(A)')"# x y f(x,y) df(x,y)/dx d^2f(x,y)/dx^2"
do i=0,Mx
do j=0,My
x=dble(i)*0.1d0
y=dble(j)*0.04d0
call c3spline2d1p(f,df,df2,x,y,Nx,Ny,fdata,xdata,ydata,1)
write(10,'(6e20.7e3)')x,y,f,df,df2,abs((f-sin(2d0*x)*exp(-0.5d0*y**2))/(f))
enddo
write(10,*)
enddo
close(10)
! Cubic-spline interpolation given position as array
do i=0,Mx
xa(i)=dble(i)*0.1d0
enddo
do j=0,My
ya(j)=dble(j)*0.04d0
enddo
open(10,file='interpolate_data2.d')
write(10,'(A)')"# x y f(x,y) "
call c3spline2d(fa,Mx,My,xa,ya,Nx,Ny,fdata,xdata,ydata)
do i=0,Mx
do j=0,My
write(10,'(3e20.7e3)')xa(i),ya(j),fa(i,j)
enddo
write(10,*)
enddo
close(10)
! 2d integration by spline interpolation
call c3spline2d_integral(s,Nx,Ny,xdata,ydata,fdata)
write(6,*)s
stop
end program main
subroutine c3spline2d1p(f,df,df2,x,y,Nx,Ny,fdata,xdata,ydata,key)
implicit none
integer,intent(in)::Nx,Ny,key
double precision,intent(in)::x,y,fdata(0:Nx,0:Ny),xdata(0:Nx),ydata(0:Ny)
double precision,intent(out)::f,df,df2
!
! key = 1 --> 1.interpolate y, 2.interpolate x | df = df/dx, df2 = d^2f/dx^2
! key = 2 --> 1.interpolate x, 2.interpolate y | df = df/dy, df2 = d^2f/dy^2
! key = 3 --> Average of key=1,2 | df = 0, df2=0
!
integer::i,j
double precision,allocatable::tfx(:),tfy(:)
double precision::p,q,dfdx,dfdy,dfdx2,dfdy2
allocate(tfx(0:Nx),tfy(0:Ny))
tfx=0d0; tfy=0d0
if(key.eq.1)then
do i=0,Nx
tfy(0:Ny)=fdata(i,0:Ny)
call c3spline1p(f,df,df2,y,Ny,tfy,ydata)
tfx(i)=f
enddo
call c3spline1p(f,df,df2,x,Nx,tfx,xdata)
elseif(key.eq.2)then
do j=0,Ny
tfx(0:Nx)=fdata(0:Nx,j)
call c3spline1p(f,df,df2,x,Nx,tfx,xdata)
tfy(j)=f
enddo
call c3spline1p(f,df,df2,y,Ny,tfy,ydata)
elseif(key.eq.3)then
do i=0,Nx
tfy(0:Ny)=fdata(i,0:Ny)
call c3spline1p(f,df,df2,y,Ny,tfy,ydata)
tfx(i)=f
enddo
call c3spline1p(p,dfdx,dfdx2,x,Nx,tfx,xdata)
do j=0,Ny
tfx(0:Nx)=fdata(0:Nx,j)
call c3spline1p(f,df,df2,x,Nx,tfx,xdata)
tfy(j)=f
enddo
call c3spline1p(q,dfdy,dfdy2,y,Ny,tfy,ydata)
f = (p+q)*0.5d0
df = 0d0
! df = dfdx
! df = dfdy
df2 = 0d0
! df2 = dfdx2
! df2 = dfdy2
endif
return
end subroutine c3spline2d1p
subroutine c3spline2d(f,Mx,My,x,y,Nx,Ny,fdata,xdata,ydata)
implicit none
integer,intent(in)::Nx,Ny,Mx,My
double precision,intent(in)::x(0:Mx),y(0:My)
double precision,intent(in)::fdata(0:Nx,0:Ny),xdata(0:Nx),ydata(0:Ny)
double precision,intent(out)::f(0:Mx,0:My)
integer::i,j
double precision,allocatable::tfx(:),tfy(:),gx(:),gy(:),gf(:,:)
allocate(tfx(0:Nx),tfy(0:Ny),gx(0:Mx),gy(0:My),gf(0:Nx,0:My))
tfx=0d0; tfy=0d0; gx=0d0; gy=0d0
do i=0,Nx
tfy(0:Ny)=fdata(i,0:Ny)
call c3spline(My,gy,y,Ny,tfy,ydata)
gf(i,0:My)=gy(0:My)
enddo
do j=0,My
tfx(0:Nx)=gf(0:Nx,j)
call c3spline(Mx,gx,x,Nx,tfx,xdata)
f(0:Mx,j)=gx(0:Mx)
enddo
return
end subroutine c3spline2d
subroutine c3spline(M,f,x,N,fdata,xdata)
implicit none
integer,intent(in)::N,M
double precision,intent(in)::x(0:M),fdata(0:N),xdata(0:N)
double precision,intent(out)::f(0:M) !,df(0:M),df2(0:M)
integer::i,j
double precision::t
double precision,allocatable::a(:),b(:),c(:),d(:)
allocate(a(0:N-1),b(0:N-1),c(0:N-1),d(0:N-1))
call spline_abcd(a,b,c,d,N,xdata,fdata)
do j=0,M
if(x(j).lt.xdata(0))then
t=x(j)-xdata(0)
f(j) = ((a(0)*t+b(0))*t+c(0))*t+d(0)
!df(j) =3d0*a(0)*t*t+2d0*b(0)*t+c(0)
!df2(j)=6d0*a(0)*t+2d0*b(0)
elseif(x(j).gt.xdata(N))then
t =x(j)-xdata(N-1)
f(j) = ((a(N-1)*t+b(N-1))*t+c(N-1))*t+d(N-1)
!df(j) =3d0*a(N-1)*t*t+2d0*b(N-1)*t+c(N-1)
!df2(j)=6d0*a(N-1)*t+2d0*b(N-1)
else
do i=0,N-1
if(x(j).ge.xdata(i).and.x(j).le.xdata(i+1))then
t=x(j)-xdata(i)
f(j) = ((a(i)*t+b(i))*t+c(i))*t+d(i)
!df(j) =3d0*a(i)*t*t+2d0*b(i)*t+c(i)
!df2(j)=6d0*a(i)*t+2d0*b(i)
exit
endif
enddo
endif
enddo
return
end subroutine c3spline
subroutine c3spline1p(f,df,df2,x,N,fdata,xdata)
implicit none
integer,intent(in)::N
double precision,intent(in)::x,fdata(0:N),xdata(0:N)
double precision,intent(out)::f,df,df2
integer::i
double precision::t
double precision,allocatable::a(:),b(:),c(:),d(:)
allocate(a(0:N-1),b(0:N-1),c(0:N-1),d(0:N-1))
call spline_abcd(a,b,c,d,N,xdata,fdata)
if(x.lt.xdata(0))then
t=x-xdata(0)
f = ((a(0)*t+b(0))*t+c(0))*t+d(0)
df =3d0*a(0)*t*t+2d0*b(0)*t+c(0)
df2=6d0*a(0)*t+2d0*b(0)
elseif(x.gt.xdata(N))then
t=x-xdata(N-1)
f= ((a(N-1)*t+b(N-1))*t+c(N-1))*t+d(N-1)
df =3d0*a(N-1)*t*t+2d0*b(N-1)*t+c(N-1)
df2=6d0*a(N-1)*t+2d0*b(N-1)
else
do i=0,N-1
if(x.ge.xdata(i).and.x.le.xdata(i+1))then
t=x-xdata(i)
f= ((a(i)*t+b(i))*t+c(i))*t+d(i)
df =3d0*a(i)*t*t+2d0*b(i)*t+c(i)
df2=6d0*a(i)*t+2d0*b(i)
exit
endif
enddo
endif
return
end subroutine c3spline1p
subroutine c3spline2d_integral(s,Nx,Ny,xdata,ydata,fdata)
implicit none
integer,intent(in)::Nx,Ny
double precision,intent(in)::fdata(0:Nx,0:Ny),xdata(0:Nx),ydata(0:Ny)
double precision,intent(out)::s
integer::i,j
double precision::t
double precision,allocatable::tfy(:),tfx(:)
allocate(tfx(0:Nx),tfy(0:Ny))
do j=0,Ny
tfx(0:Nx)=fdata(0:Nx,j)
call c3spline_integral(t,Nx,tfx,xdata)
tfy(j)=t
enddo
call c3spline_integral(s,Ny,tfy,ydata)
return
end subroutine c3spline2d_integral
subroutine c3spline_integral(s,N,fdata,xdata)
implicit none
integer,intent(in)::N
double precision,intent(in)::fdata(0:N),xdata(0:N)
double precision,intent(out)::s
integer::i
double precision::t
double precision,allocatable::a(:),b(:),c(:),d(:)
allocate(a(0:N-1),b(0:N-1),c(0:N-1),d(0:N-1))
call spline_abcd(a,b,c,d,N,xdata,fdata)
s=0d0
do i=0,N-1
t=xdata(i+1)-xdata(i)
s=s+0.25d0*a(i)*t**4 + (b(i)/3d0)*t**3 + 0.5d0*c(i)*t**2 + d(i)*t
enddo
return
end subroutine c3spline_integral
subroutine spline_abcd(a,b,c,d,N,xdata,fdata)
implicit none
integer,intent(in)::N
double precision,intent(out)::a(0:N-1),b(0:N-1),c(0:N-1),d(0:N-1)
double precision,intent(in)::xdata(0:N),fdata(0:N)
integer::i,j
double precision,allocatable::l(:),mu(:),h(:),alpha(:),z(:)
allocate(h(0:N-1),alpha(1:N-1))
do i=0,N-1
h(i)=xdata(i+1)-xdata(i)
enddo
do i=1,N-1
alpha(i)=3d0*(fdata(i+1)-fdata(i))/h(i)-3d0*(fdata(i)-fdata(i-1))/h(i-1)
enddo
allocate(l(0:N-1),mu(0:N-1),z(0:N-1))
l=0d0; mu=0d0; z=0d0
l(0)=1d0
do i=1,N-1
l(i)=2d0*(xdata(i+1)-xdata(i-1))-h(i-1)*mu(i-1)
mu(i)=h(i)/l(i)
z(i)=(alpha(i)-h(i-1)*z(i-1))/l(i)
enddo
b(N-1)=z(N-1)
c(N-1)=(fdata(N)-fdata(N-1))/h(N-1)-h(N-1)*(2d0*b(N-1))/3d0
a(N-1)=-b(N-1)/(3d0*h(N-1))
d(N-1)=fdata(N-1)
do j=N-2,0,-1
b(j)=z(j)-mu(j)*b(j+1)
c(j)=(fdata(j+1)-fdata(j))/h(j)-h(j)*(b(j+1)+2d0*b(j))/3d0
a(j)=(b(j+1)-b(j))/(3d0*h(j))
d(j)=fdata(j)
enddo
return
end subroutine spline_abcd