You are on page 1of 83

Dan Racoi

Elemente de Fortran 95
1
Cuprins
0. Introducere
1.0 Constante i variabile
1.1 Operaii algebrice simple
2.1 Instruciunea IF
2.1.1 Instruciunea IF aritmetic
2.1.2 Instruciunea IF logic
2.1.3 Instruciunea BLOCK IF
2.1.4 Compararea irurilor de caractere
2.1.5 Instruciunea select case
3. Instruciunea DO
3.1 Forma 1
3.2 Forma 2
3.3 Forma 3
3.4 Instruciunea DO WHILE
3.5 Iteraii
3.5.1 Calculul radicalului
3.5.2 Rezolvarea ecuaiilor algebrice neliniare cu metoda Newton
3.5.3 Rezolvarea sistemelor algebrice neliniare de dou ecuaii cu metoda Newton
3.5.4 Rezolvarea ecuaiilor algebrice polinomiale cu coeficieni compleci cu metoda
Newton
4. Dezvoltri n serie
5. Tablouri
5.1 Vectori
5.2 Matrice
5.3 Gauss Seidel
5.4 Alocarea dinamic de memorie (n execuie)
6. Funcii i subprograme
6.1 Clauza contains. Funcii interne
6.2 Funcii externe
6.3 Funcii n complex
6.4 Instruciunea external
6.5 Subrutine
6.5.1 Transmiterea tablourilor la subprograme
6.5.2 Rezolvarea sistemelor de ecuaii algebrice lineare
6.5.3 Calculul valorilor proprii
7. Instruciunea COMMON
7.1 Instruciunea COMMON blank
7.2 Instruciunea COMMON etichetat
7.3 Instruciunea BLOCK DATA
8. Instruciunea INTERFACE
9. Instruciunea MODULE
10. Aplicaii
10.1 Calculul integralelor definite, QUADPACK
10.2 Integrarea ecuaiilor difereniale ordinare, problema Cauchy
10.3 Ecuaia Burgers omogen
Dan Racoi
Elemente de Fortran 95
2
10.4 Ecuaia Poisson
10.5 Ecuaia de potenial pe cerc
10.6 Rezolvarea sistemelor de ecuaii neliniare

0. Introducere
Fortran este un limbaj de programare potrivit n special pentru calculule
numerice i calcule tiinifice. Limbajul dezvoltat plecnd din 1950 a fost utilizat
extensiv n meteorologie, analiza structurilor cu metoda elementelor finite, computational
fluid dynamics (CFD), computational physics and computational chemistry.
Este limbajul de programare utilizat pe supercalculatoare.
Numele limbajului provine de la FORmula TRANslating System.
Versiunile succesive au adugat procesarea irurilor de caractere, block if, do
enddo, do while (FOTRAN 77), programarea modular, array sections, object-based
programming (Fortran 90/95) i object-oriented and generic programming (Fortran 2003).
Prin evoluie limbajul a devenit deosebit de complex. n expunerea succint care
urmeaz s-au avut n vedere n special aspectele legate de metodele numerice i CFD.
Pentru compatibilitate cu bibliotecile de programe existente, NETLIB.ORG, Fortran 90
Codes, etc., se prezint toat gama de instruciuni incluznd instruciunea COMMON i
BLOCK DATA.
Programarea modular (MODULE) permite scrierea de programe compacte i
bine structurate i de aceea este recomandat ca tehnic de programare.
Sunt prezentate o serie de exemple simple (tehnici numerice de baz) dar i
aplicaii mai complexe (ecuaii difereniale cu derivate pariale 2D). Unele programe au
fost pstrate n forma original deoarece sunt algoritmi omologai.
Forma fix a limbajului *.f, *.for are 80 de coloane cu un caracter de continuare
n coloana 6 (diferit de zero) . Zona 1-5 este zon etichet. Zona 7-72 este zon
instruciune. Comentariile ncep cu litera C din coloana 1 sau cu !.
Urmtorul program face parte din biblioteca pppack din NETIB.

c ivex.f
chapter iv. runge example, with cubic hermite interpolation
c from * a practical guide to splines * by c. de boor
integer i,istep,j,n,nm1
real aloger,algerp,c(4,20),decay,divdf1,divdf3,dtau,dx,errmax,g,h
* ,pnatx,step,tau(20)
data step, istep /20., 20/
g(x) = 1./(1.+(5.*x)**2)
print 600
600 format(28h n max.error decay exp.//)
decay = 0.
do 40 n=2,20,2
c choose interpolation points tau(1), ..., tau(n) , equally
c spaced in (-1,1), and set c(1,i) = g(tau(i)), c(2,i) =
c gprime(tau(i)) = -50.*tau(i)*g(tau(i))**2, i=1,...,n.
nm1 = n-1
h = 2./float(nm1)
do 10 i=1,n
tau(i) = float(i-1)*h - 1.
c(1,i) = g(tau(i))
10 c(2,i) = -50.*tau(i)*c(1,i)**2
c calculate the coefficients of the polynomial pieces
c
do 20 i=1,nm1
Dan Racoi
Elemente de Fortran 95
3
dtau = tau(i+1) - tau(i)
divdf1 = (c(1,i+1) - c(1,i))/dtau
divdf3 = c(2,i) + c(2,i+1) - 2.*divdf1
c(3,i) = (divdf1 - c(2,i) - divdf3)/dtau
20 c(4,i) = (divdf3/dtau)/dtau
c
c estimate max.interpolation error on (-1,1).
errmax = 0.
do 30 i=2,n
dx = (tau(i)-tau(i-1))/step
do 30 j=1,istep
h = float(j)*dx
c evaluate (i-1)st cubic piece
c
pnatx = c(1,i-1)+h*(c(2,i-1)+h*(c(3,i-1)+h*c(4,i-1)))
c
30 errmax = amax1(errmax,abs(g(tau(i-1)+h)-pnatx))
aloger = alog(errmax)
if (n .gt. 2) decay =
* (aloger - algerp)/alog(float(n)/float(n-2))
algerp = aloger
40 print 640,n,errmax,decay
640 format(i3,e12.4,f11.2)
stop
end


Forma free a limbajului are extensia *.f90. Caracterul de continuare este &, la
sfritul liniei. Comentariile ncep cu semnul de exclamare !.

! ivex.f90
! chapter iv. runge example, with cubic hermite interpolation
! from * a practical guide to splines * by c. de boor
integer i,istep,j,n,nm1
real aloger,algerp,c(4,20),decay,divdf1,divdf3,dtau,dx,errmax,g,h &
,pnatx,step,tau(20)
data step, istep /20., 20/
g(x) = 1./(1.+(5.*x)**2)
print 600
600 format(28h n max.error decay exp.//)
decay = 0.
do 40 n=2,20,2
! choose interpolation points tau(1), ..., tau(n) , equally
! spaced in (-1,1), and set c(1,i) = g(tau(i)), c(2,i) =
! gprime(tau(i)) = -50.*tau(i)*g(tau(i))**2, i=1,...,n.
nm1 = n-1
h = 2./float(nm1)
do 10 i=1,n
tau(i) = float(i-1)*h - 1.
c(1,i) = g(tau(i))
10 c(2,i) = -50.*tau(i)*c(1,i)**2
! calculate the coefficients of the polynomial pieces
!
do 20 i=1,nm1
dtau = tau(i+1) - tau(i)
divdf1 = (c(1,i+1) - c(1,i))/dtau
divdf3 = c(2,i) + c(2,i+1) - 2.*divdf1
c(3,i) = (divdf1 - c(2,i) - divdf3)/dtau
20 c(4,i) = (divdf3/dtau)/dtau
!
! estimate max.interpolation error on (-1,1).
errmax = 0.
Dan Racoi
Elemente de Fortran 95
4
do 30 i=2,n
dx = (tau(i)-tau(i-1))/step
do 30 j=1,istep
h = float(j)*dx
! evaluate (i-1)st cubic piece
!
pnatx = c(1,i-1)+h*(c(2,i-1)+h*(c(3,i-1)+h*c(4,i-1)))
!
30 errmax = amax1(errmax,abs(g(tau(i-1)+h)-pnatx))
aloger = alog(errmax)
if (n .gt. 2) decay = &
(aloger - algerp)/alog(float(n)/float(n-2))
algerp = aloger
40 print 640,n,errmax,decay
640 format(i3,e12.4,f11.2)
stop
end


1.0 Constante i variabile
In limbajul FORTRAN sunt definite urmtoarele tipuri de constante:
a) Constante de tip ntreg, numere cu semn fr punct zecimal:
12, +54, -321
b) Constante de tip real simpl precizie, numere cu semn i punct zecimal i eventual
exponent:
1.1 , +5.3, 8.31451e0, 9.7654e-3
c) Constante de tip real dubl precizie, numere cu semn i punct zecimal. Exponentul se
noteaz cu litera d (dubl precizie):
3.14d0, 8.31451d0,7.77d+3,6.754d-9.
d) Constante complexe simpl precizie:
(parte_real_simpl_precizie,parte_imaginar_simpl_precizie)
(1.2,-3.4)
e) Constante complexe dubl precizie:
(parte_real_dubl_precizie,parte_imaginar_dubl_precizie)
(+3,1234d2,+0.987d0)
f) Constante de tip logic, .true. pentru adevrat i .false. pentru fals.
g) Constante de tip ir de caractere:
sir1,sirul_doi_de_caractere,Vant Hoff

program constante
implicit none
integer i
real a
real(4) x
real(8) s
double precision f
logical adev,fals
character(4) sir1,sir2
complex z1
complex(8) z2
i=-3
a=1.1
x=3.5e-4
s=8.31451d0
f=0.123456789e-5
adev=.true.
Dan Racoi
Elemente de Fortran 95
5
fals=.false.
sir1='abcd'
sir2="ab'd"
z1=(4.,-3.)
z2=(1.234d-2,0.98765d2)
namelist/lista/i,a,x,s,f,adev,fals,sir1,sir2,z1,z2
write(*,lista)
end program constante

Variabilele n FORTRAN sunt de tipul:
a) Intregi
integer list_variabile
integer(4) list_variabile

integer indice1,indice2,alfa
integer(4) indice3,indice4
b) Reale simpl precizie:

real list_variabile
real(4) list_variabile

real j,i,s1,beta
real(4) gama,lambda_1

c) Reale dubl precizie:

real(8) list_variabile
double precision list_variabile

real(8) w1,w2
double precision k1,h2

d) Complexe simpl precizie:

complex list_variabile
complex(4) list_variabile

complex y2,z2,a1,b2

e) Complexe dubl precizie

complex(8) lista_variabile
double complex lista_variabile

complex(8) zz1,a_y
double complex ew,er

f) Logice

Dan Racoi
Elemente de Fortran 95
6
logical list_variabile

logical predicat1,predicat2
Variabilele de tip logic iau valorile adevrat .true. , i fals .false.

h) Sir de caractere

character(lungime_ir) lista_variabile

character(3) sir1,sir2
character(16) nume,prenume

program constante1 ! declaratii explicite de variabile scalare
implicit none ! se suspenda conventia implicita

integer(kind=2) c1,c2,c3,c4 ; integer*2 c
integer(2) d1,d2,d3,d4 ; integer*2 d
integer(kind=4) e1,e2,e3,e4 ; integer*4 e
integer(4) :: b1,b2,b3,b4 ; integer b
integer a1,a2,a3,a4 ; integer*4 a

real(kind=4) i1,i2,i3,i4 ; real*4 i
real(4) j1,j2,j3,j4 ; real j
real(4) k1,k2,k3,k4 ; real k
real*4 l1,l2,l3,l4 ; real*4 l

real(kind=8) :: di1,di2,di3,di4 ; real*8 di
real(8) dj1,dj2,dj3,dj4 ; real(8) dj
real*8 dk1,dk2,dk3,dk4 ; real*8 dk
real(8) :: de1,de2,de3,de4,de
double precision dl1,dl2,dl3,dl4,dl

complex(kind=4) z1,z2,z3,z4
complex(4) w1,w2,w3,w4 ; complex*8 w
complex :: v1,v2,v3,v4

complex(kind=8) dz1,dz2,dz3,dz4
complex(8) dw1,dw2,dw3,dw4
double complex :: dv1,dv2,dv3,dv4

logical(kind=2) q1,q2,q3,q4
logical(4) r1,r2,r3,r4
logical p1,p2,p3,p4

c1=1 ; c2=2 ; c3=3 ; c4=4_2
c=c1+c2+c3*c4
d1=-1 ; d2=-2 ; d3=-3 ; d4=-4_2
d=d1+d2+d3-d4

e1=1201 ; e2=1202 ; e3=1203 ; e4=1204
e=e1+e2+e3+e4
a1=-1411 ; a2=-1412 ; a3=-1413_4 ; a4=-1414_4
a=a1*a2/a3+a4
namelist/lista1/c1,c2,c3,c4,c,d1,d2,d3,d4,d
write(*,lista1) ; pause 1
namelist/lista2/e1,e2,e3,e4,e,a1,a2,a3,a4,a
write(*,lista2) ; pause 2

i1=1.1001 ; i2=-1.21e-01_4 ; i3=4.12 ; i4=5.6
Dan Racoi
Elemente de Fortran 95
7
i=i1*i2+i3/i4
j1=i1**2 ; j2=i2**2 ; j3=i3**2 ; j4=i4**2 ; j=j1+j2+j3+j4
k1=i1+j1 ; k2=i2+j2 ; k3=i3+j3 ; k4=i4/j4 ; k=k1/k2*k3/k4
l1=0._4 ; l2=0.01_4 ; l3=+0.02e+03_4 ; l4=0.03e-03
l=l1+l2+l3+l4
namelist/lista3/i1,i2,i3,i4,i,j1,j2,j3,j4,j
namelist/lista4/k1,k2,k3,k4,k,l1,l2,l3,l4,l
write(*,lista3) ; pause 3
write(*,lista4) ; pause 4

di1=1._8 ; di2=2._8 ; di3=3._8 ; di4=4.d0
di=di1/di2+di3**di4
dj1=-0.00123_8 ; dj2=.005_8 ; dj3=+06d-3 ; dj4=0.d0
dj=abs(dj1)+abs(dj2)+abs(dj3)+abs(dj4)
dk1=dble(k1)
dk2=dble(k2)
dk3=dble(k3)
dk4=dble(k4)
dk=dk1+dk2+dk3+dk4
de1=dk1*dk2 ; de2=dk2-dk3 ; de3=(dk1-dk2)/(dk3+dk4)
de4=de1*de2+de3
de=de1-de2-de3+de4
namelist/lista5/di1,di2,di3,di4,di,dj1,dj2,dj3,dj4,dj
namelist/lista6/dk1,dk2,dk3,dk4,dk,de1,de2,de3,de4,de
write(*,lista5) ; pause 5
write(*,lista6) ; pause 6

z1=(1.,2.) ; z2=(-1.e03_4,7.01_4)
z3=cmplx(i1,i2) ; z4=cmplx(i3,i4)
w1=conjg(z1) ;w2=conjg(z2); w3=z1+z2-(z3-z4) ; w4=abs(w3)
w=w1/w2+w2*w3
namelist/lista7/z1,z2,z3,z4,w1,w2,w3,w4,w
write(*,lista7) ; pause 7
j1=real(w) ; j2=imag(w)
write(*,*)'partea reala w=',j1
write(*,*)'partea imaginara w=',j2
write(*,*)' w=',w
v1=z1+w1 ; v2=z2-w2 ; v3=z3/w3 ; v4=z4*w4
namelist/lista8/v1,v2,v3,v4
write(*,lista8) ; pause 8

q1=.true. ; q2=.false.
q3=c1<c2 ; q4=c3>c4
r1=dk1<=dk2 ; r2=q3.and.q4 ; r3=.not.r2 ; r4=q3.or.q4
p1=r1.and.r2 ; p2=.not.(r1.or.r2) ; p3=p1.and.p2
p4=p1.or.p2
namelist/lista9/q1,q2,q3,q4,r1,r2,r3,r4
write(*,lista9) ; pause 9
namelist/lista10/p1,p2,p3,p4
write(*,lista10)
end program constante1

1.1 Operaii algebrice simple

Programul p1 utilizeaz limbajul FORTRAN pentru a operaii algebrice
elementare n real i complex. Se utilizeaz convenia implicit de declarare a
variabilelor. Variabilele care ncep cu literele (a-h,o-z) sunt de tip real simpl precizie.
Variabilele care ncep cu literele i,j,k,l,m sunt de tip ntreg.

program p1
!
Dan Racoi
Elemente de Fortran 95
8
! Calculator stiintific 1
!
! Conventia implicita de declarare a variabilelor
! Variabilele care incep cu literele (a-h,o-z) sunt reale
! simpla precizie.
! Variabilele care incep cu literele i,j,k,l,m,m sunt de tip
! intreg.
!
complex z1,z2,sc,dc,pc,rc,puc
write(*,*)'program p1'
x=-1.123
y=6.764
suma=x+y
diferenta=x-y
produs=x*y
raport=x/y
n=2
putere1=x**n
putere2=y**x
namelist/lista1/x,y,suma,diferenta,produs,raport,putere1,putere2
write(*,lista1)
x1=-2. ; y1=1.4
x2= 9.1 ; y2=0.7
z1=cmplx(x1,y1) ! z1=x1+sqrt(-1)*y1
z2=cmplx(x2,y2) ! z2=x2+sqrt(-1)*y2
!
! Operatii aritmetice simple in complex
!
sc=z1+z2
dc=z1-z2
pc=z1*z2
rc=z1/z2
rc_r=real(rc) ! partea reala
rc_i=imag(rc) ! partea imaginara
puc=z1**n
namelist/lista2/z1,z2,sc,dc,pc,rc,rc_r,rc_i,puc
write(*,lista2)
end program p1

Programul p1e utilizeaz limbajul FORTRAN pentru a operaii algebrice
elementare n real i complex. Se utilizeaz convenia explicit de declarare a
variabilelor.

program p1e
!
! Calculator stiintific 1
!
! Conventia explicita de declarare a variabilelor
!
implicit none
real x,y,suma,diferenta,produs,raport,putere1,putere2
integer n
real x1,y1,x2,y2
complex z1,z2,sc,dc,pc,rc,puc
real rc_r,rc_i
write(*,*)'program p1e'
x=-1.123
y=6.764
suma=x+y
diferenta=x-y
produs=x*y
raport=x/y
Dan Racoi
Elemente de Fortran 95
9
n=2
putere1=x**n
putere2=y**x
namelist/lista1/x,y,suma,diferenta,produs,raport,putere1,putere2
write(*,lista1)
x1=-2. ; y1=1.4
x2= 9.1 ; y2=0.7
z1=cmplx(x1,y1) ! z1=x1+sqrt(-1)*y1
z2=cmplx(x2,y2) ! z2=x2+sqrt(-1)*y2
!
! Operatii aritmetice simple in complex
!
sc=z1+z2
dc=z1-z2
pc=z1*z2
rc=z1/z2
rc_r=real(rc) ! partea reala
rc_i=imag(rc) ! partea imaginara
puc=z1**n
namelist/lista2/z1,z2,sc,dc,pc,rc,rc_r,rc_i,puc
write(*,lista2)
end program p1e

Programul p2 arat utilizarea funciilor formul (statement functions).
Funciile formul corespund funciilor din analiza matematic (funcii reale de
una sau mai multe variabile reale sau complexe).

nume_funcie(argumente_formale)=expresie_aritmetic

In funcia formul pe lng variabile se pot utiliza constante definite n program
nainte de apelul funciei.
Apelul funciei se face prin nume i cu argumentele efective.

valoare=nume_funcie(argumente_efective)

