Apuntesde Fortran 90 by rrk61112

VIEWS: 15 PAGES: 29

									Apuntes de Fortran 90




       ınguez y F.J. Sayas
 V. Dom´
        Junio de 2001
1.             o
     Introducci´n
                              o
Fortran 90 es una actualizaci´n de Fortran 77 que moderniza este lenguaje, incorporando algunas de las
        ısticas comunes de los lenguajes m´s modernos (C, C++, Pascal,etc.). Con el nuevo lenguaje se
caracter´                                 a
persiguen los siguientes objetivos:
     Modernizar la sintaxis.
                                   o
     Incluir aspectos de programaci´n modular, recursividad,. . .
                                                       a
     Mejorar la “habilidad” para trabajar con las matem´ticas.
                o
     Incorporaci´n de estructuras de datos y de punteros.
                                       ıa a                                                    ı       n
Dentro de los posible se mantiene todav´ v´lida las instrucciones y sintaxis del Fortran 77. As´ peque˜as
                                    o                         o
modificaciones permiten pasar un c´digo en Fortran 77 a un c´digo 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 identifican con vectores y matrices. La nueva filosof´ de   ıa
Fortran 90 consiste en el manejo de estas estructuras globalmente en lugar de elemento a elemento.
     ´                  n                              o
Por ultimo conviene se˜alar que existe una actualizaci´n posterior que se conoce como Fortran 95. Sin
embargo los cambios que incorpora son de una magnitud sensiblemente inferior a los desarrollados en la
     o
versi´n 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.
                              u            u
     No se distingue entre may´sculas y min´sculas. Hay compiladores que distinguen para los nombres
     de variables.
                   ınea de comentario. Todo lo que sigue no se compila.
     ! indica una l´
                                  ınea. Se escribe al final de la l´
     & se emplea para cortar una l´                               ınea cortada y al principio de la siguiente.
     Estructura del programa.
     program nombre programa
              o
     declaraci´n de variables
     cuerpo del programa
     end program nombre programa
                                                                                                   Ejemplo

! mi primer programa en FORTRAN 90

program primero                    ! arranque del programa
implicit none                               o
                                 ! declaraci´n variables
real :: x,y

! 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
2.            o                         o
     Declaraci´n de variables y asignaci´n
     Tipos de constantes y variables:
       • enteras (integer)
                                                        o
       • de coma flotante (real) a simple y doble precisi´n
                                                     o
       • complejas (complex) a simple y doble precisi´n
            a
       • car´cter (character)
          o                 ´
       • l´gicas (logical): unicamente pueden adoptar los valores

                                             .TRUE.           .FALSE

     La orden
                                               implicit none
                             ıcito de declaraci´n de variables y obliga a declarar todas las variables
     cancela un convenio impl´                 o
                                              o
     Por defecto real y complex son de precisi´n simple, pero depende del compilador.

                                                                                               Ejemplo


program asignaciones
implicit none
integer :: i,j
real (kind=4) :: x,y                                            o
                                  ! declara variables de precisi´n simple
real (kind=8) :: z,t                       o
                                  ! precisi´n 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 10−4
y=-2.312e2
x=3.4
y=4                            o                     o
               ! esta asignaci´n incluye una conversi´n de entero a real
z=3.23e-4 8                                            o
                       ! 8 indica que es doble precisi´n
t=2. 8
z=(3.e-1,2.)             ! =0,3 + 2ı
palabra=’casa’                                                         a
                          ! las comillas identifican las constantes car´cter
palabra="Juan"                    e
                          ! tambi´n se usan las dobles comillas
test=.TRUE.

end program asignaciones




            o
Inicializaci´n 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
                                        o                                  e
     En las asignaciones de inicializaci´n no puede haber operaciones aritm´ticas. Es aconsejable que no
                              a
     haya conversiones autom´ticas (entero a real, etc).




                                                   3
programa asignaciones
implicit none
real :: x=4.,t,z=3.e-2                     ! asigna valores de arranque a x y z
real (kind=8) :: u=6.e2 8
complex :: a=(2.,3.)
character (4) :: palabra=’casa’                            ! (4) abrevia (len=4)
real, parameter :: pi=3.141592
...

3.   Lectura y escritura en pantalla
Para escribir en pantalla y leer de teclado, en formato libre, se usan respectivamente

                                         print*,              read*,
                                                                                         Ejemplo


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




