Está en la página 1de 29

Apuntes de Fortran 90

V. Dom nguez y F.J. Sayas


Junio de 2001

1.

Introducci on

Fortran 90 es una actualizaci on de Fortran 77 que moderniza este lenguaje, incorporando algunas de las caracter sticas comunes de los lenguajes m as modernos (C, C++, Pascal,etc.). Con el nuevo lenguaje se persiguen los siguientes objetivos: Modernizar la sintaxis. Incluir aspectos de programaci on modular, recursividad,. . . Mejorar la habilidad para trabajar con las matem aticas. Incorporaci on de estructuras de datos y de punteros. Dentro de los posible se mantiene todav a v alida las instrucciones y sintaxis del Fortran 77. As peque nas modicaciones permiten pasar un c odigo en Fortran 77 a un c odigo en Fortran 90. Sin embargo con ello perdemos las principales ventajas que incorpora el nuevo lenguaje. Cap tulo aparte merece el caso del manejo de tablas. En nuestro caso nos concentraremos en tablas unidimensionales y bidimensionales que se identican con vectores y matrices. La nueva losof a de Fortran 90 consiste en el manejo de estas estructuras globalmente en lugar de elemento a elemento. Por u ltimo conviene se nalar que existe una actualizaci on posterior que se conoce como Fortran 95. Sin embargo los cambios que incorpora son de una magnitud sensiblemente inferior a los desarrollados en la versi on anterior Primeras ideas sobre la sintaxis. se emplea desde la columna inicial, a diferencia del Fortran 77 que dejaba las 6 primeras libres para etiquetas y control de bucles. No se distingue entre may usculas y min usculas. Hay compiladores que distinguen para los nombres de variables. ! indica una l nea de comentario. Todo lo que sigue no se compila. & se emplea para cortar una l nea. Se escribe al nal de la l nea cortada y al principio de la siguiente. Estructura del programa. program nombre programa declaraci on de variables cuerpo del programa end program nombre programa Ejemplo ! mi primer programa en FORTRAN 90 program primero implicit none real :: x,y ! arranque del programa ! declaraci on variables

! programa print*,dame dos numeros reales read*,x,y print*,su suma es,x+y print*,Esta es una linea partida en dos,& & (x+(2*y)*x-y*y)/3.5 end program primero ! final

2.

Declaraci on de variables y asignaci on


Tipos de constantes y variables: enteras (integer) de coma otante (real) a simple y doble precisi on complejas (complex) a simple y doble precisi on car acter (character) l ogicas (logical): u nicamente pueden adoptar los valores .TRUE. La orden implicit none cancela un convenio impl cito de declaraci on de variables y obliga a declarar todas las variables Por defecto real y complex son de precisi on simple, pero depende del compilador. Ejemplo .FALSE

program asignaciones implicit none integer :: i,j real (kind=4) :: x,y ! declara variables de precisi on simple real (kind=8) :: z,t ! precisi on doble complex :: u ! complex(kind=4) :: u character (len=4) :: palabra ! (len=4) indica que tiene 4 caracteres logical :: test x=3.23e-4 ! asignacion de 3,23 104 y=-2.312e2 x=3.4 y=4 ! esta asignaci on incluye una conversi on de entero a real z=3.23e-4 8 ! 8 indica que es doble precisi on t=2. 8 z=(3.e-1,2.) ! =0,3 + 2 palabra=casa ! las comillas identifican las constantes car acter palabra="Juan" ! tambi en se usan las dobles comillas test=.TRUE. end program asignaciones

Inicializaci on de variables. Se pueden dar valores de arranque a las variables al declararlas parameter bloque la posibilidad de reasignar la variable en el transcurso del programa En las asignaciones de inicializaci on no puede haber operaciones aritm eticas. Es aconsejable que no haya conversiones autom aticas (entero a real, etc).

programa asignaciones implicit none real :: x=4.,t,z=3.e-2 real (kind=8) :: u=6.e2 8 complex :: a=(2.,3.) character (4) :: palabra=casa real, parameter :: pi=3.141592 ...

! asigna valores de arranque a x y z

! (4) abrevia (len=4)

3.

Lectura y escritura en pantalla


print*, read*, Ejemplo

Para escribir en pantalla y leer de teclado, en formato libre, se usan respectivamente

... x=3.5 print*,x es ,x print*,da un valor a y read*,y print*,valores de x e y,x,y ...

4.

Operaciones num ericas


+ * / **

