Código 2

De Física Computacional
Ir para navegação Ir para pesquisar
      MODULE globais
          IMPLICIT NONE
          INTEGER :: N,L 
      END MODULE
      PROGRAM exemplo2_laplace
      USE globais
      IMPLICIT NONE
      INTEGER :: i,j,k,c,t,edge
      REAL :: dV
      INTEGER,DIMENSION(:,:),ALLOCATABLE :: masc
      REAL,DIMENSION(:,:),ALLOCATABLE :: V,V1,E1,E2,x,y 
      
      N = 10
      edge = 20*N
      L = edge + 1
      
      ALLOCATE(V(L,L),V1(L,L),E1(L,L),E2(L,L),x(L,L),y(L,L),masc(L,L)) 
      
      DO i=1,L
          DO j=1,L
              x(j,i) = -1.0 + (i-1)*0.1/N
              y(j,i) = -1.0 + (j-1)*0.1/N
          END DO
      END DO

! Calcula utilizando o algoritmo de Jacobi

      CALL inicia_zeros(E1)
      CALL inicia_zeros(E2)
      CALL initialize_V(V,masc)
      c = 0
      V1 = V
      CALL laplace_jacobi(V,V1,masc,dV,c)
      CALL electric_field(V,E1,E2)
      WRITE(*,*) 'Jacobi:',dV,c
      CALL dados(x,y,V,E1,E2)

! Calcula utilizando o algoritmo de Gauss-Siedel

      CALL inicia_zeros(E1)
      CALL inicia_zeros(E2)
      CALL initialize_V(V,masc)
      c = 0
      
      CALL laplace_gauss_siedel(V,masc,dV,c)
      CALL electric_field(V,E1,E2)
      WRITE(*,*) 'Gauss-Siedel:',dV,c
      CALL dados(x,y,V,E1,E2)
      END PROGRAM
      SUBROUTINE inicia_zeros(M)

! Inicializa uma matriz em zeros

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j
          REAL,DIMENSION(L,L) :: M
          DO i=1,L
              DO j=1,L
                  M(j,i) = 0.0
              END DO
          END DO
      END SUBROUTINE inicia_zeros
      
      SUBROUTINE initialize_V(V0,mascara)

! Inicialização do potencial

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j,m,o,p,q
          INTEGER,DIMENSION(L,L) :: mascara
          REAL,DIMENSION(L,L) :: V0

! Inicializa a mascara em 0

          DO m=1,L
              DO o=1,L
                  mascara(o,m) = 0
              END DO
          END DO

! Escreve 1's onde o V=1.0

          DO p=7*N+1,13*N+1
              DO q=7*N+1,13*N+1
                  mascara(q,p) = 1
              END DO
          END DO

! Escreve o potencial

          DO i=1,L
              DO j=1,L
                  IF (mascara(j,i) == 1) THEN
                      V0(j,i) = 1.0 
                  ELSE 
                      V0(j,i) = 0.0
                  END IF 
              END DO 
          END DO 
      END SUBROUTINE initialize_V
      SUBROUTINE update_V_jacobi(Vn,Vn1,mascara,deltaV)

! Calcula a atualização uma vez

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j
          REAL :: deltaV
          INTEGER,DIMENSION(L,L) :: mascara 
          REAL,DIMENSION(L,L) :: Vn,Vn1
          deltaV = 0.0 
          DO i=2,L-1
              DO j=2,L-1
                  IF (mascara(j,i) == 0) THEN
                      Vn1(j,i) = (Vn(j+1,i) + Vn(j-1,i) + Vn(j,i+1) + &
    Vn(j,i-1))/4.0
                      deltaV = deltaV + abs(Vn(j,i) - Vn1(j,i))
                  END IF
              END DO
          END DO
      END SUBROUTINE update_V_jacobi 
      SUBROUTINE laplace_jacobi(Vm,Vm1,mascara,delta_v,cont)

! Implementa o método de Jacobi

          USE globais
          IMPLICIT NONE
          INTEGER :: cont,x
          REAL :: delta_v,tol
          INTEGER,DIMENSION(L,L) :: mascara
          REAL,DIMENSION(L,L) :: Vm,Vm1
          tol = 1e-5*L*L 
          delta_v = 41.0
          DO WHILE (delta_v .gt. tol)
              CALL update_V_jacobi(Vm,Vm1,mascara,delta_v)
              CALL update_V_jacobi(Vm1,Vm,mascara,delta_v)
              cont = cont+1
          END DO
      END SUBROUTINE laplace_jacobi
      
      SUBROUTINE update_V_gauss_siedel(Vn,mascara,deltaV)

! Calcula a atualização uma vez

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j
          REAL :: deltaV,v1,v2
          INTEGER,DIMENSION(L,L) :: mascara
          REAL,DIMENSION(L,L) :: Vn
          deltaV = 0.0
          DO i=2,L-1
              DO j=2,L-1
                  IF (mascara(j,i) == 0) THEN
                      v1 = Vn(j,i)
                      Vn(j,i) = (Vn(j+1,i) + Vn(j-1,i) + Vn(j,i+1) +   &
    Vn(j,i-1))/4.0
                      v2 = Vn(j,i)
                      deltaV = deltaV + abs(v2 - v1)
                  END IF
              END DO
          END DO
      END SUBROUTINE update_V_gauss_siedel
      SUBROUTINE laplace_gauss_siedel(Vm,mascara,delta_v,cont)

