Aprendizaje Fortran
Aprendizaje Fortran
Aprendizaje Fortran
#fortran
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 2
Examples 2
Instalación o configuración 2
Hola Mundo 3
Ecuación cuadrática 4
Insensibilidad a la caja 5
Examples 6
Aritmética si declaración 7
Construcciones de OD no en bloque 8
Retorno alternativo 8
Bloques comunes 12
Asignado GOTO 13
GOTO computado 14
Funciones de sentencias 15
Capítulo 3: Arrays 17
Examples 17
Notación básica 17
Arreglos asignables 18
Constructores de matrices 18
Forma explícita 21
Forma asumida 21
Tamaño asumido 22
Forma diferida 22
Forma implícita 22
Arreglos enteros 23
Elementos de matriz 23
Secciones de matriz 23
Operaciones de matriz 25
Adición y sustracción 25
Función 25
Multiplicación y división 26
Operaciones matriciales 26
Tripletes de subíndices 27
Subíndices vectoriales 27
Examples 29
Si construir 29
Construcción de bloques DO 31
Donde construir 33
Capítulo 5: Extensiones de archivo fuente (.f, .f90, .f95, ...) y cómo se relacionan con e 35
Introducción 35
Examples 35
Extensiones y significados 35
Capítulo 6: I / O 37
Sintaxis 37
Examples 37
E / S simple 37
Examples 41
Capítulo 8: Interoperabilidad C 44
Examples 44
C structs en fortran 45
Observaciones 46
Examples 46
Sintaxis funcional 46
Declaración de devolución 47
Procedimientos recursivos 47
Observaciones 52
Examples 52
Examples 54
Tipo de Procedimientos 54
Extensión de tipo 56
Tipo constructor 57
Examples 59
Tipos intrinsecos 59
Constantes literales 64
Declaración y atributos. 67
Examples 69
Programas de fortran 69
Módulos y submódulos. 70
Procedimientos externos 70
Subprogramas internos 71
Examples 74
Módulos intrínsecos 76
Control de acceso 76
Creditos 80
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: fortran
It is an unofficial and free Fortran ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official Fortran.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@zzzprojects.com
https://riptutorial.com/es/home 1
Capítulo 1: Empezando con Fortran
Observaciones
Fortran es un lenguaje utilizado ampliamente en la comunidad científica debido a su idoneidad
para el cálculo numérico. Particularmente atractiva es su intuitiva notación matricial, que facilita la
escritura de cómputos vectorizados rápidos.
Versiones
Examples
Instalación o configuración
Fortran es un lenguaje que puede compilarse utilizando compiladores suministrados por muchos
proveedores. Diferentes compiladores están disponibles para diferentes plataformas de hardware
y sistemas operativos. Algunos compiladores son software libre, algunos se pueden utilizar de
forma gratuita y otros requieren la compra de una licencia.
El compilador gratuito más común de Fortran es GNU Fortran o gfortran. El código fuente está
disponible en GNU como parte de GCC, la colección del compilador GNU. Los binarios para
muchos sistemas operativos están disponibles en https://gcc.gnu.org/wiki/GFortranBinaries . Las
distribuciones de Linux a menudo contienen gfortran en su gestor de paquetes.
https://riptutorial.com/es/home 2
• Oracle Developer Studio
En los sistemas HPC, a menudo hay compiladores especializados disponibles por el proveedor
del sistema como, por ejemplo, los compiladores IBM o Cray .
Todos estos compiladores soportan el estándar Fortran 95. ACM Fortran Forum ofrece una
descripción general sobre el estado de Fortran 2003 y el estado de Fortran 2008 de varios
compiladores y está disponible en la Wiki de Fortran.
Hola Mundo
Cualquier programa de Fortran tiene que incluir el end como última declaración. Por lo tanto, el
programa Fortran más simple se ve así:
end
Para mayor claridad, ahora es común usar la declaración del program para iniciar un programa y
darle un nombre. La declaración end puede referirse a este nombre para que sea obvio a qué se
refiere, y permitir que el compilador verifique que el código sea correcto. Además, todos los
programas de Fortran deben incluir una declaración implicit none . Por lo tanto, un programa
mínimo de Fortran debería tener el siguiente aspecto:
program hello
implicit none
write(*,*) 'Hello world!'
end program hello
El siguiente paso lógico a partir de este punto es cómo ver el resultado del programa hello world.
Esta sección muestra cómo lograr eso en un entorno similar a Linux. Suponemos que tiene
algunas nociones básicas de los comandos de shell , principalmente sabe cómo llegar al terminal
de shell. También asumimos que ya ha configurado su entorno fortran . Utilizando su editor de
texto preferido (notepad, notepad ++, vi, vim, emacs, gedit, kate, etc.), guarde el programa de
saludo de arriba (copie y pegue) en un archivo llamado hello.f90 en su directorio de inicio.
hello.f90
https://riptutorial.com/es/home 3
es su archivo fuente. Luego vaya a la línea de comandos y navegue hasta el directorio
(¿directorio de inicio?) Donde guardó su archivo fuente, luego escriba el siguiente comando:
Acabas de crear tu programa ejecutable hello world. En términos técnicos, acaba de compilar su
programa. Para ejecutarlo, escriba el siguiente comando:
>./hello
Ecuación cuadrática
Hoy en día Fortran se utiliza principalmente para el cálculo numérico. Este ejemplo muy simple
ilustra la estructura básica del programa para resolver ecuaciones cuadráticas:
program quadratic
!a comment
real :: a, b, c
real :: discriminant
real :: x1, x2
if ( discriminant>0 ) then
x1 = ( -b + sqrt(discriminant)) / (2 * a)
x2 = ( -b - sqrt(discriminant)) / (2 * a)
print *, "Real roots:"
print *, x1, x2
x1 = - b / (2 * a)
print *, "Real root:"
print *, x1
else
https://riptutorial.com/es/home 4
end program quadratic
Insensibilidad a la caja
Las letras mayúsculas y minúsculas del alfabeto son equivalentes en el conjunto de caracteres de
Fortran. En otras palabras, Fortran no distingue entre mayúsculas y minúsculas . Este
comportamiento está en contraste con los lenguajes que distinguen entre mayúsculas y
minúsculas, como C ++ y muchos otros.
Como consecuencia, las variables a y A son la misma variable. En principio se podría escribir un
programa de la siguiente manera
pROgrAm MYproGRaM
..
enD mYPrOgrAM
https://riptutorial.com/es/home 5
Capítulo 2: Alternativas modernas a las
características históricas.
Examples
Tipos de variables implícitas
Cuando Fortran se desarrolló originalmente, la memoria era muy importante. Las variables y los
nombres de los procedimientos podrían tener un máximo de 6 caracteres, y las variables a
menudo se escribían de forma implícita . Esto significa que la primera letra del nombre de la
variable determina su tipo.
program badbadnotgood
j = 4
key = 5 ! only the first letter determines the type
x = 3.142
print*, "j = ", j, "key = ", key, "x = ", x
end program badbadnotgood
Incluso puede definir sus propias reglas implícitas con la declaración implicit :
program oops
real :: somelongandcomplicatedname
...
call expensive_subroutine(somelongandcomplEcatedname)
end program oops
https://riptutorial.com/es/home 6
Este programa estará felizmente ejecutado y hará lo incorrecto.
program much_better
implicit none
integer :: j = 4
real :: x = 3.142
print*, "j = ", j, "x = ", x
end program much_better
Si no hubiéramos usado implicit none en el programa oops arriba, el compilador se habría dado
cuenta de inmediato y produjo un error.
Aritmética si declaración
La instrucción aritmética if permite usar tres ramas dependiendo del resultado de una expresión
aritmética
Esta instrucción if transfiere el flujo de control a una de las etiquetas de un código. Si el resultado
de arith_expr es negativo, label1 está involucrado, si el resultado es cero, se usa label2 y si el
resultado es positivo, se aplica la última label3 . Aritmética if requiere las tres etiquetas, pero
permite la reutilización de las etiquetas, por lo tanto, esta declaración se puede simplificar a una
rama dos if .
Ejemplos:
Ahora esta función es obsoleta con la misma funcionalidad ofrecida por el if declaración y if-else
construcción. Por ejemplo, el fragmento.
if (X<0) then
print*, "Negative"
else if (X==0) then
print*, "Zero"
https://riptutorial.com/es/home 7
else
print*, "Positive"
end if
Un sustituto if de
tal vez
Construcciones de OD no en bloque
integer i
do 100, i=1, 5
100 print *, i
integer i
do 100 i=1,5
print *, i
100 continue
integer i
do i=1,5
print *, i
end do
Retorno alternativo
El rendimiento alternativo es una facilidad para controlar el flujo de ejecución en el retorno desde
una subrutina. A menudo se utiliza como una forma de manejo de errores:
real x
https://riptutorial.com/es/home 8
100 print*, "Negative input value"
stop
end
subroutine sub(x, i, *, *)
real, intent(out) :: x
integer, intent(in) :: i
if (i<0) return 1
if (i>10) return 2
x = i
end subroutine
El retorno alternativo está marcado por los argumentos * en la lista de argumentos ficticios de
subrutina.
En la declaración de call anterior *100 y *200 refieren a las declaraciones etiquetadas 100 y 200
respectivamente.
real x
integer status
end
status = 0
https://riptutorial.com/es/home 9
if (i<0) then
status = 1
else if (i>10)
status = 2
else
x = i
end if
end subroutine
Fortran originalmente fue diseñado para un formato de formato fijo basado en una tarjeta
perforada de 80 columnas:
Estos fueron creados en una máquina perforadora de tarjetas, muy similar a esto:
El formato, como se muestra en la tarjeta de muestra ilustrada, tenía las primeras cinco columnas
reservadas para las etiquetas de estados de cuenta. La primera columna se usó para denotar los
comentarios mediante una letra C. La sexta columna se usó para denotar una continuación de la
https://riptutorial.com/es/home 10
declaración (insertando cualquier carácter que no sea un cero '0'). Las últimas 8 columnas se
usaron para la identificación y secuenciación de las tarjetas, ¡lo cual fue muy valioso si dejaste
caer el mazo de cartas en el suelo! La codificación de caracteres para tarjetas perforadas tenía
solo un conjunto limitado de caracteres y solo estaba en mayúsculas. Como resultado, los
programas de Fortran se parecían a esto:
El carácter de espacio también se ignoró en todas partes, excepto dentro de una constante de
carácter Hollerith (como se muestra arriba). Esto significaba que los espacios podían aparecer
dentro de palabras y constantes reservadas, o se podían perder por completo. Esto tuvo el efecto
secundario de algunas afirmaciones bastante engañosas como:
DO 1 I = 1.0
DO1I = 1,0
Fortran moderno ahora no requiere esta forma fija de entrada y permite la forma libre usando
cualquier columna. Los comentarios ahora están indicados por un ! que también se puede añadir
a una línea de declaración. Los espacios ahora no están permitidos en ningún lugar y deben
usarse como separadores, como en la mayoría de los otros idiomas. El programa anterior se
podría escribir en Fortran moderno como:
Aunque la continuación de estilo antiguo ya no se usa, el ejemplo anterior ilustra que todavía se
producirán declaraciones muy largas. Modern Fortran usa un símbolo & al final y al comienzo de la
continuación. Por ejemplo, podríamos escribir lo anterior en una forma más legible:
https://riptutorial.com/es/home 11
Bloques comunes
En las primeras formas de Fortran, el único mecanismo para crear un almacén de variables global
visible desde subrutinas y funciones es usar el mecanismo de bloque COMMON . Esto permitió que
las secuencias de variables fueran nombres y se compartieran en común.
Además de los bloques comunes con nombre, también puede haber un bloque común en blanco
(sin nombre).
common i, j
mientras que las variables bloque nombradas podrían ser declaradas como
common /variables/ i, j
Como ejemplo completo, podríamos imaginar una tienda de almacenamiento dinámico utilizada
por rutinas que pueden agregar y eliminar valores:
PROGRAM STACKING
COMMON /HEAP/ ICOUNT, ISTACK(1023)
ICOUNT = 0
READ *, IVAL
CALL PUSH(IVAL)
CALL POP(IVAL)
END
SUBROUTINE PUSH(IVAL)
COMMON /HEAP/ ICOUNT, ISTACK(1023)
ICOUNT = ICOUNT + 1
ISTACK(ICOUNT) = IVAL
RETURN
END
SUBROUTINE POP(IVAL)
COMMON /HEAP/ ICOUNT, ISTACK(1023)
IVAL = ISTACK(ICOUNT)
ICOUNT = ICOUNT - 1
RETURN
END
Las declaraciones comunes se pueden usar para declarar implícitamente el tipo de una variable y
para especificar el atributo de dimension . Este comportamiento solo es a menudo una fuente
suficiente de confusión. Además, la asociación de almacenamiento implícita y los requisitos para
definiciones repetidas en las unidades del programa hacen que el uso de bloques comunes sea
propenso a errores.
Finalmente, los bloques comunes están muy restringidos en los objetos que contienen. Por
ejemplo, una matriz en un bloque común debe ser de tamaño explícito; objetos asignables no
pueden ocurrir; Los tipos derivados no deben tener inicialización por defecto.
https://riptutorial.com/es/home 12
En Fortran moderno, este uso compartido de variables se puede manejar mediante el uso de
módulos . El ejemplo anterior se puede escribir como:
module heap
implicit none
! In Fortran 2008 all module variables are implicitly saved
integer, save :: count = 0
integer, save :: stack(1023)
end module heap
program stacking
implicit none
integer val
read *, val
call push(val)
call pop(val)
contains
subroutine push(val)
use heap, only : count, stack
integer val
count = count + 1
stack(count) = val
end subroutine push
subroutine pop(val)
use heap, only : count, stack
integer val
val = stack(count)
count = count - 1
end subroutine pop
end program stacking
• Los objetos en bloques comunes nombrados pueden definirse inicialmente; Los objetos en
blanco no serán comunes.
• los objetos en bloques comunes en blanco se comportan como si el bloque común tuviera el
atributo de save ; los objetos en bloques comunes nombrados sin el atributo de save pueden
volverse indefinidos cuando el bloque no está en el alcance de una unidad de programa
activa
Este último punto puede contrastarse con el comportamiento de las variables del módulo en el
código moderno. Todas las variables de módulo en Fortran 2008 se guardan implícitamente y no
se vuelven indefinidas cuando el módulo queda fuera del alcance. Antes de que las variables del
módulo Fortran 2008, como las variables en bloques comunes con nombre, también se volvieran
indefinidas cuando el módulo quedaba fuera del alcance.
Asignado GOTO
El GOTO asignado utiliza una variable entera a la que se asigna una etiqueta de declaración
utilizando la instrucción ASSIGN.
https://riptutorial.com/es/home 13
100 CONTINUE
...
...
GOTO ILABEL
GOTO computado
El GOTO computado permite la bifurcación del programa según el valor de una expresión entera.
Ejemplo:
ivar = 2
...
Antes de Fortran 95 era posible usar formatos asignados para entrada o salida. Considerar
integer i, fmt
read *, i
print fmt, i
https://riptutorial.com/es/home 14
end
La declaración de assign asigna una etiqueta de declaración a una variable entera. Esta variable
entera se usa más tarde como el especificador de formato en la declaración de print .
integer i
read *, i
if (i<100000) then
print 100, i
else
print 200, i
end if
end
integer i
read *, i
fmt=>big_fmt
if (i<100000) fmt=>small_fmt
print fmt, i
end
Funciones de sentencias
Considerar el programa
implicit none
integer f, i
f(i)=i
print *, f(1)
end
Dicha función de declaración existe dentro del alcance en el que se define. En particular, tiene
acceso a variables y constantes con nombre accesibles en ese ámbito.
https://riptutorial.com/es/home 15
Sin embargo, las funciones de declaración están sujetas a muchas restricciones y son
potencialmente confusas (mirando a simple vista como una instrucción de asignación de
elementos de matriz). Las restricciones importantes son:
Los beneficios principales de las funciones de sentencias son repetidos por las funciones
internas.
implicit none
print *, f(1)
contains
end
Las funciones internas no están sujetas a las restricciones mencionadas anteriormente, aunque
quizás vale la pena señalar que un subprograma interno puede no contener un subprograma
interno adicional (pero puede contener una función de declaración).
Las funciones internas tienen su propio alcance, pero también tienen una asociación de host
disponible.
1En los ejemplos de código antiguo anterior, no sería extraño ver que los argumentos ficticios de
una función de declaración se escriben de forma implícita, incluso si el resultado tiene un tipo
explícito.
https://riptutorial.com/es/home 16
Capítulo 3: Arrays
Examples
Notación básica
Cualquier tipo se puede declarar como una matriz utilizando el atributo de dimensión o
simplemente indicando directamente la dimension o dimension de la matriz:
Fortran almacena matrices en orden de columnas mayores . Es decir, los elementos de la bar se
almacenan en la memoria de la siguiente manera:
bar(1, 1), bar(2, 1), bar(3, 1), bar(4, 1), bar(1, 2), bar(2, 2), ...
Esto declara una matriz de forma (6, 3) , cuyo primer elemento son los geese(7, -3) .
Los límites inferior y superior a lo largo de las 2 (o más) dimensiones pueden accederse mediante
las funciones intrínsecas ubound y lbound . De hecho, lbound(geese,2) devolvería -3 , mientras que
ubound(geese,1) devolvería 12 .
https://riptutorial.com/es/home 17
Se puede acceder al tamaño de una matriz mediante el size función intrínseca. Por ejemplo,
size(geese, dim = 1) devuelve el tamaño de la primera dimensión que es 6.
Arreglos asignables
deallocate(foo)
Si por alguna razón falla una instrucción de allocate , el programa se detendrá. Esto se puede
evitar si el estado se comprueba mediante la palabra clave stat :
allocate(geese(17), stat=status)
if (stat /= 0) then
print*, "Something went wrong trying to allocate 'geese'"
stop 1
end if
status es una variable entera cuyo valor es 0 si la asignación o desasignación fue exitosa.
Constructores de matrices
Se puede crear un valor de matriz de rango 1 utilizando un constructor de matriz , con la sintaxis
(/ ... /)
[ ... ]
https://riptutorial.com/es/home 18
La forma [...] se introdujo en Fortran 2003 y generalmente es considerado como más fáciles de
interpretar, sobre todo en expresiones complejas. Este formulario se utiliza exclusivamente en
este ejemplo.
Los valores que aparecen en un constructor de matriz pueden ser valores escalares, valores de
matriz o bucles implícitos.
Los parámetros de tipo y tipo de la matriz construida coinciden con los de los valores en el
constructor de matriz
integer i
[1, (i, i=2, 5), 6] ! A rank-1 length-6 array of default integer type with an implied-do
En los formularios anteriores, todos los valores dados deben ser del mismo tipo y tipo de
parámetro. Los tipos de mezcla, o parámetros de tipo, no están permitidos. Los siguientes
ejemplos no son válidos.
Para construir una matriz utilizando diferentes tipos, se dará una especificación de tipo para la
matriz
Esta última forma para matrices de caracteres es especialmente conveniente para evitar el
espacio de relleno, como la alternativa
y para tipos parametrizados por longitud, el parámetro de longitud puede ser asumido
https://riptutorial.com/es/home 19
La especificación de tipo también se requiere en la construcción de matrices de longitud cero.
Desde
los parámetros de tipo y tipo no se pueden determinar a partir del conjunto de valores no
existentes. Para crear una matriz de enteros por defecto de longitud cero:
[integer :: ]
Los constructores de matrices construyen solo matrices de rango 1. A veces, como al establecer
el valor de una constante nombrada, también se requieren arreglos de rango más alto en una
expresión. Las matrices de rango más alto se pueden tomar del resultado de la reshape con una
matriz de rango 1 construida
En un constructor de matriz, los valores de la matriz en orden de elementos con cualquier matriz
en la lista de valores es como si los elementos individuales se dieran en orden de elementos de
matriz. Así, el ejemplo anterior
es equivalente a
En general, los valores en el constructor pueden ser expresiones arbitrarias, incluidos los
constructores de matrices anidadas. Para que un constructor de matriz de este tipo cumpla ciertas
condiciones, como ser una expresión constante o de especificación, las restricciones se aplican a
los valores constituyentes.
SPREAD(0, 1, 10)
https://riptutorial.com/es/home 20
El atributo de dimension en un objeto especifica que ese objeto es una matriz. Hay, en Fortran
2008, cinco naturalezas de matrices: 1
• forma explícita
• forma asumida
• tamaño asumido
• forma diferida
• forma implícita
integer a, b, c
dimension(5) a ! Explicit shape (default lower bound 1), extent 5
dimension(:) b ! Assumed or deferred shape
dimension(*) c ! Assumed size or implied shape array
Con estos se puede ver que se requiere un contexto adicional para determinar completamente la
naturaleza de una matriz.
Forma explícita
Una matriz de forma explícita es siempre la forma de su declaración. A menos que la matriz se
declare como local a un subprograma o construcción de block , los límites que definen la forma
deben ser expresiones constantes. En otros casos, una matriz de forma explícita puede ser un
objeto automático, utilizando extensiones que pueden variar en cada invocación de un
subprograma o block .
subroutine sub(n)
integer, intent(in) :: n
integer a(5) ! A local explicit shape array with constant bound
integer b(n) ! A local explicit shape array, automatic object
end subroutine
Forma asumida
Una matriz de forma asumida es un argumento ficticio sin el atributo allocatable o pointer . Dicha
matriz toma su forma del argumento real con el que está asociada.
contains
subroutine sub(x)
integer x(:) ! Assumed shape dummy argument
end subroutine sub
end
https://riptutorial.com/es/home 21
Cuando un argumento ficticio ha tomado forma, el alcance que hace referencia al procedimiento
debe tener una interfaz explícita disponible para ese procedimiento.
Tamaño asumido
Una matriz de tamaño asumido es un argumento ficticio que tiene su tamaño asumido a partir de
su argumento real.
subroutine sub(x)
integer x(*) ! Assumed size array
end subroutine
Las matrices de tamaños asumidos se comportan de manera muy diferente a las matrices de
formas asumidas y estas diferencias se documentan en otra parte.
Forma diferida
Una matriz de forma diferida es una matriz que tiene el atributo allocatable o pointer . La forma
de dicha matriz está determinada por su asignación o asignación de puntero.
Forma implícita
Una matriz de formas implícita es una constante con nombre que toma su forma de la expresión
utilizada para establecer su valor
1 Una Especificación Técnica que extiende Fortran 2008 agrega una sexta naturaleza de matriz:
rango asumido. Esto no está cubierto aquí.
integer, dimension(5) :: a
integer, dimension(:) :: b
integer, dimension(*) :: c
integer a(5)
https://riptutorial.com/es/home 22
integer b(:)
integer c(*)
real x(10)
1. Toda la matriz x ;
2. Elementos de matriz, como x(1) ;
3. Arreglo de secciones, como x(2:6) .
Arreglos enteros
En la mayoría de los casos, toda la matriz x refiere a todos los elementos de la matriz como una
sola entidad. Puede aparecer en sentencias ejecutables, como print *, SUM(x) , print *, SIZE(x)
o x=1 .
Una matriz completa puede hacer referencia a matrices que no tienen forma explícita (como x
arriba):
function f(y)
real, intent(out) :: y(:)
real, allocatable :: z(:)
Una matriz de tamaño supuesto también puede aparecer como una matriz completa, pero solo en
circunstancias limitadas (para ser documentada en otra parte).
Elementos de matriz
Se hace referencia a un elemento de la matriz para dar índices enteros, uno para cada rango de
la matriz, que denota la ubicación en la matriz completa:
real x(5,2)
x(1,1) = 0.2
x(2,4) = 0.3
Secciones de matriz
https://riptutorial.com/es/home 23
Una sección de matriz es una referencia a una serie de elementos (quizás solo uno) de una
matriz completa, utilizando una sintaxis que involucra dos puntos:
real x(5,2)
x(:,1) = 0. ! Referring to x(1,1), x(2,1), x(3,1), x(4,1) and x(5,1)
x(2,:) = 0. ! Referring to x(2,1), x(2,2)
x(2:4,1) = 0. ! Referring to x(2,1), x(3,1) and x(4,1)
x(2:3,1:2) = 0. ! Referring to x(2,1), x(3,1), x(2,2) and x(3,2)
x(1:1,1) = 0. ! Referring to x(1,1)
x([1,3,5],2) = 0. ! Referring to x(1,2), x(3,2) and x(5,2)
La forma final anterior utiliza un subíndice vectorial . Esto está sujeto a una serie de restricciones
más allá de otras secciones de la matriz.
Cada sección de matriz es en sí misma una matriz, incluso cuando solo se hace referencia a un
elemento. Eso es x(1:1,1) es una matriz de rango 1 y x(1:1,1:1) es una matriz de rango 2.
Las secciones de matriz en general no tienen un atributo de toda la matriz. En particular, donde
la asignación
x(:) = [1,2,3,4,5] ! This is bad when x isn't the same shape as the right-hand side
no está permitido: x(:) , aunque una sección de matriz con todos los elementos de x , no es una
matriz asignable.
x(:) = [5,6,7,8]
type t
real y(5)
end type t
type(t) x(2)
https://riptutorial.com/es/home 24
x%y(1) ! An array section
x(1)%y(:) ! An array section
x([1,2]%y(1) ! An array section
x(1)%y(1:1) ! An array section
En tales casos, no se nos permite tener más de una parte de la referencia que consiste en una
matriz de rango 1. Lo siguiente, por ejemplo, no está permitido
Operaciones de matriz
Debido a sus objetivos computacionales, las operaciones matemáticas en matrices son sencillas
en Fortran.
Adición y sustracción
Las operaciones en matrices de la misma forma y tamaño son muy similares al álgebra matricial.
En lugar de recorrer todos los índices con bucles, se puede escribir suma (y resta):
real, dimension(2,3) :: A, B, C
real, dimension(5,6,3) :: D
A = 3. ! Assigning single value to the whole array
B = 5. ! Equivalent writing for assignment
C = A + B ! All elements of C now have value 8.
D = A + B ! Compiler will raise an error. The shapes and dimensions are not the same
integer :: i, j
real, dimension(3,2) :: Mat = 0.
real, dimension(3) :: Vec1 = 0., Vec2 = 0., Vec3 = 0.
i = 0
j = 0
do i = 1,3
do j = 1,2
Mat(i,j) = i+j
enddo
enddo
Vec1 = Mat(:,1)
Vec2 = Mat(:,2)
Vec3 = Mat(1:2,1) + Mat(2:3,2)
Función
De la misma manera, la mayoría de las funciones intrínsecas se pueden usar de forma implícita
asumiendo una operación de componentes (aunque esto no es sistemático):
real, dimension(2) :: A, B
https://riptutorial.com/es/home 25
A(1) = 6
A(2) = 44 ! Random values
B = sin(A) ! Identical to B(1) = sin(6), B(2) = sin(44).
Multiplicación y división
Se debe tener cuidado con el producto y la división: las operaciones intrínsecas que usan * y /
son símbolos en forma elemental:
real, dimension(2) :: A, B, C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = A*B ! Returns C(1) = 2*1 and C(2) = 4*3
Operaciones matriciales
Las operaciones matriciales son procedimientos intrínsecos. Por ejemplo, el producto matricial de
las matrices de la sección anterior se escribe de la siguiente manera:
real, dimension(2,1) :: A, B
real, dimension(1,1) :: C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = matmul(transpose(A),B) ! Returns the scalar product of vectors A and B
real, dimension(3,3) :: A, B, C
A(:) = 4
B(:) = 5
C = matmul(transpose(A),matmul(B,matmul(A,transpose(B)))) ! Equivalent to A^t.B.A.B^T
real x(10)
x(:) = 0.
https://riptutorial.com/es/home 26
x(2:6) = 1.
x(3:4) = [3., 5.]
Sin embargo, las secciones de matriz pueden ser más generales que esto. Pueden tomar la forma
de tripletes de subíndice o subíndices vectoriales.
Tripletes de subíndices
Un subíndice triple toma la forma [bound1]:[bound2][:stride] . Por ejemplo
real x(10)
x(1:10) = ... ! Elements x(1), x(2), ..., x(10)
x(1:) = ... ! The omitted second bound is equivalent to the upper, same as above
x(:10) = ... ! The omitted first bound is equivalent to the lower, same as above
x(1:6:2) = ... ! Elements x(1), x(3), x(5)
x(5:1) = ... ! No elements: the lower bound is greater than the upper
x(5:1:-1) = ... ! Elements x(5), x(4), x(3), x(2), x(1)
x(::3) = ... ! Elements x(1), x(4), x(7), x(10), assuming omitted bounds
x(::-3) = ... ! No elements: the bounds are assumed with the first the lower, negative
stride
Cuando se especifica un paso (que no debe ser cero), la secuencia de elementos comienza con
el primer límite especificado. Si la zancada es positiva (resp. Negativa), los elementos
seleccionados siguiendo una secuencia incrementada (resp. Decrementada) por la zancada hasta
que el último elemento no sea mayor (resp. Más pequeño) que el segundo límite se toma. Si se
omite el paso, se trata como si fuera uno.
Cabe señalar que x(10:1:-1) no es lo mismo que x(1:10:1) aunque cada elemento de x aparezca
en ambos casos.
Subíndices vectoriales
Un subíndice vectorial es una matriz de enteros de rango 1. Esto designa una secuencia de
elementos correspondientes a los valores de la matriz.
real x(10)
integer i
x([1,6,4]) = ... ! Elements x(1), x(6), x(4)
x([(i,i=2,4)]) = ... ! Elements x(2), x(3) and x(4)
print*, x([2,5,2]) ! Elements x(2), x(5) and x(2)
Una sección de matriz con un subíndice vectorial está restringida en la forma en que se puede
usar:
• puede que no sea un argumento asociado con un argumento ficticio que se define en el
procedimiento;
https://riptutorial.com/es/home 27
• puede que no sea el objetivo en una instrucción de asignación de puntero;
• puede que no sea un archivo interno en una declaración de transferencia de datos.
Además, tal sección de matriz puede no aparecer en una declaración que implique su definición
cuando el mismo elemento se selecciona dos veces. Desde arriba:
real x(5,2)
print*, x(::2,2:1:-1) ! Elements x(1,2), x(3,2), x(5,2), x(1,1), x(3,1), x(5,1)
https://riptutorial.com/es/home 28
Capítulo 4: Control de ejecución
Examples
Si construir
dónde,
Un nombre de construcción al comienzo de una instrucción if then debe tener el mismo valor que
el nombre de construcción al end if instrucción end if , y debe ser único para la unidad de
alcance actual.
En las sentencias if , las ecuaciones (in) y las expresiones lógicas que evalúan una sentencia se
pueden utilizar con los siguientes operadores:
Ejemplos:
https://riptutorial.com/es/home 29
endif
! named if construct
circle: if (r >= 0) then
l = 2 * pi * r
end if circle
dónde,
Ejemplos:
https://riptutorial.com/es/home 30
case default
print "Something strange is happened"
end select
En este ejemplo, (:-1) valor de un caso es un rango de valores que coincide con todos los
valores menores que cero, (0) coincide con los ceros, y (1:) coincide con todos los valores por
encima de cero, la sección default incluye si otras secciones lo hicieron sin ejecutar.
Construcción de bloques DO
Una construcción do es una construcción de bucle que tiene una serie de iteraciones gobernadas
por un control de bucle
integer i
do i=1, 5
print *, i
end do
print *, i
En la forma anterior, la variable de bucle i pasa a través del bucle 5 veces, tomando los valores
de 1 a 5 por turno. Una vez que la construcción ha completado, la variable de bucle tiene el valor
6, es decir, la variable de bucle se incrementa una vez más después de completar el bucle .
El bucle comienza con i con el valor first , incrementando cada iteración por step hasta que i
sea mayor que la last (o menor que la last si el tamaño del paso es negativo).
Es importante tener en cuenta que desde Fortran 95, la variable de bucle y las expresiones de
control de bucle deben ser enteras.
do i=1, 5
if (i==4) cycle
end do
do i=1, 5
if (i==4) exit
end do
print *, i
https://riptutorial.com/es/home 31
do_name: do i=1, 5
end do do_name
do1: do i=1, 5
do j=1,6
if (j==3) cycle ! This cycles the j construct
if (j==4) cycle ! This cycles the j construct
if (i+j==7) cycle do1 ! This cycles the i construct
if (i*j==15) exit do1 ! This exits the i construct
end do
end do1
integer :: i=0
do
i=i+1
if (i==5) exit
end do
integer :: i=0
do while (i<6)
i=i+1
end do
print *,'forever'
do while(.true.)
print *,'and ever'
end do
do concurrent (i=1:5)
end do
teniendo en cuenta que la forma de control de bucle es la misma que en un control forall .
Hay varias restricciones en las declaraciones que pueden ejecutarse dentro del rango de una
construcción do concurrent que están diseñadas para garantizar que no haya dependencias de
datos entre las iteraciones de la construcción. Esta indicación explícita por parte del programador
puede permitir una mayor optimización (incluida la paralelización) por parte del compilador, lo que
puede ser difícil de determinar de otro modo.
https://riptutorial.com/es/home 32
Las variables "privadas" dentro de una interacción se pueden realizar mediante el uso de una
construcción de block dentro del do concurrent :
Otra forma del bloque do constructivo utiliza una instrucción continue etiquetada en lugar de un end
do :
do 100, i=1, 5
100 continue
Incluso es posible anidar tales construcciones con una declaración de terminación compartida
do 100, i=1,5
do 100, j=1,5
100 continue
Donde construir
Sintaxis:
Aquí,
https://riptutorial.com/es/home 33
• máscara - es una expresión lógica aplicada a todos los elementos
• bloque - serie de comandos a ejecutar
Ejemplos:
! Example variables
real:: A(5),B(5),C(5)
A = 0.0
B = 1.0
C = [0.0, 4.0, 5.0, 10.0, 0.0]
https://riptutorial.com/es/home 34
Capítulo 5: Extensiones de archivo fuente (.f,
.f90, .f95, ...) y cómo se relacionan con el
compilador.
Introducción
Los archivos de Fortran están bajo una variedad de extensiones y cada uno de ellos tiene un
significado diferente. Especifican la versión de lanzamiento de Fortran, el estilo de formato de
código y el uso de directivas de preprocesador similares al lenguaje de programación C.
Examples
Extensiones y significados
Las siguientes son algunas de las extensiones comunes que se utilizan en los archivos fuente de
Fortran y las funcionalidades en las que pueden trabajar.
F minúscula en la extensión
F mayúscula en la extensión
Estos archivos tienen las características de las directivas de preprocesador similares al lenguaje
de programación C. Los preprocesadores se definen dentro de los archivos o utilizan archivos de
encabezado como C / C ++ o ambos. Estos archivos deben preprocesarse para obtener los
archivos de extensión en minúsculas que se pueden usar para compilar. Por ejemplo: .F, .FOR,
.F95
Se usan para archivos Fortran que usan el formato de estilo Fijo y, por lo tanto, usan la versión
de lanzamiento de Fortran 77 . Como son extensiones en minúsculas, no pueden tener directivas
de preprocesador.
Se usan para archivos Fortran que usan el formato de estilo Fijo y, por lo tanto, usan la versión
de lanzamiento de Fortran 77 . Como son extensiones en mayúsculas, pueden tener directivas
de preprocesador y, por lo tanto, deben procesarse previamente para obtener los archivos de
extensión en minúsculas.
https://riptutorial.com/es/home 35
.f90, .f95, .f03, .f08 Se usan para archivos Fortran que usan el formato de estilo libre y, por lo
tanto, usan versiones de Fortran más recientes. Las versiones de lanzamiento están en el
nombre.
• f90 - Fortran 90
• f95 - Fortran 95
• f03 - Fortran 2003
• f08 - Fortran 2008
.F90, .F95, .F03, .F08 Se usan para archivos Fortran que usan el formato de estilo libre y, por lo
tanto, usan versiones de Fortran más recientes. Las versiones de lanzamiento están en el
nombre.
• F90 - Fortran 90
• F95 - Fortran 95
• F03 - Fortran 2003
• F08 - Fortran 2008
Como son extensiones en mayúsculas, tienen directivas de preprocesador y, por lo tanto, deben
procesarse previamente para obtener los archivos de extensión en minúsculas.
Lea Extensiones de archivo fuente (.f, .f90, .f95, ...) y cómo se relacionan con el compilador. en
línea: https://riptutorial.com/es/fortran/topic/10265/extensiones-de-archivo-fuente---f---f90---f95-----
--y-como-se-relacionan-con-el-compilador-
https://riptutorial.com/es/home 36
Capítulo 6: I / O
Sintaxis
• WRITE(unit num, format num)genera los datos después de los corchetes en una nueva línea.
• READ(unit num, format num) entradas a la variable después de los corchetes.
• OPEN(unit num, FILE=file) abre un archivo. (Hay más opciones para abrir archivos, pero no
son importantes para E / S.
• CLOSE(unit num) cierra un archivo.
Examples
E / S simple
Como ejemplo de escritura de entrada y salida, tomaremos un valor real y devolveremos el valor y
su cuadrado hasta que el usuario ingrese un número negativo.
print *,"The entered value was ", x," and its square is ",x*x
program SimpleIO
implicit none
integer, parameter :: wp = selected_real_kind(15,307)
real(kind=wp) :: x
Un ejemplo moderno de Fortran que incluye la verificación de errores y una función para obtener
https://riptutorial.com/es/home 37
un nuevo número de unidad para el archivo.
module functions
contains
logical :: op
integer :: f
f = 1
do
inquire(f,opened=op)
if (op .eqv. .false.) exit
f = f + 1
enddo
end function
end module
program file_read
use functions, only : get_new_fileunit
implicit none
filename = "somefile.txt"
inquire(file=trim(filename), exist=exists)
if (exists) then
unitno = get_new_fileunit()
open(unitno, file=trim(filename), action="read", iostat=ierr)
if (ierr .eq. 0) then
read(unitno, *, iostat=readerr) somevalue
if (readerr .eq. 0) then
print*, "Value in file ", trim(filename), " is ", somevalue
else
print*, "Error ", readerr, &
" attempting to read file ", &
trim(filename)
endif
else
print*, "Error ", ierr ," attempting to open file ", trim(filename)
stop
endif
else
print*, "Error -- cannot find file: ", trim(filename)
stop
endif
https://riptutorial.com/es/home 38
Donde se admiten los argumentos de la línea de comando, se pueden leer a través del intrínseco
get_command_argument (introducido en el estándar Fortran 2003). El intrínseco
command_argument_count proporciona una manera de conocer el número de argumentos
proporcionados en la línea de comandos.
Todos los argumentos de la línea de comando se leen como cadenas, por lo que se debe realizar
una conversión de tipo interna para los datos numéricos. Como ejemplo, este código simple suma
los dos números proporcionados en la línea de comando:
PROGRAM cmdlnsum
IMPLICIT NONE
CHARACTER(100) :: num1char
CHARACTER(100) :: num2char
REAL :: num1
REAL :: num2
REAL :: numsum
!First, make sure the right number of inputs have been provided
IF(COMMAND_ARGUMENT_COUNT().NE.2)THEN
WRITE(*,*)'ERROR, TWO COMMAND-LINE ARGUMENTS REQUIRED, STOPPING'
STOP
ENDIF
END PROGRAM
Muchos compiladores también ofrecen intrínsecos no estándar (como getarg ) para acceder a los
argumentos de la línea de comandos. Como estos no son estándar, se debe consultar la
documentación del compilador correspondiente.
El uso de get_command_argument puede extenderse más allá del ejemplo anterior con los
argumentos de length y status . Por ejemplo, con
character(5) arg
integer stat
call get_command_argument(number=1, value=arg, status=stat)
el valor de stat será -1 si el primer argumento existe y tiene una longitud mayor que 5. Si hay
alguna otra dificultad para recuperar el argumento, el valor de stat será un número positivo (y arg
constará completamente de espacios en blanco). De lo contrario su valor será 0 .
El argumento de length se puede combinar con una variable de carácter de longitud diferida,
https://riptutorial.com/es/home 39
como en el siguiente ejemplo.
https://riptutorial.com/es/home 40
Capítulo 7: Interfaces explícitas e implícitas
Examples
Subprogramas internos / módulos e interfaces explícitas
Un subprograma (que define un procedimiento ), puede ser una subroutine o una function ; se
dice que es un subprograma interno si se llama o se invoca desde el mismo program o
subprograma que lo contains , como sigue
program my_program
! declarations
! executable statements,
! among which an invocation to
! internal procedure(s),
call my_sub(arg1,arg2,...)
fx = my_fun(xx1,xx2,...)
contains
subroutine my_sub(a1,a2,...)
! declarations
! executable statements
end subroutine my_sub
En este caso, el compilador sabrá todo sobre cualquier procedimiento interno, ya que trata la
unidad del programa como un todo. En particular, "verá" la interface del procedimiento, es decir,
Al conocerse la interfaz, el compilador puede verificar si los argumentos reales ( arg1 , arg2 , xx1 ,
xx2 , fx , ...) pasaron al procedimiento con los argumentos ficticios ( a1 , a2 , x1 , x2 , f , .. .).
module my_mod
! declarations
https://riptutorial.com/es/home 41
contains
subroutine my_mod_sub(b1,b2,...)
! declarations
! executable statements
r = my_mod_fun(b1,b2,...)
end subroutine my_sub
o por una declaración en otra unidad de programa que use s ese módulo,
program my_prog
use my_mod
call my_mod_sub(...)
Como en la situación anterior, el compilador sabrá todo sobre el subprograma y, por lo tanto,
decimos que la interfaz es explícita .
Se puede usar una declaración external para especificar que el nombre de un procedimiento es
relativo a un procedimiento externo,
external external_name_list
interface
interface_body
https://riptutorial.com/es/home 42
end interface
donde interface_body es normalmente una copia exacta del encabezado del procedimiento
seguido de la declaración de todos sus argumentos y, si es una función, del resultado.
interface
real function WindSpeed(u, v)
real, intent(in) :: u, v
end function WindSpeed
end interface
https://riptutorial.com/es/home 43
Capítulo 8: Interoperabilidad C
Examples
Llamando C desde Fortran
Fortran 2003 introdujo características de lenguaje que pueden garantizar la interoperabilidad entre
C y Fortran (y para más idiomas utilizando C como intermediario). A estas funciones se accede
principalmente a través del módulo intrínseco iso_c_binding :
La palabra clave intrinsic aquí garantiza que se use el módulo correcto, y no un módulo creado
por el usuario con el mismo nombre.
El uso de parámetros de tipo C garantiza que los datos pueden transferirse entre los programas C
y Fortran.
Para llamar realmente a una función C desde Fortran, primero se debe declarar la interfaz. Esto
es esencialmente equivalente al prototipo de la función C, y le permite al compilador conocer el
número y el tipo de los argumentos, etc. El atributo de bind se usa para decirle al compilador el
nombre de la función en C, que puede ser diferente al de Fortran. nombre.
gansos.h
gansos f90
! Interface to C routine
interface
integer(c_int) function how_many_geese(flock_num) bind(C, 'howManyGeese')
! Interface blocks don't know about their context,
! so we need to use iso_c_binding to get c_int definition
use, intrinsic :: iso_c_binding, only : c_int
integer(c_int) :: flock_num
end function how_many_geese
end interface
https://riptutorial.com/es/home 44
El programa de Fortran debe estar vinculada con la librería C (compilador dependiente, se
incluyen aquí?), Que incluye la implementación de howManyGeese() , y luego how_many_geese() puede
ser llamado desde Fortran.
C structs en fortran
gansos.h
struct Goose {
int flock;
float buoyancy;
}
gansos f90
type(goose_t) :: goose_f
Los datos ahora se pueden transferir entre goose_c y goose_f . Las rutinas C que toman
argumentos de tipo Goose se pueden llamar desde Fortran con type(goose_t) .
https://riptutorial.com/es/home 45
Capítulo 9: Procedimientos - Funciones y
subrutinas.
Observaciones
Las funciones y las subrutinas , junto con los módulos , son las herramientas para dividir un
programa en unidades. Esto hace que el programa sea más legible y manejable. Cada una de
estas unidades puede considerarse como parte del código que, idealmente, podría compilarse y
probarse de forma aislada. Los programas principales pueden llamar (o invocar) a dichos
subprogramas (funciones o subrutinas) para realizar una tarea.
• Las funciones devuelven un solo objeto y, generalmente, no alteran los valores de sus
argumentos (es decir, ¡actúan como una función matemática);
• Las subrutinas generalmente realizan una tarea más complicada y generalmente alteran
sus argumentos (si hay alguno presente), así como otras variables (por ejemplo, aquellas
declaradas en el módulo que contiene la subrutina).
Examples
Sintaxis funcional
function name()
integer name
name = 42
end function
Las funciones devuelven valores a través de un resultado de función . A menos que la declaración
de función tenga una cláusula de result el result la función tendrá el mismo nombre que la
https://riptutorial.com/es/home 46
función. Con result el result la función es el dado por el result . En cada uno de los dos primeros
ejemplos anteriores, el resultado de la función viene dado por name ; en el tercero por res .
Función pura significa que esta función no tiene ningún efecto secundario:
La función elemental se define como operador escalar, pero se puede invocar con array como
argumento real, en cuyo caso la función se aplicará de forma elemental. A menos que se
especifique el prefijo impure (introducido en Fortran 2008), una función elemental también es una
función pura .
Declaración de devolución
f = x
do i = 1, 10
f = sqrt(f) - 1.0
if (f < 0) then
f = -1000.
return
end if
end do
end function
Esta función realiza un cálculo iterativo. Si el valor de f vuelve negativo, la función devuelve el
valor -1000.
Procedimientos recursivos
https://riptutorial.com/es/home 47
En Fortran, las funciones y las subrutinas deben declararse explícitamente como recursivas , si
han de llamarse a sí mismas de nuevo, directa o indirectamente. Por lo tanto, una implementación
recursiva de la serie Fibonacci podría tener este aspecto:
if(n == 0) then
f = 1
else
f = n * f(n-1)
end if
end function factorial
Para que una función se refiera directamente a sí misma, su definición debe usar el sufijo de
result . No es posible que una función sea tanto recursive como elemental .
El atributo de intent de un argumento ficticio en una subrutina o función declara su uso previsto.
La sintaxis es una de
intent(IN)
intent(OUT)
intent(INOUT)
f = x*x
end function
La intent(IN) especifica que el argumento ficticio (sin puntero) x nunca se puede definir o perder
su definición a lo largo de la función o su inicialización. Si un argumento ficticio de puntero tiene el
atributo intent(IN) , esto se aplica a su asociación.
https://riptutorial.com/es/home 48
intent(OUT) para un argumento ficticio no puntero significa que el argumento ficticio se convierte
en indefinido en la invocación del subprograma (a excepción de cualquier componente de un tipo
derivado con inicialización predeterminada) y se debe establecer durante la ejecución. El
argumento real pasado como argumento ficticio debe ser definible: no se permite pasar una
constante con nombre o literal, o una expresión.
intent(INOUT) especifica que el argumento real es definible y es adecuado para pasar y devolver
datos del procedimiento.
Finalmente, un argumento ficticio puede estar sin el atributo de intent . Tal argumento ficticio
tiene su uso limitado por el argumento real pasado.
integer :: i = 0
call sub(i, .TRUE.)
call sub(1, .FALSE.)
end
El argumento i puede tener ningún atributo de intent que permita las dos llamadas de subrutina
del programa principal.
Para que una función o subrutina sea útil debe ser referenciada. Se hace referencia a una
subrutina en una instrucción de call
call sub(...)
y una función dentro de una expresión. A diferencia de muchos otros idiomas, una expresión no
forma una declaración completa, por lo que una referencia de función se ve a menudo en una
instrucción de asignación o se usa de alguna otra manera:
x = func(...)
y = 1 + 2*func(...)
https://riptutorial.com/es/home 49
• un componente de procedimiento de un objeto de tipo derivado
• un nombre de enlace de procedimiento vinculado
subroutine sub()
end subroutine
module mod
type t
procedure(sub), pointer, nopass :: sub_ptr=>sub
contains
procedure, nopass :: sub
end type
contains
subroutine sub()
end subroutine
end module
use mod
type(t) x
call x%sub_ptr() ! Procedure component
call x%sub() ! Binding name
end
Considere la subrutina
subroutine sub(a, b, c)
integer a, b
integer, optional :: c
end subroutine
Esto se denomina referencia de posición : los argumentos reales se asocian según la posición en
las listas de argumentos. Aquí, el dummy a está asociado con 1 , b con 2 y c (cuando se
https://riptutorial.com/es/home 50
especifica) con 3 .
Sin embargo, con palabras clave los argumentos reales se pueden ofrecer en cualquier orden
siempre que se proporcione una palabra clave para cada argumento después de la primera
aparición de una palabra clave
https://riptutorial.com/es/home 51
Capítulo 10: Procedimientos intrínsecos
Observaciones
Muchos de los procedimientos intrínsecos disponibles tienen tipos de argumentos en común. Por
ejemplo:
• un argumento lógico MASK que selecciona elementos de las matrices de entrada para ser
procesados
• un argumento escalar entero KIND que determina el tipo de resultado de la función
• un argumento entero DIM para una función de reducción que controla la dimensión sobre la
que se realiza la reducción
Examples
Uso de PACK para seleccionar elementos que cumplan una condición
La función de pack intrínseco pack una matriz en un vector, seleccionando elementos basados en
una máscara dada. La función tiene dos formas.
PACK(array, mask)
PACK(array, mask, vector)
En ambos casos, la array es una matriz, y una mask de tipo lógico y compatible con la array (ya
sea un escalar o una matriz de la misma forma).
En el primer caso, el resultado es una matriz de rango 1 de tipo y los parámetros de tipo de array
con el número de elementos siendo el número de elementos verdaderos en la máscara.
Con el argumento vector rango-1 presente, el resultado ahora es el tamaño del vector (que debe
tener al menos tantos elementos como valores reales en la mask .
El efecto con vector es devolver esa matriz con los elementos iniciales de esa matriz sobrescritos
por los elementos enmascarados de la array . Por ejemplo
https://riptutorial.com/es/home 52
resulta en [2,3,5,40,50] positive_values siendo la matriz [2,3,5,40,50] .
Además de seleccionar los elementos de una matriz que cumplen una condición de
enmascaramiento, a menudo es útil determinar los índices para los cuales se cumple la condición
de enmascaramiento. Este lenguaje común se puede expresar como
https://riptutorial.com/es/home 53
Capítulo 11: Programación orientada a
objetos
Examples
Definición de tipo derivado
Fortran 2003 introdujo el soporte para la programación orientada a objetos. Esta característica
permite aprovechar las modernas técnicas de programación. Los tipos derivados se definen con
la siguiente forma:
dónde,
Ejemplo:
type shape
integer :: color
end type shape
Tipo de Procedimientos
Para obtener un comportamiento similar a una clase, el tipo y los procedimientos relacionados
(subrutina y funciones) se colocarán en un módulo:
Ejemplo:
module MShape
implicit none
private
https://riptutorial.com/es/home 54
type, public :: Shape
private
integer :: radius
contains
procedure :: set => shape_set_radius
procedure :: print => shape_print
end type Shape
contains
subroutine shape_set_radius(this, value)
class(Shape), intent(in out) :: self
integer, intent(in) :: value
self%radius = value
end subroutine shape_set_radius
subroutine shape_print(this)
class(Shape), intent(in) :: self
Más adelante, en un código, podemos usar esta clase de Forma de la siguiente manera:
Tal tipo derivado nunca puede ser instanciado, tal como por
type(base_type) t1
allocate(type(base_type) :: t2)
class(base_type), allocatable :: t1
function f(t1)
class(base_type) t1
end function
https://riptutorial.com/es/home 55
Los tipos abstractos pueden tener componentes y procedimientos de tipo unido
El procedimiento def_func es un procedimiento de tipo diferido con interfaz func_iface . Este tipo
de procedimiento diferido debe ser implementado por cada tipo de extensión.
Extensión de tipo
Un tipo derivado es extensible si no tiene el atributo de bind ni el atributo de sequence . Tal tipo
puede ser extendido por otro tipo.
module mod
type base_type
integer i
end type base_type
Una variable polimórfica con el tipo base_type declarado es compatible con el tipo higher_type y
puede tenerlo como tipo dinámico
La compatibilidad de tipos desciende a través de una cadena de hijos, pero un tipo puede
extenderse solo a otro tipo.
Un tipo derivado extendido hereda los procedimientos de tipo enlazado del padre, pero esto
puede ser anulado
module mod
type base_type
contains
procedure :: sub => sub_base
end type base_type
https://riptutorial.com/es/home 56
contains
subroutine sub_base(this)
class(base_type) this
end subroutine sub_base
subroutine sub_higher(this)
class(higher_type) this
end subroutine sub_higher
program prog
use mod
obj = base_type()
call obj%sub
obj = higher_type()
call obj%sub
end program
Tipo constructor
Se pueden crear constructores personalizados para tipos derivados utilizando una interfaz para
sobrecargar el nombre del tipo. De esta manera, los argumentos de palabras clave que no
corresponden a componentes pueden usarse al construir un objeto de ese tipo.
module ball_mod
implicit none
type :: ball_t
real :: mass
end type ball_t
contains
if (heavy) then
new_ball%mass = 100
else
new_ball%mass = 1
https://riptutorial.com/es/home 57
end if
program test
use ball_mod
implicit none
type(ball_t) :: football
type(ball_t) :: boulder
Esto se puede usar para hacer una API más ordenada que usar rutinas de inicialización
separadas:
subroutine make_heavy_ball(ball)
type(ball_t), intent(inout) :: ball
ball%mass = 100
end subroutine make_heavy_ball
...
call make_heavy_ball(boulder)
https://riptutorial.com/es/home 58
Capítulo 12: Tipos de datos
Examples
Tipos intrinsecos
integer
real
character
complex
logical
integer(kind=specific_kind)
o solo
integer(specific_kind)
character char
declara que char es una variable de longitud-1 carácter de tipo predeterminado, mientras que
character(len=len) name
declara que el name es una variable de carácter del tipo predeterminado y la longitud len . El tipo
también puede ser especificado
declara que el name es un carácter de tipo kind y longitud len . char es una longitud de 1 carácter
de tipo kind .
https://riptutorial.com/es/home 59
Alternativamente, la forma obsoleta para la declaración de caracteres.
character*len name
puede verse en el código anterior, declarando que el name es de longitud len y tipo de carácter
predeterminado.
La declaración de una variable de tipo intrínseco puede ser de la forma anterior, pero también
puede usar la forma type(...) :
integer i
real x
double precision y
type(integer) i
type(real) x
type(double precision) y
type :: mytype
integer :: int
real :: float
end type mytype
type(mytype) :: foo
foo%int = 4
foo%float = 3.142
Una característica de Fortran 2003 (aún no implementada por todos los compiladores) permite
definir tipos de datos parametrizados:
La matrix tipos derivada tiene tres parámetros de tipo que se enumeran entre paréntesis después
https://riptutorial.com/es/home 60
del nombre de tipo (son rows , cols k ). En la declaración de cada parámetro de tipo debe indicarse
si son parámetros de tipo kind ( kind ) o length ( len ).
Los parámetros de tipo de clase, como los de los tipos intrínsecos, deben ser expresiones
constantes, mientras que los parámetros de tipo de longitud, como la longitud de una variable de
carácter intrínseco, pueden variar durante la ejecución.
Tenga en cuenta que el parámetro k tiene un valor predeterminado, por lo que se puede
proporcionar u omitir cuando se declara una variable de tipo matrix , de la siguiente manera
El nombre de un tipo derivado no puede ser de doubleprecision o el mismo que cualquiera de los
tipos intrínsecos.
1. Muchas personas se preguntan por qué Fortran usa % como operador de acceso a
componentes, en lugar de los más comunes . . Esto se debe a . ya está en la sintaxis del
operador, es decir, .not. , .and. , .my_own_operator. .
Los números de punto flotante de tipo real no pueden tener ningún valor real. Pueden representar
números reales hasta cierta cantidad de dígitos decimales.
FORTRAN 77 garantizó dos tipos de punto flotante y las normas más recientes garantizan al
menos dos tipos reales. Las variables reales pueden ser declaradas como
real x
double precision y
xaquí es un tipo real por defecto e y es un tipo real con mayor precisión decimal que x . En
Fortran 2008, la precisión decimal de y es al menos 10 y su rango de exponente decimal al menos
37.
print *, single
print *, double
huellas dactilares
1.12345684
1.1234567890123457
https://riptutorial.com/es/home 61
Observe la d0 en la constante de doble precisión. Un literal real que contiene d lugar de e para
denotar el exponente se usa para indicar doble precisión.
Fortran 90 introdujo tipos real parametrizados utilizando tipos. El tipo de un tipo real es un entero
llamado constante o constante literal:
real(kind=real_kind) :: x
o solo
real(real_kind) :: x
Esta declaración declara que x es de tipo real con una cierta precisión dependiendo del valor de
real_kind .
Los literales de punto flotante se pueden declarar con un tipo específico usando un sufijo
1.23456e78_real_kind
normalmente se imprimirá
4 8
1 2
https://riptutorial.com/es/home 62
integer, parameter :: single_kind = selected_real_kind( p=6, r=37 )
integer, parameter :: double_kind = selected_real_kind( p=15, r=200 )
3. A partir de Fortran 2003, las constantes predefinidas están disponibles a través del módulo
intrínseco ISO_C_Binding para garantizar que las clases reales sean interoperables con los
tipos float , double o long_double del compilador C que lo acompaña:
use ISO_C_Binding
4. A partir de Fortran 2008, las constantes predefinidas están disponibles a través del módulo
intrínseco ISO_Fortran_env . Estas constantes proporcionan tipos reales con cierto tamaño de
almacenamiento en bits
use ISO_Fortran_env
Las variables de tipo de carácter o de un tipo derivado con parámetro de longitud pueden tener el
parámetro de longitud asumido o diferido . El name variable de caracteres.
character(len=len) name
Es de longitud len largo de la ejecución. Por el contrario, el especificador de longitud puede ser
En la funcion
function f(dummy_name)
character(len=*) dummy_name
end function f
https://riptutorial.com/es/home 63
el argumento ficticio dummy_name tiene la longitud del argumento real.
Los parámetros de tipo de longitud diferida pueden variar durante la ejecución. Una variable con
longitud diferida debe tener el atributo allocatable o pointer
type t(len)
integer, len :: len
integer i(len)
end type t
type(t(:)), allocatable :: t1
type(t(5)) t2
call sub(t2)
allocate(type(t(5)) :: t1)
contains
subroutine sub(t2)
type(t(*)), intent(out) :: t2
end subroutine sub
end
Constantes literales
Las unidades de programa a menudo hacen uso de constantes literales. Estos cubren los casos
obvios como
Excepto en un caso, cada constante literal es un escalar que tiene tipo, parámetros de tipo y valor
dado por la sintaxis.
https://riptutorial.com/es/home 64
Las constantes literales enteras son de la forma
1
-1
-1_1 ! For valid kind parameter 1
1_ik ! For the named constant ik being a valid kind paramter
(1, 1.) ! Complex with integer and real components, literal constants
(real, imag) ! Complex with named constants as components
Si los componentes real e imaginario son ambos enteros, la constante literal compleja es
compleja por defecto, y los componentes enteros se convierten en real por defecto. Si un
componente es real, el parámetro kind de la constante literal compleja es el de lo real (y el
componente entero se convierte a ese tipo real). Si ambos componentes son reales, la constante
literal compleja es de la clase de lo real con la mayor precisión.
Como se sugirió anteriormente, las constantes literales de los caracteres deben estar delimitadas
por apóstrofes o comillas, y los marcadores de inicio y final deben coincidir. Los apóstrofes
literales se pueden incluir estando dentro de los delimitadores de comillas o apareciendo
duplicados. Lo mismo para las comillas.
Las constantes de BOZ son distintas de las anteriores, ya que solo especifican un valor: no tienen
tipo ni parámetro de tipo. Una constante BOZ es un patrón de bits y se especifica como
https://riptutorial.com/es/home 65
B'00000' ! A binary bit pattern
B"01010001" ! A binary bit pattern
O'012517' ! An octal bit pattern
O"1267671" ! An octal bit pattern
Z'0A4F' ! A hexadecimal bit pattern
Z"FFFFFF" ! A hexadecimal bit pattern
Las constantes literales de BOZ están limitadas en donde pueden aparecer: como constantes en
declaraciones de data y una selección de procedimientos intrínsecos.
greeting(2:4) ! "ell"
pero
greeting(1)(2:4) ! "ell"
"Hello"(2:4)
Una parte de una variable de carácter también se puede definir utilizando una subcadena como
variable. Por ejemplo
https://riptutorial.com/es/home 66
integer :: i=1
character :: filename = 'file000.txt'
filename(9:11) = 'dat'
write(filename(5:7), '(I3.3)') i
La entidad compleja
Tiene parte real 1. y parte compleja 4. .. Podemos acceder a estos componentes individuales
como
La forma x%.. es nueva para Fortran 2008 y no es ampliamente compatible con compiladores. Sin
embargo, esta forma se puede usar para establecer directamente los componentes individuales
de una variable compleja
complex y
y%re = 0.
y%im = 1.
Declaración y atributos.
A lo largo de los temas y ejemplos aquí veremos muchas declaraciones de variables, funciones,
etc.
Además de su nombre, los objetos de datos pueden tener atributos . Cubierto en este tema son
declaraciones de declaración como
que le da al objeto single_kind el atributo de parameter (por lo que es una constante con nombre).
• target
• pointer
• optional
• save
https://riptutorial.com/es/home 67
integer i ! i is an integer (of default kind)...
pointer i ! ... with the POINTER attribute...
optional i ! ... and the OPTIONAL attribute
Sin embargo, generalmente se considera que es mejor evitar el uso de estas declaraciones de
especificación de atributos. Para mayor claridad, los atributos pueden especificarse como parte
de una sola declaración.
En la mayoría de los casos, en esta documentación de Fortran, se prefiere esta declaración única.
https://riptutorial.com/es/home 68
Capítulo 13: Unidades de programa y diseño
de archivos.
Examples
Programas de fortran
• programa principal
• función o subprograma de subrutina
• módulo o submódulo
• unidad de programa de datos de bloque
Estas unidades del programa Fortran pueden ser archivos distintos o dentro de un solo archivo.
prog.f90
program main
use mod
end program main
mod.f90
module mod
end module mod
todo.f90
module mod
end module mod
program prog
use mod
end program prog
https://riptutorial.com/es/home 69
function f()
end function f()
En este caso, sin embargo, debe tenerse en cuenta que la función f sigue siendo una función
externa en lo que respecta al programa principal y el módulo. Sin embargo, el programa principal
estará accesible para el módulo.
module mod
implicit none
end module mod
program prog
use mod
implicit none
end program prog
function f()
implicit none
<type> f
end function f
Módulos y submódulos.
Los compiladores a menudo generan los llamados archivos de módulo : generalmente el archivo
que contiene
module my_module
end module
resultará en un archivo llamado algo así como my_module.mod por el compilador. En tales casos,
para que un módulo sea accesible por una unidad de programa, ese archivo de módulo debe
estar visible antes de que se procese esta última unidad de programa.
Procedimientos externos
Un procedimiento externo es uno que se define fuera de otra unidad de programa, o por un medio
que no sea Fortran.
https://riptutorial.com/es/home 70
Es una función externa.
program prog
implicit none
interface
integer function f()
end interface
end program prog
program prog
implicit none
integer, external :: f
end program prog
o incluso
program prog
implicit none
integer f
external f
end program prog
program prog
implicit none
integer i
integer f
i = f() ! f is now an external function
end program prog
Las unidades de programa de datos de bloque son unidades de programa que proporcionan
valores iniciales para objetos en bloques comunes. Estos se dejan deliberadamente sin
documentar aquí, y aparecerán en la documentación de las características históricas de Fortran.
Subprogramas internos
Una unidad de programa que no es un subprograma interno puede contener otras unidades de
programa, llamadas subprogramas internos .
program prog
implicit none
contains
function f()
end function f
https://riptutorial.com/es/home 71
subroutine g()
end subroutine g
end program
• existe una asociación de host entre las entidades en el subprograma y el programa externo
• las reglas de escritura implícitas se heredan ( implicit none está vigente en f arriba)
• Los subprogramas internos tienen una interfaz explícita disponible en el servidor.
Los subprogramas de módulo y los subprogramas externos pueden tener subprogramas internos,
como
module mod
implicit none
contains
function f()
contains
subroutine s()
end subroutine s
end function f
end module mod
Un archivo de código fuente es un (generalmente) archivo de texto plano que debe ser procesado
por el compilador. Un archivo de código fuente puede contener hasta un programa principal y
cualquier número de módulos y subprogramas externos. Por ejemplo, un archivo de código fuente
puede contener lo siguiente
module mod1
end module mod1
module mod2
end module mod2
Debemos recordar aquí que, aunque los subprogramas externos se encuentran en el mismo
archivo que los módulos y el programa principal, los subprogramas externos no son conocidos
explícitamente por ningún otro componente.
https://riptutorial.com/es/home 72
incluso compilados en diferentes momentos. La documentación del compilador debe leerse sobre
cómo combinar varios archivos en un solo programa.
Un solo archivo de código fuente puede contener un código fuente de forma fija o de forma libre:
no se pueden mezclar, aunque varios archivos que se combinan en tiempo de compilación
pueden tener diferentes estilos.
El indicador de tiempo de compilación para indicar el origen de forma libre o fija se puede
encontrar en la documentación del compilador.
El uso del sufijo .f90 para indicar la fuente de forma libre (que se introdujo en el estándar Fortran
90) a menudo tienta al programador a usar el sufijo para indicar el estándar de idioma con el que
se ajusta el código fuente. Por ejemplo, podemos ver archivos con sufijos .f03 o .f08 . Esto
generalmente debe evitarse: la mayoría de las fuentes de Fortran 2003 también son compatibles
con Fortran 77, Fortran 90/5 y Fortran 2008. Además, muchos comilers no consideran
automáticamente tales sufijos.
Para los sistemas de archivos que file.F mayúsculas y minúsculas, el archivo file.F menudo se
toma como un archivo fuente de forma fija que debe file.F90 previamente y file.F90 es un
archivo fuente de forma libre que debe file.F90 previamente. Como antes, se debe consultar la
documentación del compilador para dichos indicadores y sufijos de archivos.
https://riptutorial.com/es/home 73
Capítulo 14: Uso de módulos
Examples
Sintaxis del modulo
module module_name
use other_module_being_used
! The use of implicit none here will set it for the scope of the module.
! Therefore, it is not required (although considered good practice) to repeat
! it in the contained subprograms.
implicit none
! Parameters declaration
real, parameter, public :: pi = 3.14159
! The keyword private limits access to e parameter only for this module
real, parameter, private :: e = 2.71828
! Type declaration
type my_type
integer :: my_int_var
end type
! Variable declaration
integer :: my_integer_variable
subroutine my_subroutine
!module variables are accessible
print *, my_integer_variable
end subroutine
Para acceder a las entidades declaradas en un módulo desde otra unidad de programa (módulo,
procedimiento o programa), el módulo debe usarse con la declaración de use .
module shared_data
implicit none
https://riptutorial.com/es/home 74
real :: rarray(4) = [1., 2., 3., 4.]
end module
program test
implicit none
print *, iarray
print *, rarray
end program
program test
implicit none
print *, iarray
end program
También se puede acceder a las entidades con un nombre diferente utilizando una lista de
cambio de nombre :
program test
implicit none
print *, local_name
print *, rarray
end program
program test
use shared_data, only : local_name => iarray
end program
de modo que solo se accede a la entidad del módulo iarray , pero tiene el nombre local local_name
.
https://riptutorial.com/es/home 75
Módulos intrínsecos
Fortran 2003 introdujo módulos intrínsecos que brindan acceso a constantes con nombre
especiales, tipos derivados y procedimientos de módulos. Ahora hay cinco módulos intrínsecos
estándar:
Estos módulos intrínsecos son parte de la biblioteca Fortran y se accede a ellos como otros
módulos, excepto que la declaración de use puede tener la naturaleza intrínseca explícitamente
establecida:
Esto garantiza que el módulo intrínseco se use cuando esté disponible un módulo proporcionado
por el usuario con el mismo nombre. A la inversa
asegura que se acceda al mismo módulo proporcionado por el usuario (que debe ser accesible)
en lugar del módulo intrínseco. Sin la naturaleza del módulo especificado como en
use ISO_C_Binding
Los módulos IEEE intrínsecos son diferentes de otros módulos en que su accesibilidad en una
unidad de alcance puede cambiar el comportamiento del código allí, incluso sin hacer referencia a
ninguna de las entidades definidas en ellos.
Control de acceso
https://riptutorial.com/es/home 76
!symbols in the list will be public
public :: name3, name4
Se puede acceder a los símbolos públicos desde las unidades de programa que usan el módulo,
pero los símbolos privados no pueden.
private
public
o utilizando atributos.
Este control de acceso también afecta a los símbolos importados de otro módulo:
module mod1
integer :: var1
end module
module mod2
use mod1, only: var1
public
end module
program test
use mod2, only: var1
end program
es posible, pero
module mod1
integer :: var1
end module
module mod2
https://riptutorial.com/es/home 77
use mod1, only: var1
public
private :: var1
end module
program test
use mod2, only: var1
end program
Además de permitir que las entidades de módulo tengan control de acceso (ya sea public o
private ), las entidades de módulo también pueden tener el atributo de protect . Una entidad
protegida pública puede estar asociada al uso, pero la entidad utilizada está sujeta a restricciones
sobre su uso.
module mod
integer, public, protected :: i=1
end module
program test
use mod, only : i
print *, i ! We are allowed to get the value of i
i = 2 ! But we can't change the value
end program test
module mod
integer, public, target, protected :: i
end module mod
program test
use mod, only : i
integer, pointer :: j
j => i ! Not allowed, even though we aren't changing the value of i
end program test
Para un puntero público protegido en un módulo, las restricciones son diferentes. Lo que está
protegido es el estado de asociación del puntero.
module mod
integer, public, target :: j
integer, public, protected, pointer :: i => j
end module mod
program test
use mod, only : i
i = 2 ! We may change the value of the target, just not the association status
end program test
https://riptutorial.com/es/home 78
Al igual que con los punteros variables, los punteros de procedimiento también pueden
protegerse, impidiendo nuevamente el cambio de asociación objetivo.
https://riptutorial.com/es/home 79
Creditos
S.
Capítulos Contributors
No
Alternativas
modernas a las Brian Tompsett - , d_1999, Enrico Maria De Angelis,
2
características francescalus, Serenity, TTT, Vladimir F, Yossarian
históricas.
Extensiones de
archivo fuente (.f,
5 .f90, .f95, ...) y cómo Arun
se relacionan con el
compilador.
Interfaces explícitas
7 Enrico Maria De Angelis, Serenity, Vladimir F
e implícitas
Procedimientos -
Alexander Vogt, Enrico Maria De Angelis, francescalus, haraldkl
9 Funciones y
, Serenity, Vladimir F, Yossarian
subrutinas.
Procedimientos
10 francescalus
intrínsecos
Programación
11 Enrico Maria De Angelis, francescalus, syscreat, Yossarian
orientada a objetos
https://riptutorial.com/es/home 80
programa y diseño
de archivos.
https://riptutorial.com/es/home 81