P. 1
Fort An

Fort An

|Views: 12|Likes:
Published by Alexandra Barbu

More info:

Published by: Alexandra Barbu on Dec 15, 2010
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

01/10/2011

pdf

text

original

Dan RacoŃi

Elemente de Fortran 95
1
Cuprins
0. Introducere
1.0 Constante şi variabile
1.1 OperaŃii algebrice simple
2.1 InstrucŃiunea IF
2.1.1 InstrucŃiunea IF aritmetic
2.1.2 InstrucŃiunea IF logic
2.1.3 InstrucŃiunea BLOCK IF
2.1.4 Compararea şirurilor de caractere
2.1.5 InstrucŃiunea select case
3. InstrucŃiunea DO
3.1 Forma 1
3.2 Forma 2
3.3 Forma 3
3.4 InstrucŃiunea DO WHILE
3.5 IteraŃii
3.5.1 Calculul radicalului
3.5.2 Rezolvarea ecuaŃiilor algebrice neliniare cu metoda Newton
3.5.3 Rezolvarea sistemelor algebrice neliniare de două ecuaŃii cu metoda Newton
3.5.4 Rezolvarea ecuaŃiilor algebrice polinomiale cu coeficienŃi complecşi cu metoda
Newton
4. Dezvoltări în serie
5. Tablouri
5.1 Vectori
5.2 Matrice
5.3 Gauss Seidel
5.4 Alocarea dinamică de memorie (în execuŃie)
6. FuncŃii şi subprograme
6.1 Clauza contains. FuncŃii interne
6.2 FuncŃii externe
6.3 FuncŃii în complex
6.4 InstrucŃiunea external
6.5 Subrutine
6.5.1 Transmiterea tablourilor la subprograme
6.5.2 Rezolvarea sistemelor de ecuaŃii algebrice lineare
6.5.3 Calculul valorilor proprii
7. InstrucŃiunea COMMON
7.1 InstrucŃiunea COMMON blank
7.2 InstrucŃiunea COMMON etichetat
7.3 InstrucŃiunea BLOCK DATA
8. InstrucŃiunea INTERFACE
9. InstrucŃiunea MODULE
10. AplicaŃii
10.1 Calculul integralelor definite, QUADPACK
10.2 Integrarea ecuaŃiilor diferenŃiale ordinare, problema Cauchy
10.3 EcuaŃia Burgers omogenă
Dan RacoŃi
Elemente de Fortran 95
2
10.4 EcuaŃia Poisson
10.5 EcuaŃia de potenŃial pe cerc
10.6 Rezolvarea sistemelor de ecuaŃii neliniare

0. Introducere
Fortran este un limbaj de programare potrivit în special pentru calculule
numerice şi calcule ştiinŃifice. Limbajul dezvoltat plecând 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 adăugat 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 evoluŃie 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 instrucŃiuni incluzând instrucŃiunea 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
aplicaŃii mai complexe (ecuaŃii diferenŃiale cu derivate parŃiale 2D). Unele programe au
fost păstrate în forma originală deoarece sunt algoritmi omologaŃi.
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ă
instrucŃiune. Comentariile încep cu litera C din coloana 1 sau cu !.
Următorul 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 RacoŃi
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
sfârşitul 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 RacoŃi
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 următoarele tipuri de constante:
a) Constante de tip întreg, numere cu semn fără 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 adevărat şi .false. pentru fals.
g) Constante de tip şir de caractere:
‘sir1’,’sirul_doi_de_caractere’,”Van’t 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 RacoŃi
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 RacoŃi
Elemente de Fortran 95
6
logical listă_variabile

logical predicat1,predicat2
Variabilele de tip logic iau valorile adevărat .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 RacoŃi
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 OperaŃii algebrice simple

Programul p1 utilizează limbajul FORTRAN pentru a operaŃii algebrice
elementare în real şi complex. Se utilizează convenŃia 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 RacoŃi
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 operaŃii algebrice
elementare în real şi complex. Se utilizează convenŃia 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 RacoŃi
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 funcŃiilor formulă (statement functions).
FuncŃiile formulă corespund funcŃiilor din analiza matematică (funcŃii reale de
una sau mai multe variabile reale sau complexe).

nume_funcŃie(argumente_formale)=expresie_aritmetică

In funcŃia formulă pe lângă variabile se pot utiliza constante definite în program
înainte de apelul funcŃiei.
Apelul funcŃiei se face prin nume şi cu argumentele efective.

valoare=nume_funcŃie(argumente_efective)

Există o corespondenŃă biunivocă între tipul şi numărul argumentelor formale şi efective.
In cazul în care funcŃia este mai complexă se utilizează clauza contains sau
funcŃii externe.
Programul p2 calculează funcŃiile:
) (
) ( ' ) ( ) ( ) ( '
) ( '
) (
) (
) (
) 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ă convenŃia implicită de declarare a variabilelor. În programul p2e se
utilizează convenŃia explicită de declarare a variabilelor.
Dan RacoŃi
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ă soluŃia unui sistem de două ecuaŃii algebrice liniare:
)
`
¹
¹
´
¦
=
)
`
¹
¹
´
¦

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

cu metoda Cramer. Se calculează determinanŃii de ordinul doi:
Dan RacoŃi
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ă soluŃia unui sistem de trei ecuaŃii algebrice liniare cu
metoda Cramer. Se utilizează convenŃia implicită de declarare a variabilelor. In
programul p4e se utilizează convenŃia explicită de declarare a variabilelor.

Dan RacoŃi
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.
DeterminanŃii 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 defineşte o funcŃie formulă pentru calculul determinantului de ordinul doi si o
funcŃie formulă pentru calculul determinantului de ordinul trei care utilizează funcŃia
formulă a determinantului de ordin 2.
SoluŃiile 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 RacoŃi
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 RacoŃi
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 InstrucŃiunea IF (dacă)
InstrucŃiunea IF este utilizată pentru comparaŃii.
2.1.1 InstrucŃiunea IF aritmetic
if(expresie)eticheta_1,eticheta_2,eticheta_3

Dacă valoarea numerică a expresiei este mai mică decât 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 decât zero se face salt la
eticheta 3.
InstrucŃiunea If aritmetic nu este recomandată. Se preferă instrucŃiunea 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 InstrucŃiunea IF logic
O expresie relaŃională constă în două sau mai multe expresii a caror valoare este
comparată pentru a determina dacă relaŃia specificată de catre operatorii logici este
satisfăcută.
Operatorii relaŃionali sunt:
.lt. sau < mai mic
.le. sau <= mai mic sau egal
.eq. sau == egal
.ne. sau /= neegal
Dan RacoŃi
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. negaŃie
.eqv. echivalenŃă logică
In cazul operatorului .and. expresia este adevărată dacă atât expresia_1 cât şi expresia_2
sunt adevărate.
Tabela de adevăr a propoziŃiei (.not.p) este:
p .not.p
.true. .false.
.false. .true.

Tabelela de adevăr a propoziŃiei (p.and.q) este următoarea:

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

Tabela de adevăr a propoziŃiei (p.or.q) este următoarea:

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

Tabela de adevăr a propoziŃiei (p.eqv.q) este următoarea:

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 RacoŃi
Elemente de Fortran 95
16
predicat=expresie_1. and. expresie_2

InstrucŃiunea if logic este următoarea:

if(expresie)intrucŃiune_atribuire

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

Dacă expresia este adevărată se execută instrucŃiunea de atribuire. In caz contrar
se trece la următoarea instrucŃiune.

if(expresie)goto etichetă

if(r. le. 9.)goto 15

Dacă expresia este adevărată se face salt la instrucŃiunea 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 InstrucŃiunea BLOC IF

Sintaxa instrucŃiunii bloc if este următoarea:

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 RacoŃi
Elemente de Fortran 95
17
else
bloc_else
endif

Dacă expresia_1 este adevărată se execută blocul 1 de instrucŃiuni şi se sare la
instrucŃiunea care urmează după endif.
Dacă expresia_n este adevărată se execută blocul n de instrucŃiuni şi se sare la
instrucŃiunea care urmează după endif.
Dacă toate expresiile sunt false se execută blocul else (dacă există).
De exemplu:

if(condiŃie_logică)then
Bloc de instrucŃiuni (se execută dacă condiŃia logică este adevărată)
endif

if(condiŃie_logică)then
Bloc de instrucŃiuni_1 (se execută dacă condiŃia logică este adevărată)
else
Bloc de instrucŃiuni_2 (se execută dacă condiŃia 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 RacoŃi
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 InstrucŃiunea select case

InstrucŃiunea select case are următoarea 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 găsi o concordanŃă (poate fi numai una). Când o concordanŃă există
se execută blocul respectiv şi se sare la instrucŃiunea 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 RacoŃi
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 RacoŃi
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. InstrucŃiunea DO
InstrucŃiunea DO este utilizată pentru realizarea ciclurilor.
3.1 Forma 1
Sintaxa instrucŃiunii este:
do etichetă variabila_întreagă = start , final, increment
bloc_instrucŃiuni
etichetă continue
Variabila întreagă ia valori de la start până 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.
InstrucŃiunea se execută de:
max(int(final-start+increment)/increment),0)
ori.
3.2 Forma 2
Sintaxa instrucŃiunii este:
do etichetă variabilă_întreagă=start, final, increment
bloc instrucŃiuni
eticheta enddo
Eticheta este opŃională.
do variabilă_întreagă=start, final, increment
bloc instrucŃiuni
enddo
Variabila întreagă ia valori de la start până la final fiind incrementată cu valoarea
increment.
Ieşirea forŃată dintr-un ciclu do se face cu instrucŃiunea exit.

do variabilă_întreagă=start, final, increment
bloc instructiuni
if(conditie_logica)exit
enddo

Eliminarea unor instrucŃiuni din ciclu se face cu instrucŃiunea cycle.

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

Dacă condiŃia logică este adevărată blocul 2 de instrucŃiuni nu se mai execută.

3.3 Forma 3

Sintaxa instrucŃiunii este:

do
bloc instrucŃiuni
if(condiŃie_logică)exit
enddo

Ieşirea din ciclu se face cu instrucŃiunea exit.

3.4 InstrucŃiunea do while

Sintaxa instrucŃiunii este:

do eticheta while(condiŃie_logică)
bloc instrucŃiuni
eticheta enddo

Ciclul se execută cât timp condiŃia logică este adevărată. Eticheta este opŃională:

do while(condiŃie_logică)
bloc instrucŃiuni
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 RacoŃi
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 IteraŃii
Numeroşi algoritmi numerici sunt iterativi. LimitaŃi întotdeauna numărul de
iteraŃii pentru a evita buclele infinite.

3.5.1 Calculul radicalului

Calculul radicalului se bazează pe rezolvarea ecuaŃiei 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 operaŃii aritmetice
elementare.
AproximaŃia iniŃială este:
Dan RacoŃi
Elemente de Fortran 95
23
2
0
x
y =
Calculul se opreşte dacă:
ε < ) (
k
y f
Numărul de iteraŃii 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 ecuaŃiilor algebrice neliniare cu metoda Newton

Metoda Newton pentru rezolvarea ecuaŃiei 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 iteraŃii. Pentru pornirea iteraŃiilor se alege o valoare
iniŃială x
0
. Metoda este convergentă în apropierea soluŃiei. IteraŃiile sunt oprite dacă
modulul funcŃiei este mai mic decât o valoare impusă:
1
) ( ε <
k
x f
sau dacă diferenŃa între două valori x este mai mică decât o valoare impusă:
2
1
ε < −
+ k k
x x
Numărul de iteraŃii este limitat la valoarea n
max
pentru a evita o buclă infinită.
Considerăm ecuaŃia neliniară:
Dan RacoŃi
Elemente de Fortran 95
24
) cos( ) exp( ) ( '
) sin( ) exp( ) (
) sin( ) exp(
x x x f
x x x f
x x
− − − =
− − =
= −

Programul pentru rezolvarea ecuaŃiei 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ă ecuaŃii cu metoda Newton

Metoda Newton pentru rezolvarea sistemului de ecuaŃii 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 iteraŃii.
AproximaŃia iniŃială este determinată minimizând funcŃia 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ă soluŃia.
Dan RacoŃi
Elemente de Fortran 95
25
Derivatele parŃiale sunt calculate numeric cu formule de derivare cu diferenŃe
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
) , ( ) , (
− − +
=


− − +
=



IteraŃiile sunt oprite dacă este îndeplinită condiŃia:
ε < ∆ + ∆ y x
Numărul maxim de iteraŃii 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 RacoŃi
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 ecuaŃiilor algebrice polinomiale cu coeficienŃi complecşi cu metoda
Newton

Rezolvarea ecuaŃiilor algebrice polinomiale cu coeficienŃi în complex de reduce la
rezolvarea unui sistem de două ecuaŃii algebrice neliniare în real. Fie ecuaŃia:
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 ecuaŃii algebrice:
0 )) ( Im( ) , (
0 )) ( Re( ) , (
= =
= =
z h y x g
z h y x f

Conform teoremei fundamentale a algebrei sistemul de două ecuaŃii are 4 soluŃii
(o ecuaŃie de gradul patru are patru soluŃii complexe).
Dan RacoŃi
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 RacoŃi
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. Dezvoltări în serie

SoluŃia analitică a ecuaŃiei Poisson:
1 1
1 1
2
2
2
2
2
+ < < −
+ < < −
− =


+


y
x
y
u
x
u

cu condiŃia 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

FuncŃia exponenŃială se calculează utilizând dezvoltarea în serie:
...
!
...
! 3 ! 2 1
1
3 2
+ + + + + + =
i
x x x x
e
i
x

Calculul se efectuează adunând termen cu termen. Dacă un termen este mai mic decât
toleranŃa impusă calculul se opreşte:
ε <
! k
x
k


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

Dan RacoŃi
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 până la 7 dimensiuni.
Tablourile cu o dimensiune corespund vectorilor n-dimensionali.
Tablourile cu două dimensiuni corespund matricilor.
Declararea unui tablou se face în felul următor:

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ă iniŃială a indicelui (dacă lipseşte 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.
OperaŃiile matematice cu vectori sunt identice cu cele din algebră pentru vectori
de tip real şi complex. OperaŃiile elementare în complex sunt definite in limbajul
FORTRAN.
Considerăm vectori de dimensiune n.
Dan RacoŃi
Elemente de Fortran 95
30
OperaŃiile cu vectoriale sunt definite în limbajul FORTRAN. Dacă a şi b sunt doi
vectori cu trei elemente complexe, operaŃia:
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
+ =
+ =
+ =
+ =

ÎnmulŃirea 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
= + =
+ =

Scăderea 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ă operaŃia de înmulŃire 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
InstrucŃiunile:

real x(3),z(3),s
Dan RacoŃi
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 RacoŃi
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 RacoŃi
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)

OperaŃiile matriciale din algebră se transpun direct in limbajul FORTRAN pentru
matrice cu elemente întregi, reale şi complexe.
Considerăm matrice cu elemente complexe pătrate de dimensiune n.
ÎnmulŃirea 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 , = = + =
+ =

Scăderea a două matrice:
n j n i b a c
B A C
ij ij ij
,..., 2 , 1 , ,..., 2 , 1 , = = − =
− =

ÎnmulŃirea a două matrice:
n j n i b a c
AB C
kj
n
j
ik ij
,..., 2 , 1 , ,..., 2 , 1 ,
1
= = =
=

=

Dan RacoŃi
Elemente de Fortran 95
34
Norma unei matrice:
5 . 0
1 1
2
|
|
¹
|

\
|
=
∑∑
= =
n
i
n
j
ij
a A
OperaŃiile 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 RacoŃi
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ă operaŃiile 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 RacoŃi
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 RacoŃi
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 iniŃializate cu instrucŃiunea data sau utilizând instrucŃiunea
reshape:

result=reshape(source,shape)
InstrucŃiunea:

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 RacoŃi
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 SemnificaŃie
vector(:) tot vectorul
vector(1:100) tot vectorul
vector(1:10) tablou unidimensional conŃinând primele 10 elemente din vector
vector(51:100) tablou unidimensional conŃinând elementele 51:100 din vector
vector(51:) identic cu vector(51:100)
vector(10:1:-1) tablou unidimensional conŃinând primele 10 elemente din
vector în ordine inversă
vector(/10,88,3,5/) tablou unidimensional conŃinând elementele 10,88,3,5 din
vector, în această ordine
vector(ivector) tablou unidimensional conŃinând elementele 1,4,8,43,54,88
din vector în această ordine


real,dimension(100,100) :: matrice

Array section SemnificaŃie
matrice(:,:) toată matricea
matrice(1:100,1:100) toată matricea
matrice(7,:) tablou unidimensional conŃinând linia 7 din matrice
matrice(7,1:100) tablou unidimensional conŃinând linia 7 din matrice
matrice(:,7) tablou unidimensional conŃinând coloana 7 din matrice
matrice(1:10,81:90) tablou bidimensional conŃinând 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 RacoŃi
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 RacoŃi
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 soluŃiei unui sistem
de ecuaŃii algebrice liniare. Metoda converge dacă matricea sistemului este simetrică şi
pozitiv definită. Metoda converge dacă matricea sistemului este diagonal dominantă pe
linii.
Considerăm sistemul de n ecuaŃii algebrice liniare:
Dan RacoŃi
Elemente de Fortran 95
41

=
=
n
j
i j ij
b x a
1
i=1,2,…,n
IteraŃiile metodei Gauss Seidel se efectuează conform ecuaŃiei:
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 iteraŃii k=0,1,…
Se pleacă de la o aproximaŃie iniŃială dată.
IteraŃiile se opresc când norma reziduului este mai mică decât 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 RacoŃi
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 RacoŃi
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 execuŃie)

In multe cazuri acelaşi algoritm matricial se utilizează pentru ordine de mărime
diferite ale matricelor. Dacă nu se cunoaşte aprioric dimensiunea matricelor şi a
vectorilor aceştia sunt declaraŃi de tip alocatabil iar rezervarea de memorie se face în
momentul execuŃiei.

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 RacoŃi
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. FuncŃii şi subprograme

6.1 Clauza contains. FuncŃii interne

Dan RacoŃi
Elemente de Fortran 95
45
Anterior s-au definit funcŃiile formulă care permit descrierea unei funcŃii definite
printr-o singură ecuaŃie. In cazul în care expresia funcŃiei este mai complexă se utilizează
funcŃii interne declarate în programul principal după cuvântul cheie contains:

program nume_program
declaraŃii
.
.
.variabilă=nume_funcŃie(argumente efective)
contains
tip function nume_funcŃie(argumente_formale)
declaratii
.
.
nume_funcŃie=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 RacoŃi
Elemente de Fortran 95
46
6.2 FuncŃii externe
FuncŃiile externe au aceeaşi structură ca şi funcŃiile interne dar constituie unităŃi
separate de program. Numele funcŃiei apare obligatoriu într-o instrucŃiune de atribuire.
Toate variabilele trebuie să fie definite în interiorul funcŃiei.

tip function nume_funcŃie(argumente_formale)
declaratii
.
.
nume_funcŃie=expresie
end function nume_functie

Intre tipul şi numărul de argumente din programul apelant şi funcŃie există o
corespondenŃă biunivocă.
FuncŃia factorial
1 ! 0
... 3 . 2 . 1 !
=
= n n

permite calculul combinărilor:
)! ( !
!
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.FuncŃii în complex

Dan RacoŃi
Elemente de Fortran 95
47
O mare atenŃie trebuie acordată calculului cu funcŃii 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ă numărul complex:
iy x z + =
şi se calculează funcŃia 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

Considerăm un cerc cu centrul în cadranul doi în punctul M. Raza cercului este a.
DistanŃa de la centrul cercului la originea axelor O, segmentul OM este m. Unghiul
ascuŃit făcut de OM cu axa orizontală este δ. DistanŃa 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 RacoŃi
Elemente de Fortran 95
48

Considerăm transformarea de coordonate:
θ δ η
θ δ ξ
sin sin
cos cos
a m
a m
+ + =
+ − =

şi numărul 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 FuncŃii recursive
Dan RacoŃi
Elemente de Fortran 95
49

FuncŃiile recursive sunt funcŃiile care se autoapelează. Un exemplu clasic este
funcŃia factorial:
1 ! 1
1 ! 0
)! 1 ( !
=
=
− = n n n

FuncŃiile recursive sunt implementate în limbajul FORTRAN. In cazul funcŃiilor
clasice în corpul funcŃiei apărea obligatoriu expresia:

nume_funcŃie=expresie_aritmetică.

In cazul funcŃiilor recursive, valoarea funcŃiei este memorată într-o variabilă auxiliară
declarată cu cuvântul cheie result.


recursive function nume_funcŃie(argumente_formale) result(valoarea_funcŃiei)
declaratii
.
.
valoarea_funcŃiei=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 RacoŃi
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 mărirea 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 diferenŃa celor două integrale şi se compară cu o toleranŃă
impusă:
tol I I < −
1 2

Dacă condiŃia 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ă condiŃia 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 RacoŃi
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 RacoŃi
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 InstrucŃiunea External

InstrucŃiunea external se utilizează pentru a transmite ca subprogramele ca
parametrii la subprograme.
Să considerăm următorul exemplu. Avem o funcŃie care calculează integrala unei
funcŃii continue cu metoda Gauss cu trei puncte. Dorim să calculăm în acelaşi program
doua integrale:





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

utilizând aceeaşi funcŃie (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 RacoŃi
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)
declaraŃii
.
.
.
end subroutine nume_subrutina

Se poate specifica (opŃional) 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 RacoŃi
Elemente de Fortran 95
54
In cazul în care argumentul este o funcŃie sau o subrutină aceasta se declară în
instrucŃiunea external în programul apelant.
Subrutina este apelată cu instrucŃiunea call:

call nume_subrutină(lista_argumente_efective)

Există o corespondenŃă biunivocă ca tip şi număr î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

Considerăm cazul uzual al matricelor pătrate:

real matrice(ndim,ndim)
Dan RacoŃi
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 ecuaŃii algebrice lineare

Prin discretizarea ecuaŃiilor fizicii matematice se obŃin sisteme algebrice liniare de
mari dimensiuni. O cale pentru a rezolva aceste sisteme de ecuaŃii liniare este algoritmul
Gauss cu pivotare parŃială. Algoritmul Gauss are extrem de multe variante şi
implementări, 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 RacoŃi
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)