Binarias b asicas. Suma, resta, producto, divisi on y exponenciaci on.

Tabla de tipos de datos y resultado. entero real doble entero entero real doble real real real real doble doble real doble

Funciones matem aticas b asicas. El argumento siempre se escribe entre par entesis. abs (valor absoluto o m odulo) sqrt (ra z cuadrada) exp (exponencial) log (logaritmo neperiano) log10 sin cos tan

asin acos atan sinh cosh tanh Otras. mod(i,j) da el resto de la divisi on entera int(x) da la parte entera de x floor(x) da el mayor entero menor o igual que x ceiling(x) da el menor entero mayor o igual que x max(x1 ,...,xn ) da el mayor de dos o varios argumentos min(x1 ,...,xn ) da el menor de dos o varios argumentos Ejemplo program partesEnteras real :: x=2.3, y=-4.3, z=7.2 integer :: i=3, j=7, k=-5 print*, floor(x), ceiling(x), int(x) print*, floor(y), ceiling(y), int(y) print*, max(x,y,z), min(i,j,k) end program partesEnteras

! preasignadas

El programa precedente devolver a en pantalla: 2 3 -5 -4 7.2 -5 2 -4

5.

Estructuras de decisi on

Operadores de comparaci on. N otese la diferencia entre el igual de comparaci on (==) y el de asignaci on. El s mbolo /= indica =. > < <= >= == /=

Operadores l ogicos. Son cuatro: y, o, o exclusivo, negaci on. .AND. Simple de sentencia u nica if (expresi on l ogica) sentencia Simple de sentencia m ultiple if (expresi on l ogica) then sentencia primera sentencia segunda ... end if If-else if (...) then ... else ... end if Decisi on m ultiple if (...) then ... else if (...) then ... else if (...) then ... else ! puede no estar ... end if Puede haber estructuras anidadas. Ejemplo program decisiones implicit none real :: x,y print*,escribe x e y read*,x,y if (y<0) print*,y es estrictamente negativo if (x==0) then print*,x es nulo else if (x>0) then print*,x es positivo else print*,x es negativo end if if ((x>0 .AND. y>0).OR.(x<0 .AND. y<0)) then print*,x*y es positivo 6 .OR. .XOR. .NOT.

else print*,x*y es negativo o nulo end if end program decisiones

La orden select case. La sintaxis es select case (criterio) case(expr1 ) ... case(expr2 ) ... ... case default ... end select ! criterio devuelve un valor num erico ! selecciona si se cumple el caso ! si se cumple este caso y no el precedente

! caso por defecto; puede no estar

Ejemplo program casos implicit none integer :: op real :: x,y print*,elija una opcion read*,op select case(op) case(1) print*,op=1 read*,x case(2) print*,op=2 read*,x,y case(3:5) print*,Valor de op entre 3 y 5 case(6:) print*,Valor de op >=6 case(:-1) print*,Valor de op negativo case default print*,op es cero end select end program casos

6.

Estructuras de repetici on
Estructura general do ndice = inicio, nal, incremento sentencias end do 7

Por defecto el incremento es 1. Puede haber bucles vac os (p.ej. con inicio menor que nal e incremento negativo): no se hace ninguna operaci on. exit se puede emplear para forzar la salida del bucle. cycle se puede emplear para pasar directamente al comienzo de la siguiente repetici on del bucle. Ejemplo program repeticiones implicit none integer :: i,op real :: x do i=10,1,-1 print*, i**2 ! cuadrados de enteros del 10 al 1 end do do i=1,10 print*,i**2 ! lo mismo del rev es end do do i=1,10,-1 ! bucle vac o print*,i end do nombre : do i=1,10 ! bucle etiquetado print*,inserta x read*,x if (.NOT.x>=0) then print*,x es negativo cycle ! se pasa de nuevo a la primera l nea, incrementando i end if print*,Otra vez? (1->si) read*,op if (op/=1) exit ! si op=1 se sale del bucle end do nombre ! cierre de bucle etiquetado end program repeticiones

7.

Ficheros
La instrucci on b asica de apertura de un chero es open(unit=unidad, file=nombreFichero, status=tipo) donde: unidad es un n umero entero que identicar a al chero mientras permanezca abierto nombreFichero es el nombre de chero que se desea abrir; lleva comillas tipo es uno de los cuatro siguientes valores old cuando el chero ya existe; permite leer pero no escribir new cuando el chero no existe y se va a crear; si ya existe, da un error replace cuando el chero no existe o existe pero se va a reemplazar por uno nuevo; borra el anterior 8

