! Ejemplo del Metodo de Diferencias Finitas para resolver la ecuacion diferencial parcial: ! Uxx=-Pi*Pi*cos(Pix) ! xi<=U<=xf ! U(xi)=vi y U(xf)=vf ! con solucion analitica: ! cos(pix) ! ! Para conocer mas del metodo ver: ! http://132.248.182.159/acl/MDF ! ! Autor: Antonio Carrillo Ledesma ! http://mmc.geofisica.unam.mx/acl program mdf1DDDBand implicit none integer i, N, nn real*16, allocatable :: A(:,:), b(:), x(:) real*16 xi, xf, vi, vf, h, R, P, Q, y xi = 0.0 ! Inicio del diminio xf = 1.0 ! Fin del dominio vi = 1.0 ! Valor en la frontera xi vf = -1.0 ! Valor en la frontera xf nn = 11 ! Particion N = nn - 2 ! Nodos interiores h = (xf - xi) / (nn-1) ! Incremento en la malla allocate (A(3,N), b(N), x(N)) ! Stencil R = 1. / (h * h) P = -2. / (h * h) Q = 1. / (h * h) ! Primer renglon de la matriz A y vector b A(2,1)=P A(3,1)=Q call ladoDerecho(xi,y) b(1)=y-vi*R ! Renglones intermedios de la matriz A y vector b do i=2,N-1 A(1,i)=R A(2,i)=P A(3,i)=Q call ladoDerecho(xi+h*(i),y) b(i)= y end do ! Renglon final de la matriz A y vector b A(1,N)=R A(2,N)=P call ladoDerecho(xi+h*N,y) b(N)= y -vf*Q call gaussSeidel(A, x, b, N, 1000) print*, "A: ", A print*, "b: ", b print*, "x: ", x call jacobi(A, x, b, N, 1000) print*, "A: ", A print*, "b: ", b print*, "x: ", x end program subroutine ladoDerecho(x,y) real*16, intent(in) :: x real*16, intent(inout) :: y real*16 pi pi = 3.1415926535897932384626433832; y = -pi * pi * cos(pi * x); end subroutine subroutine gaussSeidel(a, x, b, nx, iter) implicit none integer, intent(in) :: nx, iter real*16, intent(in) :: a(3,nx), b(nx) real*16, intent(inout) :: x(nx) integer i, j, m real*16 sum do m = 1, iter sum = a(3,1) * x(2) x(1) = (1.0 / a(2,1)) * (b(1) - sum) do i = 2, nx-1 sum = a(1,i) * x(i-1) + a(3,i) * x(i+1) x(i) = (1.0 / a(2,i)) * (b(i) - sum) end do sum = a(1,i) * x(i-1) x(i) = (1.0 / a(2,i)) * (b(i) - sum) end do end subroutine subroutine jacobi(a, x, b, nx, iter) implicit none integer, intent(in) :: nx, iter real*16, intent(in) :: a(3,nx), b(nx) real*16, intent(inout) :: x(nx) real*16, allocatable :: xt(:) integer i, j, m real*16 sum allocate (xt(nx)) do m = 1, iter sum = a(3,1) * x(2) xt(1) = (1.0 / a(2,1)) * (b(1) - sum) do i = 2, nx-1 sum = a(1,i) * x(i-1) + a(3,i) * x(i+1) xt(i) = (1.0 / a(2,i)) * (b(i) - sum) end do sum = a(1,i) * x(i-1) xt(i) = (1.0 / a(2,i)) * (b(i) - sum) do i = 1, nx x(i) = xt(i) end do end do end subroutine