4.                  e
     Operaciones num´ricas
          a                                    o                o
Binarias b´sicas. Suma, resta, producto, divisi´n y exponenciaci´n.
                                     +        -       *       /       **

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

               a       a                                                e
Funciones matem´ticas b´sicas. El argumento siempre se escribe entre par´ntesis.
                            o
     abs (valor absoluto o m´dulo)

             ız
     sqrt (ra´ cuadrada)
     exp (exponencial)
     log (logaritmo neperiano)
     log10
     sin
     cos
     tan


                                                      4
     asin

     acos
     atan
     sinh
     cosh
     tanh

Otras.

                                      o
     mod(i,j) da el resto de la divisi´n 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                      ! preasignadas
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



                               ıa
El programa precedente devolver´ en pantalla:

2   3    2
-5 -4    -4
7.2 -5

5.                        o
     Estructuras de decisi´n
                              o o                                          o
Operadores de comparaci´n. N´tese la diferencia entre el igual de comparaci´n (==) y el de asigna-
  o       ımbolo /= indica =.
ci´n. El s´
                               >      <    <=          >=   ==     /=




                                                   5
            o                                            o
Operadores l´gicos. Son cuatro: y, o, o exclusivo, negaci´n.
                                 .AND.   .OR.       .XOR.      .NOT.

                         ´
     Simple de sentencia unica

                o o
     if (expresi´n l´gica) sentencia

                          u
     Simple de sentencia m´ltiple

                o o
     if (expresi´n l´gica) then
         sentencia primera
         sentencia segunda
         ...
     end if

     If-else

     if (...) then
          ...
     else
          ...
     end if

           o   u
     Decisi´n m´ltiple

     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
else
    print*,’x*y es negativo o nulo’
end if
end program decisiones




La orden select case. La sintaxis es
select case (criterio)                                                e
                                      ! criterio devuelve un valor num´rico
    case(expr1 )                 ! selecciona si se cumple el caso
        ...
    case(expr2 )                 ! si se cumple este caso y no el precedente
        ...
    ...
    case default                   ! caso por defecto; puede no estar
        ...
end select
                                                                               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.                            o
       Estructuras de repetici´n
       Estructura general

          ındice = inicio, final, incremento
       do ´
            sentencias
       end do

                                                7
     Por defecto el incremento es 1.

                           ıos
     Puede haber bucles vac´ (p.ej. con inicio menor que final e incremento negativo): no se hace
                    o
     ninguna operaci´n.

     exit se puede emplear para forzar la salida del bucle.
                                                                                        o
     cycle se puede emplear para pasar directamente al comienzo de la siguiente repetici´n 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                                e
                             ! lo mismo del rev´s
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
                 o a
     La instrucci´n b´sica de apertura de un fichero es

     open(unit=unidad, file=nombreFichero, status=tipo)

     donde:
       • unidad es un n´mero entero que identificar´ al fichero mientras permanezca abierto
                       u                          a
       • nombreFichero es el nombre de fichero que se desea abrir; lleva comillas
       • tipo es uno de los cuatro siguientes valores
              ◦ ’old’ cuando el fichero ya existe; permite leer pero no escribir
              ◦ ’new’ cuando el fichero no existe y se va a crear; si ya existe, da un error
              ◦ ’replace’ cuando el fichero no existe o existe pero se va a reemplazar por uno nuevo;
                borra el anterior


                                                  8
                                                                                       a
             ◦ ’scratch’ cuando se trate de un fichero temporal de trabajo que se borrar´ al cerrar

      Las instrucciones

      write(unidad,*)
      read(unidad,*)

      sirven para escribir y leer en formato libre.
                  o
      La instrucci´n open dada abre ficheros de tipo texto. Se puede modificar para ficheros binarios (sin
      formato).

      El fichero 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 fichero datos.dat tiene la forma

5
4.        2.
6.        3.
-2.       4.
1.        1.2e-3
2.        1.1e2

                          a
el fichero salida.res tendr´ la forma

6.
9.
2.
1.0012
112.




                                                      9