! Implementa o método de Gauss_Siedel

          USE globais
          IMPLICIT NONE
          INTEGER :: cont
          REAL :: delta_v,tol
          INTEGER,DIMENSION(L,L) :: mascara
          REAL,DIMENSION(L,L) :: Vm
          tol = 1e-5*L*L 
          delta_v = 10.0
          DO WHILE (delta_v .gt. tol)
              CALL update_V_gauss_siedel(Vm,mascara,delta_v)
              CALL update_V_gauss_siedel(Vm,mascara,delta_v)
              cont = cont+1
          END DO
      END SUBROUTINE laplace_gauss_siedel
      
      SUBROUTINE electric_field(Vk,Ex,Ey)

! Calcula o campo elétrico a partir do potencial

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j
          REAL,DIMENSION(L,L) :: Vk,Ex,Ey

! Derivada para frente (bordas)

          DO i=1,L-1
              Ex(1,i) = - (Vk(1,i+1) - Vk(1,i)) 
              Ex(L,i) = - (Vk(L,i+1) - Vk(L,i))               
              Ey(i,1) = - (Vk(i+1,1) - Vk(i,1)) 
              Ey(i,L) = - (Vk(i+1,L) - Vk(i,L)) 
          END DO

! Derivada para trás (bordas)

          Ex(1,L) = - (Vk(1,L) - Vk(1,L-1))
          Ex(L,L) = - (Vk(L,L) - Vk(L,L-1))
          Ey(L,1) = - (Vk(L,1) - Vk(L-1,1))
          Ey(L,L) = - (Vk(L,L) - Vk(L-1,L))

! Derivada centrada

          DO i=2,L-1
              DO j=2,L-1 
                  Ex(j,i) = - (Vk(j,i+1) - Vk(j,i-1))/2.0 
                  Ey(j,i) = - (Vk(j+1,i) - Vk(j-1,i))/2.0 
              END DO
          END DO
      END SUBROUTINE electric_field
      SUBROUTINE dados(x1,y1,Vk,Ex,Ey)

! Imprime os dados em arquivos

          USE globais
          IMPLICIT NONE
          INTEGER :: i,j,k
          REAL,DIMENSION(L,L) :: Vk,Ex,Ey,x1,y1
          CHARACTER(28),DIMENSION(2) :: a
          CHARACTER(27),DIMENSION(2) :: b
          CHARACTER(32),DIMENSION(2) :: c
          a(1) = 'potencial_laplace_jacob2.dat'
          a(2) = 'potencial_laplace_gauss2.dat'
          b(1) = 'electric_laplace_jacob2.dat'
          b(2) = 'electric_laplace_gauss2.dat'
          c(1) = 'equipotencial_laplace_jacob2.dat'
          c(2) = 'equipotencial_laplace_gauss2.dat'
          DO k=1,2
          OPEN(10,FILE=a(k),STATUS='unknown',ACTION='write')
              DO i=1,L
                  DO j=1,L
                      WRITE(10,*) x1(j,i),y1(j,i),Vk(j,i)
                  END DO
                  WRITE(10,*) 
              END DO
          CLOSE(10)
          OPEN(20,FILE=b(k),STATUS='unknown',ACTION='write')
              DO i=1,L
                  DO j=1,L
                      WRITE(20,*) x1(j,i),y1(j,i),Ex(j,i),Ey(j,i)
                  END DO
                  WRITE(20,*) 
              END DO
          CLOSE(20)
          OPEN(30,FILE=c(k),STATUS='unknown',ACTION='write')
              DO i=1,L
                  DO j=1,L
                      IF ((Vk(j,i) .lt. 0.96) .and. (Vk(j,i) .gt. 0.94 & 
    ))THEN
                          WRITE(30,*) x1(j,i),y1(j,i)
                      ELSE IF ( (Vk(j,i) .lt. 0.76) .and. (Vk(j,i) .gt.& 
    0.74 )) THEN
                          WRITE(30,*) x1(j,i),y1(j,i)
                      ELSE IF ( (Vk(j,i) .lt. 0.56) .and. (Vk(j,i) .gt.&
    0.54 )) THEN
                          WRITE(30,*) x1(j,i),y1(j,i)
                      ELSE IF ( (Vk(j,i) .lt. 0.36) .and. (Vk(j,i) .gt.&
    0.34 )) THEN 
                          WRITE(30,*) x1(j,i),y1(j,i)
                      ELSE IF ( (Vk(j,i) .lt. 0.16) .and. (Vk(j,i) .gt.&
    0.14 )) THEN
                          WRITE(30,*) x1(j,i),y1(j,i)
                      END IF
                  END DO
              END DO
          CLOSE(30)
          END DO
          
      END SUBROUTINE dados