Está en la página 1de 9

SUBPROGRAMAS Y MODULOS

Un problema se puede solucionar al dividir en subprogramas (o procedimientos)


separados, cada uno de los cuales lleva a cabo una tarea particular y bien definida.
Eso a menudo sucede que estos subprogramas pueden ser utilizados por muchos
programas "principales" diferentes, y de hecho, por diferentes usuarios del mismo
sistema de computación.
Fortran 90 le permite implementar estos subprogramas como funciones y subrutinas
que son independientes del programa principal. Por ejemplos, procedimientos para
realizar operaciones estadísticas o para clasificar elementos, o para encontrar la mejor
línea recta a través de un conjunto de puntos, o para resolver un sistema de
diferenciales ecuaciones.
Los subprogramas pueden ser internos o externos. Los procedimientos útiles se
pueden recopilar juntos como Bibliotecas. Estas colecciones se denominan módulos.
Programas principales (es decir, todo lo que tenemos vistos hasta ahora), los
subprogramas externos y los módulos se denominan unidades de programa.

SUBPROGRAMAS INTERNOS
Hay dos tipos de subprogramas: funciones y subrutinas. Primero veremos las
funciones. Ya hemos visto cómo utilizar algunas de las funciones intrínsecas que
proporciona Fortran 90, como SIN, COS, LOG, etc. Puede escribir sus propias
funciones, para usarlas de la misma manera en un programa.

EJEMPLO 1:

program RaizNewton
implicit none

integer :: Its = 0 ! contador de interacción


integer :: MaxIts = 20 ! interacciones máxima
logical :: Converged = .false. ! bandera de convergencia
real :: Eps = 1e-6 ! error máximo
real :: X = 2 ! iniciando
do while (.NOT. Converged .AND. Its < MaxIts)
X = X - F(X) / DF(X)
print*, X, F(X)
Its = Its + 1
Converged = abs( F(X) ) <= Eps
end do

if (Converged) then
print*, 'Newton converged'
else
print*, 'Newton diverged'
end if

contains
function F(X) ! subprograma F(X)
! problem is to solve f(x) = 0
real F, X
F = X ** 3 + X - 3
end function F
function DF(X) ! subprograma F(X)
! first derivative of f(x)
real DF, X
DF = 3 * X ** 2 + 1
end function DF
end program

****************************************************************************

Ejemplo 2:

¿Algo errado?
program factorial
implicit none
integer i
do i = 1, 10
print*, i, fact(i)
end do
contains
function fact( n )
integer fact, n, temp
temp = 1
do i = 2, n
temp = i * temp
end do
fact = temp
end function
end

¡Corregido!

program factorial
implicit none
integer i
do i = 1, 10
print*, i, fact(i)
end do

contains
function fact( n )
integer fact, n, temp
integer i ! declarar de nuevo i dentro de la función fact()
temp = 1
do i = 2, n
temp = i * temp
end do
fact = temp
end function
end

SUBRUTINAS INTERNAS
Las subrutinas son muy similares a las funciones. Las diferencias son:
• No hay ningún valor asociado con el nombre de una subrutina, por lo que no debe
declararse.
• Se invoca una subrutina con una instrucción CALL.
• La palabra clave SUBROUTINE se usa en la definición y la instrucción END.
• Una subrutina no necesita tener argumentos, en cuyo caso el nombre se escribe sin
paréntesis, p. ej.
CALL PLONK

Ejemplo 3: imprime una línea en la pantalla, usando la subrutina prettyline


implicit none
call prettyline(50,2) !llama a la subrutina
contains

subroutine prettyline(num, symbol )


integer i, num, symbol
character*80 line
do i = 1, num
line(i:i) = achar( symbol )
end do
print*, line
end subroutine
end
PROGRAMA PRINCIPAL
Cada programa completo debe tener uno y solo un programa principal, que tiene la
forma

SUBPROGRAMAS EXTERNOS
Un subprograma externo reside en un archivo separado del programa principal. Por lo
general, realizará una tarea específica, y es externo para ser accesible a muchos
programas de llamada diferentes. Aparte del encabezado y la sentencia END, un
subprograma es idéntico en apariencia a un programa:

Tenga en cuenta las diferencias pequeñas pero significativas entre los subprogramas
internos y externos:
• los subprogramas externos pueden contener ellos mismos subprogramas internos
(que solo serán accesible al subprograma externo mismo); Los subprogramas internos
no pueden contener subprogramas internos
• la palabra clave FUNCTION o SUBROUTINE es opcional en la instrucción END del
subprograma externo, pero obligatoria en la instrucción END del subprograma interno.
los nombres de todos los subprogramas externos deben especificarse en un
EXTERNAL
declaración, que debe ir después de cualquier declaración USE (Sección 8.5) o
IMPLÍCITA. Nombrar un subprograma externo como este asegura que está vinculado
como un subprograma externo, y hace que cualquier subprograma intrínseco con el
mismo nombre no disponible. Esta práctica se recomienda encarecidamente.

BLOQUES DE INTERFASE
Si el compilador va a generar llamadas a subprogramas correctamente, necesita saber
ciertas cosas sobre el subprograma: nombre, número y tipo de argumentos, etc. Esta
colección de información se llama la interfaz del subprograma. En el caso de
subprogramas intrínsecos, subprogramas internos y módulo subprogramas, la interfaz
siempre es conocida por el compilador, y se dice que es explícita.

Sin embargo, cuando el compilador genera una llamada a un subprograma externo,


esta información no es disponible, y la interfaz del subprograma debe estar implícita.