8.   Funciones
                           o           ´
     En principio una funci´n devuelve unicamente un valor.
     La sintaxis general es

     function nombre
              o
     declaraci´n de variables
     instrucciones
     return
     end function nombre

                            o                                                             a
     nombre es la denominaci´n de la variable de salida y debe estar declarada con las dem´s.
                  a                        o
     Puede haber m´s de un return por funci´n. El final es innecesario.

                                                                                            Ejemplo


program programaPrincipal
implicit none
integer :: i,n
real :: x, f                        o
                          ! la funci´n 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                   ! z es una variable local
if (y>=0) then
     z=y**3
     f=z+z**2                          a
                                ! f ser´ el valor de salida
else
     f=0
end if
return
end function f




9.   Subrutinas
     La sintaxis de una subrutina es

     subroutine nombre(arg1 ,..., argn )
              o
     declaraci´n de variables
     instrucciones
     end subroutine nombre



                                                 10
    Todos los argumentos son, salvo que se indique lo contrario mediante los especificadores intent,
                                                                                              o
    de entrada y salida, es decir, su valor puede ser modificado en el transcurso de la ejecuci´n.
    La llamada a una subrutina se realiza mediante la orden call

    call nombre(var1 ,..., varn )

    El especificador intent sirve para bloquear un argumento como argumento de entrada o salida.
    Sus posibles valores son
       • in (entrada); no admite que sea modificada
       • 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)
         o
Declaraci´n de matrices.                             o
                              Se hace en la declaraci´n de variables, utilizando el especificador dimension.
                                                                                                  Ejemplo


...
real, dimension(10) :: b,c              ! vectores de 10 componentes
real(kind=8), dimension(10,12) :: a                                             o
                                                 ! matriz 10 × 12, doble precisi´n
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.
                                          e
      - : Resta elemento a elemento. Tambi´n, 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                          o
                           ! combinaci´n lineal
end program operaciones




                          ıcitos. La asignaci´n siguiente
Asignaciones y bucles impl´                  o

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

                  ıcito
o en un bucle impl´

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)
                               u
FORTRAN 90 dispone de un buen n´mero de funciones para manejar matrices y vectores.
        transpose(a)       devuelve la traspuesta de a
        dot product(a,b)   calcula el producto escalar de dos vectores a y b
        matmul(a,b)        calcula el producto de dos matrices a y b;
                           o el producto de una matriz a por un vector b
        sum(a)             devuelve la suma de todos los elementos de a
        product(a)         devuelve el producto de todos los elementos de a
        maxval(a)                         a
                           devuelve el m´ximo valor de a
        minval(a)          devuelve el m´ ınimo valor de a
        maxloc(a)                                            o                 a
                           devuelve un vector con la posici´n relativa del m´ximo valor de a,
                                             o                           ındices arrancan en 1.
                           esto es, la posici´n en el array si todos los ´
        minloc(a)          idem con el m´  ınimo
        shape(a)           devuelve un vector con las dimensiones de a

                                                                                             Ejemplo

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




                                                13
Filas y columnas.                                                          ındice
                      Si se tiene una matriz e i es un valor admisible del ´
a(i,:)
                   a                 e
es una referencia v´lida de la fila i–´sima, que se puede emplear como vector. De la misma forma
a(:,i)
                                 e
sirve para emplear la columna i–´sima.
     o
Las ´rdenes de escritura y lectura se pueden hacer por filas, 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.                                                           o
                                          La idea anterior se puede generalizar a la selecci´n de secciones
de matrices y vectores.

                                     o
     Dada una matriz a de dimensi´n m× n, entonces a(i1:i2, j1:j2) es la matriz obtenida al selec-
     cionar las filas i1 a i2 y las columnas j1 a j2.
     Si aparece algo del estilo a(:i2,j1:j2), las filas se toman desde el principio hasta la i2 (esto es,
     un ´ındice que no aparece toma el primer valor posible).
                                             ındices que no se mueven consecutivamente, siguiendo el
     La sintaxis se puede complicar, tomando ´
     convenio

     limiteInferior:limiteSuperior:incremento

     Ejemplo: Consideremos las matrices a1 y a2

                                      1    2    3    4             -1 -2
                                      5    6    7    8             -3 -4
                                      9    10   11   12            -5 -6

     Entonces a(1:2,2:4) es la submatriz
                                                     2 3   4
                                                     6 7   8
     La sentencia

     a1(2:3,1:2)=a2(2:3,:)

                                                     14
      transforma a1 en
                                                  1    2    3        4
                                                 -3    -4   7        8
                                                 -5    -6   11       12

      Ejemplo: dado el vector b
                                         3   2    1    -4   -6       -2 -2
      se tiene que b(2:5) es
                                                  2    1 -4 -6
      mientras que b(6:2:-2) proporciona
                                                      -2 -4      2

                                                                                                      Ejemplo