Considerăm sistemul algebric linear:
b Ax =
Matricea A este descompusă într-un produs de două matrice triunghiulare L
(lower) şi U (upper). Rezolvarea sistemului de ecuaŃii este redusă la rezolvarea a două
sisteme de ecuaŃii cu matrice triunghiulară prin retrosubstituŃie.
y Ux
b Ly
b LUx
LU A
=
=
=
=

Pentru a calcula inversa unei matrice de dimensiune 3 se rezolvă prin
retrosubstituŃie 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 RacoŃi
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 RacoŃi
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 RacoŃi
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 (vibraŃiile structurilor aerospaŃiale) 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 cercetări desfăşurate în anii 1970-1980 au condus la
realizarea unui pachet de programe numit EISPACK (NETLIB.ORG). În această colecŃie
de subrutine sunt programaŃi algoritmii numerici pentru probleme de valori proprii.
Dan RacoŃi
Elemente de Fortran 95
60
Vom considera o problemă un pic mai complicată, problema generalizată de
valori proprii:
Bx Ax λ =
Fie ecuaŃia diferenŃială, problema Sturm-Liouville:
b x a
y
dx
y d
<= <=
= λ
2
2

cu două condiŃii la limite, pentru x=a şi pentru x=b.
Considerăm un sistem de funcŃii liniar independente, f
i
(x) care satisfac condiŃiile
la limite.
Căutăm soluŃia în forma (metoda Galerkin):
) ( ) ( ) (
2 2 1 1
x f a x f a x y + =
Substituind această soluŃie în ecuaŃia diferenŃială obŃinem:
)) ( ) ( ( ) ( ) (
2 2 1 1
' '
2 2
' '
1 1
x f a x f a x f a x f a + = + λ
ÎnmulŃim ultima ecuaŃie succesiv cu f
1
(x) şi f
2
(x) şi integrăm de la a la b.
Se obŃine 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 obŃin
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 decât 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 RacoŃi
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 RacoŃi
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 RacoŃi
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. InstrucŃiunea COMMON

InstrucŃiunea COMMON este utilizată pentru a transmite valorile variabilelor în
subprograme independent de lista de parametrii. Parametrii din instrucŃiunea COMMON
trebuie să fie diferiŃi de parametrii din lista de variabile.
InstrucŃiunea COMMON este deosebit de puternică dar trebuie utilizată cu mare
atenŃie.

7.1 InstrucŃiunea COMMON blank

Sintaxa instrucŃiunii este:

common listă_parametrii

InstrucŃiunea 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 RacoŃi
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 InstrucŃiunea COMMON etichetat

Sintaxa instrucŃiunii 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 acelaşi tip într-o instrucŃiune 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 RacoŃi
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 InstrucŃiunea BLOCK DATA

InstrucŃiunea block data se utilizează pentru a iniŃializa valorile variabilelor din
common etichetat (labeled common) cu instrucŃiunea data.
Sintaxa instrucŃiunii 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. AplicaŃii
Se prezintă în continuare o serie de aplicaŃii în FORTRAN utilizând algoritmi
consacraŃi din bibliotecile de programe disponibile pe INTERNET (NETLIB.ORG).

Dan RacoŃi
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 RacoŃi
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 RacoŃi
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 RacoŃi
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 EcuaŃii diferenŃiale ordinare. Problema Cauchy

Se consideră sistemul de n ecuaŃii diferenŃiale ordinare nonstiff:
) ,... , ( ) (
1
'
n i
y y x f x y = i=1,2,…,n
cu condiŃia iniŃială:
0 0
0
) ( y x y
x x
i
=
=

Dacă soluŃiile sistemului de ecuaŃii diferenŃiale au scale diferite de timp, respectiv
unele soluŃii au o variaŃie mult mai rapidă decât altele, atunci sistemul de ecuaŃii
diferenŃiale este stiff.
Sistemele de ecuaŃii diferenŃiale nonstiff se integrează cu metode Runge Kutta
explicite.
Sistemele de ecuaŃii diferenŃiale 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
restricŃii. Se consideră două corpuri de masă 1-µ şi µ în mişcare circulară de rotaŃie în
plan şi un al treilea corp de masă neglijabilă care se mişcă în acelaşi plan. EcuaŃiile sunt:
Dan RacoŃi
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ă ecuaŃii diferenŃiale de ordinul doi se transformă într-un sistem
de patru ecuaŃii diferenŃiale de ordinul întâi 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
µ µ
µ
µ
µ
µ
− − − =


+
− + =
=
=

CondiŃia iniŃială la x=0 este:
y
1
=0.994
y
2
=0.0D0
y
3
=0.0D0
y
4
=-2.00158510637908252240537862224
Sistemul de integrează până la:
x
end
=17.0652165601579625588917206249
Sistemul neliniar de patru ecuaŃii diferenŃiale ordinare are soluŃii periodice.
Sistemul de patru ecuaŃii diferenŃiale este descris în subrutina FAREN.
SoluŃia sistemului de ecuaŃii diferenŃiale este scrisă în subrutina SOLOUT.
Reprezentarea grafică a soluŃiei 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 soluŃiei sistemului de ecuaŃii diferenŃiale în planul fazelor

C ----------------------------------------------------------
C NUMERICAL SOLUTION OF A SYSTEM OF FIRST 0RDER
Dan RacoŃi
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 RacoŃi
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 EcuaŃia Burgers omogenă

Se consideră ecuaŃia:
0
) (
=


+


x
u f
t
u

cu condiŃia iniŃială, problema Cauchy:
la t=0 ) sin( ) ( ) (
0
x x u x u π = = , [ ] 2 , 0 ∈ x .
Pentru ecuaŃia lui Burgers:
Dan RacoŃi
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ă funcŃia 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 următor de timp se face cu ecuaŃia:
[ ] ) , ( ) , (
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 soluŃiei (condiŃie la limită numerică).
SoluŃia ecuaŃiei 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 SoluŃia ecuaŃiei Burgers omogene la t=1.
uo3 condiŃia iniŃială
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 RacoŃi
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 RacoŃi
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 EcuaŃia Poisson
Se consideră ecuaŃia cu derivate parŃiale:
2
2
2
2
2
− =


+


y
u
x
u

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

cu condiŃia la limite u=0 pe frontieră.
Fie n
x
numărul de puncte ale grilei de discretizare pe axa x, n
y
numărul de puncte
pe axa y. Se definesc paşi 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 funcŃiei în nodurile reŃelei:
) , (
, j i j i
y x u u = i=1,2,…,n
x
j=1,2,…,n
y
.
Derivatele parŃiale sunt discretizate cu formule de derivare numerică cu diferenŃe
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 defineşte sistemul de ecuaŃii 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 RacoŃi
Elemente de Fortran 95
76
Sistemul de ecuaŃii se completează cu ecuaŃii pe frontieră (condiŃiile la limite).
Sistemul algebric linear de nx*ny ecuaŃii se rezolvă cu metoda Newton, o iteraŃie.
Jacobianul se calculează numeric cu formule de derivare cu diferenŃe 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. SoluŃia numerică şi soluŃia 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 RacoŃi
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 RacoŃi
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 EcuaŃia de potenŃial pe cerc

Se consideră ecuaŃia cu derivate parŃiale:
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ă soluŃiile periodice ale ecuaŃiei de potenŃial cu condiŃiile la limite:
Dan RacoŃi
Elemente de Fortran 95
79
r=r
1
: 0 =


=
r
v
r
ϕ

r=r
2
: θ ϕ cos

= V
Derivatele parŃiale se discretizează cu formule cu diferenŃe centrale. Se obŃine un
sistem algebric neliniar care se rezolvă cu metoda Newton. Jacobianul sistemului este
calculat numeric. AproximaŃia iniŃială este soluŃia ecuaŃiei Laplace pe cerc în curent
paralel. SoluŃia numerică se compară cu soluŃia obŃinută 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. SoluŃia numerică (puncte) şi soluŃia obŃinută 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 RacoŃi
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 RacoŃi
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 RacoŃi
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 ecuaŃii 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 RacoŃi
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'

Dan RacoŃi Elemente de Fortran 95 10.4 EcuaŃia Poisson 10.5 EcuaŃia de potenŃial pe cerc 10.6 Rezolvarea sistemelor de ecuaŃii neliniare 0. Introducere Fortran este un limbaj de programare potrivit în special pentru calculule numerice şi calcule ştiinŃifice. Limbajul dezvoltat plecând 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 adăugat 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 evoluŃie 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 instrucŃiuni incluzând instrucŃiunea 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 aplicaŃii mai complexe (ecuaŃii diferenŃiale cu derivate parŃiale 2D). Unele programe au fost păstrate în forma originală deoarece sunt algoritmi omologaŃi. 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ă instrucŃiune. Comentariile încep cu litera C din coloana 1 sau cu !. Următorul 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

2

Dan RacoŃi Elemente de Fortran 95
dtau = divdf1 divdf3 c(3,i) c(4,i) tau(i+1) - tau(i) = (c(1,i+1) - c(1,i))/dtau = c(2,i) + c(2,i+1) - 2.*divdf1 = (divdf1 - c(2,i) - divdf3)/dtau = (divdf3/dtau)/dtau

20 c c

c 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 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))) 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 30

Forma free a limbajului are extensia *.f90. Caracterul de continuare este &, la sfârşitul 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.

3

Dan RacoŃi Elemente de Fortran 95
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))) ! 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 30

! !

1.0 Constante şi variabile In limbajul FORTRAN sunt definite următoarele tipuri de constante: a) Constante de tip întreg, numere cu semn fără 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 adevărat şi .false. pentru fals. g) Constante de tip şir de caractere: ‘sir1’,’sirul_doi_de_caractere’,”Van’t 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.

4

0.b2 e) Complexe dublă precizie complex(8) lista_variabile double complex lista_variabile complex(8) zz1.beta real(4) gama. sir1='abcd' sir2="ab'd" z1=(4.f.adev.indice4 b) Reale simplă precizie: real listă_variabile real(4) listă_variabile real j.z2.-3.alfa integer(4) indice3.z1.x.s1.w2 double precision k1.) z2=(1.sir2.lambda_1 c) Reale dublă precizie: real(8) listă_variabile double precision listă_variabile real(8) w1.z2 write(*.indice2.sir1.er f) Logice 5 .h2 d) Complexe simplă precizie: complex listă_variabile complex(4) listă_variabile complex y2.234d-2.false.s.a.i.a1.a_y double complex ew.lista) end program constante Variabilele în FORTRAN sunt de tipul: a) Intregi integer listă_variabile integer(4) listă_variabile integer indice1.Dan RacoŃi Elemente de Fortran 95 fals=..fals.98765d2) namelist/lista/i.