Hemos visto que la instrucción EXTERNAL en el programa de llamada es suficiente


para proporcionar al compilador con el nombre del subprograma externo, y esto
permite encontrarlo y vincularlo.
Sin embargo, la interfaz todavía está implícita y en casos más complicados (como con
opcionales o argumentos de palabras clave, como se explica a continuación) se
requiere más información para una interfaz satisfactoria. Fortran 90 tiene un
mecanismo, llamado bloque de interfaz, que permite que una interfaz explícita sea
hecho.

MODULOS
Recuerde que hay tres tipos de unidad de programa: un programa principal, un
subprograma externo y un módulo.
Un módulo se diferencia de un subprograma en dos aspectos importantes:
• un módulo puede contener más de un subprograma (llamado subprograma de
módulo);
• un módulo puede contener declaraciones y sentencias específicas que son
accesibles para todas unidades de programa que utilizan el módulo.
Los módulos también se compilan por separado.

En el siguiente ejemplo, la subrutina SWOP se coloca en un módulo MyUtils. Por el


bien de Ilustración, el módulo también declara un parámetro real Pi. El programa
principal ahora tiene una declaración USE MyUtils que hace que el módulo sea
accesible para él. Por tanto, el nombre Pi es conocido por programa principal El
programa principal modificado es:

USE MyUtils
IMPLICIT NONE
REAL A, B
READ*, A
B = Pi
CALL SWOP( A, B )
PRINT*, A, B
END

whilethe module(again saved in a separatefile)is

MODULE MyUtils
REAL, PARAMETER :: Pi = 3.1415927
CONTAINS
SUBROUTINE SWOP( X, Y )
REAL Temp, X, Y
Temp = X
X=Y
Y = Temp
END SUBROUTINE SWOP
END MODULE MyUtils

Forma general de un módulo:

MODULE name
[declaration statements]
[CONTAINS
module subprograms]
END [MODULE [name]]
SOLUCION DE ECUACIONES LINEALES

METODO DE REDUCCION DE GAUSS

Escriba los coeficientes del lado izquierdo como una matriz, con las constantes del
lado derecho como un vector unido a la matriz, separados por una línea vertical, así:

Esto es simplemente una abreviatura del conjunto original y, a veces, es una matriz
incrementada llamada matriz aumentada del sistema. Siempre que realicemos solo
operaciones de fila en los números, podemos omita los símbolos x, y y z cada vez.
Nos referiremos a la matriz aumentada como A.

Comenzamos con la primera fila (R 1) y la llamamos fila pivote. Llamamos al elemento


a11 (= 2) el elemento pivote. Divida toda la fila pivote por el elemento pivote, por lo que
la matriz aumentada ahora se ve así esta:

Las filas R2 y R3 ahora se denominan filas blancos. El objetivo es obtener ceros en


todas las filas blancos abajo (y arriba, si es necesario) el elemento pivote. Tome la fila
blanco R2. Reemplace cada elemento en la fila por sí misma restando el elemento
correspondiente en la fila pivote. La matriz ahora se ve así:

Ahora toma la fila de destino R3. Para reducir a31 a cero con una operación que
involucra la fila pivote R1 requiere reemplazar la fila de destino por sí misma menos la
fila de pivote multiplicada por a31 (¡teniendo en cuenta para la subsiguiente solución
informática que esta operación puede cambiar el valor de a31 en sí mismo!):
Ahora designamos R2 como la fila de pivote y el nuevo a a22 como el elemento de
pivote. El conjunto El procedimiento se repite, excepto que las filas de destino ahora
son R1 y R3, y el objeto es obtener ceros en estas dos filas por encima y por debajo del
elemento pivote. El resultado es:

Ahora tome R3 como fila pivote, con el nuevo a33 como elemento pivote y R 1 y R2 como
objetivo. filas. Después de repetir operaciones similares en ellos, la matriz finalmente
se ve así:

La solución es: x = 1, y = 0, z = 2.

La subrutina Gauss del programa de abajo realiza una reducción de Gauss en un


sistema de cualquier tamaño. La matriz aumentada que A es pasada como argumento.
Al ingresar, su columna de la derecha debe contener las constantes del lado derecho
de las ecuaciones. A su regreso, la columna más a la derecha contendrá la solución.
program gausstest
implicit none
real, dimension(:,:), allocatable :: a ! augmented matrix
integer i, j, n
print*, "how many equations?"
read*, n
allocate( a(n, n+1) ) ! extra column for rhs
print*, "enter augmented matrix by rows:"
read*, ((a(i,j), j = 1,n+1), i = 1,n)
call gauss( a )
print*
print*, "solution is in last column:"
do i = 1, n
print "(10f7.2)", (a(i,j), j = 1, n+1)
end do
contains
subroutine gauss( a )
real, dimension(:,:) :: a
real pivelt, tarelt
integer :: n ! number of equations
integer pivrow, tarrow
n = size( a, 1 )
do pivrow = 1, n ! process every row
pivelt = a( pivrow, pivrow ) ! choose pivot element
a( pivrow, 1:n+1 ) = a( pivrow, 1:n+1 ) / pivelt ! divide
! whole row
! now replace all other rows by target row minus pivot row ...
! ... times element in target row and pivot column:
do tarrow = 1, n
if (tarrow /= pivrow) then
tarelt = a( tarrow, pivrow )
a( tarrow, 1:n+1 ) = a( tarrow, 1:n+1 ) &
- a( pivrow, 1:n+1 ) * tarelt
end if
end do
end do
end subroutine gauss
end program gausstest

También podría gustarte