...
print*,maxval( (/ sum( abs(a(i,:)) ),i=1,n) /) )                             !   A   ∞      a
                                                                                         = m´xj   i   |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)                                           n
                               ! array local ajustado a tama~o exterior
aa(1:n,1:n)=a
aa(:,n+1)=b              ! matriz ampliada
do i=1,n                          o
                       ! eliminaci´n 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                         o
                         ! sustituci´n regresiva
                                                                                                  n
    x(i)=aa(i,n+1)-dot product(aa(i,i+1:n),x(i+1:n))               ! xi = bi −                    j=i+1        aij xj
    x(i)=x(i)/aa(i,i)
end do
end subroutine gauss




12.    Vectores y matrices (3)
      la orden reshape permite asignar tablas de diferentes dimensiones. La sintaxis elemental es

      reshape(tabla, perfil)

      donde
        • tabla es la matriz–vector que queremos reorganizar
        • perfil es el vector de dimensiones de la tabla final


                                                      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     5
                                                    2 4     6

      Si seguidamente hacemos

      mm=reshape(m,(/3,2/))

      obtenemos la matriz
                                                      1 4
                                                      2 5
                                                      3 6

13.    Matrices y vectores (4)
Secciones arbitrarias de matrices y vectores.
      Si

      ind=(/ i1 ,i2 ,..., ir /)

                                                 ındices correspondientes
      entonces a(ind,:) selecciona las r filas de ´

                                        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)

                  a
      De manera an´loga b(ind) es el vector de componentes

                                           b(i1 ) b(i2 ) ... b(ir )

                    ındices repetidos, esto permite emplear a(ind,:) en operaciones, pero puede dar
      Si en ind hay ´
      problemas en asignaciones. (ver comentarios sobre subrutinas)
      Igualmente, si

      indi=(/   i1 ,i2 ,...,   ir /)
      indj=(/   j1 ,j2 ,...,   js /)

      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 3    -1
                              -2   2 1     0
                                                          2 1 2    -3 2
                              2    1 3     2
                              1    3 1     1

Entonces a(ind,:) y a(2:3,ind) son respectivamente

                                    1   2 3    -1
                                                              -2 0 2
                                    1   3 1    1
                                                              2 2 1
                                   -2   2 1    0

mientras que b(ind) es
                                               2    -3    1

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

          o       a
Declaraci´n din´mica. En FORTRAN 90 es posible declarar matrices y vectores sin asignarles sus
dimensiones, esperando a que se fijen durante el programa:
                                                   o                    ındices de dimensiones mudos,
     El especificador allocatable en la declaraci´n de un array, con los ´
                   o                o
     deja la cuesti´n de la asignaci´n de memoria en suspenso. No obstante, hay que decidir a priori en
                 o      u
     la declaraci´n el n´mero de ´ındices del array.
     Con allocate se asignan dimensiones.
     Con deallocate se deasignan dimensiones.
                                                                                             Ejemplo


program dinamica
implicit none
real, allocatable :: a(:,:), b(:)                         ! una matriz y un vector
integer :: n,i,j,op
do j=1,10

                                                    17
    print*,’dar dimension’
    read*,n
    allocate(a(n,2*n),b(2*n))                        o                              o
                                           ! asignaci´n; ambas en la misma instrucci´n
    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)                           o
                                 ! desasignaci´n de memoria
    print*,’¿Otra vez? (1->Si)’
    read*,op
    if(op/=1) exit
end do
end program dinamica




14.    Matrices y vectores en subrutinas
                                                                          a
      La forma correcta de enviar una matriz a una subrutina es dando adem´s 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) /)                     ! suma de los elementos de cada fila
end subroutine sumaColumnas




                                                  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)

                              ıan                                                         ındices. Si
    Esto no funciona si se env´ trozos de matrices con referencia mediante un conjunto de ´
    hacemos, por ejemplo,

    call sumaColumnas(a(ind,:),b(ind),mind,n)

                                      u                      ıan
    donde ind es un vector de mind n´meros enteros, se env´ 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 final.
    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 final 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))&                            ! con i=1, nada

                                                    19
            &-dot product(a(i,i+1:n),xold(i+1:n))                                      ı
                                                                           ! sigue la l´nea
        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