de2.d3. . integer*2 integer*2 integer*4 integer integer*4 c d e b a i1.di2. i2=-1.r4 p1.j3.de4.q2. real*4 l real(kind=8) :: di1.q3.dl2.a4.l4 .d4. c2=2 .12 . d4=-4_2 d=d1+d2+d3-d4 e1=1201 .dj2. e3=1203 .l3.a write(*.sir2 character(16) nume.lista1) .b2.21e-01_4 . c4=4_2 c=c1+c2+c3*c4 d1=-1 .dz3. . .i2.v4 complex(kind=8) complex(8) double complex :: logical(kind=2) logical(4) logical dz1.predicat2 Variabilele de tip logic iau valorile adevărat . pause 1 namelist/lista2/e1.c4 d1.e2.w3.i3.e3.dl3. .dv2. e2=1202 . e4=1204 e=e1+e2+e3+e4 a1=-1411 .p2.z4 complex(4) w1. i4=5.dk4 .a2.dz4 dw1.d2.e4.i4 j1.c.d3.k3.a3.e4 b1.e2.dl complex(kind=4) z1.dk3. real j real k . d2=-2 . l1.b4 a1.dj3.dw2.dv4 q1.di3.q4 r1.l2.p3.r3.a3. i3=4.p4 c1=1 .c2. a2=-1412 .true.c2.c3.a2.r2.e. h) Sir de caractere character(lungime_şir) lista_variabile character(3) sir1.di4 .dv3.de3. d3=-3 .d2.z2.v3.b3.c3. real*4 i . real(8) dj real*8 dk1.k2.a4 .dz2.dk2.d write(*.lista2) .z3.j4 k1.6 6 .false.prenume program constante1 ! declaratii explicite de variabile scalare implicit none ! se suspenda conventia implicita integer(kind=2) integer(2) integer(kind=4) integer(4) :: integer real(kind=4) real(4) real(4) real*4 c1. complex*8 w complex :: v1.1001 . a3=-1413_4 .d4 e1.dw4 dv1. a4=-1414_4 a=a1*a2/a3+a4 namelist/lista1/c1.w2. real*8 di real(8) dj1. şi fals . pause 2 i1=1.dw3.Dan RacoŃi Elemente de Fortran 95 logical listă_variabile logical predicat1.c4.a1.w4 .de double precision dl1.dj4 .j2.k4 . real*8 dk real(8) :: de1.v2.dl4.e3. c3=3 . .d1.

) . k3=i3+j3 .005_8 .q2.dk4.k.k2.w write(*.di3.dj namelist/lista6/dk1. pause 7 j1=real(w) .and.lista5) . di3=3.dj4.l3.q3. k4=i4/j4 .r3. j2=i2**2 .2.or. Variabilele care încep cu literele i.l write(*. z4=cmplx(i3. l4=0. v4=z4*w4 namelist/lista8/v1. r3=. k2=i2+j2 .i2) .i.dk2. pause 5 write(*.o-z) sunt de tip real simplă precizie. dj3=+06d-3 . Variabilele care încep cu literele (a-h.dj1. program p1 ! 7 .de3. v2=z2-w2 .r4 write(*.dj2. pause 3 write(*.j2.*)'partea imaginara w='.r2 .dk3.e03_4. w3=z1+z2-(z3-z4) .p3.p2 namelist/lista9/q1. l3=+0. j=j1+j2+j3+j4 k1=i1+j1 .dk.or. l2=0. dj2=. de2=dk2-dk3 . k=k1/k2*k3/k4 l1=0. w4=abs(w3) w=w1/w2+w2*w3 namelist/lista7/z1. p3=p1. pause 6 z1=(1.not.or.z4.lista4) ._8 . j4=i4**2 .false.00123_8 . pause 4 di1=1.true. q2=.r2) .j2 write(*. r4=q3.i3. di2=2.p2.d0 di=di1/di2+di3**di4 dj1=-0.lista8) . pause 8 q1=.di4. q3=c1<c2 .lista6) .*)'partea reala w='.w v1=z1+w1 .lista10) end program constante1 1.i4) w1=conjg(z1) .m sunt de tip întreg.*)' w='._8 .not.w3.r2.(r1.r1.j1.v3.i4.Dan RacoŃi Elemente de Fortran 95 i=i1*i2+i3/i4 j1=i1**2 .01_4 .v4 write(*.k4. q4=c3>c4 r1=dk1<=dk2 .l4.r2 .j1 write(*.03e-03 l=l1+l2+l3+l4 namelist/lista3/i1.l1. r2=q3.w2=conjg(z2).z3. di4=4.dj3.l2. Se utilizează convenŃia implicită de declarare a variabilelor.q4.p2 p4=p1.z2.w4.p4 write(*.w2. p2=.w1.l.v2.de4.de write(*.j3.de2.lista7) .7.de1.and. .1 OperaŃii algebrice simple Programul p1 utilizează limbajul FORTRAN pentru a operaŃii algebrice elementare în real şi complex.and.q4 p1=r1.j namelist/lista4/k1. v3=z3/w3 . pause 9 namelist/lista10/p1.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 . j3=i3**2 . dj4=0. de3=(dk1-dk2)/(dk3+dk4) de4=de1*de2+de3 de=de1-de2-de3+de4 namelist/lista5/di1.di2._4 .k3._8 . j2=imag(w) write(*. z2=(-1.lista9) ..j4.j.i2.lista3) .q4 .02e+03_4 .di.k.01_4) z3=cmplx(i1.

y.lista2) end program p1 Programul p1e utilizează limbajul FORTRAN pentru a operaŃii algebrice elementare în real şi complex.x2.putere1.dc. Variabilele care incep cu literele i.putere2 write(*.m sunt de tip intreg.y1) ! z1=x1+sqrt(-1)*y1 z2=cmplx(x2.suma.z2. Se utilizează convenŃia explicită de declarare a variabilelor.puc real rc_r.puc write(*.sc. .l.k.pc.dc.diferenta. complex z1.rc.puc write(*.7 z1=cmplx(x1.*)'program p1' x=-1.rc_i write(*. program p1e ! ! ! ! ! Calculator stiintific 1 Conventia explicita de declarare a variabilelor implicit none real x.raport.j. y1=1.123 y=6.1 .diferenta.pc.dc.y.4 x2= 9.rc.produs.rc_i.764 suma=x+y diferenta=x-y produs=x*y raport=x/y n=2 putere1=x**n putere2=y**x namelist/lista1/x.produs.z2. y2=0.suma.rc.123 y=6.lista1) x1=-2.m.y2 complex z1.o-z) sunt reale simpla precizie.rc_r.sc.raport.Dan RacoŃi Elemente de Fortran 95 ! ! ! ! ! ! ! ! Calculator stiintific 1 Conventia implicita de declarare a variabilelor Variabilele care incep cu literele (a-h.putere2 integer n real x1.putere1.sc.764 suma=x+y diferenta=x-y produs=x*y raport=x/y 8 .z2.pc.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.y1.*)'program p1e' x=-1.

pc.y1) ! z1=x1+sqrt(-1)*y1 z2=cmplx(x2. FuncŃiile formulă corespund funcŃiilor din analiza matematică (funcŃii reale de una sau mai multe variabile reale sau complexe).rc_r.Dan RacoŃi Elemente de Fortran 95 n=2 putere1=x**n putere2=y**x namelist/lista1/x. y2=0.raport.putere2 write(*.suma.diferenta. nume_funcŃie(argumente_formale)=expresie_aritmetică In funcŃia formulă pe lângă variabile se pot utiliza constante definite în program înainte de apelul funcŃiei.z2.lista2) end program p1e Programul p2 arată utilizarea funcŃiilor formulă (statement functions).produs.putere1. .sc. Apelul funcŃiei se face prin nume şi cu argumentele efective.4 x2= 9.y.rc_i. Programul p2 calculează funcŃiile: f ( x) = a1 + a 2 x 2 f ' ( x ) = 2a 2 x g ( x) = sin(πx) g ' ( x) = π cos(πx) f ( x) g ( x) f ' ( x) g ( x) − f ( x) g ' ( x) h' ( x ) = g 2 ( x) h( x ) = Se utilizează convenŃia implicită de declarare a variabilelor. 9 . y1=1. valoare=nume_funcŃie(argumente_efective) Există o corespondenŃă biunivocă între tipul şi numărul argumentelor formale şi efective.dc. În programul p2e se utilizează convenŃia explicită de declarare a variabilelor.1 .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.puc write(*.lista1) x1=-2. In cazul în care funcŃia este mai complexă se utilizează clauza contains sau funcŃii externe.rc.7 z1=cmplx(x1.

21 .f(x).*)'program p2' a1=1.x.1 write(*.*atan(1.' g(x)='.Dan RacoŃi Elemente de Fortran 95 program p2 ! ! ! Statement function f(x)=a1+a2*x**2 fp(x)=2.gp(x) write(*.' g(x)='. a2=-1.fp.pi f(x)=a1+a2*x**2 fp(x)=2.x.' fp(x)='.*a2*x g(x)=sin(pi*x) gp(x)=pi*cos(pi*x) h(x)=f(x)/g(x) ! derivata functiei f(x) ! derivata functiei g(x) hp(x)=(fp(x)*g(x)-f(x)*gp(x))/g(x)**2 ! derivata functiei h(x) write(*. Se calculează determinanŃii de ordinul doi: 10 .x.f(x).fp(x) write(*.*)'x='.g(x).*)'x='.) x=1.*)'program p2' a1=1.g.32e-1 .' fp(x)='.' gp(x)='. a2=-1.h(x).' hp(x)='.' h(x)='.' f(x)='.*)'x='.' hp(x)='.' f(x)='.*)'x='.hp(x) end program p2e Programul p3 calculează soluŃia unui sistem de două ecuaŃii algebrice liniare: a11 a12   x1   b1   a   =    21 a 22   x 2  b2  cu metoda Cramer.gp.x.x.' gp(x)='.1 write(*.*)'x='. pi=4.h(x).*)'x='.g(x). pi=4.*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(*.' h(x)='.h.fp(x) write(*.a2.) x=1.hp(x) end program p2 program p2e ! ! ! Statement function implicit none real x.32e-1 .*atan(1.x.hp real a1.gp(x) write(*.f.21 .

a12.a21.v2 write(*.b1.l1) end program p3 Programul p4 calculează soluŃia unui sistem de trei ecuaŃii algebrice liniare cu metoda Cramer.x2.a22) if(d0 == 0.a12.a21. b1=5. 11 .b1 .a12.3e0 .b2.x1. In programul p4e se utilizează convenŃia explicită de declarare a variabilelor.Dan RacoŃi Elemente de Fortran 95 d0 = d1 = d2 = a11 a 21 b1 b2 a11 a12 a 22 a12 a 22 b1 = a11a 22 − a12 a 21 a 21 b2 Se presupune că determinantul d0 este diferit de zero.c.v1.b2 . a12= 2.3e0 . x1 = x2 = d1 d0 d2 d0 program p3 ! ! ! Rezolva un sistem de doua ecuatii algebrice liniare cu metoda Cramer real a11.b.e0 write(*. a22= 9.a22.a22.x1 real a21. Se utilizează convenŃia implicită de declarare a variabilelor.e-2 a21=-0.2e0 .d)=a*d-b*c ! determinant de ordinul doi ! ! Coeficientii sistemului ! a11= 1.b1.a21.)stop 'sistem singular' d1=det2(b1 .*)'program p3' ! ! Calculul determinantilor de ordin doi ! d0=det2(a11.a22) d2=det2(a11. x2=d2/d0 ! ! Verificarea solutiei ! v1=a11*x1+a12*x2-b1 v2=a21*x1+a22*x2-b2 namelist/l1/a11.7e1 .b2.x2 det2(a.b2 ) ! ! Cramer ! x1=d1/d0 .a12. b2=4.

c.Dan RacoŃi Elemente de Fortran 95  a11 a  21  a31  a12 a 22 a32 a13   x1   b1      a 23   x 2  = b2   a33   x3  b3      a11 d 0 = a 21 a31 b1 d1 = b2 b3 a11 d 2 = a 21 a31 a12 a 22 a32 a12 a 22 a 32 b1 b2 b3 a13 a 23 a33 a13 a 23 a33 a13 a 23 a33 a11 a12 b1 d 3 = a 21 a 22 b2 a31 a 23 b3 Se presupune că determinantul d0 este diferit de zero. SoluŃiile se calculează cu regula lui Cramer: d1 x1 = d0 x2 = x3 = d2 d0 d3 d0 program p4 ! ! Rezolva un sistem de trei ecuatii algebrice liniare ! cu regula lui Cramer ! det2(a. DeterminanŃii de ordin trei se calculează prin dezvoltare după prima linie: a11 a12 a13 a a 23 a a13 a a13 a 21 a 22 a 23 = (−1)1+1 a11 22 + (−1) 2+1 a 21 12 + (−1) (1+3) a31 12 a32 a33 a32 a33 a 22 a 23 a31 a32 a33 Se defineşte o funcŃie formulă pentru calculul determinantului de ordinul doi si o funcŃie formulă pentru calculul determinantului de ordinul trei care utilizează funcŃia formulă a determinantului de ordin 2.d)=a*d-b*c ! determinant de ordinul 2 ! ! Determinant de ordinul trei (dezvoltare dupa prima linie) 12 .b.

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.d0 .a13.e0 .a33) $ +(-1.a32.d0 .a12.a31.a13.a31.a33) if(d0.9e0 ! ! Calculul determinantilor ! d0=det3(a11.a21. a23=5.e0 a31= 4.a23) ! ! Coeficientii sistemului de ecuatii liniare ! a11=-1.a21.d0 .a12.b3 .a22.a23.v3 write(*.a21.e0 a21=-2.a21.a33) $ +(-1.a32.e0)**(3+1)*a31*det2(a12.e0 .a31.b2 .b2 .x2. a32=-6.a32.a12. # x1.a13.a33) $ +(-1.e0 .a32. a33=1.b3 .a33) if(d0.v2.a23.Dan RacoŃi Elemente de Fortran 95 ! det3(a11. b2=1. a12=+1.a21.e0 .a32.a33.d0)**(3+1)*a31*det2(a12.b2 .d0 . a22=-3.a13.a13.d0 a21=-2.a22.b1 .c.a13. a33=1.a12.1d0 .b.a22.d0)**(1+1)*a11*det2(a22.a13. a32=-6.a33) d3=det3(a11.a22.a23.b1.a23.a33) 13 .a12.a33) $ +(-1.a23) ! ! Coeficientii sistemului de ecuatii liniare ! a11=-1.a32.0.a33)= $ +(-1.a31.b3 .e0 .a22.a22.a22.eq.a31.a23.e0)**(2+1)*a21*det2(a12.a21. a23=5.1e0 . a13=3.a23.e0 .a31.e0)**(1+1)*a11*det2(a22.a13.a33) d2=det3(a11.a32.a12.a22.a13.d0 a31= 4.a23.v1.d0 .a12.e0 . b1=4.a32.e0 .a32.d)=a*d-b*c ! determinant de ordinul 2 ! ! Determinant de ordinul trei (dezvoltare dupa prima linie) ! det3(a11.a33)= $ +(-1.b1 .a32.0.a13.a21.a12.a23. b2=1.o-z) ! dubla precizie det2(a. a22=-3.a22. a12=+1. a13=3.b2 .x3.)stop 'sistem singular' d1=det3(b1 .a31. b1=4.d0 .a13.d0)**(2+1)*a21*det2(a12.a22.d0 .a32. b3=0.a32.b3.eq.a32. b3=0.a23.b2.)stop 'sistem singular' d1=det3(b1 .b3 ) ! ! Cramer ! x1=d1/d0 .a13.l1) end program p4 program p4e ! ! Rezolva un sistem de trei ecuatii algebrice liniare ! cu regula lui Cramer ! implicit real(8) (a-h. x2=d2/d0 .9d0 ! ! Calculul determinantilor ! d0=det3(a11.d0 .

sau /= neegal 14 .a32.1 .*)'delta egal cu zero' goto 40 continue write(*. Operatorii relaŃionali sunt: .a33. 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.*a*c if(delta)10.eticheta_2.a33) d3=det3(a11.1.eq.a21.*)'delta negativ' goto 40 continue write(*.c.lt.3 .eticheta_3 Dacă valoarea numerică a expresiei este mai mică decât zero se face salt la eticheta_1.a13. program if1 ! instructiunea if aritmetic real a.a13.1 InstrucŃiunea IF (dacă) InstrucŃiunea IF este utilizată pentru comparaŃii. b=1.a12.b3 ) ! ! Cramer ! x1=d1/d0 .ne.b1 .a31.a22.a32.l1) end program p4e 2.20.delta a=1.x2.Dan RacoŃi Elemente de Fortran 95 d2=det3(a11.v2.b1.b2.b3. sau == egal .1 InstrucŃiunea IF aritmetic if(expresie)eticheta_1.a21.2 InstrucŃiunea IF logic O expresie relaŃională constă în două sau mai multe expresii a caror valoare este comparată pentru a determina dacă relaŃia specificată de catre operatorii logici este satisfăcută. sau <= mai mic sau egal .v1.b. 2.b3 .*)"delta mai mare decat zero" continue end program if1 10 20 30 40 2.a31.1.a21. Se preferă instrucŃiunea if logic.b2 .v3 write(*.a23. Dacă valoarea numerică a expresiei este mai mare decât zero se face salt la eticheta 3. x2=d2/d0 .b1 .le. c=4.a32.a12.30 continue write(*.x3. Dacă valoarea numerica a expresiei este egală cu zero se face salt la eticheta_2. # x1.5 delta=b**2-4. InstrucŃiunea If aritmetic nu este recomandată.b2 . sau < mai mic .a31.a22.

false.false.true.false. .q) este următoarea: p .true.q) este următoarea: p .true. echivalenŃă logică In cazul operatorului . negaŃie .expresie_1.ge.q .true. expresia este adevărată dacă atât expresia_1 cât şi expresia_2 sunt adevărate.true. sau logic .true. q .false.not. . . p.or.false. Tabela de adevăr a propoziŃiei (p.expresie_2 .ge. .true.false.true.gt.false. . expresie_1=a. sau > mai mare . q . . . . Tabela de adevăr a propoziŃiei (.and.true.eqv. . p. . .false.not. .true.false.Dan RacoŃi Elemente de Fortran 95 . logical predicat.false.lt. . .false.false.true.and.q .not.true. .false. . . . expresie_2= b. .eqv.and. . .5 .and.false. . .true. sau >= mai mare sau egal Operatorii logici uzuali sunt: . şi logic .true.false.or. Tabela de adevăr a propoziŃiei (p. . .q) este următoarea: p . q . . .or.true.eqv. . .false. .false. Tabelela de adevăr a propoziŃiei (p. . .false.h 15 .true.p . p.true. .false.p) este: p .false.true.true.true.q .

)write(*.2 .*a) if(delta > 0.*)'Radacini reale' x1=(-b+sqrt(delta))/(2.)x2=(-b+sqrt(delta))/(2.*)'delta negativ' if(delta == 0.3 InstrucŃiunea BLOC IF Sintaxa instrucŃiunii bloc if este următoarea: if(expresie_1)then bloc _1 elseif(expresie_2)then bloc_2 elseif(expresie_3)then bloc_3 … elseif(expresie_n)then bloc_n 16 .*)'x1='.1 .c.)goto 15 Dacă expresia este adevărată se face salt la instrucŃiunea care are eticheta respectivă.)write(*. le.x2 stop 55 continue write(*.*)'delta egal cu zero' if(delta > 0.*)'delta mai mare decat zero' if(delta < 0. gt. x2c=-sqrt(-delta)/(2.delta ! ! Coeficientii ecuatiei de gradul doi ! a=-2.x1.*a) end program if2 2.*a) x2r=-b/(2.*a) . and. In caz contrar se trece la următoarea instrucŃiune.)goto 55 write(*. c=5.*)'radacini complexe' x1r=-b/(2. b=-4.'x2='.6e0 delta=b*b-4.3 Dacă expresia este adevărată se execută instrucŃiunea de atribuire. 0. expresie_2 InstrucŃiunea if logic este următoarea: if(expresie)intrucŃiune_atribuire if(a.1.*a) write(*. 9. x1c=+sqrt(-delta)/(2.b.Dan RacoŃi Elemente de Fortran 95 predicat=expresie_1. program if2 ! if logic real a.) x=1.)write(*.*a*c if(delta < 0.*a) . if(expresie)goto etichetă if(r.

*)'conditia 3 este adevarata.*)'delta mai mare decat zero' endif end program if3 program if4 real a. a>0.5 .(b>0.((b+c)<0.*)'conditia 1 este adevarata.lista) if(predicat1)then write(*. De exemplu: if(condiŃie_logică)then Bloc de instrucŃiuni (se execută dacă condiŃia logică este adevărată) endif if(condiŃie_logică)then Bloc de instrucŃiuni_1 (se execută dacă condiŃia logică este adevărată) else Bloc de instrucŃiuni_2 (se execută dacă condiŃia logică este falsă) endif program if3 real a.) predicat3=((b+c)<0.)' elseif(a*b*c>9.and. if(predicat1)then write(*.c.c.predicat2.b.).c logical predicat1.e3 .(a<0.*)'delta negativ' elseif(delta == 0.(c<0.) namelist/lista/a.).predicat3 a=-4. predicat2=(a<0.Dan RacoŃi Elemente de Fortran 95 else bloc_else endif Dacă expresia_1 este adevărată se execută blocul 1 de instrucŃiuni şi se sare la instrucŃiunea care urmează după endif. b=9. b=1.' elseif(predicat2)then write(*.predicat2.predicat3 write(*.delta logical predicat1 a=0.b. Dacă toate expresiile sunt false se execută blocul else (dacă există).)then write(*.(b>0.b.predicat1.or.9 .and.(c<0.).*a*c predicat1=delta < 0.*)'conditia 2 este adevarata.)' elseif(predicat3)then write(*.)then 17 .or.*)'delta egal cu zero' else write(*.). c=45. Dacă expresia_n este adevărată se execută blocul n de instrucŃiuni şi se sare la instrucŃiunea care urmează după endif. c=8.e-2 delta=b*b-4. predicat1=a > 0.4 .

’abd’) return .true.Dan RacoŃi Elemente de Fortran 95 write(*. 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 18 .*)'a*b*c>9. Când o concordanŃă există se execută blocul respectiv şi se sare la instrucŃiunea de după end select. 2.eqv.sir2) mai mic lexical variabila_logică=lgt(sir1. .sir2) mai mare sau egal lexical logical l1.1. Dacă expresia este logică atunci: case_index .5 InstrucŃiunea select case InstrucŃiunea select case are următoarea sintaxă: select case(expr) case(case_value_1) block_1 case(case_value_2) block_2 . Rezultatul.l2 l1=lle(‘abc’. case default block_default end select Se evaluează expresia (expr).sir2) mai mic sau egal lexical variabila_logică=llt(sir1. .' 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. case_index se compară cu fiecare case_value pentru a găsi o concordanŃă (poate fi numai una).sir2) mai mare egal lexical variabila_logică=lge(sir1.

b character(1) operatie write(*.*)a.eq.true.*)'Numarul este 1 sau 3 sau 5 sau 7.*)numar select case(numar) case(1.false.b write(*.*)'Introduceti un numar (intreg)' read(*.12) write(*.Dan RacoŃi Elemente de Fortran 95 case(1:) end select Exemplu: select case (itest.3.) call subprogram1 case(.'(a)')operatie 19 .) call subprogram2 end select Exemplu: select case(itest) case(1) call sub1 case(2) call sub2 case default call subd end select ! i>= 1 Interval low: :high low:high A match case case_index>=low case_index<=high low<=case_index<=high program select_case implicit none integer numar real a.8.*)'Introduceti doua numere reale:' read(*.9 sau 12' case default write(*.*)'Intoduceti operatia aritmetica:' read(*.7:9.5.1) case(.*)'Numarul nu este in secventa programata' end select write(*.

do variabilă_întreagă=start.*)'Suma este:'. increment bloc instructiuni if(conditie_logica)exit enddo Eliminarea unor instrucŃiuni din ciclu se face cu instrucŃiunea cycle.*)'Produsul este:'.*)'Raportul este:'.a*b case('/') write(*.*)'Diferenta este:'. increment bloc_instrucŃiuni etichetă continue Variabila întreagă ia valori de la start până la final fiind incrementată cu valoarea increment. do variabilă_întreagă=start. final. InstrucŃiunea DO InstrucŃiunea DO este utilizată pentru realizarea ciclurilor. final. Limbajul Fortran acceptă şi variabile de tip real pentru variabilele start.a+b case('-') write(*.2 Forma 2 Sintaxa instrucŃiunii este: do etichetă variabilă_întreagă=start.*)'Operatie nedefinita' end select end program select_case 3.final şi increment. 3. Ieşirea forŃată dintr-un ciclu do se face cu instrucŃiunea exit. final. Dacă variabila increment nu este specificată se consideră implicit valoarea 1.Dan RacoŃi Elemente de Fortran 95 select case(operatie) case('+') write(*.a-b case('*') write(*.a/b case default write(*. 20 . InstrucŃiunea se execută de: max(int(final-start+increment)/increment). 3.1 Forma 1 Sintaxa instrucŃiunii este: do etichetă variabila_întreagă = start . increment bloc instrucŃiuni eticheta enddo Eticheta este opŃională.0) ori. final. increment bloc instrucŃiuni enddo Variabila întreagă ia valori de la start până la final fiind incrementată cu valoarea increment.

i enddo 10 21 .4 InstrucŃiunea do while Sintaxa instrucŃiunii este: do eticheta while(condiŃie_logică) bloc instrucŃiuni enddo eticheta Ciclul se execută cât timp condiŃia logică este adevărată.*)'i='.2 write(*.5 write(*.3 Forma 3 Sintaxa instrucŃiunii este: do bloc instrucŃiuni if(condiŃie_logică)exit enddo Ieşirea din ciclu se face cu instrucŃiunea exit.i continue write(*. 3.i enddo write(*.*)'i='.*) do i=-10.increment bloc1 if(conditie_logică) cycle bloc2 enddo Dacă condiŃia logică este adevărată blocul 2 de instrucŃiuni nu se mai execută.final.14. 3.*)'i='. Eticheta este opŃională: do while(condiŃie_logică) bloc instrucŃiuni enddo program do1 ! ! ! Cicluri do elementare implicit real(8) (a-h.Dan RacoŃi Elemente de Fortran 95 do var=start.*) do i=1.6 write(*.o-z) ! dubla precizie do 10 i=1.

' radical x='.1.j j=j+1 enddo write(*.i enddo write(*.d0)cycle write(*.1d0 do x=x+1.x x=x-1.1. k=0.x. LimitaŃi întotdeauna numărul de iteraŃii pentru a evita buclele infinite.1 Calculul radicalului Calculul radicalului se bazează pe rezolvarea ecuaŃiei neliniare: y= x f ( y) = y 2 − x = 0 f ' ( y) = 2 y Şirul iterativ Newton este:  f (yk ) x  y k +1 = y k − = 0.*)'j='.5d0 if(x<0.5 IteraŃii Numeroşi algoritmi numerici sunt iterativi.d0) write(*.k 12345 enddo write(*.-1 write(*. 3.*) x=-5.5 y k + k  . do while(j<5) write(*.Dan RacoŃi Elemente de Fortran 95 write(*.3 write(*.*)'x='.*)'k='.d0 enddo write(*.15.5. AproximaŃia iniŃială este: 22 .sqrt(x) if(x>20.d0 do while(x>0.*)'x='.*)'i='.*) do 12345 k=1.*) x=10.*) j=0.*) n=10 do i=n.d0)exit enddo end program do1 3.… k  f '( y ) y    După cum se observă calculul radicalului se reduce la operaŃii aritmetice elementare.

5.*)iter. Metoda este convergentă în apropierea soluŃiei.2 Rezolvarea ecuaŃiilor algebrice neliniare cu metoda Newton Metoda Newton pentru rezolvarea ecuaŃiei neliniare: f ( x) = 0 este: f (x k ) k=0.d0 y=x/2.y.'(/.a.parameter :: iter_max=10 real(8) :: eps=1.1.*)'x='.d-8 logical succes fy(y)=y**2-x x=9.f enddo write(*.5d0*(y+x/y) f=fy(y) write(*. if(succes)then write(*. Pentru pornirea iteraŃiilor se alege o valoare iniŃială x0./)')'Iteratiile Newton' succes=.d0 ! aproximatia initiala Newton f=fy(y) write(*.true.*) if(iter<iter_max)succes=. iter=0 write(*.y.Dan RacoŃi Elemente de Fortran 95 y0 = k x 2 Calculul se opreşte dacă: f (y ) < ε Numărul de iteraŃii este limitat de o valoare maximă pentru a evita intrarea într-o buclă infinită.(f>eps)) iter=iter+1 y=0.and.x. program radical implicit real(8) (a-h.f do while((iter<iter_max). Considerăm ecuaŃia neliniară: 23 .o-z) integer.2.y else write(*.false.… f '(x k ) Variabila k este contorul de iteraŃii. IteraŃiile sunt oprite dacă modulul funcŃiei este mai mic decât o valoare impusă: f (x k ) < ε1 x k +1 = x k − sau dacă diferenŃa între două valori x este mai mică decât o valoare impusă: x k +1 − x k < ε 2 Numărul de iteraŃii este limitat la valoarea nmax pentru a evita o buclă infinită.' radical(x)='.*)'Metoda nu converge' endif end program radical 3.*)iter.

y ) x k +1 = x k + ∆x as < x < ad bx < y < b y prin explorarea domeniului în care se caută soluŃia.*)'Valoarea functiei este='.x write(*.*)'Solutia ecuatiei este ='.d-6) integer. y ) = f 2 ( x.o-z) parameter (eps1=1.1.3 Rezolvarea sistemelor algebrice neliniare de două ecuaŃii cu metoda Newton Metoda Newton pentru rezolvarea sistemului de ecuaŃii neliniare: f ( x.parameter :: nmax=25 ! numarul maxim de iteratii fct(x)=exp(-x)-sin(x) ! functia dfct(x)=-exp(-x)-cos(x) ! derivata write(*.f if(abs(f)<eps1)goto 33 df=dfct(x) dx=f/df if(abs(dx)<eps2)goto 33 x=x-dx enddo write(*. y k )  ∆y   g(x . AproximaŃia iniŃială este determinată minimizând funcŃia de două variabile: φ ( x.Dan RacoŃi Elemente de Fortran 95 exp(− x) = sin( x) f ( x) = exp(− x) − sin( x) f ' ( x) = − exp(− x) − cos( x) Programul pentru rezolvarea ecuaŃiei neliniare este prezentat în continuare.*)'Metoda nu converge in nmax iteratii' stop continue write(*. program iteratii_1 implicit real(8) (a-h. y ) = 0 g ( x.*) write(*. y k )  ∂x  k k  ∂g ( x . y )  ∂x  ∂f ( x k .5.nmax f=fct(x) write(*.fct(x) end program iteratii_1 33 3.d-5) parameter (eps2=1. y k )   ∆x   f ( x k .*)iter. y k ) ∂y   = − k k  ∂g ( x k .x.… y k +1 = y k + ∆y Indicele k este contorul de iteraŃii.1d0 ! aproximatia initiala do iter=0.*)'Iteratiile metodei Newton' x=0. y ) = 0 este:  ∂f ( x k . y ) + g 2 ( x. y )  ∂y  k=0. 24 .

y ) = 2h ∂x ∂f g ( x.d0*x+2.det2 real(8) :: al=-10. bl<y<bd ! do i=1.j real(8) pas.y)=x-0.d2 real(8) dx. y + h ) − g ( x .n-1 do j=1. y + h ) − f ( x.98d0*y det2(a11.dgdy integer.d1.a12.d0 ! marginea dreapta a intervalului pentru x real(8) :: bl=-10.d0*y-0.d77 ! ! Se determina minimul functiei fct(x.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.d0 ! marginea stanga a intervalului pentru x real(8) :: ad=+10.dfdy.parameter :: iter_max=15 ! ! Sistemul de ecuatii neliniare ! fct(x.y)**2 25 .d0 ! marginea stanga a intervalului pentru y real(8) :: bd=+10.gct.y)**2 prin explorarea ! domeniului al<x<ad.dy real(8) a11.y)**2 + gct(x.01d0*exp(y) gct(x.a21.a12. program iteratii_2 implicit none real(8) x.fct. y − h ) = ∂y 2h ∂g g ( x + h.a22 integer iter. y − h ) = ∂y 2h IteraŃiile sunt oprite dacă este îndeplinită condiŃia: ∆x + ∆y < ε Numărul maxim de iteraŃii este limitat pentru a nu se intra într-o buclă infinită.y)=x**2-3.n-1 x=al+(i-1)*hx y=bl+(j-1)*hy f=fct(x. y ) = ∂x 2h ∂f f ( x.dfdx.y)**2+gct(x. y ) − f ( x − h.f. y ) − g ( x − h.d0 ! marginea dreapta a intervalului pentru y integer.y.'(a.a21.dgdx.g.Dan RacoŃi Elemente de Fortran 95 Derivatele parŃiale sunt calculate numeric cu formule de derivare cu diferenŃe centrale: ∂f f ( x + h./)')"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.i.a22)=a11*a22-a12*a21 ! determinantul de ordin doi write(*.

6)')'Solutia ='.dfdy.y+pas)-fct(x./)')'Iteratiile metodei Newton' write(*.dfdy.y) dgdx=(gct(x+pas. y ) = Re(h( z )) = 0 g ( x.1x))')iter.y) dfdx=(fct(x+pas.y)-fct(x-pas.1.Dan RacoŃi Elemente de Fortran 95 if(f<fmin)then fmin=f xs=x . y=ys ! aproximatiile initiale Newton pas=1.'(/.y.6.'(i3.y).-g) dx=d1/d0 ! corectiile Newton dy=d2/d0 if(abs(dx)+abs(dy) < 1.gct(x. y ) = Im(h( z )) = 0 Conform teoremei fundamentale a algebrei sistemul de două ecuaŃii are 4 soluŃii (o ecuaŃie de gradul patru are patru soluŃii complexe).x.y-pas))/(pas+pas) ! ! ! Derivatele partiale ale functiei gct(x.*)'neconvergenta Newton 2D' stop 33 66 write(*.dgdy) d2=det2(dfdx.f.6.f13.y write(*.dgdx.d0 ! pas de derivare numerica write(*.iter_max f=fct(x.5.2x.f13. g=gct(x.d0)stop 'Jacobian singular' d1=det2(-f.4(g13.x.d-6)go to 33 ! ! ! Derivatele partiale ale functiei fct(x.d77)stop 'nelocalizare 2D' x=xs . ys=y endif enddo enddo if(fmin.6)')'Functiile='.y)-gct(x-pas.y) continue end program iteratii_2 g' 3.eq.4 Rezolvarea ecuaŃiilor algebrice polinomiale cu coeficienŃi complecşi cu metoda Newton Rezolvarea ecuaŃiilor algebrice polinomiale cu coeficienŃi în complex de reduce la rezolvarea unui sistem de două ecuaŃii algebrice neliniare în real.'(/.-f.y))/(pas+pas) dfdy=(fct(x.f13.y-pas))/(pas+pas) ! ! ! Rezolvarea unui sistem liniar de gradul doi cu metoda Cramer d0=det2(dfdx.eq.dgdy) if(d0. a3 .y+pas)-gct(x. a 5 ∈ C este echivalentă cu sistemul de ecuaŃii algebrice: f ( x.f13.fct(x.g if(abs(f)+abs(g) < 1. a 2 . a 4 .0. 26 .dgdx.'(a.6.d0/512.y) write(*.y))/(pas+pas) dgdy=(gct(x.*)' x y f do iter=1.a.d-6)goto 33 x=x+dx ! iteratiile Newton y=y+dy enddo write(*.y) .-g. Fie ecuaŃia: h( z ) = a1 + a 2 z + a3 z 2 + a 4 z 3 + a 5 z 4 = 0 a1 .a.

a3.79d0) a5=(1.6.1x))')iter.fz complex a1.y.parameter :: iter_max=15 complex(8) z.dgdy) d2=det2(dfdx.-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(*. y=+1.eq.dfdy.dgdx.a21.y)-fct(x-pas.-g.a./)')"program iteratii_3" x=-1. 0.o-z) integer.88d0) a3=(3.y-pas))/(pas+pas) ! ! ! Rezolvarea unui sistem liniar de gradul doi cu metoda Cramer d0=det2(dfdx.y))) gct(x.d0 ! pas de derivare numerica write(*.x.y) dgdx=(gct(x+pas.4(g13.08d0) write(*.y+pas)-fct(x.dfdy.y-pas))/(pas+pas) ! ! ! Derivatele partiale ale functiei gct(x.0d0.Dan RacoŃi Elemente de Fortran 95 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.y)-gct(x-pas.y) .f.a2.y))) det2(a11.d0 .y))/(pas+pas) dgdy=(gct(x.y) write(*.y)=real(fz(cmplx(x.y+pas)-gct(x.d0)stop 'Jacobian singular' d1=det2(-f.a22)=a11*a22-a12*a21 ! determinantul de ordin doi ! ! Coeficientii complecsi ai ecuatiei algebrice ! a1=(1.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.0d0.-1.d-6)go to 33 ! ! ! Derivatele partiale ale functiei fct(x.dgdy) if(d0.-0.45d0) a2=(2. 0.2x.'(a.'(i3.'(/.55d0) a4=(0.*)'neconvergenta Newton 2D' g' 27 .d0 ! aproximatiile initiale Newton pas=1.y) dfdx=(fct(x+pas.3d0. g=gct(x.0d0.0d0./)')'Iteratiile metodei Newton' write(*.y))/(pas+pas) dfdy=(fct(x. 0.a12.y)=imag(fz(cmplx(x.-f.0.iter_max f=fct(x.*)' x y f do iter=1.dgdx.a4.g if(abs(f)+abs(g) < 1.d0/512.

Dan RacoŃi Elemente de Fortran 95
33 66 stop write(*,'(/,a,f13.6,f13.6)')'Solutia =',x,y write(*,'(a,f13.6,f13.6)')'Functiile=',fct(x,y),gct(x,y) continue end program iteratii_3

4. Dezvoltări în serie SoluŃia analitică a ecuaŃiei Poisson: ∂ u ∂ 2u + = −2 ∂x 2 ∂y 2 − 1 < x < +1
2

− 1 < y < +1 cu condiŃia la limită u=0 pe contur este: mπx nπy cos( ) cos( ) ∞ ∞ 128 2 2 u ( x, y ) = 4 ∑ ∑ π n =1,3,5 m=1,3,5 mn(m 2 + n 2 )
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

FuncŃia exponenŃială se calculează utilizând dezvoltarea în serie:

ex = 1+

x x2 x3 xi + + + ... + + ... 1 2! 3! i!

Calculul se efectuează adunând termen cu termen. Dacă un termen este mai mic decât toleranŃa impusă calculul se opreşte:

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

28

Dan RacoŃi Elemente de Fortran 95
PROGRAM calculul_functiei_exponentiale ! DEZVOLTARE IN SERIE IMPLICIT NONE INTEGER :: index REAL(8) :: termen REAL(8) :: exp_calc REAL(8) :: X REAL(8),PARAMETER :: tol = 1.d-9 WRITE(*,*)'INTRODUCETI X' READ(*,*) X index = 1 exp_calc = 1.0 termen = X DO IF (ABS(termen) < tol) EXIT exp_calc = exp_calc + termen index = index + 1 termen = termen * (X / index) ENDDO WRITE(*,*) WRITE(*,*) WRITE(*,*) WRITE(*,*) END PROGRAM 'Dupa ', index, ' Exp_calculat ' Exp_exact ' Abs(Error) ' = = = ! ! ! ! ! numarul de termeneni un termen valoarea seriei valoarea argumentului toleranta

! primul termen din serie ! al doilea termen in serie

iteratii:' ', exp_calc ', EXP(X) ', ABS(exp_calc - EXP(X))

calculul_functiei_exponentiale

5. Tablouri Limbajul FORTRAN acceptă tablouri cu până la 7 dimensiuni. Tablourile cu o dimensiune corespund vectorilor n-dimensionali. Tablourile cu două dimensiuni corespund matricilor. Declararea unui tablou se face în felul următor: 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ă iniŃială a indicelui (dacă lipseşte 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. OperaŃiile matematice cu vectori sunt identice cu cele din algebră pentru vectori de tip real şi complex. OperaŃiile elementare în complex sunt definite in limbajul FORTRAN. Considerăm vectori de dimensiune n.

29

Dan RacoŃi Elemente de Fortran 95 OperaŃiile cu vectoriale sunt definite în limbajul FORTRAN. Dacă a şi b sunt doi vectori cu trei elemente complexe, operaŃia: c = a +b este echivalentă cu adunarea explicită a elementelor vectorilor: c1 = a1 + b1 c 2 = a 2 + b2 c3 = a3 + b3 In FORTRAN se scrie: complex a(3),b(3),c(3) c = a+b

sau c(1) = a (1) + b(1) c ( 2) = a ( 2) + b ( 2) c(3) = a (3) + b(3) ÎnmulŃirea unui vector cu o constantă: v 2 = cv1 v 2i = cv1i , i = 1,2,..., n Adunarea a doi vectori: v3 = v1 + v 2 v3i = v1i + v 2i , i = 1,2,..., n Scăderea a doi vectori: v3 = v1 − v2 v3i = v1i − v 2i , i = 1,2,..., n Produsul scalar a doi vectori:

v1 .v 2 = ∑ v1i v 2i
i =1

n

Norma unui vector:
2  n  v =  ∑ vi   i =1    Dacă vectorul este de tip real atunci: 0.5 v = (v .v ) In FORTRAN este definită operaŃia de înmulŃire a doi vectori, element cu element.  x1   y1   x1 y1        x = x2  y =  y2  x * y = x2 y 2  x  y  x y   3  3  3 3 InstrucŃiunile: 0.5

real x(3),z(3),s

30

Dan RacoŃi Elemente de Fortran 95 s=sum(x*z) conduc la: s = x1 y1 + x 2 y 2 + x3 y 3

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 !

31

345 v3=v1*const ! vectorial write(*.n v3(i)=v1(i)-v2(i) write(*.*)'Inmultirea pe componente' write(*.'(i3.*)'norma vectorului v1='.*)'Inmultirea vectorului v1 cu constanta='.vector2) calculeaza produsul scalar ! write(*.n) ! ! Adunarea a doi vectori ! v3=v1+v2 ! vectorial ! ! Adunarea explicita ! write(*.6)')(v1(i).6)')v1(i).norma end program vect1 program maxloc_minloc ! ! locul valorii maxime si valoarea maxima intr-un vector 32 .v2(i).2x.abs(v1))) write(*.'(3g13.*)'Produs_scalar='.n) ! ! Norma unui vector ! norma=sqrt(dot_product(abs(v1).6)')v1(i).v1(i).v2) ! ! Inmultirea a doi vectori component cu component ! v3=v1*v2 write(*.v2(i).ps ! ! Functia dot_product(vector1.*)'Produs_scalar='.*)'Diferenta a doi vectori' do i=1.n v3(i)=v1(i)+v2(i) write(*.'(2g13.const write(*.i=1.dot_product(v1.*)'Produs scalar' ps=0.v3(i).Dan RacoŃi Elemente de Fortran 95 ! Inmultirea unui vector cu o constanta ! const=1.*)'Suma a doi vectori' do i=1.v2(i).3g13.n ps=ps+v1(i)*v2(i) enddo write(*.6)')(i.'(3g13.d0 do i=1.v3(i).v3(i) enddo ! ! Scaderea a doi vectori ! v3=v1-v2 ! vectorial ! ! Scaderea explicita ! write(*.v3(i) enddo ! ! Produsul scalar ! write(*.i=1.

.dimension(5) :: x=(/1.1:3) echivalentă cu real a(2...1) 2 a(2. reale şi complexe. i = 1.1) a(2. n.xmin write(*...5.xmin end program maxloc_minloc 5.3) a(2.3) OperaŃiile matriciale din algebră se transpun direct in limbajul FORTRAN pentru matrice cu elemente întregi........3) Reprezentarea internă: 1 a(1..2) a(2. i = 1. i = 1.1) 3 a(1..2.2) 5 a(1.3) a(1.2. j = 1..2.2. i = 1... n Scăderea a două matrice: C = A− B cij = aij − bij .*)locatie.7. n.2. n j =1 n 33 . n./) real xmax..*)x locatie=maxloc(x) ! indicele valorii maxime xmax=maxval(x) ! valoarea maxima write(*. Matricile sunt memorate pe coloană. j = 1. n Adunarea a două matrice: C = A+ B cij = aij + bij .. j = 1.2.2..-1.*)locatie. n ÎnmulŃirea a două matrice: C = AB cij = ∑ aik bkj ... j = 1....Dan RacoŃi Elemente de Fortran 95 ! locul valorii minime si valoarea minima intr-un vector ! implicit none integer locatie(1) real. ÎnmulŃirea unei matrice cu o constantă: C = cA cij = caij .2) a(1.2) 4 a(2.2 Matrici Matricile sunt tablouri cu două dimensiuni.... Considerăm matrice cu elemente complexe pătrate de dimensiune n..2.xmax locatie=minloc(x) ! indicele valorii minime xmin=minval(x) ! valoarea minima write(*.....1) a(1.4.. real a(1:2.. n..3) 6 a(2.

parameter :: n=3 ! dimensiunea matricilor real.1) + b(1.2) c(2.2.2)..2.5.*)'Produsul unei matrici cu o constanta' write(*.b ! se declara matricile a si b ! cu n linii si n coloane real c(n. & ! prima coloana din matricea b -6.5 c = a+b sau : c(1.1) = a (2.n)/1.-2.3/ ! vectorul v1 write(*...j=1.*)'Matricea b' write(*.j=1./ ! a treia linie din matricea a data b/-1.j data (a(1.f90 efectuează calculele matriciale elementare matricial.*)'Matricea a' do i=1..1) c(1.2) 0.1) = a (1.Dan RacoŃi Elemente de Fortran 95 Norma unei matrice:  n n 2 A =  ∑∑ aij     i =1 j =1  OperaŃiile matriciale sunt definite în FORTRAN...6. program mat1 implicit none integer.3. & ! a doua coloana din matricea b 8.i=1.'(3g13./ ! a doua linie din matricea a data (a(3..2) = a (2.6)')(a(i./ ! a treia coloana din matricea b data v1(1).6)')((b(i. complex a(2.v1(3)/1.j=1.2.n).j=1.n) ! ! Produsul unei matrici cu o constanta ! c=const*a ! matricial write(*.j)..i=1.3.8.6)')((c(i.v1(n).2) + b(1.n).'(3g13.-4.v2(n) real :: const=3.*)'Matricea c' write(*..j=1.dimension(n.-3.'(3g13.c(2.n write(*../ ! prima linie din matricea a data (a(2.2).1. 1.-2.j).j).j).n) enddo write(*.1) c(2.2) + b(2.v1(2).n) :: a.3 ! Se defineste constanta const real norma integer i. 2.j)..j).n) ! ! Suma a doua matrici ! c=a+b ! matricial 34 ...n).1) + b(2.n)/7.2) = a (1.n)/4.2) Programul mat1.j=1..9.b(2.

b) write(*.-3./ ! a doua linie din matricea a data (a(3..k data (a(1..j=1.../ ! prima linie din matricea a data (a(2.j=1.parameter :: n=3 ! dimensiunea matricilor real.d0 do i=1.j).6)')((c(i.n)/4.n).n)/1.3.6)')((c(i.n) ! ! Produsul a doua matrici ! c=matmul(a.. & ! prima -6.*)'Matricea c' write(*.n) :: a.5.-2.-4.'(3g13.-2.j).3 ! Se defineste constanta const real norma..j))**2 enddo enddo norma=sqrt(norma) write(*.2.dimension(n.*)'Produsul a doua matrici' write(*.9..Dan RacoŃi Elemente de Fortran 95 write(*.i=1.j.v1(n).n) ! ! Diferenta a doua matrici ! c=a-b ! matricial write(*.j=1.i=1.n) ! ! Produsul unei matrici cu un vector ! v2=matmul(a..norma end program mat1 Programul mat2.j=1.*)'Norma matricei a' write(*.*)'Suma a doua matrici' write(*.*)'Diferenta a doua matrici' write(*.*)'Produsul unei matrici cu un vector' write(*..j).n).suma integer i.n do j=1.f90 efectuează operaŃiile matriciale explicit.j). program mat2 implicit none integer..i=1.'(3g13.6)')(v2(i).v2(n) real :: const=3.'(3g13.i=1..n) ! ! ! Norma matriciala norma=0.j).j).n norma=norma+abs(a(i.*)'Matricea c' write(*.6.n).*)'norma='.j=1.. & ! a doua coloana din matricea b coloana din matricea b 35 .*)'Matricea c' write(*./ ! a treia linie din matricea a data b/-1.8.6)')((c(i.b ! se declara matricile a si b ! cu n linii si n coloane real c(n.n).n)/7.'(g13.j=1.v1) write(*.

*)'Matricea c' write(*.j)=a(i.j)+b(i.*)'Matricea c' write(*.3/ ! vectorul v1 write(*.'(3g13.j)=const*a(i.n do j=1. 1.6)')(v2(i).6)')((c(i.1.6)')(a(i./ ! a treia coloana din matricea b data v1(1).j)=a(i.3. do j=1.i=1.n write(*.'(3g13.n c(i.i=1.n) ! ! Diferenta a doua matrici ! do i=1.6)')((b(i.n) ! ! Produsul a doua matrici ! do i=1.j).*)'Diferenta a doua matrici' write(*.j=1.'(g13.*)'Matricea b' write(*.'(3g13.n).j).6)')((c(i.v1(2).Dan RacoŃi Elemente de Fortran 95 8..i=1.'(3g13.*)'Suma a doua matrici' write(*.*)'Produsul unei matrici cu o constanta' write(*.n).j)-b(i.j)*v1(j) enddo v2(i)=suma enddo write(*.j) enddo enddo write(*.n) ! ! Suma a doua matrici ! do i=1.2.n) ! ! Produsul unei matrici cu o constanta ! do i=1.j=1.j).v1(3)/1.n do j=1.6)')((c(i.n do j=1.n).i=1.n) enddo write(*.j).2.j) enddo enddo write(*.j=1.'(3g13.j) enddo enddo write(*.j=1.n c(i..*)'Matricea c' write(*.*)'Matricea a' do i=1.j).n c(i.n suma=0.n).n suma=suma+a(i.i=1.n) ! ! Produsul unei matrici cu un vector ! do i=1.n 36 .j=1.*)'Produsul unei matrici cu un vector' write(*. 2.n do j=1.

4..:) enddo ! ! Matricea unitate (3.*)'Norma matricei a' write(*.1.2.shape) InstrucŃiunea: a=reshape((/1.*)'Matricea c' write(*..2.3.3) ! b=reshape((/1.4./).*)a(i.j=1.6.3) integer i ! ! Matricea a memorata pe coloane ! a=reshape((/1...'(3g13.... program reshape_function implicit none real a(2. a=  2.k)*b(k.6)')((c(i.0.(/2.:) enddo 37 ../) este echivalentă cu: 1.j))**2 enddo enddo norma=sqrt(norma) write(*./).i=1. do k=1.0.b(3..n) ! ! Norma matricei a ! norma=0..*)b(i.5./). 3.n).1.norma end program mat2 Matricele pot fi iniŃializate cu instrucŃiunea data sau utilizând instrucŃiunea reshape: result=reshape(source.*)'Produsul a doua matrici' write(*.3. 4.2.2 write(*..3)..0.n do j=1..3/)) write(*.*) do i=1...0.n suma=suma+a(i.0..0.j) enddo c(i.(/2.n norma=norma+abs(a(i.3/)) do i=1.d0 do i=1..j)=suma enddo enddo write(*.Dan RacoŃi Elemente de Fortran 95 suma=0.j).(/3.*)'norma='.3 write(*.

3)/) ! ! ! ! ! numarul de linii ! numarul de coloane ! se declara o matrice (lin.81:90) SemnificaŃie toată matricea toată matricea tablou unidimensional conŃinând linia 7 din matrice tablou unidimensional conŃinând linia 7 din matrice tablou unidimensional conŃinând coloana 7 din matrice tablou bidimensional conŃinând sub_blocul din matrice indicat prin rangul indicilor.:)=(/(i.1:100) matrice(:.100) :: matrice Array section matrice(:.3..54.:)=(/1.6./) a(2.2.col) :: a a(1. tablou(10.88..4..5.10) program initializare_matrici integer.:) matrice(7.i=1.parameter :: col=3 real.:)=(/4.1:100) matrice(7..dimension(lin.43.dimension(100. în această ordine vector(ivector) tablou unidimensional conŃinând elementele 1.8.5 din vector.i=-1.parameter :: lin=4 integer.54.5/) tablou unidimensional conŃinând elementele 10.88/) Array section vector(:) vector(1:100) vector(1:10) vector(51:100) vector(51:) vector(10:1:-1) SemnificaŃie tot vectorul tot vectorul tablou unidimensional conŃinând primele 10 elemente din vector tablou unidimensional conŃinând elementele 51:100 din vector identic cu vector(51:100) tablou unidimensional conŃinând primele 10 elemente din vector în ordine inversă vector(/10.:) matrice(1:100.7) matrice(1:10.8..:) ! se scrie linia i enddo 38 .Dan RacoŃi Elemente de Fortran 95 end program reshape_function Advanced.dimension(6) :: ivector=(/1.'(3g13.col) prima linie din matrice a doua linie din matrice a treia linie din matrice a patra linie din matrice do i=1.:)=(/(0.43. ARRAY SECTIONS Se definesc (extrag) tablouri din vectori şi matrice.1)/) a(4.4.3.lin write(*.3.88 din vector în această ordine real. real(4) dimension(100) :: vector integer.5)')a(i.88./) a(3.

do j=1.:)*x) ! m1(i.:) write(*.j)=rand(0) ! se genereaza aleator elementele matricei B enddo 39 .j)=rand(0) ! generare aleatoare enddo write(*.j real rand write(*. dimension(n.j.parameter :: n=3 real.Dan RacoŃi Elemente de Fortran 95 end program initializare_matrici program array_constructor implicit none integer. rezultatul este un vector ! sum calculeaza suma vectorului write(*.*)m1(3.j)=rand(0) ! se genereaza aleator elementele matricei A b(i.n do j=1.j=1.:) corespunde unui vector enddo ! m1(i.c real rand integer i.*) write(*.*)v ! ! Inmultirea cu array_constructor ! do i=1.*)v end program array_constructor Advanced program array ! Tablouri in F90 implicit none integer.n) real.n) ! scriere explicita x(i)=rand(0) enddo write(*.k do i=1.*)'Prima linie din matricea m1' write(*.n a(i.dimension(n) :: x.*)'Matricea m1' do i=1.*)(m1(i.b.v real s integer i.n do j=1.n m1(i.:) ! ! Inmultirea explicita a unei matrici cu un vector ! do i=1.n s=s+m1(i.j)*x(j) enddo v(i)=s enddo write(*. dimension(n) :: m1(n.parameter :: n=3 real.n) :: a.j).*)m1(1.*) write(*.*)m1(2.:)*x inmultirea component cu component ! a doi vectori.:) write(*.*)'A doua linie din matricea m1' write(*.*)'A treia linie din matricea m1' write(*.n s=0.n v(i)=sum(m1(i.

:) ! scrie o linie enddo write(*.3 Gauss Seidel Metoda Gauss Seidel este o metodă iterativă pentru calculul soluŃiei unui sistem de ecuaŃii algebrice liniare.n) do i=1.j)=sum(a(i.' (6(g12.n) matrici in FORTRAN 90 scrie_matrice(c.j)) enddo enddo write(*. enddo .c(i) enddo write(*. c(i)=rand(0) .m .n write(*.*)'Matricea A' .5.n do j=1.n.n) Automatic array program automatic integer. enddo do i=1.m write(*.m write(*.parameter :: n=2 real a(ndim.m) ! automatic array ! automatic array do i=1.n . do j=1.:) enddo end subroutine sub1 5.i real. enddo .1x))')a(i.m .b) real b(ndim. call end program array subroutine scrie_matrice(a.*)'Matricea B' .n) ! tipareste un tablou implicit none integer :: n.Dan RacoŃi Elemente de Fortran 95 enddo write(*.n) scrie_matrice(b. call ! ! Inmultirea explicita a doua ! do i=1. Considerăm sistemul de n ecuaŃii algebrice liniare: 40 .*) do i=1.a) end program automatic subroutine sub1(ndim. Metoda converge dacă matricea sistemului este diagonal dominantă pe linii.n) :: a do i=1. call write(*. enddo call sub1(ndim.m. a(i.*) ! scrie o linie alba end subroutine scrie_matrice scrie_matrice(a.m) real c(m) real d(m. d(i.dimension(n.:)*b(:. Metoda converge dacă matricea sistemului este simetrică şi pozitiv definită.j)=rand(0) .:).*)'Matricea C' .j)=rand(0) .parameter :: ndim=5 integer. do j=1.n .*)d(i.*)b(i.n c(i.

parameter :: n=3 integer.b(n).*)'vectorul b' do i=1.x(n).parameter :: it_max=111 ! numarul maxim de iteratii real(8).d0.01d0 ! aproximatia initiala (vectorial) write(*.j).….Dan RacoŃi Elemente de Fortran 95 ∑a j =1 n ij x j = bi i=1.d0/) ! vectorul b j = i +1 ∑a ij xk j write(*.j=1.n).n write(*.d0.2.parameter :: eps=1.2.n IteraŃiile metodei Gauss Seidel se efectuează conform ecuaŃiei: i −1 n bi − ∑ aij x k +1 − j xik +1 = j =1 i=1.d0.r(n).14.2.*)'matricea A' do i=1. & ! a doua coloana din matricea a 1. IteraŃiile se opresc când norma reziduului este mai mică decât o toleranŃă impusă: r = b − Ax k r <ε program gauss_seidel ! ! Determina solutia unui sistem diagonal dominant ! cu metoda iterativa Gauss Seidel ! implicit none integer.d-5 ! toleranta impusa real(8) norma_reziduu real(8) a(n.'(5g11.d0.… Se pleacă de la o aproximaŃie iniŃială dată.4)')b(i) enddo x=0.2.s integer i.(norma_reziduu>eps)) do i=1.2.'(5g11.d0.10.x)-b ! calculul reziduului (matricial) norma_reziduu=maxval(abs(r)) iter=0 do while((iter<it_max).4)')(a(i. & ! prima coloana din matricea a 1.d0.d0 41 .….d0.j.1.d0.n s=0.iter data a/10.d0.n aii Cu k s-a notat contorul de iteraŃii k=0.and.10.1.d0/ ! a treia coloana din matricea a b=(/12.d0.*)'Iteratii Seidel' r=matmul(a.n) enddo write(*.n write(*.13.

j=1.iter.n ! suma de la j=i+1 pana la n s=s+a(i.d0/) ! vectorul b write(*.n write(*.i-1 ! suma de la j=1 pana la i-1 s=s+a(i.x)-b ! calculul reziduului (matricial) norma_reziduu=maxval(abs(r)) iter=0 42 .f13.r(i).parameter :: n=3 integer.i) else stop 'pivot zero' endif enddo iter=iter+1 r=matmul(a.n).d0/ ! a treia coloana din matricea a b=(/12.n) enddo write(*.i).b(n).d0.01d0 ! aproximatia initiala (vectorial) write(*.5)')'iter='. norma_reziduu enddo if(iter<it_max)then write(*.parameter :: it_max=111 ! numarul maxim de iteratii real(8).d0.s1.*)'vectorul b' do i=1.'(5g11.*)'Iteratii Seidel' r=matmul(a.ne.d0.d0.'(5g11. & ! a doua coloana din matricea a 1.j.13.j).d0.d0)then x(i)=(b(i)-s)/a(i.'(a.'(g12.*)'solutia' write(*.n write(*.j)*x(j) enddo do j=i+1.s2 integer i.10.r(n).2.j)*x(j) enddo if(a(i.s.d0.i=1.n) else write(*.i5.d0.4)')b(i) enddo x=0.d0.0.*)'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.x(n).2.5)')(x(i).*)'matricea A' do i=1.Dan RacoŃi Elemente de Fortran 95 do j=1.parameter :: eps=1.14.d0.1.d0.iter data a/10. & ! prima coloana din matricea a 1.10.d-5 ! toleranta impusa real(8) norma_reziduu real(8) a(n.2.4)')(a(i.f13.5.x)-b ! calculul reziduului (matricial) norma_reziduu=maxval(abs(r)) write(*.

d0)then x(i)=(b(i)-s)/a(i.1:i-1)*x(1:i-1)) ! suma de la 1 la i-1 s2=sum(a(i.0.n s1=sum(a(i.*)'solutia' write(*.c(:) Se citeste ordinul matricei write(*.x)-b ! calculul reziduului (matricial) norma_reziduu=maxval(abs(r)) write(*.allocatable :: b(:).i=1.5.(norma_reziduu>eps)) do i=1.and.iter. Dacă nu se cunoaşte aprioric dimensiunea matricelor şi a vectorilor aceştia sunt declaraŃi de tip alocatabil iar rezervarea de memorie se face în momentul execuŃiei.ialoc5 integer n. program alocate implicit none integer ialoc0.*)'neconvergenta Seidel' endif end program gauss_seidel_array_sections 5. 43 .Dan RacoŃi Elemente de Fortran 95 do while((iter<it_max).ne.*)n if(n<2)n=2 ! ! ! ! Se aloca spatiu pentru matricea a Daca alocarea reuseste variabila ialoc0 ia valoarea 0.ialoc2.'(a.n) else write(*.ialoc4.i) else stop 'pivot zero' endif enddo iter=iter+1 r=matmul(a.*)'Introduceti n' read(*.ialoc1.i+1:n)*x(i+1:n)) ! suma de la i+1 la n s=s1+s2 if(a(i.i.j real(8) s.i5.ialoc3. In caz contrar se opreste executia programului.5)')(x(i).5)')'iter='.r(i). norma_reziduu enddo if(iter<it_max)then write(*.f13.f13.'(g12.:) Se declara alocatabili vectorii b si c real(8).4 Alocarea dinamică de memorie (în execuŃie) In multe cazuri acelaşi algoritm matricial se utilizează pentru ordine de mărime diferite ale matricelor.drand ! ! Alocarea dinamica de memorie in timpul executiei ! ! ! ! ! ! ! ! ! ! Se declara alocatabila matricea a real(8).allocatable :: a(:.i).

Daca alocarea reuseste variabila ialoc2 ia valoarea 0. ! Daca dealocarea reuseste ialoc3 ia valoarea zero. ! Daca dealocarea reuseste ialoc4 ia valoarea zero.if(ialoc3.*)'Vectorul c' do i=1.*)i.ne.n s=s+a(i. ! ! ! ! ! ! ! ! ! ! ! ! ! if(ialoc0.0)stop 'ialoc2' Se genereaza aleator elementele matricei a si ale vectorului b do i=1.0)stop 'ialoc0' Se aloca spatiu pentru vectorul b.stat=ialoc2) . ! deallocate (b.n s=0. In caz contrar se opreste executia programului.ne.ne.ne.0)stop 'ialoc1' Se aloca spatiu pentru vectorul c.if(ialoc4. allocate (b(n ).if(ialoc5.0)stop 'ialoc4' ! ! Se elibereaza spatiul ocupat de vectorul c.ne.n do j=1.j)*b(i) enddo c(i)=s write(*. allocate (c(n ).stat=ialoc5). if(ialoc1. ! deallocate (c. write(*.stat=ialoc0) .c(i) enddo ! ! Se elibereaza spatiul ocupat de matricea a. ! deallocate (a.d0 do j=1.1 Clauza contains.n). FuncŃii interne 44 .Dan RacoŃi Elemente de Fortran 95 ! allocate (a(n. In caz contrar se opreste executia programului.j)=drand(0) enddo b(i)=drand(0) enddo ! ! ! Se inmulteste matricea a cu vectorul b si se obtine vectorul c.stat=ialoc1) . FuncŃii şi subprograme 6.stat=ialoc4). ! Daca dealocarea reuseste ialoc4 ia valoarea zero.0)stop 'ialoc3' ! ! Se elibereaza spatiul ocupat de vectorul b. if(ialoc2.stat=ialoc3).ne. Daca alocarea reuseste variabila ialoc1 ia valoarea 0.0)stop 'ialoc5' end program alocate 6.n a(i.

-1.y) implicit none real(4).variabilă=nume_funcŃie(argumente efective) contains tip function nume_funcŃie(argumente_formale) declaratii . expresia functiei numele functiei apare obligatoriu intr-o instructiune de atribuire 45 .y. .pi x=1.*)x.*atan(1. .1 .c c=fct(-2.y)=exp(x)*sin(pi*y) pentru x>=0 ! exp(x)*cos(pi*y) pentru x<0 ! implicit none real(4) x.-1. intent(in) ! ! Valoarea variabilei pi este ! asociere HOST ! if(x<0.) c=fct(x. nume_funcŃie=expresie end function nume_functie end program nume_program program contains_exemple ! ! Calculeaza f(x.intent(in) :: x.1.y ! parametrii de intrare. pi=4.)then fct=exp(x)*cos(pi*y) ! ! ! else fct=exp(x)*sin(pi*x) endif end function fct end program contains_exemple preluata din programul apelant.y.1 .1.1) ! apelul functiei ! apelul functiei write(*.1. . y=2.c.Dan RacoŃi Elemente de Fortran 95 Anterior s-au definit funcŃiile formulă care permit descrierea unei funcŃii definite printr-o singură ecuaŃie.*)-2.y) write(*. In cazul în care expresia funcŃiei este mai complexă se utilizează funcŃii interne declarate în programul principal după cuvântul cheie contains: program nume_program declaraŃii .c contains real(4) function fct(x.

Toate variabilele trebuie să fie definite în interiorul funcŃiei. FuncŃia factorial n!= 1.. INTENT(IN) :: N INTEGER :: F.COMBINARI END PROGRAM EXEMPLU_FACTORIAL INTEGER FUNCTION FACTORIAL(N) IMPLICIT NONE INTEGER.COMBINARI.3.N.I IF(N==0)THEN FACTORIAL=1 ELSEIF(N>1)THEN F = 1 DO I = 1..FACTORIAL. .F. M=2 F=FACTORIAL(N) COMBINARI=FACTORIAL(N)/FACTORIAL(M)/FACTORIAL(N-M) WRITE(*.F N=4 .*)'N='.Dan RacoŃi Elemente de Fortran 95 6.2 FuncŃii externe FuncŃiile externe au aceeaşi structură ca şi funcŃiile interne dar constituie unităŃi separate de program. Numele funcŃiei apare obligatoriu într-o instrucŃiune de atribuire.' M='.M.M. tip function nume_funcŃie(argumente_formale) declaratii .2. N F = F * I END DO FACTORIAL = F ELSE STOP 'ARGUMENT INCORECT' ENDIF END FUNCTION FACTORIAL ! ARGUMENTUL ! SE CALCULEAZA IN BUCLA n! 6.FuncŃii în complex 46 .1.n 0!= 1 permite calculul combinărilor: n! m Cn = m!(n − m)! PROGRAM EXEMPLU_FACTORIAL IMPLICIT NONE INTEGER N.' F='. nume_funcŃie=expresie end function nume_functie Intre tipul şi numărul de argumente din programul apelant şi funcŃie există o corespondenŃă biunivocă.' C='.2.

y.Dan RacoŃi Elemente de Fortran 95 O mare atenŃie trebuie acordată calculului cu funcŃii complexe deoarece pot avea mai multe valori (sun multiforme).5 0 y -0. DistanŃa de la centrul cercului la originea axelor O.y.' y='.*)'x='.5 1 Figura 6.” Se dau două numere reale x şi y. .y) fz=fct(z) write(*.1 Profil Jukovski generat prin transformare conformă 47 .z. Unghiul ascuŃit făcut de OM cu axa orizontală este δ. Se determină numărul complex: z = x + iy şi se calculează funcŃia complexă: 1 f (z) = z + z Partea reală şi partea imaginară sunt Re( f ( z )) şi Im( f ( z )) . Raza cercului este a. De exemplu calculul radicalului in Fortran: „ As a result of type complex is the principal value.*)'x='.*)'z='.' Real(fz)='.' y='.' Imag(fz)='. the imaginary part is greather than or equal to zero. z=cmplx(x.5 0 x 0.y complex z.2 . When the real part of the result is zero.2. Profil Jucovski general 1 0.x. program functii_complexe implicit none real x.fz.fz write(*. with the real part greather than or equal to zero./z end function fct Profil Jukovski general Considerăm un cerc cu centrul în cadranul doi în punctul M.imag(fz) end program functii_complexe complex function fct(z) complex.' fz='.real(fz) write(*.fct x=2. y=2. DistanŃa de la originea axelor la cerc pe axa orizontală este q. segmentul OM este m.x.intent(in) ::z fct=z+1.5 -1 -1 -0.

file='c:\for\jg.txt') q=0.d0.d0*atan(1.'(6(f10.pi/24.xx(teta).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.o-z) real(8) m complex(8) zeta. Coordonatele carteziene ale profilului sunt: x = Re( z ) y = Im( z ) program jukovski_g ! profil Jukovski general implicit real(8) (a-h.4d0 ! constanta din transformata Jukovski delta=15.csi.csi.d0) open(1.yy(teta).2*pi.yy(teta).Dan RacoŃi Elemente de Fortran 95 Considerăm transformarea de coordonate: ξ = −m cos δ + a cos θ η = + m sin δ + a sin θ şi numărul complex: ζ = ξ + iη Transformarea conformă Jucovski: z =ζ + q2 ζ reprezintă conform exteriorul unui cerc de rază a cu centrul în M pe exteriorul unui profil în planul z.eta) z=zeta+q**2/zeta ! transformata Jukowski x=real(z) ! coordonate carteziene y=imag(z) write(*.1x))')x.d0/180.'(6(f10.1d0 a=sqrt(q**2+m**2+2*q*m*cos(delta)) ! (18.eta write(1.6.z pi=4.y.d0*pi m=0.1x))')x.y.6.66) Carafoli do teta=0.xx(teta).d0 csi=-m*cos(delta)+a*cos(teta) eta= m*sin(delta)+a*sin(teta) zeta=cmplx(csi.3 FuncŃii recursive 48 .

n. . valoarea_funcŃiei=expresie end function nume_functie end program nume_program program recursivef ! ! Calculeaza functia factorialorial recursiv ! implicit none integer n. In cazul funcŃiilor recursive. recursive function nume_funcŃie(argumente_formale) result(valoarea_funcŃiei) declaratii .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 49 .' factorialorial='. valoarea funcŃiei este memorată într-o variabilă auxiliară declarată cu cuvântul cheie result.f.factorial n=4 f=factorial(n) ! apelul functiei recursive factorial write(*.*)'n='. In cazul funcŃiilor clasice în corpul funcŃiei apărea obligatoriu expresia: nume_funcŃie=expresie_aritmetică.Dan RacoŃi Elemente de Fortran 95 FuncŃiile recursive sunt funcŃiile care se autoapelează.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. Un exemplu clasic este funcŃia factorial: n!= n(n − 1)! 0!= 1 1!= 1 FuncŃiile recursive sunt implementate în limbajul FORTRAN.

5( f (0. INTENT (IN) :: A. ABS_ERROR) RESULT (REZULTAT) REAL(8). PROGRAM RECURSIVE ! TEST_ADAPTIVE_QUAD ! ! Copyright Bo Einersson and Yurij Stokin ! ! Fortran 90 for Fortran 77 Programmer.5( f (a) + f (b) ) a b Pentru mărirea preciziei se introduce un punct intermediar la mijlocul intervalului: 0. atunci se împarte intervalul în două ş. echivalentă cu formula lui Simpson: I 2 − I1 I = I2 + 3 Dacă condiŃia nu este îndeplinită.Dan RacoŃi Elemente de Fortran 95 Copyright 1993. 1996 by Bo Einersson and Yurij Stokin Fortran 90 for Fortran 77 Programmer.a. A. B. TOL REAL(8) :: ABS_ERROR ! EROAREA ABSOLUTA REAL(8) :: REZULTAT ! VALOAREA CALCULATA A INTEGRALEI REAL(8) :: PI 50 . INTENT (OUT) :: ABS_ERROR REAL(8) :: REZULTAT END FUNCTION ADAPTIVE_QUAD END INTERFACE REAL(8) :: A.5 ( b − a ) ∫ f ( x)dx = 0.d. TOL.5(b − a)) ) + 0.5 ( b − a ) I2 = ∫ a f ( x)dx + 0.5( f (a) + f (0. B.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).m.5(b − a)) + f (b)) b Se observă că pentru a calcula I2 se apelează tot la formula trapezelor (recursivitate). Version 2.3 Calculul unei integrale definite cu metoda trapezelor se bazează pe formula: I 1 = ∫ f ( x)dx =0. INTENT(IN) :: X REAL(8) :: FUNCTION_VALUE END FUNCTION F END INTERFACE INTERFACE RECURSIVE FUNCTION ADAPTIVE_QUAD & (F. Version 2. B. TOL REAL(8). EXTERNAL :: F REAL(8). Eroarea absolută este dată de diferenŃa celor două integrale şi se compară cu o toleranŃă impusă: I 2 − I 1 < tol Dacă condiŃia este realizată se calculează valoarea finală a integralei prin extrapolare Richardson.

25d0 * (F(MIDDLE_POINT) + F(B)) ONE_T_AREA :: A. TOL.0d0) A= 0. MIDDLE_POINT. INTENT(OUT) REAL(8) REAL(8) REAL(8) REAL(8) REAL(8) STEP = B-A MIDDLE_POINT= 0. F15. B=PI TOL =0. RIGHT_AREA DIFF.VAL_E ENDDO END PROGRAM RECURSIVE ! TEST_ADAPTIVE_QUAD FUNCTION F(X) RESULT (FUNCTION_VALUE) IMPLICIT NONE REAL(8).0d0 REZULTAT = ADAPTIVE_QUAD (F. TWO_T_AREAS LEFT_AREA. A.10)")"Inr_e ". TOL :: ABS_ERROR :: REZULTAT :: :: :: :: STEP. INTENT(IN) :: X REAL(8) :: FUNCTION_VALUE END FUNCTION F END INTERFACE REAL(8).D0 .ABS_ERROR VAL_E=PRIMITIVA(B)-PRIMITIVA(A) ! LEIBNITZ-NEWTON WRITE(*. ABS_ERROR_L.10)")"Int_a ". F15. A.Dan RacoŃi Elemente de Fortran 95 REAL(8) :: VAL_E INTEGER :: I REAL(8) :: PRIMITIVA. & VAL_E.10. " err_real ". F15. B. TOL.0d0 ! EXTRAPOLARE RICHARDSON ABS_ERROR = ABS(DIFF) ELSE LEFT_AREA = ADAPTIVE_QUAD (F. INTENT(IN) :: X REAL(8) :: FUNCTION_VALUE FUNCTION_VALUE = SIN(X) END FUNCTION F RECURSIVE FUNCTION ADAPTIVE_QUAD (F. A.1d0 ! VALOAREA EXACTA ! PRIMITIVA FUNCTIEI CARE SE ! INTEGREAZA NUMERIC ! LIMITELE DE INTEGRARE ! TOLERANTA INITIALA DO I = 1. 5 TOL = TOL/10. A. F15.5d0 * (A+B) ONE_T_AREA = STEP TWO_T_AREAS = STEP STEP DIFF = TWO_T_AREAS * * * 0.*) WRITE(*. INTENT(IN) REAL(8). ABS_ERROR_L) 51 . & REZULTAT.5d0*TOL."(A. ABS_ERROR) WRITE(*. ABS_ERROR_R IF ( ABS (DIFF) < TOL ) THEN REZULTAT = TWO_T_AREAS + DIFF/3.X PRIMITIVA(X)=-COS(X) PI = 4."(A.10.REZULTAT . B. " err_estm ".25d0 * (F(A) + F(MIDDLE_POINT))+& 0.50d0 * (F(A) + F(B)) 0. B. A. ABS_ERROR) & RESULT (REZULTAT) IMPLICIT NONE INTERFACE FUNCTION F(X) RESULT (FUNCTION_VALUE) REAL(8). & 0. MIDDLE_POINT ONE_T_AREA.0d0 * ATAN(1.

ABS_ERROR_R) REZULTAT = LEFT_AREA + RIGHT_AREA ABS_ERROR = ABS_ERROR_L + ABS_ERROR_R END IF END FUNCTION ADAPTIVE_QUAD 6.3 2 2 Eroarea metodei este dată de formula restului: 5 1  b − a  (4) R2 =   f (ξ ) 135  2  unde ξ este un punct din intervalul (a.4 InstrucŃiunea External InstrucŃiunea external se utilizează pentru a transmite ca subprogramele ca parametrii la subprograme.2. program external1 implicit none real a. & 0. B.b).6 xi = b+a b−a + t i . Metoda Gauss pe trei puncte este: b b−a ∫ f ( x)dx = 2 ( A1 f ( x1 ) + A2 f ( x2 ) + A3 f ( x3 ) ) a t1 = − 0.6 t2 = 0 t 3 = + 0. MIDDLE_POINT.x external functia1. Avem o funcŃie care calculează integrala unei funcŃii continue cu metoda Gauss cu trei puncte.er2 ! eroarea absoluta real gauss3 real primitiva1.5d0*TOL. Dorim să calculăm în acelaşi program doua integrale: I 1 = ∫ exp( x)dx a b I 2 = ∫ sin( x)dx a b utilizând aceeaşi funcŃie (metoda Gauss) pentru calculul numeric al integralelor.f2e ! valorile analitice ale integralelor real er1. Să considerăm următorul exemplu.Dan RacoŃi Elemente de Fortran 95 RIGHT_AREA = ADAPTIVE_QUAD (F.functia2 primitiva1(x)= exp(x) 52 . i = 1.primitiva2.b real f1c.f2c ! valorile calculate ale integralelor real f1e.

' f2e='.5*(b-a)*t3 gauss3=0.a.f2c.er1 f2c=gauss3(functia2.' f1e='. t2=0.' er2='.5 f1c=gauss3(functia1. t3=+sqrt(0. 53 . .b) implicit none real.5*(b-a)*t1 x2=0. f2e=primitiva2(b)-primitiva2(a) er2=abs(f2c-f2e) write(*. x1=0.f2e.b ! limitele de integrare real fct ! functia care se integreaza real t1.5*(b-a)*(a1*fct(x1)+a2*fct(x2)+a3*fct(x3)) end function gauss3 real function functia1(x) implicit none real.f1c.' er1='. .er2 end program external1 real function gauss3(fct.intent(in) :: x functia1=exp(x) end real function functia2(x) implicit none real. . a2=8.a3 real x1.6) a1=5./9.6) . . [recursive ] subroutine nume_subrutină(lista_argumente_formale) declaraŃii .5*(b-a)*t2 x3=0.b) .*)'f2c='.5*(b+a)+0.5*(b+a)+0. a3=5.intent(in) :: a./9.t3 real a1.t2. end subroutine nume_subrutina Se poate specifica (opŃional) 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ă.*)'f1c='.x2. . b=0.f1e./9.Dan RacoŃi Elemente de Fortran 95 primitiva2(x)=-cos(x) a=0. .5*(b+a)+0.5 Subrutine Subprogramele de tip SUBROUTINE permit calculul mai multor valori în corpul subprogramului şi transmiterea lor în programul apelant.intent(in) :: x functia2=sin(x) end 6.b) . f1e=primitiva1(b)-primitiva1(a) er1=abs(f1c-f1e) write(*.a.a.a2.x3 ! abscise Gauss ! ponderi Gauss t1=-sqrt(0.

Dan RacoŃi Elemente de Fortran 95 In cazul în care argumentul este o funcŃie sau o subrutină aceasta se declară în instrucŃiunea external în programul apelant.a. b=1.functie(x) enddo end subroutine tabelare real function fct1(x) real.dreapta.*) call tabelare(fct2.n) ! tabelarea functiei fct1 write(*.ndim) 54 .b ! limitele intervalului in care se tabeleaza functia integer n ! numarul de puncte din tabel real fct1.m) implicit none real :: functie real.intent(in) :: dreapta integer. program subr1 ! ! Tabeleaza doua functii pentru a <= x <= b ! implicit none real a.) fct2=exp(x)*cos(pi*x) end function fct2 6.a.1 Transmiterea tablourilor la subprograme Considerăm cazul uzual al matricelor pătrate: real matrice(ndim.intent(in) :: x real pi pi=4.b.n) ! tabelarea functiei fct2 end program subr1 subroutine tabelare(functie.5. Subrutina este apelată cu instrucŃiunea call: call nume_subrutină(lista_argumente_efective) Există o corespondenŃă biunivocă ca tip şi număr între lista de argumente formale şi lista de argumente efective.b. n=11 call tabelare(fct1.intent(in) :: stanga real. .m x=stanga+(i-1)*dx write(*.*)x.*atan(1.fct2 ! functiile care se tabeleaza external fct1.) fct1=exp(x)*sin(pi*x) end function fct1 real function fct2(x) real.intent(in) :: x real pi pi=4.stanga.intent(in) :: m real dx.x integer i dx=(dreapta-stanga)/(m-1) do i=1.*atan(1.fct2 ! functiile sunt transmise ca argument a=0. .

n.2 Rezolvarea sistemelor de ecuaŃii algebrice lineare Prin discretizarea ecuaŃiilor fizicii matematice se obŃin sisteme algebrice liniare de mari dimensiuni.parameter :: ndim=5 real. call subrutina(ndim. Moler. B. P. 55 . LINEAR EQUATION SOLVER.Dan RacoŃi Elemente de Fortran 95 Valoarea ndim (leading dimension) este transmisă obligatoriu subprogramului. 274. In cazul in care n=3 în subrutină se lucrează cu o matrice cu trei linii şi trei coloane.*) n=5 do i=1.n do j=1.dimension(ndim.j do i=1.dimension(ndim.intent(in) :: n real. 15 (1972).j)=rand(0) enddo enddo call scrie_matrice(ndim. C. Algoritmul Gauss are extrem de multe variante şi implementări.M.ORG .matrice) end program subr2 subroutine scrie_matrice(ndim.'(5(g13.matrice) program subr2 ! ! transmiterea tablourilor in subprograme ! integer.3. Vom prezenta implementarea standard datorată lui C.6.j=1.n matrice(i. In cazul în care n=5 în subrutină se lucrează cu o matrice cu 5 linii şi cinci coloane.5.intent(in) :: ndim integer. Să presupunem că ndim=5.n) enddo end subroutine scrie_matrice 6. Dimensiunea efectivă (cu care se lucrează) este n mai mic sau egal cu ndim.n matrice(i.matrice) call subrutina(ndim.C.intent(in) :: a integer i.*).j).A.j n=3 do i=1. O cale pentru a rezolva aceste sisteme de ecuaŃii liniare este algoritmul Gauss cu pivotare parŃială. vezi NETLIB. Subprogramul poate fi apelat cu n=5 sau cu n=3.ndim) :: matrice integer n.n write(*.a) implicit none integer.n do j=1.n.j)=rand(0) ! functia rand genereaza numere pseudo aleatoare enddo enddo call scrie_matrice(ndim. .n.matrice) ! scrie matricea de dimensiune n write(*.1x))')(a(i.5.i. ALGORITHM 423.

Elementele matricei inverse sunt notate cu xij: 1 0 0  x11 x12 x13  1 0 0  0 1 0  A  x  = I = 0 1 0  −1 AA = I =    21 x 22 x 23    0 0 1  x31 x32 x33  0 0 1         x11 LU  x 21   x31  x12 x 22 x32 x13  1 0 0  = I = 0 1 0  x 23    0 0 1  x33      x11  1  x12  0  x13  0             LU  x 21  = 0 LU  x22  = 1 LU  x 23  = 0  x  0  x  0      31     32     x33  1 program inversa_moler ! ! ! ! ! ! ! ! ! ! Calculeaza inversa unei matrici patrate de dimensiune n. NONSTIFF PROBLEMS. Rezolvarea sistemului de ecuaŃii este redusă la rezolvarea a două sisteme de ecuaŃii cu matrice triunghiulară prin retrosubstituŃie.Dan RacoŃi Elemente de Fortran 95 AUTHORS: E. SPRINGER-VERLAG (1996) Ax = b Considerăm sistemul algebric linear: Matricea A este descompusă într-un produs de două matrice triunghiulare L (lower) şi U (upper). S. SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS.n) real(8) matricea X=A**(-1)(n. Se rezolva apoi prin retrosubstitutie n sisteme algebrice avand drept membru drept cate o coloana din matricea unitate.ch Gerhard. NORSETT AND G. HAIRER AND G. HAIRER.n) real(8) vectorul B(n) real(8) Total real(8) n*n n*n n 2*n*n+n 56 .Wanner@math.unige.P. WANNER UNIVERSITE DE GENEVE. 2ND EDITION. SWITZERLAND E-MAIL: Ernst.unige. SOLVING ORDINARY DIFFERENTIAL EQUATIONS I. DE MATHEMATIQUES CH-1211 GENEVE 24. A = LU LUx = b Ly = b Ux = y Pentru a calcula inversa unei matrice de dimensiune 3 se rezolvă prin retrosubstituŃie trei sisteme algebrice liniare.ch THIS CODE IS DESCRIBED IN: E. Se efectueaza descompunerea LU a matricei sistemului. WANNER. DEPT.Hairer@math. matricea A(n.

IER) ! MOLER ! if(ier.n) end SUBROUTINE DEC (N. DEPT.n a(i.n) as=a ! salveaza matricea A pentru verificare call DEC (N.unige.d0 write(*. HAIRER AND G.n) ! matricea A salvata pentru verificare integer ip(n) ! vector permutari linii do i=1. A. NDIM.d0 ! vectorial b(j)=1.unige.j=1.f7.*)'Coloana='.n).o-z) integer.n) call SOL (N.j).as) write(*.0)stop 'matrice singulara' ! ! ! Calcul inversa X(*.j write(*.'(5f7.5)')((a(i.*)'Matricea [A]**(-1)*[A]' write(*.*)'Matricea [A]' write(*.j).ch Gerhard.'(5f12.2)')(k.2x.i=1.n) c=matmul(x.*) cite o coloana o data' do j=1.n). A.b(n) real(8) c(n. N.Wanner@math. WANNER UNIVERSITE DE GENEVE.n ! coloana j din matricea inversa (matricea A este inlocuita cu descompunerea LU) b=0.5)')((x(i.3)')((c(i.ne. N. DE MATHEMATIQUES CH-1211 GENEVE 24. A.j)=drand(0) enddo enddo write(*.j=1.k=1.i=1.n).'(5f12. IP. SWITZERLAND E-MAIL: Ernst.j).'(i2.j=1.i=1.x(n.j)=b(i) enddo enddo write(*.Dan RacoŃi Elemente de Fortran 95 ! ! vectorul ip(n) integer(4) implicit real(8) (a-h.n). IP. 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.b(k).n) ! matricea unitate real(8) as(n.n do j=1. IER) ! ! ! ! ! ! ! ! AUTHORS: E.n).*)'Matricea [A]**(-1)' write(*.n x(i.Hairer@math.parameter :: n=5 real(8) a(n.ch THIS CODE IS DESCRIBED IN: 57 . B.

EQ.T DIMENSION A(NDIM. ! ! REFERENCE.LE. HAIRER.Dan RacoŃi Elemente de Fortran 95 ! E.IP.N). I . OR K IF FOUND TO BE ! SINGULAR AT STAGE K.J). LINEAR EQUATION SOLVER. I. K) GO TO 20 IP(N) = -IP(N) A(M.K) = -A(I...J) = A(K.NM1. 0. ! SPRINGER-VERLAG (1993) ! ! VERSION REAL DOUBLE PRECISION INTEGER N.N T = A(M.N A(I. K.K) = A(K. ! C. !----------------------------------------------------------------------IER = 0 IP(N) = 1 IF (N .GT.J).KP1.2)*. WANNER.N = INDEX OF K-TH PIVOT ROW. ! IP(K).J) = A(I. ALGORITHM 423. ! IF IP(N)=O. DABS(A(M. A IS SINGULAR.C.K)*T CONTINUE CONTINUE CONTINUE K = N 30 40 45 50 60 70 58 . 0.N).J = MULTIPLIERS = LOWER TRIANGULAR FACTOR. 1) GO TO 70 NM1 = N . ! IP(N) = (-1)**(NUMBER OF INTERCHANGES) OR O . NONSTIFF PROBLEMS.NM1 KP1 = K + 1 M = K DO 10 I = KP1.EQ. ! A(I.K)*T DO 50 J = KP1. IP(N) !----------------------------------------------------------------------! MATRIX TRIANGULARIZATION BY GAUSSIAN ELIMINATION. S. MOLER.N A(I.K) IF (M .EQ.I.K))) M = I 10 CONTINUE IP(K) = M T = A(M.M.1)*A(2. 2ND EDITION. ! NDIM = DECLARED DIMENSION OF ARRAY A . ! USE SL TO OBTAIN SLUTION OF LINEAR SYSTEM. I.J) = T IF (T . ! IER = 0 IF MATRIX A IS NONSINGULAR...LT. U .D0) GO TO 45 DO 40 I = KP1.P.K) = T 20 CONTINUE IF (T .EQ.IER. 15 (1972).L.J) A(K. SL WILL DIVIDE BY ZERO. ! OUTPUT.J = UPPER TRIANGULAR FACTOR.1 DO 60 K = 1.*A(N. ! SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS. ! C. NORSETT AND G.J) + A(I. ! A(I.N IF (DABS(A(I.K) A(K.NDIM. ! INPUT.D0) GO TO 80 T = 1.J DOUBLE PRECISION A.M.GT. B.K)) .. SOLVING ORDINARY ! DIFFERENTIAL EQUATIONS I. ! A = MATRIX TO BE TRIANGULARIZED.J) A(M.D0/T DO 30 I = KP1.K. 274. ! N = ORDER OF MATRIX. P.A. ! DETERM(A) = IP(N)*A(1.

K. B(N).K) T = -B(K) DO 30 I = 1.1) RETURN END SUBROUTINE SOL 80 6. ! INPUT.KP1.Dan RacoŃi Elemente de Fortran 95 IF (A(N. ! DO NOT USE IF DC HAS SET IER . 0.KB. A*X = B .KM1 30 B(I) = B(I) + A(I.IP. A. Matricea A poate fi reală sau complexă.EQ.NM1 KP1 = K + 1 M = IP(K) T = B(M) B(M) = B(K) B(K) = T DO 10 I = KP1.T DIMENSION A(NDIM. ! B = SOLUTION VECTOR.NM1.N) .B.NE. 59 . 0. 1) GO TO 50 NM1 = N .D0) GO TO 80 RETURN IER = K IP(N) = 0 RETURN END SUBROUTINE DEC SUBROUTINE SOL (N. Rezultatele unor importante cercetări desfăşurate în anii 1970-1980 au condus la realizarea unui pachet de programe numit EISPACK (NETLIB.N).3 Calculul valorilor proprii Numeroase probleme de inginerie (vibraŃiile structurilor aerospaŃiale) conduc la probleme de valori proprii de tipul: Ax = λx Cu λ s-au notat valorile proprii iar cu x vectorii proprii.EQ. ! OUTPUT. ! NDIM = DCLARED DIMENSION OF ARRAY A . IP(N) !----------------------------------------------------------------------! SOLUTION OF LINEAR SYSTEM.5. B.KB K = KM1 + 1 B(K) = B(K)/A(K.K)*T 20 CONTINUE DO 40 KB = 1. ! N = ORDER OF MATRIX. NDIM.NDIM. X ..1 DO 20 K = 1. ! A = TRIANGULARIZED MATRIX OBTAINED FROM DC. ! IP = PIVOT VECTOR OBTAINED FROM DC.. ! B = RIGHT HAND SIDE VECTOR.I.K)*T 40 CONTINUE 50 B(1) = B(1)/A(1.N 10 B(I) = B(I) + A(I.KM1 DOUBLE PRECISION A. !----------------------------------------------------------------------IF (N . IP) ! VERSION REAL DOUBLE PRECISION INTEGER N.ORG).M. În această colecŃie de subrutine sunt programaŃi algoritmii numerici pentru probleme de valori proprii.NM1 KM1 = N .

problema generalizată de valori proprii: Ax = λBx Fie ecuaŃia diferenŃială. B. fi(x) care satisfac condiŃiile la limite. Garbow.Dan RacoŃi Elemente de Fortran 95 Vom considera o problemă un pic mai complicată.M. Considerăm un sistem de funcŃii liniar independente.B. New York. Se obŃine problema generalizată de valori proprii: b b  b ''  b  ''  ∫ f1 ( x) f 1 ( x)dx ∫ f 2 ( x) f 1 ( x)dx  a  ∫ f 1 ( x) f 1 ( x)dx ∫ f 2 ( x) f1 ( x)dx  a a a a  1  = λ  a  1      b b b b  a 2   ''  a 2   ''  ∫ f 1 ( x) f 2 ( x)dx ∫ f 2 ( x) f 2 ( x)dx  ∫ f 1 ( x) f 2 ( x)dx ∫ f 2 ( x) f 2 ( x)dx  a a a  a  Se calculează analitic sau numeric integralele din ultima expresie şi se obŃin matricele A şi B. Springer-Verlag. p. Boyle.mathematics and computer science div. problema Sturm-Liouville: 2 d y = λy dx 2 a <= x <= b cu două condiŃii la limite. 1977. pentru x=a şi pentru x=b.S. J.J. J. C. Matricele A şi B au elemente reale şi în acest caz sunt simetrice. Moler. Matrix Eigensytem Routine EISPACK Guide Extension. Lecture Notes in Computer Science. Căutăm soluŃia în forma (metoda Galerkin): y ( x) = a1 f1 ( x) + a 2 f 2 ( x) Substituind această soluŃie în ecuaŃia diferenŃială obŃinem: '' a1 f1 ( x) + a 2 f 2'' ( x) = λ (a1 f 1 ( x) + a 2 f 2 ( x)) ÎnmulŃim ultima ecuaŃie succesiv cu f1(x) şi f2(x) şi integrăm de la a la b. Dongarra. respectiv problema de valori proprii generalizată: a  a  A 1  = λ B  1  a 2  a 2  Generalizarea la n mai mare decât doi este imediată.PARAMETER :: N=5 60 . garbow. 44 PROGRAM VALORI_PROPRII ! ! burton s. ! argonne national laboratory !_____________________________________________________________ ! ! Se rezolva problema de valori proprii generalizata ! ! A*x=lambda*B*x ! ! A si B sunt matrici reale ! IMPLICIT NONE INTEGER.

J.D0)THEN DO J=1.Dan RacoŃi Elemente de Fortran 95 REAL(8).ALFI(N). p.N ZR(J.ALFI.ZR.K-1) ENDDO ENDIF ENDDO DO I=1.B. Boyle.Z.N ! genereaza aleator matricea B DO J=1.NE.N WRITE(*.K)=0.'(G13. C.N) ENDDO END PROGRAM VALORI_PROPRII subroutine rgg(nm.0.IERR ! codul de eroare ! ! Valorile proprii ! DO I=1.N A(I.I.matz 61 .N ! genereaza aleator matricea A DO J=1.b.IERR.K)=Z(J.BETA(I) ENDIF ENDDO 1 FORMAT(A. Dongarra.I WRITE(*.K) ZI(J.nm.1)'VP='. 44 ! DO K=1. J.J=1.I2. 1977.ALFR(I)/BETA(I).N IF(BETA(I).I.B.a.alfi.ierr.n.6)')(ZR(J.N ZR(J.Z.K-1) ZI(J.BETA. ! Matrix Eigensytem Routine EISPACK Guide Extension. J.I). Moler.ALFI(I).N ZR(J.D0)THEN WRITE(*.z.beta.D0)THEN DO J=1.K)=-ZI(J.ierr) ! integer n.IERR) WRITE(*. ! Lecture Notes in Computer Science. ! Springer-Verlag.K)=Z(J.J.D0 ENDDO ELSEIF(ALFI(K)>0.2X.6.3G13.ZI REAL(8).K.N IF(ALFI(K).I).ALFI(I)/BETA(I) ELSE WRITE(*.matz.MATZ.K+1) ENDDO ELSEIF(ALFI(K)<0.0.2X.*)'VECTORUL PROPRIU '.M.ZI(J.DIMENSION(N) :: ALFR(N).MATZ REAL(8) DRAND DO I=1.BETA(N) INTEGER I.G13.6) ! ! VECTORII PROPRII ! ! B.DIMENSION(N.K)=Z(J. New York.J)=DRAND(0) ENDDO ENDDO MATZ=1 ! se calculeaza valorile proprii si vectorii proprii CALL RGG(N.N. Garbow.alfr.B.J)=DRAND(0) ENDDO ENDDO DO I=1.N) :: A.N B(I.*)'IERR='.EQ.1)' '.K) ZI(J.A.ALFR.ALFR(I).K)= ZR(J.D0)THEN DO J=1.S.

.alfr(n).false.b(nm. argonne national laboratory this version dated august 1983... beta contains the denominators of the eigenvalues.ierr) 62 . garbow. tf = . mathematics and computer science div.0d0. contains a real general matrix.beta(n). on output alfr and alfi contain the real and imaginary parts...0.a.. on input nm must be set to the row dimension of the two-dimensional array parameters as declared in the calling program dimension statement.alfi(n). -----------------------------------------------------------------if (n .z. 0) go to 20 .tf..... which are thus given by the ratios (alfr+i*alfi)/beta. if the j-th eigenvalue is real.le.n).. the conjugate of this vector is the eigenvector for the conjugate eigenvalue. call qzhes(nm. matz is an integer variable set equal to zero if only eigenvalues are desired. n a b is the order of the matrices a and b. contains a real general matrix.n). z contains the real and imaginary parts of the eigenvectors if matz is not zero. otherwise it is set to any non-zero integer for both eigenvalues and eigenvectors.z(nm.. the j-th column of z contains its eigenvector..tf. ierr is an integer output variable set equal to an error completion code described in the documentation for qzit. nm) go to 10 ierr = 10 * n go to 50 ! ! 10 if (matz .Dan RacoŃi Elemente de Fortran 95 double precision a(nm.. respectively. the j-th and (j+1)-th columns of z contain the real and imaginary parts of its eigenvector...n.. questions and comments should be directed to burton s.a.b.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.ne.. find eigenvalues only .n.b. if the j-th eigenvalue is complex with positive imaginary part. of the numerators of the eigenvalues. complex conjugate pairs of eigenvalues appear consecutively with the eigenvalue having the positive imaginary part first. the normal completion code is zero.z) call qzit(nm.

call qzhes(nm.c write(*.*)'x ='.c1 common a1.tf.a.Dan RacoŃi Elemente de Fortran 95 call qzval(nm.' b ='.b. b=4.b.b1. InstrucŃiunea COMMON InstrucŃiunea COMMON este utilizată pentru a transmite valorile variabilelor în subprograme independent de lista de parametrii. Parametrii din instrucŃiunea COMMON trebuie să fie diferiŃi de parametrii din lista de variabile.0..a.b.n.z) if (ierr .beta.beta.*)'a ='.n..*)'a ='.intent(in) :: x real a.alfi...true.alfi.alfr.b.c.. find both eigenvalues and eigenvectors .a. .b. program common1 implicit none real a.F90' 7.beta.. 7.a. c=5..ierr) call qzval(nm.b. 0) go to 50 call qzvec(nm...n.tf.z) call qzit(nm.n..a.a.c1 ! corespondenta intre variabilele din programul principal ! si subrutina 63 .z.' b ='....a.z) 50 return end subroutine rgg ! INCLUDE 'C:\FOR\S_VALORI_PROPRII.x write(*.' c ='.1 a=3.c.b1.ne..b.b.b.b.c x=1.b. ' Programul principal' call sub1(x) call sub2 end program common1 subroutine sub1(x) implicit none real.alfr.alfr.c common a.b..0d0..c real x common a.' c ='. 20 tf = .. .alfi.tf.c write(*.. InstrucŃiunea COMMON este deosebit de puternică dar trebuie utilizată cu mare atenŃie.tf. ' Subrutina sub1' end subroutine sub1 subroutine sub2 implicit none real a1. ! se initializeaza valorile variabilelor a.1 InstrucŃiunea COMMON blank Sintaxa instrucŃiunii este: common listă_parametrii InstrucŃiunea COMMON se plasează în programul principal şi în subprogramele în care se transmit valorile parametrilor.n.z) go to 50 .

v1.n) :: mata. matb(i.v1.v3 write(*.b1.a complex z1(5).1x))')(matc(i.Dan RacoŃi Elemente de Fortran 95 ! a1 <==> a ! b1 <==> b ! c1 <==> c ! write(*.n mata(i.'(2(g13.v2.matc.dimension(n) :: v1.' b1='.j)=rand(0) enddo v1(i)=rand(0) v2(i)=rand(0) enddo call sub1 ! calculeaza matc.' c1='.v3 matc=mata+matb ! se calculeaza suma matricilor si se transmite 64 .'(3(g13.dimension(n) :: v1.6.*)'Matricea C' do i=1.j common /tablouri/mata.v3 real rand integer i.i=1.' Subrutina sub2' end subroutine sub2 7.j=1.a common /variabile_complexe/z1.zz common /variabile_întregi/k.j)=rand(0) .jj real x(3).zz Se recomandă gruparea variabilelor de acelaşi tip într-o instrucŃiune common etichetată pentru a conserva alinierea în memorie.a1.matb.v3 do i=1.6.matb.z.parameter :: n=3 real.dimension(n.parameter :: n=3 real.z2.matb.n write(*.dimension(n.n) :: mata.v3(i).1x))')(v2(i).*)'Vectorii v2 si v3' write(*.n) end program common2 subroutine sub1 implicit none integer. v2.v2.v3 common /tablouri/mata.matb.j).v2.matc.jj common /variabile_reale/x.*)'a1='.c1.z(3).v2. program common2 implicit none integer.matc real.matc real.z2(5).n do j=1.2 InstrucŃiunea COMMON etichetat Sintaxa instrucŃiunii este: common /eticheta/listă_variabile integer k(3).n) enddo write(*.

*)'constanta gazelor ='. 65 .presiunea_standard.v1) ! se calculeaza produsul dintre matrice si ! vector si se transmite rezultatul in programul ! principal prin common ! se calculeaza produsul dintre matrice si ! vector si se transmite rezultatul in programul ! principal prin common v3=matmul(matb.*)'temperatura standard='.15/ ! K data presiunea_standard /1.constanta_gazelor. ! write(*.presiunea_standard ! ! Initializarea variabilelor din common cu intructiunea data ! data constanta_gazelor /8.v1) end subroutine sub1 7.e5/ ! N/m**2 end block data constante_termodinamice 10.31451/ ! J/mol/K data temperatura_standard/298.temperatura_standard.Dan RacoŃi Elemente de Fortran 95 ! rezultatul prin common in programul principal v2=matmul(mata.' 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.presiunea_standard ! ! Valorile constantelor sunt precizate in procedura block data ! si transmise prin common.ORG). AplicaŃii Se prezintă în continuare o serie de aplicaŃii în FORTRAN utilizând algoritmi consacraŃi din bibliotecile de programe disponibile pe INTERNET (NETLIB. Sintaxa instrucŃiunii 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 ='.' J/mol/K' write(*.' K' write(*.temperatura_standard.3 InstrucŃiunea BLOCK DATA InstrucŃiunea block data se utilizează pentru a iniŃializa valorile variabilelor din common etichetat (labeled common) cu instrucŃiunea data.

o-z) parameter (limit=128) 66 .ier) implicit real(8) (a-h.appl.*)'ier='.5d0 eps=1.1 Calculul integralelor definite. ! gauss-kronrod !***author piessens.ier ! cod de eroare write(*.alfa ! parametrii definiti in programul ! principal external f ! functia care se integreaza ! ! M. Uberhuber. Kahaner Quadpack: a Subroutine Package for Automatic Integration Springer Verlag.a.o-z) g(x)=exp(alfa*x)*sin(p*x) common /parametrii/pi.abserr.epsabs. Piessens.key.leuven ! de doncker.d0) write(*.leuven ! implicit real(8) (a-h.a. div.epsrel.elise. div . traducere din limba rusa. R.appl.d0*atan(1. Ed.*)'program quadpack' alfa=1. 1983.rezult ! valoarea integralei calculata numeric write(*. Tabele de integrale nedefinite. D.b.u. formula 45. Quadpack este un pachet de programe f77 care calculează integrale definite.robert .d0 p=pi a=0.43/Q1S 100394Z program quadpack ! !***keywords automatic integrator. ! integrand examinator.k. globally adaptive.k.d0 b=0.1.u. math. p.eps.result.rezult.alfa p=pi f=g(x) end subroutine dr_dqag(f.key.o-z) common /parametrii/pi.*)'Ia='.*)'In='. Tehnica. E.b. deDoncker-Kapenga. . 129 ! primitiva(x)=exp(alfa*x)* $ (alfa*sin(p*x)-p*cos(p*x))/(alfa**2+p**2) pi=4.Dan RacoŃi Elemente de Fortran 95 10.d-8 key=2 ! ! ! ! limita inferioara a integralei definite limita superioara a integralei definite toleranta impusa 10-21 puncte gauss in formula de quadratura call dr_dqag(f.1 515. QUADPACK. Series in Computational Mathematics v. Smoleanski. general-purpose. & progr.abserr.eps.(primitiva(b)-primitiva(a)) ! analitic end program quadpack real(8) function f(x) implicit real(8) (a-h.ier) write(*. math. ! Bucuresti 1972. C. & progr.L.

acc.key.appl.epsrel*abs(i)). ! ! on return ! result .abserr.elise.21 points if key = 2. ! hopefully satisfying following claim for accuracy ! abs(i-result)le. the actual name for f needs to be ! declared e x t e r n a l in the driver program. globally adaptive.15 points if key. general-purpose.leuven !***purpose the routine calculates an approximation result to a given ! definite integral i = integral of f over (a.2. ! integrand examinator.b).work) !***begin prologue dqag !***date written 800101 (yymmdd) !***revision date 830518 (yymmdd) !***category no.u. ! 20 .epsabs.mach.a.b. ! gauss-kronrod !***author piessens. & progr.double precision ! lower limit of integration ! ! b .double precision ! approximation to the integral ! ! abserr .gt.lenw.lt. h2a1a1 !***keywords automatic integrator.double precision 67 . ! 10 .max(epsabs.b.le.double precision ! relative accuracy requested ! if epsabs. !***description ! ! computation of a definite integral ! standard fortran subroutine ! double precision version ! ! f . ! ! a .41 points if key = 4. ! 30 .u. ! 15 .ier. . ! the routine will end with ier = 6.result.double precision ! function subprogam defining the integrand ! function f(x).a.neval.0 ! and epsrel.max(50*rel. $ limit.61 points if key.iwork.epsrel.iwork.last. div .ier.double precision ! upper limit of integration ! ! epsabs ..abserr. math. ! * limit.last. & progr.neval.5.work) end ! subroutine dqag(f.key. ! ! key .epsrel.5d-28). math.lenw.51 points if key = 5.0.robert.result. div.k.Dan RacoŃi Elemente de Fortran 95 parameter (lenw=4*limit) integer iwork(limit) real(8) work(lenw) external f call dqag(f. ! 25 .integer ! key for choice of local integration rule ! a gauss-kronrod pair is used with ! 7 .epsabs.lt.31 points if key = 3.appl.leuven ! de doncker.double precision ! absolute accoracy requested ! epsrel .k.

integer ier = 0 normal and reliable termination of the routine. iwork(1). ier.le. 68 .integer dimensioning parameter for work lenw must be at least limit*4.limit*4.gt. neval. work(limit*2+1) and work(limit*3+1) are set to zero.e. which should equal or exceed abs(i-result) neval . = 2 the occurrence of roundoff error is detected. if this yield no improvement it is advised to analyze the integrand in order to determine the integration difficulaties.5d-28)) or limit.0.1.max(50*rel. work(1) is set to a and work(limit+1) to b.0 and epsrel. lenw .mach.lt. = 6 the input is invalid. if lenw.ge. because (epsabs. if possible. abserr. discontinuity within the interval) one will probably gain from splitting up the interval at this point and calling the integrator on the subranges. an appropriate special-purpose integrator should be used which is designed for handling the type of difficulty involved. the routine will end with ier = 6.lt. if limit. error messages ier = 1 maximum number of subdivisions allowed has been achieved.1 or lenw. ier dimensioning parameters limit .lt. = 3 extremely bad integrand behaviour occurs at some points of the integration interval. which prevents the requested tolerance from being achieved.lt.1. however. except when lenw is invalid.integer number of integrand evaluations .b).. last are set to zero. one can allow more subdivisions by increasing the value of limit (and taking the according dimension adjustments into account). it is assumed that the requested accuracy has not been achieved. if the position of a local difficulty can be determined (i.singularity.integer dimensioning parameter for iwork limit determines the maximum number of subintervals in the partition of the given integration interval (a. it is assumed that the requested accuracy has been achieved.Dan RacoŃi Elemente de Fortran 95 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! estimate of the modulus of the absolute error. result. the routine will end with ier = 6.0 abnormal termination of the routine the estimates for result and error are less reliable.limit*4.lt. limit.acc.

double precision ! vector of dimension at least lenw ! on return ! work(1). ! ! work arrays ! iwork . work(limit*3+iwork(k)) ! form a decreasing sequence with k = last if ! last.2. .le.n cu condiŃia iniŃială: x = x0 ' i y i ( x0 ) = y 0 Dacă soluŃiile sistemului de ecuaŃii diferenŃiale au scale diferite de timp.2 EcuaŃii diferenŃiale ordinare... New York. y1 . and k = limit+1-last otherwise ! ! work .b). work(last) contain the left end ! points of the subintervals in the partition of ! (a. atunci sistemul de ecuaŃii diferenŃiale este stiff. work(limit+last) contain the ! right end points. p.. ! work(limit*2+1). the first k ! elements of which contain pointers to the error ! estimates over the subintervals. . Sistemele de ecuaŃii diferenŃiale nonstiff se integrează cu metode Runge Kutta explicite.. work(limit*3+last) contain ! the error estimates. Hairer. which ! determines the number of significant elements ! actually in the work arrays. work(limit*2+last) contain ! the integral approximations over the subintervals. last equals the number of subintervals ! produced in the subdiviosion process. ! work(limit+1). . such that ! work(limit*3+iwork(1)). Solving Ordinary Differential Equations I.... 1977. Norsett. ! !***references (none) !***routines called dqage.for' 10.integer ! on return. Sistemele de ecuaŃii diferenŃiale stiff se integrează cu metode Runge Kutta implicite. Wanner.Dan RacoŃi Elemente de Fortran 95 ! last .. EcuaŃiile sunt: 69 . P. . S..xerror !***end prologue dqag include 'c:\for\s_quadpack. Springer... .(limit/2+2).. y n ) i=1..integer ! vector of dimension at least limit. Vom ilustra metodele Runge Kutta explicite cu o problema celor trei corpuri cu restricŃii. E.….. Nonstiff Problems. 127-128.. Problema Cauchy Se consideră sistemul de n ecuaŃii diferenŃiale ordinare nonstiff: y ( x) = f ( x. Se consideră două corpuri de masă 1-µ şi µ în mişcare circulară de rotaŃie în plan şi un al treilea corp de masă neglijabilă care se mişcă în acelaşi plan... respectiv unele soluŃii au o variaŃie mult mai rapidă decât altele.. ! work(limit*3+1). S.

1.5 1 0.5 µ = 0. Reprezentarea grafică a soluŃiei este prezentată în Figura 10.0D0 y4=-2.5 'dopri5.5 2 D2 = (( y1 − µ ' ) 2 + y 2 )1.012277471 µ' =1− µ Sistemul de două ecuaŃii diferenŃiale de ordinul doi se transformă într-un sistem de patru ecuaŃii diferenŃiale de ordinul întâi care se integrează cu metoda DOPRI5: y1' = y 3 ' y2 = y4 y1'' = y1 + 2 y 4 − µ ' ' y 2' = y 2 − 2 y 3 − µ ' y1 + µ y − µ' −µ 1 D1 D2 y2 y −µ 2 D1 D2 CondiŃia iniŃială la x=0 este: y1=0.5 -1 -1. Sistemul de patru ecuaŃii diferenŃiale este descris în subrutina FAREN.00158510637908252240537862224 Sistemul de integrează până la: xend=17. Reprezentarea soluŃiei sistemului de ecuaŃii diferenŃiale în planul fazelor C ---------------------------------------------------------C NUMERICAL SOLUTION OF A SYSTEM OF FIRST 0RDER 70 . Orbita Arensdorf 1.2.5 y2 0 -0.0652165601579625588917206249 Sistemul neliniar de patru ecuaŃii diferenŃiale ordinare are soluŃii periodice.994 y2=0.5 -1.0D0 y3=0.Dan RacoŃi Elemente de Fortran 95 ' y1'' = y1 + 2 y 2 − µ ' y1 + µ y − µ' −µ 1 D1 D2 y2 y −µ 2 D1 D2 ' y 2' = y 2 − 2 y1' − µ ' 2 D1 = (( y1 + µ ) 2 + y 2 )1.2.txt' u 2:3 -1 -0.1.5 1 Figura 10. SoluŃia sistemului de ecuaŃii diferenŃiale este scrisă în subrutina SOLOUT.5 y1 0 0.

IOUT. DE MATHEMATIQUES CH-1211 GENEVE 24.LIWORK=NRDENS+21) DIMENSION Y(NDGL).I4. WANNER UNIVERSITE DE GENEVE.20 IWORK(I)=0 10 WORK(I)=0.20) 91 FORMAT(' tol='. & SOLOUT.0D-7 ATOL=RTOL C --. & RTOL.Wanner@math.DRIVER FOR DOPRI5 ON ARENSTORF ORBIT C * * * * * * * * * * * * * * * * * * * * * * * * * IMPLICIT REAL*8 (A-H.' rejct='.WORK(LWORK).OUTPUT ROUTINE (AND DENSE OUTPUT) IS USED DURING INTEGRATION IOUT=2 C --.DIMENSION OF THE SYSTEM OPEN(1.unige.SOLOUT C --.unige.IWORK(LIWORK).' fcn='.(IWORK(J).D8. SWITZERLAND E-MAIL: Ernst. 2ND EDITION.012277471D0 RPAR(2)=1.Y(2) 99 FORMAT(1X. 1996 C * * * * * * * * * * * * * * * * * * * * * * * * * C --. SPRINGER-VERLAG (1993) VERSION OF APRIL 25.RPAR(2) EXTERNAL FAREN.0D0 Y(4)=-2.REQUIRED (RELATIVE AND ABSOLUTE) TOLERANCE ITOL=0 RTOL=1.X.I4.' step='. HAIRER.ATOL.P. SOLVING ORDINARY DIFFERENTIAL EQUATIONS I.Dan RacoŃi Elemente de Fortran 95 C C C C C C C C C C C C C C C C C C ORDINARY DIFFERENTIAL EQUATIONS Y'=F(X. AUTHORS: E. THIS IS AN EXPLICIT RUNGE-KUTTA METHOD OF ORDER (4)5 DUE TO DORMAND & PRINCE (WITH STEPSIZE CONTROL AND DENSE OUTPUT). WANNER.PRINT FINAL SOLUTION WRITE (6. NORSETT AND G.Y.'X = XEND Y ='. & ' accpt='.IPAR.2E18.994D0 Y(2)=0.FAREN.PRINT STATISTICS WRITE (6.RPAR.TXT') N=NDGL C --. NONSTIFF PROBLEMS.0652165601579625588917206249D0 C --.0D0 Y(3)=0.LIWORK. DEPT. S.ch Gerhard.10) C --.XEND.91) RTOL.IWORK.D0 C --.ch THIS CODE IS DESCRIBED IN: E.0D0 Y(1)=0.Hairer@math.DEFAULT VALUES FOR PARAMETERS DO 10 I=1.2.INITIAL VALUES AND ENDPOINT OF INTEGRATION RPAR(1)=0. & WORK.99) Y(1).LWORK.00158510637908252240537862224D0 XEND=17.I3) 71 .FILE='C:\FOR\DOPRI5.DENSE OUTPUT IS USED FOR THE TWO POSITION COORDINATES 1 AND 2 IWORK(5)=NRDENS C --.Y).ITOL.NRDENS=4) PARAMETER (LWORK=8*NDGL+5*NRDENS+21. HAIRER AND G.IDID) C --.I5.D0-RPAR(1) X=0. SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS.CALL OF THE SUBROUTINE DOPRI5 CALL DOPRI5(N.J=17.O-Z) PARAMETER (NDGL=4.