scratch cuando se trate de un chero temporal de trabajo que se borrar a al cerrar Las instrucciones write(unidad,*) read(unidad,*) sirven para escribir y leer en formato libre. La instrucci on open dada abre cheros de tipo texto. Se puede modicar para cheros binarios (sin formato). El chero se cierra con close(unidad) Ejemplo program ficheros implicit none real :: a,b integer :: i,n open(unit=1, file=datos.dat, status=old) open(unit=2, file=salida.res, status=replace) read(1,*) n do i=1,n read(1,*) a,b write(2,*) a+b end do close(1) close(2) end program ficheros

Si el chero datos.dat tiene la forma 5 4. 6. -2. 1. 2. 2. 3. 4. 1.2e-3 1.1e2

el chero salida.res tendr a la forma 6. 9. 2. 1.0012 112.

8.

Funciones
En principio una funci on devuelve u nicamente un valor. La sintaxis general es function nombre declaraci on de variables instrucciones return end function nombre nombre es la denominaci on de la variable de salida y debe estar declarada con las dem as. Puede haber m as de un return por funci on. El nal es innecesario. Ejemplo

program programaPrincipal implicit none integer :: i,n real :: x, f ! la funci on f se declara como otra variable print*,inserta numero repeticiones read*,n do i=1,n print*,escribe x read*,x print*,f(x) print*,x+f(x) end do end program programaPrincipal function f(y) implicit none real :: y,f,z if (y>=0) then z=y**3 f=z+z**2 else f=0 end if return end function f

! z es una variable local

! f ser a el valor de salida

9.

Subrutinas
La sintaxis de una subrutina es subroutine nombre(arg1 ,..., argn ) declaraci on de variables instrucciones end subroutine nombre

10

Todos los argumentos son, salvo que se indique lo contrario mediante los especicadores intent, de entrada y salida, es decir, su valor puede ser modicado en el transcurso de la ejecuci on. La llamada a una subrutina se realiza mediante la orden call call nombre(var1 ,..., varn ) El especicador intent sirve para bloquear un argumento como argumento de entrada o salida. Sus posibles valores son in (entrada); no admite que sea modicada out (salida) inout (entrada y salida) Se puede regresar al programa principal desde cualquier punto de la subrutina con return. Ejemplo program programaPrincipal implicit none integer :: i,j real :: x,y,z print*,introducir dos enteros y dos reales read*,i,j,x,y call intercambia(i,j) print*,i,j call potencias(x,y,z,i,j) end program programaPrincipal subroutine intercambiar(u,v) integer :: u,v,w ! u,v son de entrada-salida; w es local w=u u=v v=w end subroutine intercambiar ! no hace falta poner un return subroutine potencias(x,y,z,i,j) integer, intent(in) :: i,j ! i,j son argumentos de entrada real :: x,y real, intent(out) :: z if ((i<0).OR.(j<0)) then z=x+y return ! regresa al programa principal end if x=x**i y=y**j z=x+y end subroutine potencias

11

10.

Vectores y matrices (1)


Se hace en la declaraci on de variables, utilizando el especicador dimension. Ejemplo

Declaraci on de matrices.

... real, dimension(10) :: b,c ! vectores de 10 componentes real(kind=8), dimension(10,12) :: a ! matriz 10 12, doble precisi on real :: bb(10), cc(10,12) ! equivalente a poner dimension integer :: ccc(-2:7) ! 10 componentes, numeradas a partir de -2 ...

Operaciones elementales. + : Suma elemento a elemento, de arrays de las mismas dimensiones. - : Resta elemento a elemento. Tambi en, cambio de signo de todos los elementos. * : Producto de un escalar por un array. * : Producto elemento a elemento de arrays de las mismas dimensiones. Las funciones abs, log, sin, cos, exp, ... se aplican elemento a elemento. Ejemplo program operaciones real :: a(10,10),b(10,10),c(10,10),v1(10),v2(10),t=3.,c1,c2 integer :: i,j do i=1,10 do j=1,10 a(i,j)=1./(i+j) end do v1(i)=i*6.5 end do b=t*a c=a+b c=-c b=c*a ! producto elemento a elemento v2=sin(v1) v1=t*v1+5*v2 ! combinaci on lineal end program operaciones

Asignaciones y bucles impl citos. La asignaci on siguiente real :: b(10) ... b=(/ -3.,-1.,1.,3.,5.,7.,9.,11.,13.,15. /) ... se puede hacer equivalentemente en un bucle desplegado 12