15.   Funciones como argumentos
Se emplea el especificador external en todas las apariciones de la misma.
                                                                                              Ejemplo


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.     o
       M´dulos
 o                                  o                                       a
M´dulos simples: contienen informaci´n como declaraciones de variables y par´metros muy repetitivas.
                o
      Construcci´n

      module nombreModulo
          informacion...
      end module nombreModulo

               o
      Utilizaci´n

      program/function/subroutine nombreParte
      use nombreModulo
      declaraciones de variables
      sentencias del programa
      end program/function/subroutine nombreParte

                                                                                           Ejemplo

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


 o            ıa:
M´dulos librer´ contienen funciones y subrutinas
                o
      Construcci´n

      module moduloSegundo
      contains
          function nombreFuncion
          ...
          end function nombreFuncion
          function otraFuncion
          ...
          end function otraFuncion
      end module moduloSegundo

                                                   21
               o
      Utilizaci´n: 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                       ! programa principal
use misfunciones                       ! no se declaran g1, g2
implicit none
integer :: num,op
real :: a,b
real :: trapecio

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
                                                      u
      Empaquetado de varias variables bajo un tipo com´n.
      Forma:

      program/subroutine/function nombreParte
      type nombreTipo
          declaraciones de identificadores
      end type nombreTipo
      declaraciones de otras variables

                                                   22
    type (nombreTipo) :: variablesConcretas
    ....

                                     o
    Ojo: hay que incluir la declaraci´n 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()                   ! sin argumentos
type fecha
    integer :: dia, mes, anho
end type fecha
type (fecha) :: leefecha
         n
print*,’A~o:’
read*,leefecha %anho
print*,’Mes:’
read*,leefecha %mes
print*,’Dia:’
read*,leefecha %dia
return
end function leefecha




                                                                                     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
                   n
print*,’Lista de a~os de nacimiento’
do i=1,num
    print*,lista(i) %nacimiento %anho
end do
end program pruebatiposdetipos




18.    Funciones con valores vectoriales
                                   o
FORTRAN 90 admite que una funci´n devuelva un array de datos.
        o
Precauci´n: tienen que estar declaradas bajo una estructura
                                               interface
                                  o
cada vez que se usen. La declaraci´n es un prototipo que aclara el tipo de variables y de resultado de la
     o
funci´n.
                                                                                                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=        6.000000
        valor apuntado por c        4.000000      valor apuntado por d       6.000000
        a= -6.000000      b=        6.000000
        valor apuntado por c       -6.000000      valor apuntado por d       6.000000
        b=   2.000000
        valor apuntado por c        2.000000      valor apuntado por d       2.000000
                                                                   a                            u
Las variables punteros pueden definirse para apuntar a estructuras m´s complicadas: arrays y estr´cturas
de datos.

20.     Ejemplo final
                                      o                                ıas.
Problema. Almacenamiento (y manipulaci´n) de matrices esencialmente vac´

Modelo sparse.
                                                          
                                              0 1,5 2,5 0
                                            −2  0   0 0,5 
                                              0 0,25 0  0

                                      real 1,5    2,5   −2     0,5 0,25
                                   integer 1       1    2       2   3
                                   integer 2       3    1       4   2
                               n                         a      u
El formato debe guardar el tama˜o de la matriz original m´s el n´mero de elementos no nulos (por
comodidad)

             a
Problema pr´ctico. El tipo de datos debe admitir longitudes por determinar. Pero no puede haber
nada allocatable:
                  o
   * en la definici´n de un tipo de datos
   * como argumento de una subrutina o funci´n
                                            o
Sustituir allocatable por pointer y hacer lo mismo. Por dentro, el programa cambia mucho; por fuera,
no.

Plan.
       o
      M´dulo con tipo sparse
      Subrutinas y funciones:
         • leer matriz sparse
         • pasar sparse a matriz
         • pasar matriz a sparse
         • multiplicar sparse por vector
                o
      Crear un m´dulo 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

                      n                            n
Nota. a entra sin tama˜o predefinido y sale con tama˜o 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

								
To top