PRINTS SOLUTION AT EQUIDISTANT OUTPUT-POINTS BY USING "CONTD5" IMPLICIT REAL*8 (A-H.for' 10.XOUT.2] .2.2E18.Y.ND) XOUT=XOUT+DXOUT GOTO 10 END IF END IF 99 FORMAT(1X.ARENSTORF ORBIT IMPLICIT REAL*8 (A-H.ICOMP.XOUT.XOUT.N.CON.ND).99) XOUT.IPAR) C --.XOUT.RPAR.XOUT.ICOMP.6.CONTD5(1.CONTD5(1.NR-1 WRITE (1.IPAR.98) X.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.X.3 EcuaŃia Burgers omogenă Se consideră ecuaŃia: ∂u ∂f (u ) + =0 ∂t ∂x cu condiŃia iniŃială.ND).CON.'X ='.ND).DXOUT DXOUT=0.' Y ='.IRTRN) C --.CON.98) XOUT.CON.Y(1).RPAR(2) COMMON /INTERN/XOUT.ICOMP.F. # CONTD5(3.CON.Y(2).EQ.CON(5*ND).X.XOUT) THEN WRITE (6.ND).Y(3).RPAR.ICOMP. x ∈ [0.Y.ICOMP.99) X. & CONTD5(2.Y(2). & CONTD5(2. problema Cauchy: la t=0 u ( x) = u 0 ( x) = sin(πx) .1D0 IF (NR.10.' NSTEP ='.F(N). Pentru ecuaŃia lui Burgers: 72 .ICOMP.1) THEN WRITE (6.XOLD.O-Z) DIMENSION Y(N).ICOMP(ND). # CONTD5(4.GE.XOUT.ND).CON.I4) 98 FORMAT(5(G13.1X)) RETURN END C SUBROUTINE FAREN(N.O-Z) DIMENSION Y(N).ICOMP.NR-1 WRITE (1.Dan RacoŃi Elemente de Fortran 95 STOP END C C SUBROUTINE SOLOUT (NR.CON.Y(4) XOUT=X+DXOUT ELSE 10 CONTINUE IF (X.F6.Y(1).ND.

i=1.…. v) = [ ] Ecuatia Burgers omogena 1 'uo3' u 1:2 'ut3' u 1:2 0.9 u max Trecerea la nivelul următor de timp se face cu ecuaŃia: ∆t u it + ∆t = u it + h(u it . uo3 condiŃia iniŃială ut3 solutia la t=1 program roe ! ! H. NASA Technical Memorandum 101088.….1.n şi se calculează pasul de timp (CFL): ∆x ∆t = 0. v) = 0.5[ f (u ) + f (v) − a (u. v)(u − v) u+v 2 Se consideră funcŃia flux numeric (Yee): h(u .1) 0 -0. NASA Technical Memorandum 101088. A Class of High-Resolution Explicit and Implicit Shock Capturing Method.….C.1 SoluŃia ecuaŃiei Burgers omogene la t=1. Yee. SoluŃia ecuaŃiei la momentul de timp t=1 este prezentată în Figura 10.3.1. u it+1 ) − h(u it−1 . v) (v − u )] H.3. Yee.C. u it ) .n+1. A Class of High-Resolution Explicit and Implicit ! Shock Capturing Method.5 1 x 1.Dan RacoŃi Elemente de Fortran 95 f (u ) = u2 2 f (u ) − f (v) = a (u .5 2 Figura 10.n ∆x In nodurile i=0 şi i=n+1 se face o extrapolare a soluŃiei (condiŃie la limită numerică). La momentul de timp t se determină viteza maximă în interval: u max = max(u it ) i=1.2. a(u .5 -1 0 0. February 1989 Se consideră grila echidistantă cu pasul ∆x pe axa x cu nodurile i=0.5 u(x. ! February 1989 ! ! ! Ecuatia Burgers omogena ! 73 .2.

umax.'(1x.4)')x(i).parameter :: m=101 real(8) x(m).dx real h.m umax=max(abs(u(i)).d0 ! intervalul de timp xs=0.d0 ! domeniul de integrare dx=(xd-xs)/(m-1) ! pasul de discretizare pe axa x do i=1.v) ! functia flux numeric implicit none real(8).d0 .xd open(1.q. xd=2.umax) enddo ! ! Pasul de timp ! dt=0.m write(2.9d0*dx/umax ! Courant Friederics Levy CFL ! ! viteza la t1=t+dt ==> v ! do i=1.file='c:\for\uo3') open(2.xs.4f11.Dan RacoŃi Elemente de Fortran 95 ! ! ! 0<x<2 uo(x)=sin(pi*x) 0<t<1 implicit none integer.m ! actualizarea vitezelor u(i)=v(i) enddo enddo ! ! Solutia la t=tf ! do i=1.v(0:m+1) integer i real uzero.d0 .file='c:\for\ut3') t0=0.t.m v(i)=u(i)-dt/dx*(h(u(i).v real(8) f.a 74 .u(i))) enddo t=t+dt do i=1.u(i+1))-h(u(i-1).d0 ! se determina viteza maxima pe tot intervalul do i=1.t0.m x(i)=xs+(i-1)*dx ! grila discreta u(i)=uzero(x(i)) ! viteza initiala write(1.4)')x(i).u(i) enddo end program roe real(8) function h(u. tf=1.'(1x.u(i) enddo t=t0 ! ! Iteratii in timp si spatiu ! do while(t<=tf) u(0) =u(1) u(m+1)=u(m) ! extrapolare conditii la limita umax=0.u(0:m+1).dt.2f11.tf.intent(in) :: u.

2. Se definesc paşi de discretizare: 2a ∆x = nx − 1 2b ny −1 şi grila de discretizare: xi = −a + (i − 1)∆x i=1.2.nx yi = −b + ( j − 1)∆y j=1. j +1 + = −2 ∆x 2 ∆y 2 Se defineşte sistemul de ecuaŃii algebrice lineare: ∆x 2 f i .….v a=0.ny-1 ∆y = 75 .d0) uzero=sin(pi*x) end function uzero 10.4 EcuaŃia Poisson Se consideră ecuaŃia cu derivate parŃiale: 2 ∂ u ∂ 2u + = −2 ∂x 2 ∂y 2 în domeniul dreptunghiular: − a < x < +a − b < x < +b cu condiŃia la limite u=0 pe frontieră.d0*atan(1. j +1 ) 2 + 2∆x 2 = 0 ∆y i=2.ny şi valorile funcŃiei în nodurile reŃelei: u i . j − 2u i .…. j + u i .2.Dan RacoŃi Elemente de Fortran 95 f(q)=0. j + (u i . j + u i +1.2.5d0*q*q h=0.v) ! viteza de propagare la interfata implicit none real(8).intent(in) :: x real(8) pi pi=4.5d0*(f(u)+f(v)-abs(a(u. Fie nx numărul de puncte ale grilei de discretizare pe axa x.v))*(v-u)) end function h real(8) function a(u.…. j + u i +1.ny. j − 2u i . j −1 − 2u i .5d0*(u+v) end real(8) function uzero(x) ! conditia initiala implicit none real(8). j = u ( xi . j u i . j + u i . j −1 − 2u i .….….nx j=1. ny numărul de puncte pe axa y.….intent(in) :: u. j=2. y j ) i=1. Derivatele parŃiale sunt discretizate cu formule de derivare numerică cu diferenŃe centrale: u i −1.nx-1. j = u i −1.

dimension(n) :: ip ! vectorul permutarilor de linii (Gauss) real(8). Sistemul algebric linear de nx*ny ecuaŃii se rezolvă cu metoda Newton.parameter :: ny=41 ! numarul de puncte de discretizare pe axa y integer.15 u 0.xs ! work space real(8) :: pi=3.2 0. o iteraŃie.14159265358979d0 end module tablouri program ps3 use tablouri ! ! ! ! ! ! ! ! ! ! Ecuatia lui Poisson in dreptunghi Torsiunea unei bare prismatice.05 module tablouri !-----------------------------------------------------+ | ! Se rezolva ecuatia Poisson.dimension(ny) :: y ! ordonate real(8). traducere din limba rusa.dimension(nx) :: x ! abscise real(8).dimension(n) :: z ! vectorul necunoscutelor real(8).5 1 Figura 10. SoluŃia numerică şi soluŃia analitică pentru x=-0. Bucuresti 1954. u=0 pe contur Kantorovici si Krilov. -b<y<b .dimension(n) :: f ! vectorul functiilor real(8).1 0. ! torsiunea unei bare prismatice: nabla(u)=-2 | !-----------------------------------------------------+ implicit none integer. nabla(u)=-2 -a<x<a .fm.5 0 y 0.4. 76 .parameter :: nx=21 ! numarul de puncte de discretizare pe axa x integer.bb ! work space integer. Torsiunea unei bare dreptunghilare 0.5d0 ! -a < x < +a real(8) :: b=+1.05 0 -1 -0. Metode aproximative ale analizei superioare Editura Academiei Romane.dimension(n.0d0 ! -b < y < +b real(8) :: hx ! pasul de discretizare pe axa x real(8) :: hy ! pasul de discretizare pe axa y real(8). Jacobianul se calculează numeric cu formule de derivare cu diferenŃe centrale.Dan RacoŃi Elemente de Fortran 95 Sistemul de ecuaŃii se completează cu ecuaŃii pe frontieră (condiŃiile la limite).dimension(n) :: fp.25 0.dimension(n) :: dx.n):: df ! Jacobianul sistemului de ecuatii real(8).parameter :: n=nx*ny ! numarul de necunoscute real(8) :: a=+0.

*)' p.. x(i)=-a+(i-1)*hx . Academiei.4.*) end program ps3 eroare' 77 .n.n xs(j)=z(j)-pas call sist(xs.D0/512.file='c:\for\ps3.uex.*)'program ps3' write(1.) x(j)+h f( .ny uex=ue(x(i)..f) ! ! ! Jacobian F numeric xs=z pas=1.' write(1..txt') write(1.5)')x(i)..bb.df. 392 u(x.y) serii duble. functia ue(x.j)=(fp-fm)/(pas+pas) xs(j)=z(j) enddo ! ! ! enddo enddo ! abscise ! ordonate ! ! ! ! ! ! x(j)-h f( ..0)stop 'matrice singulara' bb=-f call sol(n.ip) ! Retrosubstitutie z=z+bb ! un pas Newton write(1.x(j)+h.*)'Solutia analitica (serii duble) Kantorovici si Krilov.j ier pas ue uex zc ! ! ! ! ! cod de eroare Gauss /=0 Jacobian singular pas de derivare numerica calculeaza solutia analitica solutia analitica solutia numerica open(1.ier) ! Gauss LU if(ier. 394' hx=2.' write(1.x(j)-h. traducere din limba rusa.zc..) coloana j din Jacobian restaurare x(j) [J]{dx}=-{f} Newton pentru {f}={0} call dec(n.*)'nabla(u)=-2' write(1. zc=z(i+(j-1)*nx) write(1.fp) df(:.d0*a/(nx-1) ! pasul de discretizare pe axa x hy=2.n.*)'Solutia problemei Poisson' write(1. z=0..fm) xs (j)=z(j)+pas call sist(xs.ne. Bucuresti 1954..*)'Ed.3f12...y) implicit none integer integer real(8) real(8) real(8) real(8) i.df..d0 ! Aproximatia initiala call sist(z. do j=1.2x.' write(1.'(2f11..*)' x y numeric analitic i=nx/2 do j=1. y(j)=-b+(j-1)*hy .ny .zc-uex enddo write(1.nx .Dan RacoŃi Elemente de Fortran 95 ! ! ! ! vol 2.D0 ! pas derivare numerica diferente centrale do j=1.y(j)) .d0*b/(ny-1) ! pasul de discretizare pe axa y do i=1.ip. p.y(j)..*)'"Metode aproximative ale analizei superioare".

yy) use tablouri implicit none real(8).d0/a)*cos(nn*pi*yy/2.Dan RacoŃi Elemente de Fortran 95 real(8) function ue(xx.d0/b) enddo enddo ue=ss*a**2*b**2*128/pi**4 end subroutine sist(zz.c1 integer mm.yy real(8) ss.41.intent(in ) :: zz(n) ! vectorul necunoscutelor real(8).2 do nn=1.intent(out) :: gg(n) ! vectorul functiilor integer i.gg) use tablouri implicit none real(8). Retrosubstitutie 10.dimension(n).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.2 c1=(-1.d0*hx**2 enddo enddo end include 'c:\for\decsol.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.s2 do j=1.41.j real(8) s1.d0)**(0.d0*zz(i +(j-1)*nx)+zz(i+1+(j-1)*nx)) gg(i+(j-1)*nx)=s1+s2*(hx/hy)**2+2.dimension(n).5 EcuaŃia de potenŃial pe cerc Se consideră ecuaŃia cu derivate parŃiale: 2  v  ∂ 2ϕ  vθ  ∂ 2ϕ 2v v ∂ 2ϕ  vθ2  ∂ϕ 1 −  2 + 1 − 2  2 2 − r 2 θ + 1 +  =0    a  r ∂θ ra ∂r∂θ  a 2  r∂θ  a  ∂r     ( χ − 1) 2 a2 = (Vmax − (vr2 + vθ2 )) 2 Se determină soluŃiile periodice ale ecuaŃiei de potenŃial cu condiŃiile la limite: 2 r 2 78 .nx-1 ! discretizare cu diferenta centrale do j=2.f90' ! Gauss descompunere LU .intent(in) :: xx. 394 ss=0.ny gg(nx+(j-1)*nx)=zz(nx+(j-1)*nx) ! sus gg(1 +(j-1)*nx)=zz(1 +(j-1)*nx) ! jos enddo (boundary) (boundary) do i=2.5d0*(mm+nn)-1)/(mm*nn*(mm**2*b**2+nn**2*a**2)) ss=ss+c1*cos(mm*pi*xx/2.nn ! ! ! Solutia analitica (serii duble) Kantorovici si Krilov p.d0 do mm=1.

Se obŃine un sistem algebric neliniar care se rezolvă cu metoda Newton. MODULE REZERVARE_MEMORIE PARAMETER (NR=101.5. Mach=0.5 -2 -2.D0 REAL(8) :: PI=3. Rezultatele sunt prezentate în figura 10.5.-1:NT+2) REAL(8) ZZ(NEC). r=r1 : v r = Ecuatia de potential pe cerc.5 -1 -1.D0 REAL(8) :: R2=11.1.NEC=MM) REAL(8) DR.Dan RacoŃi Elemente de Fortran 95 ∂ϕ =0 ∂r r=r2 : ϕ = V∞ cos θ Derivatele parŃiale se discretizează cu formule cu diferenŃe centrale. Jacobianul sistemului este calculat numeric. SoluŃia numerică (puncte) şi soluŃia obŃinută prin dezvoltare în serie Mach=0.4D0 REAL(8) :: RG=287.5*v_inf*v_inf ! ! a**2=hi*r*t ! IMPLICIT REAL*8 (A-H.5 2 1. SoluŃia numerică se compară cu soluŃia obŃinută prin dezvoltare în serie.4.FM(NEC).5 0 1 2 3 Teta 4 5 6 7 Figura 10.DFDZ(NEC.MM=NR*NT.XS(NEC) INTEGER IP(NEC) REAL(8) :: TINF=300. AproximaŃia iniŃială este soluŃia ecuaŃiei Laplace pe cerc în curent paralel.VMAX REAL(8) PT(NR.5 0 -0.DT.D0 REAL(8) :: HI=1.NT=37.VINF.4 2.TETA(NT).5 1 V_teta 0.FCT(NEC).5*v*v=cp*t_inf+0.NEC) REAL(8) FP(NEC).D0 REAL(8) :: MACH=0.4D0 REAL(8) :: R1=1.O-Z) 79 .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.1.

FCT) ERM=MAXVAL(ABS(FCT)) ! norma erorii WRITE(*.NR RR=R1+(I-1)*DR DO J=1.NT-1) PT(I. ENDDO K=0 DO I=1.NT K=K+1 ZZ(K)=VINF/VMAX*(RR+1.2) PT(I.D0) DO J=1.'(1X.Dan RacoŃi Elemente de Fortran 95 OPEN(1.IP) ! retrosubstitutie ZZ=ZZ+FCT ! corectii NEWTON CALL SIST(ZZ.nt-2) PT(I.6)')'It='.A.DFDZ.NT K=K+1 .0 )=PT(I.D0*PI/(NT-1.NR PT(I.FILE='C:\FOR\p2.A.DFDZ.0.00001D0)EXIT ! convergenta ENDDO K=0 DO I=1.IER) ! descompunere LU (Gauss) IF(IER.D0*SIN(TE)-0.D0/RR)*COS(TETA(J)) ENDDO ENDDO CALL SIST(ZZ.NEC.D0/512.D0 ! Pasa derivare numerica DO NEWTON=1.LT.' Er='.0)STOP 'JACOBIAN SINGULAR' FCT=-FCT CALL SOL(NEC.NT .J)=ZZ(K)*(VMAX/VINF) ENDDO ENDDO DO I=1.D0*SIN(TE)+MACH**2*(2. PT(I.1 ! Solutia pe cerc RR=R1+(I-1)*DR ! Raza DO J=1.D0/3.FCT.I3.NT+1)=PT(I.FM) DFDZ(:.J+1)-PT(I.5D0*SIN(3.D0) .NT+2)=PT(I. TETA(J)=(J-1)*DT .NEWTON.D0*CP*TINF+VINF**2) DR=(R2-R1)/(NR-1. DT=2.IP.FP) XS(J)=ZZ(J)-H CALL SIST(XS.F13.NEC.D0*TE)) & 80 .D0) AINF=SQRT(HI*RG*TINF) VINF=AINF*MACH VMAX=SQRT(2.-1 )=PT(I.J-1))/(DT+DT)/RR ! Derivata potentialului ! Solutia obtinuta prin dezvoltare in serie VTE=2.10 ! iteratii Newton XS=ZZ DO J=1.J)=(FP-FM)/(H+H) ! diferente centrale coloana j XS(J)=ZZ(J) ENDDO CALL DEC(NEC.txt') CP=HI*RG/(HI-1.3) ENDDO ! periodicitate DO I=1.NT TE=TETA(J) VT=(PT(I.FCT) H=1.ERM IF(ERM.NR DO J=1.NEC ! calculul numeric al Jacobianului XS(J)=ZZ(J)+H CALL SIST(XS.NE.

NT K=K+1 PT(I.D0)*(23.NR-1 DO J=1.D0*PT(I.D0*SIN(5.J)-PT(3.D0*SIN(TE)-11.VT-VTE IF(I.D0/8.VTE.DIMENSION(NEC).6F12.F) USE REZERVARE_MEMORIE IMPLICIT REAL*8 (A-H.VT.VTE.0 )=PT(I.VT-VTE ENDIF ENDDO WRITE(1.J+2))*DT1/12.D0 D2PDR2=(PT(I+1.J+1)-PT(I. vr=0 K=K+1 F(K)=-3.D0*PT(I.D0*PT(I.D0 *SIN(5.J) ! R=R1 ENDDO DO J=1.O-Z) REAL(8).NT RR=R1+(I-1)*DR VR=(PT(I+1.NR ! Periodicitate PT(I.'(1X.D0/DR**2 DO I=2.NR DO J=1.J))*DC D2PDRDT=(PT(I+1.NT ! Conditia la limita pe cerc .NT+1)=PT(I.J)-2.J-2)+ & +16.J-1))/(DT+DT)/RR AP=(HI-1.J))/(DR+DR) VT=(PT(I.D0/40.J-1) & -30.& PT(I+1.NT-2) PT(I.J)=ZZL(K) ENDDO ENDDO DO I=1.D0*PT(1.D0*PT(2.D0*TE))) VTE=-VTE WRITE(*.D0*TE)+ (HI-1.D0*PT(I.D0*PT(I.NT+2)=PT(I.D0/DR/DT & & & & 81 .J+1))/4.J)-(VINF/VMAX)*R2*COS(TETA(J)) ENDDO DT1=1.2) PT(I.*) ENDDO END PROGRAM POTENTIAL_CERC_NELINIAR SUBROUTINE SIST(ZZL.EQ.D0*TE) + 3.J-1)-PT(I-1.INTENT(OUT) :: F K=0 DO I=1.4)')TE.D0/24.1)THEN WRITE(1.NT-1) PT(I.1.D0*SIN(3.DIMENSION(NEC).J)+4.INTENT(IN ) :: ZZL REAL(8).J)+PT(I-1.1.D0*SIN(3.D0)/2.J+1) & .6F12.D0/8.D0*SIN(TE) -25.-1 )=PT(I.4)')TE.3) ENDDO K=0 DO J=1.J-1).D0*PT(I.J)-PT(I-1.D0*(1.'(1X.Dan RacoŃi Elemente de Fortran 95 +MACH**4*( 37.VT.J+1)+PT(I-1.D0/DT**2 DC=1.NT ! Conditia la limita R=R2 "Infinit" K=K+1 F(K)=PT(NR.D0/40.D0/120.D0-VR**2-VT**2) D2PDT2=(.D0*TE)+ 1.J ) & +16.

D0-VT**2/AP C3=-2.J))/(DR+DR) K=K+1 C1=1. ! User Guide for MINPACK-1 ! Argonne National Laboratory.*)'number of calls to FCN has reached or exceeded 200*(N+1)' case(3) write(*.*)'improper input parameters' case(1) write(*.D0-VR**2/AP C2=1.info external sist ! sistemul de ecuatii neliniare write(*.d0 x(2)=0.*)' approximate solution X is possible' case(4) 82 .info select case(info) case(0) write(*.5)')' the solution is at most TOL='.F90' 10.D0*VR*VT/AP C4=1. Illinois.*)' TOL is too small. No further improvement in the' write(*.*)'info='. Burton Garbow and Kenneth Hillstrom.*)'algorithm estimates that the relative error between X and' write(*.x. ! ! Modified by: ! ! John Burkardt ! implicit none integer.'(a.n.6 Rezolvarea sistemelor de ecuaŃii algebrice neliniare program powell_hybrid ! ! Rezolva sisteme algebrice neliniare cu algoritmul Powell hibrid ! Sistemul algebric este descris in subrutina sist ! ! Reference: ! ! Jorge More.info) write(*./)')'Program powell_hybrid' tol=1.tol.f.Dan RacoŃi Elemente de Fortran 95 DPDR=(PT(I+1.tol case(2) write(*.'(a. ! Argonne.J)-PT(I-1. 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.g13.d-6 x(1)=0.d0 ! precizia impusa ! aproximatia initiala x(1) ! aproximatia initiala x(2) call hybrd1(sist.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.

7.i.a. ! ! Discussion: ! ! HYBRD1 finds a zero of a system of N nonlinear functions in N variables ! by a modification of the Powell hybrid method.')='. Burton Garbow and Kenneth Hillstrom.f90' :: :: :: :: n x f iflag 83 .f(i).'f('.a. ! ! Reference: ! ! Jorge More.dimension(n) real(8).intent(in ) real(8). Illinois.6)') & ('x('. ! Argonne.'(/.f13. This is done by using the ! more general nonlinear equation solver HYBRD.intent(inout) f(1)=x(1)**2+x(2)**2-1.x(i).i.Dan RacoŃi Elemente de Fortran 95 write(*.*)'the iteration is not making good progress' end select write(*.a.g14.i=1.intent(in ).'(a.a.intent(out). The user must provide a ! subroutine which calculates the functions. The jacobian is then ! calculated by a forward-difference approximation.f.i1.n) end program powell_hybrid subroutine sist(n.iflag) implicit none integer. ! User Guide for MINPACK-1 ! Argonne National Laboratory.i1.x.dimension(n) integer.')='.d0 f(2)=x(1)-x(2) end subroutine sist !*****************************************************************************8 0 ! !! HYBRD1 seeks a zero of N nonlinear equations in N variables. ! ! Modified by: ! ! John Burkardt ! include 'c:\for\minpack./)')'Solutia' write(*.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->