Exist o coresponden biunivoc ntre tipul i numrul argumentelor formale i efective.
In cazul n care funcia este mai complex se utilizeaz clauza contains sau
funcii externe.
Programul p2 calculeaz funciile:
) (
) ( ' ) ( ) ( ) ( '
) ( '
) (
) (
) (
) cos( ) ( '
) sin( ) (
2 ) ( '
) (
2
2
2
2 1
x g
x g x f x g x f
x h
x g
x f
x h
x x g
x x g
x a x f
x a a x f

=
=
=
=
=
+ =



Se utilizeaz convenia implicit de declarare a variabilelor. n programul p2e se
utilizeaz convenia explicit de declarare a variabilelor.
Dan Racoi
Elemente de Fortran 95
10

program p2
!
! Statement function
!
f(x)=a1+a2*x**2
fp(x)=2.*a2*x ! derivata functiei f(x)
g(x)=sin(pi*x)
gp(x)=pi*cos(pi*x) ! derivata functiei g(x)
h(x)=f(x)/g(x)
hp(x)=(fp(x)*g(x)-f(x)*gp(x))/g(x)**2 ! derivata functiei h(x)

write(*,*)'program p2'

a1=1.21 ; a2=-1.32e-1 ; pi=4.*atan(1.)
x=1.1

write(*,*)'x=',x,' f(x)=',f(x),' fp(x)=',fp(x)
write(*,*)'x=',x,' g(x)=',g(x),' gp(x)=',gp(x)
write(*,*)'x=',x,' h(x)=',h(x),' hp(x)=',hp(x)

end program p2

program p2e
!
! Statement function
!
implicit none
real x,f,fp,g,gp,h,hp
real a1,a2,pi

f(x)=a1+a2*x**2
fp(x)=2.*a2*x ! derivata functiei f(x)
g(x)=sin(pi*x)
gp(x)=pi*cos(pi*x) ! derivata functiei g(x)
h(x)=f(x)/g(x)

hp(x)=(fp(x)*g(x)-f(x)*gp(x))/g(x)**2 ! derivata functiei h(x)

write(*,*)'program p2'

a1=1.21 ; a2=-1.32e-1 ; pi=4.*atan(1.)
x=1.1

write(*,*)'x=',x,' f(x)=',f(x),' fp(x)=',fp(x)
write(*,*)'x=',x,' g(x)=',g(x),' gp(x)=',gp(x)
write(*,*)'x=',x,' h(x)=',h(x),' hp(x)=',hp(x)

end program p2e

Programul p3 calculeaz soluia unui sistem de dou ecuaii algebrice liniare:
)
`

=
)
`

2
1
2
1
22 21
12 11
b
b
x
x
a a
a a

cu metoda Cramer. Se calculeaz determinanii de ordinul doi:
Dan Racoi
Elemente de Fortran 95
11
2 21
1 11
2
22 2
12 1
1
21 12 22 11
22 21
12 11
0
b a
b a
d
a b
a b
d
a a a a
a a
a a
d
=
=
= =

Se presupune c determinantul d
0
este diferit de zero.

0
2
2
0
1
1
d
d
x
d
d
x
=
=


program p3
!
! Rezolva un sistem de doua ecuatii algebrice liniare cu metoda Cramer
!
real a11,a12,b1,x1
real a21,a22,b2,x2

det2(a,b,c,d)=a*d-b*c ! determinant de ordinul doi
!
! Coeficientii sistemului
!
a11= 1.2e0 ; a12= 2.3e0 ; b1=5.e-2
a21=-0.7e1 ; a22= 9.3e0 ; b2=4.e0

write(*,*)'program p3'
!
! Calculul determinantilor de ordin doi
!
d0=det2(a11,a21,a12,a22)
if(d0 == 0.)stop 'sistem singular'
d1=det2(b1 ,b2 ,a12,a22)
d2=det2(a11,a21,b1 ,b2 )
!
! Cramer
!
x1=d1/d0 ; x2=d2/d0
!
! Verificarea solutiei
!
v1=a11*x1+a12*x2-b1
v2=a21*x1+a22*x2-b2

namelist/l1/a11,a12,b1,a21,a22,b2,x1,x2,v1,v2
write(*,l1)
end program p3

Programul p4 calculeaz soluia unui sistem de trei ecuaii algebrice liniare cu
metoda Cramer. Se utilizeaz convenia implicit de declarare a variabilelor. In
programul p4e se utilizeaz convenia explicit de declarare a variabilelor.

Dan Racoi
Elemente de Fortran 95
12