do i=1,10 b(i)=2*(i-2)-1 end do o en un bucle impl cito b=(/ (2*i-1, i=-1,8) /) o incluso b=(/ (i, i=-3,11,2) /) Ejemplo ... integer :: b(8), c(9) b=(/ (i,i=-3,15,2) /) ! (/-3,-1,1,3,5,7,...,11 /) b=(/ 1,2,(i**2,i=2,4), (-i**2,i=4,2,-1) /) ! (/ 1,2,4,9,16,-16,-9,-4 /) c=(/ ( (10*j+i,i=1,3), j=1,3 /) ! anidados:(/11,12,13,21,22,23,31,32,33/) ...

11.

Matrices y vectores (2)


transpose(a) dot product(a,b) matmul(a,b) sum(a) product(a) maxval(a) minval(a) maxloc(a) minloc(a) shape(a) devuelve la traspuesta de a calcula el producto escalar de dos vectores a y b calcula el producto de dos matrices a y b; o el producto de una matriz a por un vector b devuelve la suma de todos los elementos de a devuelve el producto de todos los elementos de a devuelve el m aximo valor de a devuelve el m nimo valor de a devuelve un vector con la posici on relativa del m aximo valor de a, esto es, la posici on en el array si todos los ndices arrancan en 1. idem con el m nimo devuelve un vector con las dimensiones de a Ejemplo

FORTRAN 90 dispone de un buen n umero de funciones para manejar matrices y vectores.

program normasVector implicit none integer :: p(1),i real :: b(-1:5) b=(/ -1./9.,1.,((-3.)**(2*i),i=1,5) /) ! norma 2 print*,sqrt(dot product(b,b)) print*,sum(abs(b)) ! norma 1 print*,maxval(abs(b)) ! norma p=maxloc(abs(b)) ! posici on relativa del m aximo print*,p end program normasVector

13

Filas y columnas. a(i,:)

Si se tiene una matriz e i es un valor admisible del ndice

es una referencia v alida de la la i esima, que se puede emplear como vector. De la misma forma a(:,i) sirve para emplear la columna i esima. Las ordenes de escritura y lectura se pueden hacer por las, etc Ejemplo programa lectura implicit none integer :: i real :: a(10,5), b(6) print*,Escribe un vector de seis componentes read*,b print*,Escribe por filas una matriz 10 por 5 do i=1,10 read*, a(i,:) end do print*,Esta es su traspuesta do i=1,5 print*,a(:,i) end do end program lectura

Secciones de vectores y matrices. de matrices y vectores.

La idea anterior se puede generalizar a la selecci on de secciones

Dada una matriz a de dimensi on m n, entonces a(i1:i2, j1:j2) es la matriz obtenida al seleccionar las las i1 a i2 y las columnas j1 a j2. Si aparece algo del estilo a(:i2,j1:j2), las las se toman desde el principio hasta la i2 (esto es, un ndice que no aparece toma el primer valor posible). La sintaxis se puede complicar, tomando ndices que no se mueven consecutivamente, siguiendo el convenio limiteInferior:limiteSuperior:incremento Ejemplo: Consideremos las matrices a1 y a2 1 5 9 2 6 10 3 7 11 4 8 12 2 3 6 7 La sentencia a1(2:3,1:2)=a2(2:3,:) 14 4 8 -1 -2 -3 -4 -5 -6

Entonces a(1:2,2:4) es la submatriz

transforma a1 en

1 -3 -5 3 2 1 2

2 -4 -6 -4

3 7 11 -6

4 8 12 -2 -2

Ejemplo: dado el vector b se tiene que b(2:5) es 1 -4 -6 -2 -4 2 Ejemplo ... print*,maxval( (/ sum( abs(a(i,:)) ),i=1,n) /) ) ... mientras que b(6:2:-2) proporciona

= m axj

|aij |

Ejemplo subroutine gauss(n,a,b,x) implicit none integer :: n,i,j real :: a(n,n), b(n),x(n),c real :: aa(n,n+1) ! array local ajustado a tama~ no exterior aa(1:n,1:n)=a aa(:,n+1)=b ! matriz ampliada do i=1,n ! eliminaci on gaussiana do j=1,n c=aa(j,i)/aa(i,i) aa(j,i:n+1)=aa(j,i:n+1)-c*aa(i,i*n+1) end do end do do i=n,1,-1 ! sustituci on regresiva x(i)=aa(i,n+1)-dot product(aa(i,i+1:n),x(i+1:n)) ! xi = bi x(i)=x(i)/aa(i,i) end do end subroutine gauss

