fortran 90

Upload: glenn-robert-revolledo-vilchez

Post on 30-Oct-2015

85 views

Category:

Documents


3 download

TRANSCRIPT

  • Apuntes de Fortran 90

    V. Domnguez y F.J. Sayas

    Junio de 2001

  • 1. Introduccion

    Fortran 90 es una actualizacion de Fortran 77 que moderniza este lenguaje, incorporando algunas de lascaractersticas comunes de los lenguajes mas modernos (C, C++, Pascal,etc.). Con el nuevo lenguaje sepersiguen los siguientes objetivos:

    Modernizar la sintaxis.

    Incluir aspectos de programacion modular, recursividad,. . .

    Mejorar la habilidad para trabajar con las matematicas.

    Incorporacion de estructuras de datos y de punteros.

    Dentro de los posible se mantiene todava valida las instrucciones y sintaxis del Fortran 77. As pequenasmodificaciones permiten pasar un codigo en Fortran 77 a un codigo en Fortran 90. Sin embargo con elloperdemos las principales ventajas que incorpora el nuevo lenguaje.Captulo aparte merece el caso del manejo de tablas. En nuestro caso nos concentraremos en tablasunidimensionales y bidimensionales que se identifican con vectores y matrices. La nueva filosofa deFortran 90 consiste en el manejo de estas estructuras globalmente en lugar de elemento a elemento.Por ultimo conviene senalar que existe una actualizacion posterior que se conoce como Fortran 95. Sinembargo los cambios que incorpora son de una magnitud sensiblemente inferior a los desarrollados en laversion anterior

    Primeras ideas sobre la sintaxis.

    se emplea desde la columna inicial, a diferencia del Fortran 77 que dejaba las 6 primeras libres paraetiquetas y control de bucles.

    No se distingue entre mayusculas y minusculas. Hay compiladores que distinguen para los nombresde variables.

    ! indica una lnea de comentario. Todo lo que sigue no se compila.

    & se emplea para cortar una lnea. Se escribe al final de la lnea cortada y al principio de la siguiente.

    Estructura del programa.program nombre programadeclaracion de variablescuerpo del programaend program nombre programa

    Ejemplo

    ! mi primer programa en FORTRAN 90

    program primero ! arranque del programaimplicit none ! declaracion variablesreal :: x,y

    ! programaprint*,dame dos numeros realesread*,x,yprint*,su suma es,x+yprint*,Esta es una linea partida en dos,&

    & (x+(2*y)*x-y*y)/3.5

    end program primero ! final

    2

  • 2. Declaracion de variables y asignacion

    Tipos de constantes y variables:

    enteras (integer) de coma flotante (real) a simple y doble precision complejas (complex) a simple y doble precision caracter (character) logicas (logical): unicamente pueden adoptar los valores

    .TRUE. .FALSE

    La ordenimplicit none

    cancela un convenio implcito de declaracion de variables y obliga a declarar todas las variables

    Por defecto real y complex son de precision simple, pero depende del compilador.

    Ejemplo

    program asignacionesimplicit noneinteger :: i,jreal (kind=4) :: x,y ! declara variables de precision simplereal (kind=8) :: z,t ! precision doblecomplex :: u ! complex(kind=4) :: ucharacter (len=4) :: palabra ! (len=4) indica que tiene 4 caractereslogical :: test

    x=3.23e-4 ! asignacion de 3,23 104

    y=-2.312e2x=3.4y=4 ! esta asignacion incluye una conversion de entero a realz=3.23e-4 8 ! 8 indica que es doble precisiont=2. 8z=(3.e-1,2.) ! =0,3 + 2palabra=casa ! las comillas identifican las constantes caracterpalabra="Juan" ! tambien se usan las dobles comillastest=.TRUE.

    end program asignaciones

    Inicializacion 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 inicializacion no puede haber operaciones aritmeticas. Es aconsejable que nohaya conversiones automaticas (entero a real, etc).

    3

  • programa asignacionesimplicit nonereal :: x=4.,t,z=3.e-2 ! asigna valores de arranque a x y zreal (kind=8) :: u=6.e2 8complex :: 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.5print*,x es ,xprint*,da un valor a yread*,yprint*,valores de x e y,x,y...

    4. Operaciones numericas

    Binarias basicas. Suma, resta, producto, division y exponenciacion.

    + - * / **

    Tabla de tipos de datos y resultado.

    entero real dobleentero entero real doblereal real real realdoble doble real doble

    Funciones matematicas basicas. El argumento siempre se escribe entre parentesis.

    abs (valor absoluto o modulo)

    sqrt (raz cuadrada)

    exp (exponencial)

    log (logaritmo neperiano)

    log10

    sin

    cos

    tan

    4

  • asin

    acos

    atan

    sinh

    cosh

    tanh

    Otras.

    mod(i,j) da el resto de la division 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 partesEnterasreal :: x=2.3, y=-4.3, z=7.2 ! preasignadasinteger :: 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

    El programa precedente devolvera en pantalla:

    2 3 2-5 -4 -47.2 -5

    5. Estructuras de decision

    Operadores de comparacion. Notese la diferencia entre el igual de comparacion (==) y el de asigna-cion. El smbolo /= indica 6=.

    > < = == /=

    5

  • Operadores logicos. Son cuatro: y, o, o exclusivo, negacion.

    .AND. .OR. .XOR. .NOT.

    Simple de sentencia unica

    if (expresion logica) sentencia

    Simple de sentencia multiple

    if (expresion logica) thensentencia primerasentencia segunda...

    end if

    If-else

    if (...) then...

    else...

    end if

    Decision multiple

    if (...) then...

    else if (...) then...

    else if (...) then...

    else ! puede no estar...

    end if

    Puede haber estructuras anidadas.

    Ejemplo

    program decisionesimplicit nonereal :: x,yprint*,escribe x e yread*,x,yif (y0) then

    print*,x es positivoelse

    print*,x es negativoend ifif ((x>0 .AND. y>0).OR.(x

  • elseprint*,x*y es negativo o nulo

    end ifend program decisiones

    La orden select case. La sintaxis es

    select case (criterio) ! criterio devuelve un valor numericocase(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 casosimplicit noneinteger :: opreal :: x,y

    print*,elija una opcionread*,opselect case(op)

    case(1)print*,op=1read*,x

    case(2)print*,op=2read*,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 defaultprint*,op es cero

    end selectend program casos

    6. Estructuras de repeticion

    Estructura general

    do ndice = inicio, final, incrementosentencias

    end do

    7

  • Por defecto el incremento es 1.

    Puede haber bucles vacos (p.ej. con inicio menor que final e incremento negativo): no se haceninguna operacion.

    exit se puede emplear para forzar la salida del bucle.

    cycle se puede emplear para pasar directamente al comienzo de la siguiente repeticion del bucle.

    Ejemplo

    program repeticionesimplicit noneinteger :: i,opreal :: xdo i=10,1,-1

    print*, i**2 ! cuadrados de enteros del 10 al 1end dodo i=1,10

    print*,i**2 ! lo mismo del revesend dodo i=1,10,-1 ! bucle vaco

    print*,iend donombre : do i=1,10 ! bucle etiquetado

    print*,inserta xread*,xif (.NOT.x>=0) then

    print*,x es negativocycle ! se pasa de nuevo a la primera lnea, incrementando i

    end ifprint*,Otra vez? (1->si)read*,opif (op/=1) exit ! si op 6=1 se sale del bucle

    end do nombre ! cierre de bucle etiquetadoend program repeticiones

    7. Ficheros

    La instruccion basica de apertura de un fichero es

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

    donde:

    unidad es un numero entero que identificara al fichero mientras permanezca abierto 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

  • scratch cuando se trate de un fichero temporal de trabajo que se borrara al cerrarLas instrucciones

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

    sirven para escribir y leer en formato libre.

    La instruccion open dada abre ficheros de tipo texto. Se puede modificar para ficheros binarios (sinformato).

    El fichero se cierra con

    close(unidad)

    Ejemplo

    program ficherosimplicit nonereal :: a,binteger :: i,nopen(unit=1, file=datos.dat, status=old)open(unit=2, file=salida.res, status=replace)read(1,*) ndo i=1,n

    read(1,*) a,bwrite(2,*) a+b

    end doclose(1)close(2)end program ficheros

    Si el fichero datos.dat tiene la forma

    54. 2.6. 3.-2. 4.1. 1.2e-32. 1.1e2

    el fichero salida.res tendra la forma

    6.9.2.1.0012112.

    9

  • 8. Funciones

    En principio una funcion devuelve unicamente un valor.

    La sintaxis general es

    function nombredeclaracion de variablesinstruccionesreturnend function nombre

    nombre es la denominacion de la variable de salida y debe estar declarada con las demas.

    Puede haber mas de un return por funcion. El final es innecesario.

    Ejemplo

    program programaPrincipalimplicit noneinteger :: i,nreal :: x, f ! la funcion f se declara como otra variableprint*,inserta numero repeticionesread*,ndo i=1,n

    print*,escribe xread*,xprint*,f(x)print*,x+f(x)

    end doend program programaPrincipal

    function f(y)implicit nonereal :: y,f,z ! z es una variable localif (y>=0) then

    z=y**3f=z+z**2 ! f sera el valor de salida

    elsef=0

    end ifreturnend function f

    9. Subrutinas

    La sintaxis de una subrutina es

    subroutine nombre(arg1,..., argn)declaracion de variablesinstruccionesend subroutine nombre

    10

  • Todos los argumentos son, salvo que se indique lo contrario mediante los especificadores intent,de entrada y salida, es decir, su valor puede ser modificado en el transcurso de la ejecucion.

    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 programaPrincipalimplicit noneinteger :: i,jreal :: x,y,zprint*,introducir dos enteros y dos realesread*,i,j,x,ycall intercambia(i,j)print*,i,jcall 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 localw=uu=vv=wend 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 entradareal :: x,yreal, intent(out) :: zif ((i

  • 10. Vectores y matrices (1)

    Declaracion de matrices. Se hace en la declaracion de variables, utilizando el especificador dimension.Ejemplo

    ...real, dimension(10) :: b,c ! vectores de 10 componentesreal(kind=8), dimension(10,12) :: a ! matriz 10 12, doble precisionreal :: bb(10), cc(10,12) ! equivalente a poner dimensioninteger :: 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. Tambien, 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 operacionesreal :: a(10,10),b(10,10),c(10,10),v1(10),v2(10),t=3.,c1,c2integer :: i,jdo i=1,10

    do j=1,10a(i,j)=1./(i+j)

    end dov1(i)=i*6.5

    end dob=t*ac=a+bc=-cb=c*a ! producto elemento a elementov2=sin(v1)v1=t*v1+5*v2 ! combinacion linealend program operaciones

    Asignaciones y bucles implcitos. La asignacion 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,10b(i)=2*(i-2)-1

    end do

    o en un bucle implcito

    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)

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

    transpose(a) devuelve la traspuesta de adot product(a,b) calcula el producto escalar de dos vectores a y bmatmul(a,b) calcula el producto de dos matrices a y b;

    o el producto de una matriz a por un vector bsum(a) devuelve la suma de todos los elementos de aproduct(a) devuelve el producto de todos los elementos de amaxval(a) devuelve el maximo valor de aminval(a) devuelve el mnimo valor de amaxloc(a) devuelve un vector con la posicion relativa del maximo valor de a,

    esto es, la posicion en el array si todos los ndices arrancan en 1.minloc(a) idem con el mnimoshape(a) devuelve un vector con las dimensiones de a

    Ejemplo

    program normasVectorimplicit noneinteger :: p(1),ireal :: b(-1:5)b=(/ -1./9.,1.,((-3.)**(2*i),i=1,5) /)print*,sqrt(dot product(b,b)) ! norma 2print*,sum(abs(b)) ! norma 1print*,maxval(abs(b)) ! norma p=maxloc(abs(b)) ! posicion relativa del maximoprint*,pend program normasVector

    13

  • Filas y columnas. Si se tiene una matriz e i es un valor admisible del ndice

    a(i,:)

    es una referencia valida de la fila iesima, que se puede emplear como vector. De la misma forma

    a(:,i)

    sirve para emplear la columna iesima.Las ordenes de escritura y lectura se pueden hacer por filas, etc

    Ejemplo

    programa lecturaimplicit noneinteger :: ireal :: a(10,5), b(6)print*,Escribe un vector de seis componentesread*,bprint*,Escribe por filas una matriz 10 por 5do i=1,10

    read*, a(i,:)end doprint*,Esta es su traspuestado i=1,5

    print*,a(:,i)end doend program lectura

    Secciones de vectores y matrices. La idea anterior se puede generalizar a la seleccion de seccionesde matrices y vectores.

    Dada una matriz a de dimension 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).

    La sintaxis se puede complicar, tomando ndices que no se mueven consecutivamente, siguiendo elconvenio

    limiteInferior:limiteSuperior:incremento

    Ejemplo: Consideremos las matrices a1 y a2

    1 2 3 45 6 7 89 10 11 12

    -1 -2-3 -4-5 -6

    Entonces a(1:2,2:4) es la submatriz2 3 46 7 8

    La sentencia

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

    14

  • transforma a1 en1 2 3 4-3 -4 7 8-5 -6 11 12

    Ejemplo: dado el vector b3 2 1 -4 -6 -2 -2

    se tiene que b(2:5) es2 1 -4 -6

    mientras que b(6:2:-2) proporciona-2 -4 2

    Ejemplo

    ...print*,maxval( (/ sum( abs(a(i,:)) ),i=1,n) /) ) ! A = maxj

    i |aij |

    ...

    Ejemplo

    subroutine gauss(n,a,b,x)implicit noneinteger :: n,i,jreal :: a(n,n), b(n),x(n),creal :: aa(n,n+1) ! array local ajustado a tama~no exterioraa(1:n,1:n)=aaa(:,n+1)=b ! matriz ampliadado i=1,n ! eliminacion gaussiana

    do j=1,nc=aa(j,i)/aa(i,i)aa(j,i:n+1)=aa(j,i:n+1)-c*aa(i,i*n+1)

    end doend dodo i=n,1,-1 ! sustitucion regresiva

    x(i)=aa(i,n+1)-dot product(aa(i,i+1:n),x(i+1:n)) ! xi = bi n

    j=i+1 aijxjx(i)=x(i)/aa(i,i)

    end doend 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 matrizvector 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 52 4 6

    Si seguidamente hacemos

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

    obtenemos la matriz1 42 53 6

    13. Matrices y vectores (4)

    Secciones arbitrarias de matrices y vectores.

    Si

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

    entonces a(ind,:) selecciona las r filas 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 analoga 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 darproblemas 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 02 1 3 21 3 1 1

    2 1 2 -3 2

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

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

    -2 0 22 2 1

    mientras que b(ind) es2 -3 1

    Ejemplo. Con indi y indj los vectores de enteros dados respectivamente por

    2 4 3 1 5 2

    y a dada por1 2 3 -1 2-2 2 1 0 42 1 3 2 21 3 1 1 3

    la seccion a(indi,indj) es-2 4 21 3 32 2 1

    La instruccion

    a(indi,indj)=0

    transformara a en1 2 3 -1 20 0 1 0 00 0 3 2 00 0 1 1 0

    Declaracion dinamica. En FORTRAN 90 es posible declarar matrices y vectores sin asignarles susdimensiones, esperando a que se fijen durante el programa:

    El especificador allocatable en la declaracion de un array, con los ndices de dimensiones mudos,deja la cuestion de la asignacion de memoria en suspenso. No obstante, hay que decidir a priori enla declaracion el numero de ndices del array.

    Con allocate se asignan dimensiones.

    Con deallocate se deasignan dimensiones.

    Ejemplo

    program dinamicaimplicit nonereal, allocatable :: a(:,:), b(:) ! una matriz y un vectorinteger :: n,i,j,opdo j=1,10

    17

  • print*,dar dimensionread*,nallocate(a(n,2*n),b(2*n)) ! asignacion; ambas en la misma instruccionprint*,escribir matriz por filasdo i=1,n

    read*,a(i,:)end doprint*,escribir vectorread*,bprint*,su producto es:, matmul(a,b)deallocate(a,b) ! desasignacion de memoriaprint*,Otra vez? (1->Si)read*,opif(op/=1) exit

    end doend program dinamica

    14. Matrices y vectores en subrutinas

    La forma correcta de enviar una matriz a una subrutina es dando ademas las dimensiones de dichamatriz 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 lasubrutina se mantiene en el programa principal.

    Ejemplo

    program pruebaSubrutinaimplicit nonereal, allocatable :: a(:,:), b(:)integer :: i,j,n,mprint*,Escribir dimensiones de la matrizread*,m,nallocate(a(m,n),b(m))do i=1,m

    read*,a(i,:)end docall sumaColumnas(a,b,m,n)print*,bend program pruebaSubrutina

    subroutine sumaColumnas(a,b,k,l)implicit noneinteger :: k,l,ireal :: a(k,l),b(k)b=(/ (sum(a(i,:)), i=1,l) /) ! suma de los elementos de cada filaend subroutine sumaColumnas

    18

  • Lo anterior sigue siendo cierto si enviamos trozos compactos de matrices como argumento. En elejemplo anterior podamos haber puesto

    call sumaColumnas(a(1:m-2,1:n-1),b(1:m-2),m-2,n-1)

    Esto no funciona si se envan trozos de matrices con referencia mediante un conjunto de ndices. Sihacemos, por ejemplo,

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

    donde ind es un vector de mind numeros enteros, se envan copias de las secciones de a y b. Portanto, 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 matrizo vector auxiliar, llamar a la subrutina y al final volcar el resultado sobre la matriz o vector original.

    Ejemplo

    program pruebaSubrutinaimplicit nonereal, allocatable :: a(:,:), b(:), b2(:)integer :: i, j, n, m, mindinteger, allocatable :: ind(:)print*,Escribir dimensionesread*,m,nallocate(a(m,n),b(m))print*,Introducir la matriz por filasdo i=1,m

    read*,a(i,:)end doprint*,Cuantas filas quieres tener en cuenta?read*, mindallocate(b2(mind),ind(mind))print*,Escribir numeros de filasread*,indcall sumaColumnas(a(ind,:),b2,mind,n) ! la parte de a pasa por valorb(ind)=b2 ! las filas que no se tienen en cuenta dan un ceroprint*,bend program pruebaSubrutina

    Ejemplo

    subroutine GaussSeidel(a,b,x,n,itmax,tol)implicit noneinteger, intent(in) :: n,itmaxreal :: a(n,n),x(n),xold(n),b(n)real, intent(in) :: tolreal :: difx=0. ! arrancamos del vector nulodo it=1,itmax

    xold=xdo 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 lneax(i)=x(i)/a(i,i)

    end dodif=maxval(abs(x-old)) ! norma infinitoif (dif

  • end select opcionesend program prueba

    16. Modulos

    Modulos simples: contienen informacion como declaraciones de variables y parametros muy repetitivas.

    Construccion

    module nombreModuloinformacion...

    end module nombreModulo

    Utilizacion

    program/function/subroutine nombreParteuse nombreModulodeclaraciones de variablessentencias del programaend program/function/subroutine nombreParte

    Ejemplo

    module constantesreal, parameter :: pi=3.141592, euler=0.57721566end module constantes

    function g1(x)use constantesimplicit nonereal :: g1,xg1=cos(2*pi*x)end function g1

    function g2(x)implicit nonereal :: g2,xg2=(x-1.)**2end function g2

    Modulos librera: contienen funciones y subrutinas

    Construccion

    module moduloSegundocontains

    function nombreFuncion...end function nombreFuncionfunction otraFuncion...end function otraFuncion

    end module moduloSegundo

    21

  • Utilizacion: igual que antes

    Ejemplo

    module misfuncionescontains

    function g1(x)use constantesimplicit nonereal :: g1,xg1=cos(2*pi*x)end function g1

    function g2(x)implicit nonereal :: g2,xg2=(x-1.)**2end function g2

    end module misfunciones

    program prueba ! programa principaluse misfunciones ! no se declaran g1, g2implicit noneinteger :: num,opreal :: a,breal :: trapecio

    print*,Extremos del intervaloread*,a,bprint*,Numero de particionesread*,numprint*,Opcion:read*,opopciones : 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 comun.

    Forma:

    program/subroutine/function nombrePartetype nombreTipo

    declaraciones de identificadoresend type nombreTipodeclaraciones de otras variables

    22

  • type (nombreTipo) :: variablesConcretas....

    Ojo: hay que incluir la declaracion del tipo en todas las partes en que se use

    Ejemplo

    program pruebatipostype fecha

    integer :: dia, mes, anhoend type fechatype (fecha) :: mifechatype (fecha), external :: leefechainteger :: aux

    mifecha=leefecha()aux=mifecha %anhoaux=aux-100*(aux/100)print*,Mi fecha:,mifecha %dia,mifecha %mes,auxend program pruebatipos

    function leefecha() ! sin argumentostype fecha

    integer :: dia, mes, anhoend type fechatype (fecha) :: leefechaprint*,A~no:read*,leefecha %anhoprint*,Mes:read*,leefecha %mesprint*,Dia:read*,leefecha %diareturnend function leefecha

    Ejemplo

    module misEstructurastype fecha

    integer :: dia, mes, anhoend type fecha

    end module misEstructuras

    program pruebatiposuse misEstructurastype (fecha) :: mifechatype (fecha), external :: leefechainteger :: aux... ! sigue como antesend program pruebatipos

    23

  • function leefecha()use misEstructurastype (fecha) :: leefecha... ! sigue como antesend function leefecha

    Ejemplo

    module misEstructurastype fecha

    integer :: dia, mes, anhoend type fechatype datos

    type(fecha) :: nacimiento ! un tipo puede utilizar otros tiposcharacter(len=40) :: nombre, apellidosinteger :: dni

    end type datosend module misEstructuras

    program pruebatiposdetiposuse misEstructurastype (datos), allocatable :: lista(:)type (fecha), external :: leefechainteger :: i,numprint*,Cuantos datos?read*,numallocate(lista(num))do i=1,num

    print*,Nombreread (a40),lista(i) %nombreprint*,Apellidosread (a40),lista(i) %apellidoslista(i) %nacimiento=leefecha()

    end doprint*,Lista de a~nos de nacimientodo i=1,num

    print*,lista(i) %nacimiento %anhoend doend program pruebatiposdetipos

    18. Funciones con valores vectoriales

    FORTRAN 90 admite que una funcion devuelva un array de datos.Precaucion: tienen que estar declaradas bajo una estructura

    interface

    cada vez que se usen. La declaracion es un prototipo que aclara el tipo de variables y de resultado de lafuncion.

    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 pruebareal :: phi,x(2)interface

    function rotacion(x,ang)real :: ang,x(2),rotacion(2)end function

    end interfaceprint*,angulo de rotacionread*,phiprint*,vector que se quiere rotarread*,xx=rotacion(x,phi)print*,vector rotado=,xend 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 punteroimplicit nonereal,target ::aa,bbreal, pointer:: c,daa=4.bb=6.c=>aa ! c apunta a aad=>bb ! d apunta a bb

    print*,aa=,aa,bb=,bbprint*,valor apuntado por c,c,valor apuntado por d,dc=-6print*,aa=,aa,bb=,bbprint*,valor apuntado por c,c,valor apuntado por d,dc=>d ! c apunta a bb (a->d->bb)c=2print*,bb=,bb

    25

  • print*,valor apuntado por c,c,valor apuntado por d,dnullify(c) ! c no apunta a ninguna variableend program puntero

    El programa anterior da como salida en pantalla

    a= 4.000000 b= 6.000000valor apuntado por c 4.000000 valor apuntado por d 6.000000a= -6.000000 b= 6.000000valor apuntado por c -6.000000 valor apuntado por d 6.000000b= 2.000000valor apuntado por c 2.000000 valor apuntado por d 2.000000

    Las variables punteros pueden definirse para apuntar a estructuras mas complicadas: arrays y estructurasde datos.

    20. Ejemplo final

    Problema. Almacenamiento (y manipulacion) de matrices esencialmente vacas.

    Modelo sparse. 0 1,5 2,5 02 0 0 0,50 0,25 0 0

    real 1,5 2,5 2 0,5 0,25

    integer 1 1 2 2 3integer 2 3 1 4 2

    El formato debe guardar el tamano de la matriz original mas el numero de elementos no nulos (porcomodidad)

    Problema practico. El tipo de datos debe admitir longitudes por determinar. Pero no puede habernada allocatable:

    * en la definicion de un tipo de datos

    * como argumento de una subrutina o funcion

    Sustituir allocatable por pointer y hacer lo mismo. Por dentro, el programa cambia mucho; por fuera,no.

    Plan.

    Modulo con tipo sparse

    Subrutinas y funciones:

    leer matriz sparse pasar sparse a matriz pasar matriz a sparse multiplicar sparse por vector

    Crear un modulo con las interfaces de todo lo anterior

    Programa de prueba

    26

  • module cosassparsetype sparse

    integer :: nf,nc,nelreal, pointer :: matriz(:)integer, pointer :: fil(:), col(:)

    end type sparseend module cosassparse

    module funcionessparseinterface

    subroutine leersparse(u)use cosassparsetype(sparse) :: u

    end subroutine leersparsefunction sparser(v,dim)

    use cosassparsetype(sparse) :: sparserinteger,dimension(2) :: dimreal :: v(dim(1),dim(2))

    end function sparserfunction matriz(a)

    use cosassparsetype(sparse) :: areal :: matriz(a %nf,a %nc)

    end function matrizfunction sparseporvector(a,x,m)

    use cosassparseinteger :: mtype(sparse) :: areal :: x(m),sparseporvector(a %nf)

    end function sparseporvectorend interfaceend module funcionessparse

    subroutine leersparse(a)use cosassparsetype (sparse) :: ainteger :: n,iprint*,Numero elementos, filas, columnasread*,n,a %nf,a %nca %nel=nallocate(a %matriz(n),a %fil(n),a %col(n))do i=1,n

    read*,a %matriz(i),a %fil(i),a %col(i)end doend subroutine leersparse

    Nota. a entra sin tamano predefinido y sale con tamano asignado.

    function matriz(a)use cosassparsetype(sparse) :: areal :: matriz(a %nf,a %nc)integer :: imatriz=0.

    27

  • do i=1,a %nelmatriz(a %fil(i),a %col(i))=a %matriz(i)

    end doend function matriz

    function sparser(v,dim)use cosassparsetype(sparse) :: sparserinteger,dimension(2) :: dimreal :: 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+1sparser %matriz(cont)=v(i,j)sparser %fil(cont)=isparser %col(cont)=j

    end ifend do

    end doend function sparser

    function sparseporvector(a,x,m)use cosassparseinteger :: mtype(sparse) :: areal :: x(m),aux(a %nf),sparseporvector(a %nf)if (m /= a %nc) then

    print*,error de dimensionesreturn

    end ifaux=0do i=1,a %nel

    aux(a %fil(i))=aux(a %fil(i))+&& a %matriz(i)*x(a %fil(i))

    end dosparseporvector=auxend function sparseporvector

    program pruebasuse cosassparseuse funcionessparsetype (sparse) :: areal,allocatable :: bb(:,:),cc(:,:),x(:),y(:)

    allocate(bb(3,5),x(5),y(3))

    28

  • do i=1,3bb(i,i+2)=3.*ibb(i,i)=-1.*i

    end doa=sparser(bb,shape(bb))print*,a %matrizallocate(cc(a %nf,a %nc))cc=matriz(a)do i=1,size(cc,dim=1)

    print*,cc(i,:)end doprint* x=1.y=sparseporvector(a,x,5)print*,yend program pruebas

    29