(
(
(

3
2
1
3
2
1
33 32 31
23 22 21
13 12 11
b
b
b
x
x
x
a a a
a a a
a a a


3 23 31
2 22 21
1 12 11
3
33 3 31
23 2 21
13 1 11
2
33 32 3
23 22 2
13 12 1
1
33 32 31
23 22 21
13 12 11
0
b a a
b a a
b a a
d
a b a
a b a
a b a
d
a a b
a a b
a a b
d
a a a
a a a
a a a
d
=
=
=
=

Se presupune c determinantul d
0
este diferit de zero.
Determinanii de ordin trei se calculeaz prin dezvoltare dup prima linie:
23 22
13 12
31
) 3 1 (
33 32
13 12
21
1 2
33 32
23 22
11
1 1
33 32 31
23 22 21
13 12 11
) 1 ( ) 1 ( ) 1 (
a a
a a
a
a a
a a
a
a a
a a
a
a a a
a a a
a a a
+ + +
+ + =
Se definete o funcie formul pentru calculul determinantului de ordinul doi si o
funcie formul pentru calculul determinantului de ordinul trei care utilizeaz funcia
formul a determinantului de ordin 2.
Soluiile se calculeaz cu regula lui Cramer:
0
3
3
0
2
2
0
1
1
d
d
x
d
d
x
d
d
x
=
=
=


program p4
!
! Rezolva un sistem de trei ecuatii algebrice liniare
! cu regula lui Cramer
!

det2(a,b,c,d)=a*d-b*c ! determinant de ordinul 2
!
! Determinant de ordinul trei (dezvoltare dupa prima linie)
Dan Racoi
Elemente de Fortran 95
13
!
det3(a11,a21,a31,a12,a22,a32,a13,a23,a33)=
$ +(-1.e0)**(1+1)*a11*det2(a22,a32,a23,a33)
$ +(-1.e0)**(2+1)*a21*det2(a12,a32,a13,a33)
$ +(-1.e0)**(3+1)*a31*det2(a12,a22,a13,a23)
!
! Coeficientii sistemului de ecuatii liniare
!
a11=-1.e0 ; a12=+1.e0 ; a13=3.e0 ; b1=4.e0
a21=-2.e0 ; a22=-3.e0 ; a23=5.e0 ; b2=1.e0
a31= 4.e0 ; a32=-6.e0 ; a33=1.1e0 ; b3=0.9e0
!
! Calculul determinantilor
!
d0=det3(a11,a21,a31,a12,a22,a32,a13,a23,a33)
if(d0.eq.0.)stop 'sistem singular'
d1=det3(b1 ,b2 ,b3 ,a12,a22,a32,a13,a23,a33)
d2=det3(a11,a21,a31,b1 ,b2 ,b3 ,a13,a23,a33)
d3=det3(a11,a21,a31,a12,a22,a32,b1 ,b2 ,b3 )
!
! Cramer
!
x1=d1/d0 ; x2=d2/d0 ; x3=d3/d0
!
! Verificarea solutiei
!
v1=a11*x1+a12*x2+a13*x3-b1
v2=a21*x1+a22*x2+a23*x3-b2
v3=a31*x1+a32*x2+a33*x3-b3

namelist/l1/a11,a12,a13,b1,a21,a22,a32,b2,a31,a32,a33,b3,
# x1,x2,x3,v1,v2,v3
write(*,l1)
end program p4


program p4e
!
! Rezolva un sistem de trei ecuatii algebrice liniare
! cu regula lui Cramer
!
implicit real(8) (a-h,o-z) ! dubla precizie

det2(a,b,c,d)=a*d-b*c ! determinant de ordinul 2
!
! Determinant de ordinul trei (dezvoltare dupa prima linie)
!
det3(a11,a21,a31,a12,a22,a32,a13,a23,a33)=
$ +(-1.d0)**(1+1)*a11*det2(a22,a32,a23,a33)
$ +(-1.d0)**(2+1)*a21*det2(a12,a32,a13,a33)
$ +(-1.d0)**(3+1)*a31*det2(a12,a22,a13,a23)
!
! Coeficientii sistemului de ecuatii liniare
!
a11=-1.d0 ; a12=+1.d0 ; a13=3.d0 ; b1=4.d0
a21=-2.d0 ; a22=-3.d0 ; a23=5.d0 ; b2=1.d0
a31= 4.d0 ; a32=-6.d0 ; a33=1.1d0 ; b3=0.9d0
!
! Calculul determinantilor
!
d0=det3(a11,a21,a31,a12,a22,a32,a13,a23,a33)
if(d0.eq.0.)stop 'sistem singular'
d1=det3(b1 ,b2 ,b3 ,a12,a22,a32,a13,a23,a33)
Dan Racoi
Elemente de Fortran 95
14
d2=det3(a11,a21,a31,b1 ,b2 ,b3 ,a13,a23,a33)
d3=det3(a11,a21,a31,a12,a22,a32,b1 ,b2 ,b3 )
!
! Cramer
!
x1=d1/d0 ; x2=d2/d0 ; x3=d3/d0
!
! Verificarea solutiei
!
v1=a11*x1+a12*x2+a13*x3-b1
v2=a21*x1+a22*x2+a23*x3-b2
v3=a31*x1+a32*x2+a33*x3-b3

namelist/l1/a11,a12,a13,b1,a21,a22,a32,b2,a31,a32,a33,b3,
# x1,x2,x3,v1,v2,v3
write(*,l1)
end program p4e

2.1 Instruciunea IF (dac)
Instruciunea IF este utilizat pentru comparaii.
2.1.1 Instruciunea IF aritmetic
if(expresie)eticheta_1,eticheta_2,eticheta_3

Dac valoarea numeric a expresiei este mai mic dect zero se face salt la
eticheta_1.
Dac valoarea numerica a expresiei este egal cu zero se face salt la eticheta_2.
Dac valoarea numeric a expresiei este mai mare dect zero se face salt la
eticheta 3.
Instruciunea If aritmetic nu este recomandat. Se prefer instruciunea if logic.

program if1 ! instructiunea if aritmetic
real a,b,c,delta
a=1.1 ; b=1.3 ; c=4.5
delta=b**2-4.*a*c
if(delta)10,20,30
10 continue
write(*,*)'delta negativ'
goto 40
20 continue
write(*,*)'delta egal cu zero'
goto 40
30 continue
write(*,*)"delta mai mare decat zero"
40 continue
end program if1

2.1.2 Instruciunea IF logic
O expresie relaional const n dou sau mai multe expresii a caror valoare este
comparat pentru a determina dac relaia specificat de catre operatorii logici este
satisfcut.
Operatorii relaionali sunt:
.lt. sau < mai mic
.le. sau <= mai mic sau egal
.eq. sau == egal
.ne. sau /= neegal
Dan Racoi
Elemente de Fortran 95
15
.gt. sau > mai mare
.ge. sau >= mai mare sau egal
Operatorii logici uzuali sunt:
.and. i logic
.or. sau logic
.not. negaie
.eqv. echivalen logic
In cazul operatorului .and. expresia este adevrat dac att expresia_1 ct i expresia_2
sunt adevrate.
Tabela de adevr a propoziiei (.not.p) este:
p .not.p
.true. .false.
.false. .true.

Tabelela de adevr a propoziiei (p.and.q) este urmtoarea:

p q p.and.q
.true. .true. .true.
.true. .false. .false.
.false. .true. .false.
.false. .false. .false.

Tabela de adevr a propoziiei (p.or.q) este urmtoarea:

p q p.or.q
.true. .true. .true.
.true. .false. .true.
.false. .true. .true.
.false. .false. .false.

Tabela de adevr a propoziiei (p.eqv.q) este urmtoarea:

p q p.eqv.q
.true. .true. .true.
.true. .false. .false.
.false. .true. .false.
.false. .false. .true.

logical predicat,expresie_1,expresie_2
.
.
expresie_1=a.lt.5
. .
.
expresie_2= b.ge.h

Dan Racoi
Elemente de Fortran 95
16
predicat=expresie_1. and. expresie_2

Instruciunea if logic este urmtoarea:

if(expresie)intruciune_atribuire

if(a. gt. 0.) x=1.3

Dac expresia este adevrat se execut instruciunea de atribuire. In caz contrar
se trece la urmtoarea instruciune.

if(expresie)goto etichet

if(r. le. 9.)goto 15

Dac expresia este adevrat se face salt la instruciunea care are eticheta
respectiv.
program if2 ! if logic
real a,b,c,delta
!
! Coeficientii ecuatiei de gradul doi
!
a=-2.1 ; b=-4.2 ; c=5.6e0
delta=b*b-4.*a*c
if(delta < 0.)write(*,*)'delta negativ'
if(delta == 0.)write(*,*)'delta egal cu zero'
if(delta > 0.)write(*,*)'delta mai mare decat zero'
if(delta < 0.)goto 55
write(*,*)'Radacini reale'
x1=(-b+sqrt(delta))/(2.*a)
if(delta > 0.)x2=(-b+sqrt(delta))/(2.*a)
write(*,*)'x1=',x1,'x2=',x2
stop
55 continue
write(*,*)'radacini complexe'
x1r=-b/(2.*a) ; x1c=+sqrt(-delta)/(2.*a)
x2r=-b/(2.*a) ; x2c=-sqrt(-delta)/(2.*a)
end program if2

2.1.3 Instruciunea BLOC IF

Sintaxa instruciunii bloc if este urmtoarea:

if(expresie_1)then
bloc _1
elseif(expresie_2)then
bloc_2
elseif(expresie_3)then
bloc_3

elseif(expresie_n)then
bloc_n
Dan Racoi
Elemente de Fortran 95
17
else
bloc_else
endif

Dac expresia_1 este adevrat se execut blocul 1 de instruciuni i se sare la
instruciunea care urmeaz dup endif.
Dac expresia_n este adevrat se execut blocul n de instruciuni i se sare la
instruciunea care urmeaz dup endif.
Dac toate expresiile sunt false se execut blocul else (dac exist).
De exemplu:

if(condiie_logic)then
Bloc de instruciuni (se execut dac condiia logic este adevrat)
endif

if(condiie_logic)then
Bloc de instruciuni_1 (se execut dac condiia logic este adevrat)
else
Bloc de instruciuni_2 (se execut dac condiia logic este fals)
endif

program if3
real a,b,c,delta
logical predicat1
a=0.9 ; b=1.4 ; c=8.e-2
delta=b*b-4.*a*c
predicat1=delta < 0.
if(predicat1)then
write(*,*)'delta negativ'
elseif(delta == 0.)then
write(*,*)'delta egal cu zero'
else
write(*,*)'delta mai mare decat zero'
endif
end program if3



program if4
real a,b,c
logical predicat1,predicat2,predicat3
a=-4.e3 ; b=9.5 ; c=45.
predicat1=a > 0.
predicat2=(a<0.).or.(c<0.)
predicat3=((b+c)<0.).and.(b>0.)
namelist/lista/a,b,c,predicat1,predicat2,predicat3
write(*,lista)
if(predicat1)then
write(*,*)'conditia 1 este adevarata, a>0.'
elseif(predicat2)then
write(*,*)'conditia 2 este adevarata,(a<0.).or.(c<0.)'
elseif(predicat3)then
write(*,*)'conditia 3 este adevarata,((b+c)<0.).and.(b>0.)'
elseif(a*b*c>9.)then
Dan Racoi
Elemente de Fortran 95
18
write(*,*)'a*b*c>9.'
else
write(*,*)'Toate propozitiile logice sunt false'
endif
end program if4

2.1.4 Compararea irurilor de caractere

irurile de caractere se compar lexical definind operatorii:
variabila_logic=lle(sir1,sir2) mai mic sau egal lexical
variabila_logic=llt(sir1,sir2) mai mic lexical

variabila_logic=lgt(sir1,sir2) mai mare egal lexical
variabila_logic=lge(sir1,sir2) mai mare sau egal lexical

logical l1,l2
l1=lle(abc,abd) return .true.

2.1.5 Instruciunea select case

Instruciunea select case are urmtoarea sintax:

select case(expr)
case(case_value_1)
block_1
case(case_value_2)
block_2
.
.
.
case default
block_default
end select

Se evalueaz expresia (expr). Rezultatul, case_index se compar cu fiecare
case_value pentru a gsi o concordan (poate fi numai una). Cnd o concordan exist
se execut blocul respectiv i se sare la instruciunea de dup end select.
Dac expresia este logic atunci:
case_index .eqv. case_value
Dac expresia este de tip numeric sau de tip caracter atunci:
case_index = = case_value
Exemplu:
integer i
select case(i)
case(:-1) ! i<= -1
index = -1
case(0) ! i=0
index=0
Dan Racoi
Elemente de Fortran 95
19
case(1:) ! i>= 1
end select

Exemplu:

select case (itest.eq.1)
case(.true.)
call subprogram1
case(.false.)
call subprogram2
end select

Exemplu:

select case(itest)
case(1)
call sub1
case(2)
call sub2
case default
call subd
end select


Interval A match case
low: case_index>=low
:high case_index<=high
low:high low<=case_index<=high


program select_case
implicit none
integer numar
real a,b
character(1) operatie

write(*,*)'Introduceti un numar (intreg)'
read(*,*)numar


select case(numar)
case(1,3,5,7:9,12)
write(*,*)'Numarul este 1 sau 3 sau 5 sau 7,8,9 sau 12'
case default
write(*,*)'Numarul nu este in secventa programata'
end select

write(*,*)'Introduceti doua numere reale:'
read(*,*)a,b
write(*,*)'Intoduceti operatia aritmetica:'
read(*,'(a)')operatie

Dan Racoi
Elemente de Fortran 95
20
select case(operatie)
case('+')
write(*,*)'Suma este:',a+b
case('-')
write(*,*)'Diferenta este:',a-b
case('*')
write(*,*)'Produsul este:',a*b
case('/')
write(*,*)'Raportul este:',a/b
case default
write(*,*)'Operatie nedefinita'
end select

end program select_case


3. Instruciunea DO
Instruciunea DO este utilizat pentru realizarea ciclurilor.
3.1 Forma 1
Sintaxa instruciunii este:
do etichet variabila_ntreag = start , final, increment
bloc_instruciuni
etichet continue
Variabila ntreag ia valori de la start pn la final fiind incrementat cu valoarea
increment. Dac variabila increment nu este specificat se consider implicit valoarea 1.
Limbajul Fortran accept i variabile de tip real pentru variabilele start,final i
increment.
Instruciunea se execut de:
max(int(final-start+increment)/increment),0)
ori.
3.2 Forma 2
Sintaxa instruciunii este:
do etichet variabil_ntreag=start, final, increment
bloc instruciuni
eticheta enddo
Eticheta este opional.
do variabil_ntreag=start, final, increment
bloc instruciuni
enddo
Variabila ntreag ia valori de la start pn la final fiind incrementat cu valoarea
increment.
Ieirea forat dintr-un ciclu do se face cu instruciunea exit.

do variabil_ntreag=start, final, increment
bloc instructiuni
if(conditie_logica)exit
enddo

Eliminarea unor instruciuni din ciclu se face cu instruciunea cycle.

Dan Racoi
Elemente de Fortran 95
21
do var=start,final,increment
bloc1
if(conditie_logic) cycle
bloc2
enddo

Dac condiia logic este adevrat blocul 2 de instruciuni nu se mai execut.

3.3 Forma 3

Sintaxa instruciunii este:

do
bloc instruciuni
if(condiie_logic)exit
enddo

Ieirea din ciclu se face cu instruciunea exit.

3.4 Instruciunea do while

Sintaxa instruciunii este:

do eticheta while(condiie_logic)
bloc instruciuni
eticheta enddo

Ciclul se execut ct timp condiia logic este adevrat. Eticheta este opional:

do while(condiie_logic)
bloc instruciuni
enddo

program do1
!
! Cicluri do elementare
!
implicit real(8) (a-h,o-z) ! dubla precizie
do 10 i=1,5
write(*,*)'i=',i
10 continue
write(*,*)

do i=1,6
write(*,*)'i=',i
enddo
write(*,*)

do i=-10,14,2
write(*,*)'i=',i
enddo
Dan Racoi
Elemente de Fortran 95
22

write(*,*)
n=10
do i=n,1,-1
write(*,*)'i=',i
enddo
write(*,*)

do 12345 k=1,15,3
write(*,*)'k=',k
12345 enddo

write(*,*)
j=0.
do while(j<5)
write(*,*)'j=',j
j=j+1
enddo

write(*,*)
x=10.d0
do while(x>0.d0)
write(*,*)'x=',x
x=x-1.d0
enddo

write(*,*)
x=-5.1d0
do
x=x+1.5d0
if(x<0.d0)cycle

write(*,*)'x=',x,' radical x=',sqrt(x)

if(x>20.d0)exit

enddo
end program do1

3.5 Iteraii
Numeroi algoritmi numerici sunt iterativi. Limitai ntotdeauna numrul de
iteraii pentru a evita buclele infinite.

3.5.1 Calculul radicalului

Calculul radicalului se bazeaz pe rezolvarea ecuaiei neliniare:
y y f
x y y f
x y
2 ) ( '
0 ) (
2
=
= =
=

irul iterativ Newton este:
|
|

\
|
+ = =
+
k
k
k
k
k k
y
x
y
y f
y f
y y 5 . 0
) ( '
) (
1
, k=0,1,
Dup cum se observ calculul radicalului se reduce la operaii aritmetice
elementare.
Aproximaia iniial este:
Dan Racoi
Elemente de Fortran 95
23
2
0
x
y =
Calculul se oprete dac:
< ) (
k
y f
Numrul de iteraii este limitat de o valoare maxim pentru a evita intrarea ntr-o
bucl infinit.

program radical
implicit real(8) (a-h,o-z)
integer,parameter :: iter_max=10
real(8) :: eps=1.d-8
logical succes
fy(y)=y**2-x
x=9.d0
y=x/2.d0 ! aproximatia initiala Newton
f=fy(y)
write(*,'(/,a,/)')'Iteratiile Newton'
succes=.false.
iter=0
write(*,*)iter,y,f
do while((iter<iter_max).and.(f>eps))
iter=iter+1
y=0.5d0*(y+x/y)
f=fy(y)
write(*,*)iter,y,f
enddo
write(*,*)
if(iter<iter_max)succes=.true.
if(succes)then
write(*,*)'x=',x,' radical(x)=',y
else
write(*,*)'Metoda nu converge'
endif
end program radical

3.5.2 Rezolvarea ecuaiilor algebrice neliniare cu metoda Newton

Metoda Newton pentru rezolvarea ecuaiei neliniare:
0 ) ( = x f

este:
) ( '
) (
1
k
k
k k
x f
x f
x x =
+
k=0,1,2,
Variabila k este contorul de iteraii. Pentru pornirea iteraiilor se alege o valoare
iniial x
0
. Metoda este convergent n apropierea soluiei. Iteraiile sunt oprite dac
modulul funciei este mai mic dect o valoare impus:
1
) ( <
k
x f
sau dac diferena ntre dou valori x este mai mic dect o valoare impus:
2
1
<
+ k k
x x
Numrul de iteraii este limitat la valoarea n
max
pentru a evita o bucl infinit.
Considerm ecuaia neliniar:
Dan Racoi
Elemente de Fortran 95
24
) cos( ) exp( ) ( '
) sin( ) exp( ) (
) sin( ) exp(
x x x f
x x x f
x x
=
=
=

Programul pentru rezolvarea ecuaiei neliniare este prezentat n continuare.

program iteratii_1
implicit real(8) (a-h,o-z)
parameter (eps1=1.d-5)
parameter (eps2=1.d-6)
integer,parameter :: nmax=25 ! numarul maxim de iteratii
fct(x)=exp(-x)-sin(x) ! functia
dfct(x)=-exp(-x)-cos(x) ! derivata
write(*,*)'Iteratiile metodei Newton'
x=0.1d0 ! aproximatia initiala
do iter=0,nmax
f=fct(x)
write(*,*)iter,x,f
if(abs(f)<eps1)goto 33
df=dfct(x)
dx=f/df
if(abs(dx)<eps2)goto 33
x=x-dx
enddo
write(*,*)'Metoda nu converge in nmax iteratii'
stop
33 continue
write(*,*)
write(*,*)'Solutia ecuatiei este =',x
write(*,*)'Valoarea functiei este=',fct(x)
end program iteratii_1

3.5.3 Rezolvarea sistemelor algebrice neliniare de dou ecuaii cu metoda Newton

Metoda Newton pentru rezolvarea sistemului de ecuaii neliniare:
0 ) , (
0 ) , (
=
=
y x g
y x f

este:
)
`

=
)
`

(
(
(
(

) , (
) , (
) , ( ) , (
) , ( ) , (
k k
k k
k k k k
k k k k
y x g
y x f
y
x
y
y x g
x
y x g
y
y x f
x
y x f

y y y
x x x
k k
k k
+ =
+ =
+
+
1
1
k=0,1,
Indicele k este contorul de iteraii.
Aproximaia iniial este determinat minimiznd funcia de dou variabile:
y x
d s
b y b
a x a
y x g y x f y x
< <
< <
+ = ) , ( ) , ( ) , (
2 2


prin explorarea domeniului n care se caut soluia.
Dan Racoi
Elemente de Fortran 95
25
Derivatele pariale sunt calculate numeric cu formule de derivare cu diferene
centrale:
h
h y x f h y x f
y
f
h
y h x f y h x f
x
f
2
) , ( ) , (
2
) , ( ) , (
+
=

+
=



h
h y x g h y x g
y
f
h
y h x g y h x g
x
g
2
) , ( ) , (
2
) , ( ) , (
+
=

+
=


Iteraiile sunt oprite dac este ndeplinit condiia:
< + y x
Numrul maxim de iteraii este limitat pentru a nu se intra ntr-o bucl infinit.

program iteratii_2
implicit none
real(8) x,y,f,g,fct,gct,det2
real(8) :: al=-10.d0 ! marginea stanga a intervalului pentru x
real(8) :: ad=+10.d0 ! marginea dreapta a intervalului pentru x
real(8) :: bl=-10.d0 ! marginea stanga a intervalului pentru y
real(8) :: bd=+10.d0 ! marginea dreapta a intervalului pentru y
integer,parameter :: n=10 ! numarul de intervale pe x si y
real(8) :: hx ! pas de discretizare pe axa x
real(8) :: hy ! pas de discretizare pe axa y
real(8) :: fmin ! valoarea minima a functiei fct(x)**2+gct(x)**2
real(8) :: xs ! abscisa punctului de minim
real(8) :: ys ! ordonata punctului de minim
real(8) d0,d1,d2
real(8) dx,dy
real(8) a11,a12,a21,a22
integer iter,i,j
real(8) pas,dfdx,dfdy,dgdx,dgdy
integer,parameter :: iter_max=15

!
! Sistemul de ecuatii neliniare
!
fct(x,y)=x**2-3.d0*x+2.d0*y-0.01d0*exp(y)
gct(x,y)=x-0.98d0*y

det2(a11,a21,a12,a22)=a11*a22-a12*a21 ! determinantul de ordin doi
write(*,'(a,/)')"program iteratii_2"
hx=(ad-al)/(n-1) ! pasul de discretizare pe axa x
hy=(bd-bl)/(n-1) ! pasul de discretizare pe axa y
fmin=1.d77
!
! Se determina minimul functiei fct(x,y)**2+gct(x,y)**2 prin explorarea
! domeniului al<x<ad, bl<y<bd
!
do i=1,n-1
do j=1,n-1
x=al+(i-1)*hx
y=bl+(j-1)*hy
f=fct(x,y)**2 + gct(x,y)**2
Dan Racoi
Elemente de Fortran 95
26
if(f<fmin)then
fmin=f
xs=x ; ys=y
endif
enddo
enddo
if(fmin.eq.1.d77)stop 'nelocalizare 2D'
x=xs ; y=ys ! aproximatiile initiale Newton
pas=1.d0/512.d0 ! pas de derivare numerica
write(*,'(/,a,/)')'Iteratiile metodei Newton'
write(*,*)' x y f g'
do iter=1,iter_max
f=fct(x,y) ; g=gct(x,y)
write(*,'(i3,2x,4(g13.6,1x))')iter,x,y,f,g
if(abs(f)+abs(g) < 1.d-6)go to 33
!
! Derivatele partiale ale functiei fct(x,y)
!
dfdx=(fct(x+pas,y)-fct(x-pas,y))/(pas+pas)
dfdy=(fct(x,y+pas)-fct(x,y-pas))/(pas+pas)
!
! Derivatele partiale ale functiei gct(x,y)
!
dgdx=(gct(x+pas,y)-gct(x-pas,y))/(pas+pas)
dgdy=(gct(x,y+pas)-gct(x,y-pas))/(pas+pas)
!
! Rezolvarea unui sistem liniar de gradul doi cu metoda Cramer
!
d0=det2(dfdx,dgdx,dfdy,dgdy)
if(d0.eq.0.d0)stop 'Jacobian singular'
d1=det2(-f,-g,dfdy,dgdy)
d2=det2(dfdx,dgdx,-f,-g)
dx=d1/d0 ! corectiile Newton
dy=d2/d0
if(abs(dx)+abs(dy) < 1.d-6)goto 33
x=x+dx ! iteratiile Newton
y=y+dy
enddo
write(*,*)'neconvergenta Newton 2D'
stop

33 write(*,'(/,a,f13.6,f13.6)')'Solutia =',x,y
write(*,'(a,f13.6,f13.6)')'Functiile=',fct(x,y),gct(x,y)
66 continue
end program iteratii_2

3.5.4 Rezolvarea ecuaiilor algebrice polinomiale cu coeficieni compleci cu metoda
Newton

Rezolvarea ecuaiilor algebrice polinomiale cu coeficieni n complex de reduce la
rezolvarea unui sistem de dou ecuaii algebrice neliniare n real. Fie ecuaia:
C a a a a a
z a z a z a z a a z h

= + + + + =
5 4 3 2 1
4
5
3
4
2
3 2 1
, , , ,
0 ) (

este echivalent cu sistemul de ecuaii algebrice:
0 )) ( Im( ) , (
0 )) ( Re( ) , (
= =
= =
z h y x g
z h y x f

Conform teoremei fundamentale a algebrei sistemul de dou ecuaii are 4 soluii
(o ecuaie de gradul patru are patru soluii complexe).
Dan Racoi
Elemente de Fortran 95
27

program iteratii_3
!
! Calculeaza o solutie complexa a ecuatiei algebrice (polinomiale)
! a1+a2*z+a3*z**2+a4*z**3+a5*z**4=0
!
implicit real(8) (a-h,o-z)
integer,parameter :: iter_max=15
complex(8) z,fz
complex a1,a2,a3,a4,a5
!
! Ecuatia algebrica polinomiala in complex
!
fz(z)=a1+a2*z+a3*z**2+a4*z**3+a5*z**4
!
! Sistemul de doua ecuatii neliniare echivalent
!
fct(x,y)=real(fz(cmplx(x,y)))
gct(x,y)=imag(fz(cmplx(x,y)))

det2(a11,a21,a12,a22)=a11*a22-a12*a21 ! determinantul de ordin doi
!
! Coeficientii complecsi ai ecuatiei algebrice
!
a1=(1.0d0, 0.45d0)
a2=(2.0d0, 0.88d0)
a3=(3.0d0,-0.55d0)
a4=(0.3d0, 0.79d0)
a5=(1.0d0,-1.08d0)

write(*,'(a,/)')"program iteratii_3"
x=-1.d0 ; y=+1.d0 ! aproximatiile initiale Newton
pas=1.d0/512.d0 ! pas de derivare numerica
write(*,'(/,a,/)')'Iteratiile metodei Newton'
write(*,*)' x y f g'
do iter=1,iter_max
f=fct(x,y) ; g=gct(x,y)
write(*,'(i3,2x,4(g13.6,1x))')iter,x,y,f,g
if(abs(f)+abs(g) < 1.d-6)go to 33
!
! Derivatele partiale ale functiei fct(x,y)
!
dfdx=(fct(x+pas,y)-fct(x-pas,y))/(pas+pas)
dfdy=(fct(x,y+pas)-fct(x,y-pas))/(pas+pas)
!
! Derivatele partiale ale functiei gct(x,y)
!
dgdx=(gct(x+pas,y)-gct(x-pas,y))/(pas+pas)
dgdy=(gct(x,y+pas)-gct(x,y-pas))/(pas+pas)
!
! Rezolvarea unui sistem liniar de gradul doi cu metoda Cramer
!
d0=det2(dfdx,dgdx,dfdy,dgdy)
if(d0.eq.0.d0)stop 'Jacobian singular'
d1=det2(-f,-g,dfdy,dgdy)
d2=det2(dfdx,dgdx,-f,-g)
dx=d1/d0 ! corectiile Newton
dy=d2/d0
if(abs(dx)+abs(dy) < 1.d-6)goto 33
x=x+dx ! iteratiile Newton
y=y+dy
enddo
write(*,*)'neconvergenta Newton 2D'
Dan Racoi
Elemente de Fortran 95
28
stop
33 write(*,'(/,a,f13.6,f13.6)')'Solutia =',x,y
write(*,'(a,f13.6,f13.6)')'Functiile=',fct(x,y),gct(x,y)
66 continue
end program iteratii_3

4. Dezvoltri n serie

Soluia analitic a ecuaiei Poisson:
1 1
1 1
2
2
2
2
2
+ < <
+ < <
=

y
x
y
u
x
u

cu condiia la limit u=0 pe contur este:

=
+
=
5 , 3 , 1 5 , 3 , 1
2 2 4
) (
)
2
cos( )
2
cos(
128
) , (
n m
n m mn
y n x m
y x u



program ds1
!
! Solutia analitica (serii duble) Ec. Poisson
! Laplacian(u)=-2
! -1<x<+1
! -1<y<+1
! Conditia la limita u=0 pe frontiera
!
implicit real(8) (a-h,o-z)
pi=4.d0*atan(1.d0)
x=0.45d0 ; y=-0.3d0
u=0.d0
do n=1,11,2
do m=1,11,2
u=u+(-1.d0)**(0.5d0*(m+n)-1)*
# cos(m*pi*x/2.d0)*cos(n*pi*y/2.d0)/(m*n*(m**2+n**2))
enddo
enddo
ue=u*128/pi**4
write(*,'(a,g13.6)')' x=',x,' y=',y,' u=',ue
end

Funcia exponenial se calculeaz utiliznd dezvoltarea n serie:
...
!
...
! 3 ! 2 1
1
3 2
+ + + + + + =
i
x x x x
e
i
x

Calculul se efectueaz adunnd termen cu termen. Dac un termen este mai mic dect
tolerana impus calculul se oprete:
<
! k
x
k


! ---------------------------------------------------------
! Calculeaza exp(x) pentru x dat utilizand dezvoltarea in serie
! infinita cu o toleranta data
! ---------------------------------------------------------

Dan Racoi
Elemente de Fortran 95
29
PROGRAM calculul_functiei_exponentiale ! DEZVOLTARE IN SERIE
IMPLICIT NONE

INTEGER :: index ! numarul de termeneni
REAL(8) :: termen ! un termen
REAL(8) :: exp_calc ! valoarea seriei
REAL(8) :: X ! valoarea argumentului
REAL(8),PARAMETER :: tol = 1.d-9 ! toleranta

WRITE(*,*)'INTRODUCETI X'
READ(*,*) X
index = 1 ! primul termen din serie
exp_calc = 1.0
termen = X ! al doilea termen in serie
DO
IF (ABS(termen) < tol) EXIT
exp_calc = exp_calc + termen
index = index + 1
termen = termen * (X / index)
ENDDO

WRITE(*,*) 'Dupa ', index, ' iteratii:'
WRITE(*,*) ' Exp_calculat = ', exp_calc
WRITE(*,*) ' Exp_exact = ', EXP(X)
WRITE(*,*) ' Abs(Error) = ', ABS(exp_calc - EXP(X))

END PROGRAM calculul_functiei_exponentiale

5. Tablouri

Limbajul FORTRAN accept tablouri cu pn la 7 dimensiuni.
Tablourile cu o dimensiune corespund vectorilor n-dimensionali.
Tablourile cu dou dimensiuni corespund matricilor.
Declararea unui tablou se face n felul urmtor:

Tip nume_tablou(n1i:n1f,n2i:n2f,n3i:n3f)

unde:
tip : integer(4), real(4), real(8), logical, complex(4), complex(8)
nume_tablou: numele tabloului
n1i : valoarea ntreag iniial a indicelui (dac lipsete se consider implicit 1)
n1f : valoarea ntreag final a indicelui

real(8) v(1:3) corespunde lui v(1),v(2),v(3)
real(8) v1(2) corespunde lui v1(1),v1(2)
real mat(1:2,1:2) corespunde lui mat(1,1),mat(1,2)
mat(2,1),mat(2,2)
5.1 Vectori
Vectorii sunt tablouri cu o dimensiune.
Operaiile matematice cu vectori sunt identice cu cele din algebr pentru vectori
de tip real i complex. Operaiile elementare n complex sunt definite in limbajul
FORTRAN.
Considerm vectori de dimensiune n.
Dan Racoi
Elemente de Fortran 95
30
Operaiile cu vectoriale sunt definite n limbajul FORTRAN. Dac a i b sunt doi
vectori cu trei elemente complexe, operaia:
b a c + =
este echivalent cu adunarea explicit a elementelor vectorilor:
3 3 3
2 2 2
1 1 1
b a c
b a c
b a c
+ =
+ =
+ =

In FORTRAN se scrie:
complex a(3),b(3),c(3)
) 3 ( ) 3 ( ) 3 (
) 2 ( ) 2 ( ) 2 (
) 1 ( ) 1 ( ) 1 (
b a c
b a c
b a c
sau
b a c
+ =
+ =
+ =
+ =

nmulirea unui vector cu o constant:
n i cv v
v c v
i i
,..., 2 , 1 ,
1 2
1 2
= =
=

Adunarea a doi vectori:
n i v v v
v v v
i i i
,..., 2 , 1 ,
2 1 3
2 1 3
= + =
+ =

Scderea a doi vectori:
n i v v v
v v v
i i i
,..., 2 , 1 ,
2 1 3
2 1 3
= =
=

Produsul scalar a doi vectori:
i
n
i
i
v v v v
2
1
1 2 1
.

=
=
Norma unui vector:
5 . 0
2
1
|
|

\
|
=

=
n
i
i
v v
Dac vectorul este de tip real atunci:
( )
5 . 0
.v v v =
In FORTRAN este definit operaia de nmulire a doi vectori, element cu
element.

=
3
2
1
x
x
x
x

=
3
2
1
y
y
y
y

=
3 3
2 2
1 1
*
y x
y x
y x
y x
Instruciunile:

real x(3),z(3),s
Dan Racoi
Elemente de Fortran 95
31
s=sum(x*z)

conduc la:
3 3 2 2 1 1
y x y x y x s + + =


program vect1 ! operatii elementare cu vectori
implicit none
integer,parameter :: n=5 ! dimensiunea vectorului
real v1(n),v2(1:n),v3(n)
real s1,s2,ps,p1,p2,v1min,v2min,v1max,v2max,norma,const
integer i
v1=(/1.,1.2,3.,4.1,5.5/) ! elementele vectorului 1
data v2/9.,3.1,2.,1.1,3.3/ ! elementele vectorului 2 declarate cu
! data lista_v/lista_constante/
write(*,*)'Program vect1'
do i=1,n
write(*,*)v1(i),v2(i)
enddo
!
! Suma elementelor vectorilor
!
s1=0.d0 ; s2=0.d0
do i=1,n
s1=s1+v1(i)
s2=s2+v2(i)
enddo
write(*,*)'Suma_v1=',s1,' Suma_v2=',s2
!
! Functia sum(vector) calculeaza suma elementelor vectorului
!
write(*,*)'Suma_v1=',sum(v1),' Suma_v2=',sum(v2)
!
! Produsul elementelor vectorilor
!
p1=1.d0 ; p2=1.d0
do i=1,n
p1=p1*v1(i)
p2=p2*v2(i)
enddo
write(*,*)'Produs_v1=',p1,' Produs_v2=',p2
!
! Functia product(vector) calculeaza produsul elementelor vectorului
!
write(*,*)'Produs_v1=',product(v1),' Produs_v2=',product(v2)
!
! Maximul si minimul din fiecare vector
!
v1max=v1(1) ; v2max=v2(1)
v1min=v1(1) ; v2min=v2(1)
do i=2,n
if(v1(i)>v1max)v1max=v1(i)
if(v2(i)>v2max)v2max=v2(i)

if(v1(i)<v1min)v1min=v1(i)
if(v2(i)<v2min)v2min=v2(i)

enddo
write(*,*)'v1_max=',v1max,' v2_max=',v2max
write(*,*)'v1_min=',v1min,' v2_min=',v2min
!
Dan Racoi
Elemente de Fortran 95
32
! Inmultirea unui vector cu o constanta
!
const=1.345
v3=v1*const ! vectorial
write(*,*)'Inmultirea vectorului v1 cu constanta=',const
write(*,'(2g13.6)')(v1(i),v3(i),i=1,n)
!
! Adunarea a doi vectori
!
v3=v1+v2 ! vectorial
!
! Adunarea explicita
!
write(*,*)'Suma a doi vectori'
do i=1,n
v3(i)=v1(i)+v2(i)
write(*,'(3g13.6)')v1(i),v2(i),v3(i)
enddo
!
! Scaderea a doi vectori
!
v3=v1-v2 ! vectorial
!
! Scaderea explicita
!
write(*,*)'Diferenta a doi vectori'
do i=1,n
v3(i)=v1(i)-v2(i)
write(*,'(3g13.6)')v1(i),v2(i),v3(i)
enddo

!
! Produsul scalar
!
write(*,*)'Produs scalar'
ps=0.d0
do i=1,n
ps=ps+v1(i)*v2(i)
enddo
write(*,*)'Produs_scalar=',ps
!
! Functia dot_product(vector1,vector2) calculeaza produsul scalar
!
write(*,*)'Produs_scalar=',dot_product(v1,v2)
!
! Inmultirea a doi vectori component cu component
!
v3=v1*v2
write(*,*)'Inmultirea pe componente'
write(*,'(i3,2x,3g13.6)')(i,v1(i),v2(i),v3(i),i=1,n)
!
! Norma unui vector
!
norma=sqrt(dot_product(abs(v1),abs(v1)))

write(*,*)'norma vectorului v1=',norma
end program vect1



program maxloc_minloc
!
! locul valorii maxime si valoarea maxima intr-un vector
Dan Racoi
Elemente de Fortran 95
33
! locul valorii minime si valoarea minima intr-un vector
!
implicit none
integer locatie(1)
real,dimension(5) :: x=(/1.,4.,7.,5.,-1./)
real xmax,xmin
write(*,*)x
locatie=maxloc(x) ! indicele valorii maxime
xmax=maxval(x) ! valoarea maxima
write(*,*)locatie,xmax
locatie=minloc(x) ! indicele valorii minime
xmin=minval(x) ! valoarea minima
write(*,*)locatie,xmin
end program maxloc_minloc

5.2 Matrici
Matricile sunt tablouri cu dou dimensiuni.
Matricile sunt memorate pe coloan.

real a(1:2,1:3) echivalent cu real a(2,3)

a(1,1) a(1,2) a(1,3)
a(2,1) a(2,2) a(2,3)

Reprezentarea intern:
1 a(1,1)
2 a(2,1)
3 a(1,2)
4 a(2,2)
5 a(1,3)
6 a(2,3)

Operaiile matriciale din algebr se transpun direct in limbajul FORTRAN pentru
matrice cu elemente ntregi, reale i complexe.
Considerm matrice cu elemente complexe ptrate de dimensiune n.
nmulirea unei matrice cu o constant:
n j n i ca c
cA C
ij ij
,..., 2 , 1 , ,..., 2 , 1 , = = =
=

Adunarea a dou matrice:
n j n i b a c
B A C
ij ij ij
,..., 2 , 1 , ,..., 2 , 1 , = = + =
+ =

Scderea a dou matrice:
n j n i b a c
B A C
ij ij ij
,..., 2 , 1 , ,..., 2 , 1 , = = =
=

nmulirea a dou matrice:
n j n i b a c
AB C
kj
n
j
ik ij
,..., 2 , 1 , ,..., 2 , 1 ,
1
= = =
=

=

Dan Racoi
Elemente de Fortran 95
34
Norma unei matrice:
5 . 0
1 1
2
|
|

\
|
=

= =
n
i
n
j
ij
a A
Operaiile matriciale sunt definite n FORTRAN.

complex a(2,2),b(2,2),c(2,2)

) 2 , 2 ( ) 2 , 2 ( ) 2 , 2 (
) 1 , 2 ( ) 1 , 2 ( ) 1 , 2 (
) 2 , 1 ( ) 2 , 1 ( ) 2 , 1 (
) 1 , 1 ( ) 1 , 1 ( ) 1 , 1 (
:
b a c
b a c
b a c
b a c
sau
b a c
+ =
+ =
+ =
+ =
+ =


Programul mat1.f90 efectueaz calculele matriciale elementare matricial.

program mat1
implicit none
integer,parameter :: n=3 ! dimensiunea matricilor
real,dimension(n,n) :: a,b ! se declara matricile a si b
! cu n linii si n coloane
real c(n,n),v1(n),v2(n)
real :: const=3.3 ! Se defineste constanta const
real norma
integer i,j

data (a(1,j),j=1,n)/1.,2.,3./ ! prima linie din matricea a
data (a(2,j),j=1,n)/4.,5.,6./ ! a doua linie din matricea a
data (a(3,j),j=1,n)/7.,8.,9./ ! a treia linie din matricea a

data b/-1.,-2.,-3., & ! prima coloana din matricea b
-6.,-4.,-2., & ! a doua coloana din matricea b
8., 2., 1./ ! a treia coloana din matricea b

data v1(1),v1(2),v1(3)/1.1,2.2,3.3/ ! vectorul v1

write(*,*)'Matricea a'
do i=1,n
write(*,'(3g13.6)')(a(i,j),j=1,n)
enddo
write(*,*)'Matricea b'
write(*,'(3g13.6)')((b(i,j),j=1,n),i=1,n)
!
! Produsul unei matrici cu o constanta
!
c=const*a ! matricial

write(*,*)'Produsul unei matrici cu o constanta'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Suma a doua matrici
!
c=a+b ! matricial
Dan Racoi
Elemente de Fortran 95
35

write(*,*)'Suma a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Diferenta a doua matrici
!
c=a-b ! matricial


write(*,*)'Diferenta a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Produsul unei matrici cu un vector
!
v2=matmul(a,v1)

write(*,*)'Produsul unei matrici cu un vector'
write(*,'(g13.6)')(v2(i),i=1,n)
!
! Produsul a doua matrici
!
c=matmul(a,b)

write(*,*)'Produsul a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Norma matriciala
!
norma=0.d0
do i=1,n
do j=1,n
norma=norma+abs(a(i,j))**2
enddo
enddo
norma=sqrt(norma)
write(*,*)'Norma matricei a'
write(*,*)'norma=',norma


end program mat1

Programul mat2.f90 efectueaz operaiile matriciale explicit.

program mat2
implicit none
integer,parameter :: n=3 ! dimensiunea matricilor
real,dimension(n,n) :: a,b ! se declara matricile a si b
! cu n linii si n coloane
real c(n,n),v1(n),v2(n)
real :: const=3.3 ! Se defineste constanta const
real norma,suma
integer i,j,k

data (a(1,j),j=1,n)/1.,2.,3./ ! prima linie din matricea a
data (a(2,j),j=1,n)/4.,5.,6./ ! a doua linie din matricea a
data (a(3,j),j=1,n)/7.,8.,9./ ! a treia linie din matricea a

data b/-1.,-2.,-3., & ! prima coloana din matricea b
-6.,-4.,-2., & ! a doua coloana din matricea b
Dan Racoi
Elemente de Fortran 95
36
8., 2., 1./ ! a treia coloana din matricea b

data v1(1),v1(2),v1(3)/1.1,2.2,3.3/ ! vectorul v1

write(*,*)'Matricea a'
do i=1,n
write(*,'(3g13.6)')(a(i,j),j=1,n)
enddo
write(*,*)'Matricea b'
write(*,'(3g13.6)')((b(i,j),j=1,n),i=1,n)
!
! Produsul unei matrici cu o constanta
!
do i=1,n
do j=1,n
c(i,j)=const*a(i,j)
enddo
enddo

write(*,*)'Produsul unei matrici cu o constanta'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Suma a doua matrici
!
do i=1,n
do j=1,n
c(i,j)=a(i,j)+b(i,j)
enddo
enddo
write(*,*)'Suma a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Diferenta a doua matrici
!
do i=1,n
do j=1,n
c(i,j)=a(i,j)-b(i,j)
enddo
enddo

write(*,*)'Diferenta a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)
!
! Produsul unei matrici cu un vector
!
do i=1,n
suma=0.
do j=1,n
suma=suma+a(i,j)*v1(j)
enddo
v2(i)=suma
enddo

write(*,*)'Produsul unei matrici cu un vector'
write(*,'(g13.6)')(v2(i),i=1,n)
!
! Produsul a doua matrici
!
do i=1,n
do j=1,n
Dan Racoi
Elemente de Fortran 95
37
suma=0.
do k=1,n
suma=suma+a(i,k)*b(k,j)
enddo
c(i,j)=suma
enddo
enddo

write(*,*)'Produsul a doua matrici'
write(*,*)'Matricea c'
write(*,'(3g13.6)')((c(i,j),j=1,n),i=1,n)

!
! Norma matricei a
!
norma=0.d0
do i=1,n
do j=1,n
norma=norma+abs(a(i,j))**2
enddo
enddo
norma=sqrt(norma)
write(*,*)'Norma matricei a'
write(*,*)'norma=',norma

end program mat2

Matricele pot fi iniializate cu instruciunea data sau utiliznd instruciunea
reshape:

result=reshape(source,shape)
Instruciunea:

a=reshape((/1.,2.,3.,4./),(/2.,2./)

este echivalent cu:
(

=
. 4 . 2
. 3 . 1
a

program reshape_function
implicit none
real a(2,3),b(3,3)
integer i
!
! Matricea a memorata pe coloane
!
a=reshape((/1.,2.,3.,4.,5.,6./),(/2,3/))
do i=1,2
write(*,*)a(i,:)
enddo
!
! Matricea unitate (3,3)
!
b=reshape((/1.,0.,0.,0.,1.,0.,0.,0.,1./),(/3,3/))
write(*,*)
do i=1,3
write(*,*)b(i,:)
enddo
Dan Racoi
Elemente de Fortran 95
38
end program reshape_function


Advanced. ARRAY SECTIONS

Se definesc (extrag) tablouri din vectori i matrice.

real(4) dimension(100) :: vector
integer,dimension(6) :: ivector=(/1,4,8,43,54,88/)

Array section Semnificaie
vector(:) tot vectorul
vector(1:100) tot vectorul
vector(1:10) tablou unidimensional coninnd primele 10 elemente din vector
vector(51:100) tablou unidimensional coninnd elementele 51:100 din vector
vector(51:) identic cu vector(51:100)
vector(10:1:-1) tablou unidimensional coninnd primele 10 elemente din
vector n ordine invers
vector(/10,88,3,5/) tablou unidimensional coninnd elementele 10,88,3,5 din
vector, n aceast ordine
vector(ivector) tablou unidimensional coninnd elementele 1,4,8,43,54,88
din vector n aceast ordine


real,dimension(100,100) :: matrice

Array section Semnificaie
matrice(:,:) toat matricea
matrice(1:100,1:100) toat matricea
matrice(7,:) tablou unidimensional coninnd linia 7 din matrice
matrice(7,1:100) tablou unidimensional coninnd linia 7 din matrice
matrice(:,7) tablou unidimensional coninnd coloana 7 din matrice
matrice(1:10,81:90) tablou bidimensional coninnd sub_blocul din matrice
indicat prin rangul indicilor; tablou(10,10)


program initializare_matrici
integer,parameter :: lin=4 ! numarul de linii
integer,parameter :: col=3 ! numarul de coloane
real,dimension(lin,col) :: a ! se declara o matrice (lin,col)

a(1,:)=(/1.,2.,3./) ! prima linie din matrice
a(2,:)=(/4.,5.,6./) ! a doua linie din matrice
a(3,:)=(/(i,i=-1,1)/) ! a treia linie din matrice
a(4,:)=(/(0.,i=1,3)/) ! a patra linie din matrice

do i=1,lin
write(*,'(3g13.5)')a(i,:) ! se scrie linia i
enddo

Dan Racoi
Elemente de Fortran 95
39
end program initializare_matrici

program array_constructor
implicit none
integer,parameter :: n=3
real, dimension(n) :: m1(n,n)
real,dimension(n) :: x,v
real s
integer i,j
real rand

write(*,*)'Matricea m1'
do i=1,n
do j=1,n
m1(i,j)=rand(0) ! generare aleatoare
enddo
write(*,*)(m1(i,j),j=1,n) ! scriere explicita
x(i)=rand(0)
enddo
write(*,*)
write(*,*)'Prima linie din matricea m1'
write(*,*)m1(1,:)
write(*,*)'A doua linie din matricea m1'
write(*,*)m1(2,:)
write(*,*)'A treia linie din matricea m1'
write(*,*)m1(3,:)
!
! Inmultirea explicita a unei matrici cu un vector
!
do i=1,n
s=0.
do j=1,n
s=s+m1(i,j)*x(j)
enddo
v(i)=s
enddo
write(*,*)
write(*,*)v
!
! Inmultirea cu array_constructor
!
do i=1,n
v(i)=sum(m1(i,:)*x) ! m1(i,:) corespunde unui vector
enddo ! m1(i,:)*x inmultirea component cu component
! a doi vectori, rezultatul este un vector
! sum calculeaza suma vectorului
write(*,*)v
end program array_constructor

Advanced

program array ! Tablouri in F90
implicit none
integer,parameter :: n=3
real, dimension(n,n) :: a,b,c
real rand
integer i,j,k
do i=1,n
do j=1,n
a(i,j)=rand(0) ! se genereaza aleator elementele matricei A
b(i,j)=rand(0) ! se genereaza aleator elementele matricei B
enddo
Dan Racoi
Elemente de Fortran 95
40
enddo
write(*,*)'Matricea A' ; call scrie_matrice(a,n)
write(*,*)'Matricea B' ; call scrie_matrice(b,n)
!
! Inmultirea explicita a doua matrici in FORTRAN 90
!
do i=1,n
do j=1,n
c(i,j)=sum(a(i,:)*b(:,j))
enddo
enddo
write(*,*)'Matricea C' ; call scrie_matrice(c,n)

end program array

subroutine scrie_matrice(a,n) ! tipareste un tablou
implicit none
integer :: n,i
real,dimension(n,n) :: a

do i=1,n
write(*,' (6(g12.5,1x))')a(i,:) ! scrie o linie
enddo
write(*,*) ! scrie o linie alba
end subroutine scrie_matrice

Automatic array

program automatic
integer,parameter :: ndim=5
integer,parameter :: n=2
real a(ndim,n)
do i=1,n ; do j=1,n ; a(i,j)=rand(0) ; enddo ; enddo
call sub1(ndim,n,a)
end program automatic

subroutine sub1(ndim,m,b)
real b(ndim,m)

real c(m) ! automatic array
real d(m,m) ! automatic array

do i=1,m ; c(i)=rand(0) ; do j=1,m ; d(i,j)=rand(0) ; enddo ; enddo
do i=1,m
write(*,*)b(i,:),c(i)
enddo
write(*,*)
do i=1,m
write(*,*)d(i,:)
enddo
end subroutine sub1


5.3 Gauss Seidel
Metoda Gauss Seidel este o metod iterativ pentru calculul soluiei unui sistem
de ecuaii algebrice liniare. Metoda converge dac matricea sistemului este simetric i
pozitiv definit. Metoda converge dac matricea sistemului este diagonal dominant pe
linii.
Considerm sistemul de n ecuaii algebrice liniare:
Dan Racoi
Elemente de Fortran 95
41

=
=
n
j
i j ij
b x a
1
i=1,2,,n
Iteraiile metodei Gauss Seidel se efectueaz conform ecuaiei:
ii
i
j
n
i j
k
j ij
k
j ij i
k
i
a
x a x a b
x

= + =
+
+

=
1
1 1
1
1
i=1,2,,n
Cu k s-a notat contorul de iteraii k=0,1,
Se pleac de la o aproximaie iniial dat.
Iteraiile se opresc cnd norma reziduului este mai mic dect o toleran impus:
<
=
r
Ax b r
k



program gauss_seidel
!
! Determina solutia unui sistem diagonal dominant
! cu metoda iterativa Gauss Seidel
!
implicit none
integer,parameter :: n=3
integer,parameter :: it_max=111 ! numarul maxim de iteratii
real(8),parameter :: eps=1.d-5 ! toleranta impusa
real(8) norma_reziduu
real(8) a(n,n),b(n),x(n),r(n),s
integer i,j,iter

data a/10.d0,2.d0,2.d0, & ! prima coloana din matricea a
1.d0,10.d0,2.d0, & ! a doua coloana din matricea a
1.d0,1.d0,10.d0/ ! a treia coloana din matricea a

b=(/12.d0,13.d0,14.d0/) ! vectorul b

write(*,*)'matricea A'
do i=1,n
write(*,'(5g11.4)')(a(i,j),j=1,n)
enddo
write(*,*)'vectorul b'
do i=1,n
write(*,'(5g11.4)')b(i)
enddo

x=0.01d0 ! aproximatia initiala (vectorial)

write(*,*)'Iteratii Seidel'

r=matmul(a,x)-b ! calculul reziduului (matricial)
norma_reziduu=maxval(abs(r))
iter=0

do while((iter<it_max).and.(norma_reziduu>eps))
do i=1,n
s=0.d0
Dan Racoi
Elemente de Fortran 95
42
do j=1,i-1 ! suma de la j=1 pana la i-1
s=s+a(i,j)*x(j)
enddo
do j=i+1,n ! suma de la j=i+1 pana la n
s=s+a(i,j)*x(j)
enddo
if(a(i,i).ne.0.d0)then
x(i)=(b(i)-s)/a(i,i)
else
stop 'pivot zero'
endif
enddo
iter=iter+1
r=matmul(a,x)-b ! calculul reziduului (matricial)
norma_reziduu=maxval(abs(r))
write(*,'(a,i5,f13.5)')'iter=',iter, norma_reziduu
enddo
if(iter<it_max)then
write(*,*)'solutia'
write(*,'(g12.5,f13.5)')(x(i),r(i),i=1,n)
else
write(*,*)'neconvergenta Seidel'
endif
end program gauss_seidel

program gauss_seidel_array_sections
!
! Determina solutia unui sistem diagonal dominant
! cu metoda iterativa Gauss Seidel
!
implicit none
integer,parameter :: n=3
integer,parameter :: it_max=111 ! numarul maxim de iteratii
real(8),parameter :: eps=1.d-5 ! toleranta impusa
real(8) norma_reziduu
real(8) a(n,n),b(n),x(n),r(n),s,s1,s2
integer i,j,iter

data a/10.d0,2.d0,2.d0, & ! prima coloana din matricea a
1.d0,10.d0,2.d0, & ! a doua coloana din matricea a
1.d0,1.d0,10.d0/ ! a treia coloana din matricea a

b=(/12.d0,13.d0,14.d0/) ! vectorul b

write(*,*)'matricea A'
do i=1,n
write(*,'(5g11.4)')(a(i,j),j=1,n)
enddo
write(*,*)'vectorul b'
do i=1,n
write(*,'(5g11.4)')b(i)
enddo

x=0.01d0 ! aproximatia initiala (vectorial)

write(*,*)'Iteratii Seidel'

r=matmul(a,x)-b ! calculul reziduului (matricial)
norma_reziduu=maxval(abs(r))
iter=0
Dan Racoi
Elemente de Fortran 95
43

do while((iter<it_max).and.(norma_reziduu>eps))
do i=1,n
s1=sum(a(i,1:i-1)*x(1:i-1)) ! suma de la 1 la i-1
s2=sum(a(i,i+1:n)*x(i+1:n)) ! suma de la i+1 la n
s=s1+s2
if(a(i,i).ne.0.d0)then
x(i)=(b(i)-s)/a(i,i)
else
stop 'pivot zero'
endif
enddo
iter=iter+1
r=matmul(a,x)-b ! calculul reziduului (matricial)
norma_reziduu=maxval(abs(r))
write(*,'(a,i5,f13.5)')'iter=',iter, norma_reziduu
enddo
if(iter<it_max)then
write(*,*)'solutia'
write(*,'(g12.5,f13.5)')(x(i),r(i),i=1,n)

else
write(*,*)'neconvergenta Seidel'
endif
end program gauss_seidel_array_sections


5.4 Alocarea dinamic de memorie (n execuie)

In multe cazuri acelai algoritm matricial se utilizeaz pentru ordine de mrime
diferite ale matricelor. Dac nu se cunoate aprioric dimensiunea matricelor i a
vectorilor acetia sunt declarai de tip alocatabil iar rezervarea de memorie se face n
momentul execuiei.

program alocate
implicit none
integer ialoc0,ialoc1,ialoc2,ialoc3,ialoc4,ialoc5
integer n,i,j
real(8) s,drand
!
! Alocarea dinamica de memorie in timpul executiei
!

!
! Se declara alocatabila matricea a
!
real(8),allocatable :: a(:,:)
!
! Se declara alocatabili vectorii b si c
!
real(8),allocatable :: b(:),c(:)
!
! Se citeste ordinul matricei
!
write(*,*)'Introduceti n'
read(*,*)n
if(n<2)n=2
!
! Se aloca spatiu pentru matricea a
! Daca alocarea reuseste variabila ialoc0 ia valoarea 0.
! In caz contrar se opreste executia programului.
Dan Racoi
Elemente de Fortran 95
44
!
allocate (a(n,n),stat=ialoc0) ; if(ialoc0.ne.0)stop 'ialoc0'
!
! Se aloca spatiu pentru vectorul b.
! Daca alocarea reuseste variabila ialoc1 ia valoarea 0.
! In caz contrar se opreste executia programului.
!
allocate (b(n ),stat=ialoc1) ; if(ialoc1.ne.0)stop 'ialoc1'
!
! Se aloca spatiu pentru vectorul c.
! Daca alocarea reuseste variabila ialoc2 ia valoarea 0.
! In caz contrar se opreste executia programului.
!
allocate (c(n ),stat=ialoc2) ; if(ialoc2.ne.0)stop 'ialoc2'
!
! Se genereaza aleator elementele matricei a si ale vectorului b
!
do i=1,n
do j=1,n
a(i,j)=drand(0)
enddo
b(i)=drand(0)
enddo
!
! Se inmulteste matricea a cu vectorul b si se obtine vectorul c.
!
write(*,*)'Vectorul c'
do i=1,n
s=0.d0
do j=1,n
s=s+a(i,j)*b(i)
enddo
c(i)=s
write(*,*)i,c(i)
enddo
!
! Se elibereaza spatiul ocupat de matricea a.
! Daca dealocarea reuseste ialoc3 ia valoarea zero.
!
deallocate (a,stat=ialoc3);if(ialoc3.ne.0)stop 'ialoc3'
!
! Se elibereaza spatiul ocupat de vectorul b.
! Daca dealocarea reuseste ialoc4 ia valoarea zero.
!

deallocate (b,stat=ialoc4);if(ialoc4.ne.0)stop 'ialoc4'
!
! Se elibereaza spatiul ocupat de vectorul c.
! Daca dealocarea reuseste ialoc4 ia valoarea zero.
!
deallocate (c,stat=ialoc5);if(ialoc5.ne.0)stop 'ialoc5'

end program alocate


6. Funcii i subprograme

6.1 Clauza contains. Funcii interne

Dan Racoi
Elemente de Fortran 95
45
Anterior s-au definit funciile formul care permit descrierea unei funcii definite
printr-o singur ecuaie. In cazul n care expresia funciei este mai complex se utilizeaz
funcii interne declarate n programul principal dup cuvntul cheie contains:

program nume_program
declaraii
.
.
.variabil=nume_funcie(argumente efective)
contains
tip function nume_funcie(argumente_formale)
declaratii
.
.
nume_funcie=expresie
end function nume_functie
end program nume_program

program contains_exemple
!
! Calculeaza f(x,y)=exp(x)*sin(pi*y) pentru x>=0
! exp(x)*cos(pi*y) pentru x<0
!
implicit none
real(4) x,y,c,pi
x=1.1 ; y=2.1 ; pi=4.*atan(1.)

c=fct(x,y) ! apelul functiei

write(*,*)x,y,c

c=fct(-2.1,-1.1) ! apelul functiei

write(*,*)-2.1,-1.1,c

contains

real(4) function fct(x,y)
implicit none
real(4),intent(in) :: x,y ! parametrii de intrare, intent(in)
!
! Valoarea variabilei pi este preluata din programul apelant,
! asociere HOST
!
if(x<0.)then
fct=exp(x)*cos(pi*y) ! expresia functiei
! numele functiei apare obligatoriu
! intr-o instructiune de atribuire
else
fct=exp(x)*sin(pi*x)
endif

end function fct

end program contains_exemple

Dan Racoi
Elemente de Fortran 95
46
6.2 Funcii externe
Funciile externe au aceeai structur ca i funciile interne dar constituie uniti
separate de program. Numele funciei apare obligatoriu ntr-o instruciune de atribuire.
Toate variabilele trebuie s fie definite n interiorul funciei.

tip function nume_funcie(argumente_formale)
declaratii
.
.
nume_funcie=expresie
end function nume_functie

Intre tipul i numrul de argumente din programul apelant i funcie exist o
coresponden biunivoc.
Funcia factorial
1 ! 0
... 3 . 2 . 1 !
=
= n n

permite calculul combinrilor:
)! ( !
!
m n m
n
C
m
n

=

PROGRAM EXEMPLU_FACTORIAL
IMPLICIT NONE
INTEGER N,M,FACTORIAL,COMBINARI,F
N=4 ; M=2
F=FACTORIAL(N)
COMBINARI=FACTORIAL(N)/FACTORIAL(M)/FACTORIAL(N-M)
WRITE(*,*)'N=',N,' M=',M,' F=',F,' C=',COMBINARI
END PROGRAM EXEMPLU_FACTORIAL
INTEGER FUNCTION FACTORIAL(N)
IMPLICIT NONE

INTEGER, INTENT(IN) :: N ! ARGUMENTUL
INTEGER :: F,I

IF(N==0)THEN
FACTORIAL=1
ELSEIF(N>1)THEN
F = 1 ! SE CALCULEAZA IN BUCLA n!
DO I = 1, N
F = F * I
END DO
FACTORIAL = F
ELSE
STOP 'ARGUMENT INCORECT'
ENDIF

END FUNCTION FACTORIAL


6.2.1.Funcii n complex

Dan Racoi
Elemente de Fortran 95
47
O mare atenie trebuie acordat calculului cu funcii complexe deoarece pot avea
mai multe valori (sun multiforme). De exemplu calculul radicalului in Fortran:

As a result of type complex is the principal value, with the real part greather
than or equal to zero.
When the real part of the result is zero, the imaginary part is greather than
or equal to zero.

Se dau dou numere reale x i y. Se determin numrul complex:
iy x z + =
i se calculeaz funcia complex:
z
z z f
1
) ( + =
Partea real i partea imaginar sunt )) ( Re( z f i )) ( Im( z f .

program functii_complexe
implicit none
real x,y
complex z,fz,fct
x=2. ; y=2.2 ; z=cmplx(x,y)
fz=fct(z)
write(*,*)'z=',z,' fz=',fz
write(*,*)'x=',x,' y=',y,' Real(fz)=',real(fz)
write(*,*)'x=',x,' y=',y,' Imag(fz)=',imag(fz)
end program functii_complexe

complex function fct(z)
complex,intent(in) ::z
fct=z+1./z
end function fct

Profil Jukovski general

Considerm un cerc cu centrul n cadranul doi n punctul M. Raza cercului este a.
Distana de la centrul cercului la originea axelor O, segmentul OM este m. Unghiul
ascuit fcut de OM cu axa orizontal este . Distana de la originea axelor la cerc pe axa
orizontal este q.
-1
-0.5
0
0.5
1
-1 -0.5 0 0.5 1
y
x
Profi l Jucovski general

Figura 6.2.1 Profil Jukovski generat prin transformare conform
Dan Racoi
Elemente de Fortran 95
48

Considerm transformarea de coordonate:


sin sin
cos cos
a m
a m
+ + =
+ =

i numrul complex:
i + =
Transformarea conform Jucovski:

2
q
z + =
reprezint conform exteriorul unui cerc de raz a cu centrul n M pe exteriorul unui profil
n planul z.
Coordonatele carteziene ale profilului sunt:
) Im(
) Re(
z y
z x
=
=

program jukovski_g ! profil Jukovski general
implicit real(8) (a-h,o-z)
real(8) m
complex(8) zeta,z
pi=4.d0*atan(1.d0)
open(1,file='c:\for\jg.txt')
q=0.4d0 ! constanta din transformata Jukovski
delta=15.d0/180.d0*pi
m=0.1d0
a=sqrt(q**2+m**2+2*q*m*cos(delta)) ! (18.66) Carafoli

do teta=0.d0,2*pi,pi/24.d0
csi=-m*cos(delta)+a*cos(teta)
eta= m*sin(delta)+a*sin(teta)
zeta=cmplx(csi,eta)
z=zeta+q**2/zeta ! transformata Jukowski
x=real(z) ! coordonate carteziene
y=imag(z)
write(*,'(6(f10.6,1x))')x,y,xx(teta),yy(teta),csi,eta
write(1,'(6(f10.6,1x))')x,y,xx(teta),yy(teta),csi,eta
enddo

contains
real(8) function xx(teta)
real(8) teta
xx=(-m*cos(delta)+a*cos(teta))* &
(1+q**2/(m**2+a**2-2*m*a*cos(teta+delta)))
end function xx

real(8) function yy(teta)
real(8) teta
yy=( m*sin(delta)+a*sin(teta))* &
(1-q**2/(m**2+a**2-2*m*a*cos(teta+delta)))
end function yy

end program jukovski_g


6.3 Funcii recursive
Dan Racoi
Elemente de Fortran 95
49

Funciile recursive sunt funciile care se autoapeleaz. Un exemplu clasic este
funcia factorial:
1 ! 1
1 ! 0
)! 1 ( !
=
=
= n n n

Funciile recursive sunt implementate n limbajul FORTRAN. In cazul funciilor
clasice n corpul funciei aprea obligatoriu expresia:

nume_funcie=expresie_aritmetic.

In cazul funciilor recursive, valoarea funciei este memorat ntr-o variabil auxiliar
declarat cu cuvntul cheie result.


recursive function nume_funcie(argumente_formale) result(valoarea_funciei)
declaratii
.
.
valoarea_funciei=expresie
end function nume_functie
end program nume_program

program recursivef
!
! Calculeaza functia factorialorial recursiv
!
implicit none
integer n,f,factorial
n=4

f=factorial(n) ! apelul functiei recursive factorial

write(*,*)'n=',n,' factorialorial=',f
end
recursive function factorial(n) result(s_fact)
! valoarea functiei este
! memorata in variabila s_fact
! de tip intreg
specificat in result
implicit none

integer,intent(in) :: n
integer :: s_fact
if(n<0)stop 'argument incorect'
if(n<=1)then
s_fact=1
else
s_fact=n*factorial(n-1) ! recursivitate
endif
end function factorial

Advanced
Dan Racoi
Elemente de Fortran 95
50

Copyright 1993, 1996 by Bo Einersson and Yurij Stokin
Fortran 90 for Fortran 77 Programmer, Version 2.3

Calculul unei integrale definite cu metoda trapezelor se bazeaz pe formula:
( ) ) ( ) ( 5 . 0 ) (
1
b f a f dx x f I
b
a
+ = =


Pentru mrirea preciziei se introduce un punct intermediar la mijlocul intervalului:
( ) ( )

+ + + = + =
) ( 5 . 0
) ( 5 . 0
2
) ( )) ( 5 . 0 ( 5 . 0 )) ( 5 . 0 ( ) ( 5 . 0 ) ( ) (
a b
a
b
a b
b f a b f a b f a f dx x f dx x f I
Se observ c pentru a calcula I
2
se apeleaz tot la formula trapezelor
(recursivitate).
Eroarea absolut este dat de diferena celor dou integrale i se compar cu o toleran
impus:
tol I I <
1 2

Dac condiia este realizat se calculeaz valoarea final a integralei prin
extrapolare Richardson, echivalent cu formula lui Simpson:
3
1 2
2
I I
I I

+ =
Dac condiia nu este ndeplinit, atunci se mparte intervalul n dou .a.m.d.

PROGRAM RECURSIVE ! TEST_ADAPTIVE_QUAD
!
! Copyright Bo Einersson and Yurij Stokin
!
! Fortran 90 for Fortran 77 Programmer, Version 2.3
!
! Calculeaza o integrala definita cu metoda trapezelor cu
! controlul erorii de integrare printr-o procedura adaptativa
! utilizand functii recursive
!
IMPLICIT NONE
INTERFACE
FUNCTION F(X) RESULT (FUNCTION_VALUE)
REAL(8), INTENT(IN) :: X
REAL(8) :: FUNCTION_VALUE
END FUNCTION F
END INTERFACE

INTERFACE
RECURSIVE FUNCTION ADAPTIVE_QUAD &
(F, A, B, TOL, ABS_ERROR) RESULT (REZULTAT)
REAL(8), EXTERNAL :: F
REAL(8), INTENT (IN) :: A, B, TOL
REAL(8), INTENT (OUT) :: ABS_ERROR
REAL(8) :: REZULTAT
END FUNCTION ADAPTIVE_QUAD
END INTERFACE
REAL(8) :: A, B, TOL
REAL(8) :: ABS_ERROR ! EROAREA ABSOLUTA
REAL(8) :: REZULTAT ! VALOAREA CALCULATA A INTEGRALEI
REAL(8) :: PI
Dan Racoi
Elemente de Fortran 95
51
REAL(8) :: VAL_E ! VALOAREA EXACTA
INTEGER :: I
REAL(8) :: PRIMITIVA,X
PRIMITIVA(X)=-COS(X) ! PRIMITIVA FUNCTIEI CARE SE
! INTEGREAZA NUMERIC
PI = 4.0d0 * ATAN(1.0d0)
A= 0.D0 ; B=PI ! LIMITELE DE INTEGRARE
TOL =0.1d0 ! TOLERANTA INITIALA

DO I = 1, 5
TOL = TOL/10.0d0
REZULTAT = ADAPTIVE_QUAD (F, A, B, TOL, ABS_ERROR)
WRITE(*,*)
WRITE(*,"(A, F15.10, A, F15.10)")"Int_a ", &
REZULTAT, " err_estm ",ABS_ERROR
VAL_E=PRIMITIVA(B)-PRIMITIVA(A) ! LEIBNITZ-NEWTON
WRITE(*,"(A, F15.10, A, F15.10)")"Inr_e ", &
VAL_E, " err_real ",REZULTAT - VAL_E
ENDDO
END PROGRAM RECURSIVE ! TEST_ADAPTIVE_QUAD

FUNCTION F(X) RESULT (FUNCTION_VALUE)
IMPLICIT NONE
REAL(8), INTENT(IN) :: X
REAL(8) :: FUNCTION_VALUE
FUNCTION_VALUE = SIN(X)
END FUNCTION F

RECURSIVE FUNCTION ADAPTIVE_QUAD (F, A, B, TOL, ABS_ERROR) &
RESULT (REZULTAT)
IMPLICIT NONE


INTERFACE
FUNCTION F(X) RESULT (FUNCTION_VALUE)
REAL(8), INTENT(IN) :: X
REAL(8) :: FUNCTION_VALUE
END FUNCTION F
END INTERFACE

REAL(8), INTENT(IN) :: A, B, TOL
REAL(8), INTENT(OUT) :: ABS_ERROR
REAL(8) :: REZULTAT

REAL(8) :: STEP, MIDDLE_POINT
REAL(8) :: ONE_T_AREA, TWO_T_AREAS
REAL(8) :: LEFT_AREA, RIGHT_AREA
REAL(8) :: DIFF, ABS_ERROR_L, ABS_ERROR_R

STEP = B-A
MIDDLE_POINT= 0.5d0 * (A+B)

ONE_T_AREA = STEP * 0.50d0 * (F(A) + F(B))
TWO_T_AREAS = STEP * 0.25d0 * (F(A) + F(MIDDLE_POINT))+&
STEP * 0.25d0 * (F(MIDDLE_POINT) + F(B))
DIFF = TWO_T_AREAS - ONE_T_AREA

IF ( ABS (DIFF) < TOL ) THEN
REZULTAT = TWO_T_AREAS + DIFF/3.0d0 ! EXTRAPOLARE RICHARDSON
ABS_ERROR = ABS(DIFF)
ELSE
LEFT_AREA = ADAPTIVE_QUAD (F, A, MIDDLE_POINT, &
0.5d0*TOL, ABS_ERROR_L)
Dan Racoi
Elemente de Fortran 95
52
RIGHT_AREA = ADAPTIVE_QUAD (F, MIDDLE_POINT, B, &
0.5d0*TOL, ABS_ERROR_R)
REZULTAT = LEFT_AREA + RIGHT_AREA
ABS_ERROR = ABS_ERROR_L + ABS_ERROR_R
END IF
END FUNCTION ADAPTIVE_QUAD


6.4 Instruciunea External

Instruciunea external se utilizeaz pentru a transmite ca subprogramele ca
parametrii la subprograme.
S considerm urmtorul exemplu. Avem o funcie care calculeaz integrala unei
funcii continue cu metoda Gauss cu trei puncte. Dorim s calculm n acelai program
doua integrale:


=
=
b
a
b
a
dx x I
dx x I
) sin(
) exp(
2
1

utiliznd aceeai funcie (metoda Gauss) pentru calculul numeric al integralelor.
Metoda Gauss pe trei puncte este:
( )
3 , 2 , 1 ,
2 2
6 . 0
0
6 . 0
) ( ) ( ) (
2
) (
3
2
1
3 3 2 2 1 1
=

+
+
=
+ =
=
=
+ +

i t
a b a b
x
t
t
t
x f A x f A x f A
a b
dx x f
i i
b
a

Eroarea metodei este dat de formula restului:
) (
2 135
1
) 4 (
5
2
f
a b
R |

\
|
=
unde este un punct din intervalul (a,b).

program external1
implicit none
real a,b
real f1c,f2c ! valorile calculate ale integralelor
real f1e,f2e ! valorile analitice ale integralelor
real er1,er2 ! eroarea absoluta
real gauss3
real primitiva1,primitiva2,x

external functia1,functia2
primitiva1(x)= exp(x)
Dan Racoi
Elemente de Fortran 95
53
primitiva2(x)=-cos(x)
a=0. ; b=0.5
f1c=gauss3(functia1,a,b) ; f1e=primitiva1(b)-primitiva1(a)
er1=abs(f1c-f1e)
write(*,*)'f1c=',f1c,' f1e=',f1e,' er1=',er1
f2c=gauss3(functia2,a,b) ; f2e=primitiva2(b)-primitiva2(a)
er2=abs(f2c-f2e)
write(*,*)'f2c=',f2c,' f2e=',f2e,' er2=',er2
end program external1

real function gauss3(fct,a,b)
implicit none

real,intent(in) :: a,b ! limitele de integrare
real fct ! functia care se integreaza

real t1,t2,t3 ! abscise Gauss
real a1,a2,a3 ! ponderi Gauss
real x1,x2,x3

t1=-sqrt(0.6) ; t2=0. ; t3=+sqrt(0.6)
a1=5./9. ; a2=8./9. ; a3=5./9.

x1=0.5*(b+a)+0.5*(b-a)*t1
x2=0.5*(b+a)+0.5*(b-a)*t2
x3=0.5*(b+a)+0.5*(b-a)*t3

gauss3=0.5*(b-a)*(a1*fct(x1)+a2*fct(x2)+a3*fct(x3))

end function gauss3

real function functia1(x)
implicit none
real,intent(in) :: x
functia1=exp(x)
end

real function functia2(x)
implicit none
real,intent(in) :: x
functia2=sin(x)
end

6.5 Subrutine
Subprogramele de tip SUBROUTINE permit calculul mai multor valori n corpul
subprogramului i transmiterea lor n programul apelant.

[recursive ] subroutine nume_subrutin(lista_argumente_formale)
declaraii
.
.
.
end subroutine nume_subrutina

Se poate specifica (opional) tipul argumentelor transmise subrutinei:
a) intent(in) argumente transmise din programul apelant subrutinei
b) intent(out) argumente transmise din subrutin programului apelant
c) intent(inout) argumente transmise din programul apelant si modificate in subrutin.
Dan Racoi
Elemente de Fortran 95
54
In cazul n care argumentul este o funcie sau o subrutin aceasta se declar n
instruciunea external n programul apelant.
Subrutina este apelat cu instruciunea call:

call nume_subrutin(lista_argumente_efective)

Exist o coresponden biunivoc ca tip i numr ntre lista de argumente formale
i lista de argumente efective.

program subr1
!
! Tabeleaza doua functii pentru a <= x <= b
!
implicit none
real a,b ! limitele intervalului in care se tabeleaza functia
integer n ! numarul de puncte din tabel
real fct1,fct2 ! functiile care se tabeleaza
external fct1,fct2 ! functiile sunt transmise ca argument
a=0. ; b=1. ; n=11
call tabelare(fct1,a,b,n) ! tabelarea functiei fct1
write(*,*)
call tabelare(fct2,a,b,n) ! tabelarea functiei fct2
end program subr1

subroutine tabelare(functie,stanga,dreapta,m)
implicit none
real :: functie
real,intent(in) :: stanga
real,intent(in) :: dreapta
integer,intent(in) :: m
real dx,x
integer i
dx=(dreapta-stanga)/(m-1)
do i=1,m
x=stanga+(i-1)*dx
write(*,*)x,functie(x)
enddo
end subroutine tabelare

real function fct1(x)
real,intent(in) :: x
real pi
pi=4.*atan(1.)
fct1=exp(x)*sin(pi*x)
end function fct1

real function fct2(x)
real,intent(in) :: x
real pi
pi=4.*atan(1.)
fct2=exp(x)*cos(pi*x)
end function fct2

6.5.1 Transmiterea tablourilor la subprograme

Considerm cazul uzual al matricelor ptrate:

real matrice(ndim,ndim)
Dan Racoi
Elemente de Fortran 95
55

Valoarea ndim (leading dimension) este transmis obligatoriu subprogramului.
S presupunem c ndim=5. Dimensiunea efectiv (cu care se lucreaz) este n mai mic sau
egal cu ndim. Subprogramul poate fi apelat cu n=5 sau cu n=3. In cazul n care n=5 n
subrutin se lucreaz cu o matrice cu 5 linii i cinci coloane. In cazul in care n=3 n
subrutin se lucreaz cu o matrice cu trei linii i trei coloane.

call subrutina(ndim,5,matrice)
call subrutina(ndim,3,matrice)

program subr2
!
! transmiterea tablourilor in subprograme
!
integer,parameter :: ndim=5
real,dimension(ndim,ndim) :: matrice
integer n,i,j
n=3
do i=1,n
do j=1,n
matrice(i,j)=rand(0) ! functia rand genereaza numere pseudo aleatoare
enddo

enddo
call scrie_matrice(ndim,n,matrice) ! scrie matricea de dimensiune n
write(*,*)
n=5
do i=1,n
do j=1,n
matrice(i,j)=rand(0)
enddo
enddo
call scrie_matrice(ndim,n,matrice)
end program subr2

subroutine scrie_matrice(ndim,n,a)
implicit none
integer,intent(in) :: ndim
integer,intent(in) :: n
real,dimension(ndim,*),intent(in) :: a
integer i,j
do i=1,n
write(*,'(5(g13.6,1x))')(a(i,j),j=1,n)
enddo
end subroutine scrie_matrice

6.5.2 Rezolvarea sistemelor de ecuaii algebrice lineare

Prin discretizarea ecuaiilor fizicii matematice se obin sisteme algebrice liniare de
mari dimensiuni. O cale pentru a rezolva aceste sisteme de ecuaii liniare este algoritmul
Gauss cu pivotare parial. Algoritmul Gauss are extrem de multe variante i
implementri, vezi NETLIB.ORG . Vom prezenta implementarea standard datorat lui C.
B. Moler, ALGORITHM 423, LINEAR EQUATION SOLVER, C.A.C.M. 15 (1972), P.
274.
.

Dan Racoi
Elemente de Fortran 95
56
AUTHORS: E. HAIRER AND G. WANNER
UNIVERSITE DE GENEVE, DEPT. DE MATHEMATIQUES
CH-1211 GENEVE 24, SWITZERLAND
E-MAIL: Ernst.Hairer@math.unige.ch
Gerhard.Wanner@math.unige.ch

THIS CODE IS DESCRIBED IN:
E. HAIRER, S.P. NORSETT AND G. WANNER, SOLVING ORDINARY
DIFFERENTIAL EQUATIONS I. NONSTIFF PROBLEMS. 2ND EDITION.
SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
SPRINGER-VERLAG (1996)

Considerm sistemul algebric linear:
b Ax =
Matricea A este descompus ntr-un produs de dou matrice triunghiulare L
(lower) i U (upper). Rezolvarea sistemului de ecuaii este redus la rezolvarea a dou
sisteme de ecuaii cu matrice triunghiular prin retrosubstituie.
y Ux
b Ly
b LUx
LU A
=
=
=
=

Pentru a calcula inversa unei matrice de dimensiune 3 se rezolv prin
retrosubstituie trei sisteme algebrice liniare. Elementele matricei inverse sunt notate cu
x
ij
:
(
(
(

= =

1 0 0
0 1 0
0 0 1
1
I AA
(
(
(

= =
(
(
(

1 0 0
0 1 0
0 0 1
33 32 31
23 22 21
13 12 11
I
x x x
x x x
x x x
A

(
(
(

= =
(
(
(

1 0 0
0 1 0
0 0 1
33 32 31
23 22 21
13 12 11
I
x x x
x x x
x x x
LU

0
0
1
31
21
11
x
x
x
LU

0
1
0
32
22
12
x
x
x
LU

1
0
0
33
23
13
x
x
x
LU


program inversa_moler
!
! Calculeaza inversa unei matrici patrate de dimensiune n.
! Se efectueaza descompunerea LU a matricei sistemului.
! Se rezolva apoi prin retrosubstitutie n sisteme algebrice
! avand drept membru drept cate o coloana din matricea unitate.
!
! matricea A(n,n) real(8) n*n
! matricea X=A**(-1)(n,n) real(8) n*n
! vectorul B(n) real(8) n
! Total real(8) 2*n*n+n
Dan Racoi
Elemente de Fortran 95
57
! vectorul ip(n) integer(4)
!

implicit real(8) (a-h,o-z)
integer,parameter :: n=5
real(8) a(n,n),x(n,n),b(n)
real(8) c(n,n) ! matricea unitate
real(8) as(n,n) ! matricea A salvata pentru verificare

integer ip(n) ! vector permutari linii

do i=1,n
do j=1,n
a(i,j)=drand(0)
enddo
enddo

write(*,*)'Matricea [A]'
write(*,'(5f12.5)')((a(i,j),j=1,n),i=1,n)
as=a ! salveaza matricea A pentru verificare

call DEC (N, N, A, IP, IER) ! MOLER (matricea A este inlocuita
! cu descompunerea LU)

if(ier.ne.0)stop 'matrice singulara'
!
! Calcul inversa X(*,*) cite o coloana o data'
!
do j=1,n ! coloana j din matricea inversa

b=0.d0 ! vectorial
b(j)=1.d0
write(*,*)'Coloana=',j
write(*,'(i2,2x,f7.2)')(k,b(k),k=1,n)
call SOL (N, N, A, B, IP) ! retrosubstitutie
! membrul drept B este coloana j din
! matricea unitate la intrare
! dupa executie B contine coloana j
! din matricea inversa
do i=1,n
x(i,j)=b(i)
enddo
enddo

write(*,*)'Matricea [A]**(-1)'
write(*,'(5f12.5)')((x(i,j),j=1,n),i=1,n)

c=matmul(x,as)

write(*,*)'Matricea [A]**(-1)*[A]'
write(*,'(5f7.3)')((c(i,j),j=1,n),i=1,n)

end

SUBROUTINE DEC (N, NDIM, A, IP, IER)
!
! AUTHORS: E. HAIRER AND G. WANNER
! UNIVERSITE DE GENEVE, DEPT. DE MATHEMATIQUES
! CH-1211 GENEVE 24, SWITZERLAND
! E-MAIL: Ernst.Hairer@math.unige.ch
! Gerhard.Wanner@math.unige.ch
!
! THIS CODE IS DESCRIBED IN:
Dan Racoi
Elemente de Fortran 95
58
! E. HAIRER, S.P. NORSETT AND G. WANNER, SOLVING ORDINARY
! DIFFERENTIAL EQUATIONS I. NONSTIFF PROBLEMS. 2ND EDITION.
! SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
! SPRINGER-VERLAG (1993)
!
! VERSION REAL DOUBLE PRECISION
INTEGER N,NDIM,IP,IER,NM1,K,KP1,M,I,J
DOUBLE PRECISION A,T
DIMENSION A(NDIM,N), IP(N)
!-----------------------------------------------------------------------
! MATRIX TRIANGULARIZATION BY GAUSSIAN ELIMINATION.
! INPUT..
! N = ORDER OF MATRIX.
! NDIM = DECLARED DIMENSION OF ARRAY A .
! A = MATRIX TO BE TRIANGULARIZED.
! OUTPUT..
! A(I,J), I.LE.J = UPPER TRIANGULAR FACTOR, U .
! A(I,J), I.GT.J = MULTIPLIERS = LOWER TRIANGULAR FACTOR, I - L.
! IP(K), K.LT.N = INDEX OF K-TH PIVOT ROW.
! IP(N) = (-1)**(NUMBER OF INTERCHANGES) OR O .
! IER = 0 IF MATRIX A IS NONSINGULAR, OR K IF FOUND TO BE
! SINGULAR AT STAGE K.
! USE SL TO OBTAIN SLUTION OF LINEAR SYSTEM.
! DETERM(A) = IP(N)*A(1,1)*A(2,2)*...*A(N,N).
! IF IP(N)=O, A IS SINGULAR, SL WILL DIVIDE BY ZERO.
!
! REFERENCE..
! C. B. MOLER, ALGORITHM 423, LINEAR EQUATION SOLVER,
! C.A.C.M. 15 (1972), P. 274.
!-----------------------------------------------------------------------
IER = 0
IP(N) = 1
IF (N .EQ. 1) GO TO 70
NM1 = N - 1
DO 60 K = 1,NM1
KP1 = K + 1
M = K
DO 10 I = KP1,N
IF (DABS(A(I,K)) .GT. DABS(A(M,K))) M = I
10 CONTINUE
IP(K) = M
T = A(M,K)
IF (M .EQ. K) GO TO 20
IP(N) = -IP(N)
A(M,K) = A(K,K)
A(K,K) = T

20 CONTINUE
IF (T .EQ. 0.D0) GO TO 80
T = 1.D0/T
DO 30 I = KP1,N
30 A(I,K) = -A(I,K)*T
DO 50 J = KP1,N
T = A(M,J)
A(M,J) = A(K,J)
A(K,J) = T
IF (T .EQ. 0.D0) GO TO 45
DO 40 I = KP1,N
40 A(I,J) = A(I,J) + A(I,K)*T
45 CONTINUE
50 CONTINUE
60 CONTINUE
70 K = N
Dan Racoi
Elemente de Fortran 95
59
IF (A(N,N) .EQ. 0.D0) GO TO 80
RETURN
80 IER = K
IP(N) = 0
RETURN

END SUBROUTINE DEC

SUBROUTINE SOL (N, NDIM, A, B, IP)
! VERSION REAL DOUBLE PRECISION
INTEGER N,NDIM,IP,NM1,K,KP1,M,I,KB,KM1
DOUBLE PRECISION A,B,T
DIMENSION A(NDIM,N), B(N), IP(N)
!-----------------------------------------------------------------------
! SOLUTION OF LINEAR SYSTEM, A*X = B .
! INPUT..
! N = ORDER OF MATRIX.
! NDIM = DCLARED DIMENSION OF ARRAY A .
! A = TRIANGULARIZED MATRIX OBTAINED FROM DC.
! B = RIGHT HAND SIDE VECTOR.
! IP = PIVOT VECTOR OBTAINED FROM DC.
! DO NOT USE IF DC HAS SET IER .NE. 0.
! OUTPUT..
! B = SOLUTION VECTOR, X .
!-----------------------------------------------------------------------
IF (N .EQ. 1) GO TO 50
NM1 = N - 1
DO 20 K = 1,NM1
KP1 = K + 1
M = IP(K)
T = B(M)
B(M) = B(K)
B(K) = T
DO 10 I = KP1,N
10 B(I) = B(I) + A(I,K)*T
20 CONTINUE
DO 40 KB = 1,NM1
KM1 = N - KB
K = KM1 + 1
B(K) = B(K)/A(K,K)
T = -B(K)
DO 30 I = 1,KM1
30 B(I) = B(I) + A(I,K)*T
40 CONTINUE
50 B(1) = B(1)/A(1,1)
RETURN

END SUBROUTINE SOL

6.5.3 Calculul valorilor proprii

Numeroase probleme de inginerie (vibraiile structurilor aerospaiale) conduc la
probleme de valori proprii de tipul:
x Ax =
Cu s-au notat valorile proprii iar cu x vectorii proprii.
Matricea A poate fi real sau complex.
Rezultatele unor importante cercetri desfurate n anii 1970-1980 au condus la
realizarea unui pachet de programe numit EISPACK (NETLIB.ORG). n aceast colecie
de subrutine sunt programai algoritmii numerici pentru probleme de valori proprii.
Dan Racoi
Elemente de Fortran 95
60
Vom considera o problem un pic mai complicat, problema generalizat de
valori proprii:
Bx Ax =
Fie ecuaia diferenial, problema Sturm-Liouville:
b x a
y
dx
y d
<= <=
=
2
2

cu dou condiii la limite, pentru x=a i pentru x=b.
Considerm un sistem de funcii liniar independente, f
i
(x) care satisfac condiiile
la limite.
Cutm soluia n forma (metoda Galerkin):
) ( ) ( ) (
2 2 1 1
x f a x f a x y + =
Substituind aceast soluie n ecuaia diferenial obinem:
)) ( ) ( ( ) ( ) (
2 2 1 1
' '
2 2
' '
1 1
x f a x f a x f a x f a + = +
nmulim ultima ecuaie succesiv cu f
1
(x) i f
2
(x) i integrm de la a la b.
Se obine problema generalizat de valori proprii:
)
`

(
(
(
(

=
)
`

(
(
(
(





2
1
2 2 2 1
1 2 1 1
2
1
2
' '
2 2
' '
1
1
' '
2 1
' '
1
) ( ) ( ) ( ) (
) ( ) ( ) ( ) (
) ( ) ( ) ( ) (
) ( ) ( ) ( ) (
a
a
dx x f x f dx x f x f
dx x f x f dx x f x f
a
a
dx x f x f dx x f x f
dx x f x f dx x f x f
b
a
b
a
b
a
b
a
b
a
b
a
b
a
b
a

Se calculeaz analitic sau numeric integralele din ultima expresie i se obin
matricele A i B, respectiv problema de valori proprii generalizat:
)
`

=
)
`

2
1
2
1
a
a
B
a
a
A
Generalizarea la n mai mare dect doi este imediat. Matricele A i B au elemente
reale i n acest caz sunt simetrice.

B.S. Garbow, J.M. Boyle, J.J. Dongarra, C.B. Moler,
Matrix Eigensytem Routine EISPACK Guide Extension,
Lecture Notes in Computer Science,
Springer-Verlag, New York, 1977, p. 44


PROGRAM VALORI_PROPRII
!
! burton s. garbow,mathematics and computer science div,
! argonne national laboratory
!_____________________________________________________________
!
! Se rezolva problema de valori proprii generalizata
!
! A*x=lambda*B*x
!
! A si B sunt matrici reale
!
IMPLICIT NONE
INTEGER,PARAMETER :: N=5
Dan Racoi
Elemente de Fortran 95
61
REAL(8),DIMENSION(N,N) :: A,B,Z,ZR,ZI
REAL(8),DIMENSION(N) :: ALFR(N),ALFI(N),BETA(N)
INTEGER I,J,K,IERR,MATZ
REAL(8) DRAND
DO I=1,N ! genereaza aleator matricea A
DO J=1,N
A(I,J)=DRAND(0)
ENDDO
ENDDO
DO I=1,N ! genereaza aleator matricea B
DO J=1,N
B(I,J)=DRAND(0)
ENDDO
ENDDO
MATZ=1 ! se calculeaza valorile proprii si vectorii proprii
CALL RGG(N,N,A,B,ALFR,ALFI,BETA,MATZ,Z,IERR)
WRITE(*,*)'IERR=',IERR ! codul de eroare
!
! Valorile proprii
!
DO I=1,N
IF(BETA(I).NE.0.D0)THEN
WRITE(*,1)'VP=',I,ALFR(I)/BETA(I),ALFI(I)/BETA(I)
ELSE
WRITE(*,1)' ',I,ALFR(I),ALFI(I),BETA(I)
ENDIF
ENDDO
1 FORMAT(A,I2,2X,3G13.6)
!
! VECTORII PROPRII
!
! B.S. Garbow, J.M. Boyle, J.J. Dongarra, C.B. Moler,
! Matrix Eigensytem Routine EISPACK Guide Extension,
! Lecture Notes in Computer Science,
! Springer-Verlag, New York, 1977, p. 44
!
DO K=1,N
IF(ALFI(K).EQ.0.D0)THEN
DO J=1,N
ZR(J,K)=Z(J,K)
ZI(J,K)=0.D0
ENDDO
ELSEIF(ALFI(K)>0.D0)THEN
DO J=1,N
ZR(J,K)=Z(J,K)
ZI(J,K)=Z(J,K+1)
ENDDO
ELSEIF(ALFI(K)<0.D0)THEN
DO J=1,N
ZR(J,K)= ZR(J,K-1)
ZI(J,K)=-ZI(J,K-1)
ENDDO
ENDIF
ENDDO
DO I=1,N
WRITE(*,*)'VECTORUL PROPRIU ',I
WRITE(*,'(G13.6,2X,G13.6)')(ZR(J,I),ZI(J,I),J=1,N)
ENDDO
END PROGRAM VALORI_PROPRII

subroutine rgg(nm,n,a,b,alfr,alfi,beta,matz,z,ierr)
!
integer n,nm,ierr,matz
Dan Racoi
Elemente de Fortran 95
62
double precision a(nm,n),b(nm,n),alfr(n),alfi(n),beta(n),z(nm,n)
logical tf
!
! this subroutine calls the recommended sequence of
! subroutines from the eigensystem subroutine package (eispack)
! to find the eigenvalues and eigenvectors (if desired)
! for the real general generalized eigenproblem ax = (lambda)bx.
!
! on input
!
! nm must be set to the row dimension of the two-dimensional
! array parameters as declared in the calling program
! dimension statement.
!
! n is the order of the matrices a and b.
!
! a contains a real general matrix.
!
! b contains a real general matrix.
!
! matz is an integer variable set equal to zero if
! only eigenvalues are desired. otherwise it is set to
! any non-zero integer for both eigenvalues and eigenvectors.
!
! on output
!
! alfr and alfi contain the real and imaginary parts,
! respectively, of the numerators of the eigenvalues.
!
! beta contains the denominators of the eigenvalues,
! which are thus given by the ratios (alfr+i*alfi)/beta.
! complex conjugate pairs of eigenvalues appear consecutively
! with the eigenvalue having the positive imaginary part first.
!
! z contains the real and imaginary parts of the eigenvectors
! if matz is not zero. if the j-th eigenvalue is real, the
! j-th column of z contains its eigenvector. if the j-th
! eigenvalue is complex with positive imaginary part, the
! j-th and (j+1)-th columns of z contain the real and
! imaginary parts of its eigenvector. the conjugate of this
! vector is the eigenvector for the conjugate eigenvalue.
!
! ierr is an integer output variable set equal to an error
! completion code described in the documentation for qzit.
! the normal completion code is zero.
!

! questions and comments should be directed to burton s. garbow,
! mathematics and computer science div, argonne national laboratory
!
! this version dated august 1983.
!
! ------------------------------------------------------------------
!
if (n .le. nm) go to 10
ierr = 10 * n
go to 50
!
10 if (matz .ne. 0) go to 20
! .......... find eigenvalues only ..........
tf = .false.
call qzhes(nm,n,a,b,tf,z)
call qzit(nm,n,a,b,0.0d0,tf,z,ierr)
Dan Racoi
Elemente de Fortran 95
63
call qzval(nm,n,a,b,alfr,alfi,beta,tf,z)
go to 50
! .......... find both eigenvalues and eigenvectors ..........
20 tf = .true.
call qzhes(nm,n,a,b,tf,z)
call qzit(nm,n,a,b,0.0d0,tf,z,ierr)
call qzval(nm,n,a,b,alfr,alfi,beta,tf,z)
if (ierr .ne. 0) go to 50
call qzvec(nm,n,a,b,alfr,alfi,beta,z)
50 return
end subroutine rgg

INCLUDE 'C:\FOR\S_VALORI_PROPRII.F90'

7. Instruciunea COMMON

Instruciunea COMMON este utilizat pentru a transmite valorile variabilelor n
subprograme independent de lista de parametrii. Parametrii din instruciunea COMMON
trebuie s fie diferii de parametrii din lista de variabile.
Instruciunea COMMON este deosebit de puternic dar trebuie utilizat cu mare
atenie.

7.1 Instruciunea COMMON blank

Sintaxa instruciunii este:

common list_parametrii

Instruciunea COMMON se plaseaz n programul principal i n subprogramele
n care se transmit valorile parametrilor.

program common1
implicit none
real a,b,c
real x
common a,b,c
x=1.1
a=3. ; b=4. ; c=5. ! se initializeaza valorile variabilelor a,b,c
write(*,*)'a =',a,' b =',b,' c =',c, ' Programul principal'
call sub1(x)
call sub2
end program common1

subroutine sub1(x)
implicit none
real,intent(in) :: x
real a,b,c
common a,b,c
write(*,*)'x =',x
write(*,*)'a =',a,' b =',b,' c =',c, ' Subrutina sub1'
end subroutine sub1

subroutine sub2
implicit none
real a1,b1,c1
common a1,b1,c1 ! corespondenta intre variabilele din programul principal
! si subrutina
Dan Racoi
Elemente de Fortran 95
64
! a1 <==> a
! b1 <==> b
! c1 <==> c
!
write(*,*)'a1=',a1,' b1=',b1,' c1=',c1,' Subrutina sub2'
end subroutine sub2

7.2 Instruciunea COMMON etichetat

Sintaxa instruciunii este:

common /eticheta/list_variabile

integer k(3),jj
real x(3),z(3),a
complex z1(5),z2(5),zz

common /variabile_ntregi/k,jj
common /variabile_reale/x,z,a
common /variabile_complexe/z1,z2,zz

Se recomand gruparea variabilelor de acelai tip ntr-o instruciune common
etichetat pentru a conserva alinierea n memorie.

program common2
implicit none
integer,parameter :: n=3
real,dimension(n,n) :: mata,matb,matc
real,dimension(n) :: v1,v2,v3
real rand
integer i,j
common /tablouri/mata,matb,matc,v1,v2,v3
do i=1,n
do j=1,n
mata(i,j)=rand(0) ; matb(i,j)=rand(0)
enddo
v1(i)=rand(0)
v2(i)=rand(0)
enddo
call sub1 ! calculeaza matc, v2,v3
write(*,*)'Matricea C'
do i=1,n
write(*,'(3(g13.6,1x))')(matc(i,j),j=1,n)
enddo
write(*,*)'Vectorii v2 si v3'
write(*,'(2(g13.6,1x))')(v2(i),v3(i),i=1,n)
end program common2

subroutine sub1
implicit none
integer,parameter :: n=3
real,dimension(n,n) :: mata,matb,matc
real,dimension(n) :: v1,v2,v3

common /tablouri/mata,matb,matc,v1,v2,v3

matc=mata+matb ! se calculeaza suma matricilor si se transmite
Dan Racoi
Elemente de Fortran 95
65
! rezultatul prin common in programul principal

v2=matmul(mata,v1) ! se calculeaza produsul dintre matrice si
! vector si se transmite rezultatul in programul
! principal prin common

v3=matmul(matb,v1) ! se calculeaza produsul dintre matrice si
! vector si se transmite rezultatul in programul
! principal prin common
end subroutine sub1

7.3 Instruciunea BLOCK DATA

Instruciunea block data se utilizeaz pentru a iniializa valorile variabilelor din
common etichetat (labeled common) cu instruciunea data.
Sintaxa instruciunii este
block data nume
declaratii
common etichetat
data
end block data nume


program block_data
implicit none
real constanta_gazelor
real temperatura_standard
real presiunea_standard
common /termo/constanta_gazelor,temperatura_standard,presiunea_standard
!
! Valorile constantelor sunt precizate in procedura block data
! si transmise prin common.
!
write(*,*)'constanta gazelor =',constanta_gazelor,' J/mol/K'
write(*,*)'temperatura standard=',temperatura_standard,' K'
write(*,*)'presiunea standard =',presiunea_standard,' N/m**2'
end program block_data

block data constante_termodinamice
implicit none
real constanta_gazelor
real temperatura_standard
real presiunea_standard
common /termo/constanta_gazelor,temperatura_standard,presiunea_standard
!
! Initializarea variabilelor din common cu intructiunea data
!
data constanta_gazelor /8.31451/ ! J/mol/K
data temperatura_standard/298.15/ ! K
data presiunea_standard /1.e5/ ! N/m**2
end block data constante_termodinamice


10. Aplicaii
Se prezint n continuare o serie de aplicaii n FORTRAN utiliznd algoritmi
consacrai din bibliotecile de programe disponibile pe INTERNET (NETLIB.ORG).

Dan Racoi
Elemente de Fortran 95
66
10.1 Calculul integralelor definite. QUADPACK.

Quadpack este un pachet de programe f77 care calculeaz integrale definite.

R. Piessens, E. deDoncker-Kapenga, C. Uberhuber, D. Kahaner
Quadpack: a Subroutine Package for Automatic Integration
Springer Verlag, 1983. Series in Computational Mathematics v.1
515.43/Q1S 100394Z


program quadpack
!
!***keywords automatic integrator, general-purpose,
! integrand examinator, globally adaptive,
! gauss-kronrod
!***author piessens,robert ,appl. math. & progr. div - k.u.leuven
! de doncker,elise,appl. math. & progr. div. - k.u.leuven
!
implicit real(8) (a-h,o-z)

common /parametrii/pi,alfa ! parametrii definiti in programul
! principal

external f ! functia care se integreaza
!
! M.L. Smoleanski, Tabele de integrale nedefinite, Ed. Tehnica,
! Bucuresti 1972, traducere din limba rusa, formula 45.1, p. 129
!
primitiva(x)=exp(alfa*x)*
$ (alfa*sin(p*x)-p*cos(p*x))/(alfa**2+p**2)
pi=4.d0*atan(1.d0)

write(*,*)'program quadpack'

alfa=1.d0
p=pi

a=0.d0 ! limita inferioara a integralei definite
b=0.5d0 ! limita superioara a integralei definite
eps=1.d-8 ! toleranta impusa
key=2 ! 10-21 puncte gauss in formula de quadratura

call dr_dqag(f,a,b,eps,eps,key,rezult,abserr,ier)

write(*,*)'ier=',ier ! cod de eroare
write(*,*)'In=',rezult ! valoarea integralei calculata numeric
write(*,*)'Ia=',(primitiva(b)-primitiva(a)) ! analitic

end program quadpack

real(8) function f(x)
implicit real(8) (a-h,o-z)
g(x)=exp(alfa*x)*sin(p*x)
common /parametrii/pi,alfa
p=pi
f=g(x)
end
subroutine dr_dqag(f,a,b,epsabs,epsrel,key,result,abserr,ier)
implicit real(8) (a-h,o-z)
parameter (limit=128)
Dan Racoi
Elemente de Fortran 95
67
parameter (lenw=4*limit)
integer iwork(limit)
real(8) work(lenw)
external f
call dqag(f,a,b,epsabs,epsrel,key,result,abserr,neval,ier,
$ limit,lenw,last,iwork,work)

end
! subroutine dqag(f,a,b,epsabs,epsrel,key,result,abserr,neval,ier,
! * limit,lenw,last,iwork,work)
!***begin prologue dqag
!***date written 800101 (yymmdd)
!***revision date 830518 (yymmdd)
!***category no. h2a1a1
!***keywords automatic integrator, general-purpose,
! integrand examinator, globally adaptive,
! gauss-kronrod
!***author piessens,robert,appl. math. & progr. div - k.u.leuven
! de doncker,elise,appl. math. & progr. div. - k.u.leuven
!***purpose the routine calculates an approximation result to a given
! definite integral i = integral of f over (a,b),
! hopefully satisfying following claim for accuracy
! abs(i-result)le.max(epsabs,epsrel*abs(i)).
!***description
!
! computation of a definite integral
! standard fortran subroutine
! double precision version
!
! f - double precision
! function subprogam defining the integrand
! function f(x). the actual name for f needs to be
! declared e x t e r n a l in the driver program.
!
! a - double precision
! lower limit of integration
!
! b - double precision
! upper limit of integration
!
! epsabs - double precision
! absolute accoracy requested
! epsrel - double precision
! relative accuracy requested
! if epsabs.le.0
! and epsrel.lt.max(50*rel.mach.acc.,0.5d-28),
! the routine will end with ier = 6.
!
! key - integer
! key for choice of local integration rule
! a gauss-kronrod pair is used with
! 7 - 15 points if key.lt.2,
! 10 - 21 points if key = 2,
! 15 - 31 points if key = 3,
! 20 - 41 points if key = 4,
! 25 - 51 points if key = 5,
! 30 - 61 points if key.gt.5.
!
! on return
! result - double precision
! approximation to the integral
!
! abserr - double precision
Dan Racoi
Elemente de Fortran 95
68
! estimate of the modulus of the absolute error,
! which should equal or exceed abs(i-result)
!
! neval - integer
! number of integrand evaluations
!
! ier - integer
! ier = 0 normal and reliable termination of the
! routine. it is assumed that the requested
! accuracy has been achieved.
! ier.gt.0 abnormal termination of the routine
! the estimates for result and error are
! less reliable. it is assumed that the
! requested accuracy has not been achieved.
! error messages
! ier = 1 maximum number of subdivisions allowed
! has been achieved. one can allow more
! subdivisions by increasing the value of
! limit (and taking the according dimension
! adjustments into account). however, if
! this yield no improvement it is advised
! to analyze the integrand in order to
! determine the integration difficulaties.
! if the position of a local difficulty can
! be determined (i.e.singularity,
! discontinuity within the interval) one
! will probably gain from splitting up the
! interval at this point and calling the
! integrator on the subranges. if possible,
! an appropriate special-purpose integrator
! should be used which is designed for
! handling the type of difficulty involved.
! = 2 the occurrence of roundoff error is
! detected, which prevents the requested
! tolerance from being achieved.
! = 3 extremely bad integrand behaviour occurs
! at some points of the integration
! interval.
! = 6 the input is invalid, because
! (epsabs.le.0 and
! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
! or limit.lt.1 or lenw.lt.limit*4.
! result, abserr, neval, last are set
! to zero.
! except when lenw is invalid, iwork(1),
! work(limit*2+1) and work(limit*3+1) are
! set to zero, work(1) is set to a and
! work(limit+1) to b.
!
! dimensioning parameters
! limit - integer
! dimensioning parameter for iwork
! limit determines the maximum number of subintervals
! in the partition of the given integration interval
! (a,b), limit.ge.1.
! if limit.lt.1, the routine will end with ier = 6.
!
! lenw - integer
! dimensioning parameter for work
! lenw must be at least limit*4.
! if lenw.lt.limit*4, the routine will end with
! ier = 6.
!
Dan Racoi
Elemente de Fortran 95
69
! last - integer
! on return, last equals the number of subintervals
! produced in the subdiviosion process, which
! determines the number of significant elements
! actually in the work arrays.
!
! work arrays
! iwork - integer
! vector of dimension at least limit, the first k
! elements of which contain pointers to the error
! estimates over the subintervals, such that
! work(limit*3+iwork(1)),... , work(limit*3+iwork(k))
! form a decreasing sequence with k = last if
! last.le.(limit/2+2), and k = limit+1-last otherwise
!
! work - double precision
! vector of dimension at least lenw
! on return
! work(1), ..., work(last) contain the left end
! points of the subintervals in the partition of
! (a,b),
! work(limit+1), ..., work(limit+last) contain the
! right end points,
! work(limit*2+1), ..., work(limit*2+last) contain
! the integral approximations over the subintervals,
! work(limit*3+1), ..., work(limit*3+last) contain
! the error estimates.
!
!***references (none)
!***routines called dqage,xerror
!***end prologue dqag

include 'c:\for\s_quadpack.for'

10.2 Ecuaii difereniale ordinare. Problema Cauchy

Se consider sistemul de n ecuaii difereniale ordinare nonstiff:
) ,... , ( ) (
1
'
n i
y y x f x y = i=1,2,,n
cu condiia iniial:
0 0
0
) ( y x y
x x
i
=
=

Dac soluiile sistemului de ecuaii difereniale au scale diferite de timp, respectiv
unele soluii au o variaie mult mai rapid dect altele, atunci sistemul de ecuaii
difereniale este stiff.
Sistemele de ecuaii difereniale nonstiff se integreaz cu metode Runge Kutta
explicite.
Sistemele de ecuaii difereniale stiff se integreaz cu metode Runge Kutta
implicite.
E. Hairer, S. P. Norsett, S. Wanner, Solving Ordinary Differential Equations I,
Nonstiff Problems, Springer, New York. 1977, p. 127-128.
Vom ilustra metodele Runge Kutta explicite cu o problema celor trei corpuri cu
restricii. Se consider dou corpuri de mas 1- i n micare circular de rotaie n
plan i un al treilea corp de mas neglijabil care se mic n acelai plan. Ecuaiile sunt:
Dan Racoi
Elemente de Fortran 95
70

=
=
+ =
+ + =
=

+
+ =
1
012277471 . 0
) ) ((
) ) ((
2
2
'
5 . 1 2
2
2 '
1 2
5 . 1 2
2
2
1 1
2
2
1
2 ' '
1 2
' '
2
2
'
1
1
1 ' '
2 1
' '
1
y y D
y y D
D
y
D
y
y y y
D
y
D
y
y y y

Sistemul de dou ecuaii difereniale de ordinul doi se transform ntr-un sistem
de patru ecuaii difereniale de ordinul nti care se integreaz cu metoda DOPRI5:
2
2
1
2 '
3 2
' '
2
2
'
1
1
1 '
4 1
' '
1
4
'
2
3
'
1
2
2
D
y
D
y
y y y
D
y
D
y
y y y
y y
y y

+
+ =
=
=

Condiia iniial la x=0 este:
y
1
=0.994
y
2
=0.0D0
y
3
=0.0D0
y
4
=-2.00158510637908252240537862224
Sistemul de integreaz pn la:
x
end
=17.0652165601579625588917206249
Sistemul neliniar de patru ecuaii difereniale ordinare are soluii periodice.
Sistemul de patru ecuaii difereniale este descris n subrutina FAREN.
Soluia sistemului de ecuaii difereniale este scris n subrutina SOLOUT.
Reprezentarea grafic a soluiei este prezentat n Figura 10.2.1.
-1.5
-1
-0.5
0
0.5
1
1.5
-1.5 -1 -0.5 0 0.5 1
y
2
y1
Orbi ta Arensdorf
'dopri 5.txt' u 2:3

Figura 10.2.1. Reprezentarea soluiei sistemului de ecuaii difereniale n planul fazelor

C ----------------------------------------------------------
C NUMERICAL SOLUTION OF A SYSTEM OF FIRST 0RDER
Dan Racoi
Elemente de Fortran 95
71
C ORDINARY DIFFERENTIAL EQUATIONS Y'=F(X,Y).
C THIS IS AN EXPLICIT RUNGE-KUTTA METHOD OF ORDER (4)5
C DUE TO DORMAND & PRINCE (WITH STEPSIZE CONTROL AND
C DENSE OUTPUT).
C
C AUTHORS: E. HAIRER AND G. WANNER
C UNIVERSITE DE GENEVE, DEPT. DE MATHEMATIQUES
C CH-1211 GENEVE 24, SWITZERLAND
C E-MAIL: Ernst.Hairer@math.unige.ch
C Gerhard.Wanner@math.unige.ch
C
C THIS CODE IS DESCRIBED IN:
C E. HAIRER, S.P. NORSETT AND G. WANNER, SOLVING ORDINARY
C DIFFERENTIAL EQUATIONS I. NONSTIFF PROBLEMS. 2ND EDITION.
C SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS,
C SPRINGER-VERLAG (1993)
C
C VERSION OF APRIL 25, 1996

C * * * * * * * * * * * * * * * * * * * * * * * * *
C --- DRIVER FOR DOPRI5 ON ARENSTORF ORBIT
C * * * * * * * * * * * * * * * * * * * * * * * * *
IMPLICIT REAL*8 (A-H,O-Z)
PARAMETER (NDGL=4,NRDENS=4)
PARAMETER (LWORK=8*NDGL+5*NRDENS+21,LIWORK=NRDENS+21)
DIMENSION Y(NDGL),WORK(LWORK),IWORK(LIWORK),RPAR(2)
EXTERNAL FAREN,SOLOUT
C --- DIMENSION OF THE SYSTEM
OPEN(1,FILE='C:\FOR\DOPRI5.TXT')
N=NDGL
C --- OUTPUT ROUTINE (AND DENSE OUTPUT) IS USED DURING INTEGRATION
IOUT=2
C --- INITIAL VALUES AND ENDPOINT OF INTEGRATION
RPAR(1)=0.012277471D0
RPAR(2)=1.D0-RPAR(1)
X=0.0D0
Y(1)=0.994D0
Y(2)=0.0D0
Y(3)=0.0D0
Y(4)=-2.00158510637908252240537862224D0
XEND=17.0652165601579625588917206249D0
C --- REQUIRED (RELATIVE AND ABSOLUTE) TOLERANCE
ITOL=0
RTOL=1.0D-7
ATOL=RTOL
C --- DEFAULT VALUES FOR PARAMETERS
DO 10 I=1,20
IWORK(I)=0
10 WORK(I)=0.D0
C --- DENSE OUTPUT IS USED FOR THE TWO POSITION COORDINATES 1 AND 2
IWORK(5)=NRDENS
C --- CALL OF THE SUBROUTINE DOPRI5
CALL DOPRI5(N,FAREN,X,Y,XEND,
& RTOL,ATOL,ITOL,
& SOLOUT,IOUT,
& WORK,LWORK,IWORK,LIWORK,RPAR,IPAR,IDID)
C --- PRINT FINAL SOLUTION
WRITE (6,99) Y(1),Y(2)
99 FORMAT(1X,'X = XEND Y =',2E18.10)
C --- PRINT STATISTICS
WRITE (6,91) RTOL,(IWORK(J),J=17,20)
91 FORMAT(' tol=',D8.2,' fcn=',I5,' step=',I4,
& ' accpt=',I4,' rejct=',I3)
Dan Racoi
Elemente de Fortran 95
72
STOP
END
C
C
SUBROUTINE SOLOUT (NR,XOLD,X,Y,N,CON,ICOMP,ND,RPAR,IPAR,IRTRN)
C --- PRINTS SOLUTION AT EQUIDISTANT OUTPUT-POINTS BY USING "CONTD5"
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION Y(N),CON(5*ND),ICOMP(ND),RPAR(2)
COMMON /INTERN/XOUT,DXOUT
DXOUT=0.1D0
IF (NR.EQ.1) THEN
WRITE (6,99) X,Y(1),Y(2),NR-1
WRITE (1,98) X,Y(1),Y(2),Y(3),Y(4)
XOUT=X+DXOUT
ELSE
10 CONTINUE
IF (X.GE.XOUT) THEN
WRITE (6,99) XOUT,CONTD5(1,XOUT,CON,ICOMP,ND),
& CONTD5(2,XOUT,CON,ICOMP,ND),NR-1
WRITE (1,98) XOUT,CONTD5(1,XOUT,CON,ICOMP,ND),
& CONTD5(2,XOUT,CON,ICOMP,ND),
# CONTD5(3,XOUT,CON,ICOMP,ND),
# CONTD5(4,XOUT,CON,ICOMP,ND)
XOUT=XOUT+DXOUT
GOTO 10
END IF
END IF
99 FORMAT(1X,'X =',F6.2,' Y =',2E18.10,' NSTEP =',I4)
98 FORMAT(5(G13.6,1X))
RETURN
END
C
SUBROUTINE FAREN(N,X,Y,F,RPAR,IPAR)
C --- ARENSTORF ORBIT
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION Y(N),F(N),RPAR(2)
AMU=RPAR(1)
AMUP=RPAR(2)
F(1)=Y(3)
F(2)=Y(4)
R1=(Y(1)+AMU)**2+Y(2)**2
R1=R1*SQRT(R1)
R2=(Y(1)-AMUP)**2+Y(2)**2
R2=R2*SQRT(R2)
F(3)=Y(1)+2*Y(4)-AMUP*(Y(1)+AMU)/R1-AMU*(Y(1)-AMUP)/R2
F(4)=Y(2)-2*Y(3)-AMUP*Y(2)/R1-AMU*Y(2)/R2
RETURN
END

include 'c:\for\dopri5.for'

10.3 Ecuaia Burgers omogen

Se consider ecuaia:
0
) (
=

x
u f
t
u

cu condiia iniial, problema Cauchy:
la t=0 ) sin( ) ( ) (
0
x x u x u = = , [ ] 2 , 0 x .
Pentru ecuaia lui Burgers:
Dan Racoi
Elemente de Fortran 95
73
2
) , (
) )( , ( ) ( ) (
2
) (
2
v u
v u a
v u v u a v f u f
u
u f
+
=
=
=

Se consider funcia flux numeric (Yee):
[ ] ) ( ) , ( ) ( ) ( 5 . 0 ) , ( u v v u a v f u f v u h + =
H.C. Yee, A Class of High-Resolution Explicit and Implicit
Shock Capturing Method, NASA Technical Memorandum 101088,
February 1989
Se consider grila echidistant cu pasul x pe axa x cu nodurile i=0,1,,n+1.
La momentul de timp t se determin viteza maxim n interval:
) max(
max
t
i
u u = i=1,2,,n
i se calculeaz pasul de timp (CFL):
max
9 . 0
u
x
t

=
Trecerea la nivelul urmtor de timp se face cu ecuaia:
[ ] ) , ( ) , (
1 1
t
i
t
i
t
i
t
i
t
i
t t
i
u u h u u h
x
t
u u
+
+

+ = , i=1,2,,n
In nodurile i=0 i i=n+1 se face o extrapolare a soluiei (condiie la limit numeric).
Soluia ecuaiei la momentul de timp t=1 este prezentat n Figura 10.3.1.

-1
-0.5
0
0.5
1
0 0.5 1 1.5 2
u
(
x
,
1
)
x
Ecuati a Burgers omogena
'uo3' u 1:2
'ut3' u 1:2

Figura 10.3.1 Soluia ecuaiei Burgers omogene la t=1.
uo3 condiia iniial
ut3 solutia la t=1

program roe
!
! H.C. Yee, A Class of High-Resolution Explicit and Implicit
! Shock Capturing Method, NASA Technical Memorandum 101088,
! February 1989
!
!
! Ecuatia Burgers omogena
!
Dan Racoi
Elemente de Fortran 95
74
! 0<x<2
! uo(x)=sin(pi*x)
! 0<t<1
implicit none
integer,parameter :: m=101
real(8) x(m),u(0:m+1),v(0:m+1)
integer i
real uzero,umax,dx
real h,t,t0,tf,dt,xs,xd

open(1,file='c:\for\uo3')
open(2,file='c:\for\ut3')

t0=0.d0 ; tf=1.d0 ! intervalul de timp
xs=0.d0 ; xd=2.d0 ! domeniul de integrare
dx=(xd-xs)/(m-1) ! pasul de discretizare pe axa x
do i=1,m
x(i)=xs+(i-1)*dx ! grila discreta
u(i)=uzero(x(i)) ! viteza initiala
write(1,'(1x,2f11.4)')x(i),u(i)
enddo
t=t0
!
! Iteratii in timp si spatiu
!
do while(t<=tf)

u(0) =u(1) ! extrapolare conditii la limita
u(m+1)=u(m)

umax=0.d0 ! se determina viteza maxima pe tot intervalul
do i=1,m
umax=max(abs(u(i)),umax)
enddo
!
! Pasul de timp
!
dt=0.9d0*dx/umax ! Courant Friederics Levy CFL
!
! viteza la t1=t+dt ==> v

!
do i=1,m
v(i)=u(i)-dt/dx*(h(u(i),u(i+1))-h(u(i-1),u(i)))
enddo
t=t+dt
do i=1,m ! actualizarea vitezelor
u(i)=v(i)
enddo
enddo
!
! Solutia la t=tf
!
do i=1,m
write(2,'(1x,4f11.4)')x(i),u(i)
enddo

end program roe

real(8) function h(u,v) ! functia flux numeric
implicit none
real(8),intent(in) :: u,v
real(8) f,q,a
Dan Racoi
Elemente de Fortran 95
75

f(q)=0.5d0*q*q

h=0.5d0*(f(u)+f(v)-abs(a(u,v))*(v-u))

end function h

real(8) function a(u,v) ! viteza de propagare la interfata
implicit none
real(8),intent(in) :: u,v
a=0.5d0*(u+v)
end

real(8) function uzero(x) ! conditia initiala
implicit none
real(8),intent(in) :: x
real(8) pi
pi=4.d0*atan(1.d0)
uzero=sin(pi*x)
end function uzero

10.4 Ecuaia Poisson
Se consider ecuaia cu derivate pariale:
2
2
2
2
2
=

y
u
x
u

n domeniul dreptunghiular:
b x b
a x a
+ < <
+ < <

cu condiia la limite u=0 pe frontier.
Fie n
x
numrul de puncte ale grilei de discretizare pe axa x, n
y
numrul de puncte
pe axa y. Se definesc pai de discretizare:
1
2
1
2

=
y
x
n
b
y
n
a
x

i grila de discretizare:
x i a x
i
+ = ) 1 ( i=1,2,,n
x
y j b y
i
+ = ) 1 ( j=1,2,,n
y

i valorile funciei n nodurile reelei:
) , (
, j i j i
y x u u = i=1,2,,n
x
j=1,2,,n
y
.
Derivatele pariale sunt discretizate cu formule de derivare numeric cu diferene
centrale:
2
2 2
2
1 , , 1 ,
2
. 1 , , 1
=

+
+

+
+ +
y
u u u
x
u u u
j i j i j i j i j i j i

Se definete sistemul de ecuaii algebrice lineare:
0 2 ) 2 ( 2
2
2
2
1 , , 1 , , 1 , . 1 ,
= +

+ + + =
+ +
x
y
x
u u u u u u f
j i j i j i j i j i j i j i

i=2,,n
x
-1, j=2,,n
y
-1
Dan Racoi
Elemente de Fortran 95
76
Sistemul de ecuaii se completeaz cu ecuaii pe frontier (condiiile la limite).
Sistemul algebric linear de nx*ny ecuaii se rezolv cu metoda Newton, o iteraie.
Jacobianul se calculeaz numeric cu formule de derivare cu diferene centrale.

0
0.05
0.1
0.15
0.2
0.25
-1 -0.5 0 0.5 1
u
y
Torsi unea unei bare dreptunghi l are

Figura 10.4. Soluia numeric i soluia analitic pentru x=-0.05


module tablouri
!-----------------------------------------------------+
! Se rezolva ecuatia Poisson, |
! torsiunea unei bare prismatice: nabla(u)=-2 |
!-----------------------------------------------------+
implicit none
integer,parameter :: nx=21 ! numarul de puncte de discretizare pe axa x
integer,parameter :: ny=41 ! numarul de puncte de discretizare pe axa y
integer,parameter :: n=nx*ny ! numarul de necunoscute
real(8) :: a=+0.5d0 ! -a < x < +a

real(8) :: b=+1.0d0 ! -b < y < +b
real(8) :: hx ! pasul de discretizare pe axa x
real(8) :: hy ! pasul de discretizare pe axa y
real(8),dimension(nx) :: x ! abscise
real(8),dimension(ny) :: y ! ordonate

real(8),dimension(n) :: z ! vectorul necunoscutelor
real(8),dimension(n) :: f ! vectorul functiilor
real(8),dimension(n,n):: df ! Jacobianul sistemului de ecuatii
real(8),dimension(n) :: dx,bb ! work space
integer,dimension(n) :: ip ! vectorul permutarilor de linii (Gauss)
real(8),dimension(n) :: fp,fm,xs ! work space
real(8) :: pi=3.14159265358979d0
end module tablouri

program ps3
use tablouri
!
! Ecuatia lui Poisson in dreptunghi
! Torsiunea unei bare prismatice.
!
! nabla(u)=-2
!
! -a<x<a ; -b<y<b ; u=0 pe contur
!
! Kantorovici si Krilov, Metode aproximative ale analizei superioare
! Editura Academiei Romane, Bucuresti 1954, traducere din limba rusa,
Dan Racoi
Elemente de Fortran 95
77
! vol 2., p. 392
!
! u(x,y) serii duble, functia ue(x,y)
!
implicit none

integer i,j
integer ier ! cod de eroare Gauss /=0 Jacobian singular
real(8) pas ! pas de derivare numerica
real(8) ue ! calculeaza solutia analitica
real(8) uex ! solutia analitica
real(8) zc ! solutia numerica

open(1,file='c:\for\ps3.txt')
write(1,*)'program ps3'
write(1,*)'nabla(u)=-2'
write(1,*)'Solutia analitica (serii duble) Kantorovici si Krilov,'
write(1,*)'"Metode aproximative ale analizei superioare",'
write(1,*)'Ed. Academiei, Bucuresti 1954, traducere din limba rusa,'

write(1,*)' p. 394'

hx=2.d0*a/(nx-1) ! pasul de discretizare pe axa x
hy=2.d0*b/(ny-1) ! pasul de discretizare pe axa y

do i=1,nx ; x(i)=-a+(i-1)*hx ; enddo ! abscise
do j=1,ny ; y(j)=-b+(j-1)*hy ; enddo ! ordonate

z=0.d0 ! Aproximatia initiala

call sist(z,f)
!
! Jacobian F numeric
!
xs=z
pas=1.D0/512.D0 ! pas derivare numerica diferente centrale

do j=1,n
xs(j)=z(j)-pas ! x(j)-h
call sist(xs,fm) ! f( ...,x(j)-h,...)
xs (j)=z(j)+pas ! x(j)+h
call sist(xs,fp) ! f( ...,x(j)+h,...)
df(:,j)=(fp-fm)/(pas+pas) ! coloana j din Jacobian
xs(j)=z(j) ! restaurare x(j)
enddo
!
! [J]{dx}=-{f} Newton pentru {f}={0}
!
call dec(n,n,df,ip,ier) ! Gauss LU
if(ier.ne.0)stop 'matrice singulara'
bb=-f
call sol(n,n,df,bb,ip) ! Retrosubstitutie
z=z+bb ! un pas Newton

write(1,*)'Solutia problemei Poisson'
write(1,*)' x y numeric analitic eroare'
i=nx/2
do j=1,ny
uex=ue(x(i),y(j)) ; zc=z(i+(j-1)*nx)
write(1,'(2f11.4,2x,3f12.5)')x(i),y(j),zc,uex,zc-uex
enddo
write(1,*)
end program ps3
Dan Racoi
Elemente de Fortran 95
78

real(8) function ue(xx,yy)
use tablouri
implicit none
real(8),intent(in) :: xx,yy
real(8) ss,c1
integer mm,nn
!
! Solutia analitica (serii duble) Kantorovici si Krilov p. 394
!
ss=0.d0
do mm=1,41,2
do nn=1,41,2
c1=(-1.d0)**(0.5d0*(mm+nn)-1)/(mm*nn*(mm**2*b**2+nn**2*a**2))
ss=ss+c1*cos(mm*pi*xx/2.d0/a)*cos(nn*pi*yy/2.d0/b)
enddo
enddo
ue=ss*a**2*b**2*128/pi**4
end

subroutine sist(zz,gg)
use tablouri
implicit none
real(8),dimension(n),intent(in ) :: zz(n) ! vectorul necunoscutelor
real(8),dimension(n),intent(out) :: gg(n) ! vectorul functiilor
integer i,j
real(8) s1,s2

do j=1,ny
gg(nx+(j-1)*nx)=zz(nx+(j-1)*nx) ! sus (boundary)
gg(1 +(j-1)*nx)=zz(1 +(j-1)*nx) ! jos (boundary)
enddo

do i=2,nx-1
gg(i +(1-1)*nx)=zz(i+( 1-1)*nx) ! stanga (boundary)
gg(i+(ny-1)*nx)=zz(i+(ny-1)*nx) ! dreapta (boundary)
enddo

do i=2,nx-1 ! discretizare cu diferenta centrale
do j=2,ny-1
s1=(zz(i +(j-2)*nx)-2.d0*zz(i +(j-1)*nx)+zz(i +(j )*nx))
s2=(zz(i-1+(j-1)*nx)-2.d0*zz(i +(j-1)*nx)+zz(i+1+(j-1)*nx))
gg(i+(j-1)*nx)=s1+s2*(hx/hy)**2+2.d0*hx**2
enddo
enddo

end
include 'c:\for\decsol.f90' ! Gauss descompunere LU ; Retrosubstitutie

10.5 Ecuaia de potenial pe cerc

Se consider ecuaia cu derivate pariale:
0 1
2
1 1
2
2 2
2 2 2
2
2
2
2
2
2
2
=

|
|

\
|
+ +

|
|

\
|
+

|
|

\
|



r a
v
r ra
v v
r a
v
r a
v
r r

( ) ) (
2
) 1 (
2 2 2
max
2

v v V a
r
+

=
Se determin soluiile periodice ale ecuaiei de potenial cu condiiile la limite:
Dan Racoi
Elemente de Fortran 95
79
r=r
1
: 0 =

=
r
v
r


r=r
2
: cos

= V
Derivatele pariale se discretizeaz cu formule cu diferene centrale. Se obine un
sistem algebric neliniar care se rezolv cu metoda Newton. Jacobianul sistemului este
calculat numeric. Aproximaia iniial este soluia ecuaiei Laplace pe cerc n curent
paralel. Soluia numeric se compar cu soluia obinut prin dezvoltare n serie.
Rezultatele sunt prezentate n figura 10.5.1.


-2.5
-2
-1.5
-1
-0.5
0
0.5
1
1.5
2
2.5
0 1 2 3 4 5 6 7
V
_
t
e
t
a
Teta
Ecuati a de potenti al pe cerc, Mach=0.4

Figura 10.5.1. Soluia numeric (puncte) i soluia obinut prin dezvoltare n serie
Mach=0.4.


MODULE REZERVARE_MEMORIE
PARAMETER (NR=101,NT=37,MM=NR*NT,NEC=MM)
REAL(8) DR,DT,TETA(NT),VINF,VMAX
REAL(8) PT(NR,-1:NT+2)
REAL(8) ZZ(NEC),FCT(NEC),DFDZ(NEC,NEC)
REAL(8) FP(NEC),FM(NEC),XS(NEC)
INTEGER IP(NEC)
REAL(8) :: TINF=300.D0
REAL(8) :: HI=1.4D0
REAL(8) :: RG=287.D0
REAL(8) :: MACH=0.4D0
REAL(8) :: R1=1.D0
REAL(8) :: R2=11.D0
REAL(8) :: PI=3.14159265358979D0
END MODULE REZERVARE_MEMORIE

PROGRAM POTENTIAL_CERC_NELINIAR
USE REZERVARE_MEMORIE
!
! Ecuatia de potential 2D cerc
!
! v*grad(v*v/2)=a**2*div(v)
!
! cp*T+0.5*v*v=cp*t_inf+0.5*v_inf*v_inf
!
! a**2=hi*r*t
!
IMPLICIT REAL*8 (A-H,O-Z)

Dan Racoi
Elemente de Fortran 95
80
OPEN(1,FILE='C:\FOR\p2.txt')

CP=HI*RG/(HI-1.D0)
AINF=SQRT(HI*RG*TINF)
VINF=AINF*MACH
VMAX=SQRT(2.D0*CP*TINF+VINF**2)

DR=(R2-R1)/(NR-1.D0) ;
DT=2.D0*PI/(NT-1.D0)
DO J=1,NT ; TETA(J)=(J-1)*DT ; ENDDO
K=0
DO I=1,NR
RR=R1+(I-1)*DR
DO J=1,NT
K=K+1
ZZ(K)=VINF/VMAX*(RR+1.D0/RR)*COS(TETA(J))
ENDDO
ENDDO
CALL SIST(ZZ,FCT)
H=1.D0/512.D0 ! Pasa derivare numerica
DO NEWTON=1,10 ! iteratii Newton
XS=ZZ
DO J=1,NEC ! calculul numeric al Jacobianului
XS(J)=ZZ(J)+H
CALL SIST(XS,FP)
XS(J)=ZZ(J)-H
CALL SIST(XS,FM)
DFDZ(:,J)=(FP-FM)/(H+H) ! diferente centrale coloana j
XS(J)=ZZ(J)
ENDDO
CALL DEC(NEC,NEC,DFDZ,IP,IER) ! descompunere LU (Gauss)
IF(IER.NE.0)STOP 'JACOBIAN SINGULAR'
FCT=-FCT
CALL SOL(NEC,NEC,DFDZ,FCT,IP) ! retrosubstitutie
ZZ=ZZ+FCT ! corectii NEWTON
CALL SIST(ZZ,FCT)
ERM=MAXVAL(ABS(FCT)) ! norma erorii
WRITE(*,'(1X,A,I3,A,F13.6)')'It=',NEWTON,' Er=',ERM
IF(ERM.LT.0.00001D0)EXIT ! convergenta
ENDDO
K=0
DO I=1,NR
DO J=1,NT
K=K+1 ; PT(I,J)=ZZ(K)*(VMAX/VINF)
ENDDO
ENDDO

DO I=1,NR ! periodicitate
PT(I,0 )=PT(I,NT-1)
PT(I,-1 )=PT(I,nt-2)
PT(I,NT+1)=PT(I,2)
PT(I,NT+2)=PT(I,3)
ENDDO

DO I=1,1 ! Solutia pe cerc
RR=R1+(I-1)*DR ! Raza
DO J=1,NT
TE=TETA(J)
VT=(PT(I,J+1)-PT(I,J-1))/(DT+DT)/RR ! Derivata potentialului

! Solutia obtinuta prin dezvoltare in serie

VTE=2.D0*SIN(TE)+MACH**2*(2.D0/3.D0*SIN(TE)-0.5D0*SIN(3.D0*TE)) &
Dan Racoi
Elemente de Fortran 95
81
+MACH**4*( 37.D0/40.D0*SIN(TE) &
-25.D0/24.D0*SIN(3.D0*TE) &
+ 3.D0/8.D0 *SIN(5.D0*TE)+ &
(HI-1.D0)*(23.D0/120.D0*SIN(TE)-11.D0/40.D0*SIN(3.D0*TE)+ &
1.D0/8.D0*SIN(5.D0*TE)))
VTE=-VTE
WRITE(*,'(1X,6F12.4)')TE,VT,VTE,VT-VTE
IF(I.EQ.1)THEN
WRITE(1,'(1X,6F12.4)')TE,VT,VTE,VT-VTE
ENDIF
ENDDO
WRITE(1,*)
ENDDO
END PROGRAM POTENTIAL_CERC_NELINIAR

SUBROUTINE SIST(ZZL,F)
USE REZERVARE_MEMORIE
IMPLICIT REAL*8 (A-H,O-Z)
REAL(8),DIMENSION(NEC),INTENT(IN ) :: ZZL
REAL(8),DIMENSION(NEC),INTENT(OUT) :: F

K=0
DO I=1,NR
DO J=1,NT
K=K+1
PT(I,J)=ZZL(K)
ENDDO
ENDDO

DO I=1,NR ! Periodicitate
PT(I,0 )=PT(I,NT-1)
PT(I,-1 )=PT(I,NT-2)
PT(I,NT+1)=PT(I,2)
PT(I,NT+2)=PT(I,3)
ENDDO

K=0
DO J=1,NT ! Conditia la limita pe cerc ; vr=0
K=K+1
F(K)=-3.D0*PT(1,J)+4.D0*PT(2,J)-PT(3,J) ! R=R1
ENDDO

DO J=1,NT ! Conditia la limita R=R2 "Infinit"
K=K+1
F(K)=PT(NR,J)-(VINF/VMAX)*R2*COS(TETA(J))
ENDDO

DT1=1.D0/DT**2
DC=1.D0/DR**2
DO I=2,NR-1
DO J=1,NT
RR=R1+(I-1)*DR
VR=(PT(I+1,J)-PT(I-1,J))/(DR+DR)
VT=(PT(I,J+1)-PT(I,J-1))/(DT+DT)/RR
AP=(HI-1.D0)/2.D0*(1.D0-VR**2-VT**2)
D2PDT2=(- 1.D0*PT(I,J-2)+ &
+16.D0*PT(I,J-1) &
-30.D0*PT(I,J ) &
+16.D0*PT(I,J+1) &
- 1.D0*PT(I,J+2))*DT1/12.D0
D2PDR2=(PT(I+1,J)-2.D0*PT(I,J)+PT(I-1,J))*DC
D2PDRDT=(PT(I+1,J+1)+PT(I-1,J-1)- &
PT(I+1,J-1)-PT(I-1,J+1))/4.D0/DR/DT
Dan Racoi
Elemente de Fortran 95
82
DPDR=(PT(I+1,J)-PT(I-1,J))/(DR+DR)
K=K+1
C1=1.D0-VR**2/AP
C2=1.D0-VT**2/AP
C3=-2.D0*VR*VT/AP
C4=1.D0+VT**2/AP
F(K)=C1*D2PDR2+C2/RR**2*D2PDT2+C3*D2PDRDT/RR+C4/RR*DPDR
ENDDO
ENDDO

END SUBROUTINE SIST

INCLUDE 'C:\FOR\DECSOL.F90'

10.6 Rezolvarea sistemelor de ecuaii algebrice neliniare

program powell_hybrid
!
! Rezolva sisteme algebrice neliniare cu algoritmul Powell hibrid
! Sistemul algebric este descris in subrutina sist
!
! Reference:
!
! Jorge More, Burton Garbow and Kenneth Hillstrom,
! User Guide for MINPACK-1
! Argonne National Laboratory,
! Argonne, Illinois.
!
! Modified by:
!
! John Burkardt
!
implicit none
integer, parameter :: n=2 ! numarul de necunoscute
real(8) x(n) ! vectorul necunoscutelor
real(8) f(n) ! vectorul functiilor
real(8) tol ! precizia impusa
integer i,info
external sist ! sistemul de ecuatii neliniare

write(*,'(a,/)')'Program powell_hybrid'

tol=1.d-6 ! precizia impusa
x(1)=0.d0 ! aproximatia initiala x(1)
x(2)=0.d0 ! aproximatia initiala x(2)

call hybrd1(sist,n,x,f,tol,info)

write(*,*)'info=',info

select case(info)
case(0)
write(*,*)'improper input parameters'
case(1)
write(*,*)'algorithm estimates that the relative error between X and'
write(*,'(a,g13.5)')' the solution is at most TOL=',tol
case(2)
write(*,*)'number of calls to FCN has reached or exceeded 200*(N+1)'
case(3)
write(*,*)' TOL is too small. No further improvement in the'
write(*,*)' approximate solution X is possible'
case(4)
Dan Racoi
Elemente de Fortran 95
83
write(*,*)'the iteration is not making good progress'
end select

write(*,'(/,a,/)')'Solutia'
write(*,'(a,i1,a,g14.7,a,i1,a,f13.6)') &
('x(',i,')=',x(i),'f(',i,')=',f(i),i=1,n)

end program powell_hybrid

subroutine sist(n,x,f,iflag)
implicit none
integer,intent(in ) :: n
real(8),intent(in ),dimension(n) :: x
real(8),intent(out),dimension(n) :: f
integer,intent(inout) :: iflag

f(1)=x(1)**2+x(2)**2-1.d0
f(2)=x(1)-x(2)
end subroutine sist

!*****************************************************************************8
0
!
!! HYBRD1 seeks a zero of N nonlinear equations in N variables.
!
! Discussion:
!
! HYBRD1 finds a zero of a system of N nonlinear functions in N variables
! by a modification of the Powell hybrid method. This is done by using the
! more general nonlinear equation solver HYBRD. The user must provide a
! subroutine which calculates the functions. The jacobian is then
! calculated by a forward-difference approximation.
!
! Reference:
!
! Jorge More, Burton Garbow and Kenneth Hillstrom,
! User Guide for MINPACK-1
! Argonne National Laboratory,
! Argonne, Illinois.
!
! Modified by:
!
! John Burkardt
!

include 'c:\for\minpack.f90'

You might also like