n j =i+1

aij xj

12.

Vectores y matrices (3)


la orden reshape permite asignar tablas de diferentes dimensiones. La sintaxis elemental es reshape(tabla, perl) donde tabla es la matrizvector que queremos reorganizar perl es el vector de dimensiones de la tabla nal 15

Por ejemplo, ... b=(/ 1,2,3,4,5,6 /) m=reshape(b,(/2,3/)) ... devuelve la matriz (por defecto se rellena por columnas) 1 3 2 4 Si seguidamente hacemos mm=reshape(m,(/3,2/)) obtenemos la matriz 1 4 2 5 3 6 5 6

13.

Matrices y vectores (4)


Si ind=(/ i1 ,i2 ,..., ir /) entonces a(ind,:) selecciona las r las de ndices correspondientes a(i1 ,1) a(i1 ,2) ... a(i1 ,n) a(i2 ,1) a(i2 ,2) ... a(i2 ,n) . . . . . . . . . a(ir ,1) a(ir ,2) ... a(ir ,n) De manera an aloga b(ind) es el vector de componentes b(i1 ) b(i2 ) ... b(ir ) Si en ind hay ndices repetidos, esto permite emplear a(ind,:) en operaciones, pero puede dar problemas en asignaciones. (ver comentarios sobre subrutinas) Igualmente, si indi=(/ indj=(/ i1 ,i2 ,..., j1 ,j2 ,..., ir /) js /)

Secciones arbitrarias de matrices y vectores.

la submatriz a(indi,indj) hace referencia a a(i1 ,j1 ) a(i1 ,j2 ) ... a(i1 ,js ) a(i2 ,j1 ) a(i2 ,j2 ) ... a(i2 ,js ) . . . . . . . . . a(ir ,j1 ) a(ir ,j2 ) ... a(ir ,js )

16

Ejemplo. Sean ind=(/1,4,2/); a y b las siguientes matriz y vector (respectivamente) 1 -2 2 1 2 3 2 1 1 3 3 1 -1 0 2 1

2 1 2

-3 2

Entonces a(ind,:) y a(2:3,ind) son respectivamente 1 1 -2 mientras que b(ind) es 2 -3 1 2 3 3 1 2 1 -1 1 0 -2 0 2 2 2 1

Ejemplo. Con indi y indj los vectores de enteros dados respectivamente por 2 4 3 y a dada por 1 -2 2 1 la secci on a(indi,indj) es -2 1 2 La instrucci on a(indi,indj)=0 transformar a a en 1 0 0 0 2 0 0 0 3 1 3 1 -1 0 2 1 2 0 0 0 4 2 3 3 2 1 2 2 1 3 3 1 3 1 -1 2 0 4 2 2 1 3 1 5 2

Declaraci on din amica. En FORTRAN 90 es posible declarar matrices y vectores sin asignarles sus dimensiones, esperando a que se jen durante el programa: El especicador allocatable en la declaraci on de un array, con los ndices de dimensiones mudos, deja la cuesti on de la asignaci on de memoria en suspenso. No obstante, hay que decidir a priori en la declaraci on el n umero de ndices del array. Con allocate se asignan dimensiones. Con deallocate se deasignan dimensiones. Ejemplo program dinamica implicit none real, allocatable :: a(:,:), b(:) integer :: n,i,j,op do j=1,10 17

! una matriz y un vector

print*,dar dimension read*,n allocate(a(n,2*n),b(2*n)) ! asignaci on; ambas en la misma instrucci on print*,escribir matriz por filas do i=1,n read*,a(i,:) end do print*,escribir vector read*,b print*,su producto es:, matmul(a,b) deallocate(a,b) ! desasignaci on de memoria print*,Otra vez? (1->Si) read*,op if(op/=1) exit end do end program dinamica

14.

Matrices y vectores en subrutinas


La forma correcta de enviar una matriz a una subrutina es dando adem as las dimensiones de dicha matriz como otro argumento. En la subrutina se declara como una matriz de las dimensiones recibidas Las matrices se reciben por referencia, es decir, cualquier cambio que hagamos en la matriz en la subrutina se mantiene en el programa principal. Ejemplo

