Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Ingeniera Aeronutica
ETSEIAT
2012
Mtodos numricos
Licencia
Esta obra est bajo una licencia Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) de
Creative Commons. Para ver una copia de esta licencia, visite:
http://creativecommons.org/licenses/by-sa/3.0/deed.es_ES
En lneas generales:
Es libre de:
-2-
Mtodos numricos
ndice
1.
Programacin en Fortran
1.1.
1.2.
1.3.
1.4.
1.5.
Subrutinas ................................................................................................................... 11
1.6.
1.7.
Programas ................................................................................................................... 13
Interpolacin
2.1.
SPLINE.......................................................................................................................... 17
2.2.
2.3.
Programa ..................................................................................................................... 20
Integracin
3.1.
3.2.
3.3.
3.4.
3.5.
3.6.
Programas ................................................................................................................... 30
4.2.
4.3.
Mtodo de la secante.................................................................................................. 37
4.4.
4.5.
4.6.
Programas ................................................................................................................... 41
-3-
Mtodos numricos
5.2.
5.3.
Descomposicin LU ..................................................................................................... 47
5.4.
Doolittle ....................................................................................................................... 47
5.5.
Crout ............................................................................................................................ 48
5.6.
Matrices dispersas....................................................................................................... 49
5.7.
5.8.
5.9.
Programas ................................................................................................................... 58
7.
7.2.
Mtodo de Euler.......................................................................................................... 74
7.3.
7.4.
7.5.
7.6.
7.7.
7.8.
7.9.
Esquema de Crank-Nicolson........................................................................................ 81
8.2.
-4-
Mtodos numricos
8.3.
8.4.
Programas ................................................................................................................... 90
9.2.
9.3.
9.4.
9.5.
9.6.
9.7.
9.8.
-5-
Mtodos numricos
-6-
Mtodos numricos
1. Programacin en Fortran
1.1.
Tipos de variables
Boolean:
Es una variable de un solo bit y por lo tanto solo puede tener dos posibles valores
(.true. o .false.).
Integer:
Solo permite tener un valor enteros, en general ocupa
bits. El primer bit contiene el
signo y por lo tanto el mdulo del nmero ocupa los restantes
bits. El valor mximo
es igual a
.
Real:
Es similar al Double usado en otros lenguajes de programacin como C. Permite
nmeros en decimales y en general ocupa
bits. De forma similar al Integer el primer
bit contiene el signo del nmero.
Complex:
Son nmeros complejos compuestos de dos nmeros Real separados por una coma y
entre parntesis. El primer nmero representa el valor real y el segundo el valor
complejo.
Character:
Se utiliza para escribir letras. Se suele generar un vector donde cada posicin es un
caracter.
Para definir una variable se debe declarar primero el tipo y luego el nombre de la variable. Las
variables tienen que tener un nombre entre y
letras o nmeros siendo la primera siempre
una letra. En Fortran no hay diferencia entre maysculas y minsculas.
real x
integer i
Tambin se puede definir el tamao en memoria de las distintas variables como por ejemplo:
real*8 x
integer*8 i
1.2.
Expresiones aritmticas
Las cinco operaciones aritmticas bsicas son: la suma (+), la resta (-), la multiplicacin (*), la
divisin (/) y el exponente (**). Fortran tambin reconoce otro tipo de funciones como por
ejemplo funciones trigonomtricas, logaritmos Las operaciones aritmticas devuelven un
resultado (que puede ser un Real o Integer) y debe ser almacenado en una variable.
-7-
Mtodos numricos
x = 1. + 3. 25 * 5. / 3.
x = cos(1.25) + y**2.
Primero:
Todas las operaciones exponenciales y se desarrollan de derecha a izquierda.
Segundo:
Todas las multiplicaciones y divisiones, el orden es de izquierda a derecha.
Tercero:
Todas las operaciones de suma y resta, el orden es de izquierda a derecha.
En este libro se va a centrar el estudio del uso de Fortran para aplicacin en mtodos
numricos. Los programas se deben escribir de forma ptima para el clculo. La latencia es el
tiempo que se consume en una operacin. Las operaciones bsicas (menos los exponentes)
tienen latencias muy bajas, en especial la suma, la resta y la multiplicacin. La divisin tiene
una latencia un poco ms alta aunque en los nuevos procesadores como por ejemplo los Intel
i7 la diferencia en latencia es despreciable, en ordenadores antiguos la latencia puede ser
hasta cinco veces ms lenta. Las operaciones exponenciales, trigonomtricas, logartmicas
son demasiado lentas y deben ser evitadas en la medida de lo posible. Por ejemplo si se quiere
calcular la siguiente ecuacin:
( )
(1.1)
Se debera evitar hacer la operacin exponente y se podra escribir de la siguiente forma (la
terminologa de los bucles en Fortran se explica ms adelante).
p = a(n)
do i .eq. n, 1, -1
p = p * x + a (n - 1)
end do
1.3.
Bucles y condiciones
-8-
Mtodos numricos
Por defecto cada vez que se ejecuta el bucle se le suma uno a la variable (en el ejemplo i) pero
se puede cambiar el valor que se aade poniendo despus del valor final una coma y el
sumando.
La funcin if ejecuta solo el cdigo si se cumple la condicin impuesta. Para poner condiciones
en Fortran se utiliza la siguiente sintaxis (abreviaciones del ingls):
-
Se puede complementar la funcin if utilizando las funciones else (si la condicin del if no se
cumple se ejecuta el cdigo que sigue al else) o elseif (parecido al else pero se le aade una
condicin ms para que se ejecute el cdigo). Se pueden poner tantos elseif como se quieran
en un mismo conjunto de if. Se debe finalizar el cdigo de esta funcin con endif.
if (a .gt. 2) then
b=1
else
b=0
end if
La funcin do while ejecuta repite el cdigo hasta que la condicin deje de cumplirse. El
cdigo dentro del do while se ejecuta hasta que se finaliza (con end do) y vuelve a la lnea del
principio para comprobar si se cumple an la condicin. Si se desea salir del bucle en algn
punto intermedio se puede utilizar la funcin exit.
do while (a .lt. 5)
a=a+1
end do
1.4.
Vectores y matrices
Se usan los vectores y matrices para utilizar un solo nombre que refiera a un conjunto de
direcciones de memoria. Todos los datos almacenados en un vector o una matriz deben ser del
mismo tipo.
Para usar un vector o matriz (a partir de ahora solo se referirn a matrices ya que el
funcionamiento es casi el mismo) se debe primero declralo. Se puede declarar de forma
esttica o de forma dinmica. Si se declara de forma dinmica no se define la dimensin de la
matriz, mientras que si se define de forma esttica si que se define la dimensin.
-9-
Mtodos numricos
Para declarar una matriz de forma esttica se pone el tipo de las variables que almacena
seguido del nombre de la matriz y en parntesis sus dimensiones, se utiliza una coma para
definir las distintas columnas de la matriz (el valor de la dimensin de cada columna debe ser
un integro).
real a(4,9)
integer b(2,n)
Para declarar una matriz de forma dinmica se debe utilizar el parmetro allocatable y utilizar
dos puntos para las columnas que no se quiere definir la dimensin. Una vez se decide dar un
valor a la dimensin se utiliza la funcin allocate.
real, allocatable : : a(4, :)
integer n
print*,"Dimensions of the matrix?"
read(*,*) n
allocate(a(:,n))
Una matriz creada de forma dinmica puede ser eliminada (para liberar espacio en la
memoria) con la funcin dellocate. Para saber si una matriz dinmica est creada o no en un
momento dado se puede usar la funcin intrnseca allocatable (la funcin devuelve un valor
booleano).
Las tablas se puede utilizar globalmente, referenciando un conjunto de elementos seguidos o
de forma individual. Si solo se indica el nombre de la matriz se referencia todos los elementos.
Para referenciar un valor especfico se debe introducir la posicin del valor de la matriz. Si se
quiere referenciar un rango se utiliza el doble punto para delimitar el rango.
real M(2,4), V(3)
V(2) = 1.
M(2,2:4) = V(2)
En el ejemplo anterior se introduce el valor de V(2) (es decir ) en los tres valores de la matriz
M (M(2,2), M(2,3), M(2,4)).
Las operaciones que se pueden hacer con matrices son:
- 10 -
Mtodos numricos
V(2)
V(3)
V(n-1)
V(n)
M(2,1,1)
M(1,2,1)
M(2,2,1)
M(1,1,2)
M(2,1,2)
M(1,2,2)
M(2,2,2)
1.5.
Subrutinas
Las subrutinas o subroutine son como funciones en otros lenguajes de programacin. Se crea
una subrutina de la misma forma que el programa principal, con la nica diferencia que se
deben poner las variables de referencia que se le quieren pasar a la subrutina.
Es recomendable definir al principio de la rutina si la variable es de entrada o de salida. De esta
forma el compilador puede informar de errores en el programa, si por ejemplo se le intenta
dar un valor a una variable de entrada.
En las subrutinas las variables se envan como referencia, es decir, se enva la direccin de
memoria de la variable. Si la variable es una matriz se enva la direccin del primer valor de la
matriz.
subroutine areaCircle(A, r)
implicit none
real, intent (in) :: r
real, intent (out) :: A
real, parameter :: pi = acos(-1)
A = pi * r * r
end subroutine
- 11 -
1.6.
Mtodos numricos
Cuando se quiere trabajar con un archivo para leer o escribir datos se debe usar la funcin
open. Se le asigna un nmero de unidad al archivo abierto que es el identificador. Dentro de la
funcin se debe definir el archivo y el acceso. El acceso se puede definir por ejemplo como
secuencial, es decir, que cada vez que se escriba o se lea pasa a la siguiente lnea. Para el
archivo se debe introducir la ruta completa o bien si el archivo est en la misma carpeta se
puede simplemente poner el nombre.
Para leer un archivo se debe utilizar la funcin read, seguido de una variable o matriz en
donde se quiera almacenar los datos de lectura. Para escribir se usa write seguido de las
variables o los datos que se quieren introducir.
Una vez se termina de usar el archivo es conveniente cerrarlo usando close.
open(unit = 1, file='fileData', access='SEQUENTIAL')
read(1,*) n
write(1,*) 2 * n
close(1)
- 12 -
1.7.
Mtodos numricos
Programas
end program
El bucle que se quiere realizar consiste en ir dividiendo por dos el valor de la variable small e ir
comprobando que se cumpla la ecuacin
. Se elige en este ejemplo un bucle tipo do
pese a que sera ms lgico utilizar un bucle while, de esta forma se puede ver como funciona
tambin la condicin if.
Dentro de cada iteracin se debe comprobar que se cumpla la ecuacin descrita, y si se cumple
se debe dividir el valor del resultado por dos. En caso de que no se cumpla la condicin hay
que salir de bucle utilizando exit.
do i = 1, 1000
if (1. + small .gt. 1.) then
small = 0.5 * small
else
exit
end if
end do
El resultado an no es exactamente el valor almacenado en small, el valor bueno es el
resultado multiplicado por dos. Para poder ver el valor en pantalla se usa la funcin print*,. Se
puede tambin utilizar la funcin epsilon(small) para poder comparar el resultado.
- 13 -
Mtodos numricos
small = 2 * small
print*, small
print*, epsilon(small)
Se puede cambiar el tipo de variable cuando se define esa, pudiendo probar con variables con
ms precisin.
real*8 small8
real*16 small16
- 14 -
Mtodos numricos
(1.3)
es igual a:
(1.4)
- 15 -
Mtodos numricos
Lo siguiente ya es calcular el valor de . Como las iteraciones se hacen muy rpido se puede
marcar que muestre el valor de cada cierto nmero de iteraciones. La funcin mod(x,y)
devuelve el resto de la divisin de ntegros.
Hay que acordarse de que siempre que se hace un clculo con variables de diferentes tipos se
deben convertir al tipo de la variable que se est calculando. Esto puede evitar errores de
clculos que no son detectados por el compilador. En este problema, como se han calculado
las variables con double precision se deben convertir con la funcin dble().
10 continue
!Ball thrown
call random_number(x)
call random_number(y)
total = total + 1
!Looks where the ball fell
if(x*x + y*y .lt. 1.) inside = inside + 1
!Shows the result every 1000 iterations
if (mod(total, 1000) .eq. 0) then
print*, total, 4. * dble(inside) / dble(total)
end if
go to 10
end program
Este programa tiene un bucle que nunca finaliza, hay que tener cuidado con este tipo de
bucles ya que, pese a que en este programa esto no afecta al resultado, en otro programa ms
complicado puede meterse en un bucle infinito y no calcular nada. Con este tipo de bucles se
puede salir utilizando la funcin exit normalmente dentro de un if.
- 16 -
Mtodos numricos
2. Interpolacin
2.1.
SPLINE
- 17 -
Mtodos numricos
Siendo la pendiente:
|
Donde el error es (
los puntos.
(2.1)
En el caso de estar en los puntos extremos, al faltar uno de los puntos, se aproxima la
pendiente con el propio punto. Por ejemplo si se est en el ltimo punto no se tendra un
punto a la derecha y por lo tanto la pendiente sera:
( )
(2.2)
2.2.
y deben acabar en
o . Las en
- 18 -
Mtodos numricos
( )
( )
4(
(2.4)
El valor de las funciones bsicas de Hermite se pueden calcular fcilmente ya que son
polinomios de tercer orden. Se calcula como ejemplo la cuarta funcin 4 . Esta funcin tiene
doble raz en
(ya que la pendiente en ese punto es ) y la tercera raz en
. A parte
se sabe que la pendiente en
es . Por lo tanto la funcin tiene la siguiente forma, donde
es una constante que se debe calcular.
(
Como la pendiente en
(2.5)
)|
(2.6)
(2.7)
)(
(2.8)
(2.11)
)(
(
(
)
)
- 19 -
(
(
)
)
(2.12)
2.3.
Mtodos numricos
Programa
Se debe hacer ahora el programa principal que es el que lea los datos de entrada calcule los
nuevos valores y los escriba en un fichero.
- 20 -
Mtodos numricos
Lo primero que se debe hacer es definir las variables. Se usan vectores y matrices para guardar
los datos de entrada. Se define una matriz para guardar el valor de la funcin y el valor de su
derivada, y un vector para almacenar la posicin en el eje . Como el programa no sabe an
cuantos valores de la funcin se tienen (los debe leer del archivo) se deben definir estas
matrices como allocatable.
Como variables adicionales se definen el nmero de valores de entrada (n) y el nmero de
valores de salida (nExit). Adems de estas variables se definen otras que ayudarn a la hora de
programar.
program program3
implicit none
real, allocatable :: ydy(:,:), x(:)
real xInt, yInt, step
integer n, i, nExit, last
Se debe leer el archive con los datos para saber la dimensin de las matrices. Se pone como
primer dato el nmero de valores de la funcin, y luego, en cada lnea los valores de la funcin.
Se utiliza la funcin allocate para dar las dimensiones a las matrices.
open(unit = 1, file='initialData', access='SEQUENTIAL')
read(1,*) n
allocate(ydy(2,n), x(n))
do i = 1, n
read(1,*) x(i), ydy(1,i)
end do
close(1)
Como solo se tiene la informacin de los puntos y de la funcin en los puntos se debe
aproximar la derivada. Se utiliza la ecuacin (2.2) para los puntos externos y la ecuacin (3.1)
para el resto.
Una vez calculadas las derivadas se pide el nmero de puntos de salida.
ydy(2,1) = (ydy(1,2) - ydy(1,1)) / (x(2) - x(1))
do i = 2, n - 1
ydy(2,i) = (ydy(1, i+1) - ydy (1, i-1)) / (x(i+1) - x(i-1))
end do
ydy(2,n) = (ydy(1,n) - ydy(1,n-1)) / (x(n) - x(n-1))
print *, 'Introduce number of points:'
read(*,*) nExit
- 21 -
Mtodos numricos
de la funcin interpolada. Se
(2.13)
Como se va a empezar a escribir resultados se abre el archivo de resultados. El parmetro que
se le ha puesto en status genera un nuevo documento cada vez que se ejecuta el programa.
En caso de que el documento ya exista, borra el anterior y crea uno nuevo.
xInt = x(1)
step = (x(n) - x(1)) / real(nExit - 1)
open(unit=2, file='dataExit', access='SEQUENTIAL', status='REPLACE')
Se empieza ahora el bucle de clculo. Cada vez que se hace una iteracin se calcular los puntos
que forman el intervalo en el que xInt est.
last = 1
do i = 1, nExit
!Find interval
do while (xInt .gt. x(last+1))
last = last + 1
end do
Se llama a la subrutina para obtener el valor de yInt para el punto xInt. Una vez se obtiene el
valor, se escribe el resultado en el archivo. Finalmente antes de terminar el bucle se toma un
nuevo valor de xInt y se asegura que todos los valores iniciales de se han tomado.
call hermite(ydy(:,last:last+1), x(last:last+1), xInt, yInt)
write(2,*) xInt, yInt
xInt = xInt + step
xInt = min(xInt, x(n))
end do
close(2)
end program
Debido a que Fortran nicamente enva del vector la direccin de memoria del primer valor
asignado, se puede escribir la llamada de la subrutina de la siguiente manera.
call hermite(ydy(1,last), x(last), xInt, yInt)
- 22 -
Mtodos numricos
3. Integracin
3.1.
Frmula de Newton-Cotes
( )
) ( )
(3.1)
Una primera forma de calcular la integral es a travs de la formula de Newton Cotes. Se puede
muestrear la funcin en una serie de puntos y extrapolar los puntos a funciones que se puedan
integrar como polinomios. Finalmente se hace la integral de los polinomios.
Como convenio, cuando se escogen los puntos de los intervalos para integrar, se escogen los
dos extremos y el resto se suelen coger de forma que el intervalo entre puntos es regular
(siendo muy cmodo que el intervalo sea igual).
Se considera una funcin como la que se ve en la Figura 3.1.
()
intervalos.
Si los intervalos son iguales ste se puede calcular fcilmente con la posicin de los extremos.
(3.2)
Teniendo el valor de ( ) para todos los puntos (
) se calculan las funciones
(
)
polinmicas que aproximan a
para cada intervalo. Esta aproximacin polinmica puede
- 23 -
Mtodos numricos
ser del orden que se desee, pudiendo aproximar con rectas, parbola u otros.La integral es
entonces la integral de los polinomios (el conjunto se define como ).
( )
( )
(3.3)
(3.4)
es la delta de Kronecker.
{
(3.5)
)(
)(
) (
) (
)(
)(
+
+
(
) (
)
)
(3.6)
Si es muy grande, el polinomio tiene muchas oscilaciones y puede variar mucho respecto a la
funcin inicial. Los valores tpicos de son
y . Al tener un pequeo, el polinomio de
Lagrange queda muy simplificado.
El error es la diferencia entre la integral que se quiere obtener y el valor obtenido.
( )
(3.7)
es del orden de
(3.8)
Este error se denomina error simple ya que es el error de un solo intervalo. El error producido
por todos los intervalos se denomina el error compuesto.
+
( )
(3.9)
+( )
(3.10)
- 24 -
(3.11)
3.2.
Mtodos numricos
La regla del punto medio establece que la funcin en los intervalos es constante, tomando solo
un punto del intervalo. Los intervalos se normalizan para que quede una funcin comprendida
entre
y .
()
()
( )
(3.12)
Se aproxima ( ) a una recta cuyo valor es ( ). La integral de esta funcin es por lo tanto:
( )
( )
( )
(3.13)
( )
( )
(3.14)
3.3.
Se aumenta el orden y ahora se toman dos puntos del intervalo en vez de uno. El polinomio
que aproxima el intervalo es por lo tanto una recta que pasa por los dos lmites del intervalo.
Se vuelve a normalizar la funcin para que est contenida entre
y .
()
()
- 25 -
Mtodos numricos
( )
( )
(3.16)
( )
( )
( )
(3.17)
( )
(3.18)
( )
( )
(3.19)
Al estar aproximando de forma lineal el error simple es un trmino de segundo orden que al
integrar se convierte en tercer orden. El error compuesto es de segundo orden. Los errores son
del mismo orden de magnitud que los de la regla del punto medio, pero no son iguales.
(3.20)
En general no basta con calcular una vez la integral para obtener un resultado vlido. Se deben
probar distintos valores de intervalos para comprobar si el resultado converge. Para no tener
que calcular desde el principio cada vez. Es recomendable aprovechar los resultados obtenidos
en las anteriores integraciones y una forma de hacerlo es dividir por dos el valor del
intervalo , es decir poner un punto ms en el centro de cada intervalo. De esta forma solo se
tienen que calcular la mitad de puntos.
Si se hace con este mtodo se empezara calculando la integral con un intervalo
resultado saldra de hacer el siguiente clculo:
. El
( ))
(3.21)
Nunca se debe dar por vlido el resultado de la primera integracin y por lo tanto hay que
y por lo tanto
hacer una segunda. Se tiene
, y adems se define
el
resultado del sumatorio de la primera integracin.
( ))
))
(3.22)
Se ve fcilmente que solo es necesario hacer la mitad de los clculos al solo tener que calcular
los intervalos con subndice impar. De forma similar se pueden ir haciendo iteracin y el
trabajo de cada iteracin es el mismo.
- 26 -
3.4.
Mtodos numricos
Regla de Simpson
En la regla de Simpson se extrapolan los intervalos en parbolas. Se toman tres puntos de cada
intervalo (
), los puntos son los extremos y el punto central del intervalo. De forma similar
].
se centra a los estudios anteriores, se centra el intervalo en [
()
()
)(
)(
( )
)
( )
(
(
)(
)(
)
)
( )
(
(
( )
)(
)(
)
)
(3.23)
y .
(
( )
( )
(3.24)
Para calcular la integral completa se deben sumar las integrales de todos los intervalos. En este
caso se toman grupos de tres puntos, y por el nmero de puntos (Figura 3.5) debe ser un
nmero par.
()
- 27 -
Mtodos numricos
( )
( )
( )]
) ):
)]
(3.25)
( )
( )
( )
(
( )
))
)]
(3.26)
El clculo del error es similar al de la regla del punto medio. Como es una regla cuadrtica se
4
podra pensar que el error seria
que viene de integrar . Pero
es una funcin
antisimtrica y al integrarla entre
el error compuesto es
3.5.
Extrapolacin de Richardson
para:
( )
(3.27)
utilizando ( ).
( )
Donde
(3.28)
(3.29)
como funcin de .
( )
( )
(3.30)
( )
)
( )
( )
( )
- 28 -
.
(3.31)
(3.32)
Mtodos numricos
Con este proceso, se obtiene una mejor aproximacin de eliminando el mayor trmino de
error que es ( ). Este proceso se puede repetir para eliminar trminos de error para
obtener una mejor aproximacin.
El problema es que no se suele saber el valor de . Se suele usar igual al orden de cuadratura
del mtodo usado o hacer una aproximacin del valor haciendo algunas iteraciones.
Se calcula la aproximacin de
para el intervalo .
( )
( )
(3.33)
( )
( )
(3.34)
Si est a punto de converger se podra decir que el hecho de dividir el intervalo por la mitad no
afecta al resultado.
( )
( )
( )
( )
(3.35)
Pudiendo aislar :
( ( )
( ))
( )
( )
- 29 -
( )
( )
( )
)
( )
(3.36)
3.6.
Mtodos numricos
Programas
( )
( )
(3.37)
( )
(3.38)
Una vez se tienen los coeficientes de la serie de cosenos y los coeficientes de la serie de senos
se pueden calcular la amplitud y el desfase.
(3.39)
Las integrales se hacen utilizando el mtodo del trapecio. Se crea una subrutina que calcule la
integral de una funcin. A esta subrutina se le debe dar un vector y(n) donde se almacenen los
valores de la funcin.
subroutine trapice(y, b, z, n)
implicit none
integer, intent (in) :: n
real, intent (in) :: y(n), b
real, intent (out) :: z
z = 0.5 * (y(1) + y(n))+ sum(y(2:n-1))
z = z * b / (real(n) - 1.)
end subroutine
La subrutina fourier debe calcular las fases y las amplitudes. Debe ir llamando a la subrutina
trapice para calcular los coeficientes de la serie de cosenos y senos.
Los valores de las amplitudes y de las fases se almacenan en una matriz llamada
modes(2,0:m). Se le asigna un rango definido a la matriz (0:m) para mantener el convenio de
subndices.
La variable n es el nmero de puntos seleccionados de la funcin para hacer las integrales. La
variable m es el nmero de trminos de la serie de Fourier que se quieren calcular.
Se aaden adems una serie de parmetros como pi o su inversa invPi. Como se sabe que se
va a dividir por bastantes veces es recomendable tener una variable que guarde su inversa y
as solo tener que hacer multiplicaciones.
- 30 -
Mtodos numricos
Se calculan ahora los coeficientes de las series y luego finalmente las amplitudes y fases. El
primer coeficiente
se calcula fuera del bucle, este valor es ya la amplitud y no hay fase
porque no multiplica una funcin trigonomtrica.
!First coeficient
call trapice(y, 2.*pi, a, n)
modes(1,0) = a * 0.5 * invPi
do i = 1, m
!Cos coeficients
z = y * cos(real(i) * x)
call trapice(z, 2.*pi, a, n)
a = a * invPi
!Sin coeficients
z = y * sin(real(i) * x)
call trapice(z, 2.*pi, b, n)
b = b * invPi
!Amplitudes and phases
modes(1,i) = sqrt(a*a + b*b)
modes(2,i) = -atan(b / a)
end do
end subroutine
- 31 -
Mtodos numricos
Finalmente se escribe la funcion principal del programa. Se utiliza una funcin de ejemplo que
ya est escrita con sus amplitudes y fases para poder comprobar si el programa funciona bien.
La funcin escogida es:
.
(3.40)
El programa debe primero seleccionar una serie de puntos y calcular el valor de la funcin
almacenndolos en el vector y(n). El programa llama a la subrutina fourier que es la que se
encarga de devolver las amplitudes y fases.
program program4
implicit none
integer, parameter :: n = 300
integer i
real, parameter :: pi = acos(-1.)
real y(n), step, x, modes(2, 0:8)
x = -pi
step = 2. * pi / (real(n) - 1.)
!Discretization
do i = 1,n
y(i) = 0.5 + 3. * cos(2. * x + 0.75) + 1. * cos(6. * x + 0.25)
x = x + step
end do
!Amplitudes and phases
call fourier (y, modes, n, 8)
!Print results
do i = 0, 8
print* , modes(1,i), modes(2,i)
end do
end program
- 32 -
Mtodos numricos
(3.41)
subroutine evaluateFunction(x, y)
implicit none
real* 8, intent(in) :: x
real* 8, intent(out) :: y
y = dcos(5. * x) + 3. * x * x
end subroutine
- 33 -
Mtodos numricos
Lo siguiente es hacer el bucle iterativo. En cada iteracin simplemente hay que sumar los
valores de la funcin a la variable suma. Se debe diferenciar la primera iteracin de las dems
ya que en la primera hay que evaluar la funcin en todos los puntos y en las dems
simplemente hay que evaluarla cuando j (subndice del punto ) sea impar.
do i = 1, 10
!Sum of the values of the function
if(i .eq. 1) then
x=a+h
do j = 1, (n - 1)
call evaluateFunction (x, aux)
suma = suma + aux
x=x+h
end do
else
x=a+h
do j = 1, (n - 1), 2
call evaluateFunction (x, aux)
suma = suma + aux
x=x+2*h
end do
end if
La integral se obtiene multiplicando la suma de todos los puntos (dividiendo por dos los
lmites) y multiplicndolo por el intervalo, ecuacin (3.18). Una vez obtenido el valor de la
integral se calcula el tamao del intervalo y el nmero de intervalos para la prxima iteracin.
!Integral
integ = h * (sumEnds + suma)
!Number of intervals and size of interval
n=2*n
h = 0.5 * h
(3.42)
- 34 -
Mtodos numricos
( )
( )
( )
(3.43)
- 35 -
Mtodos numricos
Mtodo de la biseccin
( )
(4.1)
(4.3)
(4.4)
. Es
En general no se puede calcular el orden de convergencia exacto, pero utilizando unas cuantas
iteraciones se puede estimar, aunque siempre considerando que a funcin converge.
4.2.
- 36 -
Mtodos numricos
Para ste mtodo se debe escoger un punto que se aproxime a la solucin. La cercana del
punto a la solucin es importante para que el resultado converja. Se puede aproximar la
funcin en una recta en ese punto utilizando la serie de Taylor.
( )
Se busca el punto
( )
( ) (
en el cual ( )
(4.5)
.
( )
( ) (
( )
( )
(4.6)
(4.7)
( )
( )
4.3.
Mtodo de la secante
Con este mtodo se evita el primer problema que tiene el mtodo de Newton-Raphson. Se
aproxima la tangente mediante la secante que pasa por dos puntos. En este mtodo se
necesitan dos puntos iniciales. La aproximacin de la derivada es:
( )
( )
( )
(4.8)
Y por lo tanto:
( )
- 37 -
( )
( )
(4.9)
Mtodos numricos
( )
( )
( )
Figura 4.2. Dos primeras iteraciones del mtodo de la secante.
En este caso se gana en simplicidad y flexibilidad de ejecucin pero se pierde en orden de
convergencia. Este mtodo no es cuadrtico pero su orden de convergencia suele ser entre .
y . , y por lo tanto no es tan rpido como el mtodo de Newton-Raphson.
Este mtodo tiene el mismo problema que el mtodo de Newton-Raphson por lo que no se
puede asegurar la convergencia y sta depende de los valores iniciales.
4.4.
El mtodo de regula falsi o falsa posicin es una combinacin del mtodo de la secante y el
mtodo de la biseccin. El orden de convergencia ronda la unidad (convergiendo ms
lentamente que el mtodo de la secante) pero ste mtodo asegura la convergencia a
diferencia de por ejemplo el mtodo de la secante.
Se debe empezar con dos valores iniciales tal que los signos de la funcin es esos puntos son
opuestos, garantizando que hay al menos una raz en el interior del intervalo (teorema de
Bolzano). Se traza una recta entre los dos puntos y se calcula el cero de esta recta.
( )
( )
( )
Figura 4.3. Dos primeras iteraciones del mtodo regula falsi.
- 38 -
Mtodos numricos
( )
( )
( )
( )
(4.10)
Una vez se obtiene el nuevo punto se calcula ( ) y se elige un nuevo intervalo que cumpla
que la raz est dentro de l. En el caso del ejemplo de la Figura 4.3 se toman los nmeros y
, ya que ( ) ( )
. Se repite el proceso de forma iterativa.
ste mtodo puede resultar lento si por ejemplo se tiene una funcin como el de la Figura 4.4
y adems no se puede asegurar que el resultado haya convergido correctamente (no se puede
asegurar que el error sea mayor de lo estimado). Esto es debido a que en esta funcin las
iteraciones avanzan solo en una direccin.
( )
( )
( )
Figura 4.4. Dos primeras iteraciones.
4.5.
( ). Se resuelve
Grficamente este mtodo consiste en encontrar el punto donde se cruza una funcin
( ). Para ello se empieza con un valor , se calcula el valor de ( ) y se
y otra funcin
busca del valor de que sea igual.
( )
( )
- 39 -
Mtodos numricos
Este mtodo puede no converger. Para que converja se debe cumplir que en la solucin
| ( )|
. Si no se cumple la condicin, la solucin diverge alejndose en cada iteracin de
la solucin, como se puede ver en la Figura 4.6.
- 40 -
4.6.
Mtodos numricos
Programas
(4.12)
La longitud del cable estirado se puede relacionar con la longitud inicial del cable .
(4.13)
Por lo tanto la deformacin es:
(4.14)
Se juntan las ecuaciones (4.11), (4.12) y (4.14) se obtiene una relacin entre el peso del
superagente y el ngulo .
(
- 41 -
(4.15)
Mtodos numricos
ecuacin
no tiene sentido. El problema est en el coseno de la ecuacin (4.15). Se
aproxima con un orden superior:
(4.17)
Adems se puede incluso hacer otra aproximacin para facilitar la resolucin de la ecuacin.
(4.18)
Por lo tanto la solucin aproximada es:
(4.19)
(4.20)
Lo primero que hay que hacer en este programa es calcular los valores iniciales. Adems se
- 42 -
Mtodos numricos
Como proteccin se pone una salida del bucle en caso de que x1 sea igual a x2. Este caso
significara que ya se tiene la solucin y se evita adems hacer clculos con divisiones por cero.
fx1 = k + sin(x1) - tan(x1)
print*, 'x= ', x1, 'f(x) = ', fx1
do i = 1, itMax
if (x1.eq.x2) exit
fx2 = k + sin(x2) - tan (x2)
print*, 'x = ', x2, 'f(x) = ',fx2
Para hacer la nueva iteracin se calcula la pendiente utilizando los dos resultados anteriores y
se usa la ecuacin (4.9) para calcular el nuevo valor x3. Una vez calculado se vuelven a
establecer las variables x1 y x2.
slope = (fx2 - fx1) / (x2 - x1)
x3 = x2 - fx2 / slope
x1 = x2
x2 = x3
fx1 = fx2
end do
end program
- 43 -
Mtodos numricos
(4.21)
Como se utilizan varias veces las funciones trigonomtricas se puede optimizar el programa
creando dos variables cosx y sinx que calculen solo una vez por iteracin la funcin
trigonomtrica.
program Program7
implicit none
integer i, j, n
integer, parameter :: itMax = 7
real, parameter :: k = 0.25E-3
real x1, x2, fx1, slope, cosx, sinx
x1 = (2. * k)**(1./3.)
do i = 1, itMax
cosx = cos(x1)
sinx = sin(x1)
fx1 = k + sinx - sinx / cosx
slope = cosx - 1. / (cosx * cosx)
print*, 'x = ', x1, 'f(x) = ', fx1
if (fx1 .eq. 0) exit
x2 = x1 - fx1 / slope
x1 = x2
end do
end program
- 44 -
Mtodos numricos
(5.1)
(
){
Una vez obtenida la matriz triangular se pueden ir obteniendo los calores de las resultados
partiendo del ltimo.
El buen resultado de este mtodo depende de la calidad de la matriz, que est relacionado con
el radio espectral de la matriz, definido por el supremo de entre los valores absolutos de los
elementos de su espectro.
- 45 -
5.2.
Mtodos numricos
Existen varias formas de definir una matriz mal condicionada. Una matriz de un sistema de
ecuaciones lineales (
) est mal condicionada si, por ejemplo, pequeos errores o
variaciones en los elementos de o tienen un gran efecto en la solucin exacta de .
Otra forma de definirlo de forma sencilla es que una matriz est mal condiciona si el
determinante es anormalmente pequeo. Se puede comparar con la norma de la matriz ,
estando mal condicionada si | | . La norma de la matriz (RMS) se puede calcular como:
(5.2)
(5.3)
(
)
No se puede despreciar ya que si se hiciese el sistema no tendra solucin (el determinante
es nulo). Se utiliza el mtodo de eliminacin de Gauss.
{
(5.4)
(5.5)
Se puede ver que tanto la solucin de como la de depende mucho del valor de . Un
problema de redondeo del programa podra arruinar el resultado. Se puede comprobar que el
determinante es mucho ms pequeo que la norma.
| |
(5.6)
Cuando se tiene una matriz mal condicionada se debe evitar que los valores problemticos
(nmeros muy pequeos) estn en la diagonal. Se debe por lo tanto reordenar la matriz en
caso de tener ese problema. Si se quiere ser riguroso en la reordenacin de la matriz se debe
conseguir una matriz lo ms parecido a una matriz diagonal dominante.
Se debe calcular un parmetro de calidad en todas las filas (desde la fila del pvot hasta la
fila n). ste es el cociente entre el valor de la columna y los elementos de la fila.
|
(|
Donde
viene dado por el elemento de la columna (
[
].
y
viene dado por
- 46 -
|
|)
(5.7)
[
Mtodos numricos
Para garantizar que la matriz est bien condicionada se cambia la fila del pvot por aquella fila
que tenga mayor.
Otro mtodo menos riguroso consiste en buscar el mximo valor de los elementos de la
columna por debajo del pvot y cambiar la fila por la del pvot. Aunque de esta forma no se
garantiza que no haya nmeros muy grandes en el resto de la fila.
5.3.
Descomposicin LU
(5.8)
) (
En este libro se estudian dos mtodos de descomposicin LU. Ambos dependen de qu matriz
( o ) tenga unos en su diagonal. El mtodo Doolittle introduce unos en la matriz (
)
y el mtodo Crout tiene los unos en la matriz (
).
Una vez se tienen las matrices y se resuelve el sistema
y luego
. Como
son diagonales, no hace falta hacer el mtodo de Gauss para obtener la solucin.
(
5.4.
(5.9)
Doolittle
En el siguiente ejemplo se puede ver como haciendo el mtodo Doolittle es anlogo a hacer el
mtodo de Gauss. Se empieza con las dos matrices y de ejemplo.
4
4
(5.10)
) (
44 )
4
4
4
(5.11)
4
4
4
4
44 )
- 47 -
Mtodos numricos
Para obtener las matrices con el mtodo Doolittle se hacen las operaciones similares a la
triangulacin de Gauss. Se triangula la matriz dejando en los ceros el multiplicador.
Como ejemplo se parte de la siguiente matriz :
(5.12)
(5.13)
(5.14)
son:
(
5.5.
(5.15)
Crout
4)
) (
4
(5.16)
44
4
4
(5.17)
4
4
4
4
44 )
4
4
- 48 -
4
4
) (5.18)
4
4
44
Mtodos numricos
(
4
4
4
4
4
(5.19)
44
Se pueden resolver
y 4 y luego 4 . Este proceso se va repitiendo con cada submatriz
utilizando la primera columna para obtener las variables
y la primera fila para obtener las
variables
.
De forma general si se tiene la siguiente matriz
y de (hasta el pvot ):
(5.20)
(
Los valores
(donde son los elementos de la columna a partir de
siguiente forma:
) se obtienen de la
Los valores de
siguiente forma:
(5.21)
) se obtienen de la
5.6.
(5.22)
Matrices dispersas
Una matriz dispersa es una matriz donde la mayor parte de los elementos son ceros. Existen
mtodos para agilizar la resolucin de sistemas de ecuaciones disminuyendo la carga
computacional y el tamao consumido en memoria para almacenar todos los valores.
Almacenamiento Skyline
Se generan vectores en cada fila de la matriz dispersa tomando desde el primero hasta el
ltimo elemento no nulo de cada fila. Es posible que hayan ceros entre los elementos
seleccionados. Por ejemplo, se quiere almacenar la siguiente matriz:
(5.23)
(
- 49 -
Mtodos numricos
{ }
{ }
{ }
{ }
{ }
(5.24)
Se escriben todos estos valores en un vector contiguo. De esta forma se almacenan solo
elementos de los
que tiene la matriz.
Para saber como estn ordenados los valores del vector se necesitan dos vectores punteros. El
vector indica la posicin del primer valor no nulo de la fila y el vector indica la cantidad de
valores que hay en esa fila.
(5.25)
{ }
{ }
(5.26)
{
Si por ejemplo que se quiere recuperar la tercera fila se va al vector o . Estos vectores
indican que se tienen tres elementos y que empiezan a partir de la quinta posicin del vector
de valores. Adems gracias al vector se sabe que los valores empiezan a partir de la tercera
columna. Por lo tanto:
(
(5.27)
En este mtodo solo se almacenan los elementos no nulos. En el caso de tener algn cero en la
diagonal tambin se tendra que almacenar. De forma similar al mtodo anterior se utilizan
tres vectores donde el primero es para almacenar los valores de las matrices. Adems se utiliza
un vector que indica la posicin de la columna del elemento y un vector que indica en que
posicin del vector de valores se encuentra el salto de lnea.
Utilizando la matriz de ejemplo
)
(
(5.28)
En el vector puntero se puede introducir un valor adicional que define la posicin de la fila
siguiente del valor que ya no existira en . No es necesario pero se hace por comodidad.
- 50 -
Mtodos numricos
Si por ejemplo se quiere recuperar la tercera fila de se ira primero al vector puntero que
indica que en la tercera fila aparecen los valores y del vector
( y ). Utilizando el
vector
se sabe que estos valores estn en las columnas y respectivamente. Por lo tanto:
(
(5.29)
Matriz banda
Una matriz banda es una matriz donde los valores no nulos son confinados en un entorno de la
diagonal principal. Se forma una banda de valores no nulos que completan la diagonal
principal y algunas diagonales en cada uno de sus costados.
El ancho de banda de la matriz es el nmero de columnas de elementos no nulos en las filas
centrales. Por ejemplo una matriz
con un ancho de banda de sera:
4
4
44
(5.30)
4
No es necesario almacenar todos los ceros de la matriz, se pueden guardar, por ejemplo, los
datos de la matriz anterior en una matriz reducida
.
(5.31)
4
El ancho de la matriz reducida es igual al ancho de banda y la columna central contiene los
elementos de la diagonal principal.
5.7.
de elementos no
(5.32)
- 51 -
Mtodos numricos
( )
(5.33)
( )
(5.34)
(5.35)
(5.36)
(5.37)
(5.38)
:
)
( )
(5.39)
es
Por lo tanto encontrando el mnimo se obtiene la solucin real. El mtodo del descenso
mximo elige la direccin ms rpida de descenso para aproximarse a la solucin. Si se hace
eso en cada iteracin al final se llega al mnimo.
Se llama al error de la iteracin
. Tambin se define el residuo
. El
objetivo es que tanto como
sean cero. Segn la ecuacin (5.37) se puede ver que el
gradiente de la funcin es el residuo.
(5.40)
- 52 -
Mtodos numricos
se obtiende
(5.42)
(5.43)
(5.44)
)]
(5.45)
Para reducir el nmero de operaciones se deben evitar los productos de matriz por vector. A
partir de la ecuacin (5.42) se tiene:
(
(5.46)
+
+
- 53 -
Mtodos numricos
Este esquema permite obtener una solucin rpida si las curvas de nivel son ms o menos
circulares. Si tienen forma de elipses alargadas, el esquema puede tardar mucho en obtener la
solucin del sistema.
Para aproximarse mejor a la solucin se debe buscar una direccin ortogonal a todas las
direcciones anteriores, asegurndose as que solo se pasa una vez por la misma direccin.
Estando por ejemplo en la primera iteracin, la nueva aproximacin es:
(5.47)
El error en la direccin de ortogonalidad es nulo (
iteraciones:
(
(
Pudiendo obtener la constante
(5.48)
.
(5.49)
El problema es que el error depende de la solucin pero esta no se conoce. Se debe por lo
tanto utilizar el residuo en vez del error. Se debe aplicar la transformacin del error por el
residuo en un espacio cuya mtrica sea:
(5.50)
Tambin hay que asegurarse de que las direcciones son ortogonales entre s.
(5.51)
El nmero de direcciones que se pueden tener es igual a la dimensin del sistema. ). De esta
forma se asegura que un sistema de
ecuaciones se obtiene la solucin exacta en
iteraciones (sin tener en cuenta errores de redondeo).
Se puede obtener la constante
)
(5.52)
- 54 -
Mtodos numricos
sea ortogonal a
. Se elimina la
(5.54)
Donde
)
(5.55)
Por lo tanto
es:
(5.56)
Para las siguientes direcciones se debe asegurar que son ortogonales a las anteriores es decir:
(5.57)
Pero mediante una demostracin que no se va a realizar en este libro se puede llegar a la
conclusin que todos las constantes
son cero para
. Pudiendo utilizar la
ecuacin (5.56) para obtener el valor de .
El esquema iterativo se presenta en la Figura 5.2.
+
+
- 55 -
5.8.
Mtodos numricos
]{ }
{ }
(5.58)
(5.59)
]{ }
(5.60)
.
{
(5.61)
}{
}
(5.62)
}[
]{
(5.63)
]{
Se calcula
(5.64)
}{
}
(5.65)
}{
.
{
- 56 -
(5.66)
Mtodos numricos
}{
}
(5.67)
4{
}[
]{
Finalmente se calcula , como la dimensin del sistema es dos y esta es la segunda iteracin,
el resultado es el exacto (ya que no se ha redondeado ningn resultado anterior).
{
- 57 -
{ }
(5.68)
5.9.
Mtodos numricos
Programas
- 58 -
Mtodos numricos
Una vez se tiene la matriz triangular se pueden obtener las soluciones. La primera solucin es
trivial de obtener. En este programa el propio vector se va modificando para ir introduciendo
las soluciones.
!Obtain solutions
b(n) = b(n) / a(n,n)
Se debe hacer un bucle para obtener las dems soluciones. Se parte de la penltima fila y se
llega hasta la primera (restando uno al valor de la fila en cada iteracin). En cada iteracin del
bucle se obtiene un nuevo resultado.
Una vez triangulada la matriz, el sistema queda de la siguiente forma:
( )
( )
( )( )
( )( )
( )
( )( )
( )
){
(5.69)
Si por ejemplo se quiere obtener la antepenltima solucin lo primero que se hace es aislar la
variable que se quiere encontrar ( ( )( )
). Para ello se pasa del otro lado los
trminos de la matriz multiplicando a las soluciones ya conocidas (en este caso y ).
Por lo tanto la ecuacin queda:
( )( )
( )( )
( )
(5.70)
La operacin ( )( )
equivale a hacer el producto escalar de los
( )
elementos de la fila que estn por detrs del pvot y de los elementos del vector solucin por
debajo de la fila del pvot.
Una vez se obtiene el resultado de la parte de la derecha de la ecuacin (5.70) simplemente se
divide por ( )( ) para obtener la solucin.
do row=n-1,1,-1
b(row) = b(row) - dot_product(a(row+1:n,row), b(row+1:n))
b(row) = b(row) / a(row,row)
end do
end subroutine
El programa principal debe inicializar la matriz
funciona correctamente.
y el vector
La subrutina solo funciona correctamente si la matriz est bien condicionada. Tanto la matriz
como el vector se generan con nmeros aleatorios. Los valores que no estn en la diagonal
que se generen estarn comprendidos entre
. y . y los elementos de la diagonal siempre
- 59 -
Mtodos numricos
sern como mnimo igual al nmero de filas de la matriz por lo que la suma de los elementos
fuera de la diagonal siempre sern menor que los de la diagonal (en cada fila).
program program8
implicit none
integer, parameter :: n = 20
integer i, j
real :: a(n,n), aTrans(n,n), b(n), x(n), rand
!Initialize matrix and vector
do i = 1, n
do j = 1, n
call random_number(rand)
a(i,j) = 0.5 - rand
end do
a(i,i) = (1. + rand) * real(n)
call random_number(rand)
b(i) = rand
end do
Se resuelve ahora el sistema. Como ya se dijo antes, en la subrutina se utiliza el convenio de
estructura del fortran por lo que se debe hacer la transpuesta de la matriz para que coincida
que el primer ndice de la matriz sea la columna.
Como la solucin del sistema en la subrutina se escribe directamente en
vector pero con los valores del vector b.
se debe enviar el
!Solve system
aTrans = transpose(a)
x=b
call solver(aTrans, x, n)
Para comprobar que el programa funciona bien se calcula
. Esto en teora tiene que dar
un vector nulo. Se imprime el mximo valor absoluto de ese vector (dando el error ms
grande) y se comprueba que el valor sea prcticamente cero.
La funcin Matmul multiplica las matrices segn el convenio matemtico, primer ndice filas y
segundo ndice columnas.
!Errors
x = matmul(a, x) - b
print *, 'If the code is correct this is a small number: ', maxval(abs(x))
end program
Nota, la subrutina modifica tanto la matriz como el vector que se enva. El vector es ya la
solucin (que se ha almacenado en ) pero la matriz queda triangulada. Por suerte en vez de
enviar la matriz se ha enviado la matriz aTrans.
- 60 -
Mtodos numricos
{ }
(5.71)
Si se quiere cambiar la primera fila por la tercera simplemente hay que cambiar el valor del
vector puntero, dejando la matriz y el vector de la siguiente forma:
(
{ }
(5.72)
De forma similar al programa anterior se crea una subrutina que resuelve el sistema. En este
caso se crea adems un vector puntero (point) y lo primero es inicializar los valores.
subroutine solveMatrix(a, b, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: b (n), a(n,n)
integer :: row, pivot, point(n), i, pos_row, posPiv
real :: mult, x(n)
!Initialize point vector
do row=1,n
point(row)=row
end do
Para reorganizar la matriz se utiliza un mtodo menos riguroso que consiste en poner el
nmero ms grande que haya por debajo del pvot. Esto no garantiza que la matriz est
perfectamente condicionada pero es ms rpido.
do pivot = 1, n-1
!Organize matrix
mult = 0.
do row = pivot,
if (abs(a(pivot,point(row))) .GT. mult) then
i = row
mult = abs(a(pivot,point(row)))
end if
end do
- 61 -
Mtodos numricos
Se tiene ahora la posicin de la fila que se quiere cambiar por la del pvot. Se debe por lo
tanto intercambiar en el puntero el valor de estas dos filas.
row = point(pivot)
point(pivot) = point(i)
point(i) = row
Se utiliza la variable posPiv sirve para guardar la posicin del pvot y no tener que utilizar
todo el rato point(pivot).
posPiv = point(pivot)
La parte del cdigo que triangula la matriz es similar a la del programa anterior. Hay que tener
cuidado en seleccionar bien la fila ya que sta puede haber sido cambiada por otra.
!Make zeros under Pivot
do row = pivot+1, n
posRow = point(row)
mult = a(pivot, posRow) / a(pivot,posPiv)
a(pivot+1:n,posRow) = a(pivot+1:n,posRow) - mult * a(pivot+1:n,posPiv)
b(posRow) = b(posRow) - mult * b(posPiv)
end do
end do
De forma similar, el cdigo que obtiene los resultados se tiene que modificar para que
seleccione bien las filas que se deben usar.
!Obtain Results
x(n) = b(point(n)) / a(n,point(n))
do row = n-1,1,-1
posRow = point(row)
x(row) = b(posRow) - dot_product(a(row+1:n,posRow), x(row+1:n))
x(row) = x(row) / a(row,posRow)
end do
b=x
end subroutine
Se crea ahora el codigo del programa principal. El codigo es similar al del programa anterior. Se
tiene un generador de matrices que genera una matriz mal condicionada. Los valores de la
matriz fuera de la diagonal principal varan entre -0.5 y 0.5 y los de la diagonal son del orden
de
.
- 62 -
Mtodos numricos
program program9
implicit none
integer, parameter :: size = 20
integer i, j
real :: a(size,size), aTrans(size,size), b(size), x(size), rand
!Generate matrix
do i = 1, size
do j = 1, size
call random_number(rand)
a(i,j) = 0.5 - rand !Number between -0.5 and 0.5
end do
a(i,i) = rand * 1.E-5
!Very small number for the diagonal
call random_number(rand)
b(i) = rand
!Number between 0. and 1.
end do
El sistema resuelve las matrices con el convenio de numeracin de matrices de Fortran (como
en el programa anterior). Se debe por lo tanto enviar la transpuesta de la matriz a la subrutina.
!Solve system
aTrans = transpose(a)
x=b
call solveMatrix(aTrans, x, size)
Se comprueba el resultado haciendo la operacin
absoluto, que indica el mayor error.
!Check results
x = matmul(a, x) - b
print *, 'If the code is correct this is a small number:', maxval(abs(x))
end program
- 63 -
Mtodos numricos
Programa 3. Doolitle
Para resolver un sistema utilizando el mtodo Doolitle (con unos en la diagonal de la matriz )
el programa tiene que descomponer primero la matriz . El programa se escribe para poder
resolver una matriz bien condicionada.
Tanto la matriz como la matriz
se pueden guardar en la misma matriz (en este caso
modificando la propia matriz . El cdigo que consigue las dos matrices es muy similar al que
triangula la matriz en el Programa 1. La diferencia es que se introducen los valores de los
multiplicadores en los elementos que son nulos.
subroutine luDecomposition(a, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: a(n,n)
integer :: row, pivot
real :: mult
do pivot = 1, n-1
do row = pivot+1, n
mult = a(pivot, row) / a(pivot,pivot
a(pivot+1:n,row) = a(pivot+1:n,row) &
- mult * a(pivot+1:n,pivot)
a(pivot,row) = mult
end do
end do
end subroutine
Se crea ahora una subrutina que resuelva el sistema utilizando las matrices
en la matriz ). Se resuelve primer
seguido de
(almacenadas
subroutine luSustitution(a, b, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: b (n)
real, intent(in) :: a(n,n)
integer :: row, i
!Ly = b
do row = 1, n
b(row) = b(row) &
- dot_product(a(1:row-1,row),b(1:row-1))
end do
!Ux = y
do row = n, 1, -1
b(row) = b(row) &
- dot_product(a(row+1:n,row),b(row+1:n))
b(row) = b(row) / a(row,row)
end do
end subroutine
- 64 -
Mtodos numricos
- 65 -
Mtodos numricos
Programa 4. Crout
En este programa se resuelve un sistema de ecuaciones lineales utilizando el mtodo de
descomposicin de Crout. De forma similar al programa anterior, primero se descompone la
matriz del sistema y luego se usa esa matriz para resolver el sistema.
La primera subrutina descompone la matriz. Se considera que la matriz est bien condicionada.
Se usa un bucle para ir moviendo el pivot e ir obteniendo los valores de las matrices y .
subroutine croutDescomp(a, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: a(n,n)
integer :: row, column, i
do i = 1, n
De forma general si se tiene la siguiente matriz
y de (hasta el pvot ):
(5.73)
(
Los valores
(donde son los elementos de la columna a partir de
siguiente forma:
) se obtienen de la
(5.74)
El sumatorio es anlogo a hacer el producto escalar entre el vector que contiene los elementos
de de la fila a la izquierda del elemento en y el vector que contiene los elementos de por
encima del pvot.
!Obtain L
do row = i, n
a(row,i) = a(row,i) - dot_product(a(row,1:i-1),a(1:i-1,i))
end do
Los valores de
siguiente forma:
) se obtienen de la
- 66 -
(5.75)
Mtodos numricos
- 67 -
Mtodos numricos
do i = 1, size
do j = 1, size
call random_number(rand)
a(i,j) = 0.5 - rand ! A number between -0.5 and 0.5
end do
a(i,i) = 0.1 * (1. + rand) * real(size) ! Good matrix
call random_number(rand)
b(i) = rand ! A number between 0. and 1.
end do
aCopy = a
x=b
call croutDescomp(aCopy,size)
call croutSust(aCopy, x, size)
x = matmul(a, x) - b
print *, 'If the code is correct this is a small number:', maxval(abs(x))
end program
- 68 -
Mtodos numricos
7
8
(5.76)
Se puede ver que solo se necesitan modificar las filas que hay por debajo del pvot. Adems
solo se pueden restar elementos de la fila del pvot a las dems filas.
subroutine gaussBand(a, b, d, n)
implicit none
integer, intent(in) :: d, n
real, intent(inout) :: a(-d:d,n), b(n)
integer pivot, row, disp
real mult
!Triangulate matrix
do pivot = 1, n - 1
do row = pivot + 1, min(pivot + d, n)
Como ya se ha dicho antes la funcin min(pivot + d, n) se utiliza para asegurarse de que el
programa no busca valores que estn fuera de la matriz.
- 69 -
Mtodos numricos
Para triangular la matriz se tiene que tener cuidado en definir bien los rangos de los vectores.
La matriz reducida no est escrita en el programa como la matriz de la ecuacin (5.76). Est
escrita de la siguiente forma:
(5.77)
)
A diferencia del Programa 1 los elementos que se eliminan no estn debajo del pvot. En el
caso del ejemplo se deben eliminar los elementos 7 y 8 . Para ello se define la variable
disp que indica el nmero de filas que hay entre la fila y el pvot. ste valor no puede superar
por lo que tambin es til para poder definir rangos de columnas.
disp = row - pivot
mult = a(-disp,row) / a(0, pivot)
a(1-disp:d-disp,row) = a(1-disp:d-disp,row) - &
mult * a(1:d,pivot)
b(row) = b(row) - mult * b(pivot)
end do
end do
De forma similar, para resolver las variables, se tiene que tener cuidado de no salirse de los
rangos de la matriz (utilizando disp = min(d, n - row)) y de definir bien los rangos de los
vectores.
Una vez triangulada la matriz, se obtiene una matriz reducida donde se tienen ceros a la
izquierda de la columna central (que contiene los elementos de la diagonal principal).
(5.78)
Por lo tanto el producto escalar como mucho se hace utilizando un vector de dimensin que
siempre empieza a partir de la columna . En el caso de las ltimas filas se debe tener cuidado
de no utilizar elementos que no existen.
Se utiliza la variable disp para obtener el nmero mximo de columnas que se tienen a la
derecha del pvot.
- 70 -
Mtodos numricos
!Solve x
do row = n, 1, -1
disp = min(d, n - row)
b(row) = b(row) - dot_product(a(1:disp,row),b(row+1:row+disp))
b(row) = b(row) / a(0,row)
end do
end subroutine
El programa principal es parecido a los otros programas. Se define la matriz
de forma
distinta ya que sta no es una matriz cuadrada. Se genera la matriz de forma que est bien
condicionada.
Program program12
implicit none
integer, parameter :: size = 50, d = 5
integer i, j, left, right
real :: a(-d:d,size), aCopy(-d:d,size), b(size), bCopy(size), x(size), rand
do i = 1, size
do j = -d, d
call random_number(rand)
a(j,i) = 0.5 - rand ! A number between -0.5 and 0.5
end do
a(0,i) = (1. + rand) * real(size) !Good matrix
call random_number(rand)
b(i) = rand !A number between 0. and 1.
end do
aCopy = a
x=b
!Solve
call gaussBand(aCopy, b, d, size)
bCopy = b
Como la matriz
operacin
!Check results
bCopy = b
do i = 1, size
left = min(d, i - 1)
right = min(d, size - i)
x(i) = dot_product(a(-left:right, i),bCopy(i-left:i+right)) - x(i)
end do
print *, 'If the code is correct this is a small number:', maxval(abs(x))
end program
- 71 -
Mtodos numricos
(6.1)
en las funciones ( ). Si
es
( )
( ) (
(6.2)
La matriz de derivadas ( ) se suele escribir como matriz . Por ejemplo en los problemas
de elementos finitos estructurales esta matriz es la matriz de rigidez. Los elementos de la
matriz son:
( )
( )
( )
( )
( )
( )
( )
(6.3)
( )
( )
( )
)
Para calcularla se necesitan hacer muchas derivadas parciales y este es un proceso caro por lo
que existen mtodos que buscan reducir al mximo el clculo de esa matriz, por ejemplo, el
mtodo de cuasi Newton.
El objetivo del mtodo es encontrar la solucin
a la ecuacin (6.2), se elige tal que:
( ) (
- 72 -
(6.4)
Mtodos numricos
tenga
(6.5)
- 73 -
Mtodos numricos
7.2.
Mtodo de Euler
( ))
( )
(7.1)
(7.3)
- 74 -
Mtodos numricos
7.3.
Como ejemplo de resolucin con este mtodo se toman los siguientes valores:
( )
(7.5)
(7.6)
Con este paso se ha calculado la pendiente de la recta que pasa por el punto inicial y va hasta
el primer punto. El primer punto es por lo tanto:
(
(7.7)
(7.8)
{
50
40
30
20
10
0
0
0.5
1.5
2.5
3.5
7.4.
El mtodo implcito de Euler o mtodo hacia atrs de Euler es muy parecido al mtodo de
Euler (que tambin se le llama mtodo hacia adelante) pero difiere en que es un mtodo
- 75 -
Mtodos numricos
implcito. ste mtodo es ms estable que el anterior y permite utilizar intervalos mayores,
aunque como siempre, hay que tener cuidado con que no afecte a la calidad de la solucin.
La diferencia ente los dos mtodos es en aproximacin de la pendiente ( (
(
+ )
).
(7.9)
Este mtodo tambin es de orden uno y el error es similar al del mtodo de Euler.
7.5.
Mtodo de Heun
( (
+ ))
(7.10)
Este mtodo utiliza el mtodo de Euler para calcular una estimacin de las coordenadas del
siguiente punto y, con este dato, se corrige la estimacin original. Considerando que el valor
),
de ( ) en la parte derecha de la ecuacin es la pendiente de la solucin en el punto (
esto se puede combinar con la estimacin de Euler en el siguiente punto para dar la pendiente
( )). La solucin es el punto intermedio
de la lnea tangente en el punto de la derecha (
entre las dos soluciones.
( )
(+ + )
- 76 -
7.6.
Mtodos numricos
( )
( )
( )
(7.11)
( )
). La segunda
(7.12)
(
(
[(
)
)
)
(7.13)
)
]
(7.14)
Se puede ver que la expresin entre corchetes de la ecuacin (7.12) se puede interpretar
como:
(
))
) (7.15)
Obteniendo:
(
( )
))
(7.16)
(7.17)
Donde
(
))
y
(7.18)
.
)y
)
(
( )
- 77 -
]
)).
(7.19)
Mtodos numricos
Est claro que esto es una generalizacin del mtodo clsico de Runge-Kutta ya que los
y
coeficientes
cumplen la ecuacin (7.17). Estos coeficientes se
suelen ordenar en una tabla conocida como Butcher tableau, donde se ponen los vectores y
y la matriz de la siguiente forma.
7.7.
Se puede aumentar el orden del mtodo de Runge-Kutta aumentando los pasos que se hacen.
De forma similar a la ecuacin (7.17) la solucin general para orden viene dada por:
( )
(7.20)
(7.21)
Donde
(
(
)
)
Para cada mtodo particular, se debe proveer con el ntegro (nmero de pasos) y los
coeficientes
(para
), b (para
) y
(para
). La
matriz se llama la matriz de Runge-Kutta, mientras que los vectores y son los pesos y los
nodos. Los valores se suelen escribir en el Butcher tableau.
- 78 -
Mtodos numricos
(7.22)
4)
(7.23)
Para que se cumpla que sea un valor promedio de la derivada se debe cumplir que la suma de
los valores que multiplican a los coeficientes sea igual a , en este caso se cumple.
Los coeficientes son:
(
(7.24)
- 79 -
7.8.
Mtodos numricos
Este mtodo es capaz de ir ajustando el intervalo . Zonas de la solucin que tienen una forma
suave (la pendiente no cambia mucho) no requieren intervalos pequeos mientras que
zonas donde la pendiente cambia rpidamente s que requieren intervalos pequeos ya que si
no la solucin no sera buena.
Implementando este mtodo en un programa se puede automatizar el proceso de seleccin
del intervalo y as agilizar el programa si necesidad de estropear la solucin. Siempre se debe
mantener el error local dentro de unos mrgenes.
Para avaluar el cambio de intervalo se calcula una estimacin del error de truncamiento local
del mtodo de Runge-Kutta de dos rdenes distintos.
Se pueden introducir los dos mtodos en el Butcher tableau, uno de orden
. La tabla se representa de la siguiente manera.
y otro de orden
(7.25)
Donde son los mismos que para el paso de mayor orden. Se comparan las soluciones dadas
por los dos pasos para calcular el error.
(7.26)
Este error es del orden ( ). Si el error est dentro de unos mrgenes de precisin significa
que la solucin del orden inferior es suficientemente buena (comparada con la de orden
superior) por lo que la curva es suave en ese punto, pudiendo incrementar el intervalo.
Como ejemplo, el mtodo de Runge-Kutta adaptativo ms simple es el que combina el mtodo
de Heun (segundo orden) con el mtodo de Euler (primer orden). La tabla extendida queda:
- 80 -
7.9.
Mtodos numricos
Esquema de Crank-Nicolson
(7.27)
) (
)]
(7.28)
(7.29)
(7.30)
(7.31)
(7.33)
Para cada intervalo se calculan de forma separada el siguiente valor de la solucin ( y ). Para
cada EDO se obtienen sus respectivos coeficientes .
Al ser una ecuacin diferencial de segundo orden se deben tener dos condiciones iniciales:
( )
( )
( )
- 81 -
( )
(7.34)
Mtodos numricos
). Si se
Se puede discretizar un dominio en diferencias finitas, buscando en esos puntos las soluciones
aproximadas ( ) de un sistema de ecuaciones diferenciales. Se define una malla de una
dimensin como la de la Figura 8.1
para
4)
(8.1)
4)
(8.2)
Se resta la ecuacin (8.2) a la ecuacin (3.1) pero aproximadas hasta el segundo orden.
+
(8.3)
(8.4)
Se puede obtener la segunda derivada de la funcin sumando las ecuaciones (3.1) y (8.2).
+
- 82 -
4)
(8.5)
Mtodos numricos
En el caso de estar situados en los nodos extremos no se pueden aplicar estas ecuaciones. Se
podra utilizar la aproximacin de primer orden de la primera derivada:
+
( )
(8.6)
Pero sta no es una buena solucin. La aproximacin de un orden superior requiere tomar el
siguiente nodo. Utilizar el nodo
puede provocar la necesidad de aumentar el ancho de
banda del sistema aumentando el nmero de operaciones. La aproximacin de un punto ms a
la derecha es:
(
(8.7)
+
+
(8.8)
(8.9)
En general los valores de las derivadas por la izquierda son los mismos que los de la derecha
pero si la derivada es impar se deben cambiar los signos (como en el caso de la primera
derivada en las ecuaciones (8.8) y (8.9)).
Se puede aumentar el orden de aproximacin Taylor para obtener expresiones para derivadas
de mayor orden. El problema de aumentar el orden de aproximacin de Taylor es que se
necesitan funciones muy suaves. Si por ejemplo se resuelven las ecuaciones de Euler, que
admiten discontinuidades (ondas de choque), y se utiliza un esquema de alto orden, la
solucin muestra unas oscilaciones en la presin y densidad que no reflejan la realidad.
Para problemas trmicos donde las funciones suelen ser suaves se puede usar un orden alto.
Existen mtodos llamados espectrales que cada nodo toma informacin de todo el dominio.
Pero si la geometra es complicada tampoco se pueden usar rdenes altos.
8.2.
El caso bidimensional es parecido al anterior pero esta vez el mallado se hace en dos
direcciones. En general se suele definir un mallado uniforme, con forma rectangular, como el
de la Figura 8.2. El intervalo en las dos direcciones puede ser diferente.
Aunque la geometra del problema no sea rectangular se pueden hacer transformaciones del
mallado. Para geometras complejas se utilizan volmenes estructurados para dividir el
dominio en distintos bloques donde aplicar diferencias finitas. El cdigo escrito por Onera para
problemas aerodinmicos (ELSA) utiliza volmenes finitos estructurados.
- 83 -
Mtodos numricos
( )
(
( )
( )
( )
( )
(8.10)
La derivada cruzada de segundo orden se obtiene utilizando las series de Taylor. Se hace la
derivada en dos pasos:
(
|
(8.11)
(8.12)
En general se suelen guardar todos los nodos en un solo vector en vez de una matriz ya que se
necesita resolver un sistema de ecuaciones del tipo
. El valor de la posicin en el
vector es:
(
8.3.
(8.13)
En una pelcula llamada Total Recall se muestra un innovativo mtodo de transporte para ir
desde Inglaterra hasta Australia. El mtodo consiste en hacer caer un ascensor por un tnel a
travs del centro de la tierra aprovechndose nicamente de la gravedad. Empezando sin
ningn tipo de velocidad ni de empuje adicional ms que la gravedad, el viaje dura 17 minutos.
Para comprobar si lo que se muestra la pelcula es correcto se hacen las siguientes
suposiciones:
-
- 84 -
Mtodos numricos
Visto que por lgica la nica forma que el ascensor llegue al otro lado en el caso de haber
friccin aerodinmica se debe tener una velocidad inicial nula. Este problema se puede
resolver analticamente si se considera que no hay fuerzas externas aparte de la gravedad,
pudiendo llegar de un lado al otro de la tierra empezando con velocidad nula.
Utilizando la formulacin adimensional explicada ms adelante se puede obtener la solucin
analtica para el caso de empezar con velocidad nula y sin friccin:
( )
( )
(8.14)
Siendo esta solucin el caso ms favorable, el tiempo que tardara en recorrer toda la tierra
sera de unos
minutos. Se empieza a ver que los guionistas no se han molestado por
investigar un poco de fsica antes de inventar sus mundos de ficcin.
Debido a que los
minutos de cada libre no pueden conseguirse empezando sin velocidad
inicial, el objetivo del problema es calcular la velocidad inicial que se necesitara para poder
llegar en 17 minutos al otro lado de la tierra.
Lo primero que se debe hacer es obtener la ecuacin que gobierna el problema. La ecuacin
del movimiento se basa en la segunda ley de Newton.
(8.15)
(8.17)
Considerando la densidad de la tierra constante en todo el tnel. La masa que ejerce una
fuerza sobre el ascensor, en una posicin desde el centro de la tierra es:
(8.18)
- 85 -
Mtodos numricos
. La
(8.20)
Ecuacin adimensional
(
(
] [
(
(
(8.21)
]
)
] (
(8.22)
adimensionales.
] (
(8.23)
de forma que no est
(8.24)
La ecuacin adimensionalizada queda:
] (
(8.25)
Discretizacin
- 86 -
(8.26)
Mtodos numricos
(8.27)
Introduciendo estas dos ecuaciones en la ecuacin (8.25) se obtiene la ecuacin del problema
discretizada.
+
] (
(8.28)
(8.30)
(8.31)
( )
(8.32)
)
El sistema de ecuaciones anterior no es lineal por lo se debe utilizar el mtodo de Newton para
sistemas no lineales para resolverlo. La matriz de derivadas para este sistema es:
( +
( +
(8.33)
Para obtener el resultado de cada iteracin se debe resolver un sistema lineal y una suma
vectorial.
- 87 -
(8.34)
Mtodos numricos
(8.35)
)
Los valores iniciales se pueden calcular obteniendo la solucin analtica en el caso que no haya
friccin aerodinmica. La ecuacin diferencial es una simple de segundo grado.
( )
(8.36)
constantes.
(8.37)
(8.38)
( )
(8.39)
(8.40)
minutos) y el
(8.41)
(8.42)
- 88 -
Mtodos numricos
pareca muy grande y para dar un poco de credibilidad a la pelcula se podra considerar que
ese ratio es de orden de magnitud 1. Por lo tanto se define
. .
Velocidad inicial
- 89 -
(8.43)
8.4.
Mtodos numricos
Programas
Generar matrices:
y
Nuevo tamao
de malla?
Fin
- 90 -
Mtodos numricos
La primera subrutina genera el vector . Debido a que esta variable depende del tamao de la
malla se tiene que hacer cada vez que se cambie el tamao de sta. Se utiliza la ecuacin
(8.42) para obtener estos valores.
subroutine initialValues(x0, n, tref, h)
implicit none
integer, intent (in) :: n
real*8, intent(in) :: tref, h
real*8, intent (out) :: x0(n)
integer i
real*8 t, tn, kn
tn = 1020. / tref
kn = (1. + dcos(tn)) / dsin(tn)
x0(1) = -1.
do i = 2, n - 1
t = dble(i - 1) * h
x0(i) = - dcos(t) + kn * dsin(t)
end do
x0(n) = 1.
end subroutine
- 91 -
Mtodos numricos
!Write vector R
R(1) = 0.
do i = 2, n - 1
R(i) = x(i) + (x(i+1) - 2. * x(i) + x(i-1)) * h2 + &
ka * (x(i+1) - x(i-1)) * (x(i+1) - x(i1)) * h2
end do
R(n) = 0.
end subroutine
La tercera subrutina es la que resuelve el sistema lineal. El sistema est compuesta por una
matriz banda de solo tres columnas por lo que es recomendable utilizar un solver que se
aproveche de esta condicin.
subroutine gaussBand(a, b, d, n)
implicit none
integer, intent(in) :: d, n
real*8, intent(inout) :: a(-d:d,n), b(n)
integer pivot, row, disp
real*8 mult
!Triangulate matrix
do pivot = 1, n - 1
do row = pivot + 1, min(pivot + d, n)
disp = row - pivot
!Gauss
mult = a(-disp,row) / a(0, pivot)
a(1-disp:d-disp,row) = a(1-disp:d-disp,row) - &
mult * a(1:d,pivot)
b(row) = b(row) - mult * b(pivot)
end do
end do
!Solve x
do row = n, 1, -1
disp = min(d, n - row)
b(row) = b(row) - dot_product(a(1:disp,row),b(row+1:row+disp))
b(row) = b(row) / a(0,row)
end do
end subroutine
- 92 -
Mtodos numricos
program finiteDifferences
implicit none
integer n, i, j, maxIt, maxLoop, kas
real*8, allocatable :: K(:,:), R(:), x(:)
real*8 v, v1, h, tref, ka, error
!Program configuration
ka
= 0.5
!Constant in drag
n
= 1000 !Initial number of nodes
maxLoop = 10
!Maximum number of times the program is runned
maxIt
= 100
!Maximum iteration in Newton's method
error
= 0.00001 !Maximum Error
tref = 6.371E6 * 6.371E6 * 6.371E6 / 3.986E14
tref = tref ** 0.5
El primer bucle es el que se encara de regenerar las mallas. Debe primero crear las matrices K,
R y x. Una vez ha generado esas matrices en memoria se llama a la subrutina que se encarga
de asignar los valores iniciales.
!Loop for number of nodes
do j = 1, maxLoop
allocate (K(3,n), R(n), x(n))
!Initial values for x
h = (1020. / tref) / dble(n - 1)
call initialValues(x, n, tref, h)
v = 0.
Seguidamente, se empiezan las iteraciones que resuelven el problema para la malla dada. El
bucle se termina o bien cuando llega al mximo de iteraciones o cuando el error menor que el
marcado en la variable
.
!Loop for number of iterations
do i = 1, maxIt
!Generate matrix K and vector R
call writeSystem (K, R, x, n, tref, h, ka)
!Solve Kdx = -R
R=-R
call gaussBand(K, R, 1, n)
- 93 -
Mtodos numricos
!Solve x1 = x0 + dx
x=x+R
!Initial velocity
v1 = v
v = (4. * x(2) - 3. * x(1) - x(3)) / (2. * h)
!Print results
if(maxval(abs(R)) .lt. error) then
print*, "Number of nodes: ", n
print*, "Error in R:
", maxval(abs(R))
print*, "Iterations needed: ", i
print*, "Initial velocity: ", "
", v
print*, " "
exit
elseif (i .eq. maxIt) then
print*, "Number of nodes: ", n
print*, "No solution found. "
print*, " "
end if
end do
Una vez se acaba el clculo se le da un nuevo valor a la malla si es necesario borrando antes las
matrices K, R y x.
!Renew discretization
deallocate(K, R, x)
n = 1000 + n
end do
end program
1000
4.05833953591406877E-010
6
33.901530208195759
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
2000
3.99446362148938426E-010
6
33.988404464699350
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
3000
3.98089342760615747E-010
6
34.006278684062110
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
4000
3.97452197374683662E-010
6
34.012788837112836
- 94 -
Mtodos numricos
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
5000
3.97345468277236172E-010
6
34.015867125092669
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
6000
3.97189273253109707E-010
6
34.017561828242137
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
7000
3.97116818907919676E-010
6
34.018593137328239
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
8000
3.97085218660822430E-010
6
34.019267018567149
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
9000
3.97022337062319620E-010
6
34.019731410085285
Number of nodes:
Error in R:
Iterations needed:
Initial velocity:
10000
3.97022961043059028E-010
6
34.020064936000409
Se puede ver que la velocidad inicial converge hacia unos 34.02. Hay que recordar que el error
es el valor absoluto mximo de la matriz R pero para el clculo de la velocidad inicial se debe
hacer una operacin matemtica que incluye la longitud de malla por lo que el error de la
velocidad es distinto.
La velocidad dada est en unidades adimensionales por lo que para pasarla a unidades
internacionales se debe multiplicar por la longitud de referencia dividida por el tiempo de
referencia.
- 95 -
(8.44)
minutos es desorbitada.
Mtodos numricos
(9.1)
El MEF permite obtener una solucin numrica aproximada sobre un dominio (medio
continuo) dividido en un nmero elevado de subdominios no intersectantes entre s
denominados elementos finitos. Dentro de cada elemento se distinguen una serie de puntos
representativos llamados nodos. Dos nodos son adyacentes si pertenecen al mismo elemento.
( )
. Adems de la ecuacin diferencial se
. Estas condiciones pueden ser:
(9.2)
(9.3)
Las condiciones de contorno del problema completo son una combinacin de los dos tipos
anteriores.
(9.4)
La definicin del problema es lo que se llama la forma fuerte del problema, esto incluye la
ecuacin diferencial y las condiciones de contorno. Hasta este punto no se ha hecho ninguna
discretizacin ni ninguna aproximacin.
9.2.
El objetivo del mtodo es resolver la ecuacin diferencial definida en la ecuacin (3.1). Una
forma de resolver la ecuacin bajando un orden a la ecuacin diferencial es integrando la
funcin en todo el dominio. Si la funcin es cero en todo el dominio entonces la integral debe
ser cero.
(9.5)
- 96 -
( )
(9.6)
Mtodos numricos
( )(
( )(
(9.7)
( )
( )
( )(
( )
(9.8)
Con esta ecuacin se obtiene la solucin del mtodo de Rayleigh-Ritz. En general este mtodo
no se usa mucho.
El mtodo de Galerkin utiliza la siguiente aproximacin para la funcin.
( )
(9.9)
El problema con este mtodo es que en general estas funciones estn definidas en todo el
dominio y es muy complicado concentrar la combinacin de
que cumplan todas las
condiciones de contorno.
9.3.
Carga concentrada
- 97 -
Mtodos numricos
Carga distribuida
( )
(9.11)
Carga concentrada
( )
( )
del
(9.13)
(9.14)
(9.15)
Se reescribe la ecuacin anterior utilizando las ecuaciones diferenciales obtenidas para el caso
de carga distribuida (ecuacin (9.11)).
(
- 98 -
( )
(9.16)
Mtodos numricos
Se le tienen que aadir las condiciones de frontera para terminar de definir la forma fuerte del
problema. Las condiciones de contorno pueden ser:
Desplazamiento vertical
( )
Rotacin
( )
(9.18)
Cortante
( )
)
(9.17)
(9.19)
Momento
( )
(9.20)
( )
()
)
()
(9.21)
Se empieza ahora definiendo la forma dbil del problema. Se utiliza la ecuacin integral
definida en la ecuacin (9.6). En este problema se podra considerar que la funcin es el
desplazamiento virtual.
(9.22)
( )
)]
( )
)
(9.23)
La parte de la izquierda est definido para los dos extremos de la barra introduciendo ah las
condiciones de contorno, en este caso es el cortante.
( )
)
()
(9.24)
( )
)
( )
]
- 99 -
( )
(9.25)
Mtodos numricos
()
()
(9.26)
( )
(9.27)
Adems para que la integral de la izquierda se pueda integrar el desplazamiento virtual debe
tener segunda derivada.
9.4.
Funciones de forma
Para resolver la ecuacin diferencial utilizando MEF se debe crear un dominio de elementos
finitos. ste se compone de elementos y nodos. Los elementos pueden tener mltiples
formas, aunque se suelen emplear elementos triangulares o cuadrilteros (en el caso 2D).
Tambin se necesita una forma de caracterizar las propiedades fsicas de los elementos. Los
vnculos entre los nodos de un elemento se caracterizan por las funciones de forma.
La funcin de forma
}{
(9.29)
Siendo
y
los desplazamientos en los nodos. Las funciones de forma en este caso seran
rectas que deben satisfacer la ecuacin (9.28).
(9.30)
- 100 -
9.5.
Mtodos numricos
Cuadratura de Gauss
En general no es necesario integrar analticamente todas las expresiones de la forma dbil una
vez introducidas las funciones de forma. Se puede, por ejemplo, utilizar la cuadratura de gauss
para obtener el resultado numrico de la integral.
A diferencia de otros mtodos de integracin numrica, los puntos de evaluacin de la funcin
estn definidos. El resultado obtenido en la cuadratura de Gauss de puntos es el de integrar
].
un polinomio de orden
o menos. El dominio de la cuadratura por regla es de [
( )
( )
(9.31)
Donde
En la siguiente tabla se pueden ver una lista de puntos de integracin y de pesos para los tres
primeros valores de .
Nm. de puntos
Puntos de integracin
Pesos
9.6.
Tipos de elementos en 2D
En el apartado 9.5 se puede ver un elemento para el caso unidimensional con dos nodos y sus
funciones de forma. Los siguientes elementos son los que ms se utilizan en el caso
bidimensional.
Las funciones de forma se definen en coordenadas locales y .
Elementos triangulares
Los elementos triangulares ms bsicos se componen de tres nodos en los vrtices del
elemento. Se utilizan coordenadas locales para para obtener las funciones de forma.
Para pasar de unas coordenadas a otras se utiliza el siguiente cambio:
{ }
]{ }
- 101 -
(9.32)
Mtodos numricos
( )
( )
( )
)(
)(
(9.33)
{ }
]{ }
}
)
(9.34)
(9.40)
Utilizando la transformacin las funciones de forma en las coordenadas globales queda:
(
[(
) ]
(9.41)
[(
) ]
(9.42)
[(
) ]
(9.43)
- 102 -
Mtodos numricos
(9.44)
(9.45)
(9.46)
Elementos cuadrilteros
Los elementos cuadrilteros ms bsicos se componen de cuatro nodos en los vrtices del
elemento.
)(
(9.47)
)(
(9.48)
)(
(9.49)
)(
(9.50)
Se cumple que la suma de todas las funciones es igual a la unidad. Las derivadas de estos
elementos respecto a las diferentes variables son:
(9.51)
(9.52)
- 103 -
(9.53)
(9.54)
Mtodos numricos
(9.55)
[
(9.56)
Elemento cuadriltero de
elementos
nodos.
Se han introducido nueve nodos en el nodo. Las funciones de forma son por lo tanto ms
complicadas. La funcin de forma del nodo debe anularse en los nuevos puntos, por ejemplo
).
en el punto (
(
(9.58)
Se tienen tres tipos diferentes de nodos en este elemento, se tienen: nodos de las esquinas
que tienen funciones de forma similares a la mostrada para , nodos laterales y el nodo
central.
(
)(
(
)
)(
- 104 -
)
)
(9.59)
(9.60)
Mtodos numricos
Elemento cuadriltero de
nodos Serendipity
Eliminando el nodo central se obtiene un elemento de nodos que tiene las ventajas de
reducir el orden de las funciones de forma. En este caso se tienen dos tipos de nodos: los de
las esquinas y los de los laterales.
(
)(
)(
)(
(9.61)
(9.62)
A parte de eliminar un grado de la ecuacin (eliminando el nodo central) los elementos del
lateral son ms simples (pierden los trminos de orden
).
9.7.
El ejemplo que se desarrolla aqu es un problema trmico con radiacin. En este apartado se
desarrolla el ejemplo y el programa descrito en este tema es el que resuelve este ejemplo.
La siguiente figura muestra la seccin de un radiador para uso en el espacio profundo. Debido
a su doble simetra solo se muestra una cuarta parte de la seccin.
( )
Figura 9.8. Seccin del radiador espacial.
La carga de pago del radiador situada en la zona central debe mantenerse a
conocida. El
radiador acta como un cuerpo negro segn la ley de Stefan-Boltzmann. La temperatura
ambiente equivalente es tan baja que se puede despreciar.
Para este ejemplo se utilizar como connotacin de matrices las letras sin cursiva y en negrita.
Forma dbil
- 105 -
es la conductividad trmica y
es el
Mtodos numricos
(9.65)
(9.66)
4)
(9.67)
(9.70)
Se pueden obtener analticamente los valores de la potencia para los casos extremos. Si
la conductividad es muy baja y el radiador se comporta como un aislante, por lo tanto la
temperatura de la superficie exterior es muy baja y la potencia emitida muy baja tambin
(
). Si en cambio la temperatura en todo el radiador es casi igual a la temperatura
de la carga de pago. En un cuarto de la seccin la potencia radiada sera:
- 106 -
(9.71)
Mtodos numricos
) para
A partir de este momento todas las variables que se utilicen son adimensionales por lo que la
notacin con acento circunflejo ya no se utiliza. Se tienen que tener en cuenta las siguientes
expresiones:
-
( )
(9.72)
Teorema de la divergencia
(9.73)
La forma dbil se obtiene integrando la ecuacin de Laplace multiplicada por una funcin
arbitraria .
(9.74)
(9.75)
). Se elige
()
(9.76)
( )
(9.77)
( )
(9.78)
Discretizacin
( )
( )
( )
( )
4(
)]
( )
[ 4]
- 107 -
las correspondientes
(9.79)
Mtodos numricos
(9.80)
[
] [ 4]
( )
( )
( )
del elemento.
(9.81)
(9.82)
(9.83)
(9.85)
)
(9.86)
Ensamblaje
(9.87)
Esto se debe hacer usando la numeracin global de nodos y elementos. La ecuacin queda:
(9.88)
Esta ecuacin debe cumplirse para cualquier
cualquier .
(9.89)
Debido a la no linealidad del problema (causada por el flujo de radiacin) el sistema se tiene
que resolver de forma iterativa.
- 108 -
Mtodos numricos
(9.90)
El subndice indica que est evaluado con las temperaturas de la iteracin anterior. La
ecuacin (9.89) se escribe finalmente como un sistema lineal.
(
Donde
(9.92)
Integracin
Los elementos que se usan son cuadrilteros de cuatro nodos. Las integrales de volumen son
del orden
(de segundo orden) y de rea ( dimensiones) por lo que se necesitan cuatro
puntos de integracin para la cuadratura de Gauss, dos en cada dimensin.
: I
Figura 9.9. Elemento cuadriltero de nodos en coordenadas locales (izq.) y globales (der.).
La integral de la ecuacin (9.85) se calcula de la siguiente forma:
4
||
Donde
es el peso (siendo igual a en todos los casos). El Jacobino
forma derivadas en un cierto punto se obtiene como:
|)
(9.93)
y las funciones de
(9.94)
(9.95)
- 109 -
Mtodos numricos
Utilizando las funciones de forma en una dimensin de la ecuacin (9.30). Se linealiza ahora
esta ecuacin.
|
]
4
(
[
)
]
[ ]
(9.96)
4)
Para obtener la potencia total se suman las contribuciones de todos los elementos.
- 110 -
(9.97)
9.8.
Mtodos numricos
Programa
- 111 -
Mtodos numricos
El mdulo subroutines incluye todas las variables y subrutinas. Las variables se utilizan de
forma global, es decir que cada subrutina puede cambiar sus valores.
module subroutines
implicit none
!Variables: Local means element coordinates. X: coordinates of node;
!N: shape function; DN: deriv.N; IP: Integ. points
real, save
:: localX(4,2), localN(4,4), localDN(4,2,4), localIP(4,2), alpha
real, allocatable, save :: node(:,:), K(:,:), T(:), q0(:), T0(:), Kr(:,:), Ktot(:,:), Tit(:,:)
integer, allocatable, save :: elemNode(:,:), boundIn(:), boundExt(:,:)
integer, save
:: nNode, nElem, nIn, nExt, nIP, nX
integer, save
:: maxIterations, endIT
real, save
:: error
contains
La primera subrutina Se encarga de abrir el archivo imput_mesh.txt y obtener los datos del
mallado.
subroutine readMesh()
implicit none
integer i
real aux, aux2
open(UNIT = 5, FILE = 'input_mesh.txt', ACCESS = 'SEQUENTIAL')
!Read nodal coordinates
read(5,*) nNode
allocate (node(nNode,2))
do i = 1, nNode
read(5,*) aux, node(i,:), aux2 !First and last numbers not needed
end do
!Read Elements
read(5,*) nElem
allocate(elemNode(nElem,4))
do i = 1, nElem
read(5,*) aux, elemNode(i,:)
end do
!Read Boundary nodes that Radiate
read(5,*) nExt
allocate(boundExt(nExt,2))
do i = 1, nExt
read(5,*) aux, boundExt(i,:)
end do
- 112 -
Mtodos numricos
La subrutina init() se encarga de inicializar variables y de crear las coordenadas locales de los
elementos y de los puntos de integracin y las matrices de funciones de formas y de sus
derivadas.
subroutine init()
implicit none
real aux
integer i
allocate(K(nNode, nNode), Kr(nNode, nNode), KTot(nNode,nNode), &
T(nNode), T0(nNode), q0(nNode))
allocate(Tit(nNode,maxIterations))
K = 0.; Kr = 0.; KTot = 0.; T = 0.; T0 = 0.; q0 = 0.; nIP = 4; nX = 4; Tit = 0.
!Initial temperature
if (alpha .ge. 1) then
T0 = 0.9
else
T0 = alpha
end if
!Node positions
localX(1,1) = -1.;
localX(2,1) = 1.;
localX(3,1) = 1.;
localX(4,1) = -1.;
localX(node, xi-eta)
localX(1,2) = -1.
localX(2,2) = -1.
localX(3,2) = 1.
localX(4,2) = 1.
- 113 -
Mtodos numricos
- 114 -
Mtodos numricos
do i = 1, nElem
!Saves, in eN(4), the number of the nodes in the element
eN = elemNode(i,:)
!Saves, in x(4,2), the positions of the nodes
!in global coordinates of the element
do j = 1, nX
x(j,:) = node(eN(j),:)
end do
localK = 0.
call isoTransform(x, dN, detJ)
!K = sum(|J| Dt D)
do j = 1, nIP
localK = localK + detJ(j) * matmul(transpose(dN(j,:,:)),dN(j,:,:))
end do
!Introduces the values in the global matrix K
do j = 1, nX
do l = 1, nX
K(eN(j), eN(l)) = K(eN(j), eN(l)) + localK(j,l)
end do
end do
end do
end subroutine assembleK
- 115 -
Mtodos numricos
!Matrix q0
!Heat on the nodes
localQ(1) = localT(1)*localT(1)*localT(1)*localT(1) + 0.5 * &
localT(2)*localT(2)*localT(2)*localT(2)
localQ(2) = localT(2)*localT(2)*localT(2)*localT(2) + 0.5 * &
localT(1)*localT(1)*localT(1)*localT(1)
aux = L / alpha
localQ = localQ * aux
!Introduce values in global q
q0(x(1)) = q0(x(1)) + localQ(1)
q0(x(2)) = q0(x(2)) + localQ(2)
!Matrix Kr
!Local Kr
aux = 4./6.
localKr(1,1) = 2. * aux * localT(1)*localT(1)*localT(1)
localKr(2,1) = aux * localT(1)*localT(1)*localT(1)
localKr(1,2) = aux * localT(2)*localT(2)*localT(2)
localKr(2,2) = 2. * aux * localT(2)*localT(2)*localT(2)
aux = - L / alpha
localKr = localKr * aux
!Introduce values in global Kr
do j = 1, 2
do k = 1, 2
Kr(x(j),x(k)) = Kr(x(j),x(k)) + localKr(j,k)
end do
end do
end do
endsubroutine assembleQ
- 116 -
Mtodos numricos
Finalmente la subrutina solver es la que se encarda del bucle iterativo y calcula la distribucin
de las temperaturas en los nodos. Para cada iteracin calcula los vectores
y
llamando a
la subrutina assembleQ. Luego construye un sistema lineal (ecuacin (9.92)) y le introduce las
condiciones de contorno llamando a la subrutina innerBoundary. Finalmente resuelve el
sistema, escribe los resultados y los verifica para saber si el bucle debe finalizarse.
subroutine solver()
implicit none
integer i, j
real a(nNode, nNode)
logical bool
bool = .true.
do i = 1, maxIterations !bucle iterativo
!Obteins matrix Kr and vector q0
call assembleQ();
- 117 -
Mtodos numricos
- 118 -
Mtodos numricos
!Length
L = (node(x(1),1) - node(x(2),1)) * (node(x(1),1) - node(x(2),1))
L = L + (node(x(1),2) - node(x(2),2)) * (node(x(1),2) - node(x(2),2))
L = sqrt(L)
!Temperatures at the nodes
localT(1) = T0(x(1))*T0(x(1))*T0(x(1))*T0(x(1))
localT(2) = T0(x(2))*T0(x(2))*T0(x(2))*T0(x(2))
!Emitted power
localW = L * aux * (localT(1) + localT(2))
!Global power
W = W + localW
end do
print*, " "
print*, "Alpha:", alpha
print*, "Non-dim. power:", W
print*, " "
end subroutine getW
Las siguientes dos subrutinas son una adaptacin de un cdigo para que el GiD pueda leer el
resultado de la distribucin de nodos, elementos y temperaturas.
subroutine writeGidMesh()
implicit none
! x : Nodal Coordinates
! conec : Conectivity (Nodes of elements)
! n_nod : Number of Nodes
! n_el : Number of Elements
integer n_nod, n_el, conec(4,nElem), i
real x(2,nNode)
!Convert the variables to R.F. variables
n_nod = nNode; n_el = nElem
x(1,:) = node(:,1); x(2,:) = node(:,2)
conec = transpose(elemNode)
open(UNIT=6,FILE='radiation_analysis.post.msh',ACCESS='SEQUENTIAL',&
STATUS='REPLACE') ! Create File
write(6,*) '# postprocess mesh for GiD' ! File Header
write(6,*) 'MESH "RADIATION_FEA" dimension 2 ElemType Quadrilateral Nnode 4'
! Write Nodal Coordinates
write(6,*) 'Coordinates'
write(6,*) '# node number coordinate_x coordinate_y'
- 119 -
Mtodos numricos
do i = 1, n_nod
write(6,*) i, x(:, i)
end do ! i
write(6,*) 'end coordinates'
! Write Surface Elements
write(6,*) 'Elements'
write(6,*) '# element node_1 node_2 node_3 node_4'
do i = 1, n_el
write(6,*) i, conec(:, i)
end do ! i
write(6,*) 'end elements'
close(6) ! Close File
end subroutine writeGidMesh
!**************************************************************
subroutine writeTemperature()
implicit none
integer n_nod, n_ite
real temperature(nNode, endIT)
integer nodeF, iter
character*(*) temp_h, scalar, endvalues, values
character*(*) header, filename
parameter (temp_h = 'Result "TEMPERATURE" "ITERATION=" ')
parameter (scalar = ' Scalar OnNodes')
parameter (endvalues = 'End Values', values = 'Values')
parameter (header = 'GiD Post Results File 1.0')
parameter (filename = 'radiation_analysis.post.res')
!Convert the variables to R.F. variables
n_nod = nNode; n_ite = endIT; temperature(:,:) = Tit(:,1:endIT)
10
20
! Format specs
format (A) ! Single character field
format (A, I0, A) ! Use to write iteration number
! Open Output File & Overwrite
open(UNIT=6, FILE=filename, ACCESS='SEQUENTIAL', &
STATUS='REPLACE')
! Write Header
write(6,10) header
! Write Temperature Distribution for Each Iteration
do iter = 1, n_ite
write(6,20) temp_h, iter, scalar
write(6,10) values
- 120 -
Mtodos numricos
do nodeF = 1, n_nod
write(6,*) nodeF, temperature(nodeF, iter)
end do ! nodeF
write(6,10) endvalues
end do ! iter
! Close file
close(6)
end subroutine writeTemperature
end module subroutines
La Figura 9.10 muestra el resultado cuando la conductividad es muy baja. Como ya se supona,
la temperatura en el interior es alta mientras que en el exterior la temperatura es muy baja.
Como caso opuesto, la Figura 9.11 muestra el resultado cuando la conductividad es muy alta.
La temperatura en todo el dominio es muy alta.
Los valores de la potencia adimensional
ver en la Tabla 9.2 y en la Figura 9.12.
- 121 -
se pueden
.
.
.
Mtodos numricos
12
10
8
6
4
2
0
1.E-03
1.E-02
1.E-01
1.E+00
1.E+01
1.E+02
1.E+03
1.E+04
1.E+05
- 122 -
Mtodos numricos
10. Apndice
10.1. Programacin en Fortran
Programa 1. Mnimo error de un tipo de variable
program program1
implicit none
real small = 1.
integer i
do i = 1, 1000
if (1. + small .gt. 1.) then
small = 0.5 * small
else
exit
end if
end do
small = 2. * small
print*, small
print*, epsilon(small)
end program
- 123 -
Mtodos numricos
continue
!Ball thrown
call random_number(x)
call random_number(y)
total = total + 1
!Looks where the ball fell
if(x*x + y*y .lt. 1.) inside = inside + 1
!Shows the result every 1000 iterations
if (mod(total, 1000) .eq. 0) then
print*, total, 4. * dble(inside) / dble(total)
end if
go to 10
end program
- 124 -
Mtodos numricos
10.2. Interpolacin
Programa 3. Entrada de datos e interpolacin
program program3
implicit none
real, allocatable :: ydy(:,:), x(:)
real xInt, yInt, step
integer n, i, nExit, last
!Reading Data
open(unit = 1, file='initialData', access='SEQUENTIAL')
read(1,*) n
allocate(ydy(2,n), x(n))
do i = 1, n
read(1,*) x(i), ydy(1,i)
end do
close(1)
!Obtaining Slopes
ydy(2,1) = (ydy(1,2) - ydy(1,1)) / (x(2) - x(1))
do i = 2, n - 1
ydy(2,i) = (ydy(1, i+1) - ydy (1, i-1)) / (x(i+1) - x(i-1))
end do
ydy(2,n) = (ydy(1,n) - ydy(1,n-1)) / (x(n) - x(n-1))
print *, 'Introduce number of points:'
read(*,*) nExit
xInt = x(1)
step = (x(n) - x(1)) / real(nExit - 1)
open(unit=2, file='dataExit', access='SEQUENTIAL', status='REPLACE')
last = 1
do i = 1, nExit
!Find interval
do while (xInt .gt. x(last+1))
last = last + 1
end do
!Obtain results
call hermite(ydy(:,last:last+1), x(last:last+1), xInt, yInt)
write(2,*) xInt, yInt
!New step
xInt = xInt + step
xInt = min(xInt, x(n))
end do
close(2)
end program
- 125 -
Mtodos numricos
!***************************************************
subroutine hermite (v1, v2, x, yx)
implicit none
real, intent(in) :: v1(4), v2(2), x
real, intent(out) :: yx
real :: chi, span
span =v2(2) - v2(1)
chi = (x - v2(1)) / span
yx = v1(1) * (1. + 2. * chi) * (1. - chi) * (1. - chi) + &
v1(2) * span * chi * (1. - chi) * (1. - chi) + &
v1(3) * chi * chi * (3. - 2. * chi) + &
v1(4) * span * chi * chi * (chi - 1.)
end subroutine
- 126 -
Mtodos numricos
10.3. Integracin
Programa 4. Obtencin de la serie de Fourier
program program4
implicit none
integer, parameter :: n = 300
integer i
real, parameter :: pi = acos(-1.)
real y(n), step, x, modes(2, 0:8)
x = -pi
step = 2. * pi / (real(n) - 1.)
!Discretization
do i = 1,n
y(i) = 0.5 + 3. * cos(2. * x + 0.75) + 1. * cos(6. * x + 0.25)
x = x + step
end do
!Amplitudes and phases
call fourier (y, modes, n, 8)
!Print results
do i = 0, 8
print* , modes(1,i), modes(2,i)
end do
end program
!***************************************************
subroutine trapice(y, b, z, n)
implicit none
integer, intent (in) :: n
real, intent (in) :: y(n), b
real, intent (out) :: z
z = 0.5 * (y(1) + y(n))+ sum(y(2:n-1))
z = z * b / (real(n) - 1.)
end subroutine
!***************************************************
subroutine fourier (y, modes, n, m)
implicit none
integer, intent (in) :: n, m
real, intent (in) :: y(n)
real, intent (out) :: modes(2, 0:m)
integer i
real z(n), x(n), dx, invPi, a, b
- 127 -
Mtodos numricos
- 128 -
Mtodos numricos
- 129 -
Mtodos numricos
!***************************************************
subroutine evaluateFunction(x, y)
implicit none
real* 8, intent(in) :: x
real* 8, intent(out) :: y
y = dcos(5. * x) + 3. * x * x
end subroutine
- 130 -
Mtodos numricos
- 131 -
Mtodos numricos
- 132 -
Mtodos numricos
- 133 -
Mtodos numricos
- 134 -
Mtodos numricos
row = point(pivot)
point(pivot) = point(i)
point(i) = row
posPiv = point(pivot)
!Make zeros under Pivot
do row = pivot+1, n
posRow = point(row)
mult = a(pivot, posRow) / a(pivot,posPiv)
a(pivot+1:n,posRow) = a(pivot+1:n,posRow) - mult &
* a(pivot+1:n,posPiv)
b(posRow) = b(posRow) - mult * b(posPiv)
end do
end do
!Obtain Results
x(n) = b(point(n)) / a(n,point(n))
do row = n-1,1,-1
posRow = point(row)
x(row) = b(posRow) - &
dot_product(a(row+1:n,posRow), x(row+1:n))
x(row) = x(row) / a(row,posRow)
end do
b=x
end subroutine
- 135 -
Mtodos numricos
- 136 -
Mtodos numricos
subroutine luSustitution(a, b, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: b (n)
real, intent(in) :: a(n,n)
integer :: row, i
!Ly = b
do row = 1, n
b(row) = b(row) - dot_product(a(1:row-1,row),b(1:row-1))
end do
!Ux = y
do row = n, 1, -1
b(row) = b(row) - dot_product(a(row+1:n,row),b(row+1:n))
b(row) = b(row) / a(row,row)
end do
end subroutine
- 137 -
Mtodos numricos
- 138 -
Mtodos numricos
subroutine croutSust(a, b, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: b (n)
real, intent(in) :: a(n,n)
integer :: row, i
!Ly = b
do row = 1, n
b(row) = b(row) - dot_product(a(row,1:row-1), b(1:row-1))
b(row) = b(row) / a(row,row)
end do
!Ux = y
do row = n, 1, -1
b(row) = b(row) - dot_product(a(row,row+1:n),b(row+1:n))
end do
end subroutine
- 139 -
Mtodos numricos
- 140 -
Mtodos numricos
!Solve x
do row = n, 1, -1
disp = min(d, n - row)
b(row) = b(row) - dot_product(a(1:disp,row),b(row+1:row+disp))
b(row) = b(row) / a(0,row)
end do
end subroutine
- 141 -
Mtodos numricos
- 142 -
Mtodos numricos
- 143 -
Mtodos numricos
integer i
real*8 t, tn, kn
tn = 1020. / tref
kn = (1. + dcos(tn)) / dsin(tn)
x0(1) = -1.
do i = 2, n - 1
t = dble(i - 1) * h
x0(i) = - dcos(t) + kn * dsin(t)
end do
x0(n) = 1.
end subroutine
!******************************************************************
subroutine gaussBand(a, b, d, n)
implicit none
integer, intent(in) :: d, n
real*8, intent(inout) :: a(-d:d,n), b(n)
integer pivot, row, disp
real*8 mult
!Triangulate matrix
do pivot = 1, n - 1
do row = pivot + 1, min(pivot + d, n)
disp = row - pivot
!Gauss
mult = a(-disp,row) / a(0, pivot)
a(1-disp:d-disp,row) = a(1-disp:d-disp,row) - &
mult * a(1:d,pivot)
b(row) = b(row) - mult * b(pivot)
end do
end do
!Solve x
do row = n, 1, -1
disp = min(d, n - row)
b(row) = b(row) - dot_product(a(1:disp,row),b(row+1:row+disp))
b(row) = b(row) / a(0,row)
end do
end subroutine
- 144 -
Mtodos numricos
!**************************************************************
subroutine readMesh()
implicit none
integer i
real aux, aux2
open(UNIT = 5, FILE = 'input_mesh.txt', ACCESS = 'SEQUENTIAL')
!Read nodal coordinates
read(5,*) nNode
allocate (node(nNode,2))
do i = 1, nNode
read(5,*) aux, node(i,:), aux2 !First and last numbers not needed
end do
!Read Elements
read(5,*) nElem
allocate(elemNode(nElem,4))
do i = 1, nElem
read(5,*) aux, elemNode(i,:)
end do
!Read Boundary nodes that Radiate
read(5,*) nExt
allocate(boundExt(nExt,2))
do i = 1, nExt
read(5,*) aux, boundExt(i,:)
end do
- 145 -
Mtodos numricos
localX(node, xi-eta)
localX(1,2) = -1.
localX(2,2) = -1.
localX(3,2) = 1.
localX(4,2) = 1.
- 146 -
Mtodos numricos
- 147 -
Mtodos numricos
!K = sum(|J| Dt D)
do j = 1, nIP
localK = localK + detJ(j) * matmul(transpose(dN(j,:,:)),dN(j,:,:))
end do
!Introduces the values in the global matrix K
do j = 1, nX
do l = 1, nX
K(eN(j), eN(l)) = K(eN(j), eN(l)) + localK(j,l)
end do
end do
end do
end subroutine assembleK
!**************************************************************
subroutine assembleQ()
implicit none
integer i, j, k, x(2)
real localQ(2), localT(2), localKr(2,2), L
real aux
!Restarts q0 and Kr
q0 = 0.; Kr = 0.
do i = 1, nExt
!Pointer to node number
x = boundExt(i,:)
!Length
L = (node(x(1),1) - node(x(2),1)) * (node(x(1),1) - node(x(2),1))
L = L + (node(x(1),2) - node(x(2),2)) * (node(x(1),2) - node(x(2),2))
L = sqrt(L)
!Temperatures at the nodes
localT(1) = T0(x(1)); localT(2) = T0(x(2))
!Matrix q0
!Heat on the nodes
localQ(1) = localT(1)*localT(1)*localT(1)*localT(1) + 0.5 * &
localT(2)*localT(2)*localT(2)*localT(2)
localQ(2) = localT(2)*localT(2)*localT(2)*localT(2) + 0.5 * &
localT(1)*localT(1)*localT(1)*localT(1)
aux = L / alpha
localQ = localQ * aux
!Introduce values in global q
q0(x(1)) = q0(x(1)) + localQ(1)
q0(x(2)) = q0(x(2)) + localQ(2)
- 148 -
Mtodos numricos
!Matrix Kr
!Local Kr
aux = 4./6.
localKr(1,1) = 2. * aux * localT(1)*localT(1)*localT(1)
localKr(2,1) = aux * localT(1)*localT(1)*localT(1)
localKr(1,2) = aux * localT(2)*localT(2)*localT(2)
localKr(2,2) = 2. * aux * localT(2)*localT(2)*localT(2)
aux = - L / alpha
localKr = localKr * aux
!Introduce values in global Kr
do j = 1, 2
do k = 1, 2
Kr(x(j),x(k)) = Kr(x(j),x(k)) + localKr(j,k)
end do
end do
end do
endsubroutine assembleQ
!**************************************************************
subroutine innerBoundary()
implicit none
integer i, n
do i = 1, nIn
n = boundIn(i)
KTot(n,:) = 0.; KTot(n,n) = 1.
T(n) = 1. !Boundary temperature is 1
end do
end subroutine innerBoundary
!**************************************************************
subroutine solveSystem(a, b, n) !Matrix needs to be transposed
implicit none
integer, intent(in) :: n
real, intent(inout) :: b (n), a(n,n)
integer :: row, pivot
real :: mult
!Triangulate the matrix
do pivot = 1, n-1
do row = pivot+1, n
mult = a(pivot, row) / a(pivot,pivot)
a(pivot+1:n,row) = a(pivot+1:n,row) - mult * &
a(pivot+1:n,pivot)
b(row) = b(row) - mult * b(pivot)
end do
end do
- 149 -
Mtodos numricos
!Obtain solutions
b(n) = b(n) / a(n,n)
do row=n-1,1,-1
b(row) = b(row) - dot_product(a(row+1:n,row), b(row+1:n))
b(row) = b(row) / a(row,row)
end do
end subroutine
!**************************************************************
subroutine solver()
implicit none
integer i, j
real a(nNode, nNode)
logical bool
bool = .true.
do i = 1, maxIterations !bucle iterativo
!Obteins matrix Kr and vector q0
call assembleQ();
!Builds linear system Ax=b Where A=KTot and b=T
KTot = K - Kr
T = q0
!Introduces Dirichlett boundary conditions
call innerBoundary()
!Solves system
a = transpose(KTot)
call solveSystem(a, T, nNode)
!Writtes result
Tit(:,i) = T
!End loop
if(maxval(abs(T - T0)).lt. error) then
print*, " "
print*, "Final iteration: ", i
print*, " "
bool = .false.
exit
end if
!New iteration
T0 = T
print*, "Iteration ", i,"Done!"
end do
- 150 -
Mtodos numricos
endIT = i
if (bool) endIT = i - 1
end subroutine
!**************************************************************
subroutine getW()
implicit none
real L, W, localW, aux, localT(2)
integer i, x(2)
aux = 0.5
W = 0.
do i = 1, nExt
!Pointer to node number
x = boundExt(i,:)
!Length
L = (node(x(1),1) - node(x(2),1)) * (node(x(1),1) - node(x(2),1))
L = L + (node(x(1),2) - node(x(2),2)) * (node(x(1),2) - node(x(2),2))
L = sqrt(L)
!Temperatures at the nodes
localT(1) = T0(x(1))*T0(x(1))*T0(x(1))*T0(x(1))
localT(2) = T0(x(2))*T0(x(2))*T0(x(2))*T0(x(2))
!Emitted power
localW = L * aux * (localT(1) + localT(2))
!Global power
W = W + localW
end do
print*, " "
print*, "Alpha:", alpha
print*, "Non-dim. power:", W
print*, " "
end subroutine getW
!**************************************************************
!**************************************************************
subroutine writeGidMesh()
implicit none
! x : Nodal Coordinates
! conec : Conectivity (Nodes of elements)
! n_nod : Number of Nodes
! n_el : Number of Elements
- 151 -
Mtodos numricos
- 152 -
10
20
Mtodos numricos
! Format specs
format (A) ! Single character field
format (A, I0, A) ! Use to write iteration number
! Open Output File & Overwrite
open(UNIT=6, FILE=filename, ACCESS='SEQUENTIAL', &
STATUS='REPLACE')
! Write Header
write(6,10) header
! Write Temperature Distribution for Each Iteration
do iter = 1, n_ite
write(6,20) temp_h, iter, scalar
write(6,10) values
do nodeF = 1, n_nod
write(6,*) nodeF, temperature(nodeF, iter)
end do ! nodeF
write(6,10) endvalues
end do ! iter
! Close file
close(6)
end subroutine writeTemperature
end module subroutines
!**************************************************************
!
Main Program
!**************************************************************
program spaceRadiator
use subroutines
implicit none
integer i
!Program configurator
alpha
= 100.
maxIterations = 30
error
= 0.0001
!Program sequence
call readMesh();
print*, "Read Mesh Done!"
call init();
print*, "Init
Done!"
call assembleK();
print*, "Assemble K Done!"; print*," "
call solver();
print*, "Solver Done!"
call getW();
Print*, "Get W Done!"
call writeGidMesh();
call writeTemperature();
end program spaceRadiator
- 153 -
Mtodos numricos
- 154 -
Mtodos numricos
- 155 -
Mtodos numricos
2.463382,
2.463382,
2.463382,
2.463382,
2.463382,
2.463382,
2.463382,
2.463382,
2.463382,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.211913,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
2.000000,
1.821629,
1.815673,
1.815169,
2.000000,
1.815784,
1.812997,
1.811110,
1.808492,
1.806234,
1.804310,
1.808224,
1.636086,
1.630681,
1.630370,
1.813192,
1.625911,
1.619998,
1.619546,
1.616625,
1.608731,
1.606702,
1.615396,
1.446553,
1.443569,
1.441455,
1.622146,
1.432886,
1.421536,
1.424186,
1.405719,
1.400527,
1.400477,
1.275691,
1.268725,
1.264471,
1.417036,
1.244228,
1.427056,
1.234777,
1.202281,
1.123014,
1.121434,
1.175523,
1.111057,
1.131105,
1.180136,
1.081815,
0.354438,
0.529341,
0.703317,
0.876831,
1.050344,
1.224321,
1.399224,
1.575517,
1.753662,
0.000000,
0.179288,
0.357637,
0.535284,
0.712461,
0.889404,
1.066347,
1.243525,
1.421171,
1.599521,
1.778809,
0.000000,
0.180000,
0.360000,
0.540000,
0.720000,
0.900000,
1.080000,
1.260000,
1.440000,
1.620000,
0.000000,
0.180872,
0.361012,
1.800000,
0.541894,
0.719583,
0.898145,
1.079273,
1.266466,
1.455508,
1.637391,
0.000000,
0.176823,
0.353756,
1.818681,
0.528767,
0.705203,
0.888848,
1.072482,
1.266208,
1.463877,
1.655375,
0.167221,
0.000000,
0.338019,
1.837785,
0.508613,
0.683612,
0.865111,
1.052398,
1.256977,
1.462519,
0.151792,
0.000000,
0.305980,
1.666282,
0.463444,
1.857294,
0.835586,
0.646075,
0.133967,
0.000000,
1.014019,
0.264424,
0.816136,
1.246738,
0.395229,
- 156 -
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
Mtodos numricos
- 157 -
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
Mtodos numricos
255,
243,
250,
247,
283,
209,
284,
199,
166,
179,
168,
175,
169,
174,
170,
173,
171,
172,
176,
187,
287,
285,
286,
201,
213,
226,
244,
281,
253,
272,
262,
216,
219,
222,
276,
228,
235,
239,
246,
249,
256,
259,
266,
275,
197,
185,
184,
183,
182,
181,
178,
180,
198,
188,
277,
279,
270,
211,
260,
224,
251,
241,
210,
189,
192,
202,
265,
269,
257,
263,
207,
195,
194,
193,
223,
252,
240,
249,
235,
246,
239,
276,
208,
275,
198,
167,
190,
178,
186,
180,
185,
181,
184,
182,
183,
177,
188,
280,
277,
279,
197,
211,
224,
241,
280,
251,
270,
260,
208,
210,
212,
273,
215,
225,
232,
238,
245,
248,
257,
265,
271,
196,
196,
195,
194,
193,
192,
189,
191,
200,
189,
269,
268,
268,
207,
261,
223,
252,
240,
200,
191,
203,
203,
263,
263,
254,
254,
206,
206,
205,
204,
221,
254,
242,
256
239
249
246
275
216
277
208
177
186
177
185
178
184
180
183
181
182
188
198
281
279
280
186
197
211
224
270
241
260
251
210
212
215
271
225
232
238
245
248
257
265
271
269
185
195
194
193
192
191
188
189
210
200
268
270
261
196
252
207
240
223
202
202
202
215
269
261
263
252
195
205
204
203
206
242
221
- 158 -
Mtodos numricos
- 159 -
Mtodos numricos
- 160 -
Mtodos numricos
- 161 -