Está en la página 1de 5

PROGRAM laplace

!Declaracion de todas las variables usadas


IMPLICIT NONE
!Coordenadas x,y
COMPLEX(8), ALLOCATABLE :: P(:,:)
! V= potencial en cada punto, Ex campo en x, Ey campo en y
REAL(8), ALLOCATABLE :: V(:,:),Ex(:,:),Ey(:,:)
REAL(8) :: precision,r,dx,dy,x,y
! Lado del cuadrado y radio del circulo con potencial sin(theta)
REAL(8), PARAMETER :: h=10,rmin=2.5
REAL(4) :: t_inicial,t_final,t
! Indices, numero de iteraciones y numero de digitos de variable iter
INTEGER :: i,j,n,iter,flength
! Sirve para ajustar dinamicamente el formato del numero de iteraciones
CHARACTER(20) :: formato
! Abre archivos para datos de potencial y campo
OPEN(10,file='potencial.dat',status='replace')
OPEN(20,file='campo.dat',status='replace')
PRINT*,''
PRINT*,'-------------------- SOLUCION A LA ECUACION DE LAPLACE ---------
-----------'
PRINT*,' C.F. Circulo con potencial sin(theta) centrado en un cuadrado
aterrizado '
PRINT*,''
WRITE(*,'(a)',advance='no')' Indica el refinamiento >>> '
! Nmero de particiones en los intervalos (100 por ejemplo)
READ*,n ! Magnitud de matriz
WRITE(*,'(a)',advance='no')' Indica la precision >>> '
! Ingresa nmero pequeo (1e-3 por ejemplo)
READ*,precision ! Presicion con la que se van a realizar los calculos
CALL CPU_TIME(t_inicial)
! CONDICIONES INICIALES Y LLENADO DE LA MATRIZ
ALLOCATE (V(n+1,n+1),Ex(n+1,n+1),Ey(n+1,n+1),P(n+1,n+1))
! Aumentos en x y y para el llenado de matriz
dx=h/n;dy=h/n
x=1e-6! cero
i=1
! Haz hasta que x es menor o igual que la frontera
eje_x: DO WHILE (x<=h)
y=1e-6!cero
j=1
! Haz hasta que y es menor o igual que la frontera
eje_y: DO WHILE (y<=h)
r=sqrt((x-5)**2+(y-5)**2)
! Condicion inicial dentro del circulo de rmin
IF (r<rmin) THEN
V(i,j)=1! Arbitrario al llenar la matriz, en este caso 1
! Conducion fuera del circulo rmin y dentro del cuadrado
ELSE IF (rmin<r .AND. x>0 .AND. x<h .AND. y>0 .AND. y<h)
THEN
V(i,j)=0! Arbitrario al llenar la matriz, en est
e caso 0
! Condicion de aterrizado en el cuadrado
ELSE IF (x==0 .OR. x==h .OR. y==0 .OR. y==h) THEN
V(i,j)=0
END IF
P(i,j)=cmplx(x,y)
y=y+dy
j=j+1
END DO eje_y
x=x+dx
i=i+1
END DO eje_x
! Invoca la subrutina que calcula solucion para la ecuacion de Laplace p
or el metodo de relajacion
CALL RELAJACION(V,n,dx,dy,rmin,precision,iter)
! Invoca la subrutina que calcula el campo electrico
CALL CAMPO(V,dx,dy,n,Ex,Ey)
! Escritura del potencial en archivo 10
WRITE(10,100)'#x','y ','V '
100 FORMAT(2(A2,8X),A2)
DO i=1,n
DO j=1,n
WRITE(10,110) real(P(i,j)),aimag(P(i,j)),V(i,j)
END DO
END DO
110 FORMAT(2(F8.6,2X),F9.6)
! Escritura del campo en archivo 20
WRITE(20,200)'#x','y ','Ex','Ey','V '
200 FORMAT(2(A2,8X),3(A2,9X))
DO i=1,n
DO j=1,n
WRITE(20,220) real(P(i,j)),aimag(P(i,j)),Ex(i,j),Ey(i,j)
,V(i,j)
END DO
END DO
220 FORMAT(2(F8.6,2X),3(F9.6,2X))
CLOSE(10);CLOSE(20)
CALL CPU_TIME(t_final)
t=t_final-t_inicial
! El siguiente IF es para ajustar dinamicamente el formato de acue
rdo a la
! cantidad de digitos que tenga el numero de iteraciones del progr
ama
! Si el numero de iteraciones es cero entonces longitud=1
IF(iter==0) THEN
flength=1
! Si el numero de iteraciones es mayor que cero entonces longitud es flo
or(log10(iter)+1
! Pero log10 necesita argumento real, entonces se toma real(iter)
ELSE
flength=floor(log10(real(iter)))+1
END IF
! Escribe en el 'archivo' formato el numero de digitos de el numero de i
teraciones
WRITE(formato,*) flength
! Escribe el tiempo de ejecucin del programa
WRITE(*,300)' Tiempo de ejecucin = ',int(t/60),int(t-int(t/60)*60),int(t*1
000-int(t)*1000)
300 FORMAT (a,I2.2,':',I2.2,'.',I3.3)
WRITE(*,'(a,I'//adjustl(formato)//')')' Numero de iteraciones = ',iter
PRINT*,''
END PROGRAM laplace
!8888888b. 8888888888 888 d8888 888888 d8888 .d8888b. 88888
88 .d88888b. 888b 888
!888 Y88b 888 888 d88888 "88b d88888 d88P Y88b 888
d88P" "Y88b 8888b 888
!888 888 888 888 d88P888 888 d88P888 888 888 888
888 888 88888b 888
!888 d88P 8888888 888 d88P 888 888 d88P 888 888 888
888 888 888Y88b 888
!8888888P" 888 888 d88P 888 888 d88P 888 888 888
888 888 888 Y88b888
!888 T88b 888 888 d88P 888 888 d88P 888 888 888 888
888 888 888 Y88888
!888 T88b 888 888 d8888888888 88P d8888888888 Y88b d88P 888
Y88b. .d88P 888 Y8888
!888 T88b 8888888888 88888888 d88P 888 888 d88P 888 "Y8888P" 88888
88 "Y88888P" 888 Y888
! d88P
! d88P
! 888P
SUBROUTINE RELAJACION(V,n,dx,dy,rmin,precision,iter)
INTEGER, INTENT(IN) :: n
INTEGER, INTENT(OUT) :: iter! Numero de iteraciones
REAL(8), DIMENSION(n+1,n+1), INTENT(INOUT) :: V
REAL(8), DIMENSION(n+1,n+1) :: V_anterior
REAL(8), INTENT(IN) :: precision,rmin,dx,dy
INTEGER :: i,j
REAL(8) :: dif=1,r,x,y
REAL(4) :: h=10
iter=0! inicia contador de iteraciones
! Se repite mientras la diferencia es mayor que la precision
DO WHILE (dif>=precision)
V_anterior=V
x=1e-6!cero
i=1
! Haz hasta que x es menor o igual que la frontera
eje_x: DO WHILE (x<=h)
y=1e-6! cero
j=1
! Haz hasta que y es menor o igual que la frontera
eje_y: DO WHILE (y<=h)
r=sqrt((x-5)**2+(y-5)**2)
! Condiciones dentro del circulo con radio rmin
! Necesitamos hacer traslacion de ejes al centro
del circulo, que esta en (5,5)
IF (r<rmin) THEN
V(i,j)=(y-5)/rmin
! Conducion fuera del circulo con radio rmin y d
entro del cuadrado
ELSE IF (rmin<r .AND. x>0 .AND. x<h .AND. y>0 .A
ND. y<h) THEN
V(i,j)=(V(i-1,j)+V(i+1,j)+V(i,j-1)+V(i,j+1))/4.
! Condicion de aterrizado en el cuadrado
ELSE IF(x==0 .OR. x==h .OR. y==0 .OR. y==h) THEN
V(i,j)=0
END IF
y=y+dy
j=j+1
END DO eje_y
x=x+dx
i=i+1
END DO eje_x
! Llama a la Subrutina DIFERENCIA que da un nuevo valor a la var
iable dif el
! cual va disminuyendo
! (Va disminuyendo por que V-V_anterior se va haciendo cada vez
mas chica)
! hasta ser menor o igual que la presicion que damos, en este ca
so 1e-6
CALL DIFERENCIA(V-V_anterior,n,dif)
! Va guardando el numero de iteraciones
iter=iter+1
! Escribe la diferencia entre V y V_anterior hasta que esta es <
= que precision
! WRITE(*,'(ES12.5)') dif !Hace el programa mas lento, pero es sencillo ver
! si se ejecuta de manera exitosa
END DO
END SUBROUTINE RELAJACION
! .d8888b. d8888 888b d888 8888888b. .d88888b.
!d88P Y88b d88888 8888b d8888 888 Y88b d88P" "Y88b
!888 888 d88P888 88888b.d88888 888 888 888 888
!888 d88P 888 888Y88888P888 888 d88P 888 888
!888 d88P 888 888 Y888P 888 8888888P" 888 888
!888 888 d88P 888 888 Y8P 888 888 888 888
!Y88b d88P d8888888888 888 " 888 888 Y88b. .d88P
! "Y8888P" d88P 888 888 888 888 "Y88888P"
SUBROUTINE CAMPO(V,dx,dy,n,Ex,Ey)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
REAL(8), DIMENSION(n+1,n+1), INTENT(IN) :: V
REAL(8), INTENT(IN) :: dx,dy
REAL(8), DIMENSION(n+1,n+1), INTENT(OUT) :: Ex,Ey
INTEGER :: i,j
eje_x: DO i=2,n
eje_y: DO j=2,n
Ex(i,j)=-(V(i+1,j)-V(i-1,j))/(2*dx)
Ey(i,j)=-(V(i,j+1)-V(i,j-1))/(2*dy)
END DO eje_y
END DO eje_x
END SUBROUTINE CAMPO
!8888888b. 8888888 8888888888 8888888888 8888888b. 8888888888 888b 888 .d88
88b. 8888888 d8888
!888 "Y88b 888 888 888 888 Y88b 888 8888b 888 d88P
Y88b 888 d88888
!888 888 888 888 888 888 888 888 88888b 888 888
888 888 d88P888
!888 888 888 8888888 8888888 888 d88P 8888888 888Y88b 888 888
888 d88P 888
!888 888 888 888 888 8888888P" 888 888 Y88b888 888
888 d88P 888
!888 888 888 888 888 888 T88b 888 888 Y88888 888
888 888 d88P 888
!888 .d88P 888 888 888 888 T88b 888 888 Y8888 Y88b
d88P 888 d8888888888
!8888888P" 8888888 888 8888888888 888 T88b 8888888888 888 Y888 "Y88
88P" 8888888 d88P 888
SUBROUTINE DIFERENCIA(A,dimA,dif)
IMPLICIT NONE
INTEGER, INTENT(IN) :: dimA
REAL(8), DIMENSION(dimA,dimA), INTENT(IN) :: A
REAL(8), DIMENSION(dimA,dimA) :: B
REAL(8), INTENT(OUT) :: dif
INTEGER :: i
dif=0
B=matmul(transpose(A),A)
! Traza
DO i=1,dimA
dif=dif+B(i,i)
END DO
END SUBROUTINE DIFERENCIA

También podría gustarte