program pruebaSubrutina implicit none real, allocatable :: a(:,:), b(:) integer :: i,j,n,m print*,Escribir dimensiones de la matriz read*,m,n allocate(a(m,n),b(m)) do i=1,m read*,a(i,:) end do call sumaColumnas(a,b,m,n) print*,b end program pruebaSubrutina subroutine sumaColumnas(a,b,k,l) implicit none integer :: k,l,i real :: a(k,l),b(k) b=(/ (sum(a(i,:)), i=1,l) /) end subroutine sumaColumnas

! suma de los elementos de cada fila

18

Lo anterior sigue siendo cierto si enviamos trozos compactos de matrices como argumento. En el ejemplo anterior pod amos haber puesto call sumaColumnas(a(1:m-2,1:n-1),b(1:m-2),m-2,n-1) Esto no funciona si se env an trozos de matrices con referencia mediante un conjunto de ndices. Si hacemos, por ejemplo, call sumaColumnas(a(ind,:),b(ind),mind,n) donde ind es un vector de mind n umeros enteros, se env an copias de las secciones de a y b. Por tanto, cualquier cambio que se haga sobre a o b en la subrutina no repercute en el valor nal. La forma de solucionar este problema es realizar una copia de lo que se quiere enviar en una matriz o vector auxiliar, llamar a la subrutina y al nal volcar el resultado sobre la matriz o vector original. Ejemplo program pruebaSubrutina implicit none real, allocatable :: a(:,:), b(:), b2(:) integer :: i, j, n, m, mind integer, allocatable :: ind(:) print*,Escribir dimensiones read*,m,n allocate(a(m,n),b(m)) print*,Introducir la matriz por filas do i=1,m read*,a(i,:) end do print*,Cuantas filas quieres tener en cuenta? read*, mind allocate(b2(mind),ind(mind)) print*,Escribir numeros de filas read*,ind call sumaColumnas(a(ind,:),b2,mind,n) ! la parte de a pasa por valor b(ind)=b2 ! las filas que no se tienen en cuenta dan un cero print*,b end program pruebaSubrutina

Ejemplo subroutine GaussSeidel(a,b,x,n,itmax,tol) implicit none integer, intent(in) :: n,itmax real :: a(n,n),x(n),xold(n),b(n) real, intent(in) :: tol real :: dif x=0. ! arrancamos del vector nulo do it=1,itmax xold=x do i=1,n x(i)=b(i)-dot product(a(i,1:i-1),x(1:i-1))& 19

! con i=1, nada

&-dot product(a(i,i+1:n),xold(i+1:n)) x(i)=x(i)/a(i,i) end do dif=maxval(abs(x-old)) ! norma infinito if (dif<tol) exit end do end subroutine GaussSeidel

! sigue la l nea

15.

Funciones como argumentos


Ejemplo

Se emplea el especicador external en todas las apariciones de la misma.

function trapecio(f,a,b,n) integer :: n,i real :: trapecio,a,b,h real, external :: f ! f es un argumento funcional trapecio=0. h=(b-a)/n do i=1,n-1 trapecio=trapecio+h*f(a+i*h) end do trapecio=trapecio+h/2.*(f(a)+f(b)) end function trapecio function g1(x) real :: g1,x real, parameter :: pi=3.141592 g1=cos(2*pi*x) end function g1 function g2(x) real :: g2,x g2=(x-1.)**2 end function g2 program prueba ! programa principal integer :: num,op real :: a,b real :: trapecio real,external :: g1,g2 ! g1, g2 deben ser declaradas como externas print*,Extremos del intervalo read*,a,b print*,Numero de particiones read*,num print*,Opcion: read*,op opciones : select case(op) case(1) print*,Resultado:,trapecio(g1,a,b,num) case(2) print*,Resultado:,trapecio(g2,a,b,num) 20

end select opciones end program prueba

16.

M odulos
Construcci on module nombreModulo informacion... end module nombreModulo Utilizaci on program/function/subroutine nombreParte use nombreModulo declaraciones de variables sentencias del programa end program/function/subroutine nombreParte Ejemplo

M odulos simples: contienen informaci on como declaraciones de variables y par ametros muy repetitivas.

module constantes real, parameter :: pi=3.141592, euler=0.57721566 end module constantes function g1(x) use constantes implicit none real :: g1,x g1=cos(2*pi*x) end function g1 function g2(x) implicit none real :: g2,x g2=(x-1.)**2 end function g2

M odulos librer a: contienen funciones y subrutinas Construcci on module moduloSegundo contains function nombreFuncion ... end function nombreFuncion function otraFuncion ... end function otraFuncion end module moduloSegundo 21

