Vous êtes sur la page 1sur 17

FORTRAN Subroutines

being an appendix to
M
3
4
N4
Computational Linear
Algebra
c Gerald Moore
The FORTRAN programs contained in these notes are available from my home-
page
http://www.ma.ic.ac.uk/~gmoore
Before calling the subroutines spfa.f and spsl.f from a main program, the
following statements will set up an n n upper-triangular matrix a.
type utmatrix
real, dimension(:), pointer :: r
end type utmatrix
type(utmatrix), dimension(:), allocatable :: a
allocate(a(n))
do j=1,n
allocate(a(j)%r(j))
end do
FORTRAN Programs 1
subroutine gefa(a,n)
real, intent(inout), dimension(:,:) :: a
integer, intent(in) :: n
integer :: j,k
do k=1,n-1
a(k+1:n,k)=a(k+1:n,k)/a(k,k)
do j=k+1,n
a(k+1:n,j)=a(k+1:n,j)-a(k,j)a(k+1:n,k)
end do
end do
return
end subroutine gefa
FORTRAN program for factorisation of a general matrix
without pivoting
subroutine gesl(a,n,b)
real, intent(in), dimension(:,:) :: a
integer, intent(in) :: n
real, intent(inout), dimension(:) :: b
integer :: k
do k=1,n-1
b(k+1:n)=b(k+1:n)-b(k)a(k+1:n,k)
end do
do k=n,1,-1
b(k)=b(k)/a(k,k)
b(1:k-1)=b(1:k-1)-b(k)a(1:k-1,k)
end do
return
end subroutine gesl
FORTRAN program for solving a general system without pivoting
2 Gerald Moore
subroutine gefapp(a,n,row)
real, intent(inout), dimension(:,:) :: a
integer, intent(in) :: n
integer, intent(inout), dimension(:) :: row
real :: t; integer :: j,k,l(1)
do k=1,n-1
l=maxloc(abs(a(k:n,k)))+k-1
row(k)=l(1)
if (a(l(1),k) == 0.) cycle
if (l(1) /= k) then
t=a(l(1),k)
a(l(1),k)=a(k,k)
a(k,k)=t
end if
a(k+1:n,k)=a(k+1:n,k)/a(k,k)
do j=k+1,n
t=a(l(1),j)
if (l(1) /= k) then
a(l(1),j)=a(k,j)
a(k,j)=t
end if
a(k+1:n,j)=a(k+1:n,j)-ta(k+1:n,k)
end do
end do
return
end subroutine gefapp
FORTRAN program for factorisation of a general matrix
with partial pivoting
FORTRAN Programs 3
subroutine geslpp(a,n,row,b)
real, intent(in), dimension(:,:) :: a
integer, intent(in) :: n
integer, intent(in), dimension(:) :: row
real, intent(inout), dimension(:) :: b
real :: t; integer :: k,l
do k=1,n-1
l=row(k)
t=b(l)
if (l /= k) then
b(l)=b(k)
b(k)=t
end if
b(k+1:n)=b(k+1:n)-ta(k+1:n,k)
end do
do k=n,1,-1
b(k)=b(k)/a(k,k)
b(1:k-1)=b(1:k-1)-b(k)a(1:k-1,k)
end do
return
end subroutine geslpp
FORTRAN program for solving a general system with partial pivoting
4 Gerald Moore
subroutine gefacp(a,n,row,col)
real, intent(inout), dimension(:,:) :: a
integer, intent(in) :: n
integer, intent(out), dimension(:) :: row,col
integer :: i,j,k,l(2); real :: t
do k=1,n-1
l=maxloc(abs(a(k:n,k:n)))+k-1
row(k)=l(1)
col(k)=l(2)
if (a(l(1),l(2)) == 0.) exit
if (l(2) /= k) then
do i=1,n
t=a(i,l(2))
a(i,l(2))=a(i,k)
a(i,k)=t
end do
end if
if (l(1) /= k) then
t=a(l(1),k)
a(l(1),k)=a(k,k)
a(k,k)=t
end if
a(k+1:n,k)=a(k+1:n,k)/a(k,k)
do j=k+1,n
t=a(l(1),j)
if (l(1) /= k) then
a(l(1),j)=a(k,j)
a(k,j)=t
end if
a(k+1:n,j)=a(k+1:n,j)-ta(k+1:n,k)
end do
end do
return
end subroutine gefacp
FORTRAN program for factorisation of a general matrix
with complete pivoting
FORTRAN Programs 5
subroutine geslcp(a,n,row,col,b)
real, intent(in), dimension(:,:) :: a
integer, intent(in) :: n
integer, intent(in), dimension(:) :: row,col
real, intent(inout), dimension(:) :: b
integer :: k,l; real :: t
do k=1,n-1
l=row(k)
t=b(l)
if (l /= k) then
b(l)=b(k)
b(k)=t
end if
b(k+1:n)=b(k+1:n)-ta(k+1:n,k)
end do
do k=n,1,-1
b(k)=b(k)/a(k,k)
b(1:k-1)=b(1:k-1)-b(k)a(1:k-1,k)
end do
do k=n-1,1,-1
l=col(k)
if (l /= k) then
t=b(l)
b(l)=b(k)
b(k)=t
end if
end do
return
end subroutine geslcp
FORTRAN program for solving a general system with complete pivoting
6 Gerald Moore
subroutine spfa(a,n)
type(utmatrix), intent(inout), dimension(:) :: a
integer, intent(in) :: n
integer :: j,k; real :: s,t
do j=1,n
s=0.
do k=1,j-1
t=a(j)%r(k)
-dot product(a(k)%r(1:k-1),a(j)%r(1:k-1))
t=t/a(k)%r(k)
a(j)%r(k)=t
s=s+tt
end do
s=a(j)%r(j)-s
a(j)%r(j)=sqrt(s)
end do
return
end subroutine spfa
FORTRAN program for Cholesky factorisation of a
symmetric, positive-denite matrix
subroutine spsl(a,n,b)
type(utmatrix), intent(in), dimension(:) :: a
integer, intent(in) :: n
real, intent(inout), dimension(:) :: b
integer :: k; real :: t
do k=1,n
t=dot product(a(k)%r(1:k-1),b(1:k-1))
b(k)=(b(k)-t)/a(k)%r(k)
end do
do k=n,1,-1
b(k)=b(k)/a(k)%r(k)
b(1:k-1)=b(1:k-1)-b(k)a(k)%r(1:k-1)
end do
return
end subroutine spsl
FORTRAN program for solving a symmetric, positive-denite system
FORTRAN Programs 7
subroutine gefab(ab,n,ml,mu)
real, intent(inout), dimension(:,:) :: ab
integer, intent(in) :: n,ml,mu
integer :: m,ju,lm,mm
m=mu+1
do k=1,n-1
lm=min(ml,n-k)
ab(m+1:m+lm,k)=ab(m+1:m+lm,k)/ab(m,k)
ju=min(mu+k,n)
mm=m
do j=k+1,ju
mm=mm-1
ab(mm+1:mm+lm,j)=ab(mm+1:mm+lm,j)&
-ab(mm,j)ab(m+1:m+lm,k)
end do
end do
return
end subroutine gefab
FORTRAN program for factorising a banded matrix without pivoting
subroutine geslb(ab,n,ml,mu,b)
real, intent(in), dimension(:,:) :: ab
integer, intent(in) :: n,ml,mu
real, intent(inout), dimension(:) :: b
real :: t; integer :: m,k,lm,l,la,lb
m=mu+1
if (ml /= 0) then
do k=1,n-1
lm=min(ml,n-k)
b(k+1:k+lm)=b(k+1:k+lm)-b(k)ab(m+1:m+lm,k)
end do
end if
do k=n,1,-1
b(k)=b(k)/ab(m,k)
lm=min(k,m)-1
b(k-lm:k-1)=b(k-lm:k-1)-b(k)ab(m-lm:m-1,k)
end do
return
end subroutine geslb
FORTRAN program for solving a banded system without pivoting
8 Gerald Moore
subroutine spfab(ab,n,m)
real, intent(inout), dimension(:,:) :: ab
integer, intent(in) :: n,m
real :: s,t; integer :: j,k,ik,jk,mu
do j=1,n
s=0.; ik=m+1; jk=max(j-m,1)
mu=max(m+2-j,1)
do k=mu,m
t=ab(k,j)-dot product(ab(ik:m,jk),ab(mu:k-1,j))
t=t/ab(m+1,jk)
ab(k,j)=t
s=s+tt
ik=ik-1; jk=jk+1
end do
s=ab(m+1,j)-s
ab(m+1,j)=sqrt(s)
end do
return
end subroutine spfab
FORTRAN program for Cholesky factorisation of a banded
symmetric, positive-denite matrix
subroutine spslb(ab,n,m,b)
real, intent(in), dimension(:,:) :: ab
integer, intent(in) :: n,m
real, intent(inout), dimension(:) :: b
real :: t; integer :: k,lm,la,lb
do k=1,n
lm=min(k-1,m); la=m+1-lm; lb=k-lm
t=dot product(ab(la:m,k),b(lb:k-1))
b(k)=(b(k)-t)/ab(m+1,k)
end do
do k=n,1,-1
lm=min(k-1,m); la=m+1-lm; lb=k-lm
b(k)=b(k)/ab(m+1,k)
b(lb:k-1)=b(lb:k-1)-b(k)ab(la:m,k)
end do
return
end subroutine spslb
FORTRAN program for solving a banded, symmetric, positive-denite system
FORTRAN Programs 9
subroutine gefabp(ab,n,ml,mu,row)
real, intent(inout), dimension(:,:) :: ab
integer, intent(in) :: n,ml,mu
integer, intent(out), dimension(:) :: row
real :: t; integer :: m,j0,j1,jz,i0,ju,lm,l(1),mm
m=ml+mu+1; j0=mu+2; j1=min(n,m)-1
do jz=j0,j1
i0=m+1-jz
ab(i0:ml,jz)=0.
end do
ab(1:ml,j1+1:n)=0.
ju=0
do k=1,n-1
lm=min(ml,n-k)
l=maxloc(abs(ab(m:m+lm,k)))+m-1
row(k)=l(1)+k-m
if (ab(l(1),k) == 0.) cycle
if (l(1) /= m) then
t=ab(l(1),k)
ab(l(1),k)=ab(m,k)
ab(m,k)=t
end if
ab(m+1:m+lm,k)=ab(m+1:m+lm,k)/ab(m,k)
ju=min(max(ju,mu+row(k)),n)
mm=m
do j=k+1,ju
l(1)=l(1)-1
mm=mm-1
t=ab(l(1),j)
if (l(1) /= mm) then
ab(l(1),j)=ab(mm,j)
ab(mm,j)=t
end if
ab(mm+1:mm+lm,j)=ab(mm+1:mm+lm,j)-tab(m+1:m+lm,k)
end do
end do
return
end subroutine gefabp
FORTRAN program for factorising a banded matrix with partial pivoting
10 Gerald Moore
subroutine geslbp(ab,n,ml,mu,row,b)
real, intent(in), dimension(:,:) :: ab
integer, intent(in) :: n,ml,mu
integer, intent(in), dimension(:) :: row
real, intent(inout), dimension(:) :: b
real :: t; integer :: m,k,lm,l,la,lb
m=ml+mu+1
if (ml /= 0) then
do k=1,n-1
lm=min(ml,n-k)
l=row(k)
t=b(l)
if (l /= k) then
b(l)=b(k)
b(k)=t
end if
b(k+1:k+lm)=b(k+1:k+lm)-tab(m+1:m+lm,k)
end do
end if
do k=n,1,-1
b(k)=b(k)/ab(m,k)
lm=min(k,m)-1
la=m-lm
lb=k-lm
b(lb:k-1)=b(lb:k-1)-b(k)ab(la:m-1,k)
end do
return
end subroutine geslbp
FORTRAN program for solving a banded system with partial pivoting
FORTRAN Programs 11
subroutine qrfac(a,n,w)
real, intent(inout), dimension(:,:) :: a
integer, intent(in) :: n
real, intent(out), dimension(:) :: w
integer :: j,k; real :: t,tn
do k=1,n-1
w(k)=0.
tn=sqrt(dot product(a(k:n,k),a(k:n,k)))
if (tn == 0.) cycle
if (a(k,k) /= 0.) tn=sign(tn,a(k,k))
a(k:n,k)=a(k:n,k)/tn
a(k,k)=1.+a(k,k)
do j=k+1,n
t=dot product(a(k:n,k),a(k:n,j))/a(k,k)
a(k:n,j)=a(k:n,j)-ta(k:n,k)
end do
w(k)=a(k,k)
a(k,k)=-tn
end do
return
end subroutine qrfac
FORTRAN program for orthogonal factorisation of a general matrix
subroutine qrsol(a,n,w,b)
real, intent(inout), dimension(:,:) :: a
integer, intent(in) :: n
real, intent(in), dimension(:) :: w
real, intent(inout), dimension(:) :: b
integer :: k; real :: t,tt
do k=1,n-1
tt=a(k,k)
a(k,k)=w(k)
t=dot product(a(k:n,k),b(k:n))/a(k,k)
b(k:n)=b(k:n)-ta(k:n,k)
a(k,k)=tt
end do
do k=n,1,-1
b(k)=b(k)/a(k,k)
b(1:k-1)=b(1:k-1)-b(k)a(1:k-1,k)
end do
return
end subroutine qrsol
FORTRAN program for solving a general system (after orthogonal factorisation)
12 Gerald Moore
program jacobi
integer, parameter :: m=20,m1=m-1
real, parameter :: h=1./m,h2=h*h
real :: u(0:m,0:m)=0,v(0:m,0:m)=0,b(1:m1,1:m1)
integer :: i,j,k,its
read, its
do j=1,m1
do i=1,m1
b(i,j)=h2f(ih,jh)
end do
end do
do k=1,its
if (k /= k/22) then
do j=1,m1
do i=1,m1
v(i,j)=(b(i,j)+u(i,j-1)+u(i-1,j)&
+u(i+1,j)+u(i,j+1))/4
end do
end do
else
do j=1,m1
do 70 i=1,m1
u(i,j)=(b(i,j)+v(i,j-1)+v(i-1,j)&
+v(i+1,j)+v(i,j+1))/4
end do
end do
endif
end do
contains
function f(x,y)
real :: f
real, intent(in) :: x,y
f=1
end function f
end program jacobi
FORTRAN program for Jacobi iteration applied to model problem
FORTRAN Programs 13
program gauss
integer, parameter :: m=20,m1=m-1
real, parameter :: h=1./m,h2=h*h
real :: u(0:m,0:m)=0,b(1:m1,1:m1)
integer :: i,j,k,its
read, its
do j=1,m1
do i=1,m1
b(i,j)=h2f(ih,jh)
end do
end do
do k=1,its
do j=1,m1
do i=1,m1
u(i,j)=(b(i,j)+u(i,j-1)+u(i-1,j)&
+u(i+1,j)+u(i,j+1))/4
end do
end do
end do
contains
function f(x,y)
real :: f
real, intent(in) :: x,y
f=1
end function f
end program gauss
FORTRAN program for Gauss-Seidel iteration applied to model problem
To alter this program so that SOR iteration with optimal is performed: add
an extra parameter statement
real, parameter :: pi=4.atan(1.),w=2./(1.+sin(pih)),w1=1.-w
and change the main iteration step to
u(i,j)=w1u(i,j)+w(b(i,j)+u(i,j-1)+u(i-1,j)+u(i+1,j)+u(i,j+1))/4
14 Gerald Moore
program cheby
integer, parameter :: m=20,m1=m-1
real, parameter :: h=1./m,h2=hh
real :: yo(0:m,0:m)=0,yn(0:m,0:m)=0,z(0:m,0:m)=0,b(1:m1,1:m1)
integer :: i,j,k,iflag,its
real :: al,be,ga,t,th,cth,w
read , iflag,its
call init(h,al,be,iflag)
w=2; t=2-be-al; ga=2/t
th=t/(be-al); cth=1/(4thth)
do j=1,m1
do i=1,m1
b(i,j)=h2f(ih,jh)
end do
end do
call inc(m1,b,yo,z,iflag)
yn(1:m1,1:m1)=yo(1:m1,1:m1)+gaz(1:m1,1:m1)
do k=1,its
w=1/(1-cthw)
call inc(m1,b,yn,z,iflag)
z(1:m1,1:m1)=w(yn(1:m1,1:m1)-yo(1:m1,1:m1)&
+gaz(1:m1,1:m1))+yo(1:m1,1:m1)
yo(1:m1,1:m1)=yn(1:m1,1:m1); yn(1:m1,1:m1)=z(1:m1,1:m1)
end do
contains
subroutine init(h,al,be,iflag)
real, intent(in) :: h
real, intent(out) :: al,be
integer, intent(in) :: iflag
real :: pi,w,w1,t
common /ssor/w,w1
save /ssor/
pi=4atan(1.)
if (iflag == 0) then
be=cos(pih); al=-be
else
t=sin(pih/2)
al=0; be=(1-t)/(1+t)
w=2/(1+2t); w1=1-w
endif
return
end subroutine init
FORTRAN Programs 15
subroutine inc(m1,b,y,z,iflag)
integer, intent(in) :: m1,iflag
real, intent(in), dimension(:,:) :: y(0:,0:),b(:,:)
real, intent(out), dimension(:,:) :: z(0:,0:)
integer ::i,j
real :: w,w1
common /ssor/w,w1
save /ssor/
if (iflag == 0) then
do j=1,m1
do i=1,m1
z(i,j)=(b(i,j)+y(i,j-1)+y(i-1,j)&
+y(i+1,j)+y(i,j+1))/4-y(i,j)
end do
end do
else
do j=1,m1
do i=1,m1
z(i,j)=w1y(i,j)+w(b(i,j)+z(i,j-1)&
+z(i-1,j)+y(i+1,j)+y(i,j+1))/4
end do
end do
do j=m1,1,-1
do i=m1,1,-1
z(i,j)=w1z(i,j)+w(b(i,j)+z(i,j-1)+z(i-1,j)&
+z(i+1,j)+z(i,j+1))/4
end do
end do
do j=1,m1
do i=1,m1
z(i,j)=z(i,j)-y(i,j)
end do
end do
endif
return
end subroutine inc
function f(x,y)
real :: f
real, intent(in) :: x,y
f=1
end function f
end program cheby
FORTRAN program for Chebyshev acceleration of Jacobi [iflag=0] or
SSOR [iflag=0] applied to the model problem

Vous aimerez peut-être aussi