Utilizaci on: igual que antes Ejemplo module misfunciones contains function g1(x) use constantes implicit none real :: g1,x g1=cos(2*pi*x) end function g1 function g2(x) implicit none real :: g2,x g2=(x-1.)**2 end function g2 end module misfunciones program prueba use misfunciones implicit none integer :: num,op real :: a,b real :: trapecio ! programa principal ! no se declaran g1, g2

print*,Extremos del intervalo read*,a,b print*,Numero de particiones read*,num print*,Opcion: read*,op opciones : select case(op) case(1) print*,Resultado:,trapecio(g1,a,b,num) case(2) print*,Resultado:,trapecio(g2,a,b,num) end select opciones end program prueba

17.

Tipos derivados de datos


Empaquetado de varias variables bajo un tipo com un. Forma: program/subroutine/function nombreParte type nombreTipo declaraciones de identificadores end type nombreTipo declaraciones de otras variables 22

type (nombreTipo) :: variablesConcretas .... Ojo: hay que incluir la declaraci on del tipo en todas las partes en que se use Ejemplo program pruebatipos type fecha integer :: dia, mes, anho end type fecha type (fecha) :: mifecha type (fecha), external :: leefecha integer :: aux mifecha=leefecha() aux=mifecha %anho aux=aux-100*(aux/100) print*,Mi fecha:,mifecha %dia,mifecha %mes,aux end program pruebatipos function leefecha() type fecha integer :: dia, mes, anho end type fecha type (fecha) :: leefecha print*,A~ no: read*,leefecha %anho print*,Mes: read*,leefecha %mes print*,Dia: read*,leefecha %dia return end function leefecha ! sin argumentos

Ejemplo module misEstructuras type fecha integer :: dia, mes, anho end type fecha end module misEstructuras program pruebatipos use misEstructuras type (fecha) :: mifecha type (fecha), external :: leefecha integer :: aux ... ! sigue como antes end program pruebatipos

23

function leefecha() use misEstructuras type (fecha) :: leefecha ... ! sigue como antes end function leefecha

Ejemplo module misEstructuras type fecha integer :: dia, mes, anho end type fecha type datos type(fecha) :: nacimiento ! un tipo puede utilizar otros tipos character(len=40) :: nombre, apellidos integer :: dni end type datos end module misEstructuras program pruebatiposdetipos use misEstructuras type (datos), allocatable :: lista(:) type (fecha), external :: leefecha integer :: i,num print*,Cuantos datos? read*,num allocate(lista(num)) do i=1,num print*,Nombre read (a40),lista(i) %nombre print*,Apellidos read (a40),lista(i) %apellidos lista(i) %nacimiento=leefecha() end do print*,Lista de a~ nos de nacimiento do i=1,num print*,lista(i) %nacimiento %anho end do end program pruebatiposdetipos

18.

Funciones con valores vectoriales

FORTRAN 90 admite que una funci on devuelva un array de datos. Precauci on: tienen que estar declaradas bajo una estructura interface cada vez que se usen. La declaraci on es un prototipo que aclara el tipo de variables y de resultado de la funci on. Ejemplo

24

function rotacion(x,theta) real :: theta,x(2),rotacion(2),matriz(2,2) matriz=reshape((/cos(theta),-sin(theta),& & sin(theta),cos(theta)/),(/2,2/)) rotacion=matmul(matriz,x) end function rotacion program prueba real :: phi,x(2) interface function rotacion(x,ang) real :: ang,x(2),rotacion(2) end function end interface print*,angulo de rotacion read*,phi print*,vector que se quiere rotar read*,x x=rotacion(x,phi) print*,vector rotado=,x end program prueba

19.

Punteros
Variables que apuntan direcciones de memoria de otras variables Se declaran con el atributo pointer Las variable a las que se va a apuntar llevan el atributo target La forma general es puntero=>objetivo Ejemplo

program puntero implicit none real,target ::aa,bb real, pointer:: c,d aa=4. bb=6. c=>aa ! c apunta a aa d=>bb ! d apunta a bb print*,aa=,aa,bb=,bb print*,valor apuntado por c,c,valor apuntado por d,d c=-6 print*,aa=,aa,bb=,bb print*,valor apuntado por c,c,valor apuntado por d,d c=>d ! c apunta a bb (a->d->bb) c=2 print*,bb=,bb 25

print*,valor apuntado por c,c,valor apuntado por d,d nullify(c) ! c no apunta a ninguna variable end program puntero

El programa anterior da como salida en pantalla a= 4.000000 b= valor apuntado por c a= -6.000000 b= valor apuntado por c b= 2.000000 valor apuntado por c 6.000000 4.000000 6.000000 -6.000000 2.000000 valor apuntado por d valor apuntado por d valor apuntado por d 6.000000 6.000000 2.000000

Las variables punteros pueden denirse para apuntar a estructuras m as complicadas: arrays y estr ucturas de datos.

20.

Ejemplo nal

Problema. Almacenamiento (y manipulaci on) de matrices esencialmente vac as. Modelo sparse. 0 1 ,5 2 ,5 0 2 0 0 0,5 0 0,25 0 0 real 1,5 integer 1 integer 2 2,5 1 3 2 2 1 0,5 0,25 2 3 4 2

El formato debe guardar el tama no de la matriz original m as el n umero de elementos no nulos (por comodidad) Problema pr actico. El tipo de datos debe admitir longitudes por determinar. Pero no puede haber nada allocatable: * en la denici on de un tipo de datos * como argumento de una subrutina o funci on Sustituir allocatable por pointer y hacer lo mismo. Por dentro, el programa cambia mucho; por fuera, no. Plan. M odulo con tipo sparse Subrutinas y funciones: leer matriz sparse pasar sparse a matriz pasar matriz a sparse multiplicar sparse por vector Crear un m odulo con las interfaces de todo lo anterior Programa de prueba 26

module cosassparse type sparse integer :: nf,nc,nel real, pointer :: matriz(:) integer, pointer :: fil(:), col(:) end type sparse end module cosassparse module funcionessparse interface subroutine leersparse(u) use cosassparse type(sparse) :: u end subroutine leersparse function sparser(v,dim) use cosassparse type(sparse) :: sparser integer,dimension(2) :: dim real :: v(dim(1),dim(2)) end function sparser function matriz(a) use cosassparse type(sparse) :: a real :: matriz(a %nf,a %nc) end function matriz function sparseporvector(a,x,m) use cosassparse integer :: m type(sparse) :: a real :: x(m),sparseporvector(a %nf) end function sparseporvector end interface end module funcionessparse subroutine leersparse(a) use cosassparse type (sparse) :: a integer :: n,i print*,Numero elementos, filas, columnas read*,n,a %nf,a %nc a %nel=n allocate(a %matriz(n),a %fil(n),a %col(n)) do i=1,n read*,a %matriz(i),a %fil(i),a %col(i) end do end subroutine leersparse Nota. a entra sin tama no predenido y sale con tama no asignado. function matriz(a) use cosassparse type(sparse) :: a real :: matriz(a %nf,a %nc) integer :: i matriz=0. 27

do i=1,a %nel matriz(a %fil(i),a %col(i))=a %matriz(i) end do end function matriz function sparser(v,dim) use cosassparse type(sparse) :: sparser integer,dimension(2) :: dim real :: v(dim(1),dim(2)) integer :: cont,i,j,aux(1) sparser %nf=dim(1) sparser %nc=dim(2) aux=count(v/=0) sparser %nel=aux(1) cont=aux(1) allocate(sparser %matriz(cont), & & sparser %fil(cont),sparser %col(cont)) cont=0. do i=1,dim(1) do j=1,dim(2) if(v(i,j) /= 0) then cont=cont+1 sparser %matriz(cont)=v(i,j) sparser %fil(cont)=i sparser %col(cont)=j end if end do end do end function sparser function sparseporvector(a,x,m) use cosassparse integer :: m type(sparse) :: a real :: x(m),aux(a %nf),sparseporvector(a %nf) if (m /= a %nc) then print*,error de dimensiones return end if aux=0 do i=1,a %nel aux(a %fil(i))=aux(a %fil(i))+& & a %matriz(i)*x(a %fil(i)) end do sparseporvector=aux end function sparseporvector program pruebas use cosassparse use funcionessparse type (sparse) :: a real,allocatable :: bb(:,:),cc(:,:),x(:),y(:) allocate(bb(3,5),x(5),y(3)) 28

do i=1,3 bb(i,i+2)=3.*i bb(i,i)=-1.*i end do a=sparser(bb,shape(bb)) print*,a %matriz allocate(cc(a %nf,a %nc)) cc=matriz(a) do i=1,size(cc,dim=1) print*,cc(i,:) end do print* x=1. y=sparseporvector(a,x,5) print*,y end program pruebas

29